Skip to content

Commit 8e19777

Browse files
tool + monitor: improve ABI
Improved tool <-> monitor ABI by creating a metadata struct per PD, rather than adding a new symbol for every type of metadata. Signed-off-by: Bill Nguyen <bill.nguyen@unsw.edu.au>
1 parent e846634 commit 8e19777

File tree

3 files changed

+85
-74
lines changed

3 files changed

+85
-74
lines changed

monitor/src/main.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,22 @@
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+
/* For reporting potential stack overflows, keep track of the stack regions for each PD. */
39+
seL4_Word stack_bottom;
40+
} __attribute__((packed));
41+
42+
/* Correspond to `struct VmMetadata` in tool/microkit/src/symbols.rs */
43+
struct vm_metadata {
44+
char name[MAX_NAME_LEN];
45+
} __attribute__((packed));
46+
47+
struct pd_metadata pd_metadata[MAX_PDS];
48+
seL4_Word pd_metadata_len;
49+
struct vm_metadata vm_metadata[MAX_VMS];
50+
seL4_Word vm_metadata_len;
4251

4352
/* Sanity check that the architecture specific macro have been set. */
4453
#if defined(ARCH_aarch64)
@@ -742,7 +751,7 @@ static void monitor(void)
742751
puts("MON|ERROR: could not bind scheduling context to notification object\n");
743752
} else {
744753
puts("MON|INFO: PD '");
745-
puts(pd_names[pd_id]);
754+
puts(pd_metadata[pd_id].name);
746755
puts("' is now passive!\n");
747756
}
748757
}
@@ -758,9 +767,9 @@ static void monitor(void)
758767
puthex64(tcb_cap);
759768
puts("\n");
760769

761-
if (pd_id < MAX_PDS && pd_names[pd_id][0] != 0) {
770+
if (pd_id < MAX_PDS && pd_metadata[pd_id].name[0] != 0) {
762771
puts("MON|ERROR: faulting PD: ");
763-
puts(pd_names[pd_id]);
772+
puts(pd_metadata[pd_id].name);
764773
puts("\n");
765774
} else {
766775
fail("MON|ERROR: unknown/invalid badge\n");
@@ -850,7 +859,7 @@ static void monitor(void)
850859
#endif
851860

852861
seL4_Word fault_addr = seL4_GetMR(seL4_VMFault_Addr);
853-
seL4_Word stack_addr = pd_stack_bottom_addrs[pd_id];
862+
seL4_Word stack_addr = pd_metadata[pd_id].stack_bottom;
854863
if (fault_addr < stack_addr && fault_addr >= stack_addr - 0x1000) {
855864
puts("MON|ERROR: potential stack overflow, fault address within one page outside of stack region\n");
856865
}
@@ -894,11 +903,11 @@ void main(void)
894903
* Assign PD/VM names to each TCB with seL4, this helps debugging when an error
895904
* message is printed by seL4 or if we dump the scheduler state.
896905
*/
897-
for (unsigned idx = 0; idx < pd_names_len; idx++) {
898-
seL4_DebugNameThread(BASE_PD_TCB_CAP + idx, pd_names[idx]);
906+
for (unsigned idx = 0; idx < pd_metadata_len; idx++) {
907+
seL4_DebugNameThread(BASE_PD_TCB_CAP + idx, pd_metadata[idx].name);
899908
}
900-
for (unsigned idx = 0; idx < vm_names_len; idx++) {
901-
seL4_DebugNameThread(BASE_VM_TCB_CAP + idx, vm_names[idx]);
909+
for (unsigned idx = 0; idx < vm_metadata_len; idx++) {
910+
seL4_DebugNameThread(BASE_VM_TCB_CAP + idx, vm_metadata[idx].name);
902911
}
903912
#endif
904913

tool/microkit/src/symbols.rs

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,23 @@ 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 stack_bottom: u64,
22+
}
23+
24+
/// Correspond to `struct vm_metadata` in monitor/src/main.c
25+
#[repr(C)]
26+
struct VmMetadata {
27+
pub name: [u8; VM_MAX_NAME_LENGTH],
28+
}
29+
1730
/// Patch all the required symbols in the Monitor and children PDs according to
1831
/// the Microkit's requirements
1932
pub fn patch_symbols(
@@ -26,25 +39,36 @@ pub fn patch_symbols(
2639
// *********************************
2740
let monitor_elf = pd_elf_files.last_mut().unwrap();
2841

29-
let pd_names: Vec<String> = system
42+
let mut pd_metadata_bytes = Vec::new();
43+
system
3044
.protection_domains
3145
.iter()
32-
.map(|pd| pd.name.clone())
33-
.collect();
46+
.map(|pd| {
47+
let mut metadata = PdMetadata {
48+
name: [0u8; PD_MAX_NAME_LENGTH],
49+
stack_bottom: kernel_config.pd_stack_bottom(pd.stack_size),
50+
};
51+
52+
copy_and_clip_string(pd.name.as_bytes(), &mut metadata.name);
53+
54+
metadata
55+
})
56+
.for_each(|metadata| {
57+
pd_metadata_bytes.extend_from_slice(unsafe { struct_to_bytes(&metadata) })
58+
});
59+
3460
monitor_elf
3561
.write_symbol(
36-
"pd_names_len",
62+
"pd_metadata_len",
3763
&system.protection_domains.len().to_le_bytes(),
3864
)
3965
.unwrap();
4066
monitor_elf
41-
.write_symbol(
42-
"pd_names",
43-
&monitor_serialise_names(&pd_names, MAX_PDS, PD_MAX_NAME_LENGTH),
44-
)
67+
.write_symbol("pd_metadata", &pd_metadata_bytes)
4568
.unwrap();
4669

47-
let vm_names: Vec<String> = system
70+
let mut vm_metadata_bytes = Vec::new();
71+
system
4872
.protection_domains
4973
.iter()
5074
.filter(|pd| pd.virtual_machine.is_some())
@@ -53,33 +77,29 @@ pub fn patch_symbols(
5377
let num_vcpus = vm.vcpus.len();
5478
std::iter::repeat_n(vm.name.clone(), num_vcpus)
5579
})
56-
.collect();
80+
.map(|vm_name| {
81+
let mut metadata = VmMetadata {
82+
name: [0u8; VM_MAX_NAME_LENGTH],
83+
};
84+
85+
copy_and_clip_string(vm_name.as_bytes(), &mut metadata.name);
5786

58-
let vm_names_len = match kernel_config.arch {
59-
Arch::Aarch64 | Arch::Riscv64 => vm_names.len(),
87+
metadata
88+
})
89+
.for_each(|metadata| {
90+
vm_metadata_bytes.extend_from_slice(unsafe { struct_to_bytes(&metadata) })
91+
});
92+
93+
let vm_metadata_len = match kernel_config.arch {
94+
Arch::Aarch64 | Arch::Riscv64 => vm_metadata_bytes.len() / size_of::<VmMetadata>(),
6095
// VM on x86 doesn't have a separate TCB.
6196
Arch::X86_64 => 0,
6297
};
6398
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-
)
99+
.write_symbol("vm_metadata_len", &vm_metadata_len.to_le_bytes())
71100
.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-
}
78101
monitor_elf
79-
.write_symbol(
80-
"pd_stack_bottom_addrs",
81-
&monitor_serialise_u64_vec(&pd_stack_bottoms),
82-
)
102+
.write_symbol("vm_metadata", &vm_metadata_bytes)
83103
.unwrap();
84104

85105
// *********************************

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)