Skip to content

Commit d500f22

Browse files
lazy SC rebind + improved tool <> mon ABI
Signed-off-by: Bill Nguyen <bill.nguyen@unsw.edu.au>
1 parent e846634 commit d500f22

File tree

5 files changed

+112
-106
lines changed

5 files changed

+112
-106
lines changed

libmicrokit/src/main.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,5 @@ void main(void)
128128
{
129129
run_init_funcs();
130130
init();
131-
132-
/*
133-
* If we are passive, now our initialisation is complete we can
134-
* signal the monitor to unbind our scheduling context and bind
135-
* it to our notification object.
136-
* We delay this signal so we are ready waiting on a recv() syscall
137-
*/
138-
if (microkit_passive) {
139-
microkit_have_signal = seL4_True;
140-
microkit_signal_msg = seL4_MessageInfo_new(0, 0, 0, 0);
141-
microkit_signal_cap = MONITOR_EP;
142-
}
143-
144131
handler_loop();
145132
}

monitor/src/main.c

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,23 @@
3232
extern seL4_IPCBuffer __sel4_ipc_buffer_obj;
3333
seL4_IPCBuffer *__sel4_ipc_buffer = &__sel4_ipc_buffer_obj;
3434

35-
char pd_names[MAX_PDS][MAX_NAME_LEN];
36-
seL4_Word pd_names_len;
37-
char vm_names[MAX_VMS][MAX_NAME_LEN] __attribute__((unused));
38-
seL4_Word vm_names_len;
39-
40-
/* For reporting potential stack overflows, keep track of the stack regions for each PD. */
41-
seL4_Word pd_stack_bottom_addrs[MAX_PDS];
35+
/* Correspond to `struct PdMetadata` in tool/microkit/src/symbols.rs */
36+
struct pd_metadata {
37+
char name[MAX_NAME_LEN];
38+
seL4_Word passive;
39+
/* For reporting potential stack overflows, keep track of the stack regions for each PD. */
40+
seL4_Word stack_bottom;
41+
} __attribute__((packed));
42+
43+
/* Correspond to `struct VmMetadata` in tool/microkit/src/symbols.rs */
44+
struct vm_metadata {
45+
char name[MAX_NAME_LEN];
46+
} __attribute__((packed));
47+
48+
struct pd_metadata pd_metadata[MAX_PDS];
49+
seL4_Word pd_metadata_len;
50+
struct vm_metadata vm_metadata[MAX_VMS];
51+
seL4_Word vm_metadata_len;
4252

4353
/* Sanity check that the architecture specific macro have been set. */
4454
#if defined(ARCH_aarch64)
@@ -731,25 +741,6 @@ static void monitor(void)
731741
seL4_Word pd_id = badge - 1;
732742
seL4_Word tcb_cap = BASE_PD_TCB_CAP + pd_id;
733743

734-
if (label == seL4_Fault_NullFault && pd_id < MAX_PDS) {
735-
/* This is a request from our PD to become passive */
736-
err = seL4_SchedContext_UnbindObject(BASE_SCHED_CONTEXT_CAP + pd_id, tcb_cap);
737-
if (err != seL4_NoError) {
738-
puts("MON|ERROR: could not unbind scheduling context from thread control block\n");
739-
} else {
740-
err = seL4_SchedContext_Bind(BASE_SCHED_CONTEXT_CAP + pd_id, BASE_NOTIFICATION_CAP + pd_id);
741-
if (err != seL4_NoError) {
742-
puts("MON|ERROR: could not bind scheduling context to notification object\n");
743-
} else {
744-
puts("MON|INFO: PD '");
745-
puts(pd_names[pd_id]);
746-
puts("' is now passive!\n");
747-
}
748-
}
749-
750-
continue;
751-
}
752-
753744
puts("MON|ERROR: received message ");
754745
puthex32(label);
755746
puts(" badge: ");
@@ -758,9 +749,9 @@ static void monitor(void)
758749
puthex64(tcb_cap);
759750
puts("\n");
760751

761-
if (pd_id < MAX_PDS && pd_names[pd_id][0] != 0) {
752+
if (pd_id < MAX_PDS && pd_metadata[pd_id].name[0] != 0) {
762753
puts("MON|ERROR: faulting PD: ");
763-
puts(pd_names[pd_id]);
754+
puts(pd_metadata[pd_id].name);
764755
puts("\n");
765756
} else {
766757
fail("MON|ERROR: unknown/invalid badge\n");
@@ -850,7 +841,7 @@ static void monitor(void)
850841
#endif
851842

852843
seL4_Word fault_addr = seL4_GetMR(seL4_VMFault_Addr);
853-
seL4_Word stack_addr = pd_stack_bottom_addrs[pd_id];
844+
seL4_Word stack_addr = pd_metadata[pd_id].stack_bottom;
854845
if (fault_addr < stack_addr && fault_addr >= stack_addr - 0x1000) {
855846
puts("MON|ERROR: potential stack overflow, fault address within one page outside of stack region\n");
856847
}
@@ -894,14 +885,37 @@ void main(void)
894885
* Assign PD/VM names to each TCB with seL4, this helps debugging when an error
895886
* message is printed by seL4 or if we dump the scheduler state.
896887
*/
897-
for (unsigned idx = 0; idx < pd_names_len; idx++) {
898-
seL4_DebugNameThread(BASE_PD_TCB_CAP + idx, pd_names[idx]);
888+
for (unsigned idx = 0; idx < pd_metadata_len; idx++) {
889+
seL4_DebugNameThread(BASE_PD_TCB_CAP + idx, pd_metadata[idx].name);
899890
}
900-
for (unsigned idx = 0; idx < vm_names_len; idx++) {
901-
seL4_DebugNameThread(BASE_VM_TCB_CAP + idx, vm_names[idx]);
891+
for (unsigned idx = 0; idx < vm_metadata_len; idx++) {
892+
seL4_DebugNameThread(BASE_VM_TCB_CAP + idx, vm_metadata[idx].name);
902893
}
903894
#endif
904895

896+
/* If there are passive PDs in the system, lazily rebind it's Scheduling Context and resume TCB.
897+
* To workaround https://github.com/seL4/seL4/issues/1617 by applying https://github.com/seL4/seL4/pull/523
898+
*/
899+
for (unsigned idx = 0; idx < pd_metadata_len; idx++) {
900+
if (pd_metadata[idx].passive) {
901+
seL4_Error err = seL4_SchedContext_Bind(BASE_SCHED_CONTEXT_CAP + idx, BASE_NOTIFICATION_CAP + idx);
902+
if (err != seL4_NoError) {
903+
puts("MON|ERROR: could not bind scheduling context to notification object\n");
904+
continue;
905+
}
906+
907+
err = seL4_TCB_Resume(BASE_PD_TCB_CAP + idx);
908+
if (err != seL4_NoError) {
909+
puts("MON|ERROR: could not bind resume passive PD TCB\n");
910+
continue;
911+
}
912+
913+
puts("MON|INFO: PD '");
914+
puts(pd_metadata[idx].name);
915+
puts("' is now passive!\n");
916+
}
917+
}
918+
905919
puts("MON|INFO: Microkit Monitor started!\n");
906920

907921
monitor();

tool/microkit/src/capdl/builder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,8 @@ pub fn build_capdl_spec(
979979
pd_tcb.extra.master_fault_ep = None; // Not used on MCS kernel.
980980
pd_tcb.extra.prio = pd.priority;
981981
pd_tcb.extra.max_prio = pd.priority;
982-
pd_tcb.extra.resume = true;
982+
// Passive PDs are resumed by the Monitor
983+
pd_tcb.extra.resume = !pd.passive;
983984

984985
pd_tcb.slots.extend(caps_to_bind_to_tcb);
985986
// Stylistic purposes only

tool/microkit/src/symbols.rs

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,24 @@ use crate::{
1010
elf::ElfFile,
1111
sdf::{self, SysMemoryRegion, SystemDescription},
1212
sel4::{Arch, Config},
13-
util::{monitor_serialise_names, monitor_serialise_u64_vec},
14-
MAX_PDS, MAX_VMS, PD_MAX_NAME_LENGTH, VM_MAX_NAME_LENGTH,
13+
util::{copy_and_clip_string, struct_to_bytes},
14+
PD_MAX_NAME_LENGTH, VM_MAX_NAME_LENGTH,
1515
};
1616

17+
/// Correspond to `struct pd_metadata` in monitor/src/main.c
18+
#[repr(C)]
19+
struct PdMetadata {
20+
pub name: [u8; PD_MAX_NAME_LENGTH],
21+
pub passive: u64,
22+
pub stack_bottom: u64,
23+
}
24+
25+
/// Correspond to `struct vm_metadata` in monitor/src/main.c
26+
#[repr(C)]
27+
struct VmMetadata {
28+
pub name: [u8; VM_MAX_NAME_LENGTH],
29+
}
30+
1731
/// Patch all the required symbols in the Monitor and children PDs according to
1832
/// the Microkit's requirements
1933
pub fn patch_symbols(
@@ -26,25 +40,37 @@ pub fn patch_symbols(
2640
// *********************************
2741
let monitor_elf = pd_elf_files.last_mut().unwrap();
2842

29-
let pd_names: Vec<String> = system
43+
let mut pd_metadata_bytes = Vec::new();
44+
system
3045
.protection_domains
3146
.iter()
32-
.map(|pd| pd.name.clone())
33-
.collect();
47+
.map(|pd| {
48+
let mut metadata = PdMetadata {
49+
name: [0u8; PD_MAX_NAME_LENGTH],
50+
passive: if pd.passive { 1 } else { 0 },
51+
stack_bottom: kernel_config.pd_stack_bottom(pd.stack_size),
52+
};
53+
54+
copy_and_clip_string(pd.name.as_bytes(), &mut metadata.name);
55+
56+
metadata
57+
})
58+
.for_each(|metadata| {
59+
pd_metadata_bytes.extend_from_slice(unsafe { struct_to_bytes(&metadata) })
60+
});
61+
3462
monitor_elf
3563
.write_symbol(
36-
"pd_names_len",
64+
"pd_metadata_len",
3765
&system.protection_domains.len().to_le_bytes(),
3866
)
3967
.unwrap();
4068
monitor_elf
41-
.write_symbol(
42-
"pd_names",
43-
&monitor_serialise_names(&pd_names, MAX_PDS, PD_MAX_NAME_LENGTH),
44-
)
69+
.write_symbol("pd_metadata", &pd_metadata_bytes)
4570
.unwrap();
4671

47-
let vm_names: Vec<String> = system
72+
let mut vm_metadata_bytes = Vec::new();
73+
system
4874
.protection_domains
4975
.iter()
5076
.filter(|pd| pd.virtual_machine.is_some())
@@ -53,33 +79,29 @@ pub fn patch_symbols(
5379
let num_vcpus = vm.vcpus.len();
5480
std::iter::repeat_n(vm.name.clone(), num_vcpus)
5581
})
56-
.collect();
82+
.map(|vm_name| {
83+
let mut metadata = VmMetadata {
84+
name: [0u8; VM_MAX_NAME_LENGTH],
85+
};
86+
87+
copy_and_clip_string(vm_name.as_bytes(), &mut metadata.name);
5788

58-
let vm_names_len = match kernel_config.arch {
59-
Arch::Aarch64 | Arch::Riscv64 => vm_names.len(),
89+
metadata
90+
})
91+
.for_each(|metadata| {
92+
vm_metadata_bytes.extend_from_slice(unsafe { struct_to_bytes(&metadata) })
93+
});
94+
95+
let vm_metadata_len = match kernel_config.arch {
96+
Arch::Aarch64 | Arch::Riscv64 => vm_metadata_bytes.len() / size_of::<VmMetadata>(),
6097
// VM on x86 doesn't have a separate TCB.
6198
Arch::X86_64 => 0,
6299
};
63100
monitor_elf
64-
.write_symbol("vm_names_len", &vm_names_len.to_le_bytes())
65-
.unwrap();
66-
monitor_elf
67-
.write_symbol(
68-
"vm_names",
69-
&monitor_serialise_names(&vm_names, MAX_VMS, VM_MAX_NAME_LENGTH),
70-
)
101+
.write_symbol("vm_metadata_len", &vm_metadata_len.to_le_bytes())
71102
.unwrap();
72-
73-
let mut pd_stack_bottoms: Vec<u64> = Vec::new();
74-
for pd in system.protection_domains.iter() {
75-
let cur_stack_vaddr = kernel_config.pd_stack_bottom(pd.stack_size);
76-
pd_stack_bottoms.push(cur_stack_vaddr);
77-
}
78103
monitor_elf
79-
.write_symbol(
80-
"pd_stack_bottom_addrs",
81-
&monitor_serialise_u64_vec(&pd_stack_bottoms),
82-
)
104+
.write_symbol("vm_metadata", &vm_metadata_bytes)
83105
.unwrap();
84106

85107
// *********************************

tool/microkit/src/util.rs

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -171,36 +171,18 @@ pub unsafe fn bytes_to_struct<T>(bytes: &[u8]) -> &T {
171171
&body[0]
172172
}
173173

174-
/// Serialise an array of u64 to a Vector of bytes.
175-
pub fn monitor_serialise_u64_vec(vec: &[u64]) -> Vec<u8> {
176-
let mut bytes = vec![0; (1 + vec.len()) * 8];
177-
for (i, value) in vec.iter().enumerate() {
178-
let start = i * 8;
179-
let end = start + 8;
180-
bytes[start..end].copy_from_slice(&value.to_le_bytes());
174+
/// Copy at most `out_str.len() - 1` bytes from `in_str` to `out_str`. Null terminates `out_str`
175+
pub fn copy_and_clip_string(in_str: &[u8], out_str: &mut [u8]) {
176+
if out_str.is_empty() {
177+
return;
181178
}
182179

183-
bytes
184-
}
185-
186-
/// For serialising an array of PD or VM names
187-
pub fn monitor_serialise_names(names: &[String], max_len: usize, max_name_len: usize) -> Vec<u8> {
188-
let mut names_bytes = vec![0; (max_len + 1) * max_name_len];
189-
for (i, name) in names.iter().enumerate() {
190-
let name_bytes = name.as_bytes();
191-
let start = i * max_name_len;
192-
// Here instead of giving an error we simply take the minimum of the name
193-
// and how large of a name we can encode. The name length is one less than
194-
// the maximum since we still have to add the null terminator.
195-
let name_length = std::cmp::min(name_bytes.len(), max_name_len - 1);
196-
let end = start + name_length;
197-
names_bytes[start..end].copy_from_slice(&name_bytes[..name_length]);
198-
// These bytes will be interpreted as a C string, so we must include
199-
// a null-terminator.
200-
names_bytes[end] = 0;
201-
}
202-
203-
names_bytes
180+
// Here instead of giving an error we simply take the minimum of the name
181+
// and how large of a name we can encode. The name length is one less than
182+
// the maximum since we still have to add the null terminator.
183+
let n = in_str.len().min(out_str.len() - 1);
184+
out_str[..n].copy_from_slice(&in_str[..n]);
185+
out_str[n] = 0;
204186
}
205187

206188
#[cfg(test)]

0 commit comments

Comments
 (0)