diff --git a/crate/bcm2837/Cargo.toml b/crate/bcm2837/Cargo.toml index 3fb3e2e..456ee0e 100644 --- a/crate/bcm2837/Cargo.toml +++ b/crate/bcm2837/Cargo.toml @@ -2,10 +2,11 @@ name = "bcm2837" version = "0.1.0" authors = ["equation314 "] +edition = "2018" [features] -use_generic_timer = [] +use_generic_timer = ["aarch64"] [dependencies] volatile = "0.2.4" -cortex-a = "2.2.2" +aarch64= { git = "https://github.com/equation314/aarch64", optional = true } diff --git a/crate/bcm2837/src/gpio.rs b/crate/bcm2837/src/gpio.rs index 1fb7fec..ef258d6 100644 --- a/crate/bcm2837/src/gpio.rs +++ b/crate/bcm2837/src/gpio.rs @@ -1,5 +1,5 @@ -use IO_BASE; -use timer::delay; +use crate::IO_BASE; +use crate::timer::delay; use core::marker::PhantomData; use volatile::{ReadOnly, Volatile, WriteOnly}; diff --git a/crate/bcm2837/src/interrupt.rs b/crate/bcm2837/src/interrupt.rs index 7324085..03657c9 100644 --- a/crate/bcm2837/src/interrupt.rs +++ b/crate/bcm2837/src/interrupt.rs @@ -1,9 +1,10 @@ -use IO_BASE; +use crate::IO_BASE; use volatile::{ReadOnly, Volatile}; const INT_BASE: usize = IO_BASE + 0xB000 + 0x200; /// Allowed interrupts (ref: peripherals 7.5, page 113) +#[repr(u8)] #[derive(Copy, Clone, PartialEq, Debug)] pub enum Interrupt { Timer1 = 1, @@ -30,6 +31,24 @@ struct Registers { DisableBasicIRQ: Volatile, } +/// Pending interrupts +pub struct PendingInterrupts(u64); + +impl Iterator for PendingInterrupts { + type Item = usize; + + #[inline] + fn next(&mut self) -> Option { + let int = self.0.trailing_zeros(); + if int < 64 { + self.0 &= !(1 << int); + Some(int as usize) + } else { + None + } + } +} + /// An interrupt controller. Used to enable and disable interrupts as well as to /// check if an interrupt is pending. pub struct Controller { @@ -38,6 +57,7 @@ pub struct Controller { impl Controller { /// Returns a new handle to the interrupt controller. + #[inline] pub fn new() -> Controller { Controller { registers: unsafe { &mut *(INT_BASE as *mut Registers) }, @@ -58,4 +78,11 @@ impl Controller { pub fn is_pending(&self, int: Interrupt) -> bool { self.registers.IRQPending[int as usize / 32].read() & (1 << (int as usize) % 32) != 0 } + + /// Return all pending interrupts. + pub fn pending_interrupts(&self) -> PendingInterrupts { + let irq1 = self.registers.IRQPending[0].read() as u64; + let irq2 = self.registers.IRQPending[1].read() as u64; + PendingInterrupts((irq2 << 32) | irq1) + } } diff --git a/crate/bcm2837/src/mini_uart.rs b/crate/bcm2837/src/mini_uart.rs index 28e2c13..c1d0101 100644 --- a/crate/bcm2837/src/mini_uart.rs +++ b/crate/bcm2837/src/mini_uart.rs @@ -1,5 +1,5 @@ -use IO_BASE; -use gpio::{Function, Gpio}; +use crate::IO_BASE; +use crate::gpio::{Function, Gpio}; use volatile::{ReadOnly, Volatile}; /// The base address for the `MU` registers. @@ -8,6 +8,13 @@ const MU_REG_BASE: usize = IO_BASE + 0x215040; /// The `AUXENB` register from page 9 of the BCM2837 documentation. const AUX_ENABLES: *mut Volatile = (IO_BASE + 0x215004) as *mut Volatile; +/// Enum representing bit fields of the `AUX_MU_IIR_REG` register. +#[repr(u8)] +pub enum MiniUartInterruptId { + Transmit = 0b010, + Recive = 0b100, +} + /// Enum representing bit fields of the `AUX_MU_LSR_REG` register. #[repr(u8)] enum LsrStatus { @@ -15,7 +22,7 @@ enum LsrStatus { TxAvailable = 1 << 5, } -/// MU registers starting from `AUX_ENABLES` (ref: peripherals 2.1, page 8) +/// MU registers starting from `MU_REG_BASE` (ref: peripherals 2.1, page 8) #[repr(C)] #[allow(non_snake_case)] struct Registers { @@ -62,23 +69,25 @@ impl MiniUart { &mut *(MU_REG_BASE as *mut Registers) }; - Gpio::new(14).into_alt(Function::Alt5).set_gpio_pd(0); - Gpio::new(15).into_alt(Function::Alt5).set_gpio_pd(0); - - registers.AUX_MU_CNTL_REG.write(0); // Disable auto flow control and disable receiver and transmitter (for now) - registers.AUX_MU_IER_REG.write(0); // Disable receive and transmit interrupts - registers.AUX_MU_LCR_REG.write(3); // Enable 8 bit mode - registers.AUX_MU_MCR_REG.write(0); // Set RTS line to be always high - registers.AUX_MU_BAUD_REG.write(270); // Set baud rate to 115200 - - registers.AUX_MU_CNTL_REG.write(3); // Finally, enable transmitter and receiver - MiniUart { registers: registers, timeout: None, } } + pub fn init(&mut self) { + Gpio::new(14).into_alt(Function::Alt5).set_gpio_pd(0); + Gpio::new(15).into_alt(Function::Alt5).set_gpio_pd(0); + + self.registers.AUX_MU_CNTL_REG.write(0); // Disable auto flow control and disable receiver and transmitter (for now) + self.registers.AUX_MU_IER_REG.write(1); // Enable receive interrupts and disable transmit interrupts + self.registers.AUX_MU_LCR_REG.write(3); // Enable 8 bit mode + self.registers.AUX_MU_MCR_REG.write(0); // Set RTS line to be always high + self.registers.AUX_MU_BAUD_REG.write(270); // Set baud rate to 115200 + + self.registers.AUX_MU_CNTL_REG.write(3); // Finally, enable transmitter and receiver + } + /// Set the read timeout to `milliseconds` milliseconds. pub fn set_read_timeout(&mut self, milliseconds: u32) { self.timeout = Some(milliseconds) @@ -111,8 +120,13 @@ impl MiniUart { } /// Reads a byte. Blocks indefinitely until a byte is ready to be read. - pub fn read_byte(&mut self) -> u8 { + pub fn read_byte(&self) -> u8 { while !self.has_byte() {} self.registers.AUX_MU_IO_REG.read() } + + // Read `AUX_MU_IIR_REG` and determine if the interrupt `id` is pending. + pub fn interrupt_is_pending(&self, id: MiniUartInterruptId) -> bool { + self.registers.AUX_MU_IIR_REG.read() & 0b110 == id as u8 + } } diff --git a/crate/bcm2837/src/timer/generic_timer.rs b/crate/bcm2837/src/timer/generic_timer.rs index 6c3c0c8..8333cb9 100644 --- a/crate/bcm2837/src/timer/generic_timer.rs +++ b/crate/bcm2837/src/timer/generic_timer.rs @@ -1,6 +1,6 @@ -extern crate cortex_a; +extern crate aarch64; -use self::cortex_a::regs::*; +use aarch64::regs::*; use volatile::*; /// The base address for the ARM generic timer, IRQs, mailboxes @@ -58,7 +58,7 @@ impl Timer { /// Reads the generic timer's counter and returns the 64-bit counter value. /// The returned value is the number of elapsed microseconds. pub fn read(&self) -> u64 { - let cntfrq = CNTFRQ_EL0.get(); + let cntfrq = CNTFRQ_EL0.get(); // 62500000 (CNTPCT_EL0.get() * 1000000 / (cntfrq as u64)) as u64 } @@ -66,7 +66,7 @@ impl Timer { /// interrupts for timer 1 are enabled and IRQs are unmasked, then a timer /// interrupt will be issued in `us` microseconds. pub fn tick_in(&mut self, us: u32) { - let cntfrq = CNTFRQ_EL0.get(); + let cntfrq = CNTFRQ_EL0.get(); // 62500000 CNTP_TVAL_EL0.set(((cntfrq as f64) * (us as f64) / 1000000.0) as u32); } diff --git a/crate/bcm2837/src/timer/system_timer.rs b/crate/bcm2837/src/timer/system_timer.rs index cad2af4..4d5dc12 100644 --- a/crate/bcm2837/src/timer/system_timer.rs +++ b/crate/bcm2837/src/timer/system_timer.rs @@ -1,6 +1,6 @@ -use ::IO_BASE; +use crate::IO_BASE; +use crate::interrupt::{Controller, Interrupt}; use volatile::{ReadOnly, Volatile}; -use interrupt::{Controller, Interrupt}; /// The base address for the ARM system timer registers. const TIMER_REG_BASE: usize = IO_BASE + 0x3000; diff --git a/crate/memory/src/lib.rs b/crate/memory/src/lib.rs index ac956fa..96d3fd1 100644 --- a/crate/memory/src/lib.rs +++ b/crate/memory/src/lib.rs @@ -1,7 +1,6 @@ #![cfg_attr(not(test), no_std)] #![feature(alloc)] #![feature(nll)] -#![feature(extern_crate_item_prelude)] // import macros from log use log::*; @@ -14,4 +13,4 @@ pub mod memory_set; mod addr; pub mod no_mmu; -pub use crate::addr::*; \ No newline at end of file +pub use crate::addr::*; diff --git a/crate/process/src/lib.rs b/crate/process/src/lib.rs index ac55f7e..764cdb6 100644 --- a/crate/process/src/lib.rs +++ b/crate/process/src/lib.rs @@ -6,7 +6,6 @@ #![feature(vec_resize_default)] #![feature(asm)] #![feature(exact_size_is_empty)] -#![feature(extern_crate_item_prelude)] extern crate alloc; diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index b0600da..064af4a 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -1,12 +1,10 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#47bf5439f5a1379f0fef6272853cf684207a4e45" +source = "git+https://github.com/equation314/aarch64#e3b60adb233ad34d05443e0b5ec34cac29253296" dependencies = [ - "bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -50,7 +48,7 @@ version = "0.1.0" name = "bcm2837" version = "0.1.0" dependencies = [ - "cortex-a 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", "volatile 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -98,14 +96,6 @@ name = "cfg-if" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cortex-a" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "fixedvec" version = "0.2.3" @@ -455,7 +445,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bootloader 0.3.4 (git+https://github.com/wangrunji0408/bootloader)" = "" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" -"checksum cortex-a 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b187d0d728b4a99ba1d79f9671b976bcdd71a8a2c719585218fd2dc14a4d08c" "checksum fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6c16d316ccdac21a4dd648e314e76facbbaf316e83ca137d0857a9c07419d0" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index aa429ce..6718500 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -12,7 +12,8 @@ no_mmu = [] # Kernel in M-mode (for riscv32) m_mode = ["no_mmu"] # (for aarch64 RaspberryPi3) -board_raspi3 = [] +board_raspi3 = ["bcm2837"] +raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] [profile.dev] # MUST >= 1 : Enable RVO to avoid stack overflow @@ -53,7 +54,7 @@ bbl = { path = "../crate/bbl" } [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64 = { git = "https://github.com/equation314/aarch64" } atags = { path = "../crate/atags" } -bcm2837 = { path = "../crate/bcm2837", features = ["use_generic_timer"] } +bcm2837 = { path = "../crate/bcm2837", optional = true } [package.metadata.bootimage] default-target = "x86_64-blog_os.json" diff --git a/kernel/Makefile b/kernel/Makefile index cc60d88..2a2b560 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -80,6 +80,15 @@ features += no_bbl endif endif +ifeq ($(board), raspi3) +# qemu only has generic timer +# TODO: configure system/generic timer automatically +raspi3_timer ?= generic +ifeq ($(raspi3_timer), generic) +features += raspi3_use_generic_timer +endif +endif + ifdef m_mode features += no_mmu m_mode bbl_m_mode := --enable-boot-machine diff --git a/kernel/src/arch/aarch64/board/raspi3/irq.rs b/kernel/src/arch/aarch64/board/raspi3/irq.rs index c78b651..d8730dc 100644 --- a/kernel/src/arch/aarch64/board/raspi3/irq.rs +++ b/kernel/src/arch/aarch64/board/raspi3/irq.rs @@ -1,11 +1,28 @@ use crate::arch::interrupt::TrapFrame; -use bcm2837::timer::Timer; -use bcm2837::interrupt::{Controller, Interrupt}; +use bcm2837::interrupt::Controller; +use log::*; -pub fn handle_irq(tf: &mut TrapFrame) { - let controller = Timer::new(); +pub use bcm2837::interrupt::Interrupt; + +static IRQ_HANDLERS: &'static [Option; 64] = &[None; 64]; + +pub fn handle_irq(_tf: &mut TrapFrame) { + let controller = bcm2837::timer::Timer::new(); if controller.is_pending() { super::timer::set_next(); crate::trap::timer(); } + + for int in Controller::new().pending_interrupts() { + if let Some(handler) = IRQ_HANDLERS[int] { + handler(); + } + } +} + +pub fn register_irq(int: Interrupt, handler: fn()) { + unsafe { + *(&IRQ_HANDLERS[int as usize] as *const _ as *mut Option) = Some(handler); + } + Controller::new().enable(int); } diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index dd1abda..bfaa4f6 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -9,10 +9,16 @@ pub mod serial; pub const IO_REMAP_BASE: usize = bcm2837::IO_BASE; pub const IO_REMAP_END: usize = 0x40001000; -pub fn init() { +/// Some initializations must be done before other initializations. +pub fn init_early() { assert_has_not_been_called!("board::init must be called only once"); serial::SERIAL_PORT.lock().init(); println!("Hello Raspberry Pi!"); } + +/// Initialize raspi3 drivers +pub fn init_driver() { + timer::init(); +} diff --git a/kernel/src/arch/aarch64/board/raspi3/serial.rs b/kernel/src/arch/aarch64/board/raspi3/serial.rs index 6e4fce8..74ed5dd 100644 --- a/kernel/src/arch/aarch64/board/raspi3/serial.rs +++ b/kernel/src/arch/aarch64/board/raspi3/serial.rs @@ -1,11 +1,11 @@ -use bcm2837::mini_uart::MiniUart; +use bcm2837::mini_uart::{MiniUart, MiniUartInterruptId}; +use lazy_static::lazy_static; use core::fmt; use spin::Mutex; -use once::*; /// Struct to get a global SerialPort interface pub struct SerialPort { - mu: Option, + mu: MiniUart, } pub trait SerialRead { @@ -14,30 +14,31 @@ pub trait SerialRead { impl SerialPort { /// Creates a new instance of `SerialPort`. - const fn new() -> SerialPort { - SerialPort { mu: None } + fn new() -> SerialPort { + SerialPort { + mu: MiniUart::new(), + } } /// Init a newly created SerialPort, can only be called once. pub fn init(&mut self) { - assert_has_not_been_called!("SerialPort::init must be called only once"); - self.mu = Some(MiniUart::new()); + self.mu.init(); + super::irq::register_irq(super::irq::Interrupt::Aux, handle_serial_irq); } /// Writes the byte `byte` to the UART device. - pub fn write_byte(&mut self, byte: u8) { - match &mut self.mu { - Some(mu) => mu.write_byte(byte), - None => panic!("SerialPort is not initialized"), - } + fn write_byte(&mut self, byte: u8) { + self.mu.write_byte(byte) } /// Reads a byte from the UART device, blocking until a byte is available. - pub fn read_byte(&mut self) -> u8 { - match &mut self.mu { - Some(mu) => return mu.read_byte(), - None => panic!("SerialPort is not initialized"), - } + fn read_byte(&self) -> u8 { + self.mu.read_byte() + } + + // Whether the interrupt `id` is pending. + fn interrupt_is_pending(&self, id: MiniUartInterruptId) -> bool { + self.mu.interrupt_is_pending(id) } } @@ -70,4 +71,13 @@ impl fmt::Write for SerialPort { } } -pub static SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); +fn handle_serial_irq() { + let serial = SERIAL_PORT.lock(); + if serial.interrupt_is_pending(MiniUartInterruptId::Recive) { + crate::trap::serial(serial.read_byte() as char) + } +} + +lazy_static!{ + pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); +} diff --git a/kernel/src/arch/aarch64/board/raspi3/timer.rs b/kernel/src/arch/aarch64/board/raspi3/timer.rs index 9a51d31..8948441 100644 --- a/kernel/src/arch/aarch64/board/raspi3/timer.rs +++ b/kernel/src/arch/aarch64/board/raspi3/timer.rs @@ -1,5 +1,4 @@ use bcm2837::timer; -use bcm2837::interrupt::{Controller, Interrupt}; use log::*; pub fn init() { diff --git a/kernel/src/arch/aarch64/driver/mod.rs b/kernel/src/arch/aarch64/driver/mod.rs new file mode 100644 index 0000000..43d8c43 --- /dev/null +++ b/kernel/src/arch/aarch64/driver/mod.rs @@ -0,0 +1,12 @@ +/// ARM64 drivers + +use once::*; + +use super::board; + +/// Initialize ARM64 common drivers +pub fn init() { + assert_has_not_been_called!(); + + board::init_driver(); +} diff --git a/kernel/src/arch/aarch64/interrupt/context.rs b/kernel/src/arch/aarch64/interrupt/context.rs index 8b231e7..0d6502c 100644 --- a/kernel/src/arch/aarch64/interrupt/context.rs +++ b/kernel/src/arch/aarch64/interrupt/context.rs @@ -99,7 +99,7 @@ impl Context { /// Pop all callee-saved registers, then return to the target. #[naked] #[inline(never)] - unsafe extern fn __switch(self_stack: &mut usize, target_stack: &mut usize) { + unsafe extern fn __switch(_self_stack: &mut usize, _target_stack: &mut usize) { asm!( " mov x10, #-(12 * 8) @@ -149,7 +149,7 @@ impl Context { tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top), }.push_at(kstack_top, ttbr) } - pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, is32: bool, ttbr: usize) -> Self { + pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, _is32: bool, ttbr: usize) -> Self { InitStack { context: ContextData::new(), tf: TrapFrame::new_user_thread(entry_addr, ustack_top), diff --git a/kernel/src/arch/aarch64/interrupt/handler.rs b/kernel/src/arch/aarch64/interrupt/handler.rs index 99652bc..68a607b 100644 --- a/kernel/src/arch/aarch64/interrupt/handler.rs +++ b/kernel/src/arch/aarch64/interrupt/handler.rs @@ -93,8 +93,9 @@ fn handle_syscall(num: u16, tf: &mut TrapFrame) { } fn handle_page_fault(tf: &mut TrapFrame) { - let addr = FAR_EL1.get(); - error!("\nEXCEPTION: Page Fault @ {:#x}", addr); - - crate::trap::error(tf); + let addr = FAR_EL1.get() as usize; + if !crate::memory::page_fault_handler(addr) { + error!("\nEXCEPTION: Page Fault @ {:#x}", addr); + crate::trap::error(tf); + } } diff --git a/kernel/src/arch/aarch64/io.rs b/kernel/src/arch/aarch64/io.rs index 1a9d1d4..bb3c986 100644 --- a/kernel/src/arch/aarch64/io.rs +++ b/kernel/src/arch/aarch64/io.rs @@ -1,7 +1,7 @@ //! Serial driver for aarch64. use core::fmt::{Arguments, Write}; -use super::board::serial::{SerialRead, SERIAL_PORT}; +use super::board::serial::*; pub fn getchar() -> char { unsafe { SERIAL_PORT.force_unlock(); } diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index 2513932..1ba7a67 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -99,7 +99,7 @@ fn init_frame_allocator() { /// remap kernel page table after all initialization. fn remap_the_kernel() { - let mut ms = unsafe { MemorySet::new_bare() }; + let mut ms = MemorySet::new_bare(); ms.push(0, bootstacktop as usize, Linear::new(0, MemoryAttr::default()), "kstack"); ms.push(stext as usize, etext as usize, Linear::new(0, MemoryAttr::default().execute().readonly()), "text"); ms.push(sdata as usize, edata as usize, Linear::new(0, MemoryAttr::default()), "data"); diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index b96f24e..1d9269f 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -6,29 +6,25 @@ pub mod memory; pub mod interrupt; pub mod consts; pub mod cpu; +pub mod driver; #[cfg(feature = "board_raspi3")] #[path = "board/raspi3/mod.rs"] pub mod board; -pub use self::board::timer; - global_asm!(include_str!("boot/boot.S")); /// The entry point of kernel #[no_mangle] // don't mangle the name of this function pub extern "C" fn rust_main() -> ! { - // Enable mmu and paging - memory::init_mmu_early(); - - // Init board to enable serial port. - board::init(); + memory::init_mmu_early(); // Enable mmu and paging + board::init_early(); println!("{}", LOGO); crate::logging::init(); interrupt::init(); memory::init(); - timer::init(); + driver::init(); crate::process::init(); diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index 6542f79..8173681 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -58,12 +58,14 @@ impl PageTable for ActivePageTable { } fn unmap(&mut self, addr: usize) { - let (frame, flush) = self.0.unmap(Page::of_addr(addr)).unwrap(); + let (_frame, flush) = self.0.unmap(Page::of_addr(addr)).unwrap(); flush.flush(); } - fn get_entry(&mut self, addr: usize) -> Option<&mut Entry> { - let entry_addr = ((addr >> 9) & 0o777_777_777_7770) | (RECURSIVE_INDEX << 39); + fn get_entry(&mut self, vaddr: usize) -> Option<&mut Entry> { + // get p1 entry + let entry_addr = ((vaddr >> 9) & 0o777_777_777_7770) | (RECURSIVE_INDEX << 39) + | (vaddr & 0xffff_0000_0000_0000); Some(unsafe { &mut *(entry_addr as *mut PageEntry) }) } } @@ -211,9 +213,11 @@ impl InactivePageTable for InactivePageTable0 { let target = ttbr_el1_read(0).start_address().as_u64() as usize; active_table().with_temporary_map(target, |active_table, p4_table: &mut Aarch64PageTable| { let backup = p4_table[RECURSIVE_INDEX].clone(); + let old_frame = ttbr_el1_read(1); // overwrite recursive mapping p4_table[RECURSIVE_INDEX].set_frame(self.p4_frame.clone(), EF::default(), MairNormal::attr_value()); + ttbr_el1_write(1, self.p4_frame.clone()); tlb_invalidate_all(); // execute f in the new context @@ -221,6 +225,7 @@ impl InactivePageTable for InactivePageTable0 { // restore recursive mapping to original p4 table p4_table[RECURSIVE_INDEX] = backup; + ttbr_el1_write(1, old_frame); tlb_invalidate_all(); ret }) diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs index 9b9d04b..725642d 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -77,13 +77,12 @@ impl Stdin { pub fn pop(&self) -> char { // QEMU v3.0 don't support M-mode external interrupt (bug?) // So we have to use polling. - // TODO: serial interrupt on aarch64 - #[cfg(any(feature = "m_mode", target_arch = "aarch64"))] + #[cfg(feature = "m_mode")] loop { let c = crate::arch::io::getchar(); if c != '\0' { return c; } } - #[cfg(not(any(feature = "m_mode", target_arch = "aarch64")))] + #[cfg(not(feature = "m_mode"))] loop { let ret = self.buf.lock().pop_front(); match ret { diff --git a/kernel/src/memory.rs b/kernel/src/memory.rs index 7e598f7..295e26e 100644 --- a/kernel/src/memory.rs +++ b/kernel/src/memory.rs @@ -1,5 +1,5 @@ pub use crate::arch::paging::*; -use bit_allocator::{BitAlloc, BitAlloc4K, BitAlloc64K, BitAlloc1M}; +use bit_allocator::BitAlloc; use crate::consts::MEMORY_OFFSET; use super::HEAP_ALLOCATOR; use ucore_memory::{*, paging::PageTable}; @@ -21,15 +21,15 @@ pub type MemorySet = ucore_memory::no_mmu::MemorySet; // x86_64 support up to 256M memory #[cfg(target_arch = "x86_64")] -pub type FrameAlloc = BitAlloc64K; +pub type FrameAlloc = bit_allocator::BitAlloc64K; // RISCV only have 8M memory #[cfg(target_arch = "riscv32")] -pub type FrameAlloc = BitAlloc4K; +pub type FrameAlloc = bit_allocator::BitAlloc4K; // Raspberry Pi 3 has 1G memory #[cfg(target_arch = "aarch64")] -pub type FrameAlloc = BitAlloc1M; +pub type FrameAlloc = bit_allocator::BitAlloc1M; lazy_static! { pub static ref FRAME_ALLOCATOR: SpinNoIrqLock = SpinNoIrqLock::new(FrameAlloc::default());