kernel/lib/types/
user_slice.rs1use crate::lib::panic::kernel_panic;
7use crate::lib::panic_codes::PanicCode;
8use crate::lib::types::fmt_buffer::FmtBuffer;
9use crate::mm::layout::USER_MAX;
10use crate::syscall::result::{SyscallError, SyscallResult};
11
12#[derive(Copy, Clone, Debug)]
14pub struct UserSlice {
15 address: u64,
16 length: u64
17}
18
19impl UserSlice {
20 pub fn new(address: u64, length: u64) -> SyscallResult<Self> {
28 let Some(end) = address.checked_add(length) else {
29 return Err(SyscallError::BadAddress)
30 };
31 if end > USER_MAX {
32 return Err(SyscallError::BadAddress)
33 }
34
35 Ok(Self {
36 address,
37 length
38 })
39 }
40
41 pub fn len(&self) -> u64 {
43 self.length
44 }
45
46 pub fn is_empty(&self) -> bool {
48 self.length == 0
49 }
50
51 pub fn copy_to_slice(&self, slice: &mut [u8]) {
57 #[cfg(feature = "debug-checks")]
58 if self.length != slice.len() as u64 {
59 self.incorrect_size_panic(slice.len(), self.length);
60 }
61
62 self.partial_copy_to_slice(slice, 0, self.length)
63 }
64
65 pub fn partial_copy_to_slice(&self, slice: &mut [u8], offset: u64, length: u64) {
74 let Some(end) = offset.checked_add(length) else {
75 kernel_panic(
76 PanicCode::InternalKernelError,
77 "UserSlice: adding offset and length overflowed"
78 );
79 };
80
81 if end > self.length {
82 kernel_panic(
83 PanicCode::InternalKernelError,
84 "UserSlice: requested range exceeds slice bounds"
85 );
86 }
87 if length > slice.len() as u64 {
88 self.incorrect_size_panic(slice.len(), length);
89 }
90
91 if length == 0 {
92 return;
93 }
94
95 #[cfg(feature = "debug-checks")]
96 if self.address.checked_add(offset).is_none() {
97 kernel_panic(
98 PanicCode::InternalKernelError,
99 "UserSlice: adding address and offset overflowed"
100 );
101 }
102 let start_addr = self.address.wrapping_add(offset);
103
104 unsafe {
108 #[cfg(target_arch = "x86_64")]
109 core::arch::asm!(
110 "rep movsb",
111
112 inout("rsi") start_addr => _,
113 inout("rdi") slice.as_mut_ptr() => _,
114 inout("rcx") length => _,
115
116 options(nostack, preserves_flags)
117 );
118
119 #[cfg(target_arch = "aarch64")]
120 compile_error!("not implemented");
121 }
122 }
123
124 #[cold]
126 #[inline(never)]
127 fn incorrect_size_panic(&self, dst_len: usize, src_len: u64) -> ! {
128 use core::fmt::Write;
129
130 let mut fmt_buffer = FmtBuffer::<512>::new();
131 let _ = write!(
132 &mut fmt_buffer,
133 "Attempted to copy data from a UserSlice ({} bytes) into an incorrectly sized slice ({} bytes)",
134 src_len,
135 dst_len
136 );
137
138 kernel_panic(
139 PanicCode::InternalKernelError,
140 fmt_buffer.as_str()
141 );
142 }
143}