diff --git a/tool/microkit/src/main.rs b/tool/microkit/src/main.rs index ccf2272b..826d9b1c 100644 --- a/tool/microkit/src/main.rs +++ b/tool/microkit/src/main.rs @@ -2702,12 +2702,12 @@ fn build_system( } for (pd_idx, pd) in system.protection_domains.iter().enumerate() { - if let Some(domain_idx) = pd.domain_idx { + if let Some(domain_id) = pd.domain_id { system_invocations.push(Invocation::new( config, InvocationArgs::DomainSetSet { domain_set: DOMAIN_CAP_ADDRESS, - domain: domain_idx as u8, + domain: domain_id as u8, tcb: pd_tcb_objs[pd_idx].cap_addr, }, )); @@ -3398,18 +3398,21 @@ fn main() -> Result<(), String> { let mut monitor_elf = ElfFile::from_path(&monitor_elf_path)?; if let Some(domain_schedule) = &system.domain_schedule { - let domains = &domain_schedule.domains; - kernel_elf.write_symbol("ksDomScheduleLength", &(domains.len() as u64).to_le_bytes())?; + let schedule = &domain_schedule.schedule; + kernel_elf.write_symbol( + "ksDomScheduleLength", + &(schedule.len() as u64).to_le_bytes(), + )?; - let mut domain_schedule = Vec::new(); - domain_schedule.reserve_exact(domains.len() * 16); + let mut out = Vec::new(); + out.reserve_exact(schedule.len() * 16); - for (i, domain) in domains.iter().enumerate() { - domain_schedule.extend(i.to_le_bytes()); - domain_schedule.extend(domain.length.to_le_bytes()); + for timeslice in schedule.iter() { + out.extend(timeslice.id.to_le_bytes()); + out.extend(timeslice.length.to_le_bytes()); } - kernel_elf.write_symbol("ksDomSchedule", &domain_schedule)?; + kernel_elf.write_symbol("ksDomSchedule", &out)?; } if monitor_elf.segments.iter().filter(|s| s.loadable).count() > 1 { diff --git a/tool/microkit/src/sdf.rs b/tool/microkit/src/sdf.rs index c3dfdae1..a01b653d 100644 --- a/tool/microkit/src/sdf.rs +++ b/tool/microkit/src/sdf.rs @@ -7,7 +7,7 @@ use crate::sel4::{Config, IrqTrigger, PageSize}; use crate::util::str_to_bool; use crate::MAX_PDS; -use std::collections::HashSet; +use std::collections::HashMap; use std::path::{Path, PathBuf}; /// @@ -46,8 +46,8 @@ const PD_DEFAULT_STACK_SIZE: u64 = 0x1000; const PD_MIN_STACK_SIZE: u64 = 0x1000; const PD_MAX_STACK_SIZE: u64 = 1024 * 1024 * 16; -/// The maximum number of domains supported by the kernel -const DOMAIN_COUNT_MAX: u64 = 256; +/// The maximum length of domain schedule supported by the kernel +const DOMAIN_SCHEDULE_MAX_LENGTH: usize = 256; /// The purpose of this function is to parse an integer that could /// either be in decimal or hex format, unlike the normal parsing @@ -164,7 +164,7 @@ pub struct ProtectionDomain { /// Location in the parsed SDF file text_pos: roxmltree::TextPos, /// Index into the domain schedule vector if the system is using domain scheduling - pub domain_idx: Option, + pub domain_id: Option, } #[derive(Debug, PartialEq, Eq, Hash)] @@ -183,14 +183,15 @@ pub struct VirtualCpu { } #[derive(Debug, PartialEq, Eq, Hash)] -pub struct Domain { - pub name: String, +pub struct DomainTimeslice { + pub id: u64, pub length: u64, } -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq)] pub struct DomainSchedule { - pub domains: Vec, + pub domain_ids: HashMap, + pub schedule: Vec, } impl SysMapPerms { @@ -437,11 +438,11 @@ impl ProtectionDomain { )); } - let mut domain_idx = None; + let mut domain_id = None; match (domain_schedule, checked_lookup(xml_sdf, node, "domain")) { (Some(domain_schedule), Ok(domain_name)) => { - domain_idx = domain_schedule.domains.iter().position(|d| d.name == domain_name); - if domain_idx.is_none() { + domain_id = domain_schedule.domain_ids.get(domain_name); + if domain_id.is_none() { return Err(format!("Protection domain {} specifies a domain {} that is not in the domain schedule", name, domain_name)); } } @@ -648,7 +649,7 @@ impl ProtectionDomain { has_children, parent: None, text_pos: xml_sdf.doc.text_pos_at(node.range().start), - domain_idx, + domain_id: domain_id.copied(), }) } } @@ -914,8 +915,9 @@ impl DomainSchedule { check_attributes(xml_sdf, node, &[])?; - let mut domains = Vec::new(); - let mut domain_names = HashSet::new(); + let mut next_domain_id = 0; + let mut domain_ids = HashMap::new(); + let mut schedule = Vec::new(); for child in node.children() { if !child.is_element() { continue; @@ -930,39 +932,44 @@ impl DomainSchedule { )); } - check_attributes(xml_sdf, &child, &["name", "length"])?; - - let name = checked_lookup(xml_sdf, &child, "name")?; - if !domain_names.insert(name.to_string()) { + if schedule.len() == DOMAIN_SCHEDULE_MAX_LENGTH { return Err(format!( - "Error: duplicate domain name '{}': {}", - name, - loc_string(xml_sdf, pos) - )); - } - if domain_names.len() as u64 > DOMAIN_COUNT_MAX { - return Err(format!( - "Error: number of domains in domain schedule exceeds maximum of 256: {}", + "Error: length of domain schedule exceeds maximum of {}: {}", + DOMAIN_SCHEDULE_MAX_LENGTH, loc_string(xml_sdf, pos) )); } - let time = checked_lookup(xml_sdf, &child, "length")?.parse::(); - if time.is_err() { + check_attributes(xml_sdf, &child, &["name", "length"])?; + let name = checked_lookup(xml_sdf, &child, "name")?; + let length = checked_lookup(xml_sdf, &child, "length")?.parse::(); + if length.is_err() { return Err(format!( - "Error: invalid domain time '{}': {}", + "Error: invalid domain timeslice length '{}': {}", name, loc_string(xml_sdf, pos) )); } - domains.push(Domain { - name: name.to_string(), - length: time.unwrap(), + let id = { + if !domain_ids.contains_key(&name.to_string()) { + domain_ids.insert(name.to_string(), next_domain_id); + next_domain_id += 1; + } + *domain_ids.get(&name.to_string()).unwrap() + }; + + domain_ids.insert(name.to_string(), id); + schedule.push(DomainTimeslice { + id, + length: length.unwrap(), }); } - Ok(DomainSchedule { domains }) + Ok(DomainSchedule { + domain_ids, + schedule, + }) } }