Skip to content
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