Compare commits

...

9 Commits

17 changed files with 1288 additions and 24 deletions

View File

@ -16,5 +16,9 @@
"**/.rustup/**": true, "**/.rustup/**": true,
"**/.cargo/registry/**": true, "**/.cargo/registry/**": true,
"**/.cargo/git/**": true, "**/.cargo/git/**": true,
},
"[riscv]": {
"editor.indentSize": "tabSize",
"editor.tabSize": 8
} }
} }

View File

@ -63,7 +63,7 @@ clean:
cargo clean cargo clean
qemu: kernel qemu: kernel
$(QEMU) $(QEMU_ARGS) $(QEMU) $(QEMU_ARGS) | tools/parse_backtrace.sh target/$(BUILD_TARGET)/$(MODE)/kernel
qemu-gdb: kernel qemu-gdb: kernel
$(QEMU) $(QEMU_ARGS) -s -S $(QEMU) $(QEMU_ARGS) -s -S

View File

@ -93,6 +93,10 @@ impl TrapContextOps for TrapContext {
if from_kernel { if from_kernel {
panic_fatal!("Page Fault in Kernel"); panic_fatal!("Page Fault in Kernel");
} }
let stval = riscv::register::stval::read();
trace!("Page Fault: sepc: {:#x}, stval: {:#x}", self.sepc, stval);
// TODO: handle page fault // TODO: handle page fault
}, },
_ => panic_fatal!("Unhandled Trap"), _ => panic_fatal!("Unhandled Trap"),

View File

@ -1,5 +1,5 @@
use crate::logging::set_log_level; use crate::logging::set_log_level;
use crate::plat::console::{set_console, ConsoleDevice, ConsoleDriver, CONSOLE}; use crate::plat::console::{set_console, ConsoleDriver};
use crate::plat::lowlevel::{Hardware, LowLevel}; use crate::plat::lowlevel::{Hardware, LowLevel};
use crate::plat::timer::{Timer, TimerOps}; use crate::plat::timer::{Timer, TimerOps};
use crate::plat::trap::{Trap, TrapOps}; use crate::plat::trap::{Trap, TrapOps};
@ -8,7 +8,7 @@ use crate::scheduler::{IDLE_THREAD, SCHEDULER};
use core::cell::Cell; use core::cell::Cell;
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
use fdt::Fdt; use fdt::Fdt;
use log::{debug, error, info, warn}; use log::{error, info, warn};
#[thread_local] #[thread_local]
pub static HART_ID: Cell<usize> = Cell::new(0); pub static HART_ID: Cell<usize> = Cell::new(0);

View File

@ -29,6 +29,7 @@ mod objects;
mod plat; mod plat;
mod root; mod root;
mod scheduler; mod scheduler;
mod syscall;
mod vspace; mod vspace;
// test infrastructure // test infrastructure

View File

@ -108,7 +108,8 @@ impl<'a> CNodeCap<'a> {
}); });
} }
let get_guard = || (cap_ptr >> (bits_remaining - guard_bits)) & MASK!(guard_bits); let get_guard =
|| cap_ptr.checked_shr((bits_remaining - guard_bits) as u32).unwrap_or_default() & MASK!(guard_bits);
if guard_bits > bits_remaining || get_guard() != cap_guard { if guard_bits > bits_remaining || get_guard() != cap_guard {
return Err(LookupFailure::GuardMismatch { return Err(LookupFailure::GuardMismatch {
bits_left: bits_remaining, bits_left: bits_remaining,

View File

@ -1,8 +1,9 @@
use crate::arch::{layout::mmap_phys_to_virt, trap::TrapContext, vspace::*}; use crate::arch::{layout::mmap_phys_to_virt, trap::TrapContext, vspace::*};
use crate::syscall::handle_syscall;
use crate::{objects::*, plat::trap::TrapContextOps, vspace::*}; use crate::{objects::*, plat::trap::TrapContextOps, vspace::*};
use core::fmt::Debug; use core::fmt::Debug;
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
use uapi::{cap::ObjectType, error::SysResult, fault::*, syscall::*}; use uapi::{cap::ObjectType, fault::*};
use utils::{ use utils::{
addr::*, addr::*,
linked_list::{Link, LinkHelper}, linked_list::{Link, LinkHelper},
@ -59,6 +60,10 @@ impl TcbObject {
} }
} }
pub fn cspace(&self) -> &CapEntry {
&self.cspace
}
pub fn set_cspace(&mut self, cspace: CapEntry) { pub fn set_cspace(&mut self, cspace: CapEntry) {
CNodeCap::try_from(&cspace).expect("set_cspace: invalid cap"); CNodeCap::try_from(&cspace).expect("set_cspace: invalid cap");
self.cspace = cspace; self.cspace = cspace;
@ -119,19 +124,8 @@ impl TcbObject {
} }
pub fn handle_syscall(&mut self) { pub fn handle_syscall(&mut self) {
let handle_syscall_inner = || -> SysResult { // TODO: don't panic here, return error to user instead
let info = MessageInfo::try_from(self.trapframe.get_reg(0))?; handle_syscall(self).unwrap();
let cspace = CNodeCap::try_from(&self.cspace)?;
let cap_ptr = self.trapframe.get_reg(1);
let cap = cspace.resolve_address_bits(cap_ptr, usize::BITS as usize);
debug!("handle_syscall: info={:?}, cap={:?}", info, cap);
todo!("handle_syscall");
};
handle_syscall_inner().unwrap();
} }
} }

View File

@ -13,9 +13,6 @@ use spin::Lazy;
use uapi::{consts::*, cspace::CNodeSlot, error::SysError}; use uapi::{consts::*, cspace::CNodeSlot, error::SysError};
use utils::{addr::*, bin::prev_power_of_two}; use utils::{addr::*, bin::prev_power_of_two};
const ROOT_ASID: usize = 1;
const ROOT_CNODE_SIZE: usize = 128;
static mut ROOT_CNODE: Lazy<[CapEntry; ROOT_CNODE_SIZE]> = static mut ROOT_CNODE: Lazy<[CapEntry; ROOT_CNODE_SIZE]> =
Lazy::new(|| core::array::from_fn(|_| CapEntry::new(NullCap::mint()))); Lazy::new(|| core::array::from_fn(|_| CapEntry::new(NullCap::mint())));

29
kernel/src/syscall.rs Normal file
View File

@ -0,0 +1,29 @@
use crate::{objects::*, plat::trap::TrapContextOps};
use log::trace;
use uapi::{error::*, syscall::*};
pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult {
let info = MessageInfo::try_from(tcb.trapframe.get_reg(0))?;
let cspace = CNodeCap::try_from(tcb.cspace())?;
let cap_ptr = tcb.trapframe.get_reg(1);
let cap = cspace
.resolve_address_bits(cap_ptr, usize::BITS as usize)
.map_err(|e| SysError::from(e))?;
trace!("handle_syscall: info={:?} cap={:?}", info, cap);
match info.label() {
Syscall::DebugPutChar => {
if info.length() != 3 {
return Err(SysError::InvalidArgument);
}
let c = tcb.trapframe.get_reg(2) as u8 as char;
crate::print!("{}", c);
return Ok(());
},
_ => unimplemented!("handle_syscall: {:?}, {:?}", info.label(), cap),
}
}

View File

@ -10,8 +10,11 @@ _start:
la t0, msg la t0, msg
.loop: .loop:
lb a2, 0(t0) lb a2, 0(t0)
beqz a2, _start # print forever beqz a2, _start
syscall (1<<12 | 1), 1 # see uapi/syscall.rs # see uapi/syscall.rs
# msg: label = DebugPutChar, length = 3
# ptr: self-referential to cspace, just to create a valid cptr
syscall (1<<12 | 3), 0x0202020202020202
addi t0, t0, 1 addi t0, t0, 1
j .loop j .loop

1001
run.log Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,8 @@
use utils::{addr::VirtAddr, size::MIB}; use utils::{addr::VirtAddr, size::MIB};
pub const ROOT_ASID: usize = 1;
pub const ROOT_CNODE_SIZE: usize = 256;
pub const ROOT_FDT_ADDR: VirtAddr = VirtAddr(0xfbf0_0000); pub const ROOT_FDT_ADDR: VirtAddr = VirtAddr(0xfbf0_0000);
pub const ROOT_FDT_MAX_SIZE: usize = 1 * MIB; pub const ROOT_FDT_MAX_SIZE: usize = 1 * MIB;
pub const ROOT_FDT_MAX_BITS: usize = ROOT_FDT_MAX_SIZE.ilog2() as usize; pub const ROOT_FDT_MAX_BITS: usize = ROOT_FDT_MAX_SIZE.ilog2() as usize;

View File

@ -7,7 +7,7 @@ pub enum SysError {
RangeError, // Untyped RangeError, // Untyped
NotMapped, // Frame NotMapped, // Frame
AlreadyMapped, // Frame AlreadyMapped, // Frame
MissingEntry, // Frame MissingEntry, // CNode, Frame
} }
pub type SysResult<T = ()> = Result<T, SysError>; pub type SysResult<T = ()> = Result<T, SysError>;

View File

@ -1,3 +1,4 @@
use crate::error::SysError;
use utils::addr::VirtAddr; use utils::addr::VirtAddr;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@ -17,6 +18,17 @@ pub enum LookupFailure {
}, },
} }
impl From<LookupFailure> for SysError {
fn from(e: LookupFailure) -> SysError {
match e {
LookupFailure::InvalidRoot => SysError::MissingEntry,
LookupFailure::MissingCapability { .. } => SysError::MissingEntry,
LookupFailure::DepthMismatch { .. } => SysError::InvalidArgument,
LookupFailure::GuardMismatch { .. } => SysError::InvalidArgument,
}
}
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct CapFault { pub struct CapFault {
address: usize, address: usize,

View File

@ -1,5 +1,6 @@
#![no_std] #![no_std]
#![feature(custom_inner_attributes)] #![feature(custom_inner_attributes)]
#![allow(dead_code)]
#[macro_use] #[macro_use]
extern crate num_derive; extern crate num_derive;

BIN
virt.dtb Normal file

Binary file not shown.

214
virt.dts Normal file
View File

@ -0,0 +1,214 @@
/dts-v1/;
/ {
#address-cells = <0x02>;
#size-cells = <0x02>;
compatible = "riscv-virtio";
model = "riscv-virtio,qemu";
poweroff {
value = <0x5555>;
offset = <0x00>;
regmap = <0x04>;
compatible = "syscon-poweroff";
};
reboot {
value = <0x7777>;
offset = <0x00>;
regmap = <0x04>;
compatible = "syscon-reboot";
};
platform-bus@4000000 {
interrupt-parent = <0x03>;
ranges = <0x00 0x00 0x4000000 0x2000000>;
#address-cells = <0x01>;
#size-cells = <0x01>;
compatible = "qemu,platform\0simple-bus";
};
memory@80000000 {
device_type = "memory";
reg = <0x00 0x80000000 0x00 0x8000000>;
};
cpus {
#address-cells = <0x01>;
#size-cells = <0x00>;
timebase-frequency = <0x989680>;
cpu@0 {
phandle = <0x01>;
device_type = "cpu";
reg = <0x00>;
status = "okay";
compatible = "riscv";
riscv,cbop-block-size = <0x40>;
riscv,cboz-block-size = <0x40>;
riscv,cbom-block-size = <0x40>;
riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0h\0zic64b\0zicbom\0zicbop\0zicboz\0ziccamoa\0ziccif\0zicclsm\0ziccrse\0zicntr\0zicsr\0zifencei\0zihintntl\0zihintpause\0zihpm\0za64rs\0zawrs\0zfa\0zca\0zcd\0zba\0zbb\0zbc\0zbs\0ssccptr\0sscounterenw\0sstc\0sstvala\0sstvecd\0svadu";
riscv,isa-base = "rv64i";
riscv,isa = "rv64imafdch_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_za64rs_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_ssccptr_sscounterenw_sstc_sstvala_sstvecd_svadu";
mmu-type = "riscv,sv57";
interrupt-controller {
#interrupt-cells = <0x01>;
interrupt-controller;
compatible = "riscv,cpu-intc";
phandle = <0x02>;
};
};
cpu-map {
cluster0 {
core0 {
cpu = <0x01>;
};
};
};
};
pmu {
riscv,event-to-mhpmcounters = <0x01 0x01 0x7fff9 0x02 0x02 0x7fffc 0x10019 0x10019 0x7fff8 0x1001b 0x1001b 0x7fff8 0x10021 0x10021 0x7fff8>;
compatible = "riscv,pmu";
};
fw-cfg@10100000 {
dma-coherent;
reg = <0x00 0x10100000 0x00 0x18>;
compatible = "qemu,fw-cfg-mmio";
};
flash@20000000 {
bank-width = <0x04>;
reg = <0x00 0x20000000 0x00 0x2000000 0x00 0x22000000 0x00 0x2000000>;
compatible = "cfi-flash";
};
chosen {
bootargs = "loglevel=4";
linux,initrd-end = <0x84204000>;
linux,initrd-start = <0x84200000>;
stdout-path = "/soc/serial@10000000";
rng-seed = <0xc6392b68 0x86d0dc43 0xc74b3112 0xf7a3a675 0x497511e1 0xb74e5d3c 0x3849ea42 0x668de090>;
};
soc {
#address-cells = <0x02>;
#size-cells = <0x02>;
compatible = "simple-bus";
ranges;
rtc@101000 {
interrupts = <0x0b>;
interrupt-parent = <0x03>;
reg = <0x00 0x101000 0x00 0x1000>;
compatible = "google,goldfish-rtc";
};
serial@10000000 {
interrupts = <0x0a>;
interrupt-parent = <0x03>;
clock-frequency = "\08@";
reg = <0x00 0x10000000 0x00 0x100>;
compatible = "ns16550a";
};
test@100000 {
phandle = <0x04>;
reg = <0x00 0x100000 0x00 0x1000>;
compatible = "sifive,test1\0sifive,test0\0syscon";
};
virtio_mmio@10008000 {
interrupts = <0x08>;
interrupt-parent = <0x03>;
reg = <0x00 0x10008000 0x00 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10007000 {
interrupts = <0x07>;
interrupt-parent = <0x03>;
reg = <0x00 0x10007000 0x00 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10006000 {
interrupts = <0x06>;
interrupt-parent = <0x03>;
reg = <0x00 0x10006000 0x00 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10005000 {
interrupts = <0x05>;
interrupt-parent = <0x03>;
reg = <0x00 0x10005000 0x00 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10004000 {
interrupts = <0x04>;
interrupt-parent = <0x03>;
reg = <0x00 0x10004000 0x00 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10003000 {
interrupts = <0x03>;
interrupt-parent = <0x03>;
reg = <0x00 0x10003000 0x00 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10002000 {
interrupts = <0x02>;
interrupt-parent = <0x03>;
reg = <0x00 0x10002000 0x00 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10001000 {
interrupts = <0x01>;
interrupt-parent = <0x03>;
reg = <0x00 0x10001000 0x00 0x1000>;
compatible = "virtio,mmio";
};
plic@c000000 {
phandle = <0x03>;
riscv,ndev = <0x5f>;
reg = <0x00 0xc000000 0x00 0x600000>;
interrupts-extended = <0x02 0x0b 0x02 0x09>;
interrupt-controller;
compatible = "sifive,plic-1.0.0\0riscv,plic0";
#address-cells = <0x00>;
#interrupt-cells = <0x01>;
};
clint@2000000 {
interrupts-extended = <0x02 0x03 0x02 0x07>;
reg = <0x00 0x2000000 0x00 0x10000>;
compatible = "sifive,clint0\0riscv,clint0";
};
pci@30000000 {
interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
interrupt-map = <0x00 0x00 0x00 0x01 0x03 0x20 0x00 0x00 0x00 0x02 0x03 0x21 0x00 0x00 0x00 0x03 0x03 0x22 0x00 0x00 0x00 0x04 0x03 0x23 0x800 0x00 0x00 0x01 0x03 0x21 0x800 0x00 0x00 0x02 0x03 0x22 0x800 0x00 0x00 0x03 0x03 0x23 0x800 0x00 0x00 0x04 0x03 0x20 0x1000 0x00 0x00 0x01 0x03 0x22 0x1000 0x00 0x00 0x02 0x03 0x23 0x1000 0x00 0x00 0x03 0x03 0x20 0x1000 0x00 0x00 0x04 0x03 0x21 0x1800 0x00 0x00 0x01 0x03 0x23 0x1800 0x00 0x00 0x02 0x03 0x20 0x1800 0x00 0x00 0x03 0x03 0x21 0x1800 0x00 0x00 0x04 0x03 0x22>;
ranges = <0x1000000 0x00 0x00 0x00 0x3000000 0x00 0x10000 0x2000000 0x00 0x40000000 0x00 0x40000000 0x00 0x40000000 0x3000000 0x04 0x00 0x04 0x00 0x04 0x00>;
reg = <0x00 0x30000000 0x00 0x10000000>;
dma-coherent;
bus-range = <0x00 0xff>;
linux,pci-domain = <0x00>;
device_type = "pci";
compatible = "pci-host-ecam-generic";
#size-cells = <0x02>;
#interrupt-cells = <0x01>;
#address-cells = <0x03>;
};
};
};