Replaced start.c

feat/start
hheik 2024-05-02 23:20:48 +03:00
parent cf55a8faa1
commit 9eba9bb925
5 changed files with 73 additions and 88 deletions

View File

@ -3,7 +3,6 @@ U=user
OBJS = \
$K/entry.o \
$K/start.o \
$K/console.o \
$K/printf.o \
$K/kalloc.o \

View File

@ -1,45 +0,0 @@
#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "defs.h"
void timerinit();
// a scratch area per CPU for machine-mode timer interrupts.
uint64 timer_scratch[NCPU][5];
// assembly code in kernelvec.S for machine-mode timer interrupt.
extern void timervec();
// arrange to receive timer interrupts.
// they will arrive in machine mode at
// at timervec in kernelvec.S,
// which turns them into software interrupts for
// devintr() in trap.c.
void timerinit() {
// each CPU has a separate source of timer interrupts.
int id = r_mhartid();
// ask the CLINT for a timer interrupt.
int interval = 1000000; // cycles; about 1/10th second in qemu.
*(uint64 *)CLINT_MTIMECMP(id) = *(uint64 *)CLINT_MTIME + interval;
// prepare information in scratch[] for timervec.
// scratch[0..2] : space for timervec to save registers.
// scratch[3] : address of CLINT MTIMECMP register.
// scratch[4] : desired interval (in cycles) between timer interrupts.
uint64 *scratch = &timer_scratch[id][0];
scratch[3] = CLINT_MTIMECMP(id);
scratch[4] = interval;
w_mscratch((uint64)scratch);
// set the machine-mode trap handler.
w_mtvec((uint64)timervec);
// enable machine-mode interrupts.
w_mstatus(r_mstatus() | MSTATUS_MIE);
// enable machine-mode timer interrupts.
w_mie(r_mie() | MIE_MTIE);
}

View File

@ -28,13 +28,12 @@ pub const VIRTIO0: i32 = 0x10001000;
pub const VIRTIO0_IRQ: i32 = 1;
// core local interruptor (CLINT), which contains the timer.
pub const CLINT: i64 = 0x2000000;
// const CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8 * (hartid));
pub const CLINT: u64 = 0x2000000;
#[inline]
pub fn CLINT_MTIMECMP(hartid: i32) -> i64 {
CLINT + 0x4000 + 8 * hartid as i64
pub fn CLINT_MTIMECMP(hartid: u64) -> *mut u64 {
(CLINT + 0x4000 + 8 * hartid) as *mut u64
}
pub const CLINT_MTIME: i64 = CLINT + 0xBFF8; // cycles since boot.
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;

View File

@ -93,16 +93,21 @@ pub unsafe fn w_sie(x: u64) {
}
// // Machine-mode Interrupt Enable
// #define MIE_MEIE (1L << 11) // external
// #define MIE_MTIE (1L << 7) // timer
// #define MIE_MSIE (1L << 3) // software
// static inline uint64 r_mie() {
// uint64 x;
// asm volatile("csrr %0, mie" : "=r"(x));
// return x;
// }
pub const MIE_MEIE: u64 = 1 << 11; // external
pub const MIE_MTIE: u64 = 1 << 7; // timer
pub const MIE_MSIE: u64 = 1 << 3; // software
// static inline void w_mie(uint64 x) { asm volatile("csrw mie, %0" : : "r"(x)); }
#[inline]
pub unsafe fn r_mie() -> u64 {
let x: u64;
asm!("csrr {x}, mie", x = out(reg) x);
x
}
#[inline]
pub unsafe fn w_mie(x: u64) {
asm!("csrw mie, {x}", x = in(reg) x);
}
// // supervisor exception program counter, holds the
// // instruction address to which a return from
@ -124,9 +129,6 @@ pub unsafe fn w_sie(x: u64) {
// return x;
// }
// static inline void w_medeleg(uint64 x) {
// asm volatile("csrw medeleg, %0" : : "r"(x));
// }
#[inline]
pub unsafe fn w_medeleg(x: u64) {
asm!("csrw medeleg, {x}", x = in(reg) x);
@ -139,9 +141,6 @@ pub unsafe fn w_medeleg(x: u64) {
// return x;
// }
// static inline void w_mideleg(uint64 x) {
// asm volatile("csrw mideleg, %0" : : "r"(x));
// }
#[inline]
pub unsafe fn w_mideleg(x: u64) {
asm!("csrw mideleg, {x}", x = in(reg) x);
@ -160,22 +159,17 @@ pub unsafe fn w_mideleg(x: u64) {
// }
// // Machine-mode interrupt vector
// static inline void w_mtvec(uint64 x) {
// asm volatile("csrw mtvec, %0" : : "r"(x));
// }
#[inline]
pub unsafe fn w_mtvec(x: u64) {
asm!("csrw mtvec, {x}", x = in(reg) x);
}
// // Physical Memory Protection
// static inline void w_pmpcfg0(uint64 x) {
// asm volatile("csrw pmpcfg0, %0" : : "r"(x));
// }
// Physical Memory Protection
#[inline]
pub unsafe fn w_pmpcfg0(x: u64) {
asm!("csrw pmpcfg0, {x}", x = in(reg) x);
}
// static inline void w_pmpaddr0(uint64 x) {
// asm volatile("csrw pmpaddr0, %0" : : "r"(x));
// }
#[inline]
pub unsafe fn w_pmpaddr0(x: u64) {
asm!("csrw pmpaddr0, {x}", x = in(reg) x);
@ -186,11 +180,8 @@ pub unsafe fn w_pmpaddr0(x: u64) {
// #define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)pagetable) >> 12))
// // supervisor address translation and protection;
// // holds the address of the page table.
// static inline void w_satp(uint64 x) {
// asm volatile("csrw satp, %0" : : "r"(x));
// }
// supervisor address translation and protection;
// holds the address of the page table.
#[inline]
pub unsafe fn w_satp(x: u64) {
asm!("csrw satp, {x}", x = in(reg) x);
@ -202,9 +193,10 @@ pub unsafe fn w_satp(x: u64) {
// return x;
// }
// static inline void w_mscratch(uint64 x) {
// asm volatile("csrw mscratch, %0" : : "r"(x));
// }
#[inline]
pub unsafe fn w_mscratch(x: u64) {
asm!("csrw mscratch, {x}", x = in(reg) x);
}
// // Supervisor Trap Cause
// static inline uint64 r_scause() {

View File

@ -1,20 +1,27 @@
use core::arch::asm;
use core::usize;
use crate::memlayout::{CLINT_MTIME, CLINT_MTIMECMP};
use crate::param::NCPU;
use crate::riscv as rv;
extern "C" {
// start.c
fn timerinit();
// assembly code in kernelvec.S for machine-mode timer interrupt.
fn timervec();
// main.c
fn main();
}
#[repr(align(16))]
pub struct AlignedStack([u8; 4096 * NCPU]);
pub struct EntryStack([u8; 4096 * NCPU]);
// entry.S needs one stack per CPU.
#[no_mangle]
pub static mut stack0: AlignedStack = AlignedStack([0; 4096 * NCPU]);
pub static mut stack0: EntryStack = EntryStack([0; 4096 * NCPU]);
// a scratch area per CPU for machine-mode timer interrupts.
static mut timer_scratch: [[u64; 5]; NCPU] = [[0; 5]; NCPU];
// entry.S jumps here in machine mode on stack0.
#[no_mangle]
@ -52,3 +59,36 @@ pub unsafe extern "C" fn start() {
// switch to supervisor mode and jump to main().
asm!("mret");
}
// arrange to receive timer interrupts.
// they will arrive in machine mode at
// at timervec in kernelvec.S,
// which turns them into software interrupts for
// devintr() in trap.c.
unsafe fn timerinit() {
// each CPU has a separate source of timer interrupts.
let id = rv::r_mhartid();
// ask the CLINT for a timer interrupt.
let interval: u64 = 1000000; // cycles; about 1/10th second in qemu.
*CLINT_MTIMECMP(id) = *CLINT_MTIME + interval;
// prepare information in scratch[] for timervec.
// scratch[0..2] : space for timervec to save registers.
// scratch[3] : address of CLINT MTIMECMP register.
// scratch[4] : desired interval (in cycles) between timer interrupts.
timer_scratch[id as usize][3] = CLINT_MTIMECMP(id) as u64;
timer_scratch[id as usize][4] = interval;
// w_mscratch((uint64)scratch);
rv::w_mscratch(timer_scratch[id as usize].as_ptr() as u64);
// set the machine-mode trap handler.
rv::w_mtvec(timervec as *const () as u64);
// enable machine-mode interrupts.
rv::w_mstatus(rv::r_mstatus() | rv::MSTATUS_MIE);
// enable machine-mode timer interrupts.
rv::w_mie(rv::r_mie() | rv::MIE_MTIE);
}