Skip to content

syscall-exec #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
6 changes: 5 additions & 1 deletion os/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ $(bin): kernel

asm:
$(objdump) -d $(kernel) | less
assembly:
$(objdump) -d $(kernel) > target/os.asm

build: $(bin)

Expand All @@ -34,6 +36,8 @@ qemu: build
-machine virt \
-nographic \
-bios default \
-device loader,file=$(bin),addr=0x80200000
-device loader,file=$(bin),addr=0x80200000 \
-drive file=../usr/build/riscv64.img,if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0

run: build qemu
61 changes: 61 additions & 0 deletions os/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use riscv::register::sstatus;
use riscv::register::{scause::Scause, sstatus::Sstatus};

#[repr(C)]
#[derive(Clone)]
pub struct TrapFrame {
pub x: [usize; 32], // General registers
pub sstatus: Sstatus, // Supervisor Status Register
Expand All @@ -11,7 +12,43 @@ pub struct TrapFrame {
pub scause: Scause, // Scause register: record the cause of exception/interrupt/trap
}

impl TrapFrame {
/// Constructs TrapFrame for a new kernel thread.
///
/// The new thread starts at function `entry` with an usize argument `arg`.
/// The stack pointer will be set to `sp`.
fn new_kernel_thread(entry: extern "C" fn(usize) -> !, arg: usize, sp: usize) -> Self {
use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() };
tf.x[10] = arg; // a0
tf.x[2] = sp;
tf.sepc = entry as usize;
tf.sstatus = sstatus::read();
tf.sstatus.set_spie(true);
tf.sstatus.set_sie(false);
tf.sstatus.set_spp(sstatus::SPP::Supervisor);
tf
}

/// Constructs TrapFrame for a new user thread.
///
/// The new thread starts at `entry_addr`.
/// The stack pointer will be set to `sp`.
pub fn new_user_thread(entry_addr: usize, sp: usize) -> Self {
use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() };
tf.x[2] = sp;
tf.sepc = entry_addr;
tf.sstatus = sstatus::read();
tf.sstatus.set_spie(true);
tf.sstatus.set_sie(false);
tf.sstatus.set_spp(sstatus::SPP::User);
tf
}
}

#[repr(C)]
#[derive(Clone)]
pub struct Context {
pub content_addr: usize,
}
Expand All @@ -31,6 +68,10 @@ impl Context {
ContextContent::new_kernel_thread(entry, kstack_top, satp).push_at(kstack_top)
}

pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, satp: usize) -> Context {
ContextContent::new_fork(tf, kstack_top, satp)
}

pub unsafe fn append_initial_arguments(&self, args: [usize; 3]) {
let contextContent = &mut *(self.content_addr as *mut ContextContent);
contextContent.tf.x[10] = args[0];
Expand Down Expand Up @@ -98,6 +139,26 @@ impl ContextContent {
}
}

/// Fork a user process and get the new Context.
///
/// The stack pointer in kernel mode will be set to `kstack_top`.
/// The SATP register will be set to `satp`.
/// All the other registers are same as the original.
unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, satp: usize) -> Context {
ContextContent {
ra: __trapret as usize,
satp,
s: [0; 12],
tf: {
let mut tf = tf.clone();
// fork function's ret value, the new process is 0
tf.x[10] = 0; // a0
tf
},
}
.push_at(kstack_top)
}

unsafe fn push_at(self, stack_top: usize) -> Context {
let ptr = (stack_top as *mut ContextContent).sub(1);
*ptr = self;
Expand Down
1 change: 1 addition & 0 deletions os/src/drivers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod virtio_disk;
Loading