compiler/
kernel/
lib/
scripts/
seed/
sublime/
test/
acceptance/
boot/
bootstrap/
cycles/
dispatch/
loader/
mmio/
kernel/
dispatchcheck.rad
7.1 KiB
machine.ras
683 B
spin.rad
2.0 KiB
native/
packages/
pages/
runtime/
scheduling/
shared/
slots/
smp/
support/
sync/
termination/
tests/
trap/
package-golden
1.6 KiB
run
3.1 KiB
runner.rad
10.5 KiB
vim/
.gitignore
336 B
.gitsigners
112 B
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
9.2 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
662 B
test/mmio/kernel/dispatchcheck.rad
raw
| 1 | //! Native fixed-width MMIO and authority rejection before register access. |
| 2 | use std::mem; |
| 3 | use kernel::abi; |
| 4 | use kernel::slots; |
| 5 | use kernel::backing; |
| 6 | use kernel::pages; |
| 7 | use kernel::capability; |
| 8 | use kernel::registry; |
| 9 | use kernel::loader; |
| 10 | use kernel::domains; |
| 11 | use kernel::budgets; |
| 12 | use kernel::dispatch; |
| 13 | use kernel::boot; |
| 14 | use kernel::events; |
| 15 | use kernel::sync; |
| 16 | use kernel::dispatchinput; |
| 17 | use kernel::devices; |
| 18 | use kernel::platform; |
| 19 | |
| 20 | /// Register storage exposed only through a synthetic Device capability. |
| 21 | static REGISTERS: [u64; 512] = [0; 512]; |
| 22 | |
| 23 | /// Bootstrap creation, allocation, and budget authority. |
| 24 | unsafe static TABLE: capability::Table = undefined; |
| 25 | /// Child domain identities retained by terminal events. |
| 26 | unsafe static CHILDREN: [abi::Ref; 9] = undefined; |
| 27 | /// Surviving event receiver and native completion checker. |
| 28 | unsafe static PARENT: abi::Ref = undefined; |
| 29 | /// Map a validated physical page. |
| 30 | fn memory(address: u64) -> *mut u8; |
| 31 | /// Current kernel package-state base. |
| 32 | fn kernelGp() -> u64; |
| 33 | /// Native entry for the completion checker. |
| 34 | fn completion() -> u64; |
| 35 | /// Signal successful completion to the machine fixture. |
| 36 | fn finish(); |
| 37 | |
| 38 | /// Give each child a disjoint window, followed by the surviving parent. |
| 39 | export unsafe fn setup() { |
| 40 | let pending = try! slots::reserve(&mut domains::STORE.slots[..]); |
| 41 | let owner = try! slots::commit(&mut domains::STORE.slots[..], pending); |
| 42 | capability::initialize(&mut TABLE, owner); |
| 43 | try! backing::registerDomain(&mut pages::STORE.backings, owner); |
| 44 | let authority = try! capability::install(&mut TABLE, capability::Entry { |
| 45 | kind: abi::Kind::Domain, object: owner, rights: abi::Rights(abi::CREATE | abi::ALLOCATE), |
| 46 | }); |
| 47 | let source = try! pages::allocate(&mut pages::STORE, &mut TABLE, authority, (dispatchinput::INPUT.len as u64 + 4095) / 4096); |
| 48 | let page = try! pages::get(&pages::STORE, (try! capability::get(&TABLE, source)).object); |
| 49 | let bytes = @sliceOf(memory(page.base), page.count * 4096); |
| 50 | let length = try! mem::copy(&mut bytes[..], &dispatchinput::INPUT[..]); |
| 51 | let image = try! loader::load(&mut loader::STATE, &mut pages::STORE, &mut registry::STORE, &mut TABLE, |
| 52 | loader::Request { authority, source, offset: 0, length: length as u64 }); |
| 53 | let parentHandle = try! domains::create(&mut domains::STORE, &mut pages::STORE.backings, ®istry::STORE, &mut TABLE, authority, image); |
| 54 | set PARENT = (try! capability::get(&TABLE, parentHandle)).object; |
| 55 | let parent = try! domains::get(&domains::STORE, PARENT); |
| 56 | set domains::STORE.records[PARENT.index].state = domains::Lifecycle::Active; |
| 57 | set domains::STORE.contexts[parent.initial.index].frame.pc = completion(); |
| 58 | set domains::STORE.contexts[parent.initial.index].frame.status = 0x1880; |
| 59 | set domains::STORE.contexts[parent.initial.index].frame.registers[2] = domains::STORE.contexts[parent.initial.index].kernelStack.end; |
| 60 | set domains::STORE.contexts[parent.initial.index].frame.registers[3] = kernelGp(); |
| 61 | let scratch = devices::STORE.count; |
| 62 | set devices::STORE.regions[scratch] = { |
| 63 | kind: platform::Kind::Uart, |
| 64 | info: { base: (&mut REGISTERS[0]) as u64, size: 4096 }, |
| 65 | rights: abi::Rights(abi::READ | abi::WRITE | abi::GRANT | abi::TRANSFER), |
| 66 | }; |
| 67 | set devices::STORE.count += 1; |
| 68 | let mut clockDevice: u32 = 0; |
| 69 | let mut finish: u32 = 0; |
| 70 | for i in 0..scratch { |
| 71 | if devices::STORE.regions[i].kind == platform::Kind::Clint { |
| 72 | set clockDevice = i; |
| 73 | } |
| 74 | if devices::STORE.regions[i].kind == platform::Kind::Finish { |
| 75 | set finish = i; |
| 76 | } |
| 77 | } |
| 78 | let mut handles: [abi::Handle; 9] = undefined; |
| 79 | let mut contexts: [abi::Ref; 9] = undefined; |
| 80 | for i in 0..9 { |
| 81 | let handle = try! domains::create(&mut domains::STORE, &mut pages::STORE.backings, ®istry::STORE, &mut TABLE, authority, image); |
| 82 | let object = (try! capability::get(&TABLE, handle)).object; |
| 83 | let mut child = try! domains::get(&domains::STORE, object); |
| 84 | set CHILDREN[i] = object; |
| 85 | set handles[i] = handle; |
| 86 | set contexts[i] = child.initial; |
| 87 | try! domains::reparent(&mut domains::STORE, &TABLE, handle, parentHandle); |
| 88 | let stack = try! pages::allocate(&mut pages::STORE, &mut TABLE, authority, 1); |
| 89 | let granted = try! pages::grant(&mut pages::STORE, &TABLE, &mut child.memory.table, stack, (abi::READ | abi::WRITE) as u64); |
| 90 | let storage = try! pages::get(&pages::STORE, (try! capability::get(&TABLE, stack)).object); |
| 91 | let mut region = scratch; |
| 92 | if i == 2 or i == 6 { |
| 93 | set region = finish; |
| 94 | } |
| 95 | let mut device = try! devices::install(&devices::STORE, &mut child.memory.table, region); |
| 96 | let slot = (try! abi::decode(device)).object.index; |
| 97 | if i == 2 { |
| 98 | set child.memory.table.entries[slot].rights = abi::Rights(abi::READ); |
| 99 | } |
| 100 | if i == 3 { |
| 101 | set child.memory.table.entries[slot].rights = abi::Rights(abi::WRITE); |
| 102 | } |
| 103 | if i == 1 { |
| 104 | set device = abi::Handle(0); |
| 105 | } |
| 106 | if i == 7 { |
| 107 | set device = granted; |
| 108 | } |
| 109 | let timerHandle = try! devices::install(&devices::STORE, &mut child.memory.table, clockDevice); |
| 110 | let args = @sliceOf(memory(storage.base) as *mut u64, 2); |
| 111 | set args[0] = *device; set args[1] = *timerHandle; |
| 112 | let size = 16 + i as u64; |
| 113 | try! domains::activate(&mut domains::STORE, &pages::STORE, &TABLE, handle, storage.base + 4096, storage.base, size); |
| 114 | } |
| 115 | let timer = try! dispatch::timer(&boot::PLATFORM, 0); |
| 116 | let clock = dispatch::now(timer); |
| 117 | let start = clock + 1000000; |
| 118 | let mut remaining = try! budgets::seed(&mut budgets::STORE, &mut TABLE, 0, start, start + 20000000); |
| 119 | for i in 0..9 { |
| 120 | let next = try! budgets::split(&mut budgets::STORE, &mut TABLE, remaining, start + (i as u64 + 1) * 2000000, clock); |
| 121 | let bound = try! budgets::bind(&mut budgets::STORE, &domains::STORE, &mut TABLE, |
| 122 | budgets::Binding { budget: remaining, domain: handles[i], context: contexts[i] }, clock); |
| 123 | set remaining = next; |
| 124 | } |
| 125 | let bound = try! budgets::bind(&mut budgets::STORE, &domains::STORE, &mut TABLE, |
| 126 | budgets::Binding { budget: remaining, domain: parentHandle, context: parent.initial }, clock); |
| 127 | } |
| 128 | |
| 129 | /// Check each terminal kind, status, and generation while the parent continues to run. |
| 130 | export unsafe fn verify() { |
| 131 | let guard = sync::enter(); |
| 132 | let mut parent = try! domains::get(&domains::STORE, PARENT); |
| 133 | let codes = [61 as u32, 256, 256, 256, 256, 256, 256, 256, 256]; |
| 134 | for i in 0..9 { |
| 135 | let event = try! events::pop(&mut parent.memory.ring) else panic "missing termination event"; |
| 136 | assert event.value == abi::id(CHILDREN[i]) and event.code == codes[i]; |
| 137 | if i == 0 { |
| 138 | assert event.kind == events::CHILD_EXIT; |
| 139 | } |
| 140 | else { |
| 141 | assert event.kind == events::FAULT; |
| 142 | } |
| 143 | assert domains::STORE.records[CHILDREN[i].index].state == domains::Lifecycle::Dead; |
| 144 | } |
| 145 | try! events::refresh(&mut domains::STORE.events, PARENT, &parent.memory.ring); |
| 146 | assert try! events::pop(&mut parent.memory.ring) == nil; |
| 147 | sync::leave(guard); |
| 148 | finish(); |
| 149 | } |