diff --git a/kernel-hal/Cargo.toml b/kernel-hal/Cargo.toml index 4023812a..d9d3a6ea 100644 --- a/kernel-hal/Cargo.toml +++ b/kernel-hal/Cargo.toml @@ -9,6 +9,8 @@ description = "Kernel HAL interface definations." [features] libos = ["async-std"] +board_qemu = [] +board_d1 = [] [dependencies] log = "0.4" @@ -50,5 +52,4 @@ x86-smpboot = { git = "https://github.com/rcore-os/x86-smpboot", rev = "43ffedf" # Bare-metal mode on riscv64 [target.'cfg(all(target_os = "none", target_arch = "riscv64"))'.dependencies] -# riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" } -# volatile = "0.2" +riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" } diff --git a/kernel-hal/src/bare/arch/riscv/consts.rs b/kernel-hal/src/bare/arch/riscv/consts.rs index cdd65076..8f3197bf 100644 --- a/kernel-hal/src/bare/arch/riscv/consts.rs +++ b/kernel-hal/src/bare/arch/riscv/consts.rs @@ -23,32 +23,31 @@ pub const MMIO_MTIMECMP0: *mut u64 = 0x0200_4000usize as *mut u64; pub const MMIO_MTIME: *const u64 = 0x0200_BFF8 as *const u64; #[cfg(feature = "board_qemu")] -pub const UART_BASE: usize = 0x10000000; +pub const UART_BASE: usize = 0x10000000; #[cfg(feature = "board_qemu")] -pub const UART0_INT_NUM: u32 = 10; +pub const UART0_INT_NUM: u32 = 10; #[cfg(feature = "board_qemu")] -pub const PLIC_PRIORITY: usize = 0x0c000000; +pub const PLIC_PRIORITY: usize = 0x0c000000; #[cfg(feature = "board_qemu")] -pub const PLIC_PENDING: usize = 0x0c001000; +pub const PLIC_PENDING: usize = 0x0c001000; #[cfg(feature = "board_qemu")] pub const PLIC_INT_ENABLE: usize = 0x0c002080; #[cfg(feature = "board_qemu")] -pub const PLIC_THRESHOLD: usize = 0x0c201000; +pub const PLIC_THRESHOLD: usize = 0x0c201000; #[cfg(feature = "board_qemu")] -pub const PLIC_CLAIM: usize = 0x0c201004; +pub const PLIC_CLAIM: usize = 0x0c201004; #[cfg(feature = "board_d1")] -pub const UART_BASE: usize = 0x02500000; +pub const UART_BASE: usize = 0x02500000; #[cfg(feature = "board_d1")] -pub const UART0_INT_NUM: u32 = 18; +pub const UART0_INT_NUM: u32 = 18; #[cfg(feature = "board_d1")] -pub const PLIC_PRIORITY: usize = 0x1000_0000; +pub const PLIC_PRIORITY: usize = 0x1000_0000; #[cfg(feature = "board_d1")] -pub const PLIC_PENDING: usize = 0x1000_1000; +pub const PLIC_PENDING: usize = 0x1000_1000; #[cfg(feature = "board_d1")] pub const PLIC_INT_ENABLE: usize = 0x1000_2080; #[cfg(feature = "board_d1")] -pub const PLIC_THRESHOLD: usize = 0x1020_1000; +pub const PLIC_THRESHOLD: usize = 0x1020_1000; #[cfg(feature = "board_d1")] -pub const PLIC_CLAIM: usize = 0x1020_1004; - +pub const PLIC_CLAIM: usize = 0x1020_1004; diff --git a/kernel-hal/src/bare/arch/riscv/context.rs b/kernel-hal/src/bare/arch/riscv/context.rs new file mode 100644 index 00000000..f40a7843 --- /dev/null +++ b/kernel-hal/src/bare/arch/riscv/context.rs @@ -0,0 +1,19 @@ +use riscv::register::{scause, stval}; + +use crate::VirtAddr; + +hal_fn_impl! { + impl mod crate::defs::context { + fn context_run(context: &mut UserContext) { + context.run(); + } + + fn fetch_fault_vaddr() -> VirtAddr { + stval::read() as _ + } + + fn fetch_trap_num(_context: &UserContext) -> usize { + scause::read().bits() + } + } +} diff --git a/kernel-hal/src/bare/arch/riscv/cpu.rs b/kernel-hal/src/bare/arch/riscv/cpu.rs new file mode 100644 index 00000000..afd95ad0 --- /dev/null +++ b/kernel-hal/src/bare/arch/riscv/cpu.rs @@ -0,0 +1,8 @@ +hal_fn_impl! { + impl mod crate::defs::cpu { + fn cpu_frequency() -> u16 { + const DEFAULT: u16 = 2600; + DEFAULT + } + } +} diff --git a/kernel-hal/src/bare/arch/riscv/interrupt.rs b/kernel-hal/src/bare/arch/riscv/interrupt.rs index be583213..2037dff6 100644 --- a/kernel-hal/src/bare/arch/riscv/interrupt.rs +++ b/kernel-hal/src/bare/arch/riscv/interrupt.rs @@ -1,94 +1,46 @@ -use alloc::boxed::Box; -use alloc::vec::Vec; -use riscv::register::{ - satp, - scause::{self, Exception, Interrupt, Trap}, - sie, sstatus, stval, -}; +use alloc::{boxed::Box, vec::Vec}; +use riscv::register::{sie, sstatus}; use spin::Mutex; -use trapframe::{TrapFrame, UserContext}; -use super::{plic, uart, sbi, timer_set_next}; -use super::consts::{PHYSICAL_MEMORY_OFFSET, UART_BASE, UART0_INT_NUM}; -use crate::{map_range, phys_to_virt, putfmt}; +use super::{consts, plic, serial, trap, uart}; + +// IRQ +const TIMER: u8 = 5; +const U_PLIC: u8 = 8; +const S_PLIC: u8 = 9; +const M_PLIC: u8 = 11; const TABLE_SIZE: usize = 256; -pub type InterruptHandle = Box; -lazy_static! { - static ref IRQ_TABLE: Mutex>> = Default::default(); + +type InterruptHandler = Box; + +lazy_static::lazy_static! { + static ref IRQ_TABLE: Mutex>> = Default::default(); } -fn init_irq() { - init_irq_table(); - irq_add_handle(Timer, Box::new(super_timer)); //模拟参照了x86_64,把timer处理函数也放进去了 - //irq_add_handle(Keyboard, Box::new(keyboard)); - irq_add_handle(S_PLIC, Box::new(plic::handle_interrupt)); +#[allow(dead_code)] +fn init_soft() { + unsafe { sie::set_ssoft() }; + sbi_println!("+++ setup soft int! +++"); } -pub fn init() { - unsafe { - sstatus::set_sie(); - - init_uart(); - - sie::set_sext(); - init_ext(); - } - - init_irq(); - - bare_println!("+++ setup interrupt +++"); +fn init_ext() { + unsafe { sie::set_sext() }; + plic::init(); + sbi_println!("+++ Setting up PLIC +++"); } -#[no_mangle] -pub extern "C" fn trap_handler(tf: &mut TrapFrame) { - let sepc = tf.sepc; - let scause = scause::read(); - let stval = stval::read(); - let is_int = scause.bits() >> 63; - let code = scause.bits() & !(1 << 63); +fn init_uart() { + uart::init(consts::UART_BASE); - match scause.cause() { - Trap::Exception(Exception::Breakpoint) => breakpoint(&mut tf.sepc), - Trap::Exception(Exception::IllegalInstruction) => { - panic!("IllegalInstruction: {:#x}->{:#x}", sepc, stval) - } - Trap::Exception(Exception::LoadFault) => { - panic!("Load access fault: {:#x}->{:#x}", sepc, stval) - } - Trap::Exception(Exception::StoreFault) => { - panic!("Store access fault: {:#x}->{:#x}", sepc, stval) - } - Trap::Exception(Exception::LoadPageFault) => page_fault(stval, tf), - Trap::Exception(Exception::StorePageFault) => page_fault(stval, tf), - Trap::Exception(Exception::InstructionPageFault) => page_fault(stval, tf), - Trap::Interrupt(Interrupt::SupervisorTimer) => super_timer(), - Trap::Interrupt(Interrupt::SupervisorSoft) => super_soft(), - Trap::Interrupt(Interrupt::SupervisorExternal) => plic::handle_interrupt(), - //Trap::Interrupt(Interrupt::SupervisorExternal) => irq_handle(code as u8), - _ => panic!("Undefined Trap: {:#x} {:#x}", is_int, code), - } -} + //但当没有SBI_CONSOLE_PUTCHAR时,却为什么不行? + serial::uart_print_fmt(format_args!("UART output testing\n\r")); -fn init_irq_table() { - let mut table = IRQ_TABLE.lock(); - for _ in 0..TABLE_SIZE { - table.push(None); - } -} - -#[export_name = "hal_irq_handle"] -pub fn irq_handle(irq: u8) { - debug!("PLIC handle: {:#x}", irq); - let table = IRQ_TABLE.lock(); - match &table[irq as usize] { - Some(f) => f(), - None => panic!("unhandled U-mode external IRQ number: {}", irq), - } + sbi_println!("+++ Setting up UART interrupts +++"); } /// Add a handle to IRQ table. Return the specified irq or an allocated irq on success -fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option { +fn irq_add_handle(irq: u8, handler: InterruptHandler) -> Option { info!("IRQ add handle {:#x?}", irq); let mut table = IRQ_TABLE.lock(); // allocate a valid irq number @@ -97,7 +49,7 @@ fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option { let mut id = 0x20; while id < table.len() { if table[id].is_none() { - table[id] = Some(handle); + table[id] = Some(handler); return Some(id as u8); } id += 1; @@ -108,206 +60,43 @@ fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option { match table[irq as usize] { Some(_) => None, None => { - table[irq as usize] = Some(handle); + table[irq as usize] = Some(handler); Some(irq) } } } -fn irq_remove_handle(irq: u8) -> bool { - info!("IRQ remove handle {:#x?}", irq); - let irq = irq as usize; +fn init_irq_table() { let mut table = IRQ_TABLE.lock(); - match table[irq] { - Some(_) => { - table[irq] = None; - false - } - None => true, + for _ in 0..TABLE_SIZE { + table.push(None); } } -fn breakpoint(sepc: &mut usize) { - bare_println!("Exception::Breakpoint: A breakpoint set @0x{:x} ", sepc); - - //sepc为触发中断指令ebreak的地址 - //防止无限循环中断,让sret返回时跳转到sepc的下一条指令地址 - *sepc += 2 +fn init_irq() { + init_irq_table(); + irq_add_handle(TIMER, Box::new(trap::super_timer)); //模拟参照了x86_64,把timer处理函数也放进去了 + //irq_add_handle(Keyboard, Box::new(keyboard)); + irq_add_handle(S_PLIC, Box::new(plic::handle_interrupt)); } -fn page_fault(stval: usize, tf: &mut TrapFrame) { - let this_scause = scause::read(); - info!( - "EXCEPTION Page Fault: {:?} @ {:#x}->{:#x}", - this_scause.cause(), - tf.sepc, - stval - ); - let vaddr = stval; - - use crate::PageTableImpl; - use kernel_hal::{MMUFlags, paging::PageTableTrait}; - use riscv::addr::{Page, PhysAddr, VirtAddr}; - use riscv::paging::{PageTableFlags as PTF, Rv39PageTable, *}; - - //let mut flags = PTF::VALID; - let code = this_scause.code(); - let mut flags = if code == 15 { - //MMUFlags::WRITE ??? - MMUFlags::READ | MMUFlags::WRITE - } else if code == 12 { - MMUFlags::EXECUTE - } else { - MMUFlags::READ - }; - - let linear_offset = if stval >= PHYSICAL_MEMORY_OFFSET { - // Kernel - PHYSICAL_MEMORY_OFFSET - } else { - // User - 0 - }; - - /* - let current = - unsafe { &mut *(phys_to_virt(satp::read().frame().start_address().as_usize()) as *mut PageTable) }; - let mut pt = Rv39PageTable::new(current, PHYSICAL_MEMORY_OFFSET); - map_range(&mut pt, vaddr, vaddr, linear_offset, flags); - */ - - let mut pti = PageTableImpl { - root_paddr: satp::read().frame().start_address().as_usize(), - }; - - let page = Page::of_addr(VirtAddr::new(vaddr)); - if let Ok(pte) = pti.get().ref_entry(page) { - let pte = unsafe { &mut *(pte as *mut PageTableEntry) }; - if !pte.is_unused() { - debug!( - "PageAlreadyMapped -> {:#x?}, {:?}", - pte.addr().as_usize(), - pte.flags() - ); - //TODO update flags - - pti.unmap(vaddr).unwrap(); - } - }; - pti.map(vaddr, vaddr - linear_offset, flags).unwrap(); +pub(super) fn init() { + unsafe { sstatus::set_sie() }; + init_uart(); + init_ext(); + init_irq(); + sbi_println!("+++ setup interrupt +++"); } -fn super_timer() { - timer_set_next(); - super::timer_tick(); - - //bare_print!("."); - - //发生外界中断时,epc的指令还没有执行,故无需修改epc到下一条 -} - -fn init_uart() { - uart::Uart::new(phys_to_virt(UART_BASE)).simple_init(); - - //但当没有SBI_CONSOLE_PUTCHAR时,却为什么不行? - super::putfmt_uart(format_args!("{}", "UART output testing\n\r")); - - bare_println!("+++ Setting up UART interrupts +++"); -} - -//被plic串口中断调用 -pub fn try_process_serial() -> bool { - match super::getchar_option() { - Some(ch) => { - super::serial_put(ch); - true - } - None => false, - } -} - -pub fn init_ext() { - // Qemu virt UART0 = 10 - // ALLWINNER D1 UART0 = 18 - plic::set_priority(UART0_INT_NUM, 7); - plic::set_threshold(0); - plic::enable(UART0_INT_NUM); - - bare_println!("+++ Setting up PLIC +++"); -} - -fn super_soft() { - sbi::clear_ipi(); - bare_println!("Interrupt::SupervisorSoft!"); -} - -pub fn init_soft() { - unsafe { - sie::set_ssoft(); - } - bare_println!("+++ setup soft int! +++"); -} - -#[export_name = "fetch_trap_num"] -pub fn fetch_trap_num(_context: &UserContext) -> usize { - scause::read().bits() -} - -pub fn wait_for_interrupt() { - unsafe { - // enable interrupt and disable - let sie = riscv::register::sstatus::read().sie(); - riscv::register::sstatus::set_sie(); - riscv::asm::wfi(); - if !sie { - riscv::register::sstatus::clear_sie(); - } - } -} - -fn timer() { - super::timer_tick(); -} - -/* - * 改道uart::handle_interrupt()中 - * -fn com1() { - let c = super::COM1.lock().receive(); - super::serial_put(c); -} -*/ - -/* -fn keyboard() { - use pc_keyboard::{DecodedKey, KeyCode}; - if let Some(key) = super::keyboard::receive() { - match key { - DecodedKey::Unicode(c) => super::serial_put(c as u8), - DecodedKey::RawKey(code) => { - let s = match code { - KeyCode::ArrowUp => "\u{1b}[A", - KeyCode::ArrowDown => "\u{1b}[B", - KeyCode::ArrowRight => "\u{1b}[C", - KeyCode::ArrowLeft => "\u{1b}[D", - _ => "", - }; - for c in s.bytes() { - super::serial_put(c); - } +hal_fn_impl! { + impl mod crate::defs::interrupt { + fn handle_irq(irq: u32) { + debug!("PLIC handle: {:#x}", irq); + let table = IRQ_TABLE.lock(); + match &table[irq as usize] { + Some(f) => f(), + None => panic!("unhandled U-mode external IRQ number: {}", irq), } } } } -*/ - -// IRQ -const Timer: u8 = 5; -const U_PLIC: u8 = 8; -const S_PLIC: u8 = 9; -const M_PLIC: u8 = 11; - -//const Keyboard: u8 = 1; -//const COM2: u8 = 3; -const COM1: u8 = 0; -//const IDE: u8 = 14; diff --git a/kernel-hal/src/bare/arch/riscv/mem.rs b/kernel-hal/src/bare/arch/riscv/mem.rs new file mode 100644 index 00000000..1fc9724e --- /dev/null +++ b/kernel-hal/src/bare/arch/riscv/mem.rs @@ -0,0 +1,3 @@ +pub fn frame_flush(_target: crate::PhysAddr) { + unimplemented!() +} diff --git a/kernel-hal/src/bare/arch/riscv/mod.rs b/kernel-hal/src/bare/arch/riscv/mod.rs index 98bee9ee..cb164263 100644 --- a/kernel-hal/src/bare/arch/riscv/mod.rs +++ b/kernel-hal/src/bare/arch/riscv/mod.rs @@ -1,567 +1,36 @@ -use super::super::*; -use kernel_hal::dev::fb::{ColorDepth, ColorFormat, FramebufferInfo, FRAME_BUFFER}; -use kernel_hal::{HalError, PhysAddr, VirtAddr, paging::PageTableTrait}; -use riscv::addr::Page; -use riscv::asm::sfence_vma_all; -use riscv::paging::{PageTableFlags as PTF, *}; -use riscv::register::{satp, sie, stval, time}; -//use crate::sbi; -use alloc::{collections::VecDeque, vec::Vec}; -use core::fmt::{self, Write}; +#![allow(dead_code)] -mod sbi; +use alloc::vec::Vec; + +#[macro_use] +pub mod serial; mod consts; +mod plic; +mod sbi; +mod trap; +mod uart; -use consts::*; +pub mod context; +pub mod cpu; +pub mod interrupt; +pub mod mem; +pub mod special; +pub mod timer; +pub mod vm; -// First core stores its SATP here. -static mut SATP: usize = 0; - -/// remap kernel with 4K page -pub fn remap_the_kernel(dtb: usize) { - let root_frame = Frame::alloc().expect("failed to alloc frame"); - let root_vaddr = phys_to_virt(root_frame.paddr); - let root = unsafe { &mut *(root_vaddr as *mut PageTable) }; - root.zero(); - let mut pt = Rv39PageTable::new(root, PHYSICAL_MEMORY_OFFSET); - - let linear_offset = PHYSICAL_MEMORY_OFFSET; - //let mut flags = PTF::VALID | PTF::READABLE | PTF::WRITABLE | PTF::EXECUTABLE | PTF::USER; - - map_range( - &mut pt, - stext as usize, - etext as usize - 1, - linear_offset, - PTF::VALID | PTF::READABLE | PTF::EXECUTABLE, - ) - .unwrap(); - map_range( - &mut pt, - srodata as usize, - erodata as usize, - linear_offset, - PTF::VALID | PTF::READABLE, - ) - .unwrap(); - map_range( - &mut pt, - sdata as usize, - edata as usize, - linear_offset, - PTF::VALID | PTF::READABLE | PTF::WRITABLE, - ) - .unwrap(); - - // Stack - map_range( - &mut pt, - bootstack as usize, - bootstacktop as usize - 1, - linear_offset, - PTF::VALID | PTF::READABLE | PTF::WRITABLE, - ) - .unwrap(); - - map_range( - &mut pt, - sbss as usize, - ebss as usize - 1, - linear_offset, - PTF::VALID | PTF::READABLE | PTF::WRITABLE, - ) - .unwrap(); - - info!("map Heap ..."); - // Heap - map_range( - &mut pt, - end as usize, - end as usize + PAGE_SIZE * 5120, - linear_offset, - PTF::VALID | PTF::READABLE | PTF::WRITABLE, - ) - .unwrap(); - info!("... Heap"); - - // Device Tree - #[cfg(feature = "board_qemu")] - map_range( - &mut pt, - dtb, - dtb + consts::MAX_DTB_SIZE, - linear_offset, - PTF::VALID | PTF::READABLE, - ) - .unwrap(); - - // PLIC - map_range( - &mut pt, - phys_to_virt(PLIC_PRIORITY), - phys_to_virt(PLIC_PRIORITY) + PAGE_SIZE * 0xf, - linear_offset, - PTF::VALID | PTF::READABLE | PTF::WRITABLE, - ) - .unwrap(); - map_range( - &mut pt, - phys_to_virt(PLIC_THRESHOLD), - phys_to_virt(PLIC_THRESHOLD) + PAGE_SIZE * 0xf, - linear_offset, - PTF::VALID | PTF::READABLE | PTF::WRITABLE, - ) - .unwrap(); - - // UART0, VIRTIO - map_range( - &mut pt, - phys_to_virt(UART_BASE), - phys_to_virt(UART_BASE) + PAGE_SIZE * 0xf, - linear_offset, - PTF::VALID | PTF::READABLE | PTF::WRITABLE, - ) - .unwrap(); - - //写satp - let token = root_frame.paddr; - unsafe { - set_page_table(token); - SATP = token; - } - - //use core::mem; - //mem::forget(pt); - - info!("remap the kernel @ {:#x}", token); -} - -pub fn map_range( - page_table: &mut Rv39PageTable, - mut start_addr: VirtAddr, - mut end_addr: VirtAddr, - linear_offset: usize, - flags: PageTableFlags, -) -> Result<(), ()> { - trace!("Mapping range addr: {:#x} ~ {:#x}", start_addr, end_addr); - - start_addr = start_addr & !(PAGE_SIZE - 1); - let mut start_page = start_addr / PAGE_SIZE; - - //end_addr = (end_addr + PAGE_SIZE - 1) & !(PAGE_SIZE -1); - //let end_page = (end_addr - 1) / PAGE_SIZE; - end_addr = end_addr & !(PAGE_SIZE - 1); - let end_page = end_addr / PAGE_SIZE; - - while start_page <= end_page { - let vaddr: VirtAddr = start_page * PAGE_SIZE; - let page = riscv::addr::Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); - let frame = riscv::addr::Frame::of_addr(riscv::addr::PhysAddr::new(vaddr - linear_offset)); - - start_page += 1; - - trace!( - "map_range: {:#x} -> {:#x}, flags={:?}", - vaddr, - vaddr - linear_offset, - flags - ); - page_table - .map_to(page, frame, flags, &mut FrameAllocatorImpl) - .unwrap() - .flush(); - } - info!( - "map range from {:#x} to {:#x}, flags: {:?}", - start_addr, - end_page * PAGE_SIZE, - flags - ); - - Ok(()) -} - -extern "C" { - fn start(); - - fn stext(); - fn etext(); - fn srodata(); - fn erodata(); - fn sdata(); - fn edata(); - - fn bootstack(); - fn bootstacktop(); - - fn sbss(); - fn ebss(); - - fn end(); -} - -/// Page Table #[repr(C)] -pub struct PageTableImpl { - root_paddr: PhysAddr, +#[derive(Debug, Copy, Clone)] +pub struct GraphicInfo { + /// Graphic mode + //pub mode: ModeInfo, + pub mode: u64, + /// Framebuffer base physical address + pub fb_addr: u64, + /// Framebuffer size + pub fb_size: u64, } -impl PageTableImpl { - /// Create a new `PageTable`. - #[allow(clippy::new_without_default)] - #[export_name = "hal_pt_new"] - pub fn new() -> Self { - let root_frame = Frame::alloc().expect("failed to alloc frame"); - let root_vaddr = phys_to_virt(root_frame.paddr); - let root = unsafe { &mut *(root_vaddr as *mut PageTable) }; - root.zero(); - - let current = - phys_to_virt(satp::read().frame().start_address().as_usize()) as *const PageTable; - map_kernel(root_vaddr as _, current as _); - trace!("create page table @ {:#x}", root_frame.paddr); - PageTableImpl { - root_paddr: root_frame.paddr, - } - } - - #[cfg(target_arch = "riscv32")] - fn get(&mut self) -> Rv32PageTable<'_> { - let root_vaddr = phys_to_virt(self.root_paddr); - let root = unsafe { &mut *(root_vaddr as *mut PageTable) }; - Rv32PageTable::new(root, phys_to_virt(0)) - } - - #[cfg(target_arch = "riscv64")] - fn get(&mut self) -> Rv39PageTable<'_> { - let root_vaddr = phys_to_virt(self.root_paddr); - let root = unsafe { &mut *(root_vaddr as *mut PageTable) }; - Rv39PageTable::new(root, phys_to_virt(0)) - } -} - -impl PageTableTrait for PageTableImpl { - /// Map the page of `vaddr` to the frame of `paddr` with `flags`. - #[export_name = "hal_pt_map"] - fn map(&mut self, vaddr: VirtAddr, paddr: PhysAddr, flags: MMUFlags) -> Result<(), HalError> { - let mut pt = self.get(); - let page = Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); - let frame = riscv::addr::Frame::of_addr(riscv::addr::PhysAddr::new(paddr)); - pt.map_to(page, frame, flags.to_ptf(), &mut FrameAllocatorImpl) - .unwrap() - .flush(); - - trace!( - "PageTable: {:#X}, map: {:x?} -> {:x?}, flags={:?}", - self.table_phys() as usize, - vaddr, - paddr, - flags - ); - Ok(()) - } - - /// Unmap the page of `vaddr`. - #[export_name = "hal_pt_unmap"] - fn unmap(&mut self, vaddr: VirtAddr) -> Result<(), HalError> { - let mut pt = self.get(); - let page = Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); - pt.unmap(page).unwrap().1.flush(); - trace!( - "PageTable: {:#X}, unmap: {:x?}", - self.table_phys() as usize, - vaddr - ); - Ok(()) - } - - /// Change the `flags` of the page of `vaddr`. - #[export_name = "hal_pt_protect"] - fn protect(&mut self, vaddr: VirtAddr, flags: MMUFlags) -> Result<(), HalError> { - let mut pt = self.get(); - let page = Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); - pt.update_flags(page, flags.to_ptf()).unwrap().flush(); - - trace!( - "PageTable: {:#X}, protect: {:x?}, flags={:?}", - self.table_phys() as usize, - vaddr, - flags - ); - Ok(()) - } - - /// Query the physical address which the page of `vaddr` maps to. - #[export_name = "hal_pt_query"] - fn query(&mut self, vaddr: VirtAddr) -> Result { - let mut pt = self.get(); - let page = Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); - let res = pt.ref_entry(page); - trace!("query: {:x?} => {:#x?}", vaddr, res); - match res { - Ok(entry) => Ok(entry.addr().as_usize()), - Err(_) => Err(HalError), - } - } - - /// Get the physical address of root page table. - #[export_name = "hal_pt_table_phys"] - fn table_phys(&self) -> PhysAddr { - self.root_paddr - } - - /// Activate this page table - #[export_name = "hal_pt_activate"] - fn activate(&self) { - let now_token = satp::read().bits(); - let new_token = self.table_phys(); - if now_token != new_token { - debug!("switch table {:x?} -> {:x?}", now_token, new_token); - unsafe { - set_page_table(new_token); - } - } - } -} - -pub unsafe fn set_page_table(vmtoken: usize) { - #[cfg(target_arch = "riscv32")] - let mode = satp::Mode::Sv32; - #[cfg(target_arch = "riscv64")] - let mode = satp::Mode::Sv39; - debug!("set user table: {:#x?}", vmtoken); - satp::set(mode, 0, vmtoken >> 12); - //刷TLB好像很重要 - sfence_vma_all(); -} - -trait FlagsExt { - fn to_ptf(self) -> PTF; -} - -impl FlagsExt for MMUFlags { - fn to_ptf(self) -> PTF { - let mut flags = PTF::VALID; - if self.contains(MMUFlags::READ) { - flags |= PTF::READABLE; - } - if self.contains(MMUFlags::WRITE) { - flags |= PTF::WRITABLE; - } - if self.contains(MMUFlags::EXECUTE) { - flags |= PTF::EXECUTABLE; - } - if self.contains(MMUFlags::USER) { - flags |= PTF::USER; - } - flags - } -} - -struct FrameAllocatorImpl; - -impl FrameAllocator for FrameAllocatorImpl { - fn alloc(&mut self) -> Option { - Frame::alloc().map(|f| { - let paddr = riscv::addr::PhysAddr::new(f.paddr); - riscv::addr::Frame::of_addr(paddr) - }) - } -} - -impl FrameDeallocator for FrameAllocatorImpl { - fn dealloc(&mut self, frame: riscv::addr::Frame) { - Frame { - paddr: frame.start_address().as_usize(), - } - .dealloc() - } -} - -lazy_static! { - static ref STDIN: Mutex> = Mutex::new(VecDeque::new()); - static ref STDIN_CALLBACK: Mutex bool + Send + Sync>>> = - Mutex::new(Vec::new()); -} - -//调用这里 -/// Put a char by serial interrupt handler. -fn serial_put(mut x: u8) { - if (x == b'\r') || (x == b'\n') { - STDIN.lock().push_back(b'\n'); - STDIN.lock().push_back(b'\r'); - }else{ - STDIN.lock().push_back(x); - } - STDIN_CALLBACK.lock().retain(|f| !f()); -} - -#[export_name = "hal_serial_set_callback"] -pub fn serial_set_callback(callback: Box bool + Send + Sync>) { - STDIN_CALLBACK.lock().push(callback); -} - -#[export_name = "hal_serial_read"] -pub fn serial_read(buf: &mut [u8]) -> usize { - let mut stdin = STDIN.lock(); - let len = stdin.len().min(buf.len()); - for c in &mut buf[..len] { - *c = stdin.pop_front().unwrap(); - } - len -} - -#[export_name = "hal_serial_write"] -pub fn print_str(s: &str) { - //putfmt(format_args!("{}", s)); - putfmt_uart(format_args!("{}", s)); -} - -// Get TSC frequency. -fn tsc_frequency() -> u16 { - const DEFAULT: u16 = 2600; - - // FIXME: QEMU, AMD, VirtualBox - DEFAULT -} - -#[export_name = "hal_apic_local_id"] -pub fn apic_local_id() -> u8 { - let lapic = 0; - lapic as u8 -} - -//////////// - -pub fn getchar_option() -> Option { - let c = sbi::console_getchar() as isize; - match c { - -1 => None, - c => Some(c as u8), - } -} - -//////////// - -pub fn putchar(ch: char) { - sbi::console_putchar(ch as u8 as usize); -} - -pub fn puts(s: &str) { - for ch in s.chars() { - putchar(ch); - } -} - -struct Stdout; - -impl fmt::Write for Stdout { - fn write_str(&mut self, s: &str) -> fmt::Result { - puts(s); - Ok(()) - } -} - -pub fn putfmt(fmt: fmt::Arguments) { - Stdout.write_fmt(fmt).unwrap(); -} -//////////// - -struct Stdout1; -impl fmt::Write for Stdout1 { - fn write_str(&mut self, s: &str) -> fmt::Result { - //每次都创建一个新的Uart ? 内存位置始终相同 - write!( - uart::Uart::new(phys_to_virt(UART_BASE)), - "{}", s - ).unwrap(); - - Ok(()) - } -} -pub fn putfmt_uart(fmt: fmt::Arguments) { - Stdout1.write_fmt(fmt).unwrap(); -} - -//////////// - -#[macro_export] -macro_rules! bare_print { - ($($arg:tt)*) => ({ - putfmt(format_args!($($arg)*)); - }); -} - -#[macro_export] -macro_rules! bare_println { - () => (bare_print!("\n")); - ($($arg:tt)*) => (bare_print!("{}\n", format_args!($($arg)*))); -} - -fn get_cycle() -> u64 { - time::read() as u64 - /* - unsafe { - MMIO_MTIME.read_volatile() - } - */ -} - -#[export_name = "hal_timer_now"] -pub fn timer_now() -> Duration { - const FREQUENCY: u64 = 10_000_000; // ??? - let time = get_cycle(); - //bare_println!("timer_now(): {:?}", time); - Duration::from_nanos(time * 1_000_000_000 / FREQUENCY as u64) -} - -#[export_name = "hal_timer_set_next"] -fn timer_set_next() { - //let TIMEBASE: u64 = 100000; - let TIMEBASE: u64 = 10_000_000; - sbi::set_timer(get_cycle() + TIMEBASE); -} - -fn timer_init() { - unsafe { - sie::set_stimer(); - } - timer_set_next(); -} - -pub fn init(config: Config) { - interrupt::init(); - timer_init(); - - /* - interrupt::init_soft(); - sbi::send_ipi(0); - */ - - unsafe { - llvm_asm!("ebreak"::::"volatile"); - } - - #[cfg(feature = "board_qemu")] - { - bare_println!("Setup virtio @devicetree {:#x}", config.dtb); - drivers::virtio::device_tree::init(config.dtb); - } -} - -pub struct Config { - pub mconfig: u64, - pub dtb: usize, -} - -#[export_name = "fetch_fault_vaddr"] -pub fn fetch_fault_vaddr() -> VirtAddr { - stval::read() as _ -} - -static mut CONFIG: Config = Config { mconfig: 0, dtb: 0 }; - /// This structure represents the information that the bootloader passes to the kernel. #[repr(C)] #[derive(Debug)] @@ -588,55 +57,28 @@ pub struct BootInfo { pub cmdline: &'static str, } -/// Graphic output information -#[derive(Debug, Copy, Clone)] -#[repr(C)] -pub struct GraphicInfo { - /// Graphic mode - //pub mode: ModeInfo, - pub mode: u64, - /// Framebuffer base physical address - pub fb_addr: u64, - /// Framebuffer size - pub fb_size: u64, +pub struct HalConfig { + pub mconfig: u64, + pub dtb: usize, } -pub mod interrupt; -mod plic; -mod uart; +pub fn init(config: HalConfig) { + trace!("hal dtb: {:#x}", config.dtb); -#[export_name = "hal_current_pgtable"] -pub fn current_page_table() -> usize { - #[cfg(target_arch = "riscv32")] - let mode = satp::Mode::Sv32; - #[cfg(target_arch = "riscv64")] - let mode = satp::Mode::Sv39; - satp::read().ppn() << 12 -} + interrupt::init(); + timer::init(); -pub fn init_framebuffer(width: u32, height: u32, addr: usize, size: usize) { - let fb_info = FramebufferInfo { - xres: width, - yres: height, - xres_virtual: width, - yres_virtual: height, - xoffset: 0, - yoffset: 0, - depth: ColorDepth::ColorDepth32, - format: ColorFormat::RGBA8888, - paddr: virt_to_phys(addr), - vaddr: addr, - screen_size: size, - }; - *FRAME_BUFFER.write() = Some(fb_info); -} + /* + interrupt::init_soft(); + sbi::send_ipi(0); + */ -#[export_name = "hal_mouse_set_callback"] -pub fn mouse_set_callback(_callback: Box) { - // -} + unsafe { asm!("ebreak") }; -#[export_name = "hal_kbd_set_callback"] -pub fn kbd_set_callback(_callback: Box) { - // + #[cfg(feature = "board_qemu")] + { + // TODO + // sbi_println!("Setup virtio @devicetree {:#x}", config.dtb); + // drivers::virtio::device_tree::init(config.dtb); + } } diff --git a/kernel-hal/src/bare/arch/riscv/plic.rs b/kernel-hal/src/bare/arch/riscv/plic.rs index f97675a8..f7fb03d5 100644 --- a/kernel-hal/src/bare/arch/riscv/plic.rs +++ b/kernel-hal/src/bare/arch/riscv/plic.rs @@ -1,6 +1,4 @@ -use super::interrupt; -use super::uart; -use crate::{putfmt, phys_to_virt}; +use super::super::mem::phys_to_virt; use super::consts::*; //通过MMIO地址对平台级中断控制器PLIC的寄存器进行设置 @@ -10,7 +8,7 @@ use super::consts::*; //声明claim会清除中断源上的相应pending位。 //即使mip寄存器的MEIP位没有置位, 也可以claim; 声明不被阀值寄存器的设置影响; //获取按优先级排序后的下一个可用的中断ID -pub fn next() -> Option { +fn next() -> Option { let claim_reg = phys_to_virt(PLIC_CLAIM) as *const u32; let claim_no; unsafe { @@ -26,7 +24,7 @@ pub fn next() -> Option { //claim时,PLIC不再从该相同设备监听中断 //写claim寄存器,告诉PLIC处理完成该中断 // id 应该来源于next()函数 -pub fn complete(id: u32) { +fn complete(id: u32) { let complete_reg = phys_to_virt(PLIC_CLAIM) as *mut u32; //和claim相同寄存器,只是读或写的区别 unsafe { complete_reg.write_volatile(id); @@ -46,7 +44,7 @@ pub fn is_pending(id: u32) -> bool { //使能target中某个给定ID的中断 //中断ID可查找qemu/include/hw/riscv/virt.h, 如:UART0_IRQ = 10 -pub fn enable(id: u32) { +fn enable(id: u32) { let enables = phys_to_virt(PLIC_INT_ENABLE) as *mut u32; //32位的寄存器 let actual_id = 1 << id; unsafe { @@ -56,7 +54,7 @@ pub fn enable(id: u32) { } //设置中断源的优先级,分0~7级,7是最高级, eg:这里id=10, 表示第10个中断源的设置, prio=1 -pub fn set_priority(id: u32, prio: u8) { +fn set_priority(id: u32, prio: u8) { let actual_prio = prio as u32 & 7; let prio_reg = phys_to_virt(PLIC_PRIORITY) as *mut u32; unsafe { @@ -65,7 +63,7 @@ pub fn set_priority(id: u32, prio: u8) { } //设置中断target的全局阀值[0..7], <= threshold会被屏蔽 -pub fn set_threshold(tsh: u8) { +fn set_threshold(tsh: u8) { let actual_tsh = tsh & 7; //使用0b111保留最后三位 let tsh_reg = phys_to_virt(PLIC_THRESHOLD) as *mut u32; unsafe { @@ -73,22 +71,30 @@ pub fn set_threshold(tsh: u8) { } } -pub fn handle_interrupt() { +pub(super) fn init() { + // Qemu virt UART0 = 10 + // ALLWINNER D1 UART0 = 18 + set_priority(UART0_INT_NUM, 7); + set_threshold(0); + enable(UART0_INT_NUM); +} + +pub(super) fn handle_interrupt() { if let Some(interrupt) = next() { match interrupt { 1..=8 => { //virtio::handle_interrupt(interrupt); - bare_println!("plic virtio external interrupt: {}", interrupt); + sbi_println!("plic virtio external interrupt: {}", interrupt); } UART0_INT_NUM => { //UART中断ID是10 - uart::handle_interrupt(); + super::uart::handle_interrupt(); //换用sbi的方式获取字符 //interrupt::try_process_serial(); } _ => { - bare_println!("Unknown external interrupt: {}", interrupt); + sbi_println!("Unknown external interrupt: {}", interrupt); } } //这将复位pending的中断,允许UART再次中断。 diff --git a/kernel-hal/src/bare/arch/riscv/sbi.rs b/kernel-hal/src/bare/arch/riscv/sbi.rs index 67ce257e..5c551833 100644 --- a/kernel-hal/src/bare/arch/riscv/sbi.rs +++ b/kernel-hal/src/bare/arch/riscv/sbi.rs @@ -1,3 +1,28 @@ +const SBI_SET_TIMER: usize = 0; +const SBI_CONSOLE_PUTCHAR: usize = 1; +const SBI_CONSOLE_GETCHAR: usize = 2; +const SBI_CLEAR_IPI: usize = 3; +const SBI_SEND_IPI: usize = 4; +const SBI_REMOTE_FENCE_I: usize = 5; +const SBI_REMOTE_SFENCE_VMA: usize = 6; +const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7; +const SBI_SHUTDOWN: usize = 8; + +#[inline(always)] +fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { + let ret; + unsafe { + asm!("ecall", + in("a0") arg0, + in("a1") arg1, + in("a2") arg2, + in("a7") which, + lateout("a0") ret, + ); + } + ret +} + pub fn console_putchar(ch: usize) { sbi_call(SBI_CONSOLE_PUTCHAR, ch, 0, 0); } @@ -6,18 +31,6 @@ pub fn console_getchar() -> usize { return sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0); } -fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { - let ret: usize; - unsafe { - llvm_asm!("ecall" - :"={x10}"(ret) - :"{x10}"(arg0), "{x11}"(arg1), "{x12}"(arg2), "{x17}"(which) - :"memory" - :"volatile"); - } - ret -} - pub fn set_timer(stime_value: u64) { #[cfg(target_pointer_width = "32")] sbi_call(SBI_SET_TIMER, stime_value as usize, (stime_value >> 32), 0); @@ -33,13 +46,3 @@ pub fn clear_ipi() { pub fn send_ipi(sipi_value: usize) { sbi_call(SBI_SEND_IPI, sipi_value, 0, 0); } - -const SBI_SET_TIMER: usize = 0; -const SBI_CONSOLE_PUTCHAR: usize = 1; -const SBI_CONSOLE_GETCHAR: usize = 2; -const SBI_CLEAR_IPI: usize = 3; -const SBI_SEND_IPI: usize = 4; -const SBI_REMOTE_FENCE_I: usize = 5; -const SBI_REMOTE_SFENCE_VMA: usize = 6; -const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7; -const SBI_SHUTDOWN: usize = 8; diff --git a/kernel-hal/src/bare/arch/riscv/serial.rs b/kernel-hal/src/bare/arch/riscv/serial.rs new file mode 100644 index 00000000..c072f83f --- /dev/null +++ b/kernel-hal/src/bare/arch/riscv/serial.rs @@ -0,0 +1,85 @@ +use alloc::{boxed::Box, collections::VecDeque, vec::Vec}; +use core::fmt::{Arguments, Result, Write}; + +use spin::Mutex; + +use super::{sbi, uart}; + +lazy_static::lazy_static! { + static ref STDIN: Mutex> = Mutex::new(VecDeque::new()); + static ref STDIN_CALLBACK: Mutex bool + Send + Sync>>> = + Mutex::new(Vec::new()); +} + +struct SbiConsole; +struct UartConsole; + +impl Write for SbiConsole { + fn write_str(&mut self, s: &str) -> Result { + for ch in s.chars() { + sbi::console_putchar(ch as u8 as usize); + } + Ok(()) + } +} + +impl Write for UartConsole { + fn write_str(&mut self, s: &str) -> Result { + if let Some(ref mut uart) = uart::UART.lock().get_mut() { + //每次都创建一个新的Uart ? 内存位置始终相同 + write!(uart, "{}", s) + } else { + SbiConsole.write_str(s) + } + } +} + +pub(super) fn sbi_print_fmt(fmt: Arguments) { + SbiConsole.write_fmt(fmt).unwrap(); +} + +pub(super) fn uart_print_fmt(fmt: Arguments) { + UartConsole.write_fmt(fmt).unwrap(); +} + +hal_fn_impl! { + impl mod crate::defs::serial { + fn serial_put(x: u8) { + if (x == b'\r') || (x == b'\n') { + STDIN.lock().push_back(b'\n'); + STDIN.lock().push_back(b'\r'); + }else{ + STDIN.lock().push_back(x); + } + STDIN_CALLBACK.lock().retain(|f| !f()); + } + + fn serial_set_callback(callback: Box bool + Send + Sync>) { + STDIN_CALLBACK.lock().push(callback); + } + + fn serial_read(buf: &mut [u8]) -> usize { + let mut stdin = STDIN.lock(); + let len = stdin.len().min(buf.len()); + for c in &mut buf[..len] { + *c = stdin.pop_front().unwrap(); + } + len + } + + fn serial_write_fmt(fmt: Arguments) { + uart_print_fmt(fmt); + } + } +} + +macro_rules! sbi_print { + ($($arg:tt)*) => ({ + crate::serial::sbi_print_fmt(format_args!($($arg)*)); + }); +} + +macro_rules! sbi_println { + () => (sbi_print!("\n")); + ($($arg:tt)*) => (sbi_print!("{}\n", format_args!($($arg)*))); +} diff --git a/kernel-hal/src/bare/arch/riscv/special.rs b/kernel-hal/src/bare/arch/riscv/special.rs new file mode 100644 index 00000000..26549ac7 --- /dev/null +++ b/kernel-hal/src/bare/arch/riscv/special.rs @@ -0,0 +1,11 @@ +pub fn wait_for_interrupt() { + unsafe { + // enable interrupt and disable + let sie = riscv::register::sstatus::read().sie(); + riscv::register::sstatus::set_sie(); + riscv::asm::wfi(); + if !sie { + riscv::register::sstatus::clear_sie(); + } + } +} diff --git a/kernel-hal/src/bare/arch/riscv/timer.rs b/kernel-hal/src/bare/arch/riscv/timer.rs new file mode 100644 index 00000000..a4a63f56 --- /dev/null +++ b/kernel-hal/src/bare/arch/riscv/timer.rs @@ -0,0 +1,29 @@ +use core::time::Duration; +use riscv::register::{sie, time}; + +fn get_cycle() -> u64 { + time::read() as u64 + /* + unsafe { + MMIO_MTIME.read_volatile() + } + */ +} + +pub(super) fn timer_set_next() { + //let TIMEBASE: u64 = 100000; + const TIMEBASE: u64 = 10_000_000; + super::sbi::set_timer(get_cycle() + TIMEBASE); +} + +pub fn timer_now() -> Duration { + const FREQUENCY: u64 = 10_000_000; // ??? + let time = get_cycle(); + //bare_println!("timer_now(): {:?}", time); + Duration::from_nanos(time * 1_000_000_000 / FREQUENCY as u64) +} + +pub(super) fn init() { + unsafe { sie::set_stimer() }; + timer_set_next(); +} diff --git a/kernel-hal/src/bare/arch/riscv/trap.rs b/kernel-hal/src/bare/arch/riscv/trap.rs new file mode 100644 index 00000000..30343494 --- /dev/null +++ b/kernel-hal/src/bare/arch/riscv/trap.rs @@ -0,0 +1,119 @@ +use riscv::register::scause::{self, Exception, Interrupt, Trap}; +use riscv::register::{satp, stval}; +use trapframe::TrapFrame; + +use super::{consts, plic, sbi}; + +fn breakpoint(sepc: &mut usize) { + sbi_println!("Exception::Breakpoint: A breakpoint set @0x{:x} ", sepc); + + //sepc为触发中断指令ebreak的地址 + //防止无限循环中断,让sret返回时跳转到sepc的下一条指令地址 + *sepc += 2 +} + +pub(super) fn super_timer() { + super::timer::timer_set_next(); + crate::timer::timer_tick(); + + //sbi_print!("."); + + //发生外界中断时,epc的指令还没有执行,故无需修改epc到下一条 +} + +fn super_soft() { + sbi::clear_ipi(); + sbi_println!("Interrupt::SupervisorSoft!"); +} + +fn page_fault(stval: usize, tf: &mut TrapFrame) { + let this_scause = scause::read(); + info!( + "EXCEPTION Page Fault: {:?} @ {:#x}->{:#x}", + this_scause.cause(), + tf.sepc, + stval + ); + let vaddr = stval; + + use crate::vm::{PageTable, PageTableTrait}; + use crate::MMUFlags; + use riscv::addr::{Page, VirtAddr}; + use riscv::paging::{Mapper, PageTableEntry as PTE}; + + //let mut flags = PTF::VALID; + let code = this_scause.code(); + let flags = if code == 15 { + //MMUFlags::WRITE ??? + MMUFlags::READ | MMUFlags::WRITE + } else if code == 12 { + MMUFlags::EXECUTE + } else { + MMUFlags::READ + }; + + let linear_offset = if stval >= consts::PHYSICAL_MEMORY_OFFSET { + // Kernel + consts::PHYSICAL_MEMORY_OFFSET + } else { + // User + 0 + }; + + /* + let current = + unsafe { &mut *(phys_to_virt(satp::read().frame().start_address().as_usize()) as *mut PageTable) }; + let mut pt = Rv39PageTable::new(current, PHYSICAL_MEMORY_OFFSET); + map_range(&mut pt, vaddr, vaddr, linear_offset, flags); + */ + + let mut pti = PageTable { + root_paddr: satp::read().frame().start_address().as_usize(), + }; + + let page = Page::of_addr(VirtAddr::new(vaddr)); + if let Ok(pte) = pti.get().ref_entry(page) { + let pte = unsafe { &mut *(pte as *mut PTE) }; + if !pte.is_unused() { + debug!( + "PageAlreadyMapped -> {:#x?}, {:?}", + pte.addr().as_usize(), + pte.flags() + ); + //TODO update flags + + pti.unmap(vaddr).unwrap(); + } + }; + pti.map(vaddr, vaddr - linear_offset, flags).unwrap(); +} + +#[no_mangle] +pub extern "C" fn trap_handler(tf: &mut TrapFrame) { + let sepc = tf.sepc; + let scause = scause::read(); + let stval = stval::read(); + let is_int = scause.bits() >> 63; + let code = scause.bits() & !(1 << 63); + + match scause.cause() { + Trap::Exception(Exception::Breakpoint) => breakpoint(&mut tf.sepc), + Trap::Exception(Exception::IllegalInstruction) => { + panic!("IllegalInstruction: {:#x}->{:#x}", sepc, stval) + } + Trap::Exception(Exception::LoadFault) => { + panic!("Load access fault: {:#x}->{:#x}", sepc, stval) + } + Trap::Exception(Exception::StoreFault) => { + panic!("Store access fault: {:#x}->{:#x}", sepc, stval) + } + Trap::Exception(Exception::LoadPageFault) => page_fault(stval, tf), + Trap::Exception(Exception::StorePageFault) => page_fault(stval, tf), + Trap::Exception(Exception::InstructionPageFault) => page_fault(stval, tf), + Trap::Interrupt(Interrupt::SupervisorTimer) => super_timer(), + Trap::Interrupt(Interrupt::SupervisorSoft) => super_soft(), + Trap::Interrupt(Interrupt::SupervisorExternal) => plic::handle_interrupt(), + //Trap::Interrupt(Interrupt::SupervisorExternal) => irq_handle(code as u8), + _ => panic!("Undefined Trap: {:#x} {:#x}", is_int, code), + } +} diff --git a/kernel-hal/src/bare/arch/riscv/uart.rs b/kernel-hal/src/bare/arch/riscv/uart.rs index ce714af2..36fc15e7 100644 --- a/kernel-hal/src/bare/arch/riscv/uart.rs +++ b/kernel-hal/src/bare/arch/riscv/uart.rs @@ -1,15 +1,18 @@ -use super::consts::UART_BASE; -use crate::{putfmt, phys_to_virt}; -use core::convert::TryInto; use core::fmt::{Error, Write}; +use spin::{Mutex, Once}; -pub struct Uart { - base_address: usize, +use super::super::mem::phys_to_virt; +use crate::{PhysAddr, VirtAddr}; + +pub(super) struct Uart { + base_address: VirtAddr, } +pub(super) static UART: Mutex> = Mutex::new(Once::new()); + // 结构体Uart的实现块 impl Uart { - pub fn new(base_address: usize) -> Self { + pub fn new(base_address: VirtAddr) -> Self { Uart { base_address } } @@ -81,26 +84,35 @@ impl Write for Uart { } } -pub fn handle_interrupt() { - let mut my_uart = Uart::new(phys_to_virt(UART_BASE)); - if let Some(c) = my_uart.get() { - let c = c & 0xff; - //CONSOLE - super::serial_put(c); +pub(super) fn handle_interrupt() { + if let Some(ref mut uart) = UART.lock().get_mut() { + if let Some(c) = uart.get() { + let c = c & 0xff; + //CONSOLE + crate::serial::serial_put(c); - /* - * 因serial_write()已可以被回调输出了,这里则不再需要了 - match c { - 0x7f => { //0x8 [backspace] ; 而实际qemu运行,[backspace]键输出0x7f, 表示del - bare_print!("{} {}", 8 as char, 8 as char); - }, - 10 | 13 => { // 新行或回车 - bare_println!(); - }, - _ => { - bare_print!("{}", c as char); - }, + /* + * 因serial_write()已可以被回调输出了,这里则不再需要了 + match c { + 0x7f => { //0x8 [backspace] ; 而实际qemu运行,[backspace]键输出0x7f, 表示del + bare_print!("{} {}", 8 as char, 8 as char); + }, + 10 | 13 => { // 新行或回车 + bare_println!(); + }, + _ => { + bare_print!("{}", c as char); + }, + } + */ } - */ } } + +pub(super) fn init(base_paddr: PhysAddr) { + UART.lock().call_once(|| { + let mut uart = Uart::new(phys_to_virt(base_paddr)); + uart.simple_init(); + uart + }); +} diff --git a/kernel-hal/src/bare/arch/riscv/vm.rs b/kernel-hal/src/bare/arch/riscv/vm.rs new file mode 100644 index 00000000..184bc2ae --- /dev/null +++ b/kernel-hal/src/bare/arch/riscv/vm.rs @@ -0,0 +1,382 @@ +use riscv::{ + addr::Page, + asm::sfence_vma_all, + paging::{ + FrameAllocator, FrameDeallocator, Mapper, PageTable as PT, PageTableFlags as PTF, + Rv39PageTable, + }, + register::satp, +}; + +use super::super::{ffi, mem::phys_to_virt}; +use super::consts; +use crate::{HalError, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE}; + +pub use crate::common::vm::*; + +// First core stores its SATP here. +static mut SATP: usize = 0; + +pub(crate) unsafe fn set_page_table(vmtoken: usize) { + #[cfg(target_arch = "riscv32")] + let mode = satp::Mode::Sv32; + #[cfg(target_arch = "riscv64")] + let mode = satp::Mode::Sv39; + debug!("set user table: {:#x?}", vmtoken); + satp::set(mode, 0, vmtoken >> 12); + //刷TLB好像很重要 + sfence_vma_all(); +} + +fn map_range( + page_table: &mut Rv39PageTable, + mut start_addr: VirtAddr, + mut end_addr: VirtAddr, + linear_offset: usize, + flags: PTF, +) -> Result<(), ()> { + trace!("Mapping range addr: {:#x} ~ {:#x}", start_addr, end_addr); + + start_addr = start_addr & !(PAGE_SIZE - 1); + let mut start_page = start_addr / PAGE_SIZE; + + //end_addr = (end_addr + PAGE_SIZE - 1) & !(PAGE_SIZE -1); + //let end_page = (end_addr - 1) / PAGE_SIZE; + end_addr = end_addr & !(PAGE_SIZE - 1); + let end_page = end_addr / PAGE_SIZE; + + while start_page <= end_page { + let vaddr: VirtAddr = start_page * PAGE_SIZE; + let page = riscv::addr::Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); + let frame = riscv::addr::Frame::of_addr(riscv::addr::PhysAddr::new(vaddr - linear_offset)); + + start_page += 1; + + trace!( + "map_range: {:#x} -> {:#x}, flags={:?}", + vaddr, + vaddr - linear_offset, + flags + ); + page_table + .map_to(page, frame, flags, &mut FrameAllocatorImpl) + .unwrap() + .flush(); + } + info!( + "map range from {:#x} to {:#x}, flags: {:?}", + start_addr, + end_page * PAGE_SIZE, + flags + ); + + Ok(()) +} + +/// remap kernel with 4K page +pub fn remap_the_kernel(dtb: usize) { + extern "C" { + fn start(); + + fn stext(); + fn etext(); + fn srodata(); + fn erodata(); + fn sdata(); + fn edata(); + + fn bootstack(); + fn bootstacktop(); + + fn sbss(); + fn ebss(); + + fn end(); + } + + let root_paddr = crate::mem::frame_alloc().expect("failed to alloc frame"); + let root_vaddr = phys_to_virt(root_paddr); + let root = unsafe { &mut *(root_vaddr as *mut PT) }; + root.zero(); + let mut pt = Rv39PageTable::new(root, consts::PHYSICAL_MEMORY_OFFSET); + + let linear_offset = consts::PHYSICAL_MEMORY_OFFSET; + //let mut flags = PTF::VALID | PTF::READABLE | PTF::WRITABLE | PTF::EXECUTABLE | PTF::USER; + + map_range( + &mut pt, + stext as usize, + etext as usize - 1, + linear_offset, + PTF::VALID | PTF::READABLE | PTF::EXECUTABLE, + ) + .unwrap(); + map_range( + &mut pt, + srodata as usize, + erodata as usize, + linear_offset, + PTF::VALID | PTF::READABLE, + ) + .unwrap(); + map_range( + &mut pt, + sdata as usize, + edata as usize, + linear_offset, + PTF::VALID | PTF::READABLE | PTF::WRITABLE, + ) + .unwrap(); + + // Stack + map_range( + &mut pt, + bootstack as usize, + bootstacktop as usize - 1, + linear_offset, + PTF::VALID | PTF::READABLE | PTF::WRITABLE, + ) + .unwrap(); + + map_range( + &mut pt, + sbss as usize, + ebss as usize - 1, + linear_offset, + PTF::VALID | PTF::READABLE | PTF::WRITABLE, + ) + .unwrap(); + + info!("map Heap ..."); + // Heap + map_range( + &mut pt, + end as usize, + end as usize + PAGE_SIZE * 5120, + linear_offset, + PTF::VALID | PTF::READABLE | PTF::WRITABLE, + ) + .unwrap(); + info!("... Heap"); + + // Device Tree + #[cfg(feature = "board_qemu")] + map_range( + &mut pt, + dtb, + dtb + consts::MAX_DTB_SIZE, + linear_offset, + PTF::VALID | PTF::READABLE, + ) + .unwrap(); + + // PLIC + map_range( + &mut pt, + phys_to_virt(consts::PLIC_PRIORITY), + phys_to_virt(consts::PLIC_PRIORITY) + PAGE_SIZE * 0xf, + linear_offset, + PTF::VALID | PTF::READABLE | PTF::WRITABLE, + ) + .unwrap(); + map_range( + &mut pt, + phys_to_virt(consts::PLIC_THRESHOLD), + phys_to_virt(consts::PLIC_THRESHOLD) + PAGE_SIZE * 0xf, + linear_offset, + PTF::VALID | PTF::READABLE | PTF::WRITABLE, + ) + .unwrap(); + + // UART0, VIRTIO + map_range( + &mut pt, + phys_to_virt(consts::UART_BASE), + phys_to_virt(consts::UART_BASE) + PAGE_SIZE * 0xf, + linear_offset, + PTF::VALID | PTF::READABLE | PTF::WRITABLE, + ) + .unwrap(); + + //写satp + let token = root_paddr; + unsafe { + set_page_table(token); + SATP = token; + } + + //use core::mem; + //mem::forget(pt); + + info!("remap the kernel @ {:#x}", token); +} + +/// Page Table +#[repr(C)] +pub struct PageTable { + pub(super) root_paddr: PhysAddr, +} + +impl PageTable { + /// Create a new `PageTable`. + #[allow(clippy::new_without_default)] + #[export_name = "hal_pt_new"] + pub fn new() -> Self { + let root_paddr = crate::mem::frame_alloc().expect("failed to alloc frame"); + let root_vaddr = phys_to_virt(root_paddr); + let root = unsafe { &mut *(root_vaddr as *mut PT) }; + root.zero(); + + let current = phys_to_virt(satp::read().frame().start_address().as_usize()) as *const PT; + unsafe { ffi::hal_pt_map_kernel(root_vaddr as _, current as _) }; + trace!("create page table @ {:#x}", root_paddr); + PageTable { root_paddr } + } + + pub fn current() -> Self { + #[cfg(target_arch = "riscv32")] + let _mode = satp::Mode::Sv32; + #[cfg(target_arch = "riscv64")] + let _mode = satp::Mode::Sv39; + let root_paddr = satp::read().ppn() << 12; + PageTable { root_paddr } + } + + #[cfg(target_arch = "riscv32")] + pub(super) fn get(&mut self) -> Rv32PageTable<'_> { + let root_vaddr = phys_to_virt(self.root_paddr); + let root = unsafe { &mut *(root_vaddr as *mut PT) }; + Rv32PageTable::new(root, phys_to_virt(0)) + } + + #[cfg(target_arch = "riscv64")] + pub(super) fn get(&mut self) -> Rv39PageTable<'_> { + let root_vaddr = phys_to_virt(self.root_paddr); + let root = unsafe { &mut *(root_vaddr as *mut PT) }; + Rv39PageTable::new(root, phys_to_virt(0)) + } +} + +impl PageTableTrait for PageTable { + /// Map the page of `vaddr` to the frame of `paddr` with `flags`. + #[export_name = "hal_pt_map"] + fn map(&mut self, vaddr: VirtAddr, paddr: PhysAddr, flags: MMUFlags) -> Result<(), HalError> { + let mut pt = self.get(); + let page = Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); + let frame = riscv::addr::Frame::of_addr(riscv::addr::PhysAddr::new(paddr)); + pt.map_to(page, frame, flags.to_ptf(), &mut FrameAllocatorImpl) + .unwrap() + .flush(); + + trace!( + "PageTable: {:#X}, map: {:x?} -> {:x?}, flags={:?}", + self.table_phys() as usize, + vaddr, + paddr, + flags + ); + Ok(()) + } + + /// Unmap the page of `vaddr`. + #[export_name = "hal_pt_unmap"] + fn unmap(&mut self, vaddr: VirtAddr) -> Result<(), HalError> { + let mut pt = self.get(); + let page = Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); + pt.unmap(page).unwrap().1.flush(); + trace!( + "PageTable: {:#X}, unmap: {:x?}", + self.table_phys() as usize, + vaddr + ); + Ok(()) + } + + /// Change the `flags` of the page of `vaddr`. + #[export_name = "hal_pt_protect"] + fn protect(&mut self, vaddr: VirtAddr, flags: MMUFlags) -> Result<(), HalError> { + let mut pt = self.get(); + let page = Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); + pt.update_flags(page, flags.to_ptf()).unwrap().flush(); + + trace!( + "PageTable: {:#X}, protect: {:x?}, flags={:?}", + self.table_phys() as usize, + vaddr, + flags + ); + Ok(()) + } + + /// Query the physical address which the page of `vaddr` maps to. + #[export_name = "hal_pt_query"] + fn query(&mut self, vaddr: VirtAddr) -> Result { + let mut pt = self.get(); + let page = Page::of_addr(riscv::addr::VirtAddr::new(vaddr)); + let res = pt.ref_entry(page); + trace!("query: {:x?} => {:#x?}", vaddr, res); + match res { + Ok(entry) => Ok(entry.addr().as_usize()), + Err(_) => Err(HalError), + } + } + + /// Get the physical address of root page table. + #[export_name = "hal_pt_table_phys"] + fn table_phys(&self) -> PhysAddr { + self.root_paddr + } + + /// Activate this page table + #[export_name = "hal_pt_activate"] + fn activate(&self) { + let now_token = satp::read().bits(); + let new_token = self.table_phys(); + if now_token != new_token { + debug!("switch table {:x?} -> {:x?}", now_token, new_token); + unsafe { + set_page_table(new_token); + } + } + } +} + +trait FlagsExt { + fn to_ptf(self) -> PTF; +} + +impl FlagsExt for MMUFlags { + fn to_ptf(self) -> PTF { + let mut flags = PTF::VALID; + if self.contains(MMUFlags::READ) { + flags |= PTF::READABLE; + } + if self.contains(MMUFlags::WRITE) { + flags |= PTF::WRITABLE; + } + if self.contains(MMUFlags::EXECUTE) { + flags |= PTF::EXECUTABLE; + } + if self.contains(MMUFlags::USER) { + flags |= PTF::USER; + } + flags + } +} + +struct FrameAllocatorImpl; + +impl FrameAllocator for FrameAllocatorImpl { + fn alloc(&mut self) -> Option { + crate::mem::frame_alloc().map(|f| { + let paddr = riscv::addr::PhysAddr::new(f); + riscv::addr::Frame::of_addr(paddr) + }) + } +} + +impl FrameDeallocator for FrameAllocatorImpl { + fn dealloc(&mut self, frame: riscv::addr::Frame) { + crate::mem::frame_dealloc(frame.start_address().as_usize()); + } +} diff --git a/kernel-hal/src/bare/arch/x86_64/interrupt.rs b/kernel-hal/src/bare/arch/x86_64/interrupt.rs index 1f9e4774..e4b7be52 100644 --- a/kernel-hal/src/bare/arch/x86_64/interrupt.rs +++ b/kernel-hal/src/bare/arch/x86_64/interrupt.rs @@ -151,6 +151,13 @@ fn irq_overwrite_handler(irq: u8, handler: Box) -> bool set } +fn init_irq_table() { + let mut table = IRQ_TABLE.lock(); + for _ in 0..TABLE_SIZE { + table.push(None); + } +} + hal_fn_impl! { impl mod crate::defs::interrupt { fn enable_irq(irq: u32) { @@ -337,13 +344,6 @@ fn keyboard() { } */ -fn init_irq_table() { - let mut table = IRQ_TABLE.lock(); - for _ in 0..TABLE_SIZE { - table.push(None); - } -} - fn irq_enable_raw(irq: u8, vector: u8) { info!("irq_enable_raw: irq={:#x?}, vector={:#x?}", irq, vector); let mut ioapic = super::apic::get_ioapic(); @@ -351,7 +351,7 @@ fn irq_enable_raw(irq: u8, vector: u8) { ioapic.enable(irq, 0) } -pub fn init() { +pub(super) fn init() { // MOUSE.lock().init().unwrap(); // MOUSE.lock().set_on_complete(mouse_on_complete); unsafe { diff --git a/kernel-hal/src/bare/arch/x86_64/serial.rs b/kernel-hal/src/bare/arch/x86_64/serial.rs index 766b5276..b3c587b1 100644 --- a/kernel-hal/src/bare/arch/x86_64/serial.rs +++ b/kernel-hal/src/bare/arch/x86_64/serial.rs @@ -37,7 +37,7 @@ hal_fn_impl! { len } - fn print_fmt(fmt: Arguments) { + fn serial_write_fmt(fmt: Arguments) { COM1.lock().write_fmt(fmt).unwrap(); // if let Some(console) = CONSOLE.lock().as_mut() { // console.write_fmt(fmt).unwrap(); diff --git a/kernel-hal/src/bare/arch/x86_64/vm.rs b/kernel-hal/src/bare/arch/x86_64/vm.rs index c5a7be5f..f4412b6a 100644 --- a/kernel-hal/src/bare/arch/x86_64/vm.rs +++ b/kernel-hal/src/bare/arch/x86_64/vm.rs @@ -3,7 +3,7 @@ use core::convert::TryFrom; use x86_64::{ registers::control::{Cr3, Cr3Flags}, structures::paging::{mapper, FrameAllocator, FrameDeallocator, Mapper, Translate}, - structures::paging::{OffsetPageTable, PageTable as X86PageTable, PageTableFlags as PTF}, + structures::paging::{OffsetPageTable, PageTable as PT, PageTableFlags as PTF}, structures::paging::{Page, PhysFrame, Size4KiB}, }; @@ -25,9 +25,9 @@ pub(crate) unsafe fn set_page_table(vmtoken: usize) { debug!("set page_table @ {:#x}", vmtoken); } -fn frame_to_page_table(frame: PhysFrame) -> *mut X86PageTable { +fn frame_to_page_table(frame: PhysFrame) -> *mut PT { let vaddr = phys_to_virt(frame.start_address().as_u64() as usize); - vaddr as *mut X86PageTable + vaddr as *mut PT } /// Page Table @@ -36,26 +36,26 @@ pub struct PageTable { } impl PageTable { - pub fn current() -> Self { - PageTable { - root_paddr: Cr3::read().0.start_address().as_u64() as _, - } - } - /// Create a new `PageTable`. pub fn new() -> Self { let root_paddr = crate::mem::frame_alloc().expect("failed to alloc frame"); let root_vaddr = phys_to_virt(root_paddr); - let root = unsafe { &mut *(root_vaddr as *mut X86PageTable) }; + let root = unsafe { &mut *(root_vaddr as *mut PT) }; root.zero(); unsafe { ffi::hal_pt_map_kernel(root_vaddr as _, frame_to_page_table(Cr3::read().0) as _) }; trace!("create page table @ {:#x}", root_paddr); PageTable { root_paddr } } + pub fn current() -> Self { + PageTable { + root_paddr: Cr3::read().0.start_address().as_u64() as _, + } + } + fn get(&mut self) -> OffsetPageTable<'_> { let root_vaddr = phys_to_virt(self.root_paddr); - let root = unsafe { &mut *(root_vaddr as *mut X86PageTable) }; + let root = unsafe { &mut *(root_vaddr as *mut PT) }; let offset = x86_64::VirtAddr::new(phys_to_virt(0) as u64); unsafe { OffsetPageTable::new(root, offset) } } diff --git a/kernel-hal/src/bare/mod.rs b/kernel-hal/src/bare/mod.rs index e9dcbd00..78a3ec66 100644 --- a/kernel-hal/src/bare/mod.rs +++ b/kernel-hal/src/bare/mod.rs @@ -6,7 +6,7 @@ cfg_if::cfg_if! { mod arch; pub use self::arch::special as x86_64; } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { - #[path = "arch/x86_64/mod.rs"] + #[path = "arch/riscv/mod.rs"] mod arch; pub use self::arch::special as riscv; } @@ -22,16 +22,14 @@ hal_fn_impl_default!(rand, vdso, dev::fb, dev::input); pub use self::arch::{context, cpu, interrupt, serial, vm, HalConfig}; +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] +pub use self::arch::{BootInfo, GraphicInfo}; + /// Initialize the HAL. /// /// This function must be called at the beginning. pub fn init(config: HalConfig) { - unsafe { - trapframe::init(); - } - - #[cfg(target_arch = "riscv64")] - trace!("hal dtb: {:#x}", config.dtb); + unsafe { trapframe::init() }; self::arch::init(config); } diff --git a/kernel-hal/src/defs.rs b/kernel-hal/src/defs.rs index d82fcf18..df02876e 100644 --- a/kernel-hal/src/defs.rs +++ b/kernel-hal/src/defs.rs @@ -121,12 +121,12 @@ hal_fn_def! { /// Read a string from serial buffer. fn serial_read(buf: &mut [u8]) -> usize; - /// Print format string and its arguments to console. - fn print_fmt(fmt: Arguments); + /// Print format string and its arguments to serial. + fn serial_write_fmt(fmt: Arguments); - /// Print a string to console. - fn print_str(s: &str) { - print_fmt(format_args!("{}", s)); + /// Print a string to serial. + fn serial_write(s: &str) { + serial_write_fmt(format_args!("{}", s)); } } diff --git a/kernel-hal/src/libos/serial.rs b/kernel-hal/src/libos/serial.rs index 772a6795..43d69a70 100644 --- a/kernel-hal/src/libos/serial.rs +++ b/kernel-hal/src/libos/serial.rs @@ -27,7 +27,7 @@ hal_fn_impl! { len } - fn print_fmt(fmt: core::fmt::Arguments) { + fn serial_write_fmt(fmt: core::fmt::Arguments) { eprint!("{}", fmt); } } diff --git a/linux-loader/src/lib.rs b/linux-loader/src/lib.rs index 607bd208..fc6559e5 100644 --- a/linux-loader/src/lib.rs +++ b/linux-loader/src/lib.rs @@ -122,7 +122,7 @@ async fn new_thread(thread: CurrentThread) { // UserContext #[cfg(target_arch = "riscv64")] { - let trap_num = kernel_hal::fetch_trap_num(&cx); + let trap_num = kernel_hal::context::fetch_trap_num(&cx); let is_interrupt = ((trap_num >> 63) & 1) == 1; let trap_num = trap_num & 0xfff; let pid = thread.proc().id(); diff --git a/linux-object/src/fs/stdio.rs b/linux-object/src/fs/stdio.rs index a80c3316..8a3af366 100644 --- a/linux-object/src/fs/stdio.rs +++ b/linux-object/src/fs/stdio.rs @@ -132,7 +132,7 @@ impl INode for Stdout { fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { // we do not care the utf-8 things, we just want to print it! let s = unsafe { core::str::from_utf8_unchecked(buf) }; - kernel_hal::serial::print_str(s); + kernel_hal::serial::serial_write(s); Ok(buf.len()) } fn poll(&self) -> Result { diff --git a/zCore/Cargo.toml b/zCore/Cargo.toml index 6a076541..07fb7f4a 100644 --- a/zCore/Cargo.toml +++ b/zCore/Cargo.toml @@ -8,8 +8,8 @@ edition = "2018" [features] graphic = [] -board_qemu = [] # "kernel-hal-bare/board_qemu"] -board_d1 = ["link_user_img"] #, "kernel-hal-bare/board_d1"] +board_qemu = ["link_user_img", "kernel-hal/board_qemu"] +board_d1 = ["link_user_img", "kernel-hal/board_d1"] link_user_img = [] zircon = ["zircon-loader"] linux = ["linux-loader", "linux-object", "rcore-fs-sfs"] diff --git a/zCore/src/arch/riscv/boot/kernel-vars.ld b/zCore/src/arch/riscv/boot/kernel-vars.ld new file mode 100644 index 00000000..d2a33136 --- /dev/null +++ b/zCore/src/arch/riscv/boot/kernel-vars.ld @@ -0,0 +1,2 @@ +/* Generated by build.rs. DO NOT EDIT. */ +PROVIDE_HIDDEN(BASE_ADDRESS = 0xffffffff80200000); diff --git a/zCore/src/logging.rs b/zCore/src/logging.rs index eee340bb..6a038a0c 100644 --- a/zCore/src/logging.rs +++ b/zCore/src/logging.rs @@ -37,12 +37,12 @@ macro_rules! with_color { } fn print_in_color(args: fmt::Arguments, color_code: u8) { - kernel_hal::serial::print_fmt(with_color!(args, color_code)); + kernel_hal::serial::serial_write_fmt(with_color!(args, color_code)); } #[allow(dead_code)] pub fn print(args: fmt::Arguments) { - kernel_hal::serial::print_fmt(args); + kernel_hal::serial::serial_write_fmt(args); } struct SimpleLogger; diff --git a/zCore/src/main.rs b/zCore/src/main.rs index cf171f45..b3a8dd7e 100644 --- a/zCore/src/main.rs +++ b/zCore/src/main.rs @@ -32,10 +32,7 @@ mod fs; use rboot::BootInfo; #[cfg(target_arch = "riscv64")] -use kernel_hal_bare::{ - drivers::virtio::{CMDLINE, GPU_DRIVERS}, - phys_to_virt, remap_the_kernel, BootInfo, GraphicInfo, -}; +use kernel_hal::{vm::remap_the_kernel, BootInfo, GraphicInfo}; use alloc::{ boxed::Box, @@ -103,7 +100,7 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { "zCore rust_main( hartid: {}, device_tree_paddr: {:#x} )", hartid, device_tree_paddr ); - let device_tree_vaddr = phys_to_virt(device_tree_paddr); + let device_tree_vaddr = device_tree_paddr + arch::consts::PHYSICAL_MEMORY_OFFSET; let boot_info = BootInfo { memory_map: Vec::new(), @@ -132,7 +129,7 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { dtb: device_tree_vaddr, }); - let cmdline_dt = CMDLINE.read(); + let cmdline_dt = "";// FIXME: CMDLINE.read(); let mut cmdline = boot_info.cmdline.to_string(); if !cmdline_dt.is_empty() { @@ -150,7 +147,7 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { .clone(); let (width, height) = gpu.resolution(); let (fb_vaddr, fb_size) = gpu.setup_framebuffer(); - kernel_hal_bare::init_framebuffer(width, height, fb_vaddr, fb_size); + kernel_hal::deb::fb::init(width, height, fb_vaddr, fb_size); } // riscv64在之后使用ramfs或virtio, 而x86_64则由bootloader载入文件系统镜像到内存 @@ -189,7 +186,7 @@ fn main(ramfs_data: &'static mut [u8], cmdline: &str) -> ! { let len = kernel_hal::serial::serial_read(&mut buffer); for c in &buffer[..len] { STDIN.push((*c).into()); - // kernel_hal_bare::print_str(alloc::format!("{}", *c as char).as_str()); + // kernel_hal::serial::serial_write(alloc::format!("{}", *c as char).as_str()); } false } @@ -215,7 +212,7 @@ fn run() -> ! { x86_64::instructions::interrupts::disable(); } #[cfg(target_arch = "riscv64")] - kernel_hal_bare::interrupt::wait_for_interrupt(); + kernel_hal::riscv::wait_for_interrupt(); } } diff --git a/zCore/src/memory.rs b/zCore/src/memory.rs index 240c3117..01366480 100644 --- a/zCore/src/memory.rs +++ b/zCore/src/memory.rs @@ -15,6 +15,8 @@ use riscv::{ addr::Frame, paging::{PageTable, PageTableFlags as EF}, }; +#[cfg(target_arch = "riscv64")] +use kernel_hal::BootInfo; #[cfg(target_arch = "x86_64")] type FrameAlloc = bitmap_allocator::BitAlloc16M; @@ -37,9 +39,6 @@ pub fn init_frame_allocator(boot_info: &BootInfo) { info!("Frame allocator init end"); } -#[cfg(target_arch = "riscv64")] -use kernel_hal_bare::BootInfo; - #[cfg(target_arch = "riscv64")] pub fn init_frame_allocator(boot_info: &BootInfo) { use core::ops::Range; diff --git a/zircon-syscall/src/debug.rs b/zircon-syscall/src/debug.rs index 990cd738..941d81c0 100644 --- a/zircon-syscall/src/debug.rs +++ b/zircon-syscall/src/debug.rs @@ -6,7 +6,7 @@ impl Syscall<'_> { pub fn sys_debug_write(&self, buf: UserInPtr, len: usize) -> ZxResult { info!("debug.write: buf=({:?}; {:#x})", buf, len); let data = buf.read_array(len)?; - kernel_hal::serial::print_str(core::str::from_utf8(&data).unwrap()); + kernel_hal::serial::serial_write(core::str::from_utf8(&data).unwrap()); Ok(()) } diff --git a/zircon-syscall/src/debuglog.rs b/zircon-syscall/src/debuglog.rs index 97babaf3..2baa1833 100644 --- a/zircon-syscall/src/debuglog.rs +++ b/zircon-syscall/src/debuglog.rs @@ -54,9 +54,9 @@ impl Syscall<'_> { let dlog = proc.get_object_with_rights::(handle_value, Rights::WRITE)?; dlog.write(Severity::Info, options, self.thread.id(), proc.id(), &data); // print to kernel console - kernel_hal::serial::print_str(&data); + kernel_hal::serial::serial_write(&data); if data.as_bytes().last() != Some(&b'\n') { - kernel_hal::serial::print_str("\n"); + kernel_hal::serial::serial_write("\n"); } Ok(()) }