use crate::riscv::{MAXVA, PGSIZE}; // Physical memory layout // qemu -machine virt is set up like this, // based on qemu's hw/riscv/virt.c: // // 00001000 -- boot ROM, provided by qemu // 02000000 -- CLINT // 0C000000 -- PLIC // 10000000 -- uart0 // 10001000 -- virtio disk // 80000000 -- boot ROM jumps here in machine mode // -kernel loads the kernel here // unused RAM after 80000000. // the kernel uses physical memory thus: // 80000000 -- entry.S, then kernel text and data // end -- start of kernel page allocation area // PHYSTOP -- end RAM used by the kernel // qemu puts UART registers here in physical memory. pub const UART0: u64 = 0x10000000; pub const UART0_IRQ: i32 = 10; // virtio mmio interface pub const VIRTIO0: i32 = 0x10001000; pub const VIRTIO0_IRQ: i32 = 1; // core local interruptor (CLINT), which contains the timer. pub const CLINT: u64 = 0x2000000; #[inline] pub fn CLINT_MTIMECMP(hartid: u64) -> *mut u64 { (CLINT + 0x4000 + 8 * hartid) as *mut u64 } pub const CLINT_MTIME: *mut u64 = (CLINT + 0xBFF8) as *mut u64; // cycles since boot. // qemu puts platform-level interrupt controller (PLIC) here. pub const PLIC: i64 = 0x0c000000; pub const PLIC_PRIORITY: i64 = PLIC + 0x0; pub const PLIC_PENDING: i64 = PLIC + 0x1000; #[inline] pub fn PLIC_MENABLE(hart: i32) -> i64 { PLIC + 0x2000 + hart as i64 * 0x100 } #[inline] pub fn PLIC_SENABLE(hart: i32) -> i64 { PLIC + 0x2080 + hart as i64 * 0x100 } #[inline] pub fn PLIC_MPRIORITY(hart: i32) -> i64 { PLIC + 0x200000 + hart as i64 * 0x2000 } #[inline] pub fn PLIC_SPRIORITY(hart: i32) -> i64 { PLIC + 0x201000 + hart as i64 * 0x2000 } #[inline] pub fn PLIC_MCLAIM(hart: i32) -> i64 { PLIC + 0x200004 + hart as i64 * 0x2000 } #[inline] pub fn PLIC_SCLAIM(hart: i32) -> i64 { PLIC + 0x201004 + hart as i64 * 0x2000 } // the kernel expects there to be RAM // for use by the kernel and user pages // from physical address 0x80000000 to PHYSTOP. pub const KERNBASE: i64 = 0x80000000; pub const PHYSTOP: i64 = KERNBASE + 128 * 1024 * 1024; // map the trampoline page to the highest address, // in both user and kernel space. pub const TRAMPOLINE: u64 = MAXVA - PGSIZE; // map kernel stacks beneath the trampoline, // each surrounded by invalid guard pages. #[inline] pub fn KSTACK(p: i32) -> u64 { TRAMPOLINE - (p as u64 + 1) * 2 * PGSIZE } // User memory layout. // Address zero first: // text // original data and bss // fixed-size stack // expandable heap // ... // TRAPFRAME (p->trapframe, used by the trampoline) // TRAMPOLINE (the same page as in the kernel) pub const TRAPFRAME: u64 = TRAMPOLINE - PGSIZE;