diff --git a/Cargo.toml b/Cargo.toml index 34df35b336ad813a6efb440fe013999d7d0801ff..8be19118503f77a92e584b21d3599cd330bfbb7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,11 +9,7 @@ description = "(Another) DSL/library for specifying and analyzing SoCs for syste # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] -name = "imx8" -path = "src/bin/imx8.rs" - -[[bin]] -name = "toy_qualpwn" +name = "repl" [[bin]] name = "mmu" diff --git a/src/bin/imx8.rs b/src/bin/imx8.rs deleted file mode 100644 index 9d106972455ca783c9f96fd1dd0e24bfb4ea0f24..0000000000000000000000000000000000000000 --- a/src/bin/imx8.rs +++ /dev/null @@ -1,196 +0,0 @@ -use log::info; - -use std::collections::{BTreeSet,BTreeMap}; -use std::fs::File; - -use sockeye3::glas::{self, *}; -use sockeye3::specs::examples::*; -use sockeye3::output; -use sockeye3::output::glas::*; - - -pub fn main() { - { - let logconf = simplelog::ConfigBuilder::new() - .set_thread_level(simplelog::LevelFilter::Error) - .set_thread_mode(simplelog::ThreadLogMode::Names) - .build(); - - simplelog::CombinedLogger::init(vec![simplelog::TermLogger::new( - //simplelog::LevelFilter::Error, - //simplelog::LevelFilter::Warn, - simplelog::LevelFilter::Info, - logconf, - simplelog::TerminalMode::Stderr, - simplelog::ColorChoice::Auto, - )]) - .unwrap(); - } - - info!("Constructing i.MX8 decoding net..."); - let use_random_xrdc_assignment = false; - let (dn, _imx8) = imx8::instantiate_imx8_example(use_random_xrdc_assignment).expect("could not create imx8 spec"); - let dn = glas::DecodingNet::from_spec(&dn).expect("Could not create GLAS"); - - let mut ctxts = dn.contexts.clone(); - let resources = dn.resources.clone(); - - let ctxts_to_remove = vec![ - //"DSP_VIEW", - //"CM4 M4 core view", - "vas (MMU_DB_A35_0)", - "MMU_DB_A35_1", - "MMU_DB_A35_2", - "MMU_DB_A35_3", - ]; - for ctx in ctxts_to_remove { - let id = dn.id_for(ctx); - let pos = ctxts.iter().position(|&x| x == id).unwrap(); - ctxts.remove(pos); - } - - let f = dn.flatten(&ctxts); - debug_flattened_address_spaces(&f, &dn); - - eprintln!("contexts ({}): ", ctxts.len()); - for &c in &ctxts { - eprint!(" '{}' ", dn.names[c]); - } - eprintln!(); - - eprintln!("resources ({}): ", resources.len()); - for &r in &resources { - eprint!(" '{}' ", dn.names[r]); - } - eprintln!(); - eprintln!(); - - debug_hw_matrix(&dn, &f, &ctxts, &resources); - - eprintln!("deriving glas (w/Z3)..."); - let glas = glas::derive_glas(&dn, &ctxts, &resources, &BTreeSet::new()); - match &glas { - Ok(glas) => { - debug_glas(&glas, &dn, &ctxts, &resources); - let mut file = std::fs::File::create("/tmp/dn.gv").unwrap(); - visualize_dn(&mut file, &dn).unwrap(); - eprintln!("wrote dn dot to /tmp/dn.gv"); - let mut file = std::fs::File::create("/tmp/glas.gv").unwrap(); - visualize_glas(&mut file, &glas, &dn).unwrap(); - eprintln!("wrote GLAS dot to /tmp/glas.gv"); - - let id = dn.names.iter().position(|p| p == "DB_A35_0").unwrap(); - let mut file = std::fs::File::create("/tmp/glas_for.gv").unwrap(); - visualize_glas_for(&mut file, &glas, &dn, &f, id, &resources).unwrap(); - eprintln!("wrote GLAS dot of an A35 core to /tmp/glas_for.gv"); - - let mut file = File::create("/tmp/imx8_glas.json").unwrap(); - output::glas::json(&mut file, &glas, &dn, &f, &resources).unwrap(); - eprintln!("wrote json to /tmp/imx8_glas.json"); - }, - Err(err) => print_err(&err, &dn), - } - -} - -fn print_err(err: &DerivationError, dn: &DecodingNet) { - match err { - DerivationError::PlaceAlreadyTaken(res1, placed, res2, target) => { - eprintln!( - "to be placed resource '{}' conflicts already placed '{}'", - dn.names[*res2], dn.names[*res1], - ); - eprintln!(" placed: {:#12x}, {} B", placed.offset, placed.length); - eprintln!(" target: {:#12x}, {} B", target.offset, target.length); - } - _ => unimplemented!(), - } -} - -fn debug_hw_matrix(dn: &DecodingNet, f: &FlattenResult, ctxts: &Vec<usize>, resources: &Vec<usize>) { - let mut matrix = Vec::new(); - let mut ress = BTreeMap::new(); - for (_, space) in f.r.iter() { - for (_,r,rr) in space { - if !resources.contains(r) { continue; } - let e = ress.entry(r).or_insert(BTreeSet::new()); - e.insert((rr.offset,rr.length)); - } - } - let mut rs = Vec::new(); - for (&r,rss) in ress.iter() { - for (ro,rl) in rss { - rs.push((r,ro,rl)); - } - } - - for (_, space) in f.r.iter() { - let mut row = vec![false; rs.len()]; - for &(_, r, rr) in space { - match rs.iter().position(|&(&r1,&ro1,&rl1)| r1 == r && ro1 == rr.offset && rl1 == rr.length) { - Some(j) => row[j] = true, - None => continue, - } - } - matrix.push(row); - } - - eprintln!("hardware protection matrix"); - - for _ in rs.iter() { - eprint!(" "); - } - eprintln!(" contexts"); - - for _ in rs.iter() { - eprint!(" "); - } - eprintln!(" --------"); - - for (i, row) in matrix.into_iter().enumerate() { - for col in row { - if col { - eprint!("x "); - } else { - eprint!(" "); - } - } - eprint!("| "); - let ctxidx = ctxts[i]; - eprintln!("{}", dn.names[ctxidx]); - } - - for _ in rs.iter() { - eprint!("--") - } - eprintln!("+"); - - let mut i = 0; - let mut do_continue = true; - while do_continue { - do_continue = false; - for &(r,ro,_) in rs.iter() { - let s = format!("{} @ {:#x}", &dn.names[*r], ro); - if i < s.len() { - do_continue = true; - eprint!("{} ", s.bytes().nth(i).unwrap() as char); - } else { - eprint!(" "); - } - } - - eprint!("| "); - - if i < "resources".len() { - do_continue = true; - eprint!("{} ", "resources".bytes().nth(i).unwrap() as char); - } else { - eprint!(" "); - } - - - i += 1; - eprintln!(); - } - -} diff --git a/src/bin/repl.rs b/src/bin/repl.rs index 2fe24261d551f7096d70c188fc8b2769b6fa687d..0327bc49f72baa44db4e98d3b96f4108b0cb701f 100644 --- a/src/bin/repl.rs +++ b/src/bin/repl.rs @@ -2,24 +2,29 @@ use sockeye3::glas; use sockeye3::glas::GLAS; use sockeye3::output; use sockeye3::output::human_bytes; +use sockeye3::range::Range; use sockeye3::spec; use sockeye3::specs::examples; use std::collections::{BTreeMap,BTreeSet}; +use std::env; use std::io; use std::io::Write; +use serde::{Serialize,Deserialize}; + type SpecDef = (String, fn(&Configuration) -> Result<spec::DecodingNet, spec::SpecError>); struct State { specs: BTreeMap<String, SpecDef>, + glas_constraints: Vec<(usize, u128, u128, u128)>, glas: Option<(glas::DecodingNet, GLAS)>, cfg: Configuration, chosen: String, model: spec::DecodingNet, } -fn main() -> Result<(), ReplError> { +fn main() -> Result<(), ReplError> { let mut specs: BTreeMap<String, SpecDef> = BTreeMap::new(); specs.insert("empty".to_string(), ( "An empty decoding net".to_string(), @@ -29,6 +34,10 @@ fn main() -> Result<(), ReplError> { "A model of the NXP i.MX8".to_string(), |cfg: &Configuration| examples::imx8::instantiate_imx8_example(cfg.imx8.use_random_xrdc).map(|s| s.0), )); + specs.insert("morello".to_string(), ( + "A model of the Morello FVP".to_string(), + |_| examples::morello::instantiate_morello_example().map(|s| s.0), + )); specs.insert("qemu_aarch64".to_string(), ( "A model of QEMU's aarch64 virt platform".to_string(), |_| examples::qemu_aarch64::create_dn(), @@ -40,12 +49,28 @@ fn main() -> Result<(), ReplError> { let mut state = State { specs, + glas_constraints: Vec::new(), glas: None, cfg, chosen, model, }; + let args: Vec<String> = env::args().collect(); + if args.len() > 1 { + let path = &args[1]; + println!("intepreting file '{}'", path); + let file = std::fs::File::open(path)?; + let mut r = std::io::BufReader::new(file); + state.run(&mut r, false)?; + } else { + repl(&mut state)?; + } + + Ok(()) +} + +fn repl(state: &mut State) -> Result<(), ReplError> { let stdin = io::stdin(); let mut handle = stdin.lock(); @@ -57,27 +82,35 @@ fn main() -> Result<(), ReplError> { impl State { fn run(&mut self, handle: &mut impl io::BufRead, interactive: bool) -> Result<(), ReplError> { let mut line = String::new(); - let mut cmds = vec![ - ("add_address_space", "name offset len", "Add a new address space"), - ("add_mapping", "src dst src_off dst_off len", "Add a new mapping"), - ("exit", "", "Exit the REPL"), - ("derive_glas", "", "Derive the GLAS"), - ("glas", "", "Print the GLAS"), - ("glas_for", "name", "Print the GLAS for a specific core"), - ("glas_json", "path", "Write the GLAS description as JSON to path"), - ("help", "", "Print available commands"), - ("info", "", "Print info about the current model"), - ("mark_context", "name", "Mark an address space as a context"), - ("mark_resource", "name", "Mark an address space as a resource"), - ("models", "", "List available models"), - ("quit", "", "Quit the REPL"), - ("read_file", "path", "Read and execute the commands in from a file"), - ("set_model", "name", "Set the current model"), - ("viz_dn", "path [open]", "Visualize the decoding net using graphviz"), - ("viz_glas", "path [open]", "Visualize the GLAS using graphviz"), - ("viz_glas_for", "name path [open]", "Visualize the GLAS for a specific core using graphviz"), - ]; - cmds.sort(); + let cmds: BTreeMap<&str, (&str, &str)> = BTreeMap::from([ + ("add_address_space", ("name offset len", "Add a new address space")), + ("add_mapping", ("src dst src_off dst_off len", "Add a new mapping")), + ("add_glas_constraint", ("name phys_addr glas_addr len", + "Add a constraint to the GLAS to force (phys_addr, len) in name to map to (glas_addr, len)")), + ("as_info", ("name", "Print info about given address_space")), + ("exit", ("", "Exit the REPL")), + ("derive_glas", ("", "Derive the GLAS")), + ("flattened_context", ("name", "Print details of flattened context")), + ("gen_pt", ("name base_addr path", "Generate page tables as C header file for the given context")), + ("glas", ("", "Print the GLAS")), + ("glas_for", ("name", "Print the GLAS for a specific core")), + ("glas_json", ("path", "Write the GLAS description as JSON to path")), + ("hw_matrix", ("[path]", "Output the hardware protection matrix")), + ("help", ("", "Print available commands")), + ("info", ("", "Print info about the current model")), + ("load_glas", ("path", "Load a derived GLAS from a file")), + ("mark_context", ("name", "Mark an address space as a context")), + ("mark_resource", ("name", "Mark an address space as a resource")), + ("models", ("", "List available models")), + ("quit", ("", "Quit the REPL")), + ("read_file", ("path", "Read and execute the commands in from a file")), + ("save_glas", ("path", "Save the derived GLAS to a file")), + ("set_model", ("name", "Set the current model")), + ("trace_path", ("name addr", "Trace address decoding path of given address")), + ("viz_dn", ("path [open]", "Visualize the decoding net using graphviz")), + ("viz_glas", ("path [open]", "Visualize the GLAS using graphviz")), + ("viz_glas_for", ("name path [open]", "Visualize the GLAS for a specific core using graphviz")), + ]); loop { line.clear(); if interactive { print!("> "); } @@ -90,16 +123,24 @@ impl State { let res = match cmd { Some("add_address_space") => self.add_address_space(&mut args), Some("add_mapping") => self.add_mapping(&mut args), + Some("add_glas_constraint") => self.add_glas_constraint(&mut args), + Some("as_info") => self.print_address_space_info(&mut args), Some("derive_glas") => self.derive_glas(), + Some("gen_pt") => self.generate_page_table_for_context(&mut args), Some("glas") => self.print_glas(), Some("glas_for") => self.print_glas_from_view(&mut args), Some("glas_json") => self.glas_json(&mut args), + Some("hw_matrix") => self.print_hardware_matrix(&mut args), + Some("flattened_context") => self.print_flattened_context(&mut args), Some("info") => self.print_info(), + Some("load_glas") => self.load_glas(&mut args), Some("mark_context") => self.mark_context(&mut args), Some("mark_resource") => self.mark_resource(&mut args), Some("models") => self.list_models(), + Some("save_glas") => self.save_glas(&mut args), Some("set_model") => self.set_model(&mut args), Some("read_file") => self.read_file(&mut args), + Some("trace_path") => self.trace_path(&mut args), Some("viz_dn") => self.visualize_dn(&mut args), Some("viz_glas") => self.visualize_glas(&mut args), Some("viz_glas_for") => self.visualize_glas_for(&mut args), @@ -107,7 +148,7 @@ impl State { Some("exit") => break, Some("help") => { println!("{:20} {:30} Description", "Command", "Parameters"); - for (name, params, descr) in cmds.iter() { + for (name, (params, descr)) in cmds.iter() { println!("{name:20} {params:30} {descr}"); } Ok(()) @@ -116,12 +157,26 @@ impl State { None => Err(ReplError::NoArgumentProvided), }; - let e = match res { - Ok(()) => continue, - Err(e) => e, - }; - - println!("error: {e}"); + match res { + Ok(()) => (), + Err(e) => { + println!("{}", e); + let cmd = cmd.unwrap_or(""); + match cmds.get(cmd) { + Some((params, descr)) => { + println!("usage:"); + println!("{cmd} {params} -- {descr}") + }, + None => { + println!("commands:"); + println!("{:20} {:30} Description", "Command", "Parameters"); + for (name, (params, descr)) in cmds.iter() { + println!("{name:20} {params:30} {descr}"); + } + } + } + }, + } } Ok(()) @@ -143,6 +198,7 @@ impl State { println!("setting model '{}'", m); self.model = f(&self.cfg)?; self.chosen = m.to_string(); + self.glas_constraints.clear(); self.glas = None; Ok(()) @@ -161,6 +217,207 @@ impl State { Ok(()) } + fn print_hardware_matrix<'a>(&self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { + let mut handle: Box<dyn io::Write> = match Self::next_arg(args) { + Ok(path) => Box::new(std::fs::File::create(path)?), + Err(_) => Box::new(std::io::stdout().lock()), + }; + + let dn = glas::DecodingNet::from_spec(&self.model).unwrap(); + let f = dn.flatten(&dn.contexts); + + let ctxts = &dn.contexts; + let resources = &dn.resources; + + let mut matrix = Vec::new(); + let mut ress = BTreeMap::new(); + for (_, space) in f.r.iter() { + for (_,r,rr) in space { + if !resources.contains(r) { continue; } + let e = ress.entry(r).or_insert(BTreeSet::new()); + e.insert((rr.offset,rr.length)); + } + } + let mut rs = Vec::new(); + for (&r,rss) in ress.iter() { + for (ro,rl) in rss { + rs.push((r,ro,rl)); + } + } + + for (_, space) in f.r.iter() { + let mut row = vec![false; rs.len()]; + for &(_, r, rr) in space { + match rs.iter().position(|&(&r1,&ro1,&rl1)| r1 == r && ro1 == rr.offset && rl1 == rr.length) { + Some(j) => row[j] = true, + None => continue, + } + } + matrix.push(row); + } + + writeln!(handle, "hardware protection matrix for model '{}'", self.chosen)?; + + for _ in rs.iter() { + write!(handle, " ")?; + } + writeln!(handle, " contexts")?; + + for _ in rs.iter() { + write!(handle, " ")?; + } + writeln!(handle, " --------")?; + + for (i, row) in matrix.into_iter().enumerate() { + for col in row { + if col { + write!(handle, "x ")?; + } else { + write!(handle, " ")?; + } + } + write!(handle, "| ")?; + let ctxidx = ctxts[i]; + writeln!(handle, "{}", dn.names[ctxidx])?; + } + + for _ in rs.iter() { + write!(handle, "--")?; + } + writeln!(handle, "+")?; + + let mut i = 0; + let mut do_continue = true; + while do_continue { + do_continue = false; + for &(r,ro,_) in rs.iter() { + let s = format!("{} @ {:#x}", &dn.names[*r], ro); + if i < s.len() { + do_continue = true; + write!(handle, "{} ", s.bytes().nth(i).unwrap() as char)?; + } else { + write!(handle, " ")?; + } + } + + write!(handle, "| ")?; + + if i < "resources".len() { + do_continue = true; + write!(handle, "{} ", "resources".bytes().nth(i).unwrap() as char)?; + } else { + write!(handle, " ")?; + } + + + i += 1; + writeln!(handle)?; + } + + Ok(()) + } + + fn print_address_space_info<'a>(&self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { + let (name, asid) = Self::next_asid(&self.model, args)?; + let address_space = &self.model.address_spaces[asid.as_usize()]; + + println!("context {}", name); + println!("description: {}", address_space.description); + println!( + "addresses {:#x} - {:#x}, length {}", + address_space.range.offset, + address_space.range.offset + address_space.range.length - 1, + human_bytes(address_space.range.length), + ); + + let mappings = &self.model.mappings[asid.as_usize()]; + if mappings.is_empty() { + println!("no mappings"); + } else { + println!("mappings"); + for mapping in self.model.mappings[asid.as_usize()].iter() { + let dst = &self.model.address_spaces[mapping.dst.as_usize()].name; + println!( + "{:#20x} - {:#20x} maps to {:20} @ {:#20x} {}", + address_space.range.offset, + address_space.range.offset + address_space.range.length - 1, + dst, + mapping.dst_range.offset, + mapping.description, + ); + } + } + + Ok(()) + } + + fn print_flattened_context<'a>(&self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { + let (name, asid) = Self::next_asid(&self.model, args)?; + self.model.contexts.contains(&asid).then_some(asid).ok_or(ReplError::NotAContext(name.to_string()))?; + + let spec = glas::DecodingNet::from_spec(&self.model).unwrap(); + let f = spec.flatten(&spec.contexts); + println!("flattened context {}", name); + + for &(src_range, r, dst_range) in f.r[&asid.as_usize()].iter() { + let r_name = &self.model.address_spaces[r].name; + println!( + "{:#20x} - {:#20x} maps to {:20} @ {:#20x}", + src_range.offset, + src_range.offset + src_range.length - 1, + r_name, + dst_range.offset + ); + } + + Ok(()) + } + + fn trace_path<'a>(&self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { + let (name, asid) = Self::next_asid(&self.model, args)?; + let addr = Self::next_num(args)?; + + println!("tracing decoding of address {:#x} in address space {}", addr, name); + + let mut a = asid; + let mut addr = addr; + loop { + let space = &self.model.address_spaces[a.as_usize()]; + if addr < space.range.offset || addr >= space.range.offset + space.range.length { + return Err(ReplError::AddressOutOfRange(addr, space.range)); + } + + + let current_mappings = &self.model.mappings[a.as_usize()]; + if current_mappings.len() == 0 { break; } + + let idx = current_mappings.binary_search_by_key( + &addr, + |m| m.src_range.offset + m.src_range.length - 1 + ); + + let idx = match idx { + Ok(idx) => idx, + Err(idx) => idx, + }; + + assert!(idx < current_mappings.len()); + let mapping = ¤t_mappings[idx]; + println!("{:#20x} in {:10} -- {}", addr, space.name, mapping.description); + + if mapping.src_range.offset <= addr && addr < mapping.src_range.offset + mapping.src_range.length { + let diff = mapping.dst_range.offset as i128 - mapping.src_range.offset as i128; + addr = (addr as i128 + diff) as u128; + a = mapping.dst; + } else { + break; + } + } + + println!("{:#20x} in {:10}", addr, self.model.address_spaces[a.as_usize()].name); + Ok(()) + } + fn print_info(&self) -> Result<(), ReplError> { println!("selected model {}", self.chosen); println!("number of address spaces: {}", self.model.address_spaces.len()); @@ -182,7 +439,7 @@ impl State { fn derive_glas(&mut self) -> Result<(), ReplError> { let spec = glas::DecodingNet::from_spec(&self.model).unwrap(); - let glas = glas::derive_glas(&spec, &spec.contexts, &spec.resources, &BTreeSet::new()).unwrap(); + let glas = glas::derive_glas(&spec, &spec.contexts, &spec.resources, &self.glas_constraints).unwrap(); self.glas = Some((spec, glas)); Ok(()) } @@ -236,11 +493,11 @@ impl State { Ok("open") => { println!("compiling figure..."); let status = std::process::Command::new("dot") - .args(["-Tpng", "-o", "/tmp/img.png", path]) + .args(["-Tpdf", "-o", "/tmp/figure.pdf", path]) .status()?; if !status.success() { return Err(ReplError::UnknownError) } println!("opening figure"); - open::that("/tmp/img.png")?; + open::that("/tmp/figure.pdf")?; }, Ok(cmd) => return Err(ReplError::UnknownCommand(cmd.to_string())), Err(_) => {}, @@ -302,14 +559,90 @@ impl State { Ok(()) } + fn generate_page_table_for_context<'a>(&mut self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { + match &self.glas { + None => self.derive_glas()?, + _ => (), + } + let (spec, glas) = self.glas.as_ref().unwrap(); + let f = spec.flatten(&spec.contexts); + + let (name, asid) = Self::next_asid(&self.model, args)?; + self.model.contexts.contains(&asid).then_some(()).ok_or(ReplError::NotAContext(name.clone()))?; + + let base_addr = Self::next_num(args)?; + + let path = Self::next_arg(args)?; + let mut file = std::fs::File::create(path)?; + + eprintln!("deriving page table..."); + let pt = glas::page_table_from_glas( + &glas, + &f, + asid.as_usize(), + base_addr, + &spec.resources, + ); + + eprintln!("number of pages used for page table: {} ({})", pt.page_tracker.used_pages, output::human_bytes(pt.page_tracker.used_pages as u128 * 4096)); + let num_entries = pt.page_tracker.used_pages * 512; + let mut entries = vec![0; num_entries]; + pt.base_table.materialize_into(&mut entries); + + writeln!(file, "typedef unsigned long long pt_entry;")?; + writeln!(file, "unsigned long long num_page_table_entries = {:#x};", num_entries)?; + writeln!(file, "pt_entry *page_table_base = (pt_entry *)({:#x});", base_addr)?; + writeln!(file, "pt_entry page_table_entries[{}] = {{", num_entries)?; + + let mut addr = base_addr; + for chunk in entries.chunks(8) { + if addr % 4096 == 0 { + writeln!(file, " // ----------- {:#x} -------------", addr)?; + } + write!(file, " ")?; + for entry in chunk { + write!(file, " {:#x},", entry)?; + addr += 8; + } + writeln!(file)?; + } + writeln!(file, "}};")?; + + writeln!(file, r#" +void activate_page_tables() {{ + for (int i = 0; i < num_page_table_entries; i++) {{ + page_table_base[i] = page_table_entries[i]; + }} + __asm__ ("LDR x1, ={:#x}\n\t" // program ttbr0 on this CPU + "MSR ttbr0_el1, x1\n\t" + "LDR x1, =0xff\n\t" // program mair on this CPU + "MSR mair_el1, x1\n\t" + "LDR x1, =0x500803510\n\t" // program tcr on this CPU + "MSR tcr_el1, x1\n\t" + "ISB\n\t" + "MRS x2, tcr_el1\n\t" // verify CPU supports desired config + "CMP x2, x1\n\t" + "B.NE .\n\t" + "LDR x1, =0x1005\n\t" // program sctlr on this CPU + "MSR sctlr_el1, x1\n\t" + "ISB\n\t" // synchronize context on this CPU + : : : + ); +}} +"#, + base_addr)?; + println!("wrote page tables to '{}'", path); + Ok(()) + } + fn next_arg<'a>(args: &mut impl Iterator<Item = &'a str>) -> Result<&'a str, ReplError> { args.next().ok_or(ReplError::NoArgumentProvided) } - fn next_num<'a, T>(args: &mut impl Iterator<Item = &'a str>) -> Result<T, ReplError> - where T: std::str::FromStr { + fn next_num<'a>(args: &mut impl Iterator<Item = &'a str>) -> Result<u128, ReplError> { let s = args.next().ok_or(ReplError::NoArgumentProvided)?; - let t = s.parse::<T>().map_err(|_| ReplError::NotANumber(s.to_string()))?; + let s = s.strip_prefix("0x").ok_or(ReplError::InvalidNumberFormat(s.to_string()))?.replace("_", ""); + let t = u128::from_str_radix(&s, 16).map_err(|_| ReplError::NotANumber(s.to_string()))?; Ok(t) } @@ -323,8 +656,8 @@ impl State { let name = args.next().ok_or(ReplError::NoArgumentProvided)?; //let asid = self.model.address_spaces.iter().position(|a| a.name == name).ok_or(ReplError::NotAnAddressSpace(name.to_string()))?; - let offset = Self::next_num::<u128>(args)?; - let len = Self::next_num::<u128>(args)?; + let offset = Self::next_num(args)?; + let len = Self::next_num(args)?; let _ = self.model.add_address_space(name, "", offset, len)?; self.glas = None; @@ -337,9 +670,9 @@ impl State { let (src, src_asid) = Self::next_asid(&self.model, args)?; let (dst, dst_asid) = Self::next_asid(&self.model, args)?; - let src_offset = Self::next_num::<u128>(args)?; - let dst_offset = Self::next_num::<u128>(args)?; - let len = Self::next_num::<u128>(args)?; + let src_offset = Self::next_num(args)?; + let dst_offset = Self::next_num(args)?; + let len = Self::next_num(args)?; let _ = self.model.add_mapping(src_asid, dst_asid, src_offset, dst_offset, len, "")?; self.glas = None; @@ -348,6 +681,60 @@ impl State { Ok(()) } + fn add_glas_constraint<'a>(&mut self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { + let (name, asid) = Self::next_asid(&self.model, args)?; + let phys_addr = Self::next_num(args)?; + let glas_addr = Self::next_num(args)?; + let len = Self::next_num(args)?; + + let spec = glas::DecodingNet::from_spec(&self.model).unwrap(); + let f = spec.flatten(&spec.contexts); + let mut is_valid_additional_constraint = false; + for &(src_range, _, _) in f.r[&asid.as_usize()].iter() { + if src_range.offset == phys_addr && src_range.length == len { + is_valid_additional_constraint = true; + } + } + if !is_valid_additional_constraint { + return Err(ReplError::InvalidGlasConstraint(phys_addr, glas_addr, len)); + } + + self.glas = None; + self.glas_constraints.push((asid.as_usize(), phys_addr, glas_addr, len)); + println!("added constraint to map {}@{:#x} to {:#x} in the GLAS", name, phys_addr, glas_addr); + + Ok(()) + } + + fn load_glas<'a>(&mut self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { + let path = Self::next_arg(args)?; + let file = std::fs::File::open(path)?; + + let loaded_glas: SerializedGlas = serde_json::from_reader(file).map_err(|_| ReplError::InvalidGlas(path.to_string()))?; + + let expected_spec = glas::DecodingNet::from_spec(&self.model).unwrap(); + if loaded_glas.spec != expected_spec { + return Err(ReplError::InvalidGlas(path.to_string())); + } + + self.glas = Some((loaded_glas.spec, loaded_glas.glas)); + Ok(()) + } + + fn save_glas<'a>(&mut self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { + let path = Self::next_arg(args)?; + let file = std::fs::File::create(path)?; + + match &self.glas { + None => self.derive_glas()?, + _ => (), + } + let (spec, glas) = self.glas.as_ref().unwrap(); + let sg = SerializedGlas{ glas: glas.clone(), spec: spec.clone() }; + serde_json::to_writer(file, &sg).map_err(|_| ReplError::UnknownError)?; + Ok(()) + } + fn mark_context<'a>(&mut self, args: &mut impl Iterator<Item = &'a str>) -> Result<(), ReplError> { let (name, asid) = Self::next_asid(&self.model, args)?; self.model.mark_context(asid, ""); @@ -367,6 +754,12 @@ impl State { } } +#[derive(Serialize, Deserialize)] +struct SerializedGlas { + spec: glas::DecodingNet, + glas: GLAS, +} + #[derive(Debug)] #[allow(dead_code)] enum ReplError { @@ -379,6 +772,10 @@ enum ReplError { NotANumber(String), NoArgumentProvided, SpecError(spec::SpecError), + AddressOutOfRange(u128, Range), + InvalidGlasConstraint(u128, u128, u128), + InvalidNumberFormat(String), + InvalidGlas(String), UnknownError, } @@ -393,7 +790,11 @@ impl std::fmt::Display for ReplError { ReplError::UnknownCommand(c) => write!(f, "unknown command '{}'", c), ReplError::NotANumber(n) => write!(f, "not a number: '{}'", n), ReplError::NoArgumentProvided => write!(f, "missing argument"), + ReplError::AddressOutOfRange(a, r) => write!(f, "{:#x} is not in range {:#x} - {:#x}", a, r.offset, r.offset + r.length - 1), ReplError::UnknownError => write!(f, "unknown error"), + ReplError::InvalidGlasConstraint(_pa, _ga, _l) => write!(f, "invalid glas constraint, can only map full resources for now\n see 'flatten_context' for the ranges that can be flattened"), + ReplError::InvalidNumberFormat(s) => write!(f, "invalid number format '{}': hex prefix (0x) required", s), + ReplError::InvalidGlas(p) => write!(f, "invalid glas at path '{}'", p), ReplError::SpecError(e) => write!(f, "underlying spec error: {:?}", e), }?; diff --git a/src/glas.rs b/src/glas.rs index 76a47664da94907e98cdb4d4a4589fb767fa5391..fc01c5be169eb2625193ea2549d54aafb19918c2 100644 --- a/src/glas.rs +++ b/src/glas.rs @@ -10,12 +10,14 @@ use std::collections::BTreeMap; use std::collections::BTreeSet; +use std::io::Write; use crate::range::Range; use crate::range_tree::RangeTree; use crate::spec; +use crate::specs::examples::mmu::PageTable; -use std::io::Write; +use serde::{Serialize, Deserialize}; pub type ASID = usize; @@ -50,7 +52,7 @@ pub fn derive_glas( dn: &DecodingNet, contexts: &Vec<usize>, resources: &Vec<usize>, - _required: &BTreeSet<(usize, usize)>, + additional_constraints: &Vec<(usize, u128, u128, u128)>, ) -> Result<GLAS, DerivationError> { let mut glas = GLAS::new(); @@ -58,7 +60,7 @@ pub fn derive_glas( let ctx = z3::Context::new(&cfg); let mut buf = Vec::new(); - let (loffs, goffs) = write_smtlib_program_to(dn, contexts, resources, _required, &mut buf)?; + let (loffs, goffs) = write_smtlib_program_to(dn, contexts, resources, additional_constraints, &mut buf)?; let prog = String::from_utf8(buf).unwrap(); eprintln!("initializing solver"); @@ -118,6 +120,7 @@ pub fn derive_glas( } glas.placement.sort_by_key(|b| b.1.offset); + glas.swizzles.sort_by_key(|b| (b.0, b.1.offset)); Ok(glas) } @@ -125,7 +128,7 @@ fn write_smtlib_program_to<W: Write>( dn: &DecodingNet, contexts: &Vec<usize>, resources: &Vec<usize>, - _required: &BTreeSet<(usize, usize)>, + additional_constraints: &Vec<(usize, u128, u128, u128)>, w: &mut W, ) -> Result< ( @@ -193,6 +196,25 @@ fn write_smtlib_program_to<W: Write>( } eprintln!("wrote constraints for local-to-global offsets"); + for &(name, phys_addr, glas_addr, len) in additional_constraints { + // we want phys_addr, len to map to glas_addr, len + // TODO: hack: we disallow any cases where (phys_addr, len) is not the length of an existing + // resource. this can be fixed easily by taking additional_constraints into consideration + // during glas::DecodingNet. + let mut is_valid_additional_constraint = false; + for &(src_range, _, _) in f[&name].iter() { + if src_range.offset == phys_addr && src_range.length == len { + is_valid_additional_constraint = true; + } + } + assert!(is_valid_additional_constraint); + + let o = format!("o_{}_{}", name, phys_addr); + let o_value: i128 = glas_addr as i128 - phys_addr as i128; + writeln!(w, "(assert (= {o} {o_value}))")?; + } + eprintln!("declared additional constriants"); + eprintln!( "writing disjointness constraints num={}", vars.keys().count() @@ -264,7 +286,7 @@ pub fn debug_glas(glas: &GLAS, dn: &DecodingNet, ctxts: &Vec<usize>, res: &Vec<u /// A decoding net, in a representation useful GLAS derivation. /// /// It is constructed from a general decoding net. -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct DecodingNet { pub address_spaces: Vec<RangeTree<(usize, Range)>>, pub names: Vec<String>, @@ -481,7 +503,7 @@ impl DecodingNet { } /// Represents a global logical address space, computed for a particular decoding net. -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct GLAS { /// Records the placement of a particular resource range in a contiguous (offset, length) /// region. For more efficient range lookups, we should use something akin to an interval tree. @@ -500,6 +522,53 @@ impl GLAS { } } +/// Generate 4-level page tables from this GLAS for this context. +/// +/// TODO: this should probably be a function per-mmu +pub fn page_table_from_glas(glas: &GLAS, f: &FlattenResult, context: usize, base_addr: u128, resources: &Vec<usize>) -> PageTable { + let mut page_table = PageTable::new(base_addr); + + let space = &f.r[&context]; + let mut placed = vec![false; glas.placement.len()]; + for (ctx_range, resource, resource_range) in space.iter().filter(|(_,r,_)| resources.contains(r)) { + let i = glas.placement.iter().position(|(r,_,c)| r == resource && c == resource_range).unwrap(); + let (_, glas_range, _) = glas.placement[i]; + + if placed[i] { continue; } + + assert!(ctx_range.offset % 4096 == 0); + assert!(glas_range.offset % 4096 == 0); + + assert!(ctx_range.length % 4096 == 0); + assert!(ctx_range.length == glas_range.length); + + + let sz = if ctx_range.offset % (1 << 30) == 0 && glas_range.offset % (1 << 30) == 0 && glas_range.length % (1 << 30) == 0 { + 1 << 30 + } else if ctx_range.offset % (1 << 21) == 0 && glas_range.offset % (1 << 21) == 0 && glas_range.length % (1 << 21) == 0 { + 1 << 21 + } else { + 1 << 12 + }; + + placed[i] = true; + for i in 0..ctx_range.length / sz { + let nsz = (sz * i) as u64; + let src = glas_range.offset as u64 + nsz; + let dst = ctx_range.offset as u64 + nsz; + match sz { + 1073741824 => page_table.add_1g_mapping(src, dst), + 2097152 => page_table.add_2m_mapping(src, dst), + 4096 => page_table.add_4k_mapping(src, dst), + _ => unreachable!(), + } + } + + } + + page_table +} + #[derive(Debug)] pub struct FlattenResult { pub r: BTreeMap<usize, Vec<(Range, usize, Range)>>, @@ -521,8 +590,7 @@ fn test_fail_conflict() { dn.add_mapping(i, r1, 0, 0, 10).unwrap(); dn.add_mapping(i, r2, 10, 0, 10).unwrap(); - let required = BTreeSet::from_iter(vec![(c1, r1), (c1, r2), (c2, r1), (c2, r2)]); - let glas = derive_glas(&dn, &vec![c1, c2], &vec![r1, r2], &required).expect("can derive glas"); + let glas = derive_glas(&dn, &vec![c1, c2], &vec![r1, r2], &Vec::new()).expect("can derive glas"); _ = glas; } diff --git a/src/output/glas.rs b/src/output/glas.rs index 04d4519b88db3b9478ef2e95fd05d5623ac54f75..b0162731e719fe4e07d7edc3c3ce9769370fef97 100644 --- a/src/output/glas.rs +++ b/src/output/glas.rs @@ -15,7 +15,7 @@ pub fn json(file: &mut File, glas: &GLAS, dn: &DecodingNet, f: &FlattenResult, r let reslen = space.iter().filter(|(_,r,_)| resources.contains(r)).count(); for (idx, (context_range,r,resource_range)) in space.iter().filter(|(_,r,_)| resources.contains(r)).enumerate() { - let i = glas.placement.iter().position(|(_,_,c)| c == resource_range).unwrap(); + let i = glas.placement.iter().position(|(res,_,c)| r == res && c == resource_range).unwrap(); let (_,glas_range,_) = glas.placement[i]; write!(file, r#" {{ @@ -78,13 +78,15 @@ pub fn json(file: &mut File, glas: &GLAS, dn: &DecodingNet, f: &FlattenResult, r /// accepting components will be color-coded. The resulting file can be processed using the `dot` /// layout algorithm in the graphviz tools. pub fn visualize_dn(file: &mut File, dn: &DecodingNet) -> Result<(), std::io::Error> { - writeln!(file,"digraph {{")?; - writeln!(file," rankdir=\"LR\";")?; + writeln!(file, "digraph {{")?; + writeln!(file, " rankdir=\"LR\";")?; + writeln!(file, " ranksep=50;")?; + writeln!(file, " nodesep=1;")?; writeln!(file," overlap=false;")?; //writeln!(file," graph [splines=ortho];"); - writeln!(file," node [shape=record,style=filled,fontname = \"monospace\"];")?; - writeln!(file," label=\"The Whole Decoding Net\";")?; - writeln!(file," labelloc=t;")?; + writeln!(file, " node [shape=record,style=filled,fontname = \"monospace\"];")?; + writeln!(file, " label=\"The Whole Decoding Net\";")?; + writeln!(file, " labelloc=t;")?; for (id, _address_space) in dn.address_spaces.iter().enumerate() { for map in dn.address_spaces[id].values.iter() { @@ -120,13 +122,14 @@ pub fn visualize_dn(file: &mut File, dn: &DecodingNet) -> Result<(), std::io::Er } pub fn visualize_glas(file: &mut File, glas: &GLAS, dn: &DecodingNet) -> Result<(), std::io::Error> { - writeln!(file,"digraph {{")?; - writeln!(file," rankdir=\"LR\";")?; - writeln!(file," overlap=false;")?; + writeln!(file, "digraph {{")?; + writeln!(file, " rankdir=\"LR\";")?; + writeln!(file, " overlap=false;")?; + writeln!(file, " ranksep=10;")?; //writeln!(file," graph [splines=ortho];")?; - writeln!(file," node [shape=record,style=filled,fontname = \"monospace\"];")?; - writeln!(file," label=\"GLAS for this SoC\";")?; - writeln!(file," labelloc=t;")?; + writeln!(file, " node [shape=record,style=filled,fontname = \"monospace\"];")?; + writeln!(file, " label=\"GLAS for this SoC\";")?; + writeln!(file, " labelloc=t;")?; for (r,glas_range,res_range) in glas.placement.iter().rev() { writeln!(file, @@ -165,13 +168,14 @@ pub fn visualize_glas_for( c: usize, resources: &Vec<usize> ) -> Result<(), std::io::Error> { - writeln!(file,"digraph {{")?; - writeln!(file," rankdir=\"LR\";")?; - writeln!(file," overlap=false;")?; + writeln!(file, "digraph {{")?; + writeln!(file, " rankdir=\"LR\";")?; + writeln!(file, " ranksep=15;")?; + writeln!(file, " overlap=false;")?; //writeln!(file," graph [splines=ortho];")?; - writeln!(file," node [shape=record,style=filled,fontname = \"monospace\"];")?; - writeln!(file," label=\"GLAS for address space of core {}\";", dn.names[c])?; - writeln!(file," labelloc=t;")?; + writeln!(file, " node [shape=record,style=filled,fontname = \"monospace\"];")?; + writeln!(file, " label=\"GLAS for address space of core {}\";", dn.names[c])?; + writeln!(file, " labelloc=t;")?; writeln!(file,"subgraph cluster_glas {{")?; writeln!(file,"label = \"GLAS\";")?; @@ -201,16 +205,16 @@ pub fn visualize_glas_for( for (r,glas_range,res_range) in glas.placement.iter().rev() { writeln!(file, - " \"g_{}\" -> \"{}_{}\"", - glas_range.offset, + " \"{}_{}\" -> \"g_{}\"", r, res_range.offset, + glas_range.offset, //(length as f64).log2(), )?; } let space = &f.r[&c]; - for (context_range,_r,resource_range) in space.iter().filter(|(_,r,_)| resources.contains(r)) { - let i = glas.placement.iter().position(|(_,_,c)| c == resource_range).unwrap(); + for (context_range,r,resource_range) in space.iter().filter(|(_,r,_)| resources.contains(r)) { + let i = glas.placement.iter().position(|(res,_,c)| r == res && c == resource_range).unwrap(); let (_r,glas_range,_) = glas.placement[i]; let color = if context_range.offset == glas_range.offset { @@ -229,9 +233,9 @@ pub fn visualize_glas_for( )?; writeln!(file, - " \"c_{}\" -> \"g_{}\" [color=\"{}\"]", - context_range.offset, + " \"g_{}\" -> \"c_{}\" [color=\"{}\"]", glas_range.offset, + context_range.offset, color, //(length as f64).log2(), )?; diff --git a/src/range.rs b/src/range.rs index cd3d8cd50085f39e2d485ef95a898fce46fe62c2..aad87f53a06005965c3329d1280d3973559e1f1f 100644 --- a/src/range.rs +++ b/src/range.rs @@ -1,6 +1,8 @@ use std::cmp::Ordering; -#[derive(Clone, Copy, PartialEq, Debug)] +use serde::{Serialize, Deserialize}; + +#[derive(Clone, Copy, PartialEq, Debug, Hash, Serialize, Deserialize)] pub struct Range { pub offset: u128, pub length: u128, diff --git a/src/range_tree.rs b/src/range_tree.rs index 841efb991e03b316cdda4c290ea27aecea71bf10..461d2a7d0d1c61b653bdbff4b4da2acff08bb996 100644 --- a/src/range_tree.rs +++ b/src/range_tree.rs @@ -1,9 +1,11 @@ use crate::range::Range; +use serde::{Serialize,Deserialize}; + /// A range tree is an efficient representation of an address space as a list of ranges. Each range /// may be associated with an arbitrary value. -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RangeTree<V> { pub name: String, pub top_level: Range, diff --git a/src/spec.rs b/src/spec.rs index 77729ee062395d03ca9b7fac32bd295fa7b9ca13..c3716a0088fc252575387c68826d562cb40f1822 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -2,10 +2,9 @@ //! decoding nets. //! -use std::collections::{BTreeSet}; +use std::collections::BTreeSet; use std::fmt; - use crate::range::Range; use serde::Serialize; @@ -171,7 +170,11 @@ impl DecodingNet { for m in &self.mappings[src.as_usize()] { if m.src_range.overlaps(src_range) { - return Err(SpecError::AlreadyMapped(src, m.src_range, src_range)); + return Err(SpecError::AlreadyMapped( + src, + m.src_range, + src_range, + )); } } @@ -230,7 +233,10 @@ impl DecodingNet { if range <= address_space.range { Ok(()) } else { - Err(SpecError::RangeOutOfBounds(address_space.range, range)) + Err(SpecError::RangeOutOfBounds( + address_space.range, + range, + )) } } } @@ -270,6 +276,7 @@ pub enum SpecError { AddressSpaceDoesNotExist(String), } + #[test] fn construct_empty_net() { let _ = DecodingNet::new(); diff --git a/src/specs.rs b/src/specs.rs index 1497195208de07363e6daad0567eec6de585609a..b9f82de8f06abeba77e533ff3591f7e24b05c792 100644 --- a/src/specs.rs +++ b/src/specs.rs @@ -5,6 +5,7 @@ pub mod common; pub mod arm; pub mod imx8; +pub mod morello; pub mod ultrascaleplus; diff --git a/src/specs/arm/v8/mmu.rs b/src/specs/arm/v8/mmu.rs index 30e6383b34c2bb391bc49a3df4bd3e331cb072b3..c40881cfe4cf70f1a1f64487843eaf026cfefc94 100644 --- a/src/specs/arm/v8/mmu.rs +++ b/src/specs/arm/v8/mmu.rs @@ -339,6 +339,20 @@ impl TTBREntry { } } } + + pub fn materialize_into(&self, bytes: &mut [u64]) { + match &self { + Self::Invalid => (), + Self::TableDescriptor { + address: base_addr, + table: l0_table, + } => { + for (i, entry) in l0_table.iter().enumerate() { + entry.materialize_into(bytes, *base_addr as u64, i); + } + } + } + } } impl fmt::Debug for L0Entry { @@ -399,6 +413,24 @@ impl L0Entry { } } } + + /// Materialize this entry's configuration, returning a descriptor + fn materialize_into(&self, bytes: &mut [u64], base_addr: u64, idx: usize) { + bytes[idx] = match &self { + Self::Invalid => 0x0, + Self::TableDescriptor { + address, + table, + } => { + let entry_offset = (address - base_addr as u128) as usize / 8; + assert!(entry_offset % 512 == 0); + for (i, entry) in table.iter().enumerate() { + entry.materialize_into(bytes, base_addr, entry_offset + i); + } + (*address as u64 & !0xFFF) | 0b11 + }, + }; + } } impl fmt::Debug for L1Entry { @@ -477,6 +509,23 @@ impl L1Entry { Ok(()) } + + /// Materialize this entry's configuration, returning a descriptor + fn materialize_into(&self, bytes: &mut [u64], base_addr: u64, idx: usize) { + bytes[idx] = match &self { + Self::Invalid => 0x0, + Self::TableDescriptor { + address, + table, + } => { + for (i, entry) in table.iter().enumerate() { + entry.materialize_into(bytes, base_addr, (address - base_addr as u128) as usize / 8 + i); + } + (*address as u64 & !0xFFF) | 0b11 + }, + Self::BlockDescriptor(address) => (*address as u64 & !0xFFF) | 0x701, + }; + } } impl fmt::Debug for L2Entry { @@ -556,6 +605,23 @@ impl L2Entry { } Ok(()) } + + /// Materialize this entry's configuration, returning a descriptor + fn materialize_into(&self, bytes: &mut [u64], base_addr: u64, idx: usize) { + bytes[idx] = match &self { + Self::Invalid => 0x0, + Self::TableDescriptor { + address, + table, + } => { + for (i, entry) in table.iter().enumerate() { + entry.materialize_into(bytes, base_addr, (address - base_addr as u128) as usize / 8 + i); + } + (*address as u64 & !0xFFF) | 0b11 + }, + Self::BlockDescriptor(address) => (*address as u64 & !0xFFF) | 0x701, + }; + } } impl fmt::Debug for L3Entry { @@ -601,6 +667,20 @@ impl L3Entry { } } } + + /// Materialize this entry's configuration, returning a descriptor + fn materialize_into(&self, bytes: &mut [u64], _base_addr: u64, idx: usize) { + bytes[idx] = match &self { + Self::Invalid => 0x0, + Self::BlockDescriptor(address) => + // TODO: HACK: FIXME: this is awful. + if *address < 0x4000_0000 { + (*address as u64 & !0xFFF) | 0x707 + } else { + (*address as u64 & !0xFFF) | 0x701 + }, + }; + } } #[test] diff --git a/src/specs/common.rs b/src/specs/common.rs index fabbbcdafbe883c3c8e5e34b6a0aeeee7d92b819..0d10fedfc0da276a71799af17c8187c6a8ae39ed 100644 --- a/src/specs/common.rs +++ b/src/specs/common.rs @@ -1,9 +1,28 @@ #![allow(dead_code, unused_variables)] +use std::ops::Add; + pub type Offset = u128; pub type Size = u128; pub type Address = u128; +#[macro_export] +macro_rules! size { + ( $x:expr, KB) => { + $x * SIZE_1KB + }; + ( $x:expr, MB) => { + $x * SIZE_1MB + }; + ( $x:expr, GB) => { + $x * SIZE_1GB + }; + ( $x:expr, TB) => { + $x * SIZE_1TB + }; +} +pub(crate) use size; + /* Size variables to make code more readable. The i.MX 8X Reference Manual also talks about size, so this is more consistent j. *); @@ -31,6 +50,7 @@ pub const OFFSET_8KB: Offset = 2_u128.pow(13); pub const OFFSET_14GB: Offset = OFFSET_16GB - OFFSET_2GB; pub const OFFSET_96KB: Offset = 6 * OFFSET_16KB; +pub const SIZE_2TB: Size = 2_u128.pow(41); pub const SIZE_1TB: Size = 2_u128.pow(40); pub const SIZE_512GB: Size = 2_u128.pow(39); pub const SIZE_256GB: Size = 2_u128.pow(38); @@ -64,13 +84,26 @@ pub const SIZE_2KB: Size = 2_u128.pow(11); pub const SIZE_1KB: Size = 2_u128.pow(10); pub const SIZE_256B: Size = 2_u128.pow(8); // "Impure" sizes pub constructed from pure ones: +pub const SIZE_3TB: Size = SIZE_2TB + SIZE_1TB; +pub const SIZE_510GB: Size = SIZE_512GB - SIZE_2GB; pub const SIZE_448GB: Size = SIZE_512GB - SIZE_64GB; pub const SIZE_224GB: Size = SIZE_256GB - SIZE_32GB; pub const SIZE_28GB: Size = SIZE_32GB - SIZE_4GB; pub const SIZE_14GB: Size = SIZE_16GB - SIZE_2GB; pub const SIZE_12GB: Size = SIZE_16GB - SIZE_4GB; +pub const SIZE_192MB: Size = SIZE_128MB + SIZE_64MB; pub const SIZE_63MB: Size = SIZE_64MB - SIZE_1MB; pub const SIZE_12MB: Size = SIZE_16MB - SIZE_4MB; +pub const SIZE_10MB: Size = SIZE_12MB - SIZE_2MB; +pub const SIZE_768KB: Size = SIZE_512KB + SIZE_256KB; pub const SIZE_448KB: Size = SIZE_512KB - SIZE_64KB; pub const SIZE_96KB: Size = 6 * SIZE_16KB; pub const SIZE_80KB: Size = 5 * SIZE_16KB; + +pub struct MapInfo { + pub name: &'static str, + pub description: &'static str, + pub start: Option<Address>, + pub end: Option<Address>, + pub length: Option<Size>, +} diff --git a/src/specs/examples.rs b/src/specs/examples.rs index 7de0bc3e87ad0b6e2209366e98fc9535450b2bee..f2726b2b3653e23d6e6c8d7071f50af22bc452ab 100644 --- a/src/specs/examples.rs +++ b/src/specs/examples.rs @@ -1,4 +1,5 @@ pub mod imx8; +pub mod morello; pub mod mmu; pub mod non_transitive_trust; pub mod qemu_aarch64; diff --git a/src/specs/examples/imx8.rs b/src/specs/examples/imx8.rs index 7a5a20699231b948805c5ef8e935bc677aeade42..684c594ba74c4ce36f21e3059eb5da6a61ef0366 100644 --- a/src/specs/examples/imx8.rs +++ b/src/specs/examples/imx8.rs @@ -20,47 +20,47 @@ pub fn instantiate_imx8_example(with_random_xrdc: bool) -> Result<(DecodingNet, } xrdc.add_to_decoding_net(&mut dn)?; - let mut l3_table = Box::new(std::array::from_fn(|_| L3Entry::Invalid)); - let mut l2_table = Box::new(std::array::from_fn(|_| L2Entry::Invalid)); - let mut l1_table = Box::new(std::array::from_fn(|_| L1Entry::Invalid)); - let mut l0_table = Box::new(std::array::from_fn(|_| L0Entry::Invalid)); - l3_table[0] = L3Entry::BlockDescriptor(0xF00F_0000); - l2_table[0] = L2Entry::TableDescriptor { - address: 0x8000_3000, - table: l3_table, - }; - l1_table[0] = L1Entry::TableDescriptor { - address: 0x8000_2000, - table: l2_table, - }; - l0_table[0] = L0Entry::TableDescriptor { - address: 0x8000_1000, - table: l1_table, - }; - let ttbr_entry = TTBREntry::TableDescriptor { - address: 0x8000_0000, - table: l0_table, - }; + //let mut l3_table = Box::new(std::array::from_fn(|_| L3Entry::Invalid)); + //let mut l2_table = Box::new(std::array::from_fn(|_| L2Entry::Invalid)); + //let mut l1_table = Box::new(std::array::from_fn(|_| L1Entry::Invalid)); + //let mut l0_table = Box::new(std::array::from_fn(|_| L0Entry::Invalid)); + //l3_table[0] = L3Entry::BlockDescriptor(0xF00F_0000); + //l2_table[0] = L2Entry::TableDescriptor { + // address: 0x8000_3000, + // table: l3_table, + //}; + //l1_table[0] = L1Entry::TableDescriptor { + // address: 0x8000_2000, + // table: l2_table, + //}; + //l0_table[0] = L0Entry::TableDescriptor { + // address: 0x8000_1000, + // table: l1_table, + //}; + //let ttbr_entry = TTBREntry::TableDescriptor { + // address: 0x8000_0000, + // table: l0_table, + //}; - let mmus = imx8.get_a35_mmus(); - let simple_cfg = Configuration::OneStage(ttbr_entry); - let vas0 = mmus[0] - .create_virtual_address_space( - &mut dn, - &simple_cfg, - "MMU_DB_A35_0", - "Victim address space for analysis", - ) - .expect("mmu configuraiton failed"); + //let mmus = imx8.get_a35_mmus(); + //let simple_cfg = Configuration::OneStage(ttbr_entry); + //let vas0 = mmus[0] + // .create_virtual_address_space( + // &mut dn, + // &simple_cfg, + // "MMU_DB_A35_0", + // "Victim address space for analysis", + // ) + // .expect("mmu configuraiton failed"); - let disabled_cfg = Configuration::Disabled; - let vas1 = mmus[1].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_1", "")?; - let vas2 = mmus[2].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_2", "")?; - let vas3 = mmus[3].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_3", "")?; - dn.mark_context(vas0, ""); - dn.mark_context(vas1, ""); - dn.mark_context(vas2, ""); - dn.mark_context(vas3, ""); + //let disabled_cfg = Configuration::Disabled; + //let vas1 = mmus[1].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_1", "")?; + //let vas2 = mmus[2].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_2", "")?; + //let vas3 = mmus[3].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_3", "")?; + //dn.mark_context(vas0, ""); + //dn.mark_context(vas1, ""); + //dn.mark_context(vas2, ""); + //dn.mark_context(vas3, ""); Ok((dn, imx8)) } diff --git a/src/specs/examples/mmu.rs b/src/specs/examples/mmu.rs index e02dd56280b32ca91fa1bf56cd84771efaac7554..e1bacfefb0816a392a3ed8aac4645d1b32622135 100644 --- a/src/specs/examples/mmu.rs +++ b/src/specs/examples/mmu.rs @@ -1,17 +1,15 @@ -#![cfg(test)] - use crate::analysis::{self, Assumptions, BehaviorAssumption, Model, StableAssumptions}; use crate::analysis::{LocalAddressRange, QualifiedAddressRange, ASID}; use crate::spec::DecodingNet; use crate::specs::arm::v8::mmu::{self, *}; -struct PageTable { - base_table: TTBREntry, - page_tracker: PageTracker, +pub struct PageTable { + pub base_table: TTBREntry, + pub page_tracker: PageTracker, } -struct PageTracker { - used_pages: usize, +pub struct PageTracker { + pub used_pages: usize, base_addr: u128, } @@ -24,7 +22,7 @@ impl PageTracker { } impl PageTable { - fn new(base_addr: u128) -> PageTable { + pub fn new(base_addr: u128) -> PageTable { Self { base_table: TTBREntry::TableDescriptor { address: base_addr, @@ -37,6 +35,92 @@ impl PageTable { } } + pub fn add_1g_mapping(&mut self, input_address: u64, output_address: u64) { + assert!(input_address % (1 << 30) == 0); + assert!(output_address % (1 << 30) == 0); + + let bt = &mut self.base_table; + let pt = &mut self.page_tracker; + + let l0_entry = bt.index_table(input_address).unwrap(); + match l0_entry { + L0Entry::Invalid => { + *l0_entry = L0Entry::TableDescriptor { + address: pt.next_page(), + table: Box::new(std::array::from_fn(|_| L1Entry::Invalid)), + } + } + L0Entry::TableDescriptor { .. } => (), + } + + let l1_entry = l0_entry.index_table(input_address).unwrap(); + match l1_entry { + L1Entry::Invalid => *l1_entry = L1Entry::BlockDescriptor(output_address), + L1Entry::TableDescriptor { .. } => unimplemented!( + "conflicting mapping at L1 table! requested={:#x} actual=table descriptor", + output_address, + ), + L1Entry::BlockDescriptor(addr) => unimplemented!( + "conflicting output addresses! requested={:#x} actual={:#x}", + output_address, + addr + ), + }; + } + + + pub fn add_2m_mapping(&mut self, input_address: u64, output_address: u64) { + assert!(input_address % (1 << 21) == 0); + assert!(output_address % (1 << 21) == 0); + + let bt = &mut self.base_table; + let pt = &mut self.page_tracker; + + let l0_entry = bt.index_table(input_address).unwrap(); + match l0_entry { + L0Entry::Invalid => { + *l0_entry = L0Entry::TableDescriptor { + address: pt.next_page(), + table: Box::new(std::array::from_fn(|_| L1Entry::Invalid)), + } + } + L0Entry::TableDescriptor { .. } => (), + } + + let l1_entry = l0_entry.index_table(input_address).unwrap(); + match l1_entry { + L1Entry::Invalid => { + *l1_entry = L1Entry::TableDescriptor { + address: pt.next_page(), + table: Box::new(std::array::from_fn(|_| L2Entry::Invalid)), + } + } + L1Entry::TableDescriptor { .. } => (), + L1Entry::BlockDescriptor { .. } => unimplemented!(), + }; + + let l2_entry = l1_entry.index_table(input_address).unwrap(); + match l2_entry { + L2Entry::Invalid => *l2_entry = L2Entry::BlockDescriptor(output_address), + L2Entry::TableDescriptor { .. } => unimplemented!( + "conflicting mapping at L2 table! requested={:#x} actual=table descriptor", + output_address, + ), + L2Entry::BlockDescriptor(addr) => unimplemented!( + "conflicting output addresses! requested={:#x} actual={:#x}", + output_address, + addr + ), + }; + } + + pub fn add_4k_mapping(&mut self, input_address: u64, output_address: u64) { + assert!(input_address % (1 << 12) == 0); + assert!(output_address % (1 << 12) == 0); + + self.add_single_mapping(input_address, output_address); + } + fn add_single_mapping(&mut self, input_address: u64, output_address: u64) { let bt = &mut self.base_table; let pt = &mut self.page_tracker; diff --git a/src/specs/examples/morello.rs b/src/specs/examples/morello.rs new file mode 100644 index 0000000000000000000000000000000000000000..d2511f7903d8b0bd2def4d476414dfedf2bfba4a --- /dev/null +++ b/src/specs/examples/morello.rs @@ -0,0 +1,59 @@ +use rand::Rng; + +use crate::spec::{DecodingNet, SpecError}; +use crate::specs::arm::v8::mmu::{Configuration, L0Entry, L1Entry, L2Entry, L3Entry, TTBREntry}; +use crate::specs::morello; + +pub fn instantiate_morello_example() -> Result<(DecodingNet, morello::Morello), SpecError> { + let mut dn = DecodingNet::new(); + let mut morello = morello::Morello::new(&mut dn)?; + + //let mut l3_table = Box::new(std::array::from_fn(|_| L3Entry::Invalid)); + //let mut l2_table = Box::new(std::array::from_fn(|_| L2Entry::Invalid)); + //let mut l1_table = Box::new(std::array::from_fn(|_| L1Entry::Invalid)); + //let mut l0_table = Box::new(std::array::from_fn(|_| L0Entry::Invalid)); + //l3_table[0] = L3Entry::BlockDescriptor(0xF00F_0000); + //l2_table[0] = L2Entry::TableDescriptor { + // address: 0x8000_3000, + // table: l3_table, + //}; + //l1_table[0] = L1Entry::TableDescriptor { + // address: 0x8000_2000, + // table: l2_table, + //}; + //l0_table[0] = L0Entry::TableDescriptor { + // address: 0x8000_1000, + // table: l1_table, + //}; + //let ttbr_entry = TTBREntry::TableDescriptor { + // address: 0x8000_0000, + // table: l0_table, + //}; + + //let mmus = morello.get_a35_mmus(); + //let simple_cfg = Configuration::OneStage(ttbr_entry); + //let vas0 = mmus[0] + // .create_virtual_address_space( + // &mut dn, + // &simple_cfg, + // "MMU_DB_A35_0", + // "Victim address space for analysis", + // ) + // .expect("mmu configuraiton failed"); + + //let disabled_cfg = Configuration::Disabled; + //let vas1 = mmus[1].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_1", "")?; + //let vas2 = mmus[2].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_2", "")?; + //let vas3 = mmus[3].create_virtual_address_space(&mut dn, &disabled_cfg, "MMU_DB_A35_3", "")?; + //dn.mark_context(vas0, ""); + //dn.mark_context(vas1, ""); + //dn.mark_context(vas2, ""); + //dn.mark_context(vas3, ""); + + Ok((dn, morello)) +} + +#[test] +fn test() { + instantiate_morello_example().expect("could not create morello example"); +} diff --git a/src/specs/examples/qemu_aarch64.rs b/src/specs/examples/qemu_aarch64.rs index 6aac5e1a434184feb711ede263fd4f369b042748..7fc36ea0f9c5eab90cfcd0cb97f85bc199244968 100644 --- a/src/specs/examples/qemu_aarch64.rs +++ b/src/specs/examples/qemu_aarch64.rs @@ -3,9 +3,9 @@ use crate::spec::SpecError; pub fn create_dn() -> Result<spec::DecodingNet, SpecError> { let mut dn = spec::DecodingNet::new(); - let c0 = dn.add_address_space("cpu core 0", "", 0, 1 << 36)?; - let c1 = dn.add_address_space("cpu core 1", "", 0, 1 << 36)?; - let c2 = dn.add_address_space("cpu core 2", "", 0, 1 << 36)?; + let c0 = dn.add_address_space("cpu_core_0", "", 0, 1 << 36)?; + let c1 = dn.add_address_space("cpu_core_1", "", 0, 1 << 36)?; + let c2 = dn.add_address_space("cpu_core_2", "", 0, 1 << 36)?; let r = dn.add_address_space("ram", "", 0, 3 * (1 << 30))?; let uart = dn.add_address_space("uart0", "", 0, 1 << 12)?; diff --git a/src/specs/imx8.rs b/src/specs/imx8.rs index 971e88a9c9ba9481c4198a7b4580dd0084543515..e85d85cf712241cffdf5c9bd8bad468958d2f6b2 100644 --- a/src/specs/imx8.rs +++ b/src/specs/imx8.rs @@ -3,7 +3,7 @@ use crate::spec::{ASID}; use crate::spec::{DecodingNet, SpecError}; -use crate::specs::arm::v8::mmu::MMU; +//use crate::specs::arm::v8::mmu::MMU; use crate::specs::common::*; use self::xrdc2::XRDC2; @@ -37,10 +37,10 @@ pub struct Imx8 { cortex_a35_2: ASID, cortex_a35_3: ASID, - cortex_a35_0_mmu: MMU, - cortex_a35_1_mmu: MMU, - cortex_a35_2_mmu: MMU, - cortex_a35_3_mmu: MMU, + //cortex_a35_0_mmu: MMU, + //cortex_a35_1_mmu: MMU, + //cortex_a35_2_mmu: MMU, + //cortex_a35_3_mmu: MMU, cortex_m4: ASID, system_control_unit: ASID, @@ -581,10 +581,10 @@ impl Imx8 { cortex_a35_2: a35_2_interconnect_view, cortex_a35_3: a35_3_interconnect_view, - cortex_a35_0_mmu: MMU::new(a35_0_interconnect_view, a35_0_interconnect_view), - cortex_a35_1_mmu: MMU::new(a35_1_interconnect_view, a35_1_interconnect_view), - cortex_a35_2_mmu: MMU::new(a35_2_interconnect_view, a35_2_interconnect_view), - cortex_a35_3_mmu: MMU::new(a35_3_interconnect_view, a35_3_interconnect_view), + //cortex_a35_0_mmu: MMU::new(a35_0_interconnect_view, a35_0_interconnect_view), + //cortex_a35_1_mmu: MMU::new(a35_1_interconnect_view, a35_1_interconnect_view), + //cortex_a35_2_mmu: MMU::new(a35_2_interconnect_view, a35_2_interconnect_view), + //cortex_a35_3_mmu: MMU::new(a35_3_interconnect_view, a35_3_interconnect_view), cortex_m4: m4_interconnect_view, system_control_unit: sc_interconnect_view, @@ -659,14 +659,14 @@ impl Imx8 { self.enet2 } - pub fn get_a35_mmus(&self) -> [&MMU; 4] { - [ - &self.cortex_a35_0_mmu, - &self.cortex_a35_1_mmu, - &self.cortex_a35_2_mmu, - &self.cortex_a35_3_mmu, - ] - } + //pub fn get_a35_mmus(&self) -> [&MMU; 4] { + // [ + // &self.cortex_a35_0_mmu, + // &self.cortex_a35_1_mmu, + // &self.cortex_a35_2_mmu, + // &self.cortex_a35_3_mmu, + // ] + //} /// Return the address space corresponding to the Cortex-M4 user core. pub fn get_m4(&self) -> ASID { diff --git a/src/specs/imx8/audio_dma/hifi4_dsp.rs b/src/specs/imx8/audio_dma/hifi4_dsp.rs index adb716d6de264a0d738ab1f040c8bff20b4a59da..18f5e092ec40900d911d96112a8f5c9ed438e2b8 100644 --- a/src/specs/imx8/audio_dma/hifi4_dsp.rs +++ b/src/specs/imx8/audio_dma/hifi4_dsp.rs @@ -41,19 +41,19 @@ impl HiFi4Dsp { )?; let dsp_iram0_asid = dn.add_address_space( "DSP_INSTRUCTION_RAM_0", - "DSP instruction RAM, as per IMX8DQXPRM @ p. 8078, Table 16-140.", + "DSP instruction RAM, as per IMX8DQXPRM @ p. 8078, Table 16-140.\nWe have no idea where this is mapped.", 0, SIZE_2KB, )?; let dsp_dram0_asid = dn.add_address_space( "DSP_DATA_RAM_0", - "DSP data RAM 0, as per IMX8DQXPRM @ p. 8078, Table 16-140.", + "DSP data RAM 0, as per IMX8DQXPRM @ p. 8078, Table 16-140.\nWe have no idea where this is mapped.", 0, SIZE_32KB, )?; let dsp_dram1_asid = dn.add_address_space( "DSP_DATA_RAM_1", - "DSP data RAM 1, as per IMX8DQXPRM @ p. 8078, Table 16-140.", + "DSP data RAM 1, as per IMX8DQXPRM @ p. 8078, Table 16-140.\nWe have no idea where this is mapped.", 0, SIZE_32KB, )?; diff --git a/src/specs/imx8/cm4.rs b/src/specs/imx8/cm4.rs index 0396009cf51e92793c8a1d8ee0e077f78b07b787..91f0564961d9010f0c45689ab4bb70707dd85536 100644 --- a/src/specs/imx8/cm4.rs +++ b/src/specs/imx8/cm4.rs @@ -144,6 +144,7 @@ impl CortexM4 { 0, 7 * SIZE_64KB, )?; + dn.mark_resource(cm4_lpcg, "")?; // Todo: Move MU to MU model let cm4_mu1_a = dn.add_address_space( @@ -152,36 +153,42 @@ impl CortexM4 { 0, SIZE_64KB, )?; + dn.mark_resource(cm4_mu1_a, "")?; let cm4_mu0_a3 = dn.add_address_space( &format!("{} MU0_A3", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_mu0_a3, "")?; let cm4_mu0_a2 = dn.add_address_space( &format!("{} MU0_A2", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_mu0_a2, "")?; let cm4_mu0_a1 = dn.add_address_space( &format!("{} MU0_A1", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_mu0_a1, "")?; let cm4_mu0_a0 = dn.add_address_space( &format!("{} MU0_A0", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_mu0_a0, "")?; let cm4_mu0_b = dn.add_address_space( &format!("{} MU0_B", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_mu0_b, "")?; let cm4_wdog = dn.add_address_space( &format!("{} WDOG", name), @@ -189,18 +196,21 @@ impl CortexM4 { 0, SIZE_64KB, )?; + dn.mark_resource(cm4_wdog, "")?; let cm4_asmc = dn.add_address_space( &format!("{} ASMC", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_asmc, "")?; let cm4_intmux = dn.add_address_space( &format!("{} INTMUX", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_intmux, "")?; let cm4_lpi2c = dn.add_address_space( &format!("{} LPI2C", name), @@ -208,24 +218,28 @@ impl CortexM4 { 0, SIZE_64KB, )?; + dn.mark_resource(cm4_lpi2c, "")?; let cm4_lpuart = dn.add_address_space( &format!("{} LPUART", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_lpuart, "")?; let cm4_lpit = dn.add_address_space( &format!("{} LPIT", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_lpit, "")?; let cm4_tpm = dn.add_address_space( &format!("{} TPM", name), "as per IMX8DQXPRM @ p. 49", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_tpm, "")?; let cm4_sema42 = dn.add_address_space( &format!("{} SEMA42", name), @@ -233,6 +247,7 @@ impl CortexM4 { 0, SIZE_64KB, )?; + dn.mark_resource(cm4_sema42, "")?; let cm4_debug = dn.add_address_space( &format!("{} Debug Block", name), @@ -240,6 +255,7 @@ impl CortexM4 { 0, SIZE_12MB, )?; + dn.mark_resource(cm4_debug, "")?; let cm4_syscnt_cmp = dn.add_address_space( &format!("{} SYSCNT CMP", name), @@ -247,18 +263,21 @@ impl CortexM4 { 0, SIZE_64KB, )?; + dn.mark_resource(cm4_syscnt_cmp, "")?; let cm4_syscnt_rd = dn.add_address_space( &format!("{} SYSCNT RD", name), "as per IMX8DQXPRM @ p. 45", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_syscnt_rd, "")?; let cm4_syscnt_ctrl = dn.add_address_space( &format!("{} SYSCNT CTRL", name), "as per IMX8DQXPRM @ p. 45", 0, SIZE_64KB, )?; + dn.mark_resource(cm4_syscnt_ctrl, "")?; /* CM4 Local View */ xrdc.add_mapping( diff --git a/src/specs/morello.rs b/src/specs/morello.rs new file mode 100644 index 0000000000000000000000000000000000000000..9b6d48b0d9fcb2413631228b741b97086123e1c2 --- /dev/null +++ b/src/specs/morello.rs @@ -0,0 +1,544 @@ +use std::collections::HashMap; + +use crate::spec::ASID; +use crate::spec::{DecodingNet, SpecError}; + +use crate::specs::common::*; + +use super::imx8::xrdc2::ProspectivePeripheral; + +mod sdp_ap_map; +mod sdp_ap_sub_iofpga_map; +mod sdp_ap_sub_peripherals_map; +mod sdp_mcp_map; +mod sdp_mcp_sub_peripherals_map; +mod sdp_mcp_sub_peripherals_scp2_mhu_map; +mod sdp_scp_map; +mod sdp_scp_sub_peripherals_map; + +pub struct Morello {} + +fn add_sub_as_addr( + dn: &mut DecodingNet, + parent: ASID, + parent_offset: Address, + name: &str, + description: &str, + start: Address, + end: Address, +) -> Result<ASID, SpecError> { + add_sub_as_len( + dn, + parent, + parent_offset, + name, + description, + start, + end - start, + ) +} +fn add_sub_as_len( + dn: &mut DecodingNet, + parent: ASID, + parent_offset: Address, + name: &str, + description: &str, + start: Address, + length: Size, +) -> Result<ASID, SpecError> { + let parent_name = dn.address_spaces[parent.as_usize()].name.clone(); + let child = dn.add_address_space( + &(parent_name.clone() + "/" + name), + description, + 0x0, + length, + )?; + let end = start + length; + println!( + "Adding {:?}, start: {:#x?}, end: {:#x?}, end-start: {:#x?}, length: {:#x?}", + name, + start, + end, + end - start, + length + ); + dn.add_mapping(parent, child, start - parent_offset, 0x0, length, "")?; + + return Ok(child); +} + +fn add_sub_as_both( + dn: &mut DecodingNet, + parent: ASID, + parent_offset: Address, + name: &str, + description: &str, + start: Address, + end: Address, + length: Size, +) -> Result<ASID, SpecError> { + assert!(end - start == length); + add_sub_as_len(dn, parent, parent_offset, name, description, start, length) +} + +fn add_from_mapinfo( + dn: &mut DecodingNet, + parent: ASID, + parent_offset: Address, + mapinfos: &[MapInfo], +) -> Result<HashMap<String, (ASID, Address)>, SpecError> { + let mut result = HashMap::new(); + + for mapinfo in mapinfos { + let asid; + + match (mapinfo.start, mapinfo.end, mapinfo.length) { + (Some(start), Some(end), Some(length)) => { + asid = add_sub_as_both( + dn, + parent, + parent_offset, + mapinfo.name, + &mapinfo.description, + start, + end, + length, + )?; + } + + (Some(start), Some(end), None) => { + asid = add_sub_as_addr( + dn, + parent, + parent_offset, + mapinfo.name, + &mapinfo.description, + start, + end, + )?; + } + + (Some(start), None, Some(length)) => { + asid = add_sub_as_len( + dn, + parent, + parent_offset, + mapinfo.name, + &mapinfo.description, + start, + length, + )?; + } + + _ => { + unimplemented!(""); + } + } + + if result.contains_key(&mapinfo.name.to_string()) { + return Err(SpecError::AddressSpaceAlreadyExists(format!("Child with key {:?} already exists for {:?}", mapinfo.name, dn.address_spaces[parent.as_usize()].name))); + + } + result.insert(mapinfo.name.to_string(), (asid, mapinfo.start.unwrap())); + } + + return Ok(result); +} + +fn child_mark_resource( + dn: &mut DecodingNet, + children: &HashMap<String, (ASID, Address)>, + name: &str, + description: &str, +) -> Result<(), SpecError> { + dn.mark_resource(children.get(name).unwrap().0, description) +} + +fn child_mark_all_resource_except( + dn: &mut DecodingNet, + children: &HashMap<String, (ASID, Address)>, + names: &[&str], + description: &str, +) -> Result<(), SpecError> { + for (name, (asid, _)) in children.iter() { + if !names.contains(&name.as_str()) { + dn.mark_resource(*asid, description)?; + } + } + Ok(()) +} + +#[must_use] +fn coalesce_equivalent_as_into_resource( + dn: &mut DecodingNet, + target_name: &str, + equivalent_names: &[(&str, Address)], +) -> Result<ASID, SpecError> { + println!("Adding coalesced resource {}", target_name); + + let mut equivalent_asids = Vec::new(); + for (idx, (name, offset)) in equivalent_names.iter().enumerate() { + equivalent_asids.push((dn.get_address_space_by_name(name).unwrap(), offset)); + } + if equivalent_asids.is_empty() { + return Err(SpecError::AddressSpaceDoesNotExist("".to_string())); + } + + let normative_range = dn.address_spaces[equivalent_asids.get(0).unwrap().0.as_usize()].range; + let mut target_length = 0; + for (asid, &offset) in &equivalent_asids { + target_length = offset + dn.address_spaces[asid.as_usize()].range.length; + } + + let target_asid = dn.add_address_space( + &("resource_".to_owned() + target_name), + "", + 0x0, + target_length, + )?; + dn.mark_resource(target_asid, "")?; + for (asid, &offset) in &equivalent_asids { + dn.add_mapping( + *asid, + target_asid, + 0x0, + offset, + dn.address_spaces[asid.as_usize()].range.length, + "", + )?; + } + + return Ok(target_asid); +} + +impl Morello { + pub fn new(dn: &mut DecodingNet) -> Result<Morello, SpecError> { + let document_name = "ARM TRM 102278_0001_04_en, Issue 04"; + + let mcp_debug_address_translation: bool = false; + let scp_debug_address_translation: bool = false; + + let ap_memory_map = dn.add_address_space("ap_memory_map", "", 0x0, 0x4000_0000_0000)?; + let ap_children = add_from_mapinfo(dn, ap_memory_map, 0x0, self::sdp_ap_map::MAPINFOS)?; + + let ap_core0 = dn.add_address_space("ap_core0", "", 0x0, 0x4000_0000_0000)?; + let ap_core1 = dn.add_address_space("ap_core1", "", 0x0, 0x4000_0000_0000)?; + let ap_core2 = dn.add_address_space("ap_core2", "", 0x0, 0x4000_0000_0000)?; + let ap_core3 = dn.add_address_space("ap_core3", "", 0x0, 0x4000_0000_0000)?; + //dn.mark_context(ap_core0, ""); + //dn.mark_context(ap_core1, ""); + //dn.mark_context(ap_core2, ""); + //dn.mark_context(ap_core3, ""); + dn.mark_context(ap_memory_map, "HACK: mark memory map as context since it has the same view.\nIt takes too long (>3h) when the ap_cores are contexts too"); + + dn.add_mapping(ap_core0, ap_memory_map, 0x0, 0x0, 0x4000_0000_0000, "")?; + dn.add_mapping(ap_core1, ap_memory_map, 0x0, 0x0, 0x4000_0000_0000, "")?; + dn.add_mapping(ap_core2, ap_memory_map, 0x0, 0x0, 0x4000_0000_0000, "")?; + dn.add_mapping(ap_core3, ap_memory_map, 0x0, 0x0, 0x4000_0000_0000, "")?; + + let gbe_controller = dn.add_address_space("GbE_controller", "RealTek RTL8111GS", 0x0, 0x4000_0000_0000)?; + let sata_controller = dn.add_address_space("sata_controller", "Marvell 88SE9170 SATA 3.0", 0x0, 0x4000_0000_0000)?; + let usb_controller = dn.add_address_space("usb_3.0_host_controller", "Texas Instruments TUSB7340IRKMT", 0x0, 0x4000_0000_0000)?; + let pcie_memory_map = dn.add_address_space("pcie_memory_map", "", 0x0, 0x4000_0000_0000)?; + + dn.add_mapping(gbe_controller, pcie_memory_map, 0x0, 0x0, 0x4000_0000_0000, "")?; + dn.add_mapping(usb_controller, pcie_memory_map, 0x0, 0x0, 0x4000_0000_0000, "")?; + dn.add_mapping(sata_controller, pcie_memory_map, 0x0, 0x0, 0x4000_0000_0000, "")?; + + dn.mark_context(pcie_memory_map, "HACK: mark pcie as context instead of subsystems to decrease derivation time."); + + let smmu = dn.add_address_space("smmu", "", 0x0, 0x4000_0000_0000)?; + dn.add_mapping(pcie_memory_map, smmu, 0, 0, 0x4000_0000_0000, "")?; + + dn.add_mapping(smmu, ap_memory_map, 0, 0, 0x4000_0000_0000, "")?; + + child_mark_all_resource_except( + dn, + &ap_children, + &["iofpga_map_window", "subsystem_peripherals" ,"dram0","dram1", "dram2"], + "" + )?; + + let (ap_subsystem_iofpga_asid, ap_subsystem_iofpga_offset) = + ap_children.get("iofpga_map_window").unwrap(); + let ap_subsystem_iofpga_children = add_from_mapinfo( + dn, + *ap_subsystem_iofpga_asid, + *ap_subsystem_iofpga_offset, + self::sdp_ap_sub_iofpga_map::MAPINFOS, + )?; + + //child_mark_resource(dn, &ap_subsystem_iofpga_children, "ddr3", "")?; + //child_mark_resource( + // dn, + // &ap_subsystem_iofpga_children, + // "scp_backup_boot_memory", + // "", + //)?; + //child_mark_resource( + // dn, + // &ap_subsystem_iofpga_children, + // "mcp_backup_boot_memory", + // "", + //)?; + //child_mark_resource(dn, &ap_subsystem_iofpga_children, "system_registers", "")?; + //child_mark_resource(dn, &ap_subsystem_iofpga_children, "sram", "")?; + + child_mark_all_resource_except(dn, &ap_subsystem_iofpga_children, &[], "")?; + + let (ap_subsystem_peripherals_asid, ap_subsystem_peripherals_offset) = + ap_children.get("subsystem_peripherals").unwrap(); + let ap_subsystem_peripherals_children = add_from_mapinfo( + dn, + *ap_subsystem_peripherals_asid, + *ap_subsystem_peripherals_offset, + self::sdp_ap_sub_peripherals_map::MAPINFOS, + )?; + + //child_mark_resource(dn, &ap_subsystem_peripherals_children, "memory_element", "")?; + child_mark_all_resource_except( + dn, + &ap_subsystem_peripherals_children, + &[ + "ap2mcp_mhu_non_secure_ram", + "ap2mcp_mhu_secure_ram", + "scp_mhu_non_secure_ram", + "scp_mhu_secure_ram", + ], + "", + )?; + + let mcp_memory_map = dn.add_address_space("mcp_memory_map", "", 0x0, 0x01_0000_0000)?; + dn.mark_context(mcp_memory_map, ""); + let mcp_children = add_from_mapinfo(dn, mcp_memory_map, 0x0, self::sdp_mcp_map::MAPINFOS)?; + + child_mark_all_resource_except( + dn, + &mcp_children, + &[ + "mcp_peripherals", + "scp2_mhu", + "system_access_port_translated_to_0x0_4000_0000_to_0x0_7fff_ffff_of_ap_memory_map", + "system_access_port_translated_to_0x0_0000_0000_to_0x0_3fff_ffff_of_ap_memory_map_with_debug_address_translation_not_enabled_translated_to_0x4_0000_0000_to_0x4_3fff_ffff_of_ap_memory_map_with_debug_address_translation_enabled", + ], + "", + )?; + + //child_mark_resource(dn, &mcp_children, "code_boot_rom", "")?; + //child_mark_resource(dn, &mcp_children, "code_tcram", "")?; + //child_mark_resource(dn, &mcp_children, "sram_dtcram", "")?; + + let (mcp_periperals_asid, mcp_peripherals_offset) = + mcp_children.get("mcp_peripherals").unwrap(); + let mcp_peripherals_children = add_from_mapinfo( + dn, + *mcp_periperals_asid, + *mcp_peripherals_offset, + self::sdp_mcp_sub_peripherals_map::MAPINFOS, + )?; + child_mark_all_resource_except( + dn, + &mcp_peripherals_children, + &["ap2_mcp_mhu_non_secure_ram", "ap2_mcp_mhu_secure_ram"], + "", + )?; + + let (mcp_periperals_asid, mcp_peripherals_scp2_mhu_offset) = + mcp_children.get("scp2_mhu").unwrap(); + let mcp_peripherals_scp2_mhu_children = add_from_mapinfo( + dn, + *mcp_periperals_asid, + *mcp_peripherals_scp2_mhu_offset, + self::sdp_mcp_sub_peripherals_scp2_mhu_map::MAPINFOS, + )?; + child_mark_all_resource_except(dn, &mcp_peripherals_scp2_mhu_children, &[], "")?; + + let (mcp_sap1_asid, mcp_sap1_offset) = mcp_children + .get("system_access_port_translated_to_0x0_4000_0000_to_0x0_7fff_ffff_of_ap_memory_map") + .unwrap(); + dn.add_mapping(*mcp_sap1_asid, ap_memory_map, 0x0, 0x0, SIZE_1GB, "")?; + + let (mcp_sap2_asid, mcp_sap2_offset) = mcp_children.get("system_access_port_translated_to_0x0_0000_0000_to_0x0_3fff_ffff_of_ap_memory_map_with_debug_address_translation_not_enabled_translated_to_0x4_0000_0000_to_0x4_3fff_ffff_of_ap_memory_map_with_debug_address_translation_enabled").unwrap(); + let mcp_sap2_offset: Address; + if mcp_debug_address_translation { + mcp_sap2_offset = 0x4_0000_0000; + } else { + mcp_sap2_offset = 0x0; + } + dn.add_mapping( + *mcp_sap2_asid, + ap_memory_map, + 0x0, + mcp_sap2_offset, + SIZE_1GB, + "", + )?; + + let scp_memory_map = dn.add_address_space("scp_memory_map", "", 0x0, 0x01_0000_0000)?; + dn.mark_context(scp_memory_map, ""); + let scp_children = add_from_mapinfo(dn, scp_memory_map, 0x0, self::sdp_scp_map::MAPINFOS)?; + + //child_mark_resource(dn, &scp_children, "code_boot_rom", "")?; + //child_mark_resource(dn, &scp_children, "code_tcram", "")?; + //child_mark_resource(dn, &scp_children, "sram_dtcram", "")?; + + child_mark_all_resource_except( + dn, + &scp_children, + &[ + "scp_peripherals", + "system_access_port_translated_to_0x0_4000_0000_to_0x0_7fff_ffff_of_ap_memory_map", + "system_access_port_translated_to_0x0_0000_0000_to_0x0_3fff_ffff_of_ap_memory_map_with_debug_address_translation_not_enabled_translated_to_0x4_0000_0000_to_0x4_3fff_ffff_of_ap_memory_map_with_debug_address_translation_enabled", + ], + "", + )?; + + let (scp_periperals_asid, scp_peripherals_offset) = + scp_children.get("scp_peripherals").unwrap(); + let scp_peripherals_children = add_from_mapinfo( + dn, + *scp_periperals_asid, + *scp_peripherals_offset, + self::sdp_scp_sub_peripherals_map::MAPINFOS, + )?; + child_mark_all_resource_except( + dn, + &scp_peripherals_children, + &[ + "scp2_mcp_mhu_non_secura_ram", + "scp2_mcp_mhu_secure_ram", + "ap2scp_mhu_non_secure_ram", + "ap2scp_mhu_secure_ram", + ], + "", + )?; + + let (scp_sap1_asid, scp_sap1_offset) = scp_children + .get("system_access_port_translated_to_0x0_4000_0000_to_0x0_7fff_ffff_of_ap_memory_map") + .unwrap(); + dn.add_mapping(*scp_sap1_asid, ap_memory_map, 0x0, 0x0, SIZE_1GB, "")?; + + let (scp_sap2_asid, scp_sap2_offset) = scp_children.get("system_access_port_translated_to_0x0_0000_0000_to_0x0_3fff_ffff_of_ap_memory_map_with_debug_address_translation_not_enabled_translated_to_0x4_0000_0000_to_0x4_3fff_ffff_of_ap_memory_map_with_debug_address_translation_enabled").unwrap(); + let scp_sap2_offset: Address; + if scp_debug_address_translation { + scp_sap2_offset = 0x4_0000_0000; + } else { + scp_sap2_offset = 0x0; + } + dn.add_mapping( + *scp_sap2_asid, + ap_memory_map, + 0x0, + scp_sap2_offset, + SIZE_1GB, + "", + )?; + + let gpu_memory_map = dn.add_address_space("gpu_memory_map", "", 0x0, 0x4000_0000_0000)?; + dn.mark_context(gpu_memory_map, ""); + dn.add_mapping( + gpu_memory_map, + ap_memory_map, + 0x0, + 0x0, + 0x3FFF_FFFF_FFFF, + "", + )?; + let dpu_memory_map = dn.add_address_space("dpu_memory_map", "", 0x0, 0x4000_0000_0000)?; + dn.mark_context(dpu_memory_map, ""); + dn.add_mapping( + dpu_memory_map, + ap_memory_map, + 0x0, + 0x0, + 0x3FFF_FFFF_FFFF, + "", + )?; + + let resource_ap2scp_mhu_non_secure_ram = coalesce_equivalent_as_into_resource( + dn, + "ap2scp_mhu_non_secure_ram", + &[ + ( + "ap_memory_map/subsystem_peripherals/scp_mhu_non_secure_ram", + 0x0, + ), + ( + "scp_memory_map/scp_peripherals/ap2scp_mhu_non_secure_ram", + 0x0, + ), + ], + )?; + let resource_ap2scp_mhu_secure_ram = coalesce_equivalent_as_into_resource( + dn, + "ap2scp_mhu_secure_ram", + &[ + ( + "ap_memory_map/subsystem_peripherals/scp_mhu_secure_ram", + 0x0, + ), + ("scp_memory_map/scp_peripherals/ap2scp_mhu_secure_ram", 0x0), + ], + )?; + + let resource_ap2mcp_mhu_non_secure_ram = coalesce_equivalent_as_into_resource( + dn, + "ap2mcp_mhu_non_secure_ram", + &[ + ( + "ap_memory_map/subsystem_peripherals/ap2mcp_mhu_non_secure_ram", + 0x0, + ), + ( + "mcp_memory_map/mcp_peripherals/ap2_mcp_mhu_non_secure_ram", + 0x0, + ), + ], + )?; + let resource_ap2mcp_mhu_secure_ram = coalesce_equivalent_as_into_resource( + dn, + "ap2mcp_mhu_secure_ram", + &[ + ( + "ap_memory_map/subsystem_peripherals/ap2mcp_mhu_secure_ram", + 0x0, + ), + ("mcp_memory_map/mcp_peripherals/ap2_mcp_mhu_secure_ram", 0x0), + ], + )?; + + let resource_scp2mcp_mhu_non_secure_ram = coalesce_equivalent_as_into_resource( + dn, + "scp2mcp_mhu_non_secure_ram", + &[ + ( + "scp_memory_map/scp_peripherals/scp2mcp_mhu_non_secure_ram", + 0x0, + ), + ("mcp_memory_map/scp2_mhu/scp2_mcp_mhu_non_secure_ram", 0x0), + ], + )?; + let resource_scp2mcp_mhu_secure_ram = coalesce_equivalent_as_into_resource( + dn, + "scp2mcp_mhu_secure_ram", + &[ + ("scp_memory_map/scp_peripherals/scp2mcp_mhu_secure_ram", 0x0), + ("mcp_memory_map/scp2_mhu/scp2_mcp_mhu_secure_ram", 0x0), + ], + )?; + + let resource_dram = coalesce_equivalent_as_into_resource( + dn, + "dram", + &[ + ("ap_memory_map/dram0", 0x0), + ("ap_memory_map/dram1", SIZE_2GB), + ("ap_memory_map/dram2", SIZE_512GB), + ], + )?; + + let mut morello = Morello {}; + + return Ok(morello); + } +} diff --git a/src/specs/morello/raw/README.md b/src/specs/morello/raw/README.md new file mode 100644 index 0000000000000000000000000000000000000000..269014bc5b6db6ce769deef7edd871edccb2f3d5 --- /dev/null +++ b/src/specs/morello/raw/README.md @@ -0,0 +1,6 @@ +# Raw CSV files + +These files were extracted from the Morello specification documents. They +contain a Python script that transforms the CSV tables into Rust source code. + +Modifications to the CSV files will not be picked up by the spec automatically. diff --git a/src/specs/morello/raw/input/morello/sdp_ap_map.csv b/src/specs/morello/raw/input/morello/sdp_ap_map.csv new file mode 100644 index 0000000000000000000000000000000000000000..b5526d4f5b02cd36452a59fb7af346f7a314b1c7 --- /dev/null +++ b/src/specs/morello/raw/input/morello/sdp_ap_map.csv @@ -0,0 +1,21 @@ +0x0_0000_0000 0x0_07FF_FFFF 128MB Boot region +0x0_0800_0000 0x0_1fff_ffff Invalid|Custom|NotCalculated IOFPGA Map Window +0x0_2000_0000 0x0_207F_FFFF 8MB PCIe rc (APB) +0x0_2080_0000 0x0_2084_FFFF 320KB PCIe PHY (APB) +0x0_2085_0000 0x0_2085_FFFF 64KB PCIe msg (APB) +0x0_2100_0000 0x0_217F_FFFF 8MB CCIX rc (APB) +0x0_2180_0000 0x0_2184_FFFF 320KB CCIX PHY (APB) +0x0_2185_0000 0x0_2185_FFFF 64KB CCIX msg (APB) +0x0_2200_0000 0x0_220F_FFFF 1MB NIC-400 SoC GPV +0x0_2210_0000 0x0_2210_FFFF 64KB GPIO +0x0_2A00_0000 0x0_4FFF_FFFF 608MB Subsystem peripherals +0x0_5000_0000 0x0_5FFF_FFFF 256MB CMN-Skeena GPV +0x0_6000_0000 0x0_6FFF_FFFF 256MB PCIe subordinate AXI 1 +0x0_7000_0000 0x0_7FFF_FFFF 256MB CCIX subordinate AXI 1 +0x0_8000_0000 0x0_FFFF_FFFF 2GB DRAM0 +0x4_0000_0000 0x4_FFFF_FFFF 4GB CoreSight subsystem +0x5_0000_0000 0x8_FFFF_FFFF 16GB IOFPGA TLX manager IF +0x9_0000_0000 0x28_FFFF_FFFF 128GB PCIe subordinate AXI 2 +0x30_0000_0000 0x4F_FFFF_FFFF 128GB CCIX subordinate AXI 2 +0x80_8000_0000 0xFF_FFFF_FFFF 510GB DRAM1 +0x100_0000_0000 0x3FF_FFFF_FFFF 3TB DRAM2 diff --git a/src/specs/morello/raw/input/morello/sdp_ap_sub_iofpga_map.csv b/src/specs/morello/raw/input/morello/sdp_ap_sub_iofpga_map.csv new file mode 100644 index 0000000000000000000000000000000000000000..25124e13fb1ef367fb15b959efa140003f8ca302 --- /dev/null +++ b/src/specs/morello/raw/input/morello/sdp_ap_sub_iofpga_map.csv @@ -0,0 +1,31 @@ +0x0800_0000 0x13FF_FFFF 192MB DDR3 +0x1400_0000 0x15FF_FFFF 32MB SCP backup boot memory +0x1600_0000 0x17FF_FFFF 32MB MCP backup boot memory +0x1800_0000 0x19FF_FFFF 32MB QSPI (SCP/MCP) +0x1A00_0000 0x1BFF_FFFF 32MB QSPI (AP) +0x1C00_0000 0x1C00_FFFF 64KB I2S +0x1C01_0000 0x1C01_FFFF 64KB System registers +0x1C02_0000 0x1C02_FFFF 64KB System control +0x1C03_0000 0x1C03_FFFF 64KB PCIe SW I2C +0x1C04_0000 0x1C04_FFFF 64KB SoC DDR SPD +0x1C05_0000 0x1C05_FFFF 64KB QSPI configuration (AP) +0x1C06_0000 0x1C06_FFFF 64KB SDIO microSD configuration +0x1C07_0000 0x1C07_FFFF 64KB SDIO eMMC configuration +0x1C08_0000 0x1C08_FFFF 64KB Reserved 1 +0x1C09_0000 0x1C09_FFFF 64KB FPGAUART0 +0x1C0A_0000 0x1C0A_FFFF 64KB FPGAUART1 +0x1C0B_0000 0x1C0B_FFFF 64KB Watchdog +0x1C0C_0000 0x1C0C_FFFF 64KB QSPI SPI configuration (AP) +0x1C0D_0000 0x1C0D_FFFF 64KB Dual Timer 0/1 +0x1C0E_0000 0x1C0E_FFFF 64KB Dual Timer 2/3 +0x1C0F_0000 0x1C0F_FFFF 64KB DVI I2C +0x1C10_0000 0x1C10_FFFF 64KB Real Time Clock +0x1C11_0000 0x1C11_FFFF 64KB GPIO 0 +0x1C12_0000 0x1C12_FFFF 64KB GPIO 1 +0x1C13_0000 0x1C13_FFFF 64KB SCC +0x1C14_0000 0x1C14_FFFF 64KB SMC configuration +0x1C15_0000 0x1C15_FFFF 64KB I2S TX +0x1D00_0000 0x1D0F_FFFF 1MB USB +0x1D10_0000 0x1D1F_FFFF 1MB Ethernet +0x1D20_0000 0x1D2F_FFFF 1MB SRAM +0x1D30_0000 0x1FFF_FFFF 45MB Reserved 2 \ No newline at end of file diff --git a/src/specs/morello/raw/input/morello/sdp_ap_sub_peripherals_map.csv b/src/specs/morello/raw/input/morello/sdp_ap_sub_peripherals_map.csv new file mode 100644 index 0000000000000000000000000000000000000000..a216111d98792bf6d2da96e911f1362042f2366a --- /dev/null +++ b/src/specs/morello/raw/input/morello/sdp_ap_sub_peripherals_map.csv @@ -0,0 +1,57 @@ +0x00_2A00_0000 0x00_2A0F_FFFF 1MB Reserved +0x00_2A10_0000 0x00_2A1F_FFFF 1MB Interconnect NIC GPV +0x00_2A30_0000 0x00_2A3F_FFFF 1MB Reserved (Base NIC GPV) +0x00_2A40_0000 0x00_2A40_FFFF 64KB APUART0 +0x00_2A41_0000 0x00_2A41_FFFF 64KB APUART1 +0x00_2A42_0000 0x00_2A42_FFFF 64KB System Security Control (SSC) registers +0x00_2A43_0000 0x00_2A43_FFFF 64KB REFCLK CNTControl +0x00_2A44_0000 0x00_2A44_FFFF 64KB Generic Watchdog Control +0x00_2A45_0000 0x00_2A45_FFFF 64KB Generic Watchdog Refresh +0x00_2A48_0000 0x00_2A48_FFFF 64KB Trusted Watchdog Control +0x00_2A49_0000 0x00_2A49_FFFF 64KB Trusted Watchdog Refresh +0x00_2A4B_0000 0x00_2A4B_FFFF 64KB AP_SEC_UART +0x00_2A80_0000 0x00_2A80_FFFF 64KB REFCLK CNTRead +0x00_2A81_0000 0x00_2A81_FFFF 64KB AP_REFCLK CNTCTL +0x00_2A82_0000 0x00_2A82_FFFF 64KB AP_REFCLK_S CNTBase1 +0x00_2A83_0000 0x00_2A83_FFFF 64KB AP_REFCLK_NS CNTBase0 +0x00_2B00_0000 0x00_2B0F_FFFF 1MB Reserved for SCP/MCP to access whole of application space. +0x00_2C00_0000 0x00_2C00_1FFF 8KB GICC registers +0x00_2C01_0000 0x00_2C01_0FFF 4KB GICH registers +0x00_2C02_0000 0x00_2C02_1FFF 8KB GICV registers +0x00_2CC0_0000 0x00_2CDF_FFFF 2MB Display Controller +0x00_2CE0_0000 0x00_2CEF_FFFF 1MB Display MMU +0x00_2D00_0000 0x00_2DFF_FFFF 16MB GPU Element +0x00_2E08_0000 0x00_2FFF_FFFF Invalid|32MB Reserved for GIC +0x00_3000_0000 0x00_3000_FFFF 64KB GICD registers +0x00_3001_0000 0x00_3001_FFFF 64KB GICA registers +0x00_3002_0000 0x00_3002_FFFF 64KB GICT registers +0x00_3003_0000 0x00_3003_FFFF 64KB GICP registers +0x00_3004_0000 0x00_3004_FFFF 64KB GICITS0 ITS address +0x00_3005_0000 0x00_3005_FFFF 64KB GICITS0 translater +0x00_3006_0000 0x00_3006_FFFF 64KB GICITS1 address +0x00_3007_0000 0x00_3007_FFFF 64KB GICITS1 translater +0x00_3008_0000 0x00_3008_FFFF 64KB GICITS2 address +0x00_3009_0000 0x00_3009_FFFF 64KB GICITS2 translater +0x00_300A_0000 0x00_300A_FFFF 64KB GICITS3 address +0x00_300B_0000 0x00_300B_FFFF 64KB GICITS3 translater +0x00_300C_0000 0x00_300C_FFFF 64KB GICR registers +0x00_4410_0000 0x00_4410_FFFF 64KB REFCLK general timer control +0x00_4411_0000 0x00_4411_FFFF 64KB Cluster 0 time frame +0x00_4412_0000 0x00_4412_FFFF 64KB Cluster 1 time frame +0x00_4500_0000 0x00_4500_FFFF 64KB SCP Message Handling Unit (MHU) 0 +0x00_4501_0000 0x00_4501_FFFF 64KB SCP MHU1 +0x00_4520_0000 0x00_4521_FFFF 128KB SCP MHU Non-secure RAM +0x00_4540_0000 0x00_4541_FFFF 128KB SCP MHU Secure RAM +0x00_4700_0000 0x00_4700_FFFF 64KB SYSCNT_MSTSYN_CTRL +0x00_4701_0000 0x00_4701_FFFF 64KB CSCNT_MSTSYNC_CTRL +0x00_4C40_0000 0x00_4C40_FFFF 64KB AP2MCP MHU +0x00_4C41_0000 0x00_4C41_FFFF 64KB AP2MCP MHU Non-Secure RAM +0x00_4C42_0000 0x00_4C42_FFFF 64KB AP2MCP MHU Secure RAM +0x00_4D00_0000 0x00_4DFF_FFFF 16MB Base STM +0x00_4E00_0000 0x00_4EFF_FFFF 16MB Memory Element +0x00_4F00_0000 0x00_4F03_FFFF 256KB Translation Control Unit (TCU) 0 for CCIX root port. +0x00_4F04_0000 0x00_4F05_FFFF 128KB Translation Buffer Unit (TBU) 0 for CCIX root port. +0x00_4F06_0000 0x00_4F07_FFFF 128KB Translation Buffer Unit (TBU) 1 for CCIX root port. +0x00_4F40_0000 0x00_4F43_FFFF 256KB Translation Control Unit (TCU) 1 for PCIe root port. +0x00_4F44_0000 0x00_4F45_FFFF 128KB Translation Buffer Unit (TBU) 0 for PCIe root port. +0x00_4F46_0000 0x00_4F47_FFFF 128KB Translation Buffer Unit (TBU) 1 for PCIe root port. \ No newline at end of file diff --git a/src/specs/morello/raw/input/morello/sdp_mcp_map.csv b/src/specs/morello/raw/input/morello/sdp_mcp_map.csv new file mode 100644 index 0000000000000000000000000000000000000000..4edf7565c5746cf555f5f067ce5e5d7b8e493a56 --- /dev/null +++ b/src/specs/morello/raw/input/morello/sdp_mcp_map.csv @@ -0,0 +1,22 @@ +0x0_0000_0000 0x0_007F_FFFF 8MB Code boot ROM +0x0_0080_0000 0x0_00FF_FFFF 8MB Code TCRAM +0x0_0100_0000 0x0_15FF_FFFF 336MB Reserved part of MCP SoC expansion memory 1 +0x0_1600_0000 0x0_17FF_FFFF 32MB TMIF interface +0x0_1800_0000 0x0_1FFF_FFFF 128MB Reserved part of MCP SoC expansion memory 2 +0x0_2000_0000 0x0_2001_FFFF 128KB SRAM DTCRAM +0x0_2100_0000 0x0_2FFF_FFFF 240MB Reserved part of MCP SoC expansion memory 3 +0x0_3000_0000 0x0_33FF_FFFF 64MB MCP QSPI AHB +0x0_3400_0000 0x0_3400_0FFF 4KB MCP QSPI APB +0x0_3400_1000 0x0_3FFF_DFFF Invalid|191MB Reserved part of MCP SoC expansion memory 4 +0x0_3FFF_E000 0x0_3FFF_EFFF 4KB Reserved 1 +0x0_3FFF_F000 0x0_3FFF_FFFF 4KB MCP I2C 1 (BMC-PCC) +0x0_4000_0000 0x0_43FF_FFFF 64MB MCP SoC expansion 1 +0x0_4560_0000 0x0_45FF_FFFF 10MB SCP2 MHU +0x0_4800_0000 0x0_4BFF_FFFF 64MB MCP SoC expansion 2 +0x0_4C00_0000 0x0_4DFF_FFFF 32MB MCP peripherals +0x0_5000_0000 0x0_507F_FFFF 8MB Element management peripherals +0x0_6000_0000 0x0_9FFF_FFFF 1GB System Access Port. Translated to 0x0_4000_0000 to 0x0_7FFF_FFFF of AP memory map. +0x0_A000_0000 0x0_DFFF_FFFF 1GB System Access Port. Translated to 0x0_0000_0000 to 0x0_3FFF_FFFF of AP memory map with debug address translation not enabled. Translated to 0x4_0000_0000 to 0x4_3FFF_FFFF of AP memory map with debug address translation enabled. +0x0_E000_0000 0x0_E003_FFFF 256KB Private peripheral bus - Internal. +0x0_E004_0000 0x0_E00F_FFFF 768KB Private peripheral bus - External. +0x0_E010_0000 0x0_FFFF_FFFF 511MB Reserved 2 \ No newline at end of file diff --git a/src/specs/morello/raw/input/morello/sdp_mcp_sub_peripherals_map.csv b/src/specs/morello/raw/input/morello/sdp_mcp_sub_peripherals_map.csv new file mode 100644 index 0000000000000000000000000000000000000000..bfbe06081ee68c2868c634c20e033d5a66768432 --- /dev/null +++ b/src/specs/morello/raw/input/morello/sdp_mcp_sub_peripherals_map.csv @@ -0,0 +1,8 @@ +0x00_4C00_0000 0x00_4C00_0FFF 4KB REFCLK CNTCTL +0x00_4C00_1000 0x00_4C00_1FFF 4KB REFCLK CNTBase0 +0x00_4C00_2000 0x00_4C00_2FFF 4KB MCPUART0 +0x00_4C00_3000 0x00_4C00_3FFF 4KB MCPUART1 +0x00_4C00_6000 0x00_4C00_6FFF 4KB Watchdog (SP805) +0x00_4C40_0000 0x00_4C40_FFFF 64KB AP2 MCP MHU +0x00_4C41_0000 0x00_4C41_FFFF 64KB AP2 MCP MHU Non-secure RAM +0x00_4C42_0000 0x00_4C42_FFFF 64KB AP2 MCP MHU Secure RAM \ No newline at end of file diff --git a/src/specs/morello/raw/input/morello/sdp_mcp_sub_peripherals_scp2_mhu_map.csv b/src/specs/morello/raw/input/morello/sdp_mcp_sub_peripherals_scp2_mhu_map.csv new file mode 100644 index 0000000000000000000000000000000000000000..c5a21491950e36309f278f091651c821c5a9301d --- /dev/null +++ b/src/specs/morello/raw/input/morello/sdp_mcp_sub_peripherals_scp2_mhu_map.csv @@ -0,0 +1,3 @@ +0x00_4560_0000 0x00_4560_FFFF 64KB SCP2 MCP Message Handling Unit (MHU) +0x00_4561_0000 0x00_4561_FFFF 64KB SCP2 MCP MHU Non-secure RAM +0x00_4562_0000 0x00_4562_FFFF 64KB SCP2 MCP MHU Secure RAM \ No newline at end of file diff --git a/src/specs/morello/raw/input/morello/sdp_scp_map.csv b/src/specs/morello/raw/input/morello/sdp_scp_map.csv new file mode 100644 index 0000000000000000000000000000000000000000..68a87919d1c7151f63c9b91941bd79faf29a5ea3 --- /dev/null +++ b/src/specs/morello/raw/input/morello/sdp_scp_map.csv @@ -0,0 +1,32 @@ +0x0_0000_0000 0x0_007F_FFFF 8MB Code boot ROM +0x0_0080_0000 0x0_00FF_FFFF 8MB Code TCRAM +0x0_0100_0000 0x0_13FF_FFFF 304MB Reserved part of SCP SoC expansion memory 1 +0x0_1400_0000 0x0_15FF_FFFF 32MB TMIF interface +0x0_1600_0000 0x0_1FFF_FFFF 160MB Reserved part of SCP SoC expansion memory 2 +0x0_2000_0000 0x0_2001_FFFF 128KB SRAM DTCRAM +0x0_2100_0000 0x0_2FFF_FFFF 240MB Reserved part of SCP SoC expansion memory 3 +0x0_3000_0000 0x0_33FF_FFFF Invalid|64MB SCP QSPI AHB +0x0_3400_0000 0x0_3400_0FFF Invalid|4KB SCP QSPI APB +0x0_3400_1000 0x0_3FFD_FFFF Invalid|191MB Reserved part of SCP SoC expansion memory 4 +0x0_3FFE_0000 0x0_3FFE_FFFF 64KB SCP PVT CTRL +0x0_3FFF_0000 0x0_3FFF_9FFF 40KB Reserved part of SCP SoC expansion memory 5 +0x0_3FFF_A000 0x0_3FFF_AFFF 4KB Reserved 1 +0x0_3FFF_B000 0x0_3FFF_BFFF 4KB SCP I2C1 (PMIC) +0x0_3FFF_C000 0x0_3FFF_CFFF 4KB SCP I2C2 (SPD-PCC) +0x0_3FFF_D000 0x0_3FFF_EFFF 8KB Reserved part of SCP SoC expansion memory 6 +0x0_3FFF_F000 0x0_3FFF_FFFF 4KB SCC registers +0x0_4000_0000 0x0_43FF_FFFF 64MB SCP SoC expansion +0x0_4400_0000 0x0_45FF_FFFF 32MB SCP peripherals +0x0_4800_0000 0x0_4BFF_FFFF 64MB MCP SoC expansion +0x0_4E00_0000 0x0_4E00_FFFF 64KB Memory element 0 configuration +0x0_4E01_0000 0x0_4E01_FFFF 64KB Memory element 0 manager +0x0_4E02_0000 0x0_4E02_FFFF 64KB Memory element 0 sensor group +0x0_4E10_0000 0x0_4E10_FFFF 64KB Memory element 1 configuration +0x0_4E11_0000 0x0_4E11_FFFF 64KB Memory element 1 manager +0x0_4E12_0000 0x0_4E12_FFFF 64KB Memory element 1 sensor group +0x0_5000_0000 0x0_507F_FFFF 8MB Element management peripherals +0x0_6000_0000 0x0_9FFF_FFFF 1GB System Access Port. Translated to 0x0_4000_0000 to 0x0_7FFF_FFFF of AP memory map. +0x0_A000_0000 0x0_DFFF_FFFF 1GB System Access Port. Translated to 0x0_0000_0000 to 0x0_3FFF_FFFF of AP memory map with debug address translation not enabled. Translated to 0x4_0000_0000 to 0x4_3FFF_FFFF of AP memory map with debug address translation enabled. +0x0_E000_0000 0x0_E003_FFFF 256KB Private peripheral bus - Internal. +0x0_E004_0000 0x0_E00F_FFFF 768KB Private peripheral bus - External. +0x0_E010_0000 0x0_FFFF_FFFF 511MB Reserved 2 \ No newline at end of file diff --git a/src/specs/morello/raw/input/morello/sdp_scp_sub_peripherals_map.csv b/src/specs/morello/raw/input/morello/sdp_scp_sub_peripherals_map.csv new file mode 100644 index 0000000000000000000000000000000000000000..d5e379a35233bf824d6137c72586fd15ab375f1c --- /dev/null +++ b/src/specs/morello/raw/input/morello/sdp_scp_sub_peripherals_map.csv @@ -0,0 +1,14 @@ +0x00_4400_0000 0x00_4400_0FFF 4KB REFCLK CNTCTL +0x00_4400_1000 0x00_4400_1FFF 4KB REFCLK CNTBase0 +0x00_4400_2000 0x00_4400_2FFF 4KB SCPUART +0x00_4400_6000 0x00_4400_6FFF 4KB Watchdog (SP805) +0x00_4400_A000 0x00_4400_AFFF 4KB CS CNTCONTROL +0x00_4410_0000 0x00_4410_FFFF 64KB REFCLK general timer control +0x00_4411_0000 0x00_4411_FFFF 64KB Cluster 0 time frame +0x00_4412_0000 0x00_4412_FFFF 64KB Cluster 1 time frame +0x00_4500_0000 0x00_4501_FFFF 128KB AP2SCP Message Handling Unit (MHU) +0x00_452C_0000 0x00_452D_FFFF 128KB AP2SCP MHU Non-secure RAM +0x00_4540_0000 0x00_4541_FFFF 128KB AP2SCP MHU Secure RAM +0x00_4560_0000 0x00_4560_FFFF 64KB SCP2MCH MHU +0x00_4561_0000 0x00_4561_FFFF 64KB SCP2MCP MHU Non-secure RAM +0x00_4562_0000 0x00_4562_FFFF 64KB SCP2MCP MHU Secure RAM \ No newline at end of file diff --git a/src/specs/morello/raw/transform.py b/src/specs/morello/raw/transform.py new file mode 100644 index 0000000000000000000000000000000000000000..67a0e590f444570082c94842dc751af7dd260c28 --- /dev/null +++ b/src/specs/morello/raw/transform.py @@ -0,0 +1,121 @@ +import os +import csv + +directory = "input" + +parent_asid_var = "subsystem_peripherals" +parent_off = "off" + +output_base_dir = "../src/specs/" + + +def write_struct( + file, line_prefix, struct_type_name, name, description, start, end, length +): + + factor = length[:-2] + unit = length[-2:] + + file.write(line_prefix + struct_type_name + " {\n") + + if "Invalid" in length: + file.write(line_prefix + " // Length: " + length + "\n") + length = None + + file.write(line_prefix + ' name: "' + name + '",\n') + file.write(line_prefix + ' description: "' + description + '",\n') + file.write(line_prefix + " start: ") + if start is not None: + file.write("Some(0x" + start.to_bytes(6, "big").hex("_", 2) + ")") + else: + file.write("None") + file.write(",\n") + file.write(line_prefix + " end: ") + if end is not None: + file.write("Some(0x" + end.to_bytes(6, "big").hex("_", 2) + ")") + else: + file.write("None") + file.write(",\n") + file.write(line_prefix + " length: ") + if length is not None: + file.write("Some(size!(" + factor + ", " + unit + "))") + else: + file.write("None") + file.write(",\n") + + file.write(line_prefix + "}") + + +for target in os.listdir("input"): + + if not os.path.isdir(output_base_dir + target): + os.makedirs(output_base_dir + target) + + for file in os.listdir("input/" + target): + + with open("input" + "/" + target + "/" + file) as csvfile: + + reader = csv.reader(csvfile, delimiter=" ") + + outfilename = file + outfilename = outfilename.replace(".csv", ".rs") + + outfile_path = output_base_dir + target + "/" + outfilename + print("Transforming " + file + " > " + outfile_path) + + array_name = "MAPINFOS" + + struct_type_name = "MapInfo" + + with open(outfile_path, "w+") as outfile: + + outfile.write("use crate::specs::common::*;\n") + outfile.write("\n") + outfile.write( + "pub static " + + array_name.upper() + + ": &'static [" + + struct_type_name + + "] = &[\n" + ) + + for idx, row in enumerate(reader): + + print(" Row " + str(idx), end="\r") + + start_address = int(row[0], base=0) + end_address = int(row[1], base=0) + length = row[2] + name = "" + for i in range(3, len(row)): + if name != "": + name = name + " " + name = name + row[i] + + variable_name = name.lower() + variable_name = variable_name.replace("(", "") + variable_name = variable_name.replace(")", "") + variable_name = variable_name.replace(".", "") + variable_name = variable_name.replace(",", "_") + variable_name = variable_name.replace("/", "_") + variable_name = variable_name.replace(" ", "_") + variable_name = variable_name.replace("-", "_") + + # print("let " + variable_name + " = add_sub_as_len(dn, " + parent_asid_var + ", " + parent_off + ", \"" + name + "\", \"\", " + address_string + ", size!(" + size + "))?;") + + # Adding one to end address, because our ranges are [start, end) not [start, end] + write_struct( + file=outfile, + line_prefix=" ", + struct_type_name=struct_type_name, + name=variable_name, + description=name, + start=start_address, + end=end_address + 1, + length=length, + ) + outfile.write(",\n") + + outfile.write("];\n") + + print("") diff --git a/src/specs/morello/sdp_ap_map.rs b/src/specs/morello/sdp_ap_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..844b8923b40ab8f924d9e9ab5bf6ba2fe6140654 --- /dev/null +++ b/src/specs/morello/sdp_ap_map.rs @@ -0,0 +1,152 @@ +use crate::specs::common::*; + +pub static MAPINFOS: &'static [MapInfo] = &[ + MapInfo { + name: "boot_region", + description: "Boot region", + start: Some(0x0000_0000_0000), + end: Some(0x0000_0800_0000), + length: Some(size!(128, MB)), + }, + MapInfo { + // Length: Invalid|Custom|NotCalculated + name: "iofpga_map_window", + description: "IOFPGA Map Window", + start: Some(0x0000_0800_0000), + end: Some(0x0000_2000_0000), + length: None, + }, + MapInfo { + name: "pcie_rc_apb", + description: "PCIe rc (APB)", + start: Some(0x0000_2000_0000), + end: Some(0x0000_2080_0000), + length: Some(size!(8, MB)), + }, + MapInfo { + name: "pcie_phy_apb", + description: "PCIe PHY (APB)", + start: Some(0x0000_2080_0000), + end: Some(0x0000_2085_0000), + length: Some(size!(320, KB)), + }, + MapInfo { + name: "pcie_msg_apb", + description: "PCIe msg (APB)", + start: Some(0x0000_2085_0000), + end: Some(0x0000_2086_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ccix_rc_apb", + description: "CCIX rc (APB)", + start: Some(0x0000_2100_0000), + end: Some(0x0000_2180_0000), + length: Some(size!(8, MB)), + }, + MapInfo { + name: "ccix_phy_apb", + description: "CCIX PHY (APB)", + start: Some(0x0000_2180_0000), + end: Some(0x0000_2185_0000), + length: Some(size!(320, KB)), + }, + MapInfo { + name: "ccix_msg_apb", + description: "CCIX msg (APB)", + start: Some(0x0000_2185_0000), + end: Some(0x0000_2186_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "nic_400_soc_gpv", + description: "NIC-400 SoC GPV", + start: Some(0x0000_2200_0000), + end: Some(0x0000_2210_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "gpio", + description: "GPIO", + start: Some(0x0000_2210_0000), + end: Some(0x0000_2211_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "subsystem_peripherals", + description: "Subsystem peripherals", + start: Some(0x0000_2a00_0000), + end: Some(0x0000_5000_0000), + length: Some(size!(608, MB)), + }, + MapInfo { + name: "cmn_skeena_gpv", + description: "CMN-Skeena GPV", + start: Some(0x0000_5000_0000), + end: Some(0x0000_6000_0000), + length: Some(size!(256, MB)), + }, + MapInfo { + name: "pcie_subordinate_axi_1", + description: "PCIe subordinate AXI 1", + start: Some(0x0000_6000_0000), + end: Some(0x0000_7000_0000), + length: Some(size!(256, MB)), + }, + MapInfo { + name: "ccix_subordinate_axi_1", + description: "CCIX subordinate AXI 1", + start: Some(0x0000_7000_0000), + end: Some(0x0000_8000_0000), + length: Some(size!(256, MB)), + }, + MapInfo { + name: "dram0", + description: "DRAM0", + start: Some(0x0000_8000_0000), + end: Some(0x0001_0000_0000), + length: Some(size!(2, GB)), + }, + MapInfo { + name: "coresight_subsystem", + description: "CoreSight subsystem", + start: Some(0x0004_0000_0000), + end: Some(0x0005_0000_0000), + length: Some(size!(4, GB)), + }, + MapInfo { + name: "iofpga_tlx_manager_if", + description: "IOFPGA TLX manager IF", + start: Some(0x0005_0000_0000), + end: Some(0x0009_0000_0000), + length: Some(size!(16, GB)), + }, + MapInfo { + name: "pcie_subordinate_axi_2", + description: "PCIe subordinate AXI 2", + start: Some(0x0009_0000_0000), + end: Some(0x0029_0000_0000), + length: Some(size!(128, GB)), + }, + MapInfo { + name: "ccix_subordinate_axi_2", + description: "CCIX subordinate AXI 2", + start: Some(0x0030_0000_0000), + end: Some(0x0050_0000_0000), + length: Some(size!(128, GB)), + }, + MapInfo { + name: "dram1", + description: "DRAM1", + start: Some(0x0080_8000_0000), + end: Some(0x0100_0000_0000), + length: Some(size!(510, GB)), + }, + MapInfo { + name: "dram2", + description: "DRAM2", + start: Some(0x0100_0000_0000), + end: Some(0x0400_0000_0000), + length: Some(size!(3, TB)), + }, +]; diff --git a/src/specs/morello/sdp_ap_sub_iofpga_map.rs b/src/specs/morello/sdp_ap_sub_iofpga_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..c082fd09575785f394e7b9d961c4da77665eac9c --- /dev/null +++ b/src/specs/morello/sdp_ap_sub_iofpga_map.rs @@ -0,0 +1,221 @@ +use crate::specs::common::*; + +pub static MAPINFOS: &'static [MapInfo] = &[ + MapInfo { + name: "ddr3", + description: "DDR3", + start: Some(0x0000_0800_0000), + end: Some(0x0000_1400_0000), + length: Some(size!(192, MB)), + }, + MapInfo { + name: "scp_backup_boot_memory", + description: "SCP backup boot memory", + start: Some(0x0000_1400_0000), + end: Some(0x0000_1600_0000), + length: Some(size!(32, MB)), + }, + MapInfo { + name: "mcp_backup_boot_memory", + description: "MCP backup boot memory", + start: Some(0x0000_1600_0000), + end: Some(0x0000_1800_0000), + length: Some(size!(32, MB)), + }, + MapInfo { + name: "qspi_scp_mcp", + description: "QSPI (SCP/MCP)", + start: Some(0x0000_1800_0000), + end: Some(0x0000_1a00_0000), + length: Some(size!(32, MB)), + }, + MapInfo { + name: "qspi_ap", + description: "QSPI (AP)", + start: Some(0x0000_1a00_0000), + end: Some(0x0000_1c00_0000), + length: Some(size!(32, MB)), + }, + MapInfo { + name: "i2s", + description: "I2S", + start: Some(0x0000_1c00_0000), + end: Some(0x0000_1c01_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "system_registers", + description: "System registers", + start: Some(0x0000_1c01_0000), + end: Some(0x0000_1c02_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "system_control", + description: "System control", + start: Some(0x0000_1c02_0000), + end: Some(0x0000_1c03_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "pcie_sw_i2c", + description: "PCIe SW I2C", + start: Some(0x0000_1c03_0000), + end: Some(0x0000_1c04_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "soc_ddr_spd", + description: "SoC DDR SPD", + start: Some(0x0000_1c04_0000), + end: Some(0x0000_1c05_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "qspi_configuration_ap", + description: "QSPI configuration (AP)", + start: Some(0x0000_1c05_0000), + end: Some(0x0000_1c06_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "sdio_microsd_configuration", + description: "SDIO microSD configuration", + start: Some(0x0000_1c06_0000), + end: Some(0x0000_1c07_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "sdio_emmc_configuration", + description: "SDIO eMMC configuration", + start: Some(0x0000_1c07_0000), + end: Some(0x0000_1c08_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "reserved_1", + description: "Reserved 1", + start: Some(0x0000_1c08_0000), + end: Some(0x0000_1c09_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "fpgauart0", + description: "FPGAUART0", + start: Some(0x0000_1c09_0000), + end: Some(0x0000_1c0a_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "fpgauart1", + description: "FPGAUART1", + start: Some(0x0000_1c0a_0000), + end: Some(0x0000_1c0b_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "watchdog", + description: "Watchdog", + start: Some(0x0000_1c0b_0000), + end: Some(0x0000_1c0c_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "qspi_spi_configuration_ap", + description: "QSPI SPI configuration (AP)", + start: Some(0x0000_1c0c_0000), + end: Some(0x0000_1c0d_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "dual_timer_0_1", + description: "Dual Timer 0/1", + start: Some(0x0000_1c0d_0000), + end: Some(0x0000_1c0e_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "dual_timer_2_3", + description: "Dual Timer 2/3", + start: Some(0x0000_1c0e_0000), + end: Some(0x0000_1c0f_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "dvi_i2c", + description: "DVI I2C", + start: Some(0x0000_1c0f_0000), + end: Some(0x0000_1c10_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "real_time_clock", + description: "Real Time Clock", + start: Some(0x0000_1c10_0000), + end: Some(0x0000_1c11_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gpio_0", + description: "GPIO 0", + start: Some(0x0000_1c11_0000), + end: Some(0x0000_1c12_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gpio_1", + description: "GPIO 1", + start: Some(0x0000_1c12_0000), + end: Some(0x0000_1c13_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "scc", + description: "SCC", + start: Some(0x0000_1c13_0000), + end: Some(0x0000_1c14_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "smc_configuration", + description: "SMC configuration", + start: Some(0x0000_1c14_0000), + end: Some(0x0000_1c15_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "i2s_tx", + description: "I2S TX", + start: Some(0x0000_1c15_0000), + end: Some(0x0000_1c16_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "usb", + description: "USB", + start: Some(0x0000_1d00_0000), + end: Some(0x0000_1d10_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "ethernet", + description: "Ethernet", + start: Some(0x0000_1d10_0000), + end: Some(0x0000_1d20_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "sram", + description: "SRAM", + start: Some(0x0000_1d20_0000), + end: Some(0x0000_1d30_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "reserved_2", + description: "Reserved 2", + start: Some(0x0000_1d30_0000), + end: Some(0x0000_2000_0000), + length: Some(size!(45, MB)), + }, +]; diff --git a/src/specs/morello/sdp_ap_sub_peripherals_map.rs b/src/specs/morello/sdp_ap_sub_peripherals_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..59a9df8531ada74f3ddac5c2c32183ac4de138dd --- /dev/null +++ b/src/specs/morello/sdp_ap_sub_peripherals_map.rs @@ -0,0 +1,404 @@ +use crate::specs::common::*; + +pub static MAPINFOS: &'static [MapInfo] = &[ + MapInfo { + name: "reserved", + description: "Reserved", + start: Some(0x0000_2a00_0000), + end: Some(0x0000_2a10_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "interconnect_nic_gpv", + description: "Interconnect NIC GPV", + start: Some(0x0000_2a10_0000), + end: Some(0x0000_2a20_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "reserved_base_nic_gpv", + description: "Reserved (Base NIC GPV)", + start: Some(0x0000_2a30_0000), + end: Some(0x0000_2a40_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "apuart0", + description: "APUART0", + start: Some(0x0000_2a40_0000), + end: Some(0x0000_2a41_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "apuart1", + description: "APUART1", + start: Some(0x0000_2a41_0000), + end: Some(0x0000_2a42_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "system_security_control_ssc_registers", + description: "System Security Control (SSC) registers", + start: Some(0x0000_2a42_0000), + end: Some(0x0000_2a43_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "refclk_cntcontrol", + description: "REFCLK CNTControl", + start: Some(0x0000_2a43_0000), + end: Some(0x0000_2a44_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "generic_watchdog_control", + description: "Generic Watchdog Control", + start: Some(0x0000_2a44_0000), + end: Some(0x0000_2a45_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "generic_watchdog_refresh", + description: "Generic Watchdog Refresh", + start: Some(0x0000_2a45_0000), + end: Some(0x0000_2a46_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "trusted_watchdog_control", + description: "Trusted Watchdog Control", + start: Some(0x0000_2a48_0000), + end: Some(0x0000_2a49_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "trusted_watchdog_refresh", + description: "Trusted Watchdog Refresh", + start: Some(0x0000_2a49_0000), + end: Some(0x0000_2a4a_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap_sec_uart", + description: "AP_SEC_UART", + start: Some(0x0000_2a4b_0000), + end: Some(0x0000_2a4c_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "refclk_cntread", + description: "REFCLK CNTRead", + start: Some(0x0000_2a80_0000), + end: Some(0x0000_2a81_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap_refclk_cntctl", + description: "AP_REFCLK CNTCTL", + start: Some(0x0000_2a81_0000), + end: Some(0x0000_2a82_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap_refclk_s_cntbase1", + description: "AP_REFCLK_S CNTBase1", + start: Some(0x0000_2a82_0000), + end: Some(0x0000_2a83_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap_refclk_ns_cntbase0", + description: "AP_REFCLK_NS CNTBase0", + start: Some(0x0000_2a83_0000), + end: Some(0x0000_2a84_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "reserved_for_scp_mcp_to_access_whole_of_application_space", + description: "Reserved for SCP/MCP to access whole of application space.", + start: Some(0x0000_2b00_0000), + end: Some(0x0000_2b10_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "gicc_registers", + description: "GICC registers", + start: Some(0x0000_2c00_0000), + end: Some(0x0000_2c00_2000), + length: Some(size!(8, KB)), + }, + MapInfo { + name: "gich_registers", + description: "GICH registers", + start: Some(0x0000_2c01_0000), + end: Some(0x0000_2c01_1000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "gicv_registers", + description: "GICV registers", + start: Some(0x0000_2c02_0000), + end: Some(0x0000_2c02_2000), + length: Some(size!(8, KB)), + }, + MapInfo { + name: "display_controller", + description: "Display Controller", + start: Some(0x0000_2cc0_0000), + end: Some(0x0000_2ce0_0000), + length: Some(size!(2, MB)), + }, + MapInfo { + name: "display_mmu", + description: "Display MMU", + start: Some(0x0000_2ce0_0000), + end: Some(0x0000_2cf0_0000), + length: Some(size!(1, MB)), + }, + MapInfo { + name: "gpu_element", + description: "GPU Element", + start: Some(0x0000_2d00_0000), + end: Some(0x0000_2e00_0000), + length: Some(size!(16, MB)), + }, + MapInfo { + // Length: Invalid|32MB + name: "reserved_for_gic", + description: "Reserved for GIC", + start: Some(0x0000_2e08_0000), + end: Some(0x0000_3000_0000), + length: None, + }, + MapInfo { + name: "gicd_registers", + description: "GICD registers", + start: Some(0x0000_3000_0000), + end: Some(0x0000_3001_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gica_registers", + description: "GICA registers", + start: Some(0x0000_3001_0000), + end: Some(0x0000_3002_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gict_registers", + description: "GICT registers", + start: Some(0x0000_3002_0000), + end: Some(0x0000_3003_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicp_registers", + description: "GICP registers", + start: Some(0x0000_3003_0000), + end: Some(0x0000_3004_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicits0_its_address", + description: "GICITS0 ITS address", + start: Some(0x0000_3004_0000), + end: Some(0x0000_3005_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicits0_translater", + description: "GICITS0 translater", + start: Some(0x0000_3005_0000), + end: Some(0x0000_3006_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicits1_address", + description: "GICITS1 address", + start: Some(0x0000_3006_0000), + end: Some(0x0000_3007_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicits1_translater", + description: "GICITS1 translater", + start: Some(0x0000_3007_0000), + end: Some(0x0000_3008_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicits2_address", + description: "GICITS2 address", + start: Some(0x0000_3008_0000), + end: Some(0x0000_3009_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicits2_translater", + description: "GICITS2 translater", + start: Some(0x0000_3009_0000), + end: Some(0x0000_300a_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicits3_address", + description: "GICITS3 address", + start: Some(0x0000_300a_0000), + end: Some(0x0000_300b_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicits3_translater", + description: "GICITS3 translater", + start: Some(0x0000_300b_0000), + end: Some(0x0000_300c_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "gicr_registers", + description: "GICR registers", + start: Some(0x0000_300c_0000), + end: Some(0x0000_300d_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "refclk_general_timer_control", + description: "REFCLK general timer control", + start: Some(0x0000_4410_0000), + end: Some(0x0000_4411_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "cluster_0_time_frame", + description: "Cluster 0 time frame", + start: Some(0x0000_4411_0000), + end: Some(0x0000_4412_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "cluster_1_time_frame", + description: "Cluster 1 time frame", + start: Some(0x0000_4412_0000), + end: Some(0x0000_4413_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "scp_message_handling_unit_mhu_0", + description: "SCP Message Handling Unit (MHU) 0", + start: Some(0x0000_4500_0000), + end: Some(0x0000_4501_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "scp_mhu1", + description: "SCP MHU1", + start: Some(0x0000_4501_0000), + end: Some(0x0000_4502_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "scp_mhu_non_secure_ram", + description: "SCP MHU Non-secure RAM", + start: Some(0x0000_4520_0000), + end: Some(0x0000_4522_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "scp_mhu_secure_ram", + description: "SCP MHU Secure RAM", + start: Some(0x0000_4540_0000), + end: Some(0x0000_4542_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "syscnt_mstsyn_ctrl", + description: "SYSCNT_MSTSYN_CTRL", + start: Some(0x0000_4700_0000), + end: Some(0x0000_4701_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "cscnt_mstsync_ctrl", + description: "CSCNT_MSTSYNC_CTRL", + start: Some(0x0000_4701_0000), + end: Some(0x0000_4702_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap2mcp_mhu", + description: "AP2MCP MHU", + start: Some(0x0000_4c40_0000), + end: Some(0x0000_4c41_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap2mcp_mhu_non_secure_ram", + description: "AP2MCP MHU Non-Secure RAM", + start: Some(0x0000_4c41_0000), + end: Some(0x0000_4c42_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap2mcp_mhu_secure_ram", + description: "AP2MCP MHU Secure RAM", + start: Some(0x0000_4c42_0000), + end: Some(0x0000_4c43_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "base_stm", + description: "Base STM", + start: Some(0x0000_4d00_0000), + end: Some(0x0000_4e00_0000), + length: Some(size!(16, MB)), + }, + MapInfo { + name: "memory_element", + description: "Memory Element", + start: Some(0x0000_4e00_0000), + end: Some(0x0000_4f00_0000), + length: Some(size!(16, MB)), + }, + MapInfo { + name: "translation_control_unit_tcu_0_for_ccix_root_port", + description: "Translation Control Unit (TCU) 0 for CCIX root port.", + start: Some(0x0000_4f00_0000), + end: Some(0x0000_4f04_0000), + length: Some(size!(256, KB)), + }, + MapInfo { + name: "translation_buffer_unit_tbu_0_for_ccix_root_port", + description: "Translation Buffer Unit (TBU) 0 for CCIX root port.", + start: Some(0x0000_4f04_0000), + end: Some(0x0000_4f06_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "translation_buffer_unit_tbu_1_for_ccix_root_port", + description: "Translation Buffer Unit (TBU) 1 for CCIX root port.", + start: Some(0x0000_4f06_0000), + end: Some(0x0000_4f08_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "translation_control_unit_tcu_1_for_pcie_root_port", + description: "Translation Control Unit (TCU) 1 for PCIe root port.", + start: Some(0x0000_4f40_0000), + end: Some(0x0000_4f44_0000), + length: Some(size!(256, KB)), + }, + MapInfo { + name: "translation_buffer_unit_tbu_0_for_pcie_root_port", + description: "Translation Buffer Unit (TBU) 0 for PCIe root port.", + start: Some(0x0000_4f44_0000), + end: Some(0x0000_4f46_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "translation_buffer_unit_tbu_1_for_pcie_root_port", + description: "Translation Buffer Unit (TBU) 1 for PCIe root port.", + start: Some(0x0000_4f46_0000), + end: Some(0x0000_4f48_0000), + length: Some(size!(128, KB)), + }, +]; diff --git a/src/specs/morello/sdp_mcp_map.rs b/src/specs/morello/sdp_mcp_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..d4e1981a77aca12bcf46a3aafdb539e085c9ea3f --- /dev/null +++ b/src/specs/morello/sdp_mcp_map.rs @@ -0,0 +1,159 @@ +use crate::specs::common::*; + +pub static MAPINFOS: &'static [MapInfo] = &[ + MapInfo { + name: "code_boot_rom", + description: "Code boot ROM", + start: Some(0x0000_0000_0000), + end: Some(0x0000_0080_0000), + length: Some(size!(8, MB)), + }, + MapInfo { + name: "code_tcram", + description: "Code TCRAM", + start: Some(0x0000_0080_0000), + end: Some(0x0000_0100_0000), + length: Some(size!(8, MB)), + }, + MapInfo { + name: "reserved_part_of_mcp_soc_expansion_memory_1", + description: "Reserved part of MCP SoC expansion memory 1", + start: Some(0x0000_0100_0000), + end: Some(0x0000_1600_0000), + length: Some(size!(336, MB)), + }, + MapInfo { + name: "tmif_interface", + description: "TMIF interface", + start: Some(0x0000_1600_0000), + end: Some(0x0000_1800_0000), + length: Some(size!(32, MB)), + }, + MapInfo { + name: "reserved_part_of_mcp_soc_expansion_memory_2", + description: "Reserved part of MCP SoC expansion memory 2", + start: Some(0x0000_1800_0000), + end: Some(0x0000_2000_0000), + length: Some(size!(128, MB)), + }, + MapInfo { + name: "sram_dtcram", + description: "SRAM DTCRAM", + start: Some(0x0000_2000_0000), + end: Some(0x0000_2002_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "reserved_part_of_mcp_soc_expansion_memory_3", + description: "Reserved part of MCP SoC expansion memory 3", + start: Some(0x0000_2100_0000), + end: Some(0x0000_3000_0000), + length: Some(size!(240, MB)), + }, + MapInfo { + name: "mcp_qspi_ahb", + description: "MCP QSPI AHB", + start: Some(0x0000_3000_0000), + end: Some(0x0000_3400_0000), + length: Some(size!(64, MB)), + }, + MapInfo { + name: "mcp_qspi_apb", + description: "MCP QSPI APB", + start: Some(0x0000_3400_0000), + end: Some(0x0000_3400_1000), + length: Some(size!(4, KB)), + }, + MapInfo { + // Length: Invalid|191MB + name: "reserved_part_of_mcp_soc_expansion_memory_4", + description: "Reserved part of MCP SoC expansion memory 4", + start: Some(0x0000_3400_1000), + end: Some(0x0000_3fff_e000), + length: None, + }, + MapInfo { + name: "reserved_1", + description: "Reserved 1", + start: Some(0x0000_3fff_e000), + end: Some(0x0000_3fff_f000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "mcp_i2c_1_bmc_pcc", + description: "MCP I2C 1 (BMC-PCC)", + start: Some(0x0000_3fff_f000), + end: Some(0x0000_4000_0000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "mcp_soc_expansion_1", + description: "MCP SoC expansion 1", + start: Some(0x0000_4000_0000), + end: Some(0x0000_4400_0000), + length: Some(size!(64, MB)), + }, + MapInfo { + name: "scp2_mhu", + description: "SCP2 MHU", + start: Some(0x0000_4560_0000), + end: Some(0x0000_4600_0000), + length: Some(size!(10, MB)), + }, + MapInfo { + name: "mcp_soc_expansion_2", + description: "MCP SoC expansion 2", + start: Some(0x0000_4800_0000), + end: Some(0x0000_4c00_0000), + length: Some(size!(64, MB)), + }, + MapInfo { + name: "mcp_peripherals", + description: "MCP peripherals", + start: Some(0x0000_4c00_0000), + end: Some(0x0000_4e00_0000), + length: Some(size!(32, MB)), + }, + MapInfo { + name: "element_management_peripherals", + description: "Element management peripherals", + start: Some(0x0000_5000_0000), + end: Some(0x0000_5080_0000), + length: Some(size!(8, MB)), + }, + MapInfo { + name: "system_access_port_translated_to_0x0_4000_0000_to_0x0_7fff_ffff_of_ap_memory_map", + description: "System Access Port. Translated to 0x0_4000_0000 to 0x0_7FFF_FFFF of AP memory map.", + start: Some(0x0000_6000_0000), + end: Some(0x0000_a000_0000), + length: Some(size!(1, GB)), + }, + MapInfo { + name: "system_access_port_translated_to_0x0_0000_0000_to_0x0_3fff_ffff_of_ap_memory_map_with_debug_address_translation_not_enabled_translated_to_0x4_0000_0000_to_0x4_3fff_ffff_of_ap_memory_map_with_debug_address_translation_enabled", + description: "System Access Port. Translated to 0x0_0000_0000 to 0x0_3FFF_FFFF of AP memory map with debug address translation not enabled. Translated to 0x4_0000_0000 to 0x4_3FFF_FFFF of AP memory map with debug address translation enabled.", + start: Some(0x0000_a000_0000), + end: Some(0x0000_e000_0000), + length: Some(size!(1, GB)), + }, + MapInfo { + name: "private_peripheral_bus___internal", + description: "Private peripheral bus - Internal.", + start: Some(0x0000_e000_0000), + end: Some(0x0000_e004_0000), + length: Some(size!(256, KB)), + }, + MapInfo { + name: "private_peripheral_bus___external", + description: "Private peripheral bus - External.", + start: Some(0x0000_e004_0000), + end: Some(0x0000_e010_0000), + length: Some(size!(768, KB)), + }, + MapInfo { + name: "reserved_2", + description: "Reserved 2", + start: Some(0x0000_e010_0000), + end: Some(0x0001_0000_0000), + length: Some(size!(511, MB)), + }, +]; diff --git a/src/specs/morello/sdp_mcp_sub_peripherals_map.rs b/src/specs/morello/sdp_mcp_sub_peripherals_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..a03752810d9abcac57ea8ac87361b3c958b2e045 --- /dev/null +++ b/src/specs/morello/sdp_mcp_sub_peripherals_map.rs @@ -0,0 +1,60 @@ +use crate::specs::common::*; + +pub static MAPINFOS: &'static [MapInfo] = &[ + MapInfo { + name: "refclk_cntctl", + description: "REFCLK CNTCTL", + start: Some(0x0000_4c00_0000), + end: Some(0x0000_4c00_1000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "refclk_cntbase0", + description: "REFCLK CNTBase0", + start: Some(0x0000_4c00_1000), + end: Some(0x0000_4c00_2000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "mcpuart0", + description: "MCPUART0", + start: Some(0x0000_4c00_2000), + end: Some(0x0000_4c00_3000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "mcpuart1", + description: "MCPUART1", + start: Some(0x0000_4c00_3000), + end: Some(0x0000_4c00_4000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "watchdog_sp805", + description: "Watchdog (SP805)", + start: Some(0x0000_4c00_6000), + end: Some(0x0000_4c00_7000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "ap2_mcp_mhu", + description: "AP2 MCP MHU", + start: Some(0x0000_4c40_0000), + end: Some(0x0000_4c41_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap2_mcp_mhu_non_secure_ram", + description: "AP2 MCP MHU Non-secure RAM", + start: Some(0x0000_4c41_0000), + end: Some(0x0000_4c42_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap2_mcp_mhu_secure_ram", + description: "AP2 MCP MHU Secure RAM", + start: Some(0x0000_4c42_0000), + end: Some(0x0000_4c43_0000), + length: Some(size!(64, KB)), + }, +]; diff --git a/src/specs/morello/sdp_mcp_sub_peripherals_scp2_mhu_map.rs b/src/specs/morello/sdp_mcp_sub_peripherals_scp2_mhu_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..499ce459bc7ae1e6031bf68d7e2635ae22a4a5b9 --- /dev/null +++ b/src/specs/morello/sdp_mcp_sub_peripherals_scp2_mhu_map.rs @@ -0,0 +1,25 @@ +use crate::specs::common::*; + +pub static MAPINFOS: &'static [MapInfo] = &[ + MapInfo { + name: "scp2_mcp_message_handling_unit_mhu", + description: "SCP2 MCP Message Handling Unit (MHU)", + start: Some(0x0000_4560_0000), + end: Some(0x0000_4561_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "scp2_mcp_mhu_non_secure_ram", + description: "SCP2 MCP MHU Non-secure RAM", + start: Some(0x0000_4561_0000), + end: Some(0x0000_4562_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "scp2_mcp_mhu_secure_ram", + description: "SCP2 MCP MHU Secure RAM", + start: Some(0x0000_4562_0000), + end: Some(0x0000_4563_0000), + length: Some(size!(64, KB)), + }, +]; diff --git a/src/specs/morello/sdp_scp_map.rs b/src/specs/morello/sdp_scp_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..ad740f0ec94c6b17c0b45b918777a70e61900acb --- /dev/null +++ b/src/specs/morello/sdp_scp_map.rs @@ -0,0 +1,231 @@ +use crate::specs::common::*; + +pub static MAPINFOS: &'static [MapInfo] = &[ + MapInfo { + name: "code_boot_rom", + description: "Code boot ROM", + start: Some(0x0000_0000_0000), + end: Some(0x0000_0080_0000), + length: Some(size!(8, MB)), + }, + MapInfo { + name: "code_tcram", + description: "Code TCRAM", + start: Some(0x0000_0080_0000), + end: Some(0x0000_0100_0000), + length: Some(size!(8, MB)), + }, + MapInfo { + name: "reserved_part_of_scp_soc_expansion_memory_1", + description: "Reserved part of SCP SoC expansion memory 1", + start: Some(0x0000_0100_0000), + end: Some(0x0000_1400_0000), + length: Some(size!(304, MB)), + }, + MapInfo { + name: "tmif_interface", + description: "TMIF interface", + start: Some(0x0000_1400_0000), + end: Some(0x0000_1600_0000), + length: Some(size!(32, MB)), + }, + MapInfo { + name: "reserved_part_of_scp_soc_expansion_memory_2", + description: "Reserved part of SCP SoC expansion memory 2", + start: Some(0x0000_1600_0000), + end: Some(0x0000_2000_0000), + length: Some(size!(160, MB)), + }, + MapInfo { + name: "sram_dtcram", + description: "SRAM DTCRAM", + start: Some(0x0000_2000_0000), + end: Some(0x0000_2002_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "reserved_part_of_scp_soc_expansion_memory_3", + description: "Reserved part of SCP SoC expansion memory 3", + start: Some(0x0000_2100_0000), + end: Some(0x0000_3000_0000), + length: Some(size!(240, MB)), + }, + MapInfo { + // Length: Invalid|64MB + name: "scp_qspi_ahb", + description: "SCP QSPI AHB", + start: Some(0x0000_3000_0000), + end: Some(0x0000_3400_0000), + length: None, + }, + MapInfo { + // Length: Invalid|4KB + name: "scp_qspi_apb", + description: "SCP QSPI APB", + start: Some(0x0000_3400_0000), + end: Some(0x0000_3400_1000), + length: None, + }, + MapInfo { + // Length: Invalid|191MB + name: "reserved_part_of_scp_soc_expansion_memory_4", + description: "Reserved part of SCP SoC expansion memory 4", + start: Some(0x0000_3400_1000), + end: Some(0x0000_3ffe_0000), + length: None, + }, + MapInfo { + name: "scp_pvt_ctrl", + description: "SCP PVT CTRL", + start: Some(0x0000_3ffe_0000), + end: Some(0x0000_3fff_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "reserved_part_of_scp_soc_expansion_memory_5", + description: "Reserved part of SCP SoC expansion memory 5", + start: Some(0x0000_3fff_0000), + end: Some(0x0000_3fff_a000), + length: Some(size!(40, KB)), + }, + MapInfo { + name: "reserved_1", + description: "Reserved 1", + start: Some(0x0000_3fff_a000), + end: Some(0x0000_3fff_b000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "scp_i2c1_pmic", + description: "SCP I2C1 (PMIC)", + start: Some(0x0000_3fff_b000), + end: Some(0x0000_3fff_c000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "scp_i2c2_spd_pcc", + description: "SCP I2C2 (SPD-PCC)", + start: Some(0x0000_3fff_c000), + end: Some(0x0000_3fff_d000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "reserved_part_of_scp_soc_expansion_memory_6", + description: "Reserved part of SCP SoC expansion memory 6", + start: Some(0x0000_3fff_d000), + end: Some(0x0000_3fff_f000), + length: Some(size!(8, KB)), + }, + MapInfo { + name: "scc_registers", + description: "SCC registers", + start: Some(0x0000_3fff_f000), + end: Some(0x0000_4000_0000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "scp_soc_expansion", + description: "SCP SoC expansion", + start: Some(0x0000_4000_0000), + end: Some(0x0000_4400_0000), + length: Some(size!(64, MB)), + }, + MapInfo { + name: "scp_peripherals", + description: "SCP peripherals", + start: Some(0x0000_4400_0000), + end: Some(0x0000_4600_0000), + length: Some(size!(32, MB)), + }, + MapInfo { + name: "mcp_soc_expansion", + description: "MCP SoC expansion", + start: Some(0x0000_4800_0000), + end: Some(0x0000_4c00_0000), + length: Some(size!(64, MB)), + }, + MapInfo { + name: "memory_element_0_configuration", + description: "Memory element 0 configuration", + start: Some(0x0000_4e00_0000), + end: Some(0x0000_4e01_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "memory_element_0_manager", + description: "Memory element 0 manager", + start: Some(0x0000_4e01_0000), + end: Some(0x0000_4e02_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "memory_element_0_sensor_group", + description: "Memory element 0 sensor group", + start: Some(0x0000_4e02_0000), + end: Some(0x0000_4e03_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "memory_element_1_configuration", + description: "Memory element 1 configuration", + start: Some(0x0000_4e10_0000), + end: Some(0x0000_4e11_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "memory_element_1_manager", + description: "Memory element 1 manager", + start: Some(0x0000_4e11_0000), + end: Some(0x0000_4e12_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "memory_element_1_sensor_group", + description: "Memory element 1 sensor group", + start: Some(0x0000_4e12_0000), + end: Some(0x0000_4e13_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "element_management_peripherals", + description: "Element management peripherals", + start: Some(0x0000_5000_0000), + end: Some(0x0000_5080_0000), + length: Some(size!(8, MB)), + }, + MapInfo { + name: "system_access_port_translated_to_0x0_4000_0000_to_0x0_7fff_ffff_of_ap_memory_map", + description: "System Access Port. Translated to 0x0_4000_0000 to 0x0_7FFF_FFFF of AP memory map.", + start: Some(0x0000_6000_0000), + end: Some(0x0000_a000_0000), + length: Some(size!(1, GB)), + }, + MapInfo { + name: "system_access_port_translated_to_0x0_0000_0000_to_0x0_3fff_ffff_of_ap_memory_map_with_debug_address_translation_not_enabled_translated_to_0x4_0000_0000_to_0x4_3fff_ffff_of_ap_memory_map_with_debug_address_translation_enabled", + description: "System Access Port. Translated to 0x0_0000_0000 to 0x0_3FFF_FFFF of AP memory map with debug address translation not enabled. Translated to 0x4_0000_0000 to 0x4_3FFF_FFFF of AP memory map with debug address translation enabled.", + start: Some(0x0000_a000_0000), + end: Some(0x0000_e000_0000), + length: Some(size!(1, GB)), + }, + MapInfo { + name: "private_peripheral_bus___internal", + description: "Private peripheral bus - Internal.", + start: Some(0x0000_e000_0000), + end: Some(0x0000_e004_0000), + length: Some(size!(256, KB)), + }, + MapInfo { + name: "private_peripheral_bus___external", + description: "Private peripheral bus - External.", + start: Some(0x0000_e004_0000), + end: Some(0x0000_e010_0000), + length: Some(size!(768, KB)), + }, + MapInfo { + name: "reserved_2", + description: "Reserved 2", + start: Some(0x0000_e010_0000), + end: Some(0x0001_0000_0000), + length: Some(size!(511, MB)), + }, +]; diff --git a/src/specs/morello/sdp_scp_sub_peripherals_map.rs b/src/specs/morello/sdp_scp_sub_peripherals_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..0cec73843465907bceb7fdd13fc1c2d7acb291ac --- /dev/null +++ b/src/specs/morello/sdp_scp_sub_peripherals_map.rs @@ -0,0 +1,102 @@ +use crate::specs::common::*; + +pub static MAPINFOS: &'static [MapInfo] = &[ + MapInfo { + name: "refclk_cntctl", + description: "REFCLK CNTCTL", + start: Some(0x0000_4400_0000), + end: Some(0x0000_4400_1000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "refclk_cntbase0", + description: "REFCLK CNTBase0", + start: Some(0x0000_4400_1000), + end: Some(0x0000_4400_2000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "scpuart", + description: "SCPUART", + start: Some(0x0000_4400_2000), + end: Some(0x0000_4400_3000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "watchdog_sp805", + description: "Watchdog (SP805)", + start: Some(0x0000_4400_6000), + end: Some(0x0000_4400_7000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "cs_cntcontrol", + description: "CS CNTCONTROL", + start: Some(0x0000_4400_a000), + end: Some(0x0000_4400_b000), + length: Some(size!(4, KB)), + }, + MapInfo { + name: "refclk_general_timer_control", + description: "REFCLK general timer control", + start: Some(0x0000_4410_0000), + end: Some(0x0000_4411_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "cluster_0_time_frame", + description: "Cluster 0 time frame", + start: Some(0x0000_4411_0000), + end: Some(0x0000_4412_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "cluster_1_time_frame", + description: "Cluster 1 time frame", + start: Some(0x0000_4412_0000), + end: Some(0x0000_4413_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "ap2scp_message_handling_unit_mhu", + description: "AP2SCP Message Handling Unit (MHU)", + start: Some(0x0000_4500_0000), + end: Some(0x0000_4502_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "ap2scp_mhu_non_secure_ram", + description: "AP2SCP MHU Non-secure RAM", + start: Some(0x0000_452c_0000), + end: Some(0x0000_452e_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "ap2scp_mhu_secure_ram", + description: "AP2SCP MHU Secure RAM", + start: Some(0x0000_4540_0000), + end: Some(0x0000_4542_0000), + length: Some(size!(128, KB)), + }, + MapInfo { + name: "scp2mch_mhu", + description: "SCP2MCH MHU", + start: Some(0x0000_4560_0000), + end: Some(0x0000_4561_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "scp2mcp_mhu_non_secure_ram", + description: "SCP2MCP MHU Non-secure RAM", + start: Some(0x0000_4561_0000), + end: Some(0x0000_4562_0000), + length: Some(size!(64, KB)), + }, + MapInfo { + name: "scp2mcp_mhu_secure_ram", + description: "SCP2MCP MHU Secure RAM", + start: Some(0x0000_4562_0000), + end: Some(0x0000_4563_0000), + length: Some(size!(64, KB)), + }, +];