From ee7b8a7e8e13571a6bc888e2718deee80725378d Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 16:26:23 -0400 Subject: [PATCH 01/10] Convert syscall() to macro aarch64 requires syscall numbers be immediates, so a standard function can't be used here. --- libuser/src/syscalls.rs | 127 ++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 58 deletions(-) diff --git a/libuser/src/syscalls.rs b/libuser/src/syscalls.rs index 471a26c4f..487f055e4 100644 --- a/libuser/src/syscalls.rs +++ b/libuser/src/syscalls.rs @@ -83,25 +83,36 @@ extern { fn syscall_inner(registers: &mut Registers); } +// unsafe fn syscall(nr: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize, arg6: usize) -> Result<(usize, usize, usize, usize), KernelError> { /// Generic syscall function. -unsafe fn syscall(nr: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize, arg6: usize) -> Result<(usize, usize, usize, usize), KernelError> { - let mut registers = Registers { - eax: nr, - ebx: arg1, - ecx: arg2, - edx: arg3, - esi: arg4, - edi: arg5, - ebp: arg6 - }; - - syscall_inner(&mut registers); - - if registers.eax == 0 { - Ok((registers.ebx, registers.ecx, registers.edx, registers.esi)) - } else { - Err(KernelError::from_syscall_ret(registers.eax as u32)) - } +macro_rules! syscall { + ($nr:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr) => {{ + let nr: usize = $nr; + let arg1: usize = $arg1; + let arg2: usize = $arg2; + let arg3: usize = $arg3; + let arg4: usize = $arg4; + let arg5: usize = $arg5; + let arg6: usize = $arg6; + + let mut registers = Registers { + eax: nr, + ebx: arg1, + ecx: arg2, + edx: arg3, + esi: arg4, + edi: arg5, + ebp: arg6 + }; + + syscall_inner(&mut registers); + + if registers.eax == 0 { + Ok((registers.ebx, registers.ecx, registers.edx, registers.esi)) + } else { + Err(KernelError::from_syscall_ret(registers.eax as u32)) + } + }}; } /// Resize the heap of a process, just like a brk. @@ -122,7 +133,7 @@ unsafe fn syscall(nr: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, /// This function can free memory, potentially invalidating references to structs that were in it. pub unsafe fn set_heap_size(new_size: usize) -> Result { let (heap_address_base, ..) = unsafe { - syscall(nr::SetHeapSize, new_size, 0, 0, 0, 0, 0)? + syscall!(nr::SetHeapSize, new_size, 0, 0, 0, 0, 0)? }; Ok(heap_address_base) } @@ -136,7 +147,7 @@ pub unsafe fn set_heap_size(new_size: usize) -> Result { pub fn query_memory(addr: usize) -> Result<(MemoryInfo, usize), KernelError> { let mut meminfo = MemoryInfo::default(); let (pageinfo, ..) = unsafe { - syscall(nr::QueryMemory, &mut meminfo as *mut _ as usize, 0, addr, 0, 0, 0)? + syscall!(nr::QueryMemory, &mut meminfo as *mut _ as usize, 0, addr, 0, 0, 0)? }; Ok((meminfo, pageinfo)) } @@ -144,7 +155,7 @@ pub fn query_memory(addr: usize) -> Result<(MemoryInfo, usize), KernelError> { /// Exits the process, killing all threads. pub fn exit_process() -> ! { unsafe { - match syscall(nr::ExitProcess, 0, 0, 0, 0, 0, 0) { + match syscall!(nr::ExitProcess, 0, 0, 0, 0, 0, 0) { Ok(_) => (), Err(err) => { let _ = output_debug_string(&format!("Failed to exit: {}", err), 10, "sunrise_libuser::syscalls::exit_process"); }, } @@ -160,7 +171,7 @@ pub fn exit_process() -> ! { /// `sp` must a valid pointer to a stack that is uniquely owned, as the thread will write to it. pub unsafe fn create_thread(ip: extern "fastcall" fn(usize) -> !, arg: usize, sp: *const u8, priority: u32, processor_id: u32) -> Result { unsafe { - let (out_handle, ..) = syscall(nr::CreateThread, ip as usize, arg, sp as _, priority as _, processor_id as _, 0)?; + let (out_handle, ..) = syscall!(nr::CreateThread, ip as usize, arg, sp as _, priority as _, processor_id as _, 0)?; Ok(Thread(Handle::new(out_handle as _))) } } @@ -168,7 +179,7 @@ pub unsafe fn create_thread(ip: extern "fastcall" fn(usize) -> !, arg: usize, sp /// Starts the thread for the provided handle. pub fn start_thread(thread_handle: &Thread) -> Result<(), KernelError> { unsafe { - syscall(nr::StartThread, (thread_handle.0).0.get() as usize, 0, 0, 0, 0, 0)?; + syscall!(nr::StartThread, (thread_handle.0).0.get() as usize, 0, 0, 0, 0, 0)?; Ok(()) } } @@ -177,7 +188,7 @@ pub fn start_thread(thread_handle: &Thread) -> Result<(), KernelError> { #[allow(unused_must_use)] pub fn exit_thread() -> ! { unsafe { - syscall(nr::ExitThread, 0, 0, 0, 0, 0, 0); + syscall!(nr::ExitThread, 0, 0, 0, 0, 0, 0); } unreachable!("svcExitThread returned, WTF ???") } @@ -185,7 +196,7 @@ pub fn exit_thread() -> ! { /// Sleeps for a specified amount of time, or yield thread. pub fn sleep_thread(nanos: usize) -> Result<(), KernelError> { unsafe { - syscall(nr::SleepThread, nanos, 0, 0, 0, 0, 0)?; + syscall!(nr::SleepThread, nanos, 0, 0, 0, 0, 0)?; Ok(()) } } @@ -199,7 +210,7 @@ pub fn sleep_thread(nanos: usize) -> Result<(), KernelError> { /// Takes either a [ReadableEvent] or a [WritableEvent]. pub fn signal_event(event: &WritableEvent) -> Result<(), KernelError> { unsafe { - syscall(nr::SignalEvent, (event.0).0.get() as _, 0, 0, 0, 0, 0)?; + syscall!(nr::SignalEvent, (event.0).0.get() as _, 0, 0, 0, 0, 0)?; Ok(()) } } @@ -216,7 +227,7 @@ pub fn signal_event(event: &WritableEvent) -> Result<(), KernelError> { /// - The event wasn't signaled. pub(crate) fn clear_event(event: HandleRef) -> Result<(), KernelError> { unsafe { - syscall(nr::ClearEvent, event.inner.get() as _, 0, 0, 0, 0, 0)?; + syscall!(nr::ClearEvent, event.inner.get() as _, 0, 0, 0, 0, 0)?; Ok(()) } } @@ -233,7 +244,7 @@ pub(crate) fn clear_event(event: HandleRef) -> Result<(), KernelError> { /// - Errors if size is not page-aligned. pub fn create_shared_memory(size: usize, myperm: MemoryPermissions, otherperm: MemoryPermissions) -> Result { unsafe { - let (out_handle, ..) = syscall(nr::CreateSharedMemory, size, myperm.bits() as _, otherperm.bits() as _, 0, 0, 0)?; + let (out_handle, ..) = syscall!(nr::CreateSharedMemory, size, myperm.bits() as _, otherperm.bits() as _, 0, 0, 0)?; Ok(SharedMemory(Handle::new(out_handle as _))) } } @@ -249,7 +260,7 @@ pub fn create_shared_memory(size: usize, myperm: MemoryPermissions, otherperm: M /// - perm must be allowed. pub fn map_shared_memory(handle: &SharedMemory, addr: usize, size: usize, perm: MemoryPermissions) -> Result<(), KernelError> { unsafe { - syscall(nr::MapSharedMemory, (handle.0).0.get() as _, addr, size, perm.bits() as _, 0, 0)?; + syscall!(nr::MapSharedMemory, (handle.0).0.get() as _, addr, size, perm.bits() as _, 0, 0)?; Ok(()) } } @@ -269,7 +280,7 @@ pub fn map_shared_memory(handle: &SharedMemory, addr: usize, size: usize, perm: /// - addr must point to a mapping backed by the given handle /// - Size must be equal to the size of the backing shared memory handle. pub unsafe fn unmap_shared_memory(handle: &SharedMemory, addr: usize, size: usize) -> Result<(), KernelError> { - syscall(nr::UnmapSharedMemory, (handle.0).0.get() as _, addr, size, 0, 0, 0)?; + syscall!(nr::UnmapSharedMemory, (handle.0).0.get() as _, addr, size, 0, 0, 0)?; Ok(()) } @@ -277,7 +288,7 @@ pub unsafe fn unmap_shared_memory(handle: &SharedMemory, addr: usize, size: usiz /// Close the given handle. pub(crate) fn close_handle(handle: u32) -> Result<(), KernelError> { unsafe { - syscall(nr::CloseHandle, handle as _, 0, 0, 0, 0, 0)?; + syscall!(nr::CloseHandle, handle as _, 0, 0, 0, 0, 0)?; Ok(()) } } @@ -328,7 +339,7 @@ pub(crate) fn close_handle(handle: u32) -> Result<(), KernelError> { /// to wait on more than 0x40 handles. pub fn wait_synchronization(handles: &[HandleRef<'_>], timeout_ns: Option) -> Result { unsafe { - let (handleidx, ..) = syscall(nr::WaitSynchronization, handles.as_ptr() as _, handles.len(), timeout_ns.unwrap_or_else(usize::max_value), 0, 0, 0)?; + let (handleidx, ..) = syscall!(nr::WaitSynchronization, handles.as_ptr() as _, handles.len(), timeout_ns.unwrap_or_else(usize::max_value), 0, 0, 0)?; Ok(handleidx) } } @@ -336,7 +347,7 @@ pub fn wait_synchronization(handles: &[HandleRef<'_>], timeout_ns: Option /// Creates a session to the given named port. pub fn connect_to_named_port(s: &str) -> Result { unsafe { - let (out_handle, ..) = syscall(nr::ConnectToNamedPort, s.as_ptr() as _, 0, 0, 0, 0, 0)?; + let (out_handle, ..) = syscall!(nr::ConnectToNamedPort, s.as_ptr() as _, 0, 0, 0, 0, 0)?; Ok(ClientSession(Handle::new(out_handle as _))) } } @@ -346,7 +357,7 @@ pub fn connect_to_named_port(s: &str) -> Result { /// Please see the IPC module for more information on IPC. pub fn send_sync_request_with_user_buffer(buf: &mut [u8], handle: &ClientSession) -> Result<(), KernelError> { unsafe { - syscall(nr::SendSyncRequestWithUserBuffer, buf.as_ptr() as _, buf.len(), (handle.0).0.get() as _, 0, 0, 0)?; + syscall!(nr::SendSyncRequestWithUserBuffer, buf.as_ptr() as _, buf.len(), (handle.0).0.get() as _, 0, 0, 0)?; Ok(()) } } @@ -356,7 +367,7 @@ pub fn send_sync_request_with_user_buffer(buf: &mut [u8], handle: &ClientSession /// Currently, this prints the string to the serial port. pub fn output_debug_string(s: &str, level: usize, target: &str) -> Result<(), KernelError> { unsafe { - syscall(nr::OutputDebugString, s.as_ptr() as _, s.len(), level, target.as_ptr() as _, target.len(), 0)?; + syscall!(nr::OutputDebugString, s.as_ptr() as _, s.len(), level, target.as_ptr() as _, target.len(), 0)?; Ok(()) } } @@ -364,7 +375,7 @@ pub fn output_debug_string(s: &str, level: usize, target: &str) -> Result<(), Ke /// Create an anonymous session. pub fn create_session(is_light: bool, unk: usize) -> Result<(ServerSession, ClientSession), KernelError> { unsafe { - let (serverhandle, clienthandle, ..) = syscall(nr::CreateSession, is_light as _, unk, 0, 0, 0, 0)?; + let (serverhandle, clienthandle, ..) = syscall!(nr::CreateSession, is_light as _, unk, 0, 0, 0, 0)?; Ok((ServerSession(Handle::new(serverhandle as _)), ClientSession(Handle::new(clienthandle as _)))) } } @@ -372,7 +383,7 @@ pub fn create_session(is_light: bool, unk: usize) -> Result<(ServerSession, Clie /// Accept a connection on the given port. pub fn accept_session(port: &ServerPort) -> Result { unsafe { - let (out_handle, ..) = syscall(nr::AcceptSession, (port.0).0.get() as _, 0, 0, 0, 0, 0)?; + let (out_handle, ..) = syscall!(nr::AcceptSession, (port.0).0.get() as _, 0, 0, 0, 0, 0)?; Ok(ServerSession(Handle::new(out_handle as _))) } } @@ -398,7 +409,7 @@ pub fn accept_session(port: &ServerPort) -> Result { /// [switchbrew's IPC marshalling page]: https://http://switchbrew.org/index.php?title=IPC_Marshalling pub fn reply_and_receive_with_user_buffer(buf: &mut [u8], handles: &[HandleRef<'_>], replytarget: Option>, timeout: Option) -> Result { unsafe { - let (idx, ..) = syscall(nr::ReplyAndReceiveWithUserBuffer, buf.as_ptr() as _, buf.len(), handles.as_ptr() as _, handles.len(), match replytarget { + let (idx, ..) = syscall!(nr::ReplyAndReceiveWithUserBuffer, buf.as_ptr() as _, buf.len(), handles.as_ptr() as _, handles.len(), match replytarget { Some(s) => s.inner.get() as _, None => 0 }, timeout.unwrap_or_else(usize::max_value))?; @@ -409,7 +420,7 @@ pub fn reply_and_receive_with_user_buffer(buf: &mut [u8], handles: &[HandleRef<' /// Create a [ReadableEvent]/[WritableEvent] pair. pub fn create_event() -> Result<(WritableEvent, ReadableEvent), KernelError> { unsafe { - let (wevent, revent, ..) = syscall(nr::CreateEvent, 0, 0, 0, 0, 0, 0)?; + let (wevent, revent, ..) = syscall!(nr::CreateEvent, 0, 0, 0, 0, 0, 0)?; Ok((WritableEvent(Handle::new(wevent as _)), ReadableEvent(Handle::new(revent as _)))) } } @@ -419,7 +430,7 @@ pub fn create_event() -> Result<(WritableEvent, ReadableEvent), KernelError> { /// Note that the process needs to be authorized to listen for the given IRQ. pub fn create_interrupt_event(irqnum: usize, flag: u32) -> Result { unsafe { - let (out_handle, ..) = syscall(nr::CreateInterruptEvent, irqnum, flag as usize, 0, 0, 0, 0)?; + let (out_handle, ..) = syscall!(nr::CreateInterruptEvent, irqnum, flag as usize, 0, 0, 0, 0)?; Ok(ReadableEvent(Handle::new(out_handle as _))) } } @@ -440,7 +451,7 @@ pub fn create_interrupt_event(irqnum: usize, flag: u32) -> Result Result<(usize, usize, usize), KernelError> { unsafe { - let (phys_addr, base_addr, phys_len, ..) = syscall(nr::QueryPhysicalAddress, virtual_address, 0, 0, 0, 0, 0)?; + let (phys_addr, base_addr, phys_len, ..) = syscall!(nr::QueryPhysicalAddress, virtual_address, 0, 0, 0, 0, 0)?; Ok((phys_addr, base_addr, phys_len)) } } @@ -448,7 +459,7 @@ pub fn query_physical_address(virtual_address: usize) -> Result<(usize, usize, u /// Creates an anonymous port. pub fn create_port(max_sessions: u32, is_light: bool, name_ptr: &[u8]) -> Result<(ClientPort, ServerPort), KernelError> { unsafe { - let (out_client_handle, out_server_handle, ..) = syscall(nr::CreatePort, max_sessions as _, is_light as _, name_ptr.as_ptr() as _, 0, 0, 0)?; + let (out_client_handle, out_server_handle, ..) = syscall!(nr::CreatePort, max_sessions as _, is_light as _, name_ptr.as_ptr() as _, 0, 0, 0)?; Ok((ClientPort(Handle::new(out_client_handle as _)), ServerPort(Handle::new(out_server_handle as _)))) } } @@ -456,7 +467,7 @@ pub fn create_port(max_sessions: u32, is_light: bool, name_ptr: &[u8]) -> Result /// Creates a named port. pub fn manage_named_port(name: &str, max_handles: u32) -> Result { unsafe { - let (out_handle, ..) = syscall(nr::ManageNamedPort, name.as_ptr() as _, max_handles as _, 0, 0, 0, 0)?; + let (out_handle, ..) = syscall!(nr::ManageNamedPort, name.as_ptr() as _, max_handles as _, 0, 0, 0, 0)?; Ok(ServerPort(Handle::new(out_handle as _))) } } @@ -464,7 +475,7 @@ pub fn manage_named_port(name: &str, max_handles: u32) -> Result Result { unsafe { - let (out_handle, ..) = syscall(nr::ConnectToPort, (port.0).0.get() as _, 0, 0, 0, 0, 0)?; + let (out_handle, ..) = syscall!(nr::ConnectToPort, (port.0).0.get() as _, 0, 0, 0, 0, 0)?; Ok(ClientSession(Handle::new(out_handle as _))) } } @@ -472,7 +483,7 @@ pub fn connect_to_port(port: &ClientPort) -> Result /// Maps the framebuffer to a kernel-chosen address. pub fn map_framebuffer() -> Result<(&'static mut [u8], usize, usize, usize), KernelError> { unsafe { - let (addr, width, height, bpp) = syscall(nr::MapFramebuffer, 0, 0, 0, 0, 0, 0)?; + let (addr, width, height, bpp) = syscall!(nr::MapFramebuffer, 0, 0, 0, 0, 0, 0)?; let framebuffer_size = bpp * width * height / 8; Ok((slice::from_raw_parts_mut(addr as *mut u8, framebuffer_size), width, height, bpp)) } @@ -491,7 +502,7 @@ pub fn map_framebuffer() -> Result<(&'static mut [u8], usize, usize, usize), Ker /// * `length` is zero. pub fn map_mmio_region(physical_address: usize, size: usize, virtual_address: usize, writable: bool) -> Result<(), KernelError> { unsafe { - syscall(nr::MapMmioRegion, physical_address, size, virtual_address, writable as usize, 0, 0)?; + syscall!(nr::MapMmioRegion, physical_address, size, virtual_address, writable as usize, 0, 0)?; Ok(()) } } @@ -530,7 +541,7 @@ pub fn map_mmio_region(physical_address: usize, size: usize, virtual_address: us /// * No returned error otherwise. pub unsafe fn set_thread_area(address: usize) -> Result<(), KernelError> { unsafe { - syscall(nr::SetThreadArea, address, 0, 0, 0, 0, 0)?; + syscall!(nr::SetThreadArea, address, 0, 0, 0, 0, 0)?; Ok(()) } } @@ -557,7 +568,7 @@ pub unsafe fn set_thread_area(address: usize) -> Result<(), KernelError> { /// [`process_permission_change_allowed`]: sunrise_libkern::MemoryState::PROCESS_PERMISSION_CHANGE_ALLOWED pub fn set_process_memory_permission(proc_hnd: &Process, addr: usize, size: usize, perms: MemoryPermissions) -> Result<(), KernelError> { unsafe { - syscall(nr::SetProcessMemoryPermission, (proc_hnd.0).0.get() as _, addr, size, perms.bits() as _, 0, 0)?; + syscall!(nr::SetProcessMemoryPermission, (proc_hnd.0).0.get() as _, addr, size, perms.bits() as _, 0, 0)?; Ok(()) } } @@ -589,7 +600,7 @@ pub fn set_process_memory_permission(proc_hnd: &Process, addr: usize, size: usiz /// handle. pub fn map_process_memory(dstaddr: usize, proc_handle: &Process, srcaddr: usize, size: usize) -> Result<(), KernelError> { unsafe { - syscall(nr::MapProcessMemory, dstaddr, (proc_handle.0).0.get() as _, srcaddr, size, 0, 0)?; + syscall!(nr::MapProcessMemory, dstaddr, (proc_handle.0).0.get() as _, srcaddr, size, 0, 0)?; Ok(()) } } @@ -628,7 +639,7 @@ pub fn map_process_memory(dstaddr: usize, proc_handle: &Process, srcaddr: usize, /// - The handle passed as an argument does not exist or is not a Process /// handle. pub unsafe fn unmap_process_memory(dstaddr: usize, proc_handle: &Process, srcaddr: usize, size: usize) -> Result<(), KernelError> { - syscall(nr::UnmapProcessMemory, dstaddr, (proc_handle.0).0.get() as _, srcaddr, size, 0, 0)?; + syscall!(nr::UnmapProcessMemory, dstaddr, (proc_handle.0).0.get() as _, srcaddr, size, 0, 0)?; Ok(()) } @@ -638,7 +649,7 @@ pub unsafe fn unmap_process_memory(dstaddr: usize, proc_handle: &Process, srcadd /// ProcessMana's `LaunchTitle` function. pub fn create_process(procinfo: &ProcInfo, caps: &[u8]) -> Result { unsafe { - let (hnd, ..) = syscall(nr::CreateProcess, procinfo as *const _ as usize, caps.as_ptr() as usize, caps.len() / 4, 0, 0, 0)?; + let (hnd, ..) = syscall!(nr::CreateProcess, procinfo as *const _ as usize, caps.as_ptr() as usize, caps.len() / 4, 0, 0, 0)?; Ok(Process(Handle::new(hnd as _))) } } @@ -666,7 +677,7 @@ pub fn create_process(procinfo: &ProcInfo, caps: &[u8]) -> Result Result<(), KernelError> { unsafe { - syscall(nr::StartProcess, (process_handle.0).0.get() as usize, main_thread_prio as _, default_cpuid as _, main_thread_stacksz as _, 0, 0)?; + syscall!(nr::StartProcess, (process_handle.0).0.get() as usize, main_thread_prio as _, default_cpuid as _, main_thread_stacksz as _, 0, 0)?; Ok(()) } } @@ -686,7 +697,7 @@ pub fn start_process(process_handle: &Process, main_thread_prio: u32, default_cp /// - The passed info_type is unknown. pub fn get_process_info(process_handle: &Process, ty: ProcessInfoType) -> Result { unsafe { - let (info, ..) = syscall(nr::GetProcessInfo, (process_handle.0).0.get() as usize, ty.0 as usize, 0, 0, 0, 0)?; + let (info, ..) = syscall!(nr::GetProcessInfo, (process_handle.0).0.get() as usize, ty.0 as usize, 0, 0, 0, 0)?; Ok(info as _) } } @@ -707,7 +718,7 @@ pub fn get_process_info(process_handle: &Process, ty: ProcessInfoType) -> Result /// - The process was in Exited state. pub(crate) fn reset_signal(event: HandleRef) -> Result<(), KernelError> { unsafe { - syscall(nr::ResetSignal, event.inner.get() as _, 0, 0, 0, 0, 0)?; + syscall!(nr::ResetSignal, event.inner.get() as _, 0, 0, 0, 0, 0)?; Ok(()) } } @@ -724,7 +735,7 @@ pub(crate) fn reset_signal(event: HandleRef) -> Result<(), KernelError> { /// - The given handle is invalid or not a process. pub fn get_process_id(process_handle: &Process) -> Result { unsafe { - let (pid, ..) = syscall(nr::GetProcessId, (process_handle.0).0.get() as usize, 0, 0, 0, 0, 0)?; + let (pid, ..) = syscall!(nr::GetProcessId, (process_handle.0).0.get() as usize, 0, 0, 0, 0, 0)?; Ok(pid as _) } } @@ -740,7 +751,7 @@ pub fn get_process_id(process_handle: &Process) -> Result { /// - The process wasn't started (it is in Created or CreatedAttached state). pub fn terminate_process(process_handle: &Process) -> Result<(), KernelError> { unsafe { - syscall(nr::TerminateProcess, (process_handle.0).0.get() as usize, 0, 0, 0, 0, 0)?; + syscall!(nr::TerminateProcess, (process_handle.0).0.get() as usize, 0, 0, 0, 0, 0)?; Ok(()) } } @@ -753,7 +764,7 @@ pub fn terminate_process(process_handle: &Process) -> Result<(), KernelError> { /// bigger than the size of PidBuffer, the user won't have all the pids. pub fn get_process_list(list: &mut [u64]) -> Result { unsafe { - let (read, ..) = syscall(nr::GetProcessList, list.as_ptr() as usize, list.len(), 0, 0, 0, 0)?; + let (read, ..) = syscall!(nr::GetProcessList, list.as_ptr() as usize, list.len(), 0, 0, 0, 0)?; Ok(read) } -} \ No newline at end of file +} From 63910634fc92fc86b2b8aa5556fc1f6a10ae186a Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 16:45:12 -0400 Subject: [PATCH 02/10] #[cfg] x86-only code --- libuser/src/crt0/mod.rs | 2 +- libuser/src/syscalls.rs | 14 +++++++++++ libuser/src/threads.rs | 53 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/libuser/src/crt0/mod.rs b/libuser/src/crt0/mod.rs index fec113157..5e7a775a5 100644 --- a/libuser/src/crt0/mod.rs +++ b/libuser/src/crt0/mod.rs @@ -5,7 +5,7 @@ pub mod relocation; /// Executable entrypoint. Handle relocations and calls real_start. -#[cfg(target_os = "sunrise")] +#[cfg(all(target_os = "sunrise", target_arch = "x86"))] #[naked] #[no_mangle] #[link_section = ".text.crt0"] diff --git a/libuser/src/syscalls.rs b/libuser/src/syscalls.rs index 487f055e4..7350bb4fc 100644 --- a/libuser/src/syscalls.rs +++ b/libuser/src/syscalls.rs @@ -169,6 +169,7 @@ pub fn exit_process() -> ! { /// # Unsafety /// /// `sp` must a valid pointer to a stack that is uniquely owned, as the thread will write to it. +#[cfg(target_arch = "x86")] pub unsafe fn create_thread(ip: extern "fastcall" fn(usize) -> !, arg: usize, sp: *const u8, priority: u32, processor_id: u32) -> Result { unsafe { let (out_handle, ..) = syscall!(nr::CreateThread, ip as usize, arg, sp as _, priority as _, processor_id as _, 0)?; @@ -176,6 +177,19 @@ pub unsafe fn create_thread(ip: extern "fastcall" fn(usize) -> !, arg: usize, sp } } +/// Creates a thread in the current process. +/// +/// # Unsafety +/// +/// `sp` must a valid pointer to a stack that is uniquely owned, as the thread will write to it. +#[cfg(not(target_arch = "x86"))] +pub unsafe fn create_thread(ip: extern fn(usize) -> !, arg: usize, sp: *const u8, priority: u32, processor_id: u32) -> Result { + unsafe { + let (out_handle, ..) = syscall!(nr::CreateThread, ip as usize, arg, sp as _, priority as _, processor_id as _, 0)?; + Ok(Thread(Handle::new(out_handle as _))) + } +} + /// Starts the thread for the provided handle. pub fn start_thread(thread_handle: &Thread) -> Result<(), KernelError> { unsafe { diff --git a/libuser/src/threads.rs b/libuser/src/threads.rs index fb9b8b936..c4c87a22c 100644 --- a/libuser/src/threads.rs +++ b/libuser/src/threads.rs @@ -193,6 +193,7 @@ static MAIN_THREAD_CONTEXT: ThreadContext = ThreadContext { /// Get a pointer to this thread's [TLS] region pointed to by `fs`, translated to the flat-memory model. #[inline] +#[cfg(target_arch = "x86")] fn get_my_tls_region() -> *mut TLS { let mut tls: *mut TLS; unsafe { @@ -203,6 +204,18 @@ fn get_my_tls_region() -> *mut TLS { tls } +/// Get a pointer to this thread's [TLS] region pointed to by `fs`, translated to the flat-memory model. +#[inline] +#[cfg(target_arch = "aarch64")] +fn get_my_tls_region() -> *mut TLS { + let mut tls: *mut TLS; + unsafe { + // get the address of the TLS region from TPIDRRO_EL0 + // safe: TPIDRRO_EL0 is guaranteed by the kernel to hold a valid pointer to TLS. + asm!("mrs $0, TPIDRRO_EL0" : "=r" (tls)); + } + tls +} /// Get a reference to this thread's [ThreadContext], from the [TLS] region pointed to by `fs`. /// @@ -337,6 +350,7 @@ impl Thread { /// It expects this argument to be the address of its `ThreadContext` so it can save it its `TLS`. /// /// The routine to call and its argument are expected to be found in this `ThreadContext`. +#[cfg(target_arch = "x86")] extern "fastcall" fn thread_trampoline(thread_context_addr: usize) -> ! { debug!("starting from new thread, context at address {:#010x}", thread_context_addr); // first save the address of our context in our TLS region @@ -363,6 +377,45 @@ extern "fastcall" fn thread_trampoline(thread_context_addr: usize) -> ! { syscalls::exit_thread() } +/// Small stub executed by every thread but the main thread when they start. +/// +/// Saves the pointer to their [ThreadContext] in their [TLS], performs copy of `.tdata` and `.tbss`, +/// calls the routine this thread was meant to perform, and calls `svcExitThread` when it's finished. +/// +/// # ABI +/// +/// This function is the entry point of a thread, called directly by the kernel, with the +/// argument passed by [Thread::create]. +/// It expects this argument to be the address of its `ThreadContext` so it can save it its `TLS`. +/// +/// The routine to call and its argument are expected to be found in this `ThreadContext`. +#[cfg(not(target_arch = "x86"))] +extern fn thread_trampoline(thread_context_addr: usize) -> ! { + debug!("starting from new thread, context at address {:#010x}", thread_context_addr); + // first save the address of our context in our TLS region + unsafe { + // safe: - get_my_tls returns a valid 0x200 aligned ptr, + // - .ptr_thread_context is correctly aligned in the TLS region to usize, + // - we're a private fn, thread_context_addr is guaranteed by our caller to point to the context. + (*get_my_tls_region()).ptr_thread_context = thread_context_addr + }; + + // use get_my_thread_context to create a ref for us + let thread_context = get_my_thread_context(); + + // make gs point to our tls + unsafe { + // safe: this module guarantees that the TLS region is unique to this thread. + thread_context.tls_elf.r#try().unwrap().enable_for_current_thread(); + } + + // call the routine saved in the context, passing it the arg saved in the context + (thread_context.entry_point)(thread_context.arg); + + debug!("exiting thread"); + syscalls::exit_thread() +} + impl Drop for Thread { fn drop(&mut self) { // TODO: Properly free resource after thread detach From 471dfced1464cfb83af0897af280ba8bedf3f9b3 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 16:45:18 -0400 Subject: [PATCH 03/10] Add aarch64 target JSON This was created by diffing the i386 JSON with i686-unknown-linux-gnu, and applying relevant changes to aarch64-unknown-linux-gnu. --- aarch64-unknown-sunrise-user.json | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 aarch64-unknown-sunrise-user.json diff --git a/aarch64-unknown-sunrise-user.json b/aarch64-unknown-sunrise-user.json new file mode 100644 index 000000000..0ab9b9dc9 --- /dev/null +++ b/aarch64-unknown-sunrise-user.json @@ -0,0 +1,29 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "win64", + "sysv64" + ], + "arch": "aarch64", + "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + "dynamic-linking": false, + "env": "user", + "executables": true, + "has-elf-tls": true, + "has-rpath": false, + "linker-flavor": "ld.lld", + "linker-is-gnu": true, + "llvm-target": "aarch64-unknown-none", + "max-atomic-width": 128, + "os": "sunrise", + "panic-strategy": "abort", + "position-independent-executables": true, + "target-c-int-width": "32", + "target-endian": "little", + "target-mcount": "\u0001_mcount", + "target-pointer-width": "64", + "tls-model": "initial-exec" +} From 11698f9145fb7cf4efb07b5a80537037700b5259 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 16:57:10 -0400 Subject: [PATCH 04/10] Use x86 get_my_tls_region on x86_64 to fix docs --- libuser/src/threads.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libuser/src/threads.rs b/libuser/src/threads.rs index c4c87a22c..70e507d21 100644 --- a/libuser/src/threads.rs +++ b/libuser/src/threads.rs @@ -193,7 +193,7 @@ static MAIN_THREAD_CONTEXT: ThreadContext = ThreadContext { /// Get a pointer to this thread's [TLS] region pointed to by `fs`, translated to the flat-memory model. #[inline] -#[cfg(target_arch = "x86")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn get_my_tls_region() -> *mut TLS { let mut tls: *mut TLS; unsafe { From 253cacddbd1484652779573c949c38c56313e6bf Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 16:59:10 -0400 Subject: [PATCH 05/10] Use non-arch-specific register names --- libuser/src/syscalls.rs | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/libuser/src/syscalls.rs b/libuser/src/syscalls.rs index 7350bb4fc..855472e2d 100644 --- a/libuser/src/syscalls.rs +++ b/libuser/src/syscalls.rs @@ -60,7 +60,7 @@ syscall_inner: #[cfg(not(target_os = "sunrise"))] #[no_mangle] extern fn syscall_inner(regs: &mut super::Registers) { - regs.eax = crate::error::KernelError::NotImplemented.make_ret() as usize; + regs.nr = crate::error::KernelError::NotImplemented.make_ret() as usize; } } @@ -70,13 +70,13 @@ syscall_inner: #[repr(C)] #[allow(clippy::missing_docs_in_private_items)] struct Registers { - eax: usize, - ebx: usize, - ecx: usize, - edx: usize, - esi: usize, - edi: usize, - ebp: usize, + nr: usize, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, + arg6: usize, } extern { @@ -96,26 +96,26 @@ macro_rules! syscall { let arg6: usize = $arg6; let mut registers = Registers { - eax: nr, - ebx: arg1, - ecx: arg2, - edx: arg3, - esi: arg4, - edi: arg5, - ebp: arg6 + nr, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6 }; syscall_inner(&mut registers); - if registers.eax == 0 { - Ok((registers.ebx, registers.ecx, registers.edx, registers.esi)) + if registers.nr == 0 { + Ok((registers.arg1, registers.arg2, registers.arg3, registers.arg4)) } else { - Err(KernelError::from_syscall_ret(registers.eax as u32)) + Err(KernelError::from_syscall_ret(registers.nr as u32)) } }}; } -/// Resize the heap of a process, just like a brk. +/// Rarg4ze the heap of a process, just like a brk. /// It can both expand, and shrink the heap. /// /// If `new_size` == 0, the heap space is entirely de-allocated. @@ -218,7 +218,7 @@ pub fn sleep_thread(nanos: usize) -> Result<(), KernelError> { /// Sets the "signaled" state of an event. Calling this on an unsignalled event /// will cause any thread waiting on this event through [wait_synchronization()] /// to wake up. Any future calls to [wait_synchronization()] with this handle -/// will immediately return - the user has to clear the "signaled" state through +/// will immarg5ately return - the user has to clear the "signaled" state through /// [clear_event()]. /// /// Takes either a [ReadableEvent] or a [WritableEvent]. @@ -540,7 +540,7 @@ pub fn map_mmio_region(physical_address: usize, size: usize, virtual_address: us /// /// ## x86_64 /// -/// ![same, but different, but still same](https://media.giphy.com/media/C6JQPEUsZUyVq/giphy.gif) +/// ![same, but different, but still same](https://marg5a.giphy.com/marg5a/C6JQPEUsZUyVq/giphy.gif) /// /// `fs` is used instead of `gs`, because reasons. /// @@ -551,7 +551,7 @@ pub fn map_mmio_region(physical_address: usize, size: usize, virtual_address: us /// /// # Errors /// -/// * The whole initial design of TLS on x86 should be considered an error. +/// * The whole initial darg4gn of TLS on x86 should be considered an error. /// * No returned error otherwise. pub unsafe fn set_thread_area(address: usize) -> Result<(), KernelError> { unsafe { From 3a4de25d4ae1d14883e58120dac403c975dccec0 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 17:09:30 -0400 Subject: [PATCH 06/10] Add aarch64 syscall stub --- libuser/src/syscalls.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libuser/src/syscalls.rs b/libuser/src/syscalls.rs index 855472e2d..851e2d699 100644 --- a/libuser/src/syscalls.rs +++ b/libuser/src/syscalls.rs @@ -105,8 +105,28 @@ macro_rules! syscall { arg6 }; + #[cfg(not(target_arch = "aarch64"))] syscall_inner(&mut registers); + #[cfg(target_arch = "aarch64")] + asm!( + "svc $7" + : "={x0}"(registers.nr), + "={x1}"(registers.arg1), + "={x2}"(registers.arg2), + "={x3}"(registers.arg3), + "={x4}"(registers.arg4), + "={x5}"(registers.arg5), + "={x6}"(registers.arg6) + : "i"($nr), + "{x1}"(registers.arg1), + "{x2}"(registers.arg2), + "{x3}"(registers.arg3), + "{x4}"(registers.arg4), + "{x5}"(registers.arg5), + "{x6}"(registers.arg6) + ); + if registers.nr == 0 { Ok((registers.arg1, registers.arg2, registers.arg3, registers.arg4)) } else { From f57980ed48dd415d47cb6372a1436849dcd6d2d4 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 17:55:37 -0400 Subject: [PATCH 07/10] Handle shifted arguments on x86 --- libuser/src/syscalls.rs | 45 +++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/libuser/src/syscalls.rs b/libuser/src/syscalls.rs index 851e2d699..6e2fb0b59 100644 --- a/libuser/src/syscalls.rs +++ b/libuser/src/syscalls.rs @@ -60,7 +60,7 @@ syscall_inner: #[cfg(not(target_os = "sunrise"))] #[no_mangle] extern fn syscall_inner(regs: &mut super::Registers) { - regs.nr = crate::error::KernelError::NotImplemented.make_ret() as usize; + regs.arg0 = crate::error::KernelError::NotImplemented.make_ret() as usize; } } @@ -70,7 +70,7 @@ syscall_inner: #[repr(C)] #[allow(clippy::missing_docs_in_private_items)] struct Registers { - nr: usize, + arg0: usize, arg1: usize, arg2: usize, arg3: usize, @@ -85,6 +85,7 @@ extern { // unsafe fn syscall(nr: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize, arg6: usize) -> Result<(usize, usize, usize, usize), KernelError> { /// Generic syscall function. +#[cfg(not(target_arch = "aarch64"))] macro_rules! syscall { ($nr:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr) => {{ let nr: usize = $nr; @@ -96,7 +97,7 @@ macro_rules! syscall { let arg6: usize = $arg6; let mut registers = Registers { - nr, + arg0: nr, arg1, arg2, arg3, @@ -105,13 +106,40 @@ macro_rules! syscall { arg6 }; - #[cfg(not(target_arch = "aarch64"))] syscall_inner(&mut registers); - #[cfg(target_arch = "aarch64")] + if registers.arg0 == 0 { + Ok((registers.arg1, registers.arg2, registers.arg3, registers.arg4)) + } else { + Err(KernelError::from_syscall_ret(registers.arg0 as u32)) + } + }}; +} + +/// Generic syscall function. +#[cfg(target_arch = "aarch64")] +macro_rules! syscall { + ($nr:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr) => {{ + let arg0: usize = $arg1; + let arg1: usize = $arg2; + let arg2: usize = $arg3; + let arg3: usize = $arg4; + let arg4: usize = $arg5; + let arg5: usize = $arg6; + + let mut registers = Registers { + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6: 0, + }; + asm!( "svc $7" - : "={x0}"(registers.nr), + : "={x0}"(registers.arg0), "={x1}"(registers.arg1), "={x2}"(registers.arg2), "={x3}"(registers.arg3), @@ -119,6 +147,7 @@ macro_rules! syscall { "={x5}"(registers.arg5), "={x6}"(registers.arg6) : "i"($nr), + "{x0}"(registers.arg0), "{x1}"(registers.arg1), "{x2}"(registers.arg2), "{x3}"(registers.arg3), @@ -127,10 +156,10 @@ macro_rules! syscall { "{x6}"(registers.arg6) ); - if registers.nr == 0 { + if registers.arg0 == 0 { Ok((registers.arg1, registers.arg2, registers.arg3, registers.arg4)) } else { - Err(KernelError::from_syscall_ret(registers.nr as u32)) + Err(KernelError::from_syscall_ret(registers.arg0 as u32)) } }}; } From b97f8a9b28f8d9bb42db5957fbf8d36344aaf5c8 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 18:02:09 -0400 Subject: [PATCH 08/10] Address review --- libuser/src/syscalls.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libuser/src/syscalls.rs b/libuser/src/syscalls.rs index 6e2fb0b59..9fa99a81b 100644 --- a/libuser/src/syscalls.rs +++ b/libuser/src/syscalls.rs @@ -154,6 +154,8 @@ macro_rules! syscall { "{x4}"(registers.arg4), "{x5}"(registers.arg5), "{x6}"(registers.arg6) + : "memory" + : "volatile" ); if registers.arg0 == 0 { @@ -164,7 +166,7 @@ macro_rules! syscall { }}; } -/// Rarg4ze the heap of a process, just like a brk. +/// Resize the heap of a process, just like a brk. /// It can both expand, and shrink the heap. /// /// If `new_size` == 0, the heap space is entirely de-allocated. @@ -267,7 +269,7 @@ pub fn sleep_thread(nanos: usize) -> Result<(), KernelError> { /// Sets the "signaled" state of an event. Calling this on an unsignalled event /// will cause any thread waiting on this event through [wait_synchronization()] /// to wake up. Any future calls to [wait_synchronization()] with this handle -/// will immarg5ately return - the user has to clear the "signaled" state through +/// will immediately return - the user has to clear the "signaled" state through /// [clear_event()]. /// /// Takes either a [ReadableEvent] or a [WritableEvent]. @@ -589,7 +591,7 @@ pub fn map_mmio_region(physical_address: usize, size: usize, virtual_address: us /// /// ## x86_64 /// -/// ![same, but different, but still same](https://marg5a.giphy.com/marg5a/C6JQPEUsZUyVq/giphy.gif) +/// ![same, but different, but still same](https://media.giphy.com/media/C6JQPEUsZUyVq/giphy.gif) /// /// `fs` is used instead of `gs`, because reasons. /// @@ -600,7 +602,7 @@ pub fn map_mmio_region(physical_address: usize, size: usize, virtual_address: us /// /// # Errors /// -/// * The whole initial darg4gn of TLS on x86 should be considered an error. +/// * The whole initial design of TLS on x86 should be considered an error. /// * No returned error otherwise. pub unsafe fn set_thread_area(address: usize) -> Result<(), KernelError> { unsafe { From eb2d5c849ff092748da81b61aa40498862475eb2 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 19:29:37 -0400 Subject: [PATCH 09/10] Add note about aarch64 threads --- libuser/src/threads.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libuser/src/threads.rs b/libuser/src/threads.rs index 70e507d21..bcf573961 100644 --- a/libuser/src/threads.rs +++ b/libuser/src/threads.rs @@ -204,7 +204,7 @@ fn get_my_tls_region() -> *mut TLS { tls } -/// Get a pointer to this thread's [TLS] region pointed to by `fs`, translated to the flat-memory model. +/// Get a pointer to this thread's [TLS] region pointed to by `TPIDRRO_EL0`. #[inline] #[cfg(target_arch = "aarch64")] fn get_my_tls_region() -> *mut TLS { @@ -391,6 +391,7 @@ extern "fastcall" fn thread_trampoline(thread_context_addr: usize) -> ! { /// The routine to call and its argument are expected to be found in this `ThreadContext`. #[cfg(not(target_arch = "x86"))] extern fn thread_trampoline(thread_context_addr: usize) -> ! { + // TODO: figure out aarch64 TLS debug!("starting from new thread, context at address {:#010x}", thread_context_addr); // first save the address of our context in our TLS region unsafe { From 708cb35618e9d00081c5bbd58e99820d3176d4fb Mon Sep 17 00:00:00 2001 From: leo60228 Date: Fri, 20 Mar 2020 19:33:51 -0400 Subject: [PATCH 10/10] Revert "Use non-arch-specific register names" This reverts commit 253cacddbd1484652779573c949c38c56313e6bf. --- libuser/src/syscalls.rs | 91 ++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 52 deletions(-) diff --git a/libuser/src/syscalls.rs b/libuser/src/syscalls.rs index 9fa99a81b..6f0d952f3 100644 --- a/libuser/src/syscalls.rs +++ b/libuser/src/syscalls.rs @@ -60,7 +60,7 @@ syscall_inner: #[cfg(not(target_os = "sunrise"))] #[no_mangle] extern fn syscall_inner(regs: &mut super::Registers) { - regs.arg0 = crate::error::KernelError::NotImplemented.make_ret() as usize; + regs.eax = crate::error::KernelError::NotImplemented.make_ret() as usize; } } @@ -70,13 +70,13 @@ syscall_inner: #[repr(C)] #[allow(clippy::missing_docs_in_private_items)] struct Registers { - arg0: usize, - arg1: usize, - arg2: usize, - arg3: usize, - arg4: usize, - arg5: usize, - arg6: usize, + eax: usize, + ebx: usize, + ecx: usize, + edx: usize, + esi: usize, + edi: usize, + ebp: usize, } extern { @@ -97,21 +97,21 @@ macro_rules! syscall { let arg6: usize = $arg6; let mut registers = Registers { - arg0: nr, - arg1, - arg2, - arg3, - arg4, - arg5, - arg6 + eax: nr, + ebx: arg1, + ecx: arg2, + edx: arg3, + esi: arg4, + edi: arg5, + ebp: arg6 }; syscall_inner(&mut registers); - if registers.arg0 == 0 { - Ok((registers.arg1, registers.arg2, registers.arg3, registers.arg4)) + if registers.eax == 0 { + Ok((registers.ebx, registers.ecx, registers.edx, registers.esi)) } else { - Err(KernelError::from_syscall_ret(registers.arg0 as u32)) + Err(KernelError::from_syscall_ret(registers.eax as u32)) } }}; } @@ -120,48 +120,35 @@ macro_rules! syscall { #[cfg(target_arch = "aarch64")] macro_rules! syscall { ($nr:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr) => {{ - let arg0: usize = $arg1; - let arg1: usize = $arg2; - let arg2: usize = $arg3; - let arg3: usize = $arg4; - let arg4: usize = $arg5; + let mut arg0: usize = $arg1; + let mut arg1: usize = $arg2; + let mut arg2: usize = $arg3; + let mut arg3: usize = $arg4; + let mut arg4: usize = $arg5; let arg5: usize = $arg6; - let mut registers = Registers { - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - arg6: 0, - }; - asm!( - "svc $7" - : "={x0}"(registers.arg0), - "={x1}"(registers.arg1), - "={x2}"(registers.arg2), - "={x3}"(registers.arg3), - "={x4}"(registers.arg4), - "={x5}"(registers.arg5), - "={x6}"(registers.arg6) + "svc $5" + : "={x0}"(arg0), + "={x1}"(arg1), + "={x2}"(arg2), + "={x3}"(arg3), + "={x4}"(arg4) : "i"($nr), - "{x0}"(registers.arg0), - "{x1}"(registers.arg1), - "{x2}"(registers.arg2), - "{x3}"(registers.arg3), - "{x4}"(registers.arg4), - "{x5}"(registers.arg5), - "{x6}"(registers.arg6) - : "memory" + "{x0}"(arg0), + "{x1}"(arg1), + "{x2}"(arg2), + "{x3}"(arg3), + "{x4}"(arg4), + "{x5}"(arg5) + : "memory", "x5", "x6" : "volatile" ); - if registers.arg0 == 0 { - Ok((registers.arg1, registers.arg2, registers.arg3, registers.arg4)) + if arg0 == 0 { + Ok((arg1, arg2, arg3, arg4)) } else { - Err(KernelError::from_syscall_ret(registers.arg0 as u32)) + Err(KernelError::from_syscall_ret(arg0 as u32)) } }}; }