Add cnode tag#539
Conversation
This adds a smaller CNode as PD's cspace and moves the original Microkit resource CNode to the root's first slot, as this makes the CSpace management more flexible. The changes are: - size of root CNode: 64 - size of Microkit CNode: 1024 -> 512 - guard size of root CNode: 0 - guard size of Microkit CNode: seL4_WordBits - 6 - 9 This also fixes the capability creation for shared VSpace and CSpace. Signed-off-by: Terry Bai <tianyi.bai@unsw.edu.au>
This adds rules for QEMU tests on x86 and enables the 'capdl_spec.json' file generation for analysis. Signed-off-by: Terry Bai <tianyi.bai@unsw.edu.au>
This checks if people try to place extra caps in slot 0, which is reserved for Microkit CNode, and adds a test case for it. Signed-off-by: Terry Bai <tianyi.bai@unsw.edu.au>
This adds 'cnode' tag in SDF, providing a way for users to define custom-sized CNodes to be shared among PDs. One typical use case is to pass capabilities from one PD to another. Custom CNodes can be mapped into PDs via 'cap_cspace' with target 'cnode_name' specified, and other CapMapType fails with 'cnode_name' specified. Signed-off-by: Terry Bai <tianyi.bai@unsw.edu.au>
This adds a few test cases for checking if invalid cnode tags or cspace mapping fails as expected. Signed-off-by: Terry Bai <tianyi.bai@unsw.edu.au>
| named_object.name.as_ref().unwrap() | ||
| ); | ||
| }; | ||
| if let Some(src_pd) = cap_map.pd { |
There was a problem hiding this comment.
I think this is assignment within if-check, that's extremely confusing.
I would either make temp vars outside the if-checks, or don't bother with them. cap_map.pd and cap_map.cnode are short and clear enough.
| capdl_util_make_cnode_cap(pd_src_shadow_cspace.cspace, 0, guard_size) | ||
| } | ||
| }; | ||
| } else if let Some(src_cnode) = cap_map.cnode { |
There was a problem hiding this comment.
It makes no logical sense that this would be an else-if instead of an if, as you're checking different fields. From a higher level it of course makes perfect sense, as they are mutually exclusive.
However, as you already wrap them in an Option, would it make more sense in Rust to have one shared src field of different types and do a switch on type instead?
| let pd_guard_size = kernel_config.cap_address_bits - cnode.size_bits as u64 - PD_ROOT_CAP_BITS as u64; | ||
| let cnode_cap_self_ref = capdl_util_make_cnode_cap(cnode_obj_id, 0, pd_guard_size.try_into().unwrap()); |
There was a problem hiding this comment.
Below it does it without the weird try_into/unwrap combo. Maybe use as u8 above like is done below?
Perhaps add something like an capdl_util_make_sub_cnode_cap() function and add that to capdl util? Then you can call that everywhere and keep this code in one place.
Edit: I realised that capdl util probably doesn't know about kernel_config.cap_address_bits and PD_ROOT_CAP_BITS, so it can't be there and must be a less generic, more local make_sub_cnode_cap().
| let pd_guard_size = kernel_config.cap_address_bits - *size_bits as u64 - PD_ROOT_CAP_BITS as u64; | ||
| let cnode_cap = capdl_util_make_cnode_cap(*cnode_obj_id, 0, pd_guard_size.try_into().unwrap()); |
There was a problem hiding this comment.
Maybe replace with a capdl_util_make_sub_cnode_cap() call here too.
However, I'm not sure you want to do this unconditionally, because the user may want to manage a 2-level sub-CSpace themselves. Gobbling all remaining bits up as guard would make this impossible.
I agree that this should be the default behaviour, but I think that it should also be possible for users to specify the guard size (and perhaps value) manually.
So the the guard size would be cap_address_bits - PD_ROOT_CAP_BITS - size_bits - user_guard_size, where the latter is default 0 and the result must be >= 0.
If adding capdl_util_make_sub_cnode_cap(), you would call it with size_bits + user_guard_size instead of just size_bits.
| return Err(value_error( | ||
| xml_sdf, | ||
| node, | ||
| format!("invalid paramter 'cnode_name' for target CapMapType"), |
| return Err(value_error( | ||
| xml_sdf, | ||
| node, | ||
| format!("Either 'pd' and 'cnode_name' should be specified"), |
There was a problem hiding this comment.
See, that's why I prefer a generic src instead of one attribute per source type. What you're doing here doesn't scale very well, and it has unclear semantics by design, making things harder for the user instead of easier.
This PR adds CNode tag to SDF, providing a way for users to define custom CNodes and share among PDs. One of the use cases is to pass capabilities from one PD to another, e.g., ACPI driver passes CNode containing memory window untypeds to PCIe driver so it can dynamically allocate and map memory regions for device drivers.
This PR is based on switch-to-two-level-cnodes PR as it should be getting merged soon.