Pass syscall data to syscall, implement iopl

This commit is contained in:
Jeremy Soller
2017-07-19 14:51:12 -06:00
parent f7b961ddff
commit 4ae6ed9d4c
5 changed files with 44 additions and 20 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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<usize> {
pub fn iopl(level: usize, stack: &mut SyscallStack) -> Result<usize> {
enforce_root()?;
//TODO
if level > 3 {
return Err(Error::new(EINVAL));
}
stack.rflags = (stack.rflags & !(3 << 12)) | ((level & 3) << 12);
Ok(0)
}

View File

@@ -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<usize> {
fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: usize, stack: &mut SyscallStack) -> Result<usize> {
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 {