diff --git a/src/interrupt/syscall.rs b/src/interrupt/syscall.rs index d1527da..bc4ea43 100644 --- a/src/interrupt/syscall.rs +++ b/src/interrupt/syscall.rs @@ -1,23 +1,19 @@ #[naked] pub unsafe extern fn syscall() { #[inline(never)] - unsafe fn inner() { + unsafe fn inner(stack: &mut SyscallStack) { extern { - fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> usize; + fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, rbp: usize, stack: &mut SyscallStack) -> usize; } let mut a; { let b; - let c; - let d; - let e; - let f; - let stack; - asm!("" : "={rax}"(a), "={rbx}"(b), "={rcx}"(c), "={rdx}"(d), "={rsi}"(e), "={rdi}"(f), "={rbp}"(stack) + let rbp; + asm!("" : "={rax}"(a), "={rbx}"(b), "={rbp}"(rbp) : : : "intel", "volatile"); - a = syscall(a, b, c, d, e, f, stack); + a = syscall(a, b, stack.rcx, stack.rdx, stack.rsi, stack.rdi, rbp, stack); } asm!("" : : "{rax}"(a) : : "intel", "volatile"); @@ -37,7 +33,11 @@ pub unsafe extern fn syscall() { mov fs, r11" : : : : "intel", "volatile"); - inner(); + // Get reference to stack variables + let rsp: usize; + asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); + + inner(&mut *(rsp as *mut SyscallStack)); // Interrupt return asm!("pop fs @@ -53,6 +53,23 @@ pub unsafe extern fn syscall() { : : : : "intel", "volatile"); } +#[allow(dead_code)] +#[repr(packed)] +pub struct SyscallStack { + pub fs: usize, + pub r11: usize, + pub r10: usize, + pub r9: usize, + pub r8: usize, + pub rsi: usize, + pub rdi: usize, + pub rdx: usize, + pub rcx: usize, + pub rip: usize, + pub cs: usize, + pub rflags: usize, +} + #[naked] pub unsafe extern fn clone_ret() -> usize { asm!("pop rbp" diff --git a/src/macros.rs b/src/macros.rs index a54fb35..2c8d133 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -85,7 +85,7 @@ macro_rules! interrupt_stack { #[naked] pub unsafe extern fn $name () { #[inline(never)] - unsafe fn inner($stack: &$crate::macros::InterruptStack) { + unsafe fn inner($stack: &mut $crate::macros::InterruptStack) { $func } @@ -109,7 +109,7 @@ macro_rules! interrupt_stack { asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); // Call inner rust function - inner(&*(rsp as *const $crate::macros::InterruptStack)); + inner(&mut *(rsp as *mut $crate::macros::InterruptStack)); // Pop scratch registers and return asm!("pop fs diff --git a/src/start.rs b/src/start.rs index c7a6dd4..cd3c0c4 100644 --- a/src/start.rs +++ b/src/start.rs @@ -172,7 +172,7 @@ pub unsafe fn usermode(ip: usize, sp: usize, arg: usize) -> ! { : "{r10}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment "{r11}"(gdt::GDT_USER_TLS << 3 | 3), // TLS segment "{r12}"(sp), // Stack pointer - "{r13}"(3 << 12 | 1 << 9), // Flags - Set IOPL and interrupt enable flag + "{r13}"(0 << 12 | 1 << 9), // Flags - Set IOPL and interrupt enable flag "{r14}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment "{r15}"(ip) // IP "{rdi}"(arg) // Argument diff --git a/src/syscall/driver.rs b/src/syscall/driver.rs index c28aa76..30f4492 100644 --- a/src/syscall/driver.rs +++ b/src/syscall/driver.rs @@ -1,8 +1,9 @@ +use interrupt::syscall::SyscallStack; use memory::{allocate_frames, deallocate_frames, Frame}; use paging::{entry, ActivePageTable, PhysicalAddress, VirtualAddress}; use context; use context::memory::Grant; -use syscall::error::{Error, EFAULT, ENOMEM, EPERM, ESRCH, Result}; +use syscall::error::{Error, EFAULT, EINVAL, ENOMEM, EPERM, ESRCH, Result}; use syscall::flag::{MAP_WRITE, MAP_WRITE_COMBINE}; fn enforce_root() -> Result<()> { @@ -16,10 +17,15 @@ fn enforce_root() -> Result<()> { } } -pub fn iopl(_level: usize, _stack_base: usize) -> Result { +pub fn iopl(level: usize, stack: &mut SyscallStack) -> Result { enforce_root()?; - //TODO + if level > 3 { + return Err(Error::new(EINVAL)); + } + + stack.rflags = (stack.rflags & !(3 << 12)) | ((level & 3) << 12); + Ok(0) } diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 8bfd132..77e6412 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -17,6 +17,7 @@ use self::error::{Error, Result, ENOSYS}; use self::number::*; use context::ContextId; +use interrupt::syscall::SyscallStack; use scheme::{FileHandle, SchemeNamespace}; /// Driver syscalls @@ -41,9 +42,9 @@ pub mod time; pub mod validate; #[no_mangle] -pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> usize { +pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: usize, stack: &mut SyscallStack) -> usize { #[inline(always)] - fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> Result { + fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: usize, stack: &mut SyscallStack) -> Result { match a & SYS_CLASS { SYS_CLASS_FILE => { let fd = FileHandle::from(b); @@ -83,7 +84,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_BRK => brk(b), SYS_GETPID => getpid().map(ContextId::into), SYS_GETPPID => getppid().map(ContextId::into), - SYS_CLONE => clone(b, stack).map(ContextId::into), + SYS_CLONE => clone(b, bp).map(ContextId::into), SYS_EXIT => exit((b & 0xFF) << 8), SYS_KILL => kill(ContextId::from(b), c), SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into), @@ -127,7 +128,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize } } - let result = inner(a, b, c, d, e, f, stack); + let result = inner(a, b, c, d, e, f, bp, stack); /* if let Err(ref err) = result {