Skip to content

Commit 9ac8c30

Browse files
committed
tool: move kernel configuration out of main
Signed-off-by: Charlotte Fulham <u7917382@anu.edu.au>
1 parent cfd5216 commit 9ac8c30

3 files changed

Lines changed: 238 additions & 210 deletions

File tree

tool/microkit/src/main.rs

Lines changed: 20 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#![allow(clippy::assertions_on_constants)]
99

1010
use microkit_tool::argparse;
11-
use microkit_tool::argparse::{Args, ArgsError, RequestedImageType};
11+
use microkit_tool::argparse::{Args, ArgsError};
1212
use microkit_tool::capdl::allocation::{
1313
simulate_capdl_object_alloc_algorithm, CapDLAllocEmulationErrorLevel,
1414
};
@@ -19,15 +19,13 @@ use microkit_tool::elf::ElfFile;
1919
use microkit_tool::loader::Loader;
2020
use microkit_tool::report::write_report;
2121
use microkit_tool::sdf::{parse, SysMemoryRegion, SysMemoryRegionPaddr};
22-
use microkit_tool::sdk::{AvailableConfig, Sdk};
22+
use microkit_tool::sdk::Sdk;
2323
use microkit_tool::sel4::{
24-
emulate_kernel_boot, emulate_kernel_boot_partial, AddressSpaceConstants, Arch, Config,
25-
ObjectSizes, PlatformConfig, RiscvVirtualMemory,
24+
emulate_kernel_boot, emulate_kernel_boot_partial, Arch, Config, ImageOutputType,
2625
};
2726
use microkit_tool::symbols::patch_symbols;
2827
use microkit_tool::util::{
29-
get_full_path, human_size_strict, json_str, json_str_as_bool, json_str_as_u64, round_down,
30-
round_up,
28+
bail_if_not_exists, get_full_path, human_size_strict, round_down, round_up,
3129
};
3230
use microkit_tool::viper;
3331
use microkit_tool::{DisjointMemoryRegion, MemoryRegion};
@@ -45,67 +43,6 @@ const KERNEL_COPY_FILENAME: &str = "sel4.elf";
4543
// also copy the 32-bit version that was prepared by build_sdk.py for convenience.
4644
const KERNEL32_COPY_FILENAME: &str = "sel4_32.elf";
4745

48-
enum ImageOutputType {
49-
Binary,
50-
Elf,
51-
Uimage,
52-
}
53-
54-
impl ImageOutputType {
55-
fn default_from_arch_and_board(arch: &Arch, board_name: &str) -> Self {
56-
match board_name {
57-
"ariane" | "cheshire" | "serengeti" => ImageOutputType::Elf,
58-
_ => match arch {
59-
Arch::Aarch64 => ImageOutputType::Binary,
60-
Arch::Riscv64 => ImageOutputType::Uimage,
61-
Arch::X86_64 => ImageOutputType::Elf,
62-
},
63-
}
64-
}
65-
66-
/// Resolve the optional user-specified image type with what is the default for the
67-
/// platform.
68-
/// Not all image types are supported for all platforms, so we check here.
69-
fn resolve(requested: &RequestedImageType, arch: &Arch, board_name: &str) -> Option<Self> {
70-
match requested {
71-
RequestedImageType::Binary => match arch {
72-
Arch::Aarch64 | Arch::Riscv64 => Some(Self::Binary),
73-
Arch::X86_64 => None,
74-
},
75-
RequestedImageType::Elf => Some(Self::Elf),
76-
RequestedImageType::Uimage => match arch {
77-
Arch::Riscv64 => Some(Self::Uimage),
78-
Arch::X86_64 | Arch::Aarch64 => None,
79-
},
80-
RequestedImageType::Unspecified => {
81-
Some(Self::default_from_arch_and_board(arch, board_name))
82-
}
83-
}
84-
}
85-
}
86-
87-
fn bail_if_not_exists(description: &'static str, path: &Path) -> Result<(), String> {
88-
if !path.exists() {
89-
eprintln!(
90-
"microkit: error: {description} '{}' does not exist",
91-
path.display()
92-
);
93-
std::process::exit(1);
94-
}
95-
Ok(())
96-
}
97-
98-
fn parse_json_file<T: serde::de::DeserializeOwned>(
99-
file_name: &str,
100-
file_description: &'static str,
101-
current_config: &AvailableConfig,
102-
) -> Result<T, String> {
103-
let path = current_config.config_dir.join(file_name);
104-
bail_if_not_exists(file_description, &path)?;
105-
serde_json::from_str(&fs::read_to_string(&path).expect("Error: Unable to read {path}"))
106-
.map_err(|err| format!("Error: Unable to parse {file_name}: {err}"))
107-
}
108-
10946
fn main() -> Result<(), String> {
11047
let sdk = match Sdk::discover() {
11148
Ok(discovered_info) => discovered_info,
@@ -134,13 +71,13 @@ fn main() -> Result<(), String> {
13471
std::process::exit(1);
13572
}
13673
};
74+
13775
args.search_paths.push(sdk.cwd.clone());
13876

139-
// NB safe unwrap: argparse would already have bailed if the config did not
140-
// exist.
141-
let current_config = sdk.select(&args.board, &args.config).unwrap();
77+
let system_path = &args.sdf_path;
78+
bail_if_not_exists("system description file", system_path)?;
14279

143-
// the real work begins here
80+
let current_config = sdk.select(&args.board, &args.config).unwrap();
14481
let elf_path = current_config.config_dir.join("elf");
14582
let loader_elf_path = elf_path.join("loader.elf");
14683
let kernel_elf_path = match args.override_kernel {
@@ -149,164 +86,39 @@ fn main() -> Result<(), String> {
14986
};
15087
let monitor_elf_path = elf_path.join("monitor.elf");
15188
let capdl_init_elf_path = elf_path.join("initialiser.elf");
152-
let kernel_config_path = current_config
153-
.config_dir
154-
.join("include/kernel/gen_config.json");
155-
let invocations_all_path = current_config.config_dir.join("invocations_all.json");
89+
15690
bail_if_not_exists("board ELF directory", &elf_path)?;
15791
bail_if_not_exists("kernel ELF", kernel_elf_path)?;
15892
bail_if_not_exists("monitor ELF", &monitor_elf_path)?;
15993
bail_if_not_exists("CapDL initialiser ELF", &capdl_init_elf_path)?;
160-
bail_if_not_exists("kernel configuration file", &kernel_config_path)?;
161-
bail_if_not_exists("invocations JSON file", &invocations_all_path)?;
162-
163-
let system_path = &args.sdf_path;
164-
bail_if_not_exists("system description file", system_path)?;
16594

16695
let xml: String = fs::read_to_string(system_path).unwrap();
16796

168-
let kernel_config_json: serde_json::Value =
169-
serde_json::from_str(&fs::read_to_string(kernel_config_path).unwrap()).unwrap();
97+
let kernel_config = Config::build_kernel_config(&args, &sdk).unwrap();
17098

171-
let invocations_labels: serde_json::Value =
172-
serde_json::from_str(&fs::read_to_string(invocations_all_path).unwrap()).unwrap();
173-
174-
let arch = match json_str(&kernel_config_json, "SEL4_ARCH")? {
175-
"aarch64" => Arch::Aarch64,
176-
"riscv64" => Arch::Riscv64,
177-
"x86_64" => Arch::X86_64,
178-
_ => panic!("Unsupported kernel config architecture"),
179-
};
99+
if kernel_config.arch != Arch::X86_64 && !loader_elf_path.exists() {
100+
eprintln!(
101+
"Error: loader ELF '{}' does not exist",
102+
loader_elf_path.display()
103+
);
104+
std::process::exit(1);
105+
}
180106

181107
let image_output_type = match ImageOutputType::resolve(
182108
&args.requested_image_type,
183-
&arch,
109+
&kernel_config.arch,
184110
args.board.as_str(),
185111
) {
186112
Some(image) => image,
187113
None => {
188114
eprintln!(
189-
"microkit: error: building the output image as '{0}' is unsupported for target architecture '{arch}'",
190-
args.requested_image_type
115+
"microkit: error: building the output image as '{0}' is unsupported for target architecture '{1}'",
116+
args.requested_image_type, kernel_config.arch
191117
);
192118
std::process::exit(1);
193119
}
194120
};
195121

196-
let (device_regions, normal_regions) = match arch {
197-
Arch::X86_64 => (None, None),
198-
_ => {
199-
let platform_gen_path = current_config.config_dir.join("platform_gen.json");
200-
bail_if_not_exists("kernel platform configuration file", &platform_gen_path)?;
201-
let kernel_platform_config: PlatformConfig =
202-
serde_json::from_str(&fs::read_to_string(platform_gen_path).unwrap()).unwrap();
203-
204-
(
205-
Some(kernel_platform_config.devices),
206-
Some(kernel_platform_config.memory),
207-
)
208-
}
209-
};
210-
211-
let object_sizes: ObjectSizes = parse_json_file(
212-
"object_sizes.json",
213-
"kernel object sizes file",
214-
current_config,
215-
)?;
216-
217-
let address_space_constants: AddressSpaceConstants = parse_json_file(
218-
"address_space_constants.json",
219-
"kernel address space constants file",
220-
current_config,
221-
)?;
222-
223-
let hypervisor = match arch {
224-
Arch::Aarch64 => json_str_as_bool(&kernel_config_json, "ARM_HYPERVISOR_SUPPORT")?,
225-
Arch::X86_64 => json_str_as_bool(&kernel_config_json, "VTX")?,
226-
// Hypervisor mode is not available on RISC-V
227-
_ => false,
228-
};
229-
230-
let iommu = match arch {
231-
Arch::X86_64 => json_str_as_bool(&kernel_config_json, "IOMMU")?,
232-
_ => false,
233-
};
234-
235-
let arm_pa_size_bits = match arch {
236-
Arch::Aarch64 => {
237-
if json_str_as_bool(&kernel_config_json, "ARM_PA_SIZE_BITS_40")? {
238-
Some(40)
239-
} else if json_str_as_bool(&kernel_config_json, "ARM_PA_SIZE_BITS_44")? {
240-
Some(44)
241-
} else {
242-
panic!("Expected ARM platform to have 40 or 44 physical address bits")
243-
}
244-
}
245-
Arch::X86_64 | Arch::Riscv64 => None,
246-
};
247-
248-
let arm_smc = match arch {
249-
Arch::Aarch64 => Some(json_str_as_bool(&kernel_config_json, "ALLOW_SMC_CALLS")?),
250-
_ => None,
251-
};
252-
253-
let kernel_frame_size = match arch {
254-
Arch::Aarch64 => 1 << 12,
255-
Arch::Riscv64 => 1 << 21,
256-
Arch::X86_64 => 1 << 12,
257-
};
258-
259-
let kernel_config = Config {
260-
arch,
261-
word_size: json_str_as_u64(&kernel_config_json, "WORD_SIZE")?,
262-
minimum_page_size: 1 << object_sizes.small_page,
263-
paddr_user_device_top: json_str_as_u64(&kernel_config_json, "PADDR_USER_DEVICE_TOP")?,
264-
kernel_frame_size,
265-
init_cnode_bits: json_str_as_u64(&kernel_config_json, "ROOT_CNODE_SIZE_BITS")?,
266-
cap_address_bits: 64,
267-
fan_out_limit: json_str_as_u64(&kernel_config_json, "RETYPE_FAN_OUT_LIMIT")?,
268-
max_num_bootinfo_untypeds: json_str_as_u64(
269-
&kernel_config_json,
270-
"MAX_NUM_BOOTINFO_UNTYPED_CAPS",
271-
)?,
272-
hypervisor,
273-
iommu,
274-
benchmark: args.config == "benchmark",
275-
num_cores: if json_str_as_bool(&kernel_config_json, "ENABLE_SMP_SUPPORT")? {
276-
json_str_as_u64(&kernel_config_json, "MAX_NUM_NODES")?
277-
.try_into()
278-
.expect("number of cores fits in u8")
279-
} else {
280-
1
281-
},
282-
num_domains: json_str_as_u64(&kernel_config_json, "NUM_DOMAINS")?
283-
.try_into()
284-
.unwrap(),
285-
num_domain_schedules: json_str_as_u64(&kernel_config_json, "NUM_DOMAIN_SCHEDULES")?,
286-
fpu: json_str_as_bool(&kernel_config_json, "HAVE_FPU")?,
287-
arm_pa_size_bits,
288-
arm_smc,
289-
riscv_pt_levels: Some(RiscvVirtualMemory::Sv39),
290-
invocations_labels,
291-
device_regions,
292-
normal_regions,
293-
object_sizes,
294-
address_space_constants,
295-
};
296-
297-
if kernel_config.arch != Arch::X86_64 && !loader_elf_path.exists() {
298-
eprintln!(
299-
"Error: loader ELF '{}' does not exist",
300-
loader_elf_path.display()
301-
);
302-
std::process::exit(1);
303-
}
304-
305-
assert!(
306-
kernel_config.word_size == 64,
307-
"Microkit tool has various assumptions about the word size being 64-bits."
308-
);
309-
310122
let mut system = match parse(
311123
system_path.as_path(),
312124
&xml,

0 commit comments

Comments
 (0)