mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 01:35:19 +08:00
Compare commits
21 Commits
c013478d0b
...
bf6297c5ac
Author | SHA1 | Date | |
---|---|---|---|
bf6297c5ac | |||
61fefde82c | |||
705fb217fd | |||
fe30d8d28c | |||
eb70cd7b73 | |||
2bf8e2341d | |||
0af7025264 | |||
e3be1c56cd | |||
7757a174ce | |||
27deb3302a | |||
ad4da2a7e4 | |||
97392a5788 | |||
8824345b17 | |||
c451aa4c76 | |||
42a7ea89c5 | |||
03aa0edcc8 | |||
8fe47c5728 | |||
da05567fbf | |||
302de5eae1 | |||
a37efbd13f | |||
f4bb68a6f4 |
44
Cargo.lock
generated
44
Cargo.lock
generated
@ -19,9 +19,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
@ -56,9 +56,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.0"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@ -69,6 +69,12 @@ version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
||||
|
||||
[[package]]
|
||||
name = "elf"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "1.0.0"
|
||||
@ -83,9 +89,9 @@ checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.28"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
|
||||
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
@ -98,6 +104,8 @@ dependencies = [
|
||||
"allocator",
|
||||
"bitflags 2.5.0",
|
||||
"cfg-if",
|
||||
"cpio",
|
||||
"elf",
|
||||
"fdt",
|
||||
"log",
|
||||
"num-derive",
|
||||
@ -114,9 +122,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.11"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
@ -130,9 +138,9 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
|
||||
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
@ -150,18 +158,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.18"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.79"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -196,9 +204,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.15"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
|
||||
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||
|
||||
[[package]]
|
||||
name = "sbi-rt"
|
||||
@ -238,9 +246,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.58"
|
||||
version = "2.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
|
||||
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
5
Makefile
5
Makefile
@ -41,6 +41,9 @@ clippy:
|
||||
cargo clippy -p utils
|
||||
cargo clippy --no-deps $(CARGO_TARGET_ARGS) --manifest-path=kernel/Cargo.toml
|
||||
|
||||
fmt:
|
||||
cargo fmt --all
|
||||
|
||||
test:
|
||||
cargo test -p allocator
|
||||
cargo test -p utils
|
||||
@ -64,4 +67,4 @@ qemu: kernel
|
||||
qemu-gdb: kernel
|
||||
$(QEMU) $(QEMU_ARGS) -s -S
|
||||
|
||||
.PHONY: kernel clippy test kernel-test-dump kernel-asm build-target clean qemu qemu-gdb
|
||||
.PHONY: kernel clippy fmt test kernel-test-dump kernel-asm build-target clean qemu qemu-gdb
|
||||
|
@ -20,12 +20,15 @@ riscv = []
|
||||
"riscv.board.virt" = ["riscv.riscv64"]
|
||||
|
||||
[dependencies]
|
||||
uapi = { path = "../uapi" }
|
||||
allocator = { path = "../lib/allocator" }
|
||||
cpio = { path = "../lib/cpio" }
|
||||
tracer = { path = "../lib/tracer" }
|
||||
uapi = { path = "../uapi" }
|
||||
utils = { path = "../lib/utils", default-features = false }
|
||||
|
||||
bitflags = "2.5"
|
||||
cfg-if = "1.0"
|
||||
elf = { version = "0.7", default-features = false }
|
||||
fdt = "0.1"
|
||||
log = "0.4"
|
||||
num-derive = "0.4"
|
||||
|
@ -18,7 +18,11 @@ impl FrameWalker {
|
||||
fn is_valid(&self) -> bool {
|
||||
let fp_valid = unsafe { BSS_START.as_virt_addr() <= self.current_fp && self.current_fp < BSS_END.as_virt_addr() };
|
||||
let pc_valid = unsafe { TEXT_START.as_virt_addr() <= self.current_pc && self.current_pc < TEXT_END.as_virt_addr() };
|
||||
fp_valid && pc_valid
|
||||
|
||||
// pc might be 0xffff_ffff in the first frame
|
||||
let first = self.current_pc == VirtAddr(usize::MAX);
|
||||
|
||||
fp_valid && (pc_valid || first)
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
|
@ -34,7 +34,7 @@ unsafe extern "C" fn _start(hart_id: usize, fdt_addr: usize) -> ! {
|
||||
ld t0, 0(t0)
|
||||
|
||||
# load and relocate registers
|
||||
lla tp, TSS_START
|
||||
lla tp, TLS_START
|
||||
lla sp, {stack} + {stack_size}
|
||||
add gp, gp, t0
|
||||
add tp, tp, t0
|
||||
@ -72,7 +72,7 @@ unsafe fn pre_main(hart_id: usize, fdt_addr: usize) {
|
||||
|
||||
setup_memory(fdt_addr);
|
||||
setup_kernel_paging();
|
||||
// TODO: on secondary cpu, we should copy existing kernel page table and TSS, then remap TSS
|
||||
// TODO: on secondary cpu, we should copy existing kernel page table and TLS, then remap TLS
|
||||
install_kernel_pagetable();
|
||||
|
||||
// after kernel paging, board level early console is broken (no address mapping)
|
||||
|
@ -22,8 +22,8 @@ extern "C" {
|
||||
pub static BOOT_STACK_END: ExternSymbol;
|
||||
pub static BSS_END: ExternSymbol;
|
||||
|
||||
pub static TSS_START: ExternSymbol;
|
||||
pub static TSS_END: ExternSymbol;
|
||||
pub static TLS_START: ExternSymbol;
|
||||
pub static TLS_END: ExternSymbol;
|
||||
|
||||
pub static TDATA_START: ExternSymbol;
|
||||
pub static TDATA_END: ExternSymbol;
|
||||
@ -33,6 +33,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
pub const PAGE_SIZE: usize = 4 * KIB;
|
||||
pub const PAGE_BITS: usize = PAGE_SIZE.ilog2() as usize;
|
||||
pub const PAGE_LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(PAGE_SIZE, PAGE_SIZE) };
|
||||
|
||||
#[inline(always)]
|
||||
@ -53,6 +54,11 @@ pub fn zero_bss() {
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE:
|
||||
* `kernel_phys_to_virt` and `kernel_virt_to_phys` should only be used when interacting with `ExternSymbol`,
|
||||
* for other cases, use `mmap_phys_to_virt` and `mmap_virt_to_phys` instead.
|
||||
*/
|
||||
|
||||
pub unsafe fn kernel_phys_to_virt(phys: PhysAddr) -> VirtAddr {
|
||||
VirtAddr(phys.as_usize() + KERNEL_OFFSET)
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ SECTIONS {
|
||||
}
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
.tss : AT(ADDR(.tss) - __kernel_offset) {
|
||||
TSS_START = .;
|
||||
.tls : AT(ADDR(.tls) - __kernel_offset) {
|
||||
TLS_START = .;
|
||||
|
||||
. = ALIGN(8);
|
||||
TDATA_START = .;
|
||||
@ -63,9 +63,10 @@ SECTIONS {
|
||||
*(.tbss .tbss.*)
|
||||
TBSS_END = .;
|
||||
|
||||
TSS_END = .;
|
||||
TLS_END = .;
|
||||
}
|
||||
|
||||
. = TLS_END;
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
KERNEL_END = .;
|
||||
|
||||
|
@ -55,8 +55,8 @@ SECTIONS {
|
||||
}
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
.tss : AT(ADDR(.tss) - __kernel_offset) {
|
||||
TSS_START = .;
|
||||
.tls : AT(ADDR(.tls) - __kernel_offset) {
|
||||
TLS_START = .;
|
||||
|
||||
. = ALIGN(8);
|
||||
TDATA_START = .;
|
||||
@ -68,9 +68,10 @@ SECTIONS {
|
||||
*(.tbss .tbss.*)
|
||||
TBSS_END = .;
|
||||
|
||||
TSS_END = .;
|
||||
TLS_END = .;
|
||||
}
|
||||
|
||||
. = TLS_END;
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
KERNEL_END = .;
|
||||
|
||||
|
@ -36,7 +36,10 @@ impl From<PTEFlags> for MapAttr {
|
||||
if flags.contains(PTEFlags::USER_ACCESSIBLE) {
|
||||
attr.insert(Self::USER_ACCESSIBLE);
|
||||
}
|
||||
if flags.contains(PTEFlags::VALID) && !flags.contains(PTEFlags::READABLE | PTEFlags::WRITABLE | PTEFlags::EXECUTABLE)
|
||||
if flags.contains(PTEFlags::VALID)
|
||||
&& !flags.contains(PTEFlags::READABLE)
|
||||
&& !flags.contains(PTEFlags::WRITABLE)
|
||||
&& !flags.contains(PTEFlags::EXECUTABLE)
|
||||
{
|
||||
attr.insert(Self::PAGE_TABLE);
|
||||
}
|
||||
@ -117,6 +120,10 @@ impl EntryOps for Entry {
|
||||
self.0 = (self.0 & !PTEFlags::all().bits()) | flags.bits();
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.0 = 0;
|
||||
}
|
||||
|
||||
fn is_valid(&self) -> bool {
|
||||
self.0 & PTEFlags::VALID.bits() != 0
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{alloc_page, install_pagetable, map_range, RAM_ALLOCATOR};
|
||||
use crate::{arch::layout::*, vspace::*};
|
||||
use crate::{arch::layout::*, objects::*, vspace::*};
|
||||
use log::{debug, info, trace};
|
||||
use spin::Mutex;
|
||||
use utils::{addr::*, size::*};
|
||||
@ -10,8 +10,6 @@ use super::ALLOC_COUNT;
|
||||
#[thread_local]
|
||||
static KERNEL_PAGETABLE: Mutex<Option<Table<Level0>>> = Mutex::new(None);
|
||||
|
||||
pub const KERNEL_PAGETABLE_SIZE: usize = 3;
|
||||
|
||||
pub unsafe fn setup_memory(fdt_addr: usize) {
|
||||
info!("Setting up memory");
|
||||
let fdt = unsafe { fdt::Fdt::from_ptr(fdt_addr as *const u8).unwrap() };
|
||||
@ -101,7 +99,7 @@ pub unsafe fn setup_memory(fdt_addr: usize) {
|
||||
}
|
||||
}
|
||||
|
||||
trace!("Memory setup complete, memory info:\n{:#x?}", mem);
|
||||
trace!("Memory setup complete, memory info:\n{:X?}", mem);
|
||||
}
|
||||
|
||||
pub unsafe fn setup_kernel_paging() {
|
||||
@ -109,7 +107,7 @@ pub unsafe fn setup_kernel_paging() {
|
||||
assert!(!is_kernel_pagetable_allocated(), "Kernel pagetable already allocated");
|
||||
|
||||
let root_pt = alloc_page();
|
||||
let mut kernel_pt = Table::<Level0>::new(root_pt.as_usize().into());
|
||||
let mut kernel_pt = Table::<Level0>::new(mmap_phys_to_virt(root_pt));
|
||||
|
||||
macro_rules! map_section {
|
||||
(($($section:ident),+),$attr:expr) => {
|
||||
@ -117,7 +115,7 @@ pub unsafe fn setup_kernel_paging() {
|
||||
let start = concat_idents!($section, _START).as_virt_addr().align_down(PAGE_SIZE);
|
||||
let end = concat_idents!($section, _END).as_virt_addr().align_up(PAGE_SIZE);
|
||||
debug!("Mapping section {}:\t[{:?}, {:?}]", stringify!($section), start, end);
|
||||
map_range(&mut kernel_pt, start, kernel_virt_to_phys(start), (end - start).as_usize(), $attr);
|
||||
map_range(alloc_page, &mut kernel_pt, start, kernel_virt_to_phys(start), (end - start).as_usize(), $attr);
|
||||
)+
|
||||
};
|
||||
}
|
||||
@ -126,12 +124,13 @@ pub unsafe fn setup_kernel_paging() {
|
||||
map_section!((RODATA), MapAttr::READABLE);
|
||||
map_section!((DATA, BSS), MapAttr::READABLE | MapAttr::WRITABLE);
|
||||
|
||||
// TODO: every core must have a separate TSS section
|
||||
map_section!((TSS), MapAttr::READABLE | MapAttr::WRITABLE);
|
||||
// TODO: every core must have a separate TLS section
|
||||
map_section!((TLS), MapAttr::READABLE | MapAttr::WRITABLE);
|
||||
|
||||
// map 4 GiB physical memory
|
||||
// TODO: walk fdt to get all memory region? put it in driver init
|
||||
map_range(
|
||||
alloc_page,
|
||||
&mut kernel_pt,
|
||||
mmap_phys_to_virt(PhysAddr(0)),
|
||||
PhysAddr(0),
|
||||
@ -143,7 +142,6 @@ pub unsafe fn setup_kernel_paging() {
|
||||
{
|
||||
let count = ALLOC_COUNT.load(core::sync::atomic::Ordering::Acquire);
|
||||
trace!("Kernel page table size: {:?}", count);
|
||||
assert!(KERNEL_PAGETABLE_SIZE == count, "Kernel page table size mismatch");
|
||||
}
|
||||
|
||||
*KERNEL_PAGETABLE.lock() = Some(kernel_pt);
|
||||
@ -152,10 +150,10 @@ pub unsafe fn setup_kernel_paging() {
|
||||
pub unsafe fn install_kernel_pagetable() {
|
||||
info!("Setting up new kernel pagetable");
|
||||
|
||||
let kernel_pt = KERNEL_PAGETABLE.lock();
|
||||
let kernel_pt = kernel_pt.as_ref().expect("No kernel pagetable found");
|
||||
let vaddr = KERNEL_PAGETABLE.lock().as_ref().expect("No kernel pagetable found").vaddr();
|
||||
let paddr = mmap_virt_to_phys(vaddr);
|
||||
|
||||
install_pagetable(kernel_pt)
|
||||
install_pagetable(paddr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -166,5 +164,23 @@ pub fn is_kernel_pagetable_allocated() -> bool {
|
||||
unsafe fn map_kernel(from: VirtAddr, to: PhysAddr, size: usize, attr: MapAttr) {
|
||||
let mut guard = KERNEL_PAGETABLE.lock();
|
||||
let pt = guard.as_mut().unwrap();
|
||||
map_range(pt, from, to, size, attr);
|
||||
map_range(alloc_page, pt, from, to, size, attr);
|
||||
}
|
||||
|
||||
pub fn copy_kernel_pagetable(root: &CapEntry) {
|
||||
let kernel_pt = KERNEL_PAGETABLE.lock();
|
||||
let from = kernel_pt.as_ref().expect("No kernel pagetable found");
|
||||
|
||||
let mut root = TableCap::try_from(root).expect("Invalid vspace cap");
|
||||
let to: Table<Level0> = root.as_object_mut();
|
||||
|
||||
for (i, (from, to)) in from.entries.iter().zip(to.entries.iter_mut()).enumerate() {
|
||||
if !from.is_valid() {
|
||||
to.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
to.set_attr(from.attr());
|
||||
to.set_paddr(from.paddr());
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,10 @@ impl<'a, T: TableLevel> TableOps<'a, T> for Table<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn vaddr(&self) -> VirtAddr {
|
||||
VirtAddr::from(self.entries.as_ptr())
|
||||
}
|
||||
|
||||
fn map(&mut self, from: VirtAddr, to: PhysAddr, attr: MapAttr) -> PageResult {
|
||||
if !from.is_aligned(T::LEVEL_SIZE) || !to.is_aligned(PAGE_SIZE) {
|
||||
return Err(PageError::NotAligned);
|
||||
|
@ -28,7 +28,14 @@ pub fn alloc_page() -> PhysAddr {
|
||||
addr
|
||||
}
|
||||
|
||||
pub fn map_range(pt: &mut Table<Level0>, from: VirtAddr, to: PhysAddr, size: usize, attr: MapAttr) {
|
||||
pub fn map_range(
|
||||
mut alloc: impl FnMut() -> PhysAddr,
|
||||
pt: &mut Table<Level0>,
|
||||
from: VirtAddr,
|
||||
to: PhysAddr,
|
||||
size: usize,
|
||||
attr: MapAttr,
|
||||
) {
|
||||
let mut virt_start = from;
|
||||
let mut phys_start = to;
|
||||
let virt_end = from + size;
|
||||
@ -56,7 +63,7 @@ pub fn map_range(pt: &mut Table<Level0>, from: VirtAddr, to: PhysAddr, size: usi
|
||||
unsafe {
|
||||
Table::<$level>::new(mmap_phys_to_virt(
|
||||
$pt.lookup_mut($addr).map(|e| e.paddr()).unwrap_or_else(|| {
|
||||
let page = alloc_page();
|
||||
let page = alloc();
|
||||
let addr = $addr.align_down(<$level as TableLevel>::PREVIOUS::LEVEL_SIZE);
|
||||
debug!("Creating new pagetable:\t{:?} -> {:?}", addr, page);
|
||||
$pt.map(addr, page, MapAttr::PAGE_TABLE).unwrap();
|
||||
@ -89,9 +96,7 @@ fn page_table_mode() -> riscv::register::satp::Mode {
|
||||
return riscv::register::satp::Mode::Sv57;
|
||||
}
|
||||
|
||||
pub unsafe fn install_pagetable(pt: &Table<Level0>) {
|
||||
let root_pt = PhysAddr::from(pt.entries.as_ptr());
|
||||
|
||||
riscv::register::satp::set(page_table_mode(), 0, root_pt.extract_ppn());
|
||||
pub unsafe fn install_pagetable(addr: PhysAddr) {
|
||||
riscv::register::satp::set(page_table_mode(), 0, addr.extract_ppn());
|
||||
riscv::asm::sfence_vma_all();
|
||||
}
|
||||
|
@ -15,9 +15,9 @@ fn panic(info: &PanicInfo) -> ! {
|
||||
location.file(),
|
||||
location.line(),
|
||||
location.column(),
|
||||
info.message().unwrap(),
|
||||
info.message(),
|
||||
),
|
||||
None => error!("[lang] Panicked: {}", info.message().unwrap()),
|
||||
None => error!("[lang] Panicked: {}", info.message()),
|
||||
}
|
||||
|
||||
unsafe { dump_backtrace() };
|
||||
|
@ -27,6 +27,7 @@ mod lang;
|
||||
mod logging;
|
||||
mod objects;
|
||||
mod plat;
|
||||
mod root;
|
||||
mod scheduler;
|
||||
mod vspace;
|
||||
|
||||
|
@ -75,7 +75,7 @@ impl Debug for CapEntry {
|
||||
ObjectType::CNode => write!(f, "{:?}", CNodeCap::try_from(self)),
|
||||
ObjectType::Frame => write!(f, "{:?}", FrameCap::try_from(self)),
|
||||
ObjectType::Null => write!(f, "{:?}", NullCap::try_from(self)),
|
||||
ObjectType::PageTable => write!(f, "{:?}", TableCap::try_from(self)),
|
||||
ObjectType::Table => write!(f, "{:?}", TableCap::try_from(self)),
|
||||
ObjectType::TCB => write!(f, "{:?}", TcbCap::try_from(self)),
|
||||
ObjectType::Untyped => write!(f, "{:?}", UntypedCap::try_from(self)),
|
||||
_ => write!(f, "UnknownCap"),
|
||||
|
@ -52,10 +52,8 @@ impl<'a> FrameCap<'a> {
|
||||
const VM_RIGHT_MASK: usize = MASK!(Self::VM_RIGHT_BITS);
|
||||
const VM_RIGHT_OFFSET: usize = 0;
|
||||
|
||||
pub fn mint(ptr: PhysAddr, size: usize, attr: MapAttr, is_device: bool) -> RawCap {
|
||||
let size_bits = size.ilog2() as usize;
|
||||
debug_assert!(size_bits <= FrameCap::FRAME_SIZE_BITS);
|
||||
assert!(size >= PAGE_SIZE);
|
||||
pub fn mint(ptr: PhysAddr, size_bits: usize, attr: MapAttr, is_device: bool) -> RawCap {
|
||||
debug_assert!(size_bits <= MASK!(Self::FRAME_SIZE_BITS)); // 1<<63
|
||||
|
||||
let arg0 = 0
|
||||
| ((attr.bits() & Self::VM_RIGHT_MASK) << Self::VM_RIGHT_OFFSET)
|
||||
|
@ -10,7 +10,7 @@ use utils::{addr::*, MASK};
|
||||
/// TableObject is an object that represents a page table
|
||||
pub struct TableObject([u8]);
|
||||
impl KernelObject for TableObject {
|
||||
const OBJ_TYPE: ObjectType = ObjectType::PageTable;
|
||||
const OBJ_TYPE: ObjectType = ObjectType::Table;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -40,7 +40,7 @@ impl<'a> TableCap<'a> {
|
||||
const IS_MAPPED_OFFSET: usize = 0;
|
||||
|
||||
pub fn mint(ptr: PhysAddr) -> RawCap {
|
||||
RawCap::new(0, 0, ptr, ObjectType::PageTable)
|
||||
RawCap::new(0, 0, ptr, ObjectType::Table)
|
||||
}
|
||||
|
||||
pub fn is_mapped(&self) -> bool {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use super::cap::RawCap;
|
||||
use super::cnode::{CNodeCap, CNodeObject};
|
||||
use super::null::NullCap;
|
||||
use super::{Cap, KernelObject};
|
||||
use super::{Cap, FrameCap, KernelObject, TableCap, TcbCap};
|
||||
use crate::vspace::MapAttr;
|
||||
use core::fmt::Debug;
|
||||
use uapi::cap::ObjectType;
|
||||
use uapi::error::{SysError, SysResult};
|
||||
@ -54,7 +55,7 @@ impl UntypedCap<'_> {
|
||||
});
|
||||
}
|
||||
|
||||
fn is_device(&self) -> bool {
|
||||
pub fn is_device(&self) -> bool {
|
||||
(self.cte.cap.get().args[1] >> 6) & 1 == 1
|
||||
}
|
||||
|
||||
@ -107,7 +108,6 @@ impl UntypedCap<'_> {
|
||||
|
||||
// Check whether we are handling device memory
|
||||
if self.is_device() && obj_type != ObjectType::Frame && obj_type != ObjectType::Untyped {
|
||||
// TODO: we might split frame into tera, giga, mega, kilo...
|
||||
return Err(SysError::InvalidArgument);
|
||||
}
|
||||
|
||||
@ -117,6 +117,9 @@ impl UntypedCap<'_> {
|
||||
let new_cap = match obj_type {
|
||||
ObjectType::Untyped => UntypedCap::mint(0, obj_type.bits(user_obj_bits), self.is_device(), addr),
|
||||
ObjectType::CNode => CNodeCap::mint(user_obj_bits, 0, 0, addr),
|
||||
ObjectType::TCB => TcbCap::mint(addr),
|
||||
ObjectType::Table => TableCap::mint(addr),
|
||||
ObjectType::Frame => FrameCap::mint(addr, user_obj_bits, MapAttr::empty(), self.is_device()),
|
||||
// TODO: other object types
|
||||
_ => return Err(SysError::InvalidArgument),
|
||||
};
|
||||
|
359
kernel/src/root.rs
Normal file
359
kernel/src/root.rs
Normal file
@ -0,0 +1,359 @@
|
||||
use crate::arch::layout::{mmap_phys_to_virt, mmap_virt_to_phys, PAGE_BITS, PAGE_SIZE};
|
||||
use crate::arch::vspace::{copy_kernel_pagetable, map_range, RAM_ALLOCATOR};
|
||||
use crate::objects::*;
|
||||
use crate::vspace::*;
|
||||
use core::{cmp::min, ops::Range};
|
||||
use elf::{abi::*, endian::AnyEndian, ElfBytes};
|
||||
use fdt::Fdt;
|
||||
use log::{debug, trace};
|
||||
use spin::Lazy;
|
||||
use uapi::{cspace::CNodeSlot, error::SysError};
|
||||
use utils::{addr::*, bin::prev_power_of_two};
|
||||
|
||||
const ROOT_CNODE_SIZE: usize = 128;
|
||||
static mut ROOT_CNODE: Lazy<[CapEntry; ROOT_CNODE_SIZE]> =
|
||||
Lazy::new(|| core::array::from_fn(|i| CapEntry::new(NullCap::mint())));
|
||||
|
||||
pub fn setup_root_server(fdt: &Fdt) {
|
||||
// Root Server is using statically allocated ROOT_CNODE
|
||||
|
||||
// 1. Setup CNodeCap -> self reference
|
||||
let cnode_entry = {
|
||||
let radix_bits = ROOT_CNODE_SIZE.ilog2() as usize;
|
||||
let guard_bits = 0;
|
||||
let cap_guard = 0;
|
||||
let ptr = unsafe { mmap_virt_to_phys(VirtAddr::from(ROOT_CNODE.as_ptr())) };
|
||||
let cap = CNodeCap::mint(radix_bits, guard_bits, cap_guard, ptr);
|
||||
CapEntry::new(cap)
|
||||
};
|
||||
let mut cnode = CNodeCap::try_from(&cnode_entry).unwrap();
|
||||
let cnode_obj = cnode.as_object_mut();
|
||||
cnode_obj[CNodeSlot::CNodeCap as usize] = cnode_entry.clone();
|
||||
|
||||
// 2. insert current free memory [CNodeSlot::UntypedCap, memory_idx)
|
||||
let memory_idx = create_untyped_memory(cnode_obj);
|
||||
|
||||
// 3. insert device memory [memory_idx, device_idx)
|
||||
let device_idx = create_untyped_device(cnode_obj, memory_idx, fdt);
|
||||
|
||||
// 4. create objects
|
||||
create_objects(cnode_obj, device_idx);
|
||||
|
||||
// 5. load root server
|
||||
let root_server_idx = load_root_server(cnode_obj, device_idx, fdt);
|
||||
|
||||
// 6. map other memory (fdt, initrd)
|
||||
|
||||
// 7. setup threads
|
||||
}
|
||||
|
||||
fn create_untyped_memory(cnode_obj: &mut CNodeObject) -> usize {
|
||||
let mut memory_idx = CNodeSlot::UntypedCap as usize;
|
||||
let mut ram = RAM_ALLOCATOR.lock();
|
||||
ram.blocks_mut()
|
||||
.iter_mut()
|
||||
.filter(|b| b.is_some())
|
||||
.map(|b| b.take().unwrap())
|
||||
.for_each(|b| {
|
||||
let start = {
|
||||
let start = b.start_addr();
|
||||
let aligned = start.align_up(PAGE_SIZE);
|
||||
|
||||
if aligned != start {
|
||||
debug!("[root] wasting memory: {:#x?} -> {:#x?}", start, aligned);
|
||||
}
|
||||
|
||||
aligned
|
||||
};
|
||||
|
||||
let bits = {
|
||||
let size = b.size();
|
||||
let aligned = align_down(size, PAGE_SIZE);
|
||||
|
||||
if aligned != size {
|
||||
debug!("[root] wasting memory: {:#x?} -> {:#x?}", start + aligned, start + size);
|
||||
}
|
||||
|
||||
if aligned != 0 {
|
||||
aligned.ilog2() as usize
|
||||
} else {
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
if bits == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
trace!(
|
||||
"[root] creating untyped memory: {}: {:?} -> {:?}, slot #{}",
|
||||
memory_idx,
|
||||
start,
|
||||
start + (1 << bits),
|
||||
memory_idx
|
||||
);
|
||||
|
||||
let cap = UntypedCap::mint(0, bits, false, start);
|
||||
let cap_entry = CapEntry::new(cap);
|
||||
cnode_obj[memory_idx] = cap_entry;
|
||||
memory_idx += 1;
|
||||
});
|
||||
|
||||
assert!(ram.blocks().iter().all(|b| b.is_none()));
|
||||
|
||||
memory_idx
|
||||
}
|
||||
|
||||
fn create_untyped_device(cnode_obj: &mut CNodeObject, memory_idx: usize, fdt: &Fdt) -> usize {
|
||||
let mut device_idx = memory_idx;
|
||||
let memory = fdt.memory();
|
||||
|
||||
fdt.all_nodes().filter_map(|n| n.reg()).for_each(|r| {
|
||||
r.filter(|r| r.size.is_some_and(|s| s > 0))
|
||||
.filter(|r| {
|
||||
memory.regions().all(|m| {
|
||||
let m_start = m.starting_address as usize;
|
||||
let m_end = m_start + m.size.unwrap();
|
||||
let r_start = r.starting_address as usize;
|
||||
let r_end = r_start + r.size.unwrap();
|
||||
r_end <= m_start || m_end <= r_start
|
||||
})
|
||||
})
|
||||
.for_each(|region| {
|
||||
let start = PhysAddr::from(region.starting_address);
|
||||
let size = region.size.unwrap();
|
||||
let bits = size.next_power_of_two().ilog2() as usize;
|
||||
|
||||
if (1 << bits) > size {
|
||||
debug!(
|
||||
"[root] allocating more device memory: {:#x} -> {:#x}",
|
||||
start + size,
|
||||
start + (1 << bits)
|
||||
);
|
||||
}
|
||||
|
||||
trace!(
|
||||
"[root] creating untyped device: {}: {:?} -> {:?}, slot #{}",
|
||||
device_idx,
|
||||
start,
|
||||
start + (1 << bits),
|
||||
device_idx
|
||||
);
|
||||
|
||||
let cap = UntypedCap::mint(0, bits, true, start);
|
||||
let cap_entry = CapEntry::new(cap);
|
||||
cnode_obj[device_idx] = cap_entry;
|
||||
device_idx += 1;
|
||||
})
|
||||
});
|
||||
|
||||
device_idx
|
||||
}
|
||||
|
||||
fn alloc_objects<T: KernelObject + ?Sized>(
|
||||
cnode_obj: &mut CNodeObject,
|
||||
end_idx: usize,
|
||||
user_obj_bits: usize,
|
||||
range: Range<usize>,
|
||||
) {
|
||||
let untyped_start = CNodeSlot::UntypedCap as usize;
|
||||
|
||||
let (memory, slots) = {
|
||||
let (prologue, remain) = cnode_obj.split_at_mut(untyped_start);
|
||||
let (memory, epilogue) = remain.split_at_mut(end_idx - untyped_start);
|
||||
|
||||
match range {
|
||||
r if r.end <= untyped_start => (memory, &mut prologue[r]),
|
||||
r if r.start >= end_idx => (memory, &mut epilogue[(r.start - end_idx)..(r.end - end_idx)]),
|
||||
_ => panic!("init: slot range overlaps with untyped memory"),
|
||||
}
|
||||
};
|
||||
|
||||
for untyped in memory {
|
||||
let mut untyped = UntypedCap::try_from(&*untyped).expect("init: untyped cap is invalid");
|
||||
|
||||
if untyped.is_device() {
|
||||
// all non-device memory are placed before device memory
|
||||
break;
|
||||
}
|
||||
|
||||
match untyped.retype(T::OBJ_TYPE, user_obj_bits, slots) {
|
||||
Ok(()) => return,
|
||||
Err(SysError::RangeError) => continue,
|
||||
_ => panic!("init: retype failed"),
|
||||
}
|
||||
}
|
||||
|
||||
panic!("init: untyped memory is exhausted");
|
||||
}
|
||||
|
||||
fn create_objects(cnode_obj: &mut CNodeObject, end_idx: usize) {
|
||||
// tcb
|
||||
{
|
||||
let tcb_idx = CNodeSlot::TcbCap as usize;
|
||||
trace!("[root] allocating tcb object at slot #{}", tcb_idx);
|
||||
alloc_objects::<TcbObject>(cnode_obj, end_idx, 0, tcb_idx..tcb_idx + 1);
|
||||
}
|
||||
|
||||
// vspace
|
||||
{
|
||||
// root
|
||||
let vspace_idx = CNodeSlot::VSpaceCap as usize;
|
||||
trace!("[root] allocating vspace object at slot #{}", vspace_idx);
|
||||
alloc_objects::<TableObject>(cnode_obj, end_idx, PAGE_BITS, vspace_idx..vspace_idx + 1);
|
||||
|
||||
// copy pagetable
|
||||
let root = &cnode_obj[vspace_idx];
|
||||
copy_kernel_pagetable(root);
|
||||
}
|
||||
|
||||
// bootinfo
|
||||
{
|
||||
let bootinfo_idx = CNodeSlot::BootInfoFrameCap as usize;
|
||||
trace!("[root] allocating bootinfo object at slot #{}", bootinfo_idx);
|
||||
alloc_objects::<FrameObject>(cnode_obj, end_idx, PAGE_BITS, bootinfo_idx..bootinfo_idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> usize {
|
||||
let table: Table<Level0> = TableCap::try_from(&cnode_obj[CNodeSlot::VSpaceCap as usize])
|
||||
.unwrap()
|
||||
.as_object_mut();
|
||||
|
||||
let mut rootfs = unsafe {
|
||||
let chosen = fdt.find_node("/chosen").expect("/chosen is required");
|
||||
|
||||
let initrd_start = chosen
|
||||
.properties()
|
||||
.find(|n| n.name == "linux,initrd-start")
|
||||
.expect("linux,initrd-start is required")
|
||||
.as_usize()
|
||||
.unwrap();
|
||||
|
||||
let initrd_end = chosen
|
||||
.properties()
|
||||
.find(|n| n.name == "linux,initrd-end")
|
||||
.expect("linux,initrd-end is required")
|
||||
.as_usize()
|
||||
.unwrap();
|
||||
|
||||
let vaddr = mmap_phys_to_virt(PhysAddr(initrd_start));
|
||||
let len = initrd_end - initrd_start;
|
||||
|
||||
let data = core::slice::from_raw_parts(vaddr.as_const_ptr(), len);
|
||||
cpio::Reader::new(data)
|
||||
};
|
||||
|
||||
let root_entry = rootfs
|
||||
.find_map(|entry| {
|
||||
if let Ok(entry) = entry {
|
||||
if entry.filename().unwrap_or_default() == "root" {
|
||||
return Some(entry);
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.expect("init: root server not found");
|
||||
|
||||
let root_start = VirtAddr::from(root_entry.data().as_ptr());
|
||||
let root_elf = ElfBytes::<AnyEndian>::minimal_parse(root_entry.data()).expect("init: invalid root server");
|
||||
|
||||
let mut nxt_slot = end_idx;
|
||||
root_elf
|
||||
.segments()
|
||||
.expect("init: root server has no segments")
|
||||
.iter()
|
||||
.filter(|phdr| phdr.p_type == PT_LOAD)
|
||||
.filter(|phdr| phdr.p_memsz > 0)
|
||||
.for_each(|phdr| {
|
||||
debug!(
|
||||
"[initrd] loading segment:\t[{:#x?}, {:#x?}]",
|
||||
phdr.p_vaddr,
|
||||
phdr.p_vaddr + phdr.p_memsz
|
||||
);
|
||||
|
||||
let seg_start = root_start + phdr.p_offset as usize;
|
||||
let seg_addr = VirtAddr::from(phdr.p_vaddr);
|
||||
|
||||
// Currently, we only support loading segments that are aligned to PAGE_SIZE
|
||||
assert!(seg_addr.is_aligned(PAGE_SIZE), "p_vaddr must be aligned");
|
||||
assert!(phdr.p_align as usize == PAGE_SIZE, "p_align must be aligned");
|
||||
assert!(is_aligned(phdr.p_memsz as usize, PAGE_SIZE), "p_memsz must be aligned");
|
||||
debug_assert!(phdr.p_filesz <= phdr.p_memsz, "invalid ELF segment");
|
||||
|
||||
let copy = |offset: usize, dest: &mut [u8]| {
|
||||
if offset > phdr.p_filesz as usize {
|
||||
dest.fill(0);
|
||||
} else {
|
||||
let len = min(phdr.p_filesz as usize - offset, dest.len());
|
||||
let src = &root_entry.data()[offset..offset + len];
|
||||
dest[..len].copy_from_slice(src);
|
||||
dest[len..].fill(0);
|
||||
}
|
||||
};
|
||||
|
||||
// allocate frames
|
||||
let mut cur = 0;
|
||||
while cur < phdr.p_memsz as usize {
|
||||
let remain = phdr.p_memsz as usize - cur;
|
||||
|
||||
// calculate block size
|
||||
let block_size = prev_power_of_two(remain as u64) as usize;
|
||||
let block_bits = block_size.ilog2() as usize;
|
||||
debug_assert!(block_size >= PAGE_SIZE);
|
||||
|
||||
// allocate frame
|
||||
trace!("[initrd] allocating frame at slot #{}", nxt_slot);
|
||||
alloc_objects::<FrameObject>(cnode_obj, end_idx, block_bits, nxt_slot..nxt_slot + 1);
|
||||
nxt_slot += 1;
|
||||
|
||||
// copy data
|
||||
let mut frame = FrameCap::try_from(&cnode_obj[nxt_slot - 1]).unwrap();
|
||||
let mem = frame.as_object_mut();
|
||||
copy(cur, mem);
|
||||
|
||||
// map frame to vspace
|
||||
let root = &cnode_obj[CNodeSlot::VSpaceCap as usize];
|
||||
let root_vaddr = TableCap::try_from(root).unwrap().as_object::<Level0>().vaddr();
|
||||
let mut root = unsafe { Table::new(root_vaddr) }; // use unsafe to workaround borrow checker
|
||||
|
||||
let vaddr = seg_addr + cur;
|
||||
let paddr = unsafe { mmap_virt_to_phys(VirtAddr::from(mem as *const _ as *const u8)) };
|
||||
let attr = {
|
||||
let mut attr = MapAttr::USER_ACCESSIBLE;
|
||||
|
||||
if phdr.p_flags & PF_X != 0 {
|
||||
attr |= MapAttr::EXECUTABLE;
|
||||
}
|
||||
if phdr.p_flags & PF_W != 0 {
|
||||
attr |= MapAttr::WRITABLE;
|
||||
}
|
||||
if phdr.p_flags & PF_R != 0 {
|
||||
attr |= MapAttr::READABLE;
|
||||
}
|
||||
|
||||
attr
|
||||
};
|
||||
|
||||
let alloc_page = || {
|
||||
trace!("[initrd] allocating pagetable at slot #{}", nxt_slot);
|
||||
|
||||
alloc_objects::<TableObject>(cnode_obj, end_idx, PAGE_BITS, nxt_slot..nxt_slot + 1);
|
||||
nxt_slot += 1;
|
||||
|
||||
let page = &cnode_obj[nxt_slot - 1];
|
||||
let page = TableCap::try_from(page).unwrap();
|
||||
let table: Table<Level0> = page.as_object(); // Any level is fine
|
||||
|
||||
unsafe { mmap_virt_to_phys(table.vaddr()) }
|
||||
};
|
||||
|
||||
map_range(alloc_page, &mut root, vaddr, paddr, block_size, attr);
|
||||
|
||||
// update pointer
|
||||
cur += block_size;
|
||||
}
|
||||
});
|
||||
|
||||
nxt_slot
|
||||
}
|
@ -23,6 +23,7 @@ pub trait EntryOps: Clone + Copy + Debug {
|
||||
|
||||
fn set_paddr(&mut self, addr: PhysAddr);
|
||||
fn set_attr(&mut self, attr: MapAttr);
|
||||
fn clear(&mut self);
|
||||
|
||||
fn is_valid(&self) -> bool;
|
||||
fn is_leaf(&self) -> bool;
|
||||
|
@ -5,6 +5,7 @@ pub trait TableOps<'a, T: TableLevel> {
|
||||
/// # Safety
|
||||
/// `location` must be a page-aligned virtual address and will not be dropped.
|
||||
unsafe fn new(location: VirtAddr) -> Self;
|
||||
fn vaddr(&self) -> VirtAddr;
|
||||
|
||||
// following methods only works at current level
|
||||
|
||||
|
@ -423,3 +423,19 @@ impl Step for VirtAddr {
|
||||
start.as_usize().checked_sub(count).map(VirtAddr)
|
||||
}
|
||||
}
|
||||
|
||||
impl PhysAddr {
|
||||
/// # Safety
|
||||
/// Only provided for the sake of completeness. Use `{mmap, kernel}_phys_to_virt` instead.
|
||||
pub unsafe fn to_virt_addr(&self) -> VirtAddr {
|
||||
VirtAddr(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtAddr {
|
||||
/// # Safety
|
||||
/// Only provided for the sake of completeness. Use `{mmap, kernel}_virt_to_phys` instead.
|
||||
pub unsafe fn to_phys_addr(&self) -> PhysAddr {
|
||||
PhysAddr(self.0)
|
||||
}
|
||||
}
|
||||
|
@ -4,3 +4,9 @@ macro_rules! MASK {
|
||||
((1 << $bits) - 1)
|
||||
};
|
||||
}
|
||||
|
||||
pub const fn prev_power_of_two(n: u64) -> u64 {
|
||||
// Taken from https://internals.rust-lang.org/t/add-prev-power-of-two/14281
|
||||
let bit = 63 - (n | 1).leading_zeros();
|
||||
(1 << bit) & n
|
||||
}
|
||||
|
17
tools/parse_backtrace.sh
Executable file
17
tools/parse_backtrace.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: $0 <ELF_FILE>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ELF_FILE=$1
|
||||
|
||||
while IFS= read -r line; do
|
||||
if [[ $line =~ PC:\ VirtAddr\((0x[0-9a-fA-F]+)\) ]]; then
|
||||
addr=${BASH_REMATCH[1]}
|
||||
func=$(addr2line -Cfpe "$ELF_FILE" "$addr")
|
||||
line+=" $func"
|
||||
fi
|
||||
echo "$line"
|
||||
done
|
@ -7,7 +7,7 @@ pub enum ObjectType {
|
||||
Reply = 4,
|
||||
Notification = 5,
|
||||
Frame = 6,
|
||||
PageTable = 7,
|
||||
Table = 7,
|
||||
Interrupt = 8,
|
||||
Untyped = 9,
|
||||
}
|
||||
@ -36,7 +36,7 @@ impl ObjectType {
|
||||
ObjectType::Reply => 0, // TODO: fill it!
|
||||
ObjectType::Notification => 0, // TODO: fill it!
|
||||
ObjectType::Frame => user_obj_bits,
|
||||
ObjectType::PageTable => user_obj_bits, // arch dependent page table size
|
||||
ObjectType::Table => user_obj_bits, // arch dependent page table size
|
||||
ObjectType::Interrupt => 0, // TODO: fill it!
|
||||
ObjectType::Untyped => user_obj_bits,
|
||||
}
|
||||
|
10
uapi/src/cspace.rs
Normal file
10
uapi/src/cspace.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
|
||||
pub enum CNodeSlot {
|
||||
NullCap = 0,
|
||||
TcbCap,
|
||||
CNodeCap,
|
||||
VSpaceCap,
|
||||
BootInfoFrameCap,
|
||||
UntypedCap,
|
||||
// IrqControlCap
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
extern crate num_derive;
|
||||
|
||||
pub mod cap;
|
||||
pub mod cspace;
|
||||
pub mod error;
|
||||
pub mod fault;
|
||||
pub mod syscall;
|
||||
|
Loading…
Reference in New Issue
Block a user