mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-21 23:56:18 +04:00
Merge remote-tracking branch 'equation314/arch-aarch64' into dev
# Conflicts: # kernel/src/arch/aarch64/memory.rs # kernel/src/arch/aarch64/paging.rs # kernel/src/process/context.rs
This commit is contained in:
commit
9b0b0064d0
@ -2,10 +2,11 @@
|
||||
name = "bcm2837"
|
||||
version = "0.1.0"
|
||||
authors = ["equation314 <equation618@gmail.com>"]
|
||||
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 }
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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<u32>,
|
||||
}
|
||||
|
||||
/// Pending interrupts
|
||||
pub struct PendingInterrupts(u64);
|
||||
|
||||
impl Iterator for PendingInterrupts {
|
||||
type Item = usize;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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<u8> = (IO_BASE + 0x215004) as *mut Volatile<u8>;
|
||||
|
||||
/// 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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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::*;
|
||||
pub use crate::addr::*;
|
||||
|
@ -6,7 +6,6 @@
|
||||
#![feature(vec_resize_default)]
|
||||
#![feature(asm)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(extern_crate_item_prelude)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
15
kernel/Cargo.lock
generated
15
kernel/Cargo.lock
generated
@ -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)" = "<none>"
|
||||
"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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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<fn()>; 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<fn()>) = Some(handler);
|
||||
}
|
||||
Controller::new().enable(int);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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<MiniUart>,
|
||||
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<SerialPort> = 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<SerialPort> = Mutex::new(SerialPort::new());
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
use bcm2837::timer;
|
||||
use bcm2837::interrupt::{Controller, Interrupt};
|
||||
use log::*;
|
||||
|
||||
pub fn init() {
|
||||
|
12
kernel/src/arch/aarch64/driver/mod.rs
Normal file
12
kernel/src/arch/aarch64/driver/mod.rs
Normal file
@ -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();
|
||||
}
|
@ -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),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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(); }
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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 {
|
||||
|
@ -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<NoMMUSupportImpl>;
|
||||
|
||||
// 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<FrameAlloc> = SpinNoIrqLock::new(FrameAlloc::default());
|
||||
|
Loading…
Reference in New Issue
Block a user