Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
541 changes: 514 additions & 27 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ members = [
# The CI tests are not meant to be released (thus are not prefixed with
# `litebox_`), but exist purely to better manage development on LiteBox.
"dev_tests",
########################################################
"ostd-test/platform",
"ostd-test/runner",
]
default-members = [
"litebox",
Expand All @@ -35,6 +38,8 @@ default-members = [
"litebox_shim_optee",
"litebox_syscall_rewriter",
"dev_tests",
"ostd-test/platform",
"ostd-test/runner",
]
# We exclude `litebox_runner_lvbs` from `default-members` because its interrupt handling
# depends on the unstable `abi_x86_interrupt` feature, which requires a nightly toolchain.
Expand Down
19 changes: 19 additions & 0 deletions OSDK.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[boot]
method = "grub-rescue-iso"

[qemu]
args = """\
-enable-kvm \
-machine q35,kernel-irqchip=split \
-cpu Icelake-Server,+x2apic \
--no-reboot \
-m 8G \
-smp 1 \
-nographic \
-serial chardev:mux \
-monitor chardev:mux \
-chardev stdio,id=mux,mux=on,signal=off \
-display none \
-device isa-debug-exit,iobase=0xf4,iosize=0x04 \
-boot d,menu=off \
"""
12 changes: 12 additions & 0 deletions bacon.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ need_stdout = false
allow_warnings = true
on_success = "job:doc" # so that we don't open the browser at each change

# osdk check
[jobs.osdk-check]
command = ["cargo", "osdk", "check"]
workdir = "ostd-test/runner"

# osdk run
[jobs.osdk-run]
command = ["cargo", "osdk", "run"]
allow_warnings = true

# Project-specific keybindings, to make it easier to run the various jobs here.
[keybindings]
k = "job:check"
Expand All @@ -104,3 +114,5 @@ alt-d = "job:doc"
v = "job:buildchecks-lvbs"
alt-s = "job:buildchecks-snp"
w = "job:clippy-windows"
o = "job:osdk-check"
alt-o = "job:osdk-run"
12 changes: 8 additions & 4 deletions litebox/src/fs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1167,10 +1167,14 @@ mod layered {

let mut names: Vec<_> = entries.iter().map(|e| e.name.as_str()).collect();
names.sort_unstable();
assert_eq!(
names,
vec![".", "..", "bar", "foo", "upperdir", "upperfile"]
);
assert_eq!(names, vec![
".",
"..",
"bar",
"foo",
"upperdir",
"upperfile"
]);

// Check file types
for entry in &entries {
Expand Down
4 changes: 4 additions & 0 deletions litebox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
//! the modules in this crate.

#![no_std]
#![feature(let_chains)]

Check failure on line 13 in litebox/src/lib.rs

View workflow job for this annotation

GitHub Actions / Build and Test LVBS

the feature `let_chains` has been stable since 1.88.0 and no longer requires an attribute to enable

error: the feature `let_chains` has been stable since 1.88.0 and no longer requires an attribute to enable --> litebox/src/lib.rs:13:12 | 13 | #![feature(let_chains)] | ^^^^^^^^^^ | = note: `-D stable-features` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(stable_features)]`

Check failure on line 13 in litebox/src/lib.rs

View workflow job for this annotation

GitHub Actions / Build and Test SNP

the feature `let_chains` has been stable since 1.88.0 and no longer requires an attribute to enable

error: the feature `let_chains` has been stable since 1.88.0 and no longer requires an attribute to enable --> litebox/src/lib.rs:13:12 | 13 | #![feature(let_chains)] | ^^^^^^^^^^ | = note: `-D stable-features` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(stable_features)]`
#![feature(unsigned_is_multiple_of)]

Check failure on line 14 in litebox/src/lib.rs

View workflow job for this annotation

GitHub Actions / Build and Test LVBS

the feature `unsigned_is_multiple_of` has been stable since 1.87.0 and no longer requires an attribute to enable

error: the feature `unsigned_is_multiple_of` has been stable since 1.87.0 and no longer requires an attribute to enable --> litebox/src/lib.rs:14:12 | 14 | #![feature(unsigned_is_multiple_of)] | ^^^^^^^^^^^^^^^^^^^^^^^

Check failure on line 14 in litebox/src/lib.rs

View workflow job for this annotation

GitHub Actions / Build and Test SNP

the feature `unsigned_is_multiple_of` has been stable since 1.87.0 and no longer requires an attribute to enable

error: the feature `unsigned_is_multiple_of` has been stable since 1.87.0 and no longer requires an attribute to enable --> litebox/src/lib.rs:14:12 | 14 | #![feature(unsigned_is_multiple_of)] | ^^^^^^^^^^^^^^^^^^^^^^^
#![feature(trait_upcasting)]

Check failure on line 15 in litebox/src/lib.rs

View workflow job for this annotation

GitHub Actions / Build and Test LVBS

the feature `trait_upcasting` has been stable since 1.86.0 and no longer requires an attribute to enable

error: the feature `trait_upcasting` has been stable since 1.86.0 and no longer requires an attribute to enable --> litebox/src/lib.rs:15:12 | 15 | #![feature(trait_upcasting)] | ^^^^^^^^^^^^^^^

Check failure on line 15 in litebox/src/lib.rs

View workflow job for this annotation

GitHub Actions / Build and Test SNP

the feature `trait_upcasting` has been stable since 1.86.0 and no longer requires an attribute to enable

error: the feature `trait_upcasting` has been stable since 1.86.0 and no longer requires an attribute to enable --> litebox/src/lib.rs:15:12 | 15 | #![feature(trait_upcasting)] | ^^^^^^^^^^^^^^^
#![feature(result_flattening)]

Check failure on line 16 in litebox/src/lib.rs

View workflow job for this annotation

GitHub Actions / Build and Test LVBS

the feature `result_flattening` has been stable since 1.89.0 and no longer requires an attribute to enable

error: the feature `result_flattening` has been stable since 1.89.0 and no longer requires an attribute to enable --> litebox/src/lib.rs:16:12 | 16 | #![feature(result_flattening)] | ^^^^^^^^^^^^^^^^^

Check failure on line 16 in litebox/src/lib.rs

View workflow job for this annotation

GitHub Actions / Build and Test SNP

the feature `result_flattening` has been stable since 1.89.0 and no longer requires an attribute to enable

error: the feature `result_flattening` has been stable since 1.89.0 and no longer requires an attribute to enable --> litebox/src/lib.rs:16:12 | 16 | #![feature(result_flattening)] | ^^^^^^^^^^^^^^^^^

extern crate alloc;

Expand Down
4 changes: 2 additions & 2 deletions litebox/src/mm/exception_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! 3. Signal/exception handlers use [`search_exception_tables`] to look up recovery points
//! 4. If found, execution is redirected to allow graceful failure handling
//!
//! New fallible functions should follow the pattern established by [`__memcpy_fallible`].
//! New fallible functions should follow the pattern established by [`__lb_memcpy_fallible`].

use crate::utils::ReinterpretUnsignedExt;

Expand Down Expand Up @@ -49,7 +49,7 @@ unsafe extern "C" {
/// see [`crate::platform::common_providers::userspace_pointers`].
///
/// Returns number of bytes that failed to copy (0 on success).
pub fn __memcpy_fallible(dst: *mut u8, src: *const u8, size: usize) -> usize;
pub fn __lb_memcpy_fallible(dst: *mut u8, src: *const u8, size: usize) -> usize;

static __ex_table_start: [ExceptionTableEntry; 0];
static __ex_table_end: [ExceptionTableEntry; 0];
Expand Down
22 changes: 8 additions & 14 deletions litebox/src/mm/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,13 +291,10 @@ impl<Platform: PageManagementProvider<ALIGN> + 'static, const ALIGN: usize> Vmem
each.start % ALIGN == 0 && each.end % ALIGN == 0,
"Vmem: reserved range is not aligned to {ALIGN} bytes"
);
vmem.vmas.insert(
each.start..each.end,
VmArea {
flags: VmFlags::empty(),
is_file_backed: false,
},
);
vmem.vmas.insert(each.start..each.end, VmArea {
flags: VmFlags::empty(),
is_file_backed: false,
});
}
vmem
}
Expand Down Expand Up @@ -720,13 +717,10 @@ impl<Platform: PageManagementProvider<ALIGN> + 'static, const ALIGN: usize> Vmem
VmemProtectError::ProtectError(e)
})?;

self.vmas.insert(
intersection,
VmArea {
flags: new_flags,
is_file_backed: vma.is_file_backed,
},
);
self.vmas.insert(intersection, VmArea {
flags: new_flags,
is_file_backed: vma.is_file_backed,
});
if !before.is_empty() {
self.vmas.insert(before, vma);
}
Expand Down
6 changes: 3 additions & 3 deletions litebox/src/mm/memcpy_fallible_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// Output:
// eax uncopied bytes or 0 if successful.
.text
.global __memcpy_fallible
.global __lb_memcpy_fallible
.code32
__memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize
__lb_memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize
push esi
push edi
push ecx
Expand All @@ -35,4 +35,4 @@ __memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize
.align 4
.long .move - .
.long .memcpy_exit - .
.popsection
.popsection
6 changes: 3 additions & 3 deletions litebox/src/mm/memcpy_fallible_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// Output:
// rcx uncopied bytes or 0 if successful.
.text
.global __memcpy_fallible
.global __lb_memcpy_fallible
.code64
__memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize
__lb_memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize
mov rcx, rdx
.move:
rep movsb
Expand All @@ -23,4 +23,4 @@ __memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize
.align 4
.long .move - .
.long .memcpy_exit - .
.popsection
.popsection
102 changes: 41 additions & 61 deletions litebox/src/mm/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,9 @@ fn test_vmm_mapping() {
}
.unwrap();
// [(0x1_0000, 0x1_c000)]
assert_eq!(
collect_mappings(&vmm),
vec![start_addr..start_addr + 12 * PAGE_SIZE]
);
assert_eq!(collect_mappings(&vmm), vec![
start_addr..start_addr + 12 * PAGE_SIZE
]);

unsafe {
vmm.remove_mapping(
Expand All @@ -113,13 +112,10 @@ fn test_vmm_mapping() {
}
.unwrap();
// [(0x1_0000, 0x1_2000), (0x1_4000, 0x1_c000)]
assert_eq!(
collect_mappings(&vmm),
vec![
start_addr..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE
]
);
assert_eq!(collect_mappings(&vmm), vec![
start_addr..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE
]);

assert!(matches!(
unsafe {
Expand Down Expand Up @@ -164,10 +160,9 @@ fn test_vmm_mapping() {
.is_ok()
);
// Grow and merge, [(0x1_0000, 0x1_c000)]
assert_eq!(
collect_mappings(&vmm),
vec![start_addr..start_addr + 12 * PAGE_SIZE]
);
assert_eq!(collect_mappings(&vmm), vec![
start_addr..start_addr + 12 * PAGE_SIZE
]);

assert!(matches!(
unsafe {
Expand All @@ -190,14 +185,11 @@ fn test_vmm_mapping() {
.is_ok()
);
// Change permission, [(0x1_0000, 0x1_2000), (0x1_2000, 0x1_4000), (0x1_4000, 0x1_c000)]
assert_eq!(
collect_mappings(&vmm),
vec![
start_addr..start_addr + 2 * PAGE_SIZE,
start_addr + 2 * PAGE_SIZE..start_addr + 4 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE
]
);
assert_eq!(collect_mappings(&vmm), vec![
start_addr..start_addr + 2 * PAGE_SIZE,
start_addr + 2 * PAGE_SIZE..start_addr + 4 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE
]);

// try to remap [0x1_2000, 0x1_4000)
let r = PageRange::new(start_addr + 2 * PAGE_SIZE, start_addr + 4 * PAGE_SIZE).unwrap();
Expand All @@ -215,14 +207,11 @@ fn test_vmm_mapping() {
}
.is_ok_and(|v| v.as_usize() == start_addr + 12 * PAGE_SIZE)
);
assert_eq!(
collect_mappings(&vmm),
vec![
start_addr..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE,
start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE
]
);
assert_eq!(collect_mappings(&vmm), vec![
start_addr..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE,
start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE
]);

// create new mapping with no suggested address
assert_eq!(
Expand All @@ -238,15 +227,12 @@ fn test_vmm_mapping() {
.as_usize(),
DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE,
);
assert_eq!(
collect_mappings(&vmm),
vec![
start_addr..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE,
start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE,
DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX,
]
);
assert_eq!(collect_mappings(&vmm), vec![
start_addr..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE,
start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE,
DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX,
]);

// create new mapping with fixed address that overlaps with other mapping
assert_eq!(
Expand All @@ -262,16 +248,13 @@ fn test_vmm_mapping() {
.as_usize(),
start_addr + PAGE_SIZE
);
assert_eq!(
collect_mappings(&vmm),
vec![
start_addr..start_addr + PAGE_SIZE,
start_addr + PAGE_SIZE..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE,
start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE,
DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX,
]
);
assert_eq!(collect_mappings(&vmm), vec![
start_addr..start_addr + PAGE_SIZE,
start_addr + PAGE_SIZE..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE,
start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE,
DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX,
]);

// shrink mapping
assert!(
Expand All @@ -283,15 +266,12 @@ fn test_vmm_mapping() {
}
.is_ok()
);
assert_eq!(
collect_mappings(&vmm),
vec![
start_addr..start_addr + PAGE_SIZE,
start_addr + PAGE_SIZE..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 6 * PAGE_SIZE,
start_addr + 8 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE,
start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE,
DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX,
]
);
assert_eq!(collect_mappings(&vmm), vec![
start_addr..start_addr + PAGE_SIZE,
start_addr + PAGE_SIZE..start_addr + 2 * PAGE_SIZE,
start_addr + 4 * PAGE_SIZE..start_addr + 6 * PAGE_SIZE,
start_addr + 8 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE,
start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE,
DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX,
]);
}
12 changes: 6 additions & 6 deletions litebox/src/platform/common_providers/userspace_pointers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Userspace Pointer Abstraction with Fallible Memory Access
//!
//! This module implements fallible userspace pointers that can safely handle invalid
//! memory accesses from userspace. The pointers use [`__memcpy_fallible`] internally,
//! memory accesses from userspace. The pointers use [`__lb_memcpy_fallible`] internally,
//! which relies on an exception table mechanism to recover from memory faults.
//!
//! ## Exception Handling Mechanism
Expand All @@ -27,7 +27,7 @@
//! accesses will still cause the program to crash (e.g., with SIGSEGV), but
//! with the additional overhead of the fallible copy mechanism.

use crate::mm::exception_table::__memcpy_fallible;
use crate::mm::exception_table::__lb_memcpy_fallible;
use crate::platform::{RawConstPointer, RawMutPointer};

/// Represent a user space pointer to a read-only object
Expand All @@ -54,7 +54,7 @@ unsafe fn read_at_offset<'a, T: Clone>(
let src = unsafe { ptr.add(usize::try_from(count).ok()?) };
let mut data = core::mem::MaybeUninit::<T>::uninit();
let failed_bytes = unsafe {
__memcpy_fallible(
__lb_memcpy_fallible(
data.as_mut_ptr().cast(),
src.cast(),
core::mem::size_of::<T>(),
Expand All @@ -77,7 +77,7 @@ unsafe fn to_cow_slice<'a, T: Clone>(
}
let mut data = alloc::vec::Vec::<T>::with_capacity(len);
let failed_bytes = unsafe {
__memcpy_fallible(
__lb_memcpy_fallible(
data.as_mut_ptr().cast(),
ptr.cast(),
len * core::mem::size_of::<T>(),
Expand Down Expand Up @@ -148,7 +148,7 @@ impl<T: Clone> RawMutPointer<T> for UserMutPtr<T> {
unsafe fn write_at_offset(self, count: isize, value: T) -> Option<()> {
let dst = unsafe { self.inner.add(usize::try_from(count).ok()?) };
let failed_bytes = unsafe {
__memcpy_fallible(
__lb_memcpy_fallible(
dst.cast(),
(&raw const value).cast(),
core::mem::size_of::<T>(),
Expand All @@ -174,7 +174,7 @@ impl<T: Clone> RawMutPointer<T> for UserMutPtr<T> {
}
let dst = unsafe { self.inner.add(start_offset) };
let failed_bytes = unsafe {
__memcpy_fallible(dst.cast(), buf.as_ptr().cast(), core::mem::size_of_val(buf))
__lb_memcpy_fallible(dst.cast(), buf.as_ptr().cast(), core::mem::size_of_val(buf))
};
if failed_bytes == 0 { Some(()) } else { None }
}
Expand Down
Loading
Loading