feat: syscall stub

This commit is contained in:
2021-10-21 12:16:24 +03:00
parent e745237130
commit 67d49f8f0e
16 changed files with 231 additions and 38 deletions
Generated
+7
View File
@@ -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"
+1
View File
@@ -10,6 +10,7 @@ edition = "2018"
[workspace]
members = [
"kernel",
"libusr",
"init",
"error"
]
+1 -1
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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
}
+8 -3
View File
@@ -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;
}
_ => {}
+2
View File
@@ -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) -> ! {
+8 -6
View File
@@ -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();
}
+7 -4
View File
@@ -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);
}
+3 -3
View File
@@ -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(&current).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);
}
}
+60
View File
@@ -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),
}
}
+8
View File
@@ -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]
+29
View File
@@ -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);
}
+31
View File
@@ -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
}
+33
View File
@@ -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);
}
+27
View File
@@ -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)
}