feat: syscall stub
This commit is contained in:
Generated
+7
@@ -64,6 +64,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "init"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libusr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel"
|
||||
@@ -77,6 +80,10 @@ dependencies = [
|
||||
"tock-registers",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libusr"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.5.6"
|
||||
|
||||
@@ -10,6 +10,7 @@ edition = "2018"
|
||||
[workspace]
|
||||
members = [
|
||||
"kernel",
|
||||
"libusr",
|
||||
"init",
|
||||
"error"
|
||||
]
|
||||
|
||||
@@ -58,7 +58,7 @@ all: kernel
|
||||
|
||||
kernel:
|
||||
cd kernel && cargo build $(CARGO_BUILD_OPTS)
|
||||
cd init && cargo build --target=../etc/$(ARCH)-osdev5.json -Z build-std=core
|
||||
cd init && cargo build --target=../etc/$(ARCH)-osdev5.json -Z build-std=core,alloc,compiler_builtins
|
||||
cp target/$(ARCH)-osdev5/debug/init $(O)/initrd.img
|
||||
ifeq ($(ARCH),aarch64)
|
||||
$(LLVM_BASE)/llvm-strip -o $(O)/kernel.strip $(O)/kernel
|
||||
|
||||
@@ -6,3 +6,4 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
libusr = { path = "../libusr" }
|
||||
|
||||
+5
-21
@@ -1,27 +1,11 @@
|
||||
#![feature(asm)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
#[macro_use]
|
||||
extern crate libusr;
|
||||
|
||||
#[link_section = ".text._start"]
|
||||
#[no_mangle]
|
||||
extern "C" fn _start(arg: usize) -> ! {
|
||||
let mut c0 = arg;
|
||||
let mut c1: usize;
|
||||
loop {
|
||||
unsafe {
|
||||
asm!("mrs {}, cntpct_el0", out(reg) c1);
|
||||
asm!("svc #0", inout("x0") c0, in("x1") c1);
|
||||
}
|
||||
|
||||
for _ in 0..1000000 {
|
||||
unsafe { asm!("nop"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_pi: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
fn main() -> i32 {
|
||||
trace!("Hello from userspace");
|
||||
123
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "libusr"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,29 @@
|
||||
#![feature(
|
||||
asm,
|
||||
alloc_error_handler,
|
||||
)]
|
||||
#![no_std]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
mod sys;
|
||||
pub mod mem;
|
||||
pub mod os;
|
||||
|
||||
#[link_section = ".text._start"]
|
||||
#[no_mangle]
|
||||
extern "C" fn _start(_arg: usize) -> ! {
|
||||
extern "Rust" {
|
||||
fn main() -> i32;
|
||||
}
|
||||
unsafe {
|
||||
sys::sys_exit(main());
|
||||
}
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(pi: &PanicInfo) -> ! {
|
||||
// TODO formatted messages
|
||||
trace!("Panic ocurred: {}", pi);
|
||||
sys::sys_exit(-1);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memcpy(dst: *mut u8, src: *mut u8, mut len: usize) -> *mut u8 {
|
||||
while len != 0 {
|
||||
len -= 1;
|
||||
*dst.add(len) = *src.add(len);
|
||||
}
|
||||
dst
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memcmp(a: *mut u8, b: *mut u8, mut len: usize) -> isize {
|
||||
while len != 0 {
|
||||
len -= 1;
|
||||
if *a.add(len) < *b.add(len) {
|
||||
return -1;
|
||||
}
|
||||
if *a.add(len) > *b.add(len) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memset(buf: *mut u8, val: u8, mut len: usize) -> *mut u8 {
|
||||
while len != 0 {
|
||||
len -= 1;
|
||||
*buf.add(len) = val;
|
||||
}
|
||||
buf
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
use crate::sys;
|
||||
use core::fmt;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! trace {
|
||||
($($args:tt)+) => ($crate::os::_trace(format_args!($($args)+)))
|
||||
}
|
||||
|
||||
struct BufferWriter<'a> {
|
||||
buf: &'a mut [u8],
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl fmt::Write for BufferWriter<'_> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for byte in s.bytes() {
|
||||
self.buf[self.pos] = byte;
|
||||
self.pos += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _trace(args: fmt::Arguments) {
|
||||
use core::fmt::Write;
|
||||
static mut BUFFER: [u8; 4096] = [0; 4096];
|
||||
let mut writer = BufferWriter {
|
||||
buf: unsafe { &mut BUFFER },
|
||||
pos: 0,
|
||||
};
|
||||
writer.write_fmt(args).ok();
|
||||
sys::sys_ex_debug_trace(unsafe { &BUFFER } as *const _, writer.pos);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
macro_rules! syscall {
|
||||
($num:expr, $a0:expr) => {{
|
||||
let mut res: usize = $a0;
|
||||
unsafe {
|
||||
asm!("svc #0", inout("x0") res, in("x8") $num, options(nostack));
|
||||
}
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr) => {{
|
||||
let mut res: usize = $a0;
|
||||
unsafe {
|
||||
asm!("svc #0", inout("x0") res, in("x1") $a1, in("x8") $num, options(nostack));
|
||||
}
|
||||
res
|
||||
}};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_exit(status: i32) -> ! {
|
||||
syscall!(1, status as usize);
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_ex_debug_trace(msg: *const u8, len: usize) -> usize {
|
||||
syscall!(120, msg as usize, len)
|
||||
}
|
||||
Reference in New Issue
Block a user