334 lines
12 KiB
Python
Executable File
334 lines
12 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Copyright 2021, Proofcraft Pty Ltd
|
|
#
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
#
|
|
|
|
#
|
|
# This script generates a theory Kernel_Config.thy from the file gen_config.h,
|
|
# which in turn is produced by the kernel build system, containing kernel
|
|
# configuration options.
|
|
#
|
|
# The script makes the following assumptions about gen_config.h:
|
|
#
|
|
# - only lines that start with "#define" are config options that are used
|
|
# - the value of the config option is separated from its name by two spaces
|
|
# - there is an optional comment after the value, separated by two spaces
|
|
# - values are numbers, booleans or strings
|
|
#
|
|
# Example excerpt from gen_config.h:
|
|
#
|
|
# #define CONFIG_FASTPATH 1 /* KernelFastpath=ON */
|
|
# #define CONFIG_NUM_DOMAINS 16
|
|
# #define CONFIG_NUM_PRIORITIES 256
|
|
# #define CONFIG_MAX_NUM_NODES 1
|
|
# /* disabled: CONFIG_ENABLE_SMP_SUPPORT */
|
|
#
|
|
|
|
import re
|
|
|
|
from datetime import date
|
|
from os import path, getenv
|
|
from typing import Dict
|
|
|
|
# Isabelle types for config keys
|
|
bool = 'boolean'
|
|
string = 'string'
|
|
nat = 'nat'
|
|
word = 'machine_word'
|
|
|
|
# All known config keys that could be set in a gen_config.h file.
|
|
# The dict maps config key to (type, definition name)
|
|
#
|
|
# This table duplicates some information from the kernel build system, but
|
|
# only which keys exist, not their values.
|
|
known_config_keys = {
|
|
'CONFIG_ARM_HIKEY_OUTSTANDING_PREFETCHERS': (bool, None),
|
|
'CONFIG_ARM_HIKEY_PREFETCHER_STRIDE': (bool, None),
|
|
'CONFIG_ARM_HIKEY_PREFETCHER_NPFSTRM': (bool, None),
|
|
'CONFIG_ARM_HIKEY_PREFETCHER_STBPFDIS': (bool, None),
|
|
'CONFIG_ARM_HIKEY_PREFETCHER_STBPFRS': (bool, None),
|
|
'CONFIG_PLAT_SABRE': (bool, None),
|
|
'CONFIG_PLAT_IMX6DQ': (bool, None),
|
|
'CONFIG_ARM_PLAT': (string, None),
|
|
'CONFIG_ARCH_AARCH32': (bool, None),
|
|
'CONFIG_ARCH_AARCH64': (bool, None),
|
|
'CONFIG_ARCH_ARM_HYP': (bool, None),
|
|
'CONFIG_ARCH_RISCV32': (bool, None),
|
|
'CONFIG_ARCH_RISCV64': (bool, None),
|
|
'CONFIG_ARCH_X86_64': (bool, None),
|
|
'CONFIG_ARCH_IA32': (bool, None),
|
|
'CONFIG_SEL4_ARCH': (string, None),
|
|
'CONFIG_ARCH': (string, None),
|
|
'CONFIG_ARCH_ARM': (bool, None),
|
|
'CONFIG_WORD_SIZE': (nat, None),
|
|
'CONFIG_PLAT_IMX7': (bool, None),
|
|
'CONFIG_USER_TOP': (word, None),
|
|
'CONFIG_PLAT_ALLWINNERA20': (bool, None),
|
|
'CONFIG_PLAT_AM335X': (bool, None),
|
|
'CONFIG_PLAT_APQ8064': (bool, None),
|
|
'CONFIG_PLAT_BCM2711': (bool, None),
|
|
'CONFIG_PLAT_BCM2837': (bool, None),
|
|
'CONFIG_PLAT_EXYNOS4': (bool, None),
|
|
'CONFIG_PLAT_EXYNOS5': (bool, None),
|
|
'CONFIG_PLAT_HIKEY': (bool, None),
|
|
'CONFIG_PLAT_IMX6': (bool, None),
|
|
'CONFIG_PLAT_IMX7_SABRE': (bool, None),
|
|
'CONFIG_PLAT_IMX8MQ_EVK': (bool, None),
|
|
'CONFIG_PLAT_IMX8MM_EVK': (bool, None),
|
|
'CONFIG_PLAT_OMAP3': (bool, None),
|
|
'CONFIG_PLAT_QEMU_ARM_VIRT': (bool, None),
|
|
'CONFIG_PLAT_TK1': (bool, None),
|
|
'CONFIG_PLAT_TQMA8XQP1GB': (bool, None),
|
|
'CONFIG_PLAT_ZYNQ7000': (bool, None),
|
|
'CONFIG_PLAT_ZYNQMP': (bool, None),
|
|
'CONFIG_PLAT': (string, None),
|
|
'CONFIG_ARM_CORTEX_A7': (bool, None),
|
|
'CONFIG_ARM_CORTEX_A8': (bool, None),
|
|
'CONFIG_ARM_CORTEX_A9': (bool, None),
|
|
'CONFIG_ARM_CORTEX_A15': (bool, None),
|
|
'CONFIG_ARM_CORTEX_A35': (bool, None),
|
|
'CONFIG_ARM_CORTEX_A53': (bool, None),
|
|
'CONFIG_ARM_CORTEX_A55': (bool, None),
|
|
'CONFIG_ARM_CORTEX_A57': (bool, None),
|
|
'CONFIG_ARM_CORTEX_A72': (bool, None),
|
|
'CONFIG_ARCH_ARM_V7A': (bool, None),
|
|
'CONFIG_ARCH_ARM_V7VE': (bool, None),
|
|
'CONFIG_ARCH_ARM_V8A': (bool, None),
|
|
'CONFIG_ARM_SMMU': (bool, None),
|
|
'CONFIG_AARCH64_SERROR_IGNORE': (bool, None),
|
|
'CONFIG_ARM_MACH': (string, None),
|
|
'CONFIG_KERNEL_MCS': (bool, None),
|
|
'CONFIG_ARM_PA_SIZE_BITS_40': (bool, 'config_ARM_PA_SIZE_BITS_40'),
|
|
'CONFIG_ARM_PA_SIZE_BITS_44': (bool, 'config_ARM_PA_SIZE_BITS_44'),
|
|
'CONFIG_ARM_ICACHE_VIPT': (bool, None),
|
|
'CONFIG_DEBUG_DISABLE_L2_CACHE': (bool, None),
|
|
'CONFIG_DEBUG_DISABLE_L1_ICACHE': (bool, None),
|
|
'CONFIG_DEBUG_DISABLE_L1_DCACHE': (bool, None),
|
|
'CONFIG_DEBUG_DISABLE_BRANCH_PREDICTION': (bool, None),
|
|
'CONFIG_ARM_HYPERVISOR_SUPPORT': (bool, None),
|
|
'CONFIG_ARM_GIC_V3_SUPPORT': (bool, None),
|
|
'CONFIG_AARCH64_VSPACE_S2_START_L1': (bool, None),
|
|
'CONFIG_ARM_HYP_ENABLE_VCPU_CP14_SAVE_AND_RESTORE': (bool, None),
|
|
'CONFIG_ARM_ERRATA_430973': (bool, None),
|
|
'CONFIG_ARM_ERRATA_773022': (bool, None),
|
|
'CONFIG_ARM_SMMU': (bool, None),
|
|
'CONFIG_TK1_SMMU': (bool, None),
|
|
'CONFIG_ENABLE_A9_PREFETCHER': (bool, None),
|
|
'CONFIG_EXPORT_PMU_USER': (bool, None),
|
|
'CONFIG_DISABLE_WFI_WFE_TRAPS': (bool, None),
|
|
'CONFIG_SMMU_INTERRUPT_ENABLE': (bool, None),
|
|
'CONFIG_AARCH32_FPU_ENABLE_CONTEXT_SWITCH': (bool, None),
|
|
'CONFIG_AARCH64_SERROR_IGNORE': (bool, None),
|
|
'CONFIG_L1_CACHE_LINE_SIZE_BITS': (nat, None),
|
|
'CONFIG_EXPORT_PCNT_USER': (bool, None),
|
|
'CONFIG_EXPORT_VCNT_USER': (bool, None),
|
|
'CONFIG_EXPORT_PTMR_USER': (bool, None),
|
|
'CONFIG_EXPORT_VTMR_USER': (bool, None),
|
|
'CONFIG_VTIMER_UPDATE_VOFFSET': (bool, None),
|
|
'CONFIG_HAVE_FPU': (bool, None),
|
|
'CONFIG_PADDR_USER_DEVICE_TOP': (word, None),
|
|
'CONFIG_ROOT_CNODE_SIZE_BITS': (nat, None),
|
|
'CONFIG_TIMER_TICK_MS': (word, None),
|
|
'CONFIG_TIME_SLICE': (nat, 'timeSlice'),
|
|
'CONFIG_RETYPE_FAN_OUT_LIMIT': (word, 'retypeFanOutLimit'),
|
|
'CONFIG_MAX_NUM_WORK_UNITS_PER_PREEMPTION': (nat, 'workUnitsLimit'),
|
|
'CONFIG_RESET_CHUNK_BITS': (nat, 'resetChunkBits'),
|
|
'CONFIG_MAX_NUM_BOOTINFO_UNTYPED_CAPS': (nat, None),
|
|
'CONFIG_FASTPATH': (bool, None),
|
|
'CONFIG_NUM_DOMAINS': (nat, 'numDomains'),
|
|
'CONFIG_NUM_PRIORITIES': (nat, 'numPriorities'),
|
|
'CONFIG_MAX_NUM_NODES': (nat, None),
|
|
'CONFIG_ENABLE_SMP_SUPPORT': (bool, None),
|
|
'CONFIG_KERNEL_STACK_BITS': (nat, None),
|
|
'CONFIG_VERIFICATION_BUILD': (bool, None),
|
|
'CONFIG_DEBUG_BUILD': (bool, None),
|
|
'CONFIG_HARDWARE_DEBUG_API': (bool, None),
|
|
'CONFIG_PRINTING': (bool, None),
|
|
'CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC': (bool, None),
|
|
'CONFIG_NO_BENCHMARKS': (bool, None),
|
|
'CONFIG_ENABLE_BENCHMARKS': (bool, None),
|
|
'CONFIG_KERNEL_LOG_BUFFER': (bool, None),
|
|
'CONFIG_MAX_NUM_TRACE_POINTS': (nat, None),
|
|
'CONFIG_IRQ_REPORTING': (bool, None),
|
|
'CONFIG_COLOUR_PRINTING': (bool, None),
|
|
'CONFIG_USER_STACK_TRACE_LENGTH': (nat, None),
|
|
'CONFIG_KERNEL_OPT_LEVEL_O2': (bool, None),
|
|
'CONFIG_KERNEL_OPT_LEVEL_OS': (bool, None),
|
|
'CONFIG_KERNEL_OPT_LEVEL_O0': (bool, None),
|
|
'CONFIG_KERNEL_OPT_LEVEL_O1': (bool, None),
|
|
'CONFIG_KERNEL_OPT_LEVEL_O3': (bool, None),
|
|
'CONFIG_KERNEL_OPT_LEVEL': (string, None),
|
|
'CONFIG_KERNEL_FWHOLE_PROGRAM': (bool, None),
|
|
'CONFIG_DANGEROUS_CODE_INJECTION': (bool, None),
|
|
'CONFIG_DEBUG_DISABLE_PREFETCHERS': (bool, None),
|
|
'CONFIG_SET_TLS_BASE_SELF': (bool, None),
|
|
'CONFIG_CLZ_32': (bool, None),
|
|
'CONFIG_CLZ_64': (bool, None),
|
|
'CONFIG_CTZ_32': (bool, None),
|
|
'CONFIG_CTZ_64': (bool, None),
|
|
'CONFIG_CLZ_NO_BUILTIN': (bool, None),
|
|
'CONFIG_CTZ_NO_BUILTIN': (bool, None),
|
|
}
|
|
|
|
|
|
def type_of(config_key: str) -> str:
|
|
"""
|
|
Return the Isabelle type of the given config key.
|
|
"""
|
|
|
|
return known_config_keys.get(config_key, (None, None))[0]
|
|
|
|
|
|
def name_of(config_key: str) -> str:
|
|
"""
|
|
Return the name of the Isabelle constant for the given config key.
|
|
"""
|
|
name = known_config_keys.get(config_key, (None, None))[1]
|
|
return name or config_key
|
|
|
|
|
|
def parse_gen_config(gen_config_file: str) -> Dict[str, str]:
|
|
"""
|
|
Parse gen_config.h and return a dictionary of the values.
|
|
"""
|
|
end_comment_re = re.compile(r'/\*.*\*/')
|
|
|
|
config = {}
|
|
with open(gen_config_file, 'r') as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
if not line.startswith('#define '):
|
|
continue
|
|
line = line[len('#define '):]
|
|
line = re.sub(end_comment_re, '', line)
|
|
key, value = line.split(' ')
|
|
config[key] = value
|
|
return config
|
|
|
|
|
|
def parse_physBase(l4v_arch: str, devices_gen_h_file: str) -> str:
|
|
"""
|
|
Parse devices_gen.h and return the physBase value as string in hex or
|
|
decimal form. Return None for architectures that don't use physBase.
|
|
"""
|
|
if l4v_arch == 'X64':
|
|
return None
|
|
|
|
physBase_re = re.compile(r'#define PHYS_BASE_RAW (0x[0-9a-fA-F]+|[0-9]+)')
|
|
with open(devices_gen_h_file, 'r') as f:
|
|
for line in f:
|
|
line = line.strip()
|
|
m = physBase_re.match(line)
|
|
if m:
|
|
return m.group(1)
|
|
raise Exception(f'Could not find PHYS_BASE_RAW in {devices_gen_h_file}')
|
|
|
|
|
|
def add_defaults(config: Dict[str, str]):
|
|
"""
|
|
Defaults are boolean config keys that are mentioned in known_config_keys
|
|
with a custom name. These are set to `false` if not present in the input
|
|
config file.
|
|
"""
|
|
for key, (_, name) in known_config_keys.items():
|
|
if key not in config and name is not None:
|
|
config[key] = 0
|
|
|
|
|
|
theory_header = """(*
|
|
* Copyright {}, Proofcraft Pty Ltd
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-only
|
|
*)
|
|
|
|
chapter "Kernel Configuration"
|
|
|
|
theory Kernel_Config
|
|
imports Word_Lib_l4v.WordSetup
|
|
begin
|
|
|
|
(*
|
|
GENERATED -- DO NOT EDIT! Changes will be overwritten.
|
|
|
|
This file was generated from {}
|
|
and {}
|
|
by the script {}.
|
|
*)
|
|
|
|
"""
|
|
|
|
|
|
def write_config_thy(header, config_thy_path, config: Dict[str, str], physBase=None):
|
|
"""
|
|
Write a Kernel_Config.thy file for a given configuration dict.
|
|
"""
|
|
file_name = path.realpath(path.join(config_thy_path, 'Kernel_Config.thy'))
|
|
with open(file_name, 'w') as f:
|
|
f.write(header)
|
|
|
|
if physBase:
|
|
f.write('(* This value is PHYS_BASE_RAW in the devices_gen.h header listed above. *)\n')
|
|
f.write('definition physBase :: machine_word where\n')
|
|
f.write(f' "physBase \\<equiv> {physBase}"\n\n')
|
|
|
|
names = ['physBase'] if physBase else []
|
|
for key, value in config.items():
|
|
type = type_of(key)
|
|
if type is nat or type is word:
|
|
name = name_of(key)
|
|
names.append(name)
|
|
f.write(f'definition {name} :: {type} where\n')
|
|
f.write(f' "{name} \\<equiv> {value}"')
|
|
if name != key:
|
|
f.write(f' (* {key} *)')
|
|
f.write('\n\n')
|
|
if type is bool:
|
|
name = name_of(key)
|
|
names.append(name)
|
|
f.write(f'definition {name} :: bool where\n')
|
|
val = 'True' if value == '1' else 'False'
|
|
f.write(f' "{name} \\<equiv> {val}"')
|
|
if name != key:
|
|
f.write(f' (* {key} *)')
|
|
f.write('\n\n')
|
|
else:
|
|
# currently ignoring string configs
|
|
pass
|
|
|
|
f.write('\n(* These definitions should only be unfolded consciously and carefully: *)\n')
|
|
for name in names:
|
|
f.write(f'hide_fact (open) {name}_def\n')
|
|
|
|
f.write('\nend\n')
|
|
|
|
print(f'Wrote {file_name}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
l4v_arch = getenv('L4V_ARCH')
|
|
if not l4v_arch:
|
|
print('L4V_ARCH environment variable not set')
|
|
exit(1)
|
|
|
|
this_dir = path.dirname(path.realpath(__file__))
|
|
build_dir = path.join(this_dir, f"config-build/{l4v_arch}")
|
|
|
|
config_path = path.join(build_dir, "gen_config/kernel/gen_config.h")
|
|
devices_gen_path = path.join(build_dir, "gen_headers/plat/machine/devices_gen.h")
|
|
|
|
thy_path = path.join(this_dir, f'../../machine/{l4v_arch}')
|
|
|
|
config = parse_gen_config(config_path)
|
|
physBase = parse_physBase(l4v_arch, devices_gen_path)
|
|
add_defaults(config)
|
|
|
|
header = theory_header.format(
|
|
date.today().year,
|
|
config_path,
|
|
devices_gen_path,
|
|
path.realpath(__file__)
|
|
)
|
|
write_config_thy(header, thy_path, config, physBase)
|