xv6-riscv-rust/theseus/src/memlayout.rs

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;