feat: syscall stub
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
use crate::arch::machine;
|
||||
use crate::debug::Level;
|
||||
use crate::dev::irq::{IntController, IrqContext};
|
||||
use crate::syscall;
|
||||
use cortex_a::registers::{ESR_EL1, FAR_EL1};
|
||||
use tock_registers::interfaces::Readable;
|
||||
|
||||
@@ -18,7 +19,7 @@ pub const EC_SVC_AA64: u64 = 0b010101;
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
struct ExceptionFrame {
|
||||
x: [u64; 32],
|
||||
x: [usize; 32],
|
||||
spsr_el1: u64,
|
||||
elr_el1: u64,
|
||||
sp_el0: u64,
|
||||
@@ -81,8 +82,12 @@ extern "C" fn __aa64_exc_sync_handler(exc: &mut ExceptionFrame) {
|
||||
dump_data_abort(Level::Error, esr, far);
|
||||
}
|
||||
EC_SVC_AA64 => {
|
||||
infoln!("{:#x} {:#x}", exc.x[0], exc.x[1]);
|
||||
exc.x[0] += 1;
|
||||
unsafe {
|
||||
match syscall::syscall(exc.x[8], &exc.x[..6]) {
|
||||
Ok(val) => exc.x[0] = val,
|
||||
Err(_) => exc.x[0] = usize::MAX,
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -31,6 +31,8 @@ pub mod mem;
|
||||
pub mod proc;
|
||||
pub mod sync;
|
||||
pub mod util;
|
||||
#[allow(missing_docs)]
|
||||
pub mod syscall;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
|
||||
|
||||
@@ -57,13 +57,15 @@ pub unsafe fn enter(initrd: Option<(usize, usize)>) -> ! {
|
||||
if let Some((start, end)) = initrd {
|
||||
let initrd = Box::into_raw(Box::new((mem::virtualize(start), mem::virtualize(end))));
|
||||
|
||||
spawn!(fn (initrd_ptr: usize) {
|
||||
debugln!("Running kernel init process");
|
||||
for _ in 0..4 {
|
||||
spawn!(fn (initrd_ptr: usize) {
|
||||
debugln!("Running kernel init process");
|
||||
|
||||
let (start, _end) = unsafe { *(initrd_ptr as *const (usize, usize)) };
|
||||
Process::execve(|space| elf::load_elf(space, start as *const u8), 0).unwrap();
|
||||
panic!("This code should not run");
|
||||
}, initrd as usize);
|
||||
let (start, _end) = unsafe { *(initrd_ptr as *const (usize, usize)) };
|
||||
Process::execve(|space| elf::load_elf(space, start as *const u8), 0).unwrap();
|
||||
panic!("This code should not run");
|
||||
}, initrd as usize);
|
||||
}
|
||||
}
|
||||
SCHED.enter();
|
||||
}
|
||||
|
||||
@@ -125,6 +125,11 @@ impl Process {
|
||||
const USTACK_VIRT_TOP: usize = 0x100000000;
|
||||
const USTACK_PAGES: usize = 4;
|
||||
|
||||
/// Returns currently executing process
|
||||
pub fn current() -> ProcessRef {
|
||||
SCHED.current_process()
|
||||
}
|
||||
|
||||
/// Schedules an initial thread for execution
|
||||
///
|
||||
/// # Safety
|
||||
@@ -190,6 +195,7 @@ impl Process {
|
||||
state: State::Ready,
|
||||
}),
|
||||
});
|
||||
debugln!("New kernel process: {}", id);
|
||||
assert!(PROCESSES.lock().insert(id, res.clone()).is_none());
|
||||
Ok(res)
|
||||
}
|
||||
@@ -263,10 +269,7 @@ impl Process {
|
||||
old_pid,
|
||||
lock.id
|
||||
);
|
||||
assert!(
|
||||
proc_lock.insert(lock.id, proc.clone()).is_none(),
|
||||
"Failed to downgrade kernel process (add user pid)"
|
||||
);
|
||||
assert!(proc_lock.insert(lock.id, proc.clone()).is_none());
|
||||
unsafe {
|
||||
SCHED.hack_current_pid(lock.id);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ impl Scheduler {
|
||||
PROCESSES.lock().get(&id).unwrap().clone()
|
||||
};
|
||||
|
||||
asm!("msr daifclr, #2");
|
||||
asm!("msr daifset, #2");
|
||||
Process::enter(thread)
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ impl Scheduler {
|
||||
let lock = PROCESSES.lock();
|
||||
(
|
||||
lock.get(¤t).unwrap().clone(),
|
||||
lock.get(&next).unwrap().clone(),
|
||||
lock.get(&next).unwrap().clone()
|
||||
)
|
||||
};
|
||||
|
||||
@@ -112,7 +112,7 @@ impl Scheduler {
|
||||
|
||||
if !Rc::ptr_eq(&from, &to) {
|
||||
unsafe {
|
||||
asm!("msr daifclr, #2");
|
||||
asm!("msr daifset, #2");
|
||||
Process::switch(from, to, discard);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
use crate::mem;
|
||||
use error::Errno;
|
||||
|
||||
fn translate(virt: usize) -> Option<usize> {
|
||||
let mut res: usize;
|
||||
unsafe {
|
||||
asm!("at s1e1r, {}; mrs {}, par_el1", in(reg) virt, out(reg) res);
|
||||
}
|
||||
if res & 1 == 0 {
|
||||
Some(res & !(0xFFF | (0xFF << 56)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_user_ptr(base: usize, len: usize) -> Result<(), Errno> {
|
||||
if base > mem::KERNEL_OFFSET || base + len > mem::KERNEL_OFFSET {
|
||||
warnln!("User region refers to kernel memory: base={:#x}, len={:#x}", base, len);
|
||||
return Err(Errno::InvalidArgument);
|
||||
}
|
||||
|
||||
for i in (base / mem::PAGE_SIZE)..((base + len + mem::PAGE_SIZE - 1) / mem::PAGE_SIZE) {
|
||||
if translate(i * mem::PAGE_SIZE).is_none() {
|
||||
warnln!(
|
||||
"User region refers to unmapped memory: base={:#x}, len={:#x} (page {:#x})",
|
||||
base,
|
||||
len,
|
||||
i * mem::PAGE_SIZE
|
||||
);
|
||||
return Err(Errno::InvalidArgument);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
|
||||
match num {
|
||||
// sys_exit
|
||||
1 => {
|
||||
use crate::proc::Process;
|
||||
Process::current().exit(args[0] as i32);
|
||||
unreachable!();
|
||||
}
|
||||
// sys_ex_debug_trace
|
||||
120 => {
|
||||
use crate::debug::Level;
|
||||
validate_user_ptr(args[0], args[1])?;
|
||||
|
||||
let buf = core::slice::from_raw_parts(args[0] as *const u8, args[1]);
|
||||
print!(Level::Debug, "[trace] ");
|
||||
for &byte in buf.iter() {
|
||||
print!(Level::Debug, "{}", byte as char);
|
||||
}
|
||||
println!(Level::Debug, "");
|
||||
Ok(args[1])
|
||||
}
|
||||
_ => panic!("Undefined system call: {}", num),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user