diff --git a/Cargo.toml b/Cargo.toml index 0d07ce45b086db7545ed1ad84b9e5dbf8ab3d891..c23dbfd09ee9e88b22b034bb54707559d0057873 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,6 +114,7 @@ strum = { version = "0.27", default-features = false, features = ["derive"] } x86_64 = { version = "0.15.2", features = ["instructions"] } # Tee Crates + tee_kernel = { path = "tee/tee_kernel" } tee_raw_sys = { path = "tee/tee_raw_sys" } mbedtls = { version = "0.13", package = "mbedtls-smx", default-features = false, features = [ "no_std_deps", @@ -144,6 +145,7 @@ klogger = { path = "util/klogger" } backtrace = { path = "util/backtrace" } kerrno = { path = "util/kerrno" } unittest = { path = "util/unittest" } +unittest_support = { path = "util/unittest_support" } kbuild_config = { path = "util/kbuild_config" } kconfig-gen = { path = "xtask/kconfig-gen" } diff --git a/Makefile b/Makefile index 7cf87fa103e4367cda64406e0eb0fc38b333bc66..6937705944e622e325426d6202aa164ccef29288 100644 --- a/Makefile +++ b/Makefile @@ -205,7 +205,7 @@ doc_check_missing: $(call cargo_doc) fmt: - cargo +nightly fmt --all + cargo +nightly-2026-03-08 fmt --all unittest: $(call unit_test) diff --git a/api/kapi/Cargo.toml b/api/kapi/Cargo.toml index 2e480d2fcb4bcc0284fbe647fd23b25c278b9115..f97dde7750688f4650948c0e5035a248082f4503 100644 --- a/api/kapi/Cargo.toml +++ b/api/kapi/Cargo.toml @@ -21,27 +21,17 @@ dice = [ "dep:mbedtls", ] tee = [ - "linux_sysno/tee", - "kalloc/tee", - "dep:tee_raw_sys", - "dep:bincode", - "dep:uuid", - "dep:hex", - "dep:rand_chacha", - "dep:mbedtls", - "dep:mbedtls-sys-auto", - "tee_ss_smx", + "dep:tee_kernel", ] -tee_cfg_memtag = [] -tee_ss_smx = [] sev = ["dep:kcpu"] -x86_csv = ["dep:kcpu"] +x86_csv = ["tee_kernel/x86_csv"] [dependencies] kbuild_config = { workspace = true } kalloc.workspace = true backtrace.workspace = true unittest = { workspace = true } +unittest_support.workspace = true rust-dice = { workspace = true, optional = true } mbedtls = { workspace = true, optional = true } mbedtls-sys-auto = { workspace = true, optional = true } @@ -95,16 +85,8 @@ ksignal.workspace = true osvm.workspace = true linux_sysno.workspace = true zerocopy = { version = "0.8.26", features = ["derive"] } +tee_kernel = { workspace = true, optional = true } -bincode = { version = "2.0.1", default-features = false, optional = true, features = [ - "alloc", - "derive", -] } -tee_raw_sys = { workspace = true, optional = true } -uuid = { version = "0.8", default-features = false, optional = true } -hex = { version = "0.4", default-features = false, optional = true, features = [ - "alloc", -] } cty = "0.2" kcore.workspace = true diff --git a/api/kapi/src/lib.rs b/api/kapi/src/lib.rs index da3d102210ececa302513e3588db8af0cd62dbee..d89f3a5f717be70e67dee79cbe520651b98eb143 100644 --- a/api/kapi/src/lib.rs +++ b/api/kapi/src/lib.rs @@ -23,11 +23,14 @@ pub mod socket; pub mod syscall; pub mod task; #[cfg(feature = "tee")] -pub mod tee; +pub use tee_kernel::tee; pub mod terminal; pub mod time; + +#[cfg(unittest)] +mod unittest_task; #[cfg(unittest)] -pub mod unittest_task; +pub use unittest_task::{register_unittest_runtime, run_with_test_user_thread}; pub mod vfs; /// Initializes VFS, /proc/interrupts accounting, and alarm task. diff --git a/api/kapi/src/syscall/mod.rs b/api/kapi/src/syscall/mod.rs index 759461fd803ed9c451f3b7f8b475d510e00733cc..6d3f66b49e5c927e834cb5935a88ffd27b19339b 100644 --- a/api/kapi/src/syscall/mod.rs +++ b/api/kapi/src/syscall/mod.rs @@ -651,7 +651,7 @@ pub fn dispatch_irq_syscall(uctx: &mut UserContext) { _ => { #[cfg(feature = "tee")] { - use tee_raw_sys::TEE_SUCCESS; + use tee_kernel::TEE_SUCCESS; use crate::tee::dispatch_irq_tee_syscall; diff --git a/api/kapi/src/task.rs b/api/kapi/src/task.rs index 010c6b099537cc44d92e761b82c38e78f72877fb..477a93ae80a1a9cc14db5c3a505130880092b389 100644 --- a/api/kapi/src/task.rs +++ b/api/kapi/src/task.rs @@ -24,10 +24,6 @@ use ktask::{TaskInner, current}; use linux_raw_sys::general::ROBUST_LIST_LIMIT; use osvm::{VirtMutPtr, VirtPtr}; -#[cfg(unittest)] -pub use crate::unittest_task::{ - TestUserArray, TestUserBuffer, TestUserValue, run_with_test_user_thread, -}; use crate::{ signal::{check_signals, unblock_next_signal}, syscall::dispatch_irq_syscall, diff --git a/api/kapi/src/unittest_task.rs b/api/kapi/src/unittest_task.rs index 7701f35c02eb74147a61a7895d47aa8c26ab06cf..5f07ed68fde98fdade8003c1ca5358d39504629d 100644 --- a/api/kapi/src/unittest_task.rs +++ b/api/kapi/src/unittest_task.rs @@ -2,32 +2,23 @@ // Copyright 2025 KylinSoft Co., Ltd. // See LICENSES for license details. -//! Unittest-only helpers for installing a simulated user thread and mapped user buffers. +//! Unittest-only helpers for installing a simulated user thread runtime. #![cfg(unittest)] -use alloc::{string::ToString, sync::Arc, vec, vec::Vec}; -use core::{ - marker::PhantomData, - mem::{MaybeUninit, size_of, transmute}, - ops::{Deref, DerefMut}, - sync::atomic::{AtomicU32, AtomicUsize, Ordering}, -}; +use alloc::{string::ToString, sync::Arc, vec}; +use core::sync::atomic::{AtomicU32, Ordering}; -use kcore::task::{AsThread, ProcessData, Thread}; -use kerrno::{KError, KResult}; -use khal::{mem::v2p, paging::MappingFlags}; +use kcore::task::{ProcessData, Thread}; +use kerrno::KResult; use kprocess::Pid; use ksignal::api::SignalActions; use ksync::{Mutex, spin::SpinNoIrq}; use ktask::{KTaskExt, TaskExt, current}; -use memaddr::{PAGE_SIZE_4K, PhysAddr, VirtAddr}; -use osvm::{read_vm_mem, write_vm_mem}; +use memaddr::PhysAddr; use unittest::{TestDescriptor, TestResult}; static NEXT_TEST_PROCESS_ID: AtomicU32 = AtomicU32::new(0x7000_0000); -static NEXT_TEST_USER_ADDR: AtomicUsize = AtomicUsize::new(kcore::config::USER_HEAP_BASE); - fn alloc_test_process_id() -> Pid { NEXT_TEST_PROCESS_ID.fetch_add(1, Ordering::Relaxed) } @@ -149,245 +140,3 @@ pub fn register_unittest_runtime() { run_with_test_user_thread(test, init_unittest_thread) }); } - -#[macro_export] -macro_rules! __unittest_user_vec { - ($value:expr; $len:expr) => {{ - $crate::unittest_task::TestUserArray::from_array([$value; $len]).unwrap() - }}; - ($($value:expr),+ $(,)?) => {{ - $crate::unittest_task::TestUserArray::from_array([$($value),+]).unwrap() - }}; -} - -pub use crate::__unittest_user_vec as user_vec; - -pub struct TestUserBuffer { - aspace: Arc>, - user_addr: usize, - mapped_size: usize, - kernel_va: usize, - num_pages: usize, - len: usize, -} - -impl TestUserBuffer { - pub fn new(len: usize) -> KResult { - let current_task = current(); - let thread = current_task.try_as_thread().ok_or(KError::BadState)?; - let aspace = thread.proc_data.aspace.clone(); - let mapped_size = len.max(1).next_multiple_of(PAGE_SIZE_4K); - let num_pages = mapped_size / PAGE_SIZE_4K; - let kernel_va = kalloc::global_allocator() - .alloc_pages(num_pages, PAGE_SIZE_4K, kalloc::UsageKind::VirtMem) - .map_err(|_| KError::NoMemory)?; - - unsafe { - core::ptr::write_bytes(kernel_va as *mut u8, 0, mapped_size); - } - - let user_addr = NEXT_TEST_USER_ADDR.fetch_add(mapped_size, Ordering::Relaxed); - aspace - .lock() - .map_linear( - VirtAddr::from_usize(user_addr), - v2p(VirtAddr::from_usize(kernel_va)), - mapped_size, - MappingFlags::READ | MappingFlags::WRITE | MappingFlags::USER, - ) - .map_err(|_| { - kalloc::global_allocator().dealloc_pages( - kernel_va, - num_pages, - kalloc::UsageKind::VirtMem, - ); - KError::NoMemory - })?; - - Ok(Self { - aspace, - user_addr, - mapped_size, - kernel_va, - num_pages, - len, - }) - } - - pub fn write_bytes(&self, data: &[u8]) -> KResult { - if data.len() > self.len { - return Err(KError::InvalidInput); - } - write_vm_mem(self.user_addr as *mut u8, data).map_err(Into::into) - } - - pub fn read_bytes(&self, len: usize) -> KResult> { - if len > self.len { - return Err(KError::InvalidInput); - } - let mut out = vec![0u8; len]; - read_vm_mem(self.user_addr as *const u8, unsafe { - transmute::<&mut [u8], &mut [MaybeUninit]>(&mut out[..]) - }) - .map_err(KError::from)?; - Ok(out) - } - - pub fn write_u64(&self, value: u64) -> KResult { - write_vm_mem(self.user_addr as *mut u64, core::slice::from_ref(&value)).map_err(Into::into) - } - - pub fn read_u64(&self) -> KResult { - let mut out = 0u64; - let out_slice = unsafe { - core::slice::from_raw_parts_mut((&mut out as *mut u64).cast::>(), 1) - }; - read_vm_mem(self.user_addr as *const u64, out_slice).map_err(KError::from)?; - Ok(out) - } - - pub fn len(&self) -> usize { - self.len - } - - pub fn as_user_ptr(&self) -> *mut T { - assert!(size_of::() <= self.len); - self.user_addr as *mut T - } - - pub fn as_user_slice(&mut self, len: usize) -> &mut [u8] { - assert!(len <= self.len); - unsafe { core::slice::from_raw_parts_mut(self.user_addr as *mut u8, len) } - } - - pub fn as_user_ref(&mut self) -> &mut T { - assert!(core::mem::size_of::() <= self.len); - unsafe { &mut *(self.user_addr as *mut T) } - } -} - -pub struct TestUserValue { - buffer: TestUserBuffer, - _marker: PhantomData, -} - -impl TestUserValue { - pub fn new() -> KResult { - Ok(Self { - buffer: TestUserBuffer::new(size_of::())?, - _marker: PhantomData, - }) - } - - pub fn from_value(value: T) -> KResult - where - T: Copy, - { - let mut user_value = Self::new()?; - user_value.write(value); - Ok(user_value) - } - - pub fn as_user_ref(&mut self) -> &mut T { - self.buffer.as_user_ref::() - } - - pub fn as_user_ptr(&self) -> *mut T { - self.buffer.as_user_ptr::() - } - - pub fn write(&mut self, value: T) - where - T: Copy, - { - *self.as_user_ref() = value; - } - - pub fn read(&self) -> T - where - T: Copy, - { - unsafe { self.as_user_ptr().read() } - } -} - -pub struct TestUserArray { - buffer: TestUserBuffer, - _marker: PhantomData, -} - -impl TestUserArray { - pub fn new() -> KResult { - Ok(Self { - buffer: TestUserBuffer::new(size_of::<[T; N]>())?, - _marker: PhantomData, - }) - } - - pub fn from_array(value: [T; N]) -> KResult - where - T: Copy, - { - let mut user_array = Self::new()?; - user_array.write(value); - Ok(user_array) - } - - pub fn len(&self) -> usize { - N - } - - pub fn as_user_slice(&mut self) -> &mut [T] { - unsafe { core::slice::from_raw_parts_mut(self.as_user_ptr(), N) } - } - - pub fn as_user_ref(&mut self) -> &mut [T; N] { - unsafe { &mut *(self.as_user_ptr() as *mut [T; N]) } - } - - pub fn as_user_ptr(&self) -> *mut T { - self.buffer.as_user_ptr::() - } - - pub fn write(&mut self, value: [T; N]) - where - T: Copy, - { - self.as_user_slice().copy_from_slice(&value); - } - - pub fn read(&self) -> [T; N] - where - T: Copy, - { - unsafe { (self.as_user_ptr() as *const [T; N]).read() } - } -} - -impl Deref for TestUserArray { - type Target = [T]; - - fn deref(&self) -> &Self::Target { - unsafe { core::slice::from_raw_parts(self.as_user_ptr(), N) } - } -} - -impl DerefMut for TestUserArray { - fn deref_mut(&mut self) -> &mut Self::Target { - self.as_user_slice() - } -} - -impl Drop for TestUserBuffer { - fn drop(&mut self) { - let _ = self - .aspace - .lock() - .unmap(VirtAddr::from_usize(self.user_addr), self.mapped_size); - kalloc::global_allocator().dealloc_pages( - self.kernel_va, - self.num_pages, - kalloc::UsageKind::VirtMem, - ); - } -} diff --git a/entry/src/main.rs b/entry/src/main.rs index 70ad099f72f7cd66c0bfc47a9d5ee1538d5e5093..d5fc1659363009aad5e8641418c4225033b5f81a 100644 --- a/entry/src/main.rs +++ b/entry/src/main.rs @@ -53,7 +53,7 @@ fn main() { #[unsafe(no_mangle)] fn main() { kapi::init(); - kapi::unittest_task::register_unittest_runtime(); + kapi::register_unittest_runtime(); { let cx = kfs::FS_CONTEXT.lock(); diff --git a/tee/tee_kernel/Cargo.toml b/tee/tee_kernel/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..7710305badf73cf6354a399268cc7c14d629ca1d --- /dev/null +++ b/tee/tee_kernel/Cargo.toml @@ -0,0 +1,77 @@ +[package] +name = "tee_kernel" +description = "TEE support crate extracted from kapi for X-Kernel" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +documentation.workspace = true + +[features] +default = ["linux_sysno/tee", "kalloc/tee", "tee_ss_smx"] +tee_cfg_memtag = [] +tee_ss_smx = [] +x86_csv = ["dep:kcpu"] + +[dependencies] +kalloc.workspace = true +unittest.workspace = true +unittest_support.workspace = true +rust-dice = { workspace = true, optional = true } +mbedtls = { workspace = true } +mbedtls-sys-auto = { workspace = true } +ktypes.workspace = true +kcpu = { workspace = true, optional = true } +kerrno.workspace = true +kfeat.workspace = true +fs-ng-vfs.workspace = true +kfs.workspace = true +khal.workspace = true +karch.workspace = true +kio.workspace = true +klogger.workspace = true +memspace.workspace = true +knet.workspace = true +kpoll.workspace = true +ksync.workspace = true +ktask.workspace = true +bitflags.workspace = true +bytemuck.workspace = true +cfg-if.workspace = true +chrono = { version = "0.4.41", default-features = false } +hashbrown = { workspace = true } +lazy_static = { workspace = true } +linux-raw-sys = { workspace = true, features = ["ioctl", "loop_device"] } +memaddr.workspace = true +osvm.workspace = true +kprocess.workspace = true +linux_sysno.workspace = true +zerocopy = { version = "0.8.26", features = ["derive"] } +bincode = { version = "2.0.1", default-features = false, features = ["alloc", "derive"] } +tee_raw_sys = { workspace = true } +uuid = { version = "0.8", default-features = false } +hex = { version = "0.4", default-features = false, features = ["alloc"] } +cty = "0.2" +kcore.workspace = true +subtle = { version = "2", default-features = false } +static_assertions = "1.1.0" +memoffset = { version = "0.9", default-features = false } +flatten_objects = "0.2.4" +rand_chacha = { version = "0.3", default-features = false } +scope-local = { workspace = true } +slab = { workspace = true } +rand = { version = "0.9.1", default-features = false, features = [ + "alloc", + "small_rng", +] } + +[target.'cfg(target_arch = "x86_64")'.dependencies] +x86 = "0.52" + +[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies] +riscv = "0.14" + +# [dev-dependencies] +# kapi = { path = "../../api/kapi" } diff --git a/tee/tee_kernel/src/file.rs b/tee/tee_kernel/src/file.rs new file mode 100644 index 0000000000000000000000000000000000000000..4ddeccf1f8d8d6de0ae83edd3571832070863da2 --- /dev/null +++ b/tee/tee_kernel/src/file.rs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2025 KylinSoft Co., Ltd. +// See LICENSES for license details. + +use core::ffi::c_int; + +use fs_ng_vfs::{Location, Metadata}; +use kerrno::{KError, KResult}; +use kfs::{FS_CONTEXT, FsContext}; +use linux_raw_sys::general::{AT_FDCWD, AT_SYMLINK_NOFOLLOW}; + +pub fn with_fs(dirfd: c_int, f: impl FnOnce(&mut FsContext) -> KResult) -> KResult { + if dirfd != AT_FDCWD { + return Err(KError::InvalidInput); + } + + let mut fs = FS_CONTEXT.lock(); + f(&mut fs) +} + +pub enum ResolveAtResult { + File(Location), +} + +impl ResolveAtResult { + pub fn stat(&self) -> KResult { + match self { + Self::File(file) => file.metadata(), + } + } +} + +pub fn resolve_at(dirfd: c_int, path: Option<&str>, flags: u32) -> KResult { + let path = path + .filter(|path| !path.is_empty()) + .ok_or(KError::NotFound)?; + + with_fs(dirfd, |fs| { + if flags & AT_SYMLINK_NOFOLLOW != 0 { + fs.resolve_no_follow(path) + } else { + fs.resolve(path) + } + .map(ResolveAtResult::File) + }) +} diff --git a/tee/tee_kernel/src/lib.rs b/tee/tee_kernel/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..695589b7da2286ef24de55fd31e17e9852e1a80a --- /dev/null +++ b/tee/tee_kernel/src/lib.rs @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2025 KylinSoft Co., Ltd. +// See LICENSES for license details. + +#![no_std] +#![allow(missing_docs)] + +#[macro_use] +extern crate klogger; + +extern crate alloc; + +pub mod file; +pub mod mm; +pub mod tee; +pub use tee_raw_sys::TEE_SUCCESS; +#[cfg(unittest)] +pub use unittest_support::{TestUserArray, TestUserBuffer, TestUserValue, user_vec}; diff --git a/tee/tee_kernel/src/mm.rs b/tee/tee_kernel/src/mm.rs new file mode 100644 index 0000000000000000000000000000000000000000..9cde27277aff28530e451e683f61796aa6dcb60f --- /dev/null +++ b/tee/tee_kernel/src/mm.rs @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2025 KylinSoft Co., Ltd. +// See LICENSES for license details. + +use alloc::string::String; +use core::ffi::c_char; + +use kerrno::{KError, KResult}; +use osvm::{load_vec, load_vec_until_null}; + +pub fn vm_load_string(ptr: *const c_char) -> KResult { + #[allow(clippy::unnecessary_cast)] + let bytes = load_vec_until_null(ptr as *const u8)?; + String::from_utf8(bytes).map_err(|_| KError::IllegalBytes) +} + +pub fn vm_load_string_with_len(ptr: *const c_char, len: usize) -> KResult { + #[allow(clippy::unnecessary_cast)] + let bytes = load_vec(ptr as *const u8, len)?; + String::from_utf8(bytes).map_err(|_| KError::IllegalBytes) +} diff --git a/api/kapi/src/tee/README.md b/tee/tee_kernel/src/tee/README.md similarity index 100% rename from api/kapi/src/tee/README.md rename to tee/tee_kernel/src/tee/README.md diff --git a/api/kapi/src/tee/arch/mod.rs b/tee/tee_kernel/src/tee/arch/mod.rs similarity index 100% rename from api/kapi/src/tee/arch/mod.rs rename to tee/tee_kernel/src/tee/arch/mod.rs diff --git a/api/kapi/src/tee/arch/x86_64/hygon_csv.rs b/tee/tee_kernel/src/tee/arch/x86_64/hygon_csv.rs similarity index 100% rename from api/kapi/src/tee/arch/x86_64/hygon_csv.rs rename to tee/tee_kernel/src/tee/arch/x86_64/hygon_csv.rs diff --git a/api/kapi/src/tee/arch/x86_64/hygon_csv_bindings.rs b/tee/tee_kernel/src/tee/arch/x86_64/hygon_csv_bindings.rs similarity index 100% rename from api/kapi/src/tee/arch/x86_64/hygon_csv_bindings.rs rename to tee/tee_kernel/src/tee/arch/x86_64/hygon_csv_bindings.rs diff --git a/api/kapi/src/tee/arch/x86_64/mod.rs b/tee/tee_kernel/src/tee/arch/x86_64/mod.rs similarity index 100% rename from api/kapi/src/tee/arch/x86_64/mod.rs rename to tee/tee_kernel/src/tee/arch/x86_64/mod.rs diff --git a/api/kapi/src/tee/bitstring.rs b/tee/tee_kernel/src/tee/bitstring.rs similarity index 100% rename from api/kapi/src/tee/bitstring.rs rename to tee/tee_kernel/src/tee/bitstring.rs diff --git a/api/kapi/src/tee/common/array.rs b/tee/tee_kernel/src/tee/common/array.rs similarity index 100% rename from api/kapi/src/tee/common/array.rs rename to tee/tee_kernel/src/tee/common/array.rs diff --git a/api/kapi/src/tee/common/file_ops.rs b/tee/tee_kernel/src/tee/common/file_ops.rs similarity index 100% rename from api/kapi/src/tee/common/file_ops.rs rename to tee/tee_kernel/src/tee/common/file_ops.rs diff --git a/api/kapi/src/tee/common/mod.rs b/tee/tee_kernel/src/tee/common/mod.rs similarity index 100% rename from api/kapi/src/tee/common/mod.rs rename to tee/tee_kernel/src/tee/common/mod.rs diff --git a/api/kapi/src/tee/config.rs b/tee/tee_kernel/src/tee/config.rs similarity index 100% rename from api/kapi/src/tee/config.rs rename to tee/tee_kernel/src/tee/config.rs diff --git a/api/kapi/src/tee/crypto/crypto.rs b/tee/tee_kernel/src/tee/crypto/crypto.rs similarity index 100% rename from api/kapi/src/tee/crypto/crypto.rs rename to tee/tee_kernel/src/tee/crypto/crypto.rs diff --git a/api/kapi/src/tee/crypto/crypto_impl.rs b/tee/tee_kernel/src/tee/crypto/crypto_impl.rs similarity index 100% rename from api/kapi/src/tee/crypto/crypto_impl.rs rename to tee/tee_kernel/src/tee/crypto/crypto_impl.rs diff --git a/api/kapi/src/tee/crypto/mod.rs b/tee/tee_kernel/src/tee/crypto/mod.rs similarity index 100% rename from api/kapi/src/tee/crypto/mod.rs rename to tee/tee_kernel/src/tee/crypto/mod.rs diff --git a/api/kapi/src/tee/crypto/sm3_hash.rs b/tee/tee_kernel/src/tee/crypto/sm3_hash.rs similarity index 100% rename from api/kapi/src/tee/crypto/sm3_hash.rs rename to tee/tee_kernel/src/tee/crypto/sm3_hash.rs diff --git a/api/kapi/src/tee/crypto/sm3_hmac.rs b/tee/tee_kernel/src/tee/crypto/sm3_hmac.rs similarity index 100% rename from api/kapi/src/tee/crypto/sm3_hmac.rs rename to tee/tee_kernel/src/tee/crypto/sm3_hmac.rs diff --git a/api/kapi/src/tee/fs_dirfile.rs b/tee/tee_kernel/src/tee/fs_dirfile.rs similarity index 100% rename from api/kapi/src/tee/fs_dirfile.rs rename to tee/tee_kernel/src/tee/fs_dirfile.rs diff --git a/api/kapi/src/tee/fs_htree.rs b/tee/tee_kernel/src/tee/fs_htree.rs similarity index 100% rename from api/kapi/src/tee/fs_htree.rs rename to tee/tee_kernel/src/tee/fs_htree.rs diff --git a/api/kapi/src/tee/fs_htree_tests.rs b/tee/tee_kernel/src/tee/fs_htree_tests.rs similarity index 100% rename from api/kapi/src/tee/fs_htree_tests.rs rename to tee/tee_kernel/src/tee/fs_htree_tests.rs diff --git a/api/kapi/src/tee/huk_subkey.rs b/tee/tee_kernel/src/tee/huk_subkey.rs similarity index 100% rename from api/kapi/src/tee/huk_subkey.rs rename to tee/tee_kernel/src/tee/huk_subkey.rs diff --git a/api/kapi/src/tee/libmbedtls/bignum.rs b/tee/tee_kernel/src/tee/libmbedtls/bignum.rs similarity index 100% rename from api/kapi/src/tee/libmbedtls/bignum.rs rename to tee/tee_kernel/src/tee/libmbedtls/bignum.rs diff --git a/api/kapi/src/tee/libmbedtls/ecc.rs b/tee/tee_kernel/src/tee/libmbedtls/ecc.rs similarity index 100% rename from api/kapi/src/tee/libmbedtls/ecc.rs rename to tee/tee_kernel/src/tee/libmbedtls/ecc.rs diff --git a/api/kapi/src/tee/libmbedtls/mod.rs b/tee/tee_kernel/src/tee/libmbedtls/mod.rs similarity index 100% rename from api/kapi/src/tee/libmbedtls/mod.rs rename to tee/tee_kernel/src/tee/libmbedtls/mod.rs diff --git a/api/kapi/src/tee/libmbedtls/rsa.rs b/tee/tee_kernel/src/tee/libmbedtls/rsa.rs similarity index 100% rename from api/kapi/src/tee/libmbedtls/rsa.rs rename to tee/tee_kernel/src/tee/libmbedtls/rsa.rs diff --git a/api/kapi/src/tee/libutee/mod.rs b/tee/tee_kernel/src/tee/libutee/mod.rs similarity index 100% rename from api/kapi/src/tee/libutee/mod.rs rename to tee/tee_kernel/src/tee/libutee/mod.rs diff --git a/api/kapi/src/tee/libutee/tee_api_objects.rs b/tee/tee_kernel/src/tee/libutee/tee_api_objects.rs similarity index 100% rename from api/kapi/src/tee/libutee/tee_api_objects.rs rename to tee/tee_kernel/src/tee/libutee/tee_api_objects.rs diff --git a/api/kapi/src/tee/libutee/utee_defines.rs b/tee/tee_kernel/src/tee/libutee/utee_defines.rs similarity index 99% rename from api/kapi/src/tee/libutee/utee_defines.rs rename to tee/tee_kernel/src/tee/libutee/utee_defines.rs index 9b80b8e3fafedc5a09e1319e0dcb9a58b5ee2557..a984f63a6f4bb67bf1b11a67c2f7b2f7a9e2e476 100644 --- a/api/kapi/src/tee/libutee/utee_defines.rs +++ b/tee/tee_kernel/src/tee/libutee/utee_defines.rs @@ -4,7 +4,6 @@ use tee_raw_sys::*; -#[cfg(feature = "tee")] use crate::tee::{ TEE_ALG_DES3_CMAC, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5, TEE_ALG_RSASSA_PKCS1_V1_5, TEE_ALG_SHAKE128, TEE_ALG_SHAKE256, TEE_ALG_SM4_XTS, TEE_ALG_X448, diff --git a/api/kapi/src/tee/macros.rs b/tee/tee_kernel/src/tee/macros.rs similarity index 100% rename from api/kapi/src/tee/macros.rs rename to tee/tee_kernel/src/tee/macros.rs diff --git a/api/kapi/src/tee/memtag.rs b/tee/tee_kernel/src/tee/memtag.rs similarity index 100% rename from api/kapi/src/tee/memtag.rs rename to tee/tee_kernel/src/tee/memtag.rs diff --git a/api/kapi/src/tee/mod.rs b/tee/tee_kernel/src/tee/mod.rs similarity index 100% rename from api/kapi/src/tee/mod.rs rename to tee/tee_kernel/src/tee/mod.rs diff --git a/api/kapi/src/tee/otp_stubs.rs b/tee/tee_kernel/src/tee/otp_stubs.rs similarity index 100% rename from api/kapi/src/tee/otp_stubs.rs rename to tee/tee_kernel/src/tee/otp_stubs.rs diff --git a/api/kapi/src/tee/protocal.rs b/tee/tee_kernel/src/tee/protocal.rs similarity index 100% rename from api/kapi/src/tee/protocal.rs rename to tee/tee_kernel/src/tee/protocal.rs diff --git a/api/kapi/src/tee/ree_fs_rpc.rs b/tee/tee_kernel/src/tee/ree_fs_rpc.rs similarity index 100% rename from api/kapi/src/tee/ree_fs_rpc.rs rename to tee/tee_kernel/src/tee/ree_fs_rpc.rs diff --git a/api/kapi/src/tee/rng_software.rs b/tee/tee_kernel/src/tee/rng_software.rs similarity index 100% rename from api/kapi/src/tee/rng_software.rs rename to tee/tee_kernel/src/tee/rng_software.rs diff --git a/api/kapi/src/tee/tee_api_defines_extensions.rs b/tee/tee_kernel/src/tee/tee_api_defines_extensions.rs similarity index 100% rename from api/kapi/src/tee/tee_api_defines_extensions.rs rename to tee/tee_kernel/src/tee/tee_api_defines_extensions.rs diff --git a/api/kapi/src/tee/tee_cancel.rs b/tee/tee_kernel/src/tee/tee_cancel.rs similarity index 100% rename from api/kapi/src/tee/tee_cancel.rs rename to tee/tee_kernel/src/tee/tee_cancel.rs diff --git a/api/kapi/src/tee/tee_fs.rs b/tee/tee_kernel/src/tee/tee_fs.rs similarity index 100% rename from api/kapi/src/tee/tee_fs.rs rename to tee/tee_kernel/src/tee/tee_fs.rs diff --git a/api/kapi/src/tee/tee_fs_key_manager.rs b/tee/tee_kernel/src/tee/tee_fs_key_manager.rs similarity index 100% rename from api/kapi/src/tee/tee_fs_key_manager.rs rename to tee/tee_kernel/src/tee/tee_fs_key_manager.rs diff --git a/api/kapi/src/tee/tee_generic.rs b/tee/tee_kernel/src/tee/tee_generic.rs similarity index 100% rename from api/kapi/src/tee/tee_generic.rs rename to tee/tee_kernel/src/tee/tee_generic.rs diff --git a/api/kapi/src/tee/tee_inter_ta.rs b/tee/tee_kernel/src/tee/tee_inter_ta.rs similarity index 100% rename from api/kapi/src/tee/tee_inter_ta.rs rename to tee/tee_kernel/src/tee/tee_inter_ta.rs diff --git a/api/kapi/src/tee/tee_misc.rs b/tee/tee_kernel/src/tee/tee_misc.rs similarity index 100% rename from api/kapi/src/tee/tee_misc.rs rename to tee/tee_kernel/src/tee/tee_misc.rs diff --git a/api/kapi/src/tee/tee_obj.rs b/tee/tee_kernel/src/tee/tee_obj.rs similarity index 100% rename from api/kapi/src/tee/tee_obj.rs rename to tee/tee_kernel/src/tee/tee_obj.rs diff --git a/api/kapi/src/tee/tee_pobj.rs b/tee/tee_kernel/src/tee/tee_pobj.rs similarity index 100% rename from api/kapi/src/tee/tee_pobj.rs rename to tee/tee_kernel/src/tee/tee_pobj.rs diff --git a/api/kapi/src/tee/tee_property.rs b/tee/tee_kernel/src/tee/tee_property.rs similarity index 100% rename from api/kapi/src/tee/tee_property.rs rename to tee/tee_kernel/src/tee/tee_property.rs diff --git a/api/kapi/src/tee/tee_ree_fs.rs b/tee/tee_kernel/src/tee/tee_ree_fs.rs similarity index 100% rename from api/kapi/src/tee/tee_ree_fs.rs rename to tee/tee_kernel/src/tee/tee_ree_fs.rs diff --git a/api/kapi/src/tee/tee_session.rs b/tee/tee_kernel/src/tee/tee_session.rs similarity index 100% rename from api/kapi/src/tee/tee_session.rs rename to tee/tee_kernel/src/tee/tee_session.rs diff --git a/api/kapi/src/tee/tee_svc_cryp.rs b/tee/tee_kernel/src/tee/tee_svc_cryp.rs similarity index 99% rename from api/kapi/src/tee/tee_svc_cryp.rs rename to tee/tee_kernel/src/tee/tee_svc_cryp.rs index 48ddc3367e8ccc43c020ebf0ba59e49f76a6213d..b66176417dd99d8d8b0329a3dd294ac8f185f4c7 100644 --- a/api/kapi/src/tee/tee_svc_cryp.rs +++ b/tee/tee_kernel/src/tee/tee_svc_cryp.rs @@ -2810,7 +2810,7 @@ pub mod tests_tee_svc_cryp { use zerocopy::IntoBytes; use super::*; - use crate::unittest_task::TestUserValue; + use crate::TestUserValue; #[unittest::def_test] fn test_tee_svc_cryp_utils() { @@ -2874,7 +2874,7 @@ pub mod tests_tee_svc_cryp { #[unittest::def_test(custom)] fn test_op_attr_secret_value_from_user() { // 测试基础数据 - let mut user_key = crate::unittest_task::user_vec![0xAAu8; 16]; + let mut user_key = crate::user_vec![0xAAu8; 16]; let mut secret_wrapper = tee_cryp_obj_secret_wrapper::new(32); // 从用户空间导入密钥 @@ -2886,7 +2886,7 @@ pub mod tests_tee_svc_cryp { assert_eq!(&secret_wrapper.data()[..16], &user_key.read()); // 测试长度超出分配大小的情况 - let mut long_user_key = crate::unittest_task::user_vec![0xBBu8; 40]; + let mut long_user_key = crate::user_vec![0xBBu8; 40]; let result = op_attr_secret_value_from_user(&mut secret_wrapper, long_user_key.as_user_slice()); assert_eq!(result.err(), Some(TEE_ERROR_SHORT_BUFFER)); @@ -2911,7 +2911,7 @@ pub mod tests_tee_svc_cryp { assert_eq!(size.read(), 16); // 第二次调用,提供足够大的 buffer - let mut user_buffer = crate::unittest_task::user_vec![0u8; 32]; + let mut user_buffer = crate::user_vec![0u8; 32]; size.write(32); let result = op_attr_secret_value_to_user( &secret_wrapper, @@ -3013,7 +3013,7 @@ pub mod tests_tee_svc_cryp { attr[..4].copy_from_slice(value_bytes); let mut size = TestUserValue::::from_value(8).unwrap(); - let mut user_buffer = crate::unittest_task::user_vec![0u8; 8]; + let mut user_buffer = crate::user_vec![0u8; 8]; let result = op_attr_value_to_user(&attr, user_buffer.as_user_slice(), size.as_user_ref()); assert!(result.is_ok()); @@ -3090,14 +3090,14 @@ pub mod tests_tee_svc_cryp { }; { let mut attr_ref = CryptoAttrRef::U32(&mut value); - let mut value_bytes_user = crate::unittest_task::user_vec![0u8; 8]; + let mut value_bytes_user = crate::user_vec![0u8; 8]; value_bytes_user.copy_from_slice(value_bytes); let result = attr_ref.update_from_user(value_bytes_user.as_user_slice()); assert!(result.is_ok()); } assert_eq!(value, 0x11223344); - let mut buffer = crate::unittest_task::user_vec![0u8; 8]; + let mut buffer = crate::user_vec![0u8; 8]; let mut size = TestUserValue::::from_value(8).unwrap(); { let attr_ref = CryptoAttrRef::U32(&mut value); @@ -3112,7 +3112,7 @@ pub mod tests_tee_svc_cryp { fn test_cryptoattrref_bignum() { // test CryptoAttrRef::BigNum let bn = BigNum::new(0x11223344).unwrap(); - let mut buffer = crate::unittest_task::user_vec![0u8; 4]; + let mut buffer = crate::user_vec![0u8; 4]; let mut size = TestUserValue::::from_value(4).unwrap(); let result = bn.to_user(buffer.as_user_slice(), size.as_user_ref()); assert!(result.is_ok()); @@ -3134,7 +3134,7 @@ pub mod tests_tee_svc_cryp { // 1. test tee_cryp_obj_secret_wrapper to user // - test to_user - let mut buffer = crate::unittest_task::user_vec![0u8; 16]; + let mut buffer = crate::user_vec![0u8; 16]; let mut size = TestUserValue::::from_value(16).unwrap(); let result = secret.to_user(buffer.as_user_slice(), size.as_user_ref()); assert!(result.is_ok()); @@ -3263,8 +3263,8 @@ pub mod tests_tee_svc_cryp { // Helper function to test RSA keypair generation and verification fn test_rsa_keypair(key_size: usize, e: u64) -> TestResult { let mut e_bytes: [u8; 8] = [0; 8]; - let mut usr_params = crate::unittest_task::user_vec![utee_attribute::default(); 1]; - let mut usr_exp = crate::unittest_task::user_vec![0u8; 8]; + let mut usr_params = crate::user_vec![utee_attribute::default(); 1]; + let mut usr_exp = crate::user_vec![0u8; 8]; let (usr_params, param_count) = { if e == 0 { @@ -3402,14 +3402,14 @@ pub mod tests_tee_svc_cryp { }; let mut attrs: [TEE_Attribute; 2] = [tee_attr_value; 2]; - let mut usr_attrs = crate::unittest_task::user_vec![utee_attribute::default(); 2]; + let mut usr_attrs = crate::user_vec![utee_attribute::default(); 2]; // index 0 is value attribute usr_attrs[0].attribute_id = TEE_ATTR_FLAG_VALUE; usr_attrs[0].a = 0x11223344_u64; usr_attrs[0].b = 0x55667788_u64; // index 1 is memref attribute // allocate memory for memref - let mem = crate::unittest_task::user_vec![0xAAu8; 16]; + let mem = crate::user_vec![0xAAu8; 16]; let mem_ptr = mem.as_user_ptr() as *mut c_void; usr_attrs[1].attribute_id &= !TEE_ATTR_FLAG_VALUE; usr_attrs[1].a = mem_ptr as u64; diff --git a/api/kapi/src/tee/tee_svc_cryp2.rs b/tee/tee_kernel/src/tee/tee_svc_cryp2.rs similarity index 99% rename from api/kapi/src/tee/tee_svc_cryp2.rs rename to tee/tee_kernel/src/tee/tee_svc_cryp2.rs index 6f3fb01c592aafd0785d637eda099a58046b2ff1..ac5a495bbdeef4a80f2d1f2d00774ec0fb8f883f 100644 --- a/api/kapi/src/tee/tee_svc_cryp2.rs +++ b/tee/tee_kernel/src/tee/tee_svc_cryp2.rs @@ -1491,10 +1491,10 @@ pub mod tests_cryp { use super::*; use crate::{ + TestUserValue, tee::tee_svc_cryp::{ syscall_cryp_obj_alloc, syscall_cryp_obj_copy, syscall_obj_generate_key, }, - unittest_task::TestUserValue, }; #[unittest::def_test(custom)] diff --git a/api/kapi/src/tee/tee_svc_storage.rs b/tee/tee_kernel/src/tee/tee_svc_storage.rs similarity index 99% rename from api/kapi/src/tee/tee_svc_storage.rs rename to tee/tee_kernel/src/tee/tee_svc_storage.rs index 8887c3427332eb8cc1d8ed8ef46e6f2edf137f11..ccc8c0b58b6f219c49d3feb373b005262debbb06 100644 --- a/api/kapi/src/tee/tee_svc_storage.rs +++ b/tee/tee_kernel/src/tee/tee_svc_storage.rs @@ -1419,7 +1419,7 @@ pub mod tests_tee_svc_storage { use unittest::{assert, assert_eq}; use super::*; - use crate::unittest_task::{TestUserBuffer, TestUserValue}; + use crate::{TestUserBuffer, TestUserValue}; const TEE_DIRNAME_BUFFER_REQUIRED_LEN: usize = tee_b2hs_hsbuf_size(TEE_UUID_HEX_LEN) + 1; diff --git a/api/kapi/src/tee/tee_ta_manager.rs b/tee/tee_kernel/src/tee/tee_ta_manager.rs similarity index 100% rename from api/kapi/src/tee/tee_ta_manager.rs rename to tee/tee_kernel/src/tee/tee_ta_manager.rs diff --git a/api/kapi/src/tee/tee_time.rs b/tee/tee_kernel/src/tee/tee_time.rs similarity index 100% rename from api/kapi/src/tee/tee_time.rs rename to tee/tee_kernel/src/tee/tee_time.rs diff --git a/api/kapi/src/tee/types_ext.rs b/tee/tee_kernel/src/tee/types_ext.rs similarity index 100% rename from api/kapi/src/tee/types_ext.rs rename to tee/tee_kernel/src/tee/types_ext.rs diff --git a/api/kapi/src/tee/user_access.rs b/tee/tee_kernel/src/tee/user_access.rs similarity index 99% rename from api/kapi/src/tee/user_access.rs rename to tee/tee_kernel/src/tee/user_access.rs index d7be05ed137794a246863ca5f578bab054527d8c..fec26368ec299419bb0a008c7c6fba648c5fe1e0 100644 --- a/api/kapi/src/tee/user_access.rs +++ b/tee/tee_kernel/src/tee/user_access.rs @@ -167,7 +167,7 @@ pub mod tests_user_access { use unittest::{assert, assert_eq}; use super::*; - use crate::unittest_task::{TestUserBuffer, TestUserValue}; + use crate::{TestUserBuffer, TestUserValue}; fn user_buffer_from_bytes(bytes: &[u8]) -> TestUserBuffer { let buffer = TestUserBuffer::new(bytes.len()).unwrap(); diff --git a/api/kapi/src/tee/user_ta.rs b/tee/tee_kernel/src/tee/user_ta.rs similarity index 100% rename from api/kapi/src/tee/user_ta.rs rename to tee/tee_kernel/src/tee/user_ta.rs diff --git a/api/kapi/src/tee/utee_defines.rs b/tee/tee_kernel/src/tee/utee_defines.rs similarity index 100% rename from api/kapi/src/tee/utee_defines.rs rename to tee/tee_kernel/src/tee/utee_defines.rs diff --git a/api/kapi/src/tee/utils.rs b/tee/tee_kernel/src/tee/utils.rs similarity index 100% rename from api/kapi/src/tee/utils.rs rename to tee/tee_kernel/src/tee/utils.rs diff --git a/api/kapi/src/tee/uuid.rs b/tee/tee_kernel/src/tee/uuid.rs similarity index 100% rename from api/kapi/src/tee/uuid.rs rename to tee/tee_kernel/src/tee/uuid.rs diff --git a/api/kapi/src/tee/vm.rs b/tee/tee_kernel/src/tee/vm.rs similarity index 100% rename from api/kapi/src/tee/vm.rs rename to tee/tee_kernel/src/tee/vm.rs diff --git a/util/unittest_support/Cargo.toml b/util/unittest_support/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..47089e5953c9818be32eb2bf835d82fb58e8bf27 --- /dev/null +++ b/util/unittest_support/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "unittest_support" +description = "Shared unittest user-memory helpers for X-Kernel crates" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +documentation.workspace = true + +[dependencies] +kalloc.workspace = true +kcore.workspace = true +kerrno.workspace = true +khal.workspace = true +ksync.workspace = true +ktask.workspace = true +memaddr.workspace = true +memspace.workspace = true +osvm.workspace = true \ No newline at end of file diff --git a/util/unittest_support/src/lib.rs b/util/unittest_support/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..82425aac4d317239716b2d69bcf6c1c833d0528b --- /dev/null +++ b/util/unittest_support/src/lib.rs @@ -0,0 +1,264 @@ +#![no_std] +#![allow(missing_docs)] + +extern crate alloc; + +use alloc::{sync::Arc, vec, vec::Vec}; +use core::{ + marker::PhantomData, + mem::{MaybeUninit, size_of, transmute}, + ops::{Deref, DerefMut}, + sync::atomic::{AtomicUsize, Ordering}, +}; + +use kcore::task::AsThread; +use kerrno::{KError, KResult}; +use khal::{mem::v2p, paging::MappingFlags}; +use ksync::Mutex; +use ktask::current; +use memaddr::{PAGE_SIZE_4K, VirtAddr}; +use osvm::{read_vm_mem, write_vm_mem}; + +static NEXT_TEST_USER_ADDR: AtomicUsize = AtomicUsize::new(kcore::config::USER_HEAP_BASE); + +#[macro_export] +macro_rules! __unittest_support_user_vec { + ($value:expr; $len:expr) => {{ + $crate::TestUserArray::from_array([$value; $len]).unwrap() + }}; + ($($value:expr),+ $(,)?) => {{ + $crate::TestUserArray::from_array([$($value),+]).unwrap() + }}; +} + +pub use crate::__unittest_support_user_vec as user_vec; + +pub struct TestUserBuffer { + aspace: Arc>, + user_addr: usize, + mapped_size: usize, + kernel_va: usize, + num_pages: usize, + len: usize, +} + +impl TestUserBuffer { + pub fn new(len: usize) -> KResult { + let current_task = current(); + let thread = current_task.try_as_thread().ok_or(KError::BadState)?; + let aspace = thread.proc_data.aspace.clone(); + let mapped_size = len.max(1).next_multiple_of(PAGE_SIZE_4K); + let num_pages = mapped_size / PAGE_SIZE_4K; + let kernel_va = kalloc::global_allocator() + .alloc_pages(num_pages, PAGE_SIZE_4K, kalloc::UsageKind::VirtMem) + .map_err(|_| KError::NoMemory)?; + + unsafe { + core::ptr::write_bytes(kernel_va as *mut u8, 0, mapped_size); + } + + let user_addr = NEXT_TEST_USER_ADDR.fetch_add(mapped_size, Ordering::Relaxed); + aspace + .lock() + .map_linear( + VirtAddr::from_usize(user_addr), + v2p(VirtAddr::from_usize(kernel_va)), + mapped_size, + MappingFlags::READ | MappingFlags::WRITE | MappingFlags::USER, + ) + .map_err(|_| { + kalloc::global_allocator().dealloc_pages( + kernel_va, + num_pages, + kalloc::UsageKind::VirtMem, + ); + KError::NoMemory + })?; + + Ok(Self { + aspace, + user_addr, + mapped_size, + kernel_va, + num_pages, + len, + }) + } + + pub fn write_bytes(&self, data: &[u8]) -> KResult { + if data.len() > self.len { + return Err(KError::InvalidInput); + } + write_vm_mem(self.user_addr as *mut u8, data).map_err(Into::into) + } + + pub fn read_bytes(&self, len: usize) -> KResult> { + if len > self.len { + return Err(KError::InvalidInput); + } + let mut out = vec![0u8; len]; + read_vm_mem(self.user_addr as *const u8, unsafe { + transmute::<&mut [u8], &mut [MaybeUninit]>(&mut out[..]) + }) + .map_err(KError::from)?; + Ok(out) + } + + pub fn write_u64(&self, value: u64) -> KResult { + write_vm_mem(self.user_addr as *mut u64, core::slice::from_ref(&value)).map_err(Into::into) + } + + pub fn read_u64(&self) -> KResult { + let mut out = 0u64; + let out_slice = unsafe { + core::slice::from_raw_parts_mut((&mut out as *mut u64).cast::>(), 1) + }; + read_vm_mem(self.user_addr as *const u64, out_slice).map_err(KError::from)?; + Ok(out) + } + + pub fn len(&self) -> usize { + self.len + } + + pub fn as_user_ptr(&self) -> *mut T { + assert!(size_of::() <= self.len); + self.user_addr as *mut T + } + + pub fn as_user_slice(&mut self, len: usize) -> &mut [u8] { + assert!(len <= self.len); + unsafe { core::slice::from_raw_parts_mut(self.user_addr as *mut u8, len) } + } + + pub fn as_user_ref(&mut self) -> &mut T { + assert!(size_of::() <= self.len); + unsafe { &mut *(self.user_addr as *mut T) } + } +} + +pub struct TestUserValue { + buffer: TestUserBuffer, + _marker: PhantomData, +} + +impl TestUserValue { + pub fn new() -> KResult { + Ok(Self { + buffer: TestUserBuffer::new(size_of::())?, + _marker: PhantomData, + }) + } + + pub fn from_value(value: T) -> KResult + where + T: Copy, + { + let mut user_value = Self::new()?; + user_value.write(value); + Ok(user_value) + } + + pub fn as_user_ref(&mut self) -> &mut T { + self.buffer.as_user_ref::() + } + + pub fn as_user_ptr(&self) -> *mut T { + self.buffer.as_user_ptr::() + } + + pub fn write(&mut self, value: T) + where + T: Copy, + { + *self.as_user_ref() = value; + } + + pub fn read(&self) -> T + where + T: Copy, + { + unsafe { self.as_user_ptr().read() } + } +} + +pub struct TestUserArray { + buffer: TestUserBuffer, + _marker: PhantomData, +} + +impl TestUserArray { + pub fn new() -> KResult { + Ok(Self { + buffer: TestUserBuffer::new(size_of::<[T; N]>())?, + _marker: PhantomData, + }) + } + + pub fn from_array(value: [T; N]) -> KResult + where + T: Copy, + { + let mut user_array = Self::new()?; + user_array.write(value); + Ok(user_array) + } + + pub fn len(&self) -> usize { + N + } + + pub fn as_user_slice(&mut self) -> &mut [T] { + unsafe { core::slice::from_raw_parts_mut(self.as_user_ptr(), N) } + } + + pub fn as_user_ref(&mut self) -> &mut [T; N] { + unsafe { &mut *(self.as_user_ptr() as *mut [T; N]) } + } + + pub fn as_user_ptr(&self) -> *mut T { + self.buffer.as_user_ptr::() + } + + pub fn write(&mut self, value: [T; N]) + where + T: Copy, + { + self.as_user_slice().copy_from_slice(&value); + } + + pub fn read(&self) -> [T; N] + where + T: Copy, + { + unsafe { (self.as_user_ptr() as *const [T; N]).read() } + } +} + +impl Deref for TestUserArray { + type Target = [T]; + + fn deref(&self) -> &Self::Target { + unsafe { core::slice::from_raw_parts(self.as_user_ptr(), N) } + } +} + +impl DerefMut for TestUserArray { + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_user_slice() + } +} + +impl Drop for TestUserBuffer { + fn drop(&mut self) { + let _ = self + .aspace + .lock() + .unmap(VirtAddr::from_usize(self.user_addr), self.mapped_size); + kalloc::global_allocator().dealloc_pages( + self.kernel_va, + self.num_pages, + kalloc::UsageKind::VirtMem, + ); + } +}