94 lines
2.6 KiB
Rust
94 lines
2.6 KiB
Rust
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;
|