[wip] caps work
This commit is contained in:
		
							parent
							
								
									babd5caaab
								
							
						
					
					
						commit
						42f0efcba9
					
				|  | @ -425,6 +425,16 @@ impl UntypedCapability { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Endpoints support all 10 IPC variants (see COMP9242 slides by Gernot)
 | ||||||
|  | impl EndpointCapability {} | ||||||
|  | // Notifications support NBSend (Signal), Wait and NBWait (Poll) (see COMP9242 slides by Gernot)
 | ||||||
|  | // Other objects support only Call() (see COMP9242 slides by Gernot)
 | ||||||
|  | // Appear as (kernel-implemented) servers
 | ||||||
|  | //     • Each has a kernel-defined protocol
 | ||||||
|  | //         • operations encoded in message tag
 | ||||||
|  | //         • parameters passed in message words
 | ||||||
|  | //     • Mostly hidden behind “syscall” wrappers
 | ||||||
|  | 
 | ||||||
| // * Capability slots: 16 bytes of memory per slot (exactly one capability). --?
 | // * Capability slots: 16 bytes of memory per slot (exactly one capability). --?
 | ||||||
| // CapNode describes `a given number of capability slots` with `a given guard`
 | // CapNode describes `a given number of capability slots` with `a given guard`
 | ||||||
| // of `a given guard size` bits.
 | // of `a given guard size` bits.
 | ||||||
|  | @ -505,6 +515,16 @@ pub enum DerivationTreeError { | ||||||
|     InvalidPrev, |     InvalidPrev, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // In seL4, the MDB is stored as a doubly-linked list, representing the **preorder-DFS** through
 | ||||||
|  | // the hierarchy of capabilities. This data structure allows easy insertion of a capability
 | ||||||
|  | // given its immediate ancestor or a copy, and easy checking for existence of copies and descendants.
 | ||||||
|  | // But when no relations are known beforehand, finding the position to place a new capability
 | ||||||
|  | // requires a O(n) linear scan through the list, as does finding ancestors and descendants
 | ||||||
|  | // of a capability given just the capability’s value. This operation is performed in
 | ||||||
|  | // the non-preemptable kernel, creating a scheduling hole that is problematic for real-time applications.
 | ||||||
|  | // To reduce the complexity of operations described above, we replace the MDB’s linked list with
 | ||||||
|  | // a more suitable search data structure.
 | ||||||
|  | // -- nevill-master-thesis Using Capabilities for OS Resource Management
 | ||||||
| impl DerivationTreeNode { | impl DerivationTreeNode { | ||||||
|     fn empty() -> Self { |     fn empty() -> Self { | ||||||
|         Self(LocalRegisterCopy::new(0)) |         Self(LocalRegisterCopy::new(0)) | ||||||
|  | @ -594,11 +614,13 @@ impl CapTableEntry { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // @note src and dest are swapped here, compared to seL4 api
 |  | ||||||
| /* | /* | ||||||
| struct CapNodePath { | struct CapNodePath { | ||||||
|     index: u32, |     /// Index contains `depth` lowermost bits of the path.
 | ||||||
|     depth: u32, |     index: u64, | ||||||
|  |     /// Depth specifies the remaining amount of bits left to traverse in the path.
 | ||||||
|  |     /// Once depth reaches zero, the selected CapNode slot is the final target.
 | ||||||
|  |     depth: usize, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct CapNodeRootedPath { | struct CapNodeRootedPath { | ||||||
|  | @ -608,19 +630,22 @@ struct CapNodeRootedPath { | ||||||
| 
 | 
 | ||||||
| // @todo just use CapNodeCap
 | // @todo just use CapNodeCap
 | ||||||
| //struct CapNodeConfig { <-- for each CapTable we would need these..
 | //struct CapNodeConfig { <-- for each CapTable we would need these..
 | ||||||
| //    guard: u32,
 | //    guard: u64,
 | ||||||
| //    guard_size: u32,
 | //    guard_bits: usize,
 | ||||||
| //}
 | //}
 | ||||||
| 
 | 
 | ||||||
|  | // @note src and dest are swapped here, compared to seL4 api
 | ||||||
| impl CapNode { | impl CapNode { | ||||||
|  |     // Derives a capability into a new, less powerful one, with potentially added Badge.
 | ||||||
|     fn mint( |     fn mint( | ||||||
|         src: CapNodeRootedPath, |         src: CapNodeRootedPath, // can be just CapNodePath since it's relative (is it?) to this CapNode.
 | ||||||
|         dest: CapNodePath, |         dest: CapNodePath, | ||||||
|         rights: CapRights, |         rights: CapRights, | ||||||
|         badge: Badge, |         badge: Badge, | ||||||
|     ) -> Result<(), CapError> { |     ) -> Result<(), CapError> { | ||||||
|         unimplemented!(); |         unimplemented!(); | ||||||
|     } |     } | ||||||
|  |     // [wip] is copy a derivation too?
 | ||||||
|     fn copy(src: CapNodeRootedPath, dest: CapNodePath, rights: CapRights) -> Result<(), CapError> { |     fn copy(src: CapNodeRootedPath, dest: CapNodePath, rights: CapRights) -> Result<(), CapError> { | ||||||
|         unimplemented!(); |         unimplemented!(); | ||||||
|     } |     } | ||||||
|  | @ -645,7 +670,7 @@ impl CapNode { | ||||||
|     fn revoke(path: CapNodePath) -> Result<(), CapError> { |     fn revoke(path: CapNodePath) -> Result<(), CapError> { | ||||||
|         unimplemented!(); |         unimplemented!(); | ||||||
|     } |     } | ||||||
|     fn save_caller(r#where: CapNodePath) -> Result<(), CapError> { |     fn save_caller(r#where: CapNodePath) -> Result<(), CapError> { // save_reply_cap() in sel4
 | ||||||
|         unimplemented!(); |         unimplemented!(); | ||||||
|     } |     } | ||||||
|     fn cancel_badged_sends(path: CapNodePath) -> Result<(), CapError> { |     fn cancel_badged_sends(path: CapNodePath) -> Result<(), CapError> { | ||||||
|  |  | ||||||
|  | @ -61,6 +61,8 @@ enum MemoryKind { | ||||||
| // Boot code reserves kernel memory and initial mapping allocations (4 pages probably - on rpi3? should be platform-dependent).
 | // Boot code reserves kernel memory and initial mapping allocations (4 pages probably - on rpi3? should be platform-dependent).
 | ||||||
| // The rest is converted to untypeds with appropriate kind and given away to start thread.
 | // The rest is converted to untypeds with appropriate kind and given away to start thread.
 | ||||||
| 
 | 
 | ||||||
|  | // Untyped.retype() derives cap to a typed cap (derivation tree must be maintained)
 | ||||||
|  | 
 | ||||||
| trait Untyped { | trait Untyped { | ||||||
|     // Uses T::SIZE_BITS to properly size the resulting object
 |     // Uses T::SIZE_BITS to properly size the resulting object
 | ||||||
|     // in some cases size_bits must be passed as argument though...
 |     // in some cases size_bits must be passed as argument though...
 | ||||||
|  | @ -135,13 +137,13 @@ struct Page {} | ||||||
| impl Page { | impl Page { | ||||||
|     // VirtSpace-like interface.
 |     // VirtSpace-like interface.
 | ||||||
|     /// Get the physical address of the underlying frame.
 |     /// Get the physical address of the underlying frame.
 | ||||||
|     fn get_address() -> Result<PhysAddr>; |     fn get_address() -> Result<PhysAddr> { todo!() } | ||||||
|     fn map(virt_space: VirtSpace/*Cap*/, vaddr: VirtAddr, rights: CapRights, attr: VMAttributes) -> Result<()>; |     fn map(virt_space: VirtSpace/*Cap*/, vaddr: VirtAddr, rights: CapRights, attr: VMAttributes) -> Result<()> { todo!() } | ||||||
|     /// Changes the permissions of an existing mapping.
 |     /// Changes the permissions of an existing mapping.
 | ||||||
|     fn remap(virt_space: VirtSpace/*Cap*/, rights: CapRights, attr: VMAttributes) -> Result<()>; |     fn remap(virt_space: VirtSpace/*Cap*/, rights: CapRights, attr: VMAttributes) -> Result<()> { todo!() } | ||||||
|     fn unmap() -> Result<()>; |     fn unmap() -> Result<()> { todo!() } | ||||||
|     // MMIO space.
 |     // MMIO space.
 | ||||||
|     fn map_io(iospace: IoSpace/*Cap*/, rights: CapRights, ioaddr: VirtAddr) -> Result<()>; |     fn map_io(iospace: IoSpace/*Cap*/, rights: CapRights, ioaddr: VirtAddr) -> Result<()> { todo!() } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PageCacheManagement for Page { | impl PageCacheManagement for Page { | ||||||
|  | @ -167,8 +169,8 @@ impl PageCacheManagement for Page { | ||||||
| struct PageTable {} | struct PageTable {} | ||||||
| 
 | 
 | ||||||
| impl PageTable { | impl PageTable { | ||||||
|     fn map(virt_space: VirtSpace/*Cap*/, vaddr: VirtAddr, attr: VMAttributes) -> Result<()>; |     fn map(virt_space: VirtSpace/*Cap*/, vaddr: VirtAddr, attr: VMAttributes) -> Result<()> { todo!() } | ||||||
|     fn unmap() -> Result<()>; |     fn unmap() -> Result<()> { todo!() } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // AArch64 - probably just impl some Mapping trait for these "structs"?
 | // AArch64 - probably just impl some Mapping trait for these "structs"?
 | ||||||
|  | @ -176,16 +178,16 @@ impl PageTable { | ||||||
| struct PageDirectory {} | struct PageDirectory {} | ||||||
| 
 | 
 | ||||||
| impl PageDirectory { | impl PageDirectory { | ||||||
|     fn map(pud: PageUpperDirectory/*Cap*/, vaddr: VirtAddr, attr: VMAttributes) -> Result<()>; |     fn map(pud: PageUpperDirectory/*Cap*/, vaddr: VirtAddr, attr: VMAttributes) -> Result<()> { todo!() } | ||||||
|     fn unmap() -> Result<()>; |     fn unmap() -> Result<()> { todo!() } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // L1 table
 | // L1 table
 | ||||||
| struct PageUpperDirectory {} | struct PageUpperDirectory {} | ||||||
| 
 | 
 | ||||||
| impl PageUpperDirectory { | impl PageUpperDirectory { | ||||||
|     fn map(pgd: PageGlobalDirectory/*Cap*/, vaddr: VirtAddr, attr: VMAttributes) -> Result<()>; |     fn map(pgd: PageGlobalDirectory/*Cap*/, vaddr: VirtAddr, attr: VMAttributes) -> Result<()> { todo!() } | ||||||
|     fn unmap() -> Result<()>; |     fn unmap() -> Result<()> { todo!() } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // L0 table
 | // L0 table
 | ||||||
|  | @ -195,17 +197,17 @@ struct PageGlobalDirectory { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PageCacheManagement for PageGlobalDirectory { | impl PageCacheManagement for PageGlobalDirectory { | ||||||
|     fn clean_data(start_offset: usize, end_offset: usize) -> _ { |     fn clean_data(start_offset: usize, end_offset: usize) -> ! { | ||||||
|         todo!() |         todo!() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn clean_invalidate_data(start_offset: usize, end_offset: usize) -> _ { |     fn clean_invalidate_data(start_offset: usize, end_offset: usize) -> ! { | ||||||
|         todo!() |         todo!() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn invalidate_data(start_offset: usize, end_offset: usize) -> _ { todo!() } |     fn invalidate_data(start_offset: usize, end_offset: usize) -> ! { todo!() } | ||||||
| 
 | 
 | ||||||
|     fn unify_instruction_cache(start_offset: usize, end_offset: usize) -> _ { |     fn unify_instruction_cache(start_offset: usize, end_offset: usize) -> ! { | ||||||
|         todo!() |         todo!() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -274,7 +276,87 @@ struct TCB { | ||||||
|     // Thread.read_registers(cap, ... call for example.
 |     // Thread.read_registers(cap, ... call for example.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Thread for TCB {} | impl Thread for TCB { | ||||||
|  |     fn configure(fault_endpoint: _, cap_space_root: _, cap_space_root_data: _, virt_space_root: _, ipc_buffer_frame: _, ipc_buffer_offset: usize) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_space(fault_endpoint: _, cap_space_root: _, cap_space_root_data: _, virt_space_root: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn configure_single_stepping(bp_num: u16, _: _) { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_breakpoint(bp_num: u16) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_breakpoint(bp_num: u16, bp: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn unset_breakpoint(bp_num: u16) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn suspend() -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn resume() -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn copy_registers(source: TCB, suspend_source: bool, resume_target: bool, transfer_frame_regs: bool, transfer_integer_regs: bool, arch_flags: u8) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn read_registers(suspend_source: bool, arch_flags: u8, num_regs: u16, register_context: &mut _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn write_registers(resume_target: bool, arch_flags: u8, num_regs: u16, register_context: &_) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn bind_notification(notification: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn unbind_notification() -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_priority(authority: TCB, priority: u32) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_mc_priority(authority: TCB, mcp: u32) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_sched_params(authority: TCB, mcp: u32, priority: u32) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_affinity(affinity: u64) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_ipc_buffer(ipc_buffer_frame: _, ipc_buffer_offset: usize) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_tls_base(tls_base: usize) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_ept_root(eptpml: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | } | ||||||
| impl KernelObject for TCB { | impl KernelObject for TCB { | ||||||
|     const SIZE_BITS: usize = 12; |     const SIZE_BITS: usize = 12; | ||||||
| } | } | ||||||
|  | @ -320,8 +402,53 @@ trait API { | ||||||
|     // Plus some debugging calls...
 |     // Plus some debugging calls...
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct Kernel {} // Nucleus, actually...
 | struct Nucleus {} | ||||||
| impl API for Kernel {} | 
 | ||||||
|  | impl API for Nucleus { | ||||||
|  |     fn send(cap: _, msg_info: _) { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn recv(src: _, reply: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn call(cap: _, msg_info: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn reply(msg_info: _) { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn nb_send(dest: _, msg_info: _) { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn reply_recv(src: _, reply: _, msg_info: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn nb_send_recv(dest: _, msg_info: _, src: _, reply: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn nb_recv(src: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn nb_send_wait(cap: _, msg_info: _, src: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn wait(src: _) -> _ { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn r#yield() { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| trait DomainSet { | trait DomainSet { | ||||||
|     // ??
 |     // ??
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue