compiler/
kernel/
lib/
scripts/
seed/
sublime/
test/
acceptance/
boot/
bootstrap/
kernel/
dispatchcheck.rad
4.8 KiB
machine.ras
683 B
root.rad
1.8 KiB
run
1.5 KiB
service.rad
155 B
cycles/
dispatch/
loader/
mmio/
modules/
native/
packages/
pages/
runtime/
scheduling/
shared/
slots/
smp/
sync/
termination/
tests/
trap/
run
2.7 KiB
runner.rad
10.3 KiB
vim/
.gitignore
336 B
.gitsigners
112 B
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
10.2 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
551 B
test/bootstrap/kernel/dispatchcheck.rad
raw
| 1 | //! Native root construction, exit, and continued resource authority. |
| 2 | use kernel::abi; |
| 3 | use kernel::boot; |
| 4 | use kernel::registry; |
| 5 | use kernel::domains; |
| 6 | use kernel::capability; |
| 7 | use kernel::pages; |
| 8 | use kernel::budgets; |
| 9 | use kernel::dispatch; |
| 10 | use kernel::calls; |
| 11 | use kernel::events; |
| 12 | use kernel::sync; |
| 13 | use kernel::startup; |
| 14 | use kernel::devices; |
| 15 | use kernel::interrupts; |
| 16 | |
| 17 | /// Initial root identity retained by the terminal event. |
| 18 | unsafe static ROOT: abi::Ref = undefined; |
| 19 | /// Surviving controller domain with inherited resource authority. |
| 20 | unsafe static CONTROLLER: abi::Ref = undefined; |
| 21 | /// Image capability installed in the controller's own table. |
| 22 | unsafe static IMAGE: abi::Handle = undefined; |
| 23 | /// Current kernel package-state table. |
| 24 | fn kernelGp() -> u64; |
| 25 | /// Controller entry address. |
| 26 | fn completion() -> u64; |
| 27 | /// Signal successful completion to the emulator. |
| 28 | fn finish(); |
| 29 | /// Map an assembly-compatible physical byte address. |
| 30 | fn memory(address: u64) -> *mut u8; |
| 31 | |
| 32 | /// Construct root from the boot catalog and give its child a later CPU window. |
| 33 | export unsafe fn setup() { |
| 34 | let image = registry::find(®istry::STORE, &"loaded"[..]) else panic "missing boot user package"; |
| 35 | let service = registry::find(®istry::STORE, &"service"[..]) else panic "missing boot service package"; |
| 36 | set ROOT = try! startup::create(&boot::PLATFORM, image, service); |
| 37 | assert ROOT.index == 0; |
| 38 | let mut root = try! domains::get(&domains::STORE, ROOT); |
| 39 | let self = try! abi::handle(abi::Kind::Domain, abi::Ref { index: 0, generation: root.memory.table.slots[0].generation }); |
| 40 | assert (try! abi::decode(root.events)).object.index == 1; |
| 41 | let executable = try! registry::install(®istry::STORE, &mut root.memory.table, image); |
| 42 | let childHandle = try! domains::create(&mut domains::STORE, &mut pages::STORE.backings, |
| 43 | ®istry::STORE, &mut root.memory.table, self, executable); |
| 44 | set CONTROLLER = (try! capability::get(&root.memory.table, childHandle)).object; |
| 45 | let mut child = try! domains::get(&domains::STORE, CONTROLLER); |
| 46 | let inherited = domains::MANAGEMENT_RIGHTS | abi::CREATE | abi::ALLOCATE; |
| 47 | let authority = try! calls::invoke(ROOT, 10, &[*childHandle, *childHandle, inherited as u64, 0], 0); |
| 48 | assert service.index == 3 and image.index == 2; |
| 49 | set IMAGE = try! registry::install(®istry::STORE, &mut child.memory.table, service); |
| 50 | try! domains::reparent(&mut domains::STORE, &root.memory.table, self, childHandle); |
| 51 | set domains::STORE.records[CONTROLLER.index].state = domains::Lifecycle::Active; |
| 52 | let frame = &mut domains::STORE.contexts[child.initial.index].frame; |
| 53 | set frame.pc = completion(); set frame.status = 0x1880; |
| 54 | set frame.registers[2] = domains::STORE.contexts[child.initial.index].kernelStack.end; |
| 55 | set frame.registers[3] = kernelGp(); |
| 56 | let now = dispatch::clock(); |
| 57 | let index = 2 + devices::STORE.count + interrupts::STORE.count; |
| 58 | let budget = try! abi::handle(abi::Kind::Budget, abi::Ref { index, generation: root.memory.table.slots[index].generation }); |
| 59 | let window = try! budgets::query(&budgets::STORE, &root.memory.table, budget); |
| 60 | let start = window.start; |
| 61 | let later = try! budgets::split(&mut budgets::STORE, &mut root.memory.table, budget, start + 10000000, now); |
| 62 | let running = try! budgets::bind(&mut budgets::STORE, &domains::STORE, &mut root.memory.table, |
| 63 | budgets::Binding { budget, domain: self, context: root.initial }, now); |
| 64 | let transferred = try! budgets::bind(&mut budgets::STORE, &domains::STORE, &mut root.memory.table, |
| 65 | budgets::Binding { budget: later, domain: childHandle, context: child.initial }, now); |
| 66 | } |
| 67 | |
| 68 | /// Root exit leaves the survivor able to allocate and create new domains. |
| 69 | export unsafe fn verify() { |
| 70 | let guard = sync::enter(); |
| 71 | let mut child = try! domains::get(&domains::STORE, CONTROLLER); |
| 72 | let terminal = try! events::pop(&mut child.memory.ring) else panic "missing root exit"; |
| 73 | assert terminal.kind == events::CHILD_EXIT and terminal.code == 0 and terminal.value == abi::id(ROOT); |
| 74 | assert child.state == domains::Lifecycle::Active and child.parent == nil; |
| 75 | try! events::refresh(&mut domains::STORE.events, CONTROLLER, &child.memory.ring); |
| 76 | sync::leave(guard); |
| 77 | let page = abi::Handle(try! calls::synchronized(CONTROLLER, 30, &[0, 1, 0, 0], dispatch::clock())); |
| 78 | let domain = abi::Handle(try! calls::synchronized(CONTROLLER, 20, &[0, *IMAGE, 0, 0], dispatch::clock())); |
| 79 | let checking = sync::enter(); |
| 80 | let allocated = try! capability::get(&child.memory.table, page); |
| 81 | assert (try! pages::get(&pages::STORE, allocated.object)).count == 1; |
| 82 | let object = (try! capability::get(&child.memory.table, domain)).object; |
| 83 | let created = try! domains::get(&domains::STORE, object); |
| 84 | assert created.creator == CONTROLLER and created.parent == CONTROLLER; |
| 85 | assert created.state == domains::Lifecycle::Pending; |
| 86 | sync::leave(checking); |
| 87 | finish(); |
| 88 | } |