forked from rcore-os/zCore
Compare commits
3 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
ffbdd8e8cb | |
|
|
b6d6e61a15 | |
|
|
e2bed6a086 |
|
|
@ -1,9 +1,10 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"zircon-object",
|
||||
"zircon-syscall",
|
||||
"zircon-loader",
|
||||
"linux-object",
|
||||
"zircon-syscall",
|
||||
"linux-syscall",
|
||||
"linux-loader",
|
||||
"kernel-hal-unix",
|
||||
"kernel-hal",
|
||||
|
|
@ -13,6 +14,5 @@ exclude = [
|
|||
"zircon-user",
|
||||
"zCore",
|
||||
"rboot",
|
||||
"linux-syscall",
|
||||
"kernel-hal-bare",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ git-version = "0.3"
|
|||
executor = { git = "https://github.com/rcore-os/executor.git", rev = "a2d02ee9" }
|
||||
trapframe = "0.8.0"
|
||||
kernel-hal = { path = "../kernel-hal" }
|
||||
naive-timer = "0.1.0"
|
||||
naive-timer = "0.2.0"
|
||||
lazy_static = { version = "1.4", features = ["spin_no_std" ] }
|
||||
uart_16550 = { version = "=0.2.15", default-features = false, features = ["stable"] }
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
x86_64 = "0.14"
|
||||
uart_16550 = "=0.2.15"
|
||||
raw-cpuid = "9.0"
|
||||
pc-keyboard = "0.5"
|
||||
apic = { git = "https://github.com/rcore-os/apic-rs", rev = "fb86bd7" }
|
||||
|
|
@ -29,7 +29,6 @@ acpi = "1.1"
|
|||
|
||||
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
|
||||
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" }
|
||||
# 注意rev版本号必须与其他组件的完全一致,不可多字符
|
||||
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
|
||||
device_tree = { git = "https://github.com/rcore-os/device_tree-rs" }
|
||||
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "568276" }
|
||||
|
|
|
|||
|
|
@ -18,14 +18,4 @@ pub const MEMORY_END: usize = 0x8800_0000;
|
|||
pub const USER_STACK_OFFSET: usize = 0x40000000 - USER_STACK_SIZE;
|
||||
pub const USER_STACK_SIZE: usize = 0x10000;
|
||||
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub const KSEG2_START: usize = 0xfe80_0000;
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub const KSEG2_START: usize = 0xffff_fe80_0000_0000;
|
||||
|
||||
pub const MAX_DTB_SIZE: usize = 0x2000;
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub const ARCH: &'static str = "riscv64";
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub const ARCH: &'static str = "riscv32";
|
||||
|
|
|
|||
|
|
@ -8,62 +8,19 @@ use riscv::register::{
|
|||
use spin::Mutex;
|
||||
use trapframe::{TrapFrame, UserContext};
|
||||
|
||||
/*
|
||||
use crate::timer::{
|
||||
TICKS,
|
||||
clock_set_next_event,
|
||||
clock_close,
|
||||
};
|
||||
*/
|
||||
|
||||
//use crate::context::TrapFrame;
|
||||
use super::plic;
|
||||
use super::sbi;
|
||||
use super::uart;
|
||||
|
||||
use super::consts::PHYSICAL_MEMORY_OFFSET;
|
||||
use super::timer_set_next;
|
||||
use crate::{map_range, phys_to_virt, putfmt};
|
||||
|
||||
//global_asm!(include_str!("trap.asm"));
|
||||
|
||||
/*
|
||||
#[repr(C)]
|
||||
pub struct TrapFrame{
|
||||
pub x: [usize; 32], //General registers
|
||||
pub sstatus: Sstatus,
|
||||
pub sepc: usize,
|
||||
pub stval: usize,
|
||||
pub scause: Scause,
|
||||
}
|
||||
*/
|
||||
|
||||
const TABLE_SIZE: usize = 256;
|
||||
pub type InterruptHandle = Box<dyn Fn() + Send + Sync>;
|
||||
lazy_static! {
|
||||
static ref IRQ_TABLE: Mutex<Vec<Option<InterruptHandle>>> = 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));
|
||||
}
|
||||
use super::{map_range, phys_to_virt, putfmt};
|
||||
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
sstatus::set_sie();
|
||||
|
||||
init_uart();
|
||||
|
||||
sie::set_sext();
|
||||
init_ext();
|
||||
}
|
||||
|
||||
init_irq();
|
||||
|
||||
bare_println!("+++ setup interrupt +++");
|
||||
info!("+++ setup interrupt +++");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
@ -90,121 +47,30 @@ pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
|
|||
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) => {
|
||||
if let Some(id) = plic::next() {
|
||||
match id {
|
||||
1..=8 => {
|
||||
//virtio::handle_interrupt(interrupt);
|
||||
info!("plic virtio external interrupt: {}", id);
|
||||
}
|
||||
10 => serial(),
|
||||
_ => info!("Unknown external interrupt: {}", id),
|
||||
}
|
||||
plic::complete(id);
|
||||
}
|
||||
}
|
||||
//Trap::Interrupt(Interrupt::SupervisorExternal) => irq_handle(code as u8),
|
||||
_ => panic!("Undefined Trap: {:#x} {:#x}", is_int, code),
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a handle to IRQ table. Return the specified irq or an allocated irq on success
|
||||
#[export_name = "hal_irq_add_handle"]
|
||||
pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
|
||||
info!("IRQ add handle {:#x?}", irq);
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
// allocate a valid irq number
|
||||
// why?
|
||||
if irq == 0 {
|
||||
let mut id = 0x20;
|
||||
while id < table.len() {
|
||||
if table[id].is_none() {
|
||||
table[id] = Some(handle);
|
||||
return Some(id as u8);
|
||||
}
|
||||
id += 1;
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
match table[irq as usize] {
|
||||
Some(_) => None,
|
||||
None => {
|
||||
table[irq as usize] = Some(handle);
|
||||
Some(irq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_remove_handle"]
|
||||
pub fn irq_remove_handle(irq: u8) -> bool {
|
||||
info!("IRQ remove handle {:#x?}", irq);
|
||||
let irq = irq as usize;
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
match table[irq] {
|
||||
Some(_) => {
|
||||
table[irq] = None;
|
||||
false
|
||||
}
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[export_name = "hal_irq_allocate_block"]
|
||||
pub fn allocate_block(irq_num: u32) -> Option<(usize, usize)> {
|
||||
info!("hal_irq_allocate_block: count={:#x?}", irq_num);
|
||||
let irq_num = u32::next_power_of_two(irq_num) as usize;
|
||||
let mut irq_start = 0x20;
|
||||
let mut irq_cur = irq_start;
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
while irq_cur < TABLE_SIZE && irq_cur < irq_start + irq_num {
|
||||
if table[irq_cur].is_none() {
|
||||
irq_cur += 1;
|
||||
} else {
|
||||
irq_start = (irq_cur - irq_cur % irq_num) + irq_num;
|
||||
irq_cur = irq_start;
|
||||
}
|
||||
}
|
||||
for i in irq_start..irq_start + irq_num {
|
||||
table[i] = Some(Box::new(|| {}));
|
||||
}
|
||||
info!(
|
||||
"hal_irq_allocate_block: start={:#x?} num={:#x?}",
|
||||
irq_start, irq_num
|
||||
);
|
||||
Some((irq_start, irq_num))
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_free_block"]
|
||||
pub fn free_block(irq_start: u32, irq_num: u32) {
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
for i in irq_start..irq_start + irq_num {
|
||||
table[i as usize] = None;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[export_name = "hal_irq_overwrite_handler"]
|
||||
pub fn overwrite_handler(msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) -> bool {
|
||||
info!("IRQ overwrite handle {:#x?}", msi_id);
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
let set = table[msi_id as usize].is_none();
|
||||
table[msi_id as usize] = Some(handle);
|
||||
set
|
||||
}
|
||||
|
||||
fn breakpoint(sepc: &mut usize) {
|
||||
bare_println!("Exception::Breakpoint: A breakpoint set @0x{:x} ", sepc);
|
||||
info!("Exception::Breakpoint: A breakpoint set @0x{:x} ", sepc);
|
||||
|
||||
//sepc为触发中断指令ebreak的地址
|
||||
//防止无限循环中断,让sret返回时跳转到sepc的下一条指令地址
|
||||
*sepc += 2
|
||||
*sepc += 2;
|
||||
}
|
||||
|
||||
fn page_fault(stval: usize, tf: &mut TrapFrame) {
|
||||
|
|
@ -217,7 +83,7 @@ fn page_fault(stval: usize, tf: &mut TrapFrame) {
|
|||
);
|
||||
let vaddr = stval;
|
||||
|
||||
use crate::PageTableImpl;
|
||||
use super::PageTableImpl;
|
||||
use kernel_hal::{MMUFlags, PageTableTrait};
|
||||
use riscv::addr::{Page, PhysAddr, VirtAddr};
|
||||
use riscv::paging::{PageTableFlags as PTF, Rv39PageTable, *};
|
||||
|
|
@ -273,29 +139,12 @@ fn super_timer() {
|
|||
timer_set_next();
|
||||
super::timer_tick();
|
||||
|
||||
//bare_print!(".");
|
||||
|
||||
//发生外界中断时,epc的指令还没有执行,故无需修改epc到下一条
|
||||
}
|
||||
|
||||
fn init_uart() {
|
||||
uart::Uart::new(0x1000_0000 + PHYSICAL_MEMORY_OFFSET).simple_init();
|
||||
|
||||
//但当没有SBI_CONSOLE_PUTCHAR时,却为什么不行?
|
||||
super::putfmt_uart(format_args!("{}", "Uart output testing\n"));
|
||||
|
||||
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,
|
||||
}
|
||||
fn serial() {
|
||||
let c = super::UART.lock().receive();
|
||||
super::serial_put(c);
|
||||
}
|
||||
|
||||
pub fn init_ext() {
|
||||
|
|
@ -305,19 +154,19 @@ pub fn init_ext() {
|
|||
plic::set_threshold(0);
|
||||
plic::enable(10);
|
||||
|
||||
bare_println!("+++ Setting up PLIC +++");
|
||||
info!("+++ Setting up PLIC +++");
|
||||
}
|
||||
|
||||
fn super_soft() {
|
||||
sbi::clear_ipi();
|
||||
bare_println!("Interrupt::SupervisorSoft!");
|
||||
info!("Interrupt::SupervisorSoft!");
|
||||
}
|
||||
|
||||
pub fn init_soft() {
|
||||
unsafe {
|
||||
sie::set_ssoft();
|
||||
}
|
||||
bare_println!("+++ setup soft int! +++");
|
||||
info!("+++ setup soft int! +++");
|
||||
}
|
||||
|
||||
#[export_name = "fetch_trap_num"]
|
||||
|
|
@ -340,46 +189,3 @@ pub fn wait_for_interrupt() {
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// 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;
|
||||
|
|
|
|||
|
|
@ -5,14 +5,15 @@ 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 alloc::{collections::VecDeque, vec::Vec, string::String};
|
||||
use core::fmt::{self, Write};
|
||||
use self::consts::PHYSICAL_MEMORY_OFFSET;
|
||||
|
||||
mod sbi;
|
||||
|
||||
mod consts;
|
||||
|
||||
use consts::PHYSICAL_MEMORY_OFFSET;
|
||||
pub mod interrupt;
|
||||
mod plic;
|
||||
pub mod virtio;
|
||||
|
||||
// First core stores its SATP here.
|
||||
static mut SATP: usize = 0;
|
||||
|
|
@ -321,19 +322,6 @@ impl PageTableTrait for PageTableImpl {
|
|||
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) {
|
||||
|
|
@ -390,43 +378,6 @@ impl FrameDeallocator for FrameAllocatorImpl {
|
|||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref STDIN: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
|
||||
static ref STDIN_CALLBACK: Mutex<Vec<Box<dyn Fn() -> 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(x);
|
||||
STDIN_CALLBACK.lock().retain(|f| !f());
|
||||
}
|
||||
|
||||
#[export_name = "hal_serial_set_callback"]
|
||||
pub fn serial_set_callback(callback: Box<dyn Fn() -> 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 serial_write(s: &str) {
|
||||
//putfmt(format_args!("{}", s));
|
||||
putfmt_uart(format_args!("{}", s));
|
||||
}
|
||||
|
||||
// Get TSC frequency.
|
||||
fn tsc_frequency() -> u16 {
|
||||
const DEFAULT: u16 = 2600;
|
||||
|
|
@ -441,73 +392,26 @@ pub fn apic_local_id() -> u8 {
|
|||
lapic as u8
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
pub fn getchar_option() -> Option<u8> {
|
||||
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);
|
||||
}
|
||||
lazy_static! {
|
||||
static ref UART: Mutex<uart_16550::MmioSerialPort>
|
||||
= Mutex::new(unsafe { uart_16550::MmioSerialPort::new(0x1000_0000 + PHYSICAL_MEMORY_OFFSET) });
|
||||
}
|
||||
|
||||
struct Stdout;
|
||||
|
||||
impl fmt::Write for Stdout {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
puts(s);
|
||||
for b in s.bytes() {
|
||||
sbi::console_putchar(b as _);
|
||||
}
|
||||
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(0x1000_0000 + PHYSICAL_MEMORY_OFFSET),
|
||||
"{}",
|
||||
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)*)));
|
||||
// FIXME: use UART would block
|
||||
// UART.lock().write_fmt(fmt).unwrap();
|
||||
}
|
||||
|
||||
pub const MMIO_MTIMECMP0: *mut u64 = 0x0200_4000usize as *mut u64;
|
||||
|
|
@ -515,22 +419,15 @@ pub const MMIO_MTIME: *const u64 = 0x0200_BFF8 as *const u64;
|
|||
|
||||
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;
|
||||
|
|
@ -547,24 +444,19 @@ fn timer_init() {
|
|||
pub fn init(config: Config) {
|
||||
interrupt::init();
|
||||
timer_init();
|
||||
UART.lock().init();
|
||||
|
||||
/*
|
||||
interrupt::init_soft();
|
||||
sbi::send_ipi(0);
|
||||
*/
|
||||
let cmdline = virtio::device_tree::init(config.dtb);
|
||||
unsafe { CMDLINE = cmdline };
|
||||
}
|
||||
|
||||
unsafe {
|
||||
llvm_asm!("ebreak"::::"volatile");
|
||||
}
|
||||
static mut CMDLINE: String = String::new();
|
||||
|
||||
bare_println!("Setup virtio @devicetree {:#x}", config.dtb);
|
||||
//virtio::init(config.dtb);
|
||||
|
||||
virtio::device_tree::init(config.dtb);
|
||||
pub fn cmdline() -> &'static str {
|
||||
unsafe { CMDLINE.as_str() }
|
||||
}
|
||||
|
||||
pub struct Config {
|
||||
pub mconfig: u64,
|
||||
pub dtb: usize,
|
||||
}
|
||||
|
||||
|
|
@ -573,53 +465,6 @@ 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)]
|
||||
pub struct BootInfo {
|
||||
pub memory_map: Vec<u64>,
|
||||
//pub memory_map: Vec<&'static MemoryDescriptor>,
|
||||
/// The offset into the virtual address space where the physical memory is mapped.
|
||||
pub physical_memory_offset: u64,
|
||||
/// The graphic output information
|
||||
pub graphic_info: GraphicInfo,
|
||||
|
||||
/// Physical address of ACPI2 RSDP, 启动的系统信息表的入口指针
|
||||
//pub acpi2_rsdp_addr: u64,
|
||||
/// Physical address of SMBIOS, 产品管理信息的结构表
|
||||
//pub smbios_addr: u64,
|
||||
pub hartid: u64,
|
||||
pub dtb_addr: u64,
|
||||
|
||||
/// The start physical address of initramfs
|
||||
pub initramfs_addr: u64,
|
||||
/// The size of initramfs
|
||||
pub initramfs_size: u64,
|
||||
/// Kernel command line
|
||||
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 mod interrupt;
|
||||
mod plic;
|
||||
mod uart;
|
||||
|
||||
pub mod virtio;
|
||||
|
||||
#[export_name = "hal_current_pgtable"]
|
||||
pub fn current_page_table() -> usize {
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
use super::consts::PHYSICAL_MEMORY_OFFSET;
|
||||
use super::interrupt;
|
||||
use super::uart;
|
||||
use crate::putfmt; //For bare_println
|
||||
|
||||
const MMODE: usize = 0;
|
||||
|
||||
|
|
@ -111,27 +108,3 @@ pub fn set_threshold(tsh: u8) {
|
|||
tsh_reg.write_volatile(actual_tsh as u32); // 0x0c20_0000 <= 0 = 0 & 7
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_interrupt() {
|
||||
if let Some(interrupt) = next() {
|
||||
match interrupt {
|
||||
1..=8 => {
|
||||
//virtio::handle_interrupt(interrupt);
|
||||
bare_println!("plic virtio external interrupt: {}", interrupt);
|
||||
}
|
||||
10 => {
|
||||
//UART中断ID是10
|
||||
uart::handle_interrupt();
|
||||
|
||||
//换用sbi的方式获取字符
|
||||
//interrupt::try_process_serial();
|
||||
}
|
||||
_ => {
|
||||
bare_println!("Unknown external interrupt: {}", interrupt);
|
||||
}
|
||||
}
|
||||
//这将复位pending的中断,允许UART再次中断。
|
||||
//否则,UART将被“卡住”
|
||||
complete(interrupt);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,14 @@ pub fn console_getchar() -> usize {
|
|||
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");
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a0") arg0,
|
||||
in("a1") arg1,
|
||||
in("a2") arg2,
|
||||
in("a7") which,
|
||||
lateout("a0") ret,
|
||||
);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
.equ XLENB, 8
|
||||
# sp + 8*a2 -> a1
|
||||
.macro LOAD a1, a2
|
||||
ld \a1, \a2*XLENB(sp)
|
||||
.endm
|
||||
|
||||
.macro STORE a1, a2
|
||||
sd \a1, \a2*XLENB(sp)
|
||||
.endm
|
||||
|
||||
# int in U: sscratch = kernel_addr; int in S: sscratch = 0;
|
||||
.macro SAVE_ALL
|
||||
csrrw sp, sscratch, sp
|
||||
|
||||
bnez sp, trap_from_user
|
||||
trap_from_kernel:
|
||||
csrr sp, sscratch
|
||||
trap_from_user:
|
||||
addi sp, sp, -36*XLENB
|
||||
|
||||
# x0 = 0, x2 = sp
|
||||
STORE x1, 1
|
||||
STORE x3, 3
|
||||
STORE x4, 4
|
||||
STORE x5, 5
|
||||
STORE x6, 6
|
||||
STORE x7, 7
|
||||
STORE x8, 8
|
||||
STORE x9, 9
|
||||
STORE x10, 10
|
||||
STORE x11, 11
|
||||
STORE x12, 12
|
||||
STORE x13, 13
|
||||
STORE x14, 14
|
||||
STORE x15, 15
|
||||
STORE x16, 16
|
||||
STORE x17, 17
|
||||
STORE x18, 18
|
||||
STORE x19, 19
|
||||
STORE x20, 20
|
||||
STORE x21, 21
|
||||
STORE x22, 22
|
||||
STORE x23, 23
|
||||
STORE x24, 24
|
||||
STORE x25, 25
|
||||
STORE x26, 26
|
||||
STORE x27, 27
|
||||
STORE x28, 28
|
||||
STORE x29, 29
|
||||
STORE x30, 30
|
||||
STORE x31, 31
|
||||
|
||||
csrrw s0, sscratch, x0
|
||||
|
||||
csrr s1, sstatus
|
||||
csrr s2, sepc
|
||||
csrr s3, stval
|
||||
csrr s4, scause
|
||||
|
||||
STORE s0, 2
|
||||
STORE s1, 32
|
||||
STORE s2, 33
|
||||
STORE s3, 34
|
||||
STORE s4, 35
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL
|
||||
|
||||
# s1 = sstatus, s2 = sepc
|
||||
LOAD s1, 32
|
||||
LOAD s2, 33
|
||||
|
||||
# int in Kernel, sstatus SPP = 1; int in User, sstatus SPP 0
|
||||
andi s0, s1, 1 << 8
|
||||
bnez s0, _to_kernel
|
||||
_to_user:
|
||||
addi s0, sp, 36 * XLENB
|
||||
csrw sscratch, s0
|
||||
_to_kernel:
|
||||
csrw sstatus, s1
|
||||
csrw sepc, s2
|
||||
|
||||
|
||||
LOAD x1, 1
|
||||
LOAD x3, 3
|
||||
LOAD x4, 4
|
||||
LOAD x5, 5
|
||||
LOAD x6, 6
|
||||
LOAD x7, 7
|
||||
LOAD x8, 8
|
||||
LOAD x9, 9
|
||||
LOAD x10, 10
|
||||
LOAD x11, 11
|
||||
LOAD x12, 12
|
||||
LOAD x13, 13
|
||||
LOAD x14, 14
|
||||
LOAD x15, 15
|
||||
LOAD x16, 16
|
||||
LOAD x17, 17
|
||||
LOAD x18, 18
|
||||
LOAD x19, 19
|
||||
LOAD x20, 20
|
||||
LOAD x21, 21
|
||||
LOAD x22, 22
|
||||
LOAD x23, 23
|
||||
LOAD x24, 24
|
||||
LOAD x25, 25
|
||||
LOAD x26, 26
|
||||
LOAD x27, 27
|
||||
LOAD x28, 28
|
||||
LOAD x29, 29
|
||||
LOAD x30, 30
|
||||
LOAD x31, 31
|
||||
|
||||
# sp
|
||||
LOAD x2, 2
|
||||
.endm
|
||||
|
||||
.section .text
|
||||
.globl __alltraps
|
||||
.align 4
|
||||
__alltraps:
|
||||
SAVE_ALL
|
||||
mv a0, sp
|
||||
jal rust_trap
|
||||
|
||||
.globl __trapret
|
||||
__trapret:
|
||||
RESTORE_ALL
|
||||
sret
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
use super::consts::PHYSICAL_MEMORY_OFFSET;
|
||||
use crate::putfmt;
|
||||
use core::convert::TryInto;
|
||||
use core::fmt::{Error, Write};
|
||||
|
||||
//use crate::console::push_stdin;
|
||||
|
||||
pub struct Uart {
|
||||
base_address: usize,
|
||||
}
|
||||
|
||||
// 结构体Uart的实现块
|
||||
impl Uart {
|
||||
pub fn new(base_address: usize) -> Self {
|
||||
Uart { base_address }
|
||||
}
|
||||
/*
|
||||
uart初始化
|
||||
设置字长为8-bits (LCR[1:0])
|
||||
使能先进先出FIFOs (FCR[0])
|
||||
使能接受中断(IER[0]), 在这只使用轮询的方式而不用中断
|
||||
|
||||
*/
|
||||
pub fn init(&mut self) {
|
||||
let ptr = self.base_address as *mut u8;
|
||||
unsafe {
|
||||
// LCR at base_address + 3
|
||||
// 置位 bit 0 bit 1
|
||||
let lcr = (1 << 0) | (1 << 1);
|
||||
ptr.add(3).write_volatile(lcr);
|
||||
|
||||
// FCR at offset 2
|
||||
ptr.add(2).write_volatile(1 << 0);
|
||||
|
||||
//IER at offset 1
|
||||
ptr.add(1).write_volatile(1 << 0);
|
||||
|
||||
// 设置波特率,除子,取整等
|
||||
// 2.729 MHz (22,729,000 cycles per second) --> 波特率 2400 (BAUD)
|
||||
|
||||
// 根据NS16550a规格说明书计算出divisor
|
||||
// divisor = ceil( (clock_hz) / (baud_sps x 16) )
|
||||
// divisor = ceil( 22_729_000 / (2400 x 16) ) = ceil( 591.901 ) = 592
|
||||
|
||||
// divisor寄存器是16 bits
|
||||
let divisor: u16 = 592;
|
||||
//let divisor_least: u8 = divisor & 0xff;
|
||||
//let divisor_most: u8 = divisor >> 8;
|
||||
let divisor_least: u8 = (divisor & 0xff).try_into().unwrap();
|
||||
let divisor_most: u8 = (divisor >> 8).try_into().unwrap();
|
||||
|
||||
// DLL和DLM会与其它寄存器共用基地址,需要设置DLAB来切换选择寄存器
|
||||
// LCR base_address + 3, DLAB = 1
|
||||
ptr.add(3).write_volatile(lcr | 1 << 7);
|
||||
|
||||
//写DLL和DLM来设置波特率, 把频率22.729 MHz的时钟划分为每秒2400个信号
|
||||
ptr.add(0).write_volatile(divisor_least);
|
||||
ptr.add(1).write_volatile(divisor_most);
|
||||
|
||||
// 设置后不需要再动了, 清空DLAB
|
||||
ptr.add(3).write_volatile(lcr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simple_init(&mut self) {
|
||||
let ptr = self.base_address as *mut u8;
|
||||
unsafe {
|
||||
// Enable FIFO; (base + 2)
|
||||
ptr.add(2).write_volatile(0xC7);
|
||||
|
||||
// MODEM Ctrl; (base + 4)
|
||||
ptr.add(4).write_volatile(0x0B);
|
||||
|
||||
// Enable interrupts; (base + 1)
|
||||
ptr.add(1).write_volatile(0x01);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&mut self) -> Option<u8> {
|
||||
let ptr = self.base_address as *mut u8;
|
||||
unsafe {
|
||||
//查看LCR, DR位为1则有数据
|
||||
if ptr.add(5).read_volatile() & 0b1 == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ptr.add(0).read_volatile())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put(&mut self, c: u8) {
|
||||
let ptr = self.base_address as *mut u8;
|
||||
unsafe {
|
||||
//此时transmitter empty
|
||||
ptr.add(0).write_volatile(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 需要实现的write_str()重要函数
|
||||
impl Write for Uart {
|
||||
fn write_str(&mut self, out: &str) -> Result<(), Error> {
|
||||
for c in out.bytes() {
|
||||
self.put(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fn unsafe mmio_write(address: usize, offset: usize, value: u8) {
|
||||
//write_volatile() 是 *mut raw 的成员;
|
||||
//new_pointer = old_pointer + sizeof(pointer_type) * offset
|
||||
//也可使用reg.offset
|
||||
|
||||
let reg = address as *mut u8;
|
||||
reg.add(offset).write_volatile(value);
|
||||
}
|
||||
|
||||
fn unsafe mmio_read(address: usize, offset: usize, value: u8) -> u8 {
|
||||
|
||||
let reg = address as *mut u8;
|
||||
|
||||
//读取8 bits
|
||||
reg.add(offset).read_volatile(value) //无分号可直接返回值
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn handle_interrupt() {
|
||||
let mut my_uart = Uart::new(0x1000_0000 + PHYSICAL_MEMORY_OFFSET);
|
||||
if let Some(c) = my_uart.get() {
|
||||
//CONSOLE
|
||||
//push_stdin(c);
|
||||
super::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);
|
||||
},
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -5,11 +5,10 @@ use device_tree::{DeviceTree, Node};
|
|||
|
||||
//use super::virtio_mmio::virtio_probe;
|
||||
use super::virtio::virtio_probe;
|
||||
use super::CMDLINE;
|
||||
|
||||
const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed;
|
||||
|
||||
fn walk_dt_node(dt: &Node) {
|
||||
fn walk_dt_node(dt: &Node, cmdline_out: &mut String) {
|
||||
if let Ok(compatible) = dt.prop_str("compatible") {
|
||||
// TODO: query this from table
|
||||
if compatible == "virtio,mmio" {
|
||||
|
|
@ -18,13 +17,12 @@ fn walk_dt_node(dt: &Node) {
|
|||
// TODO: initial other devices (16650, etc.)
|
||||
}
|
||||
if let Ok(bootargs) = dt.prop_str("bootargs") {
|
||||
if bootargs.len() > 0 {
|
||||
info!("Kernel cmdline: {}", bootargs);
|
||||
*CMDLINE.write() = String::from(bootargs);
|
||||
if !bootargs.is_empty() {
|
||||
*cmdline_out = String::from(bootargs);
|
||||
}
|
||||
}
|
||||
for child in dt.children.iter() {
|
||||
walk_dt_node(child);
|
||||
walk_dt_node(child, cmdline_out);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,16 +31,18 @@ struct DtbHeader {
|
|||
size: u32,
|
||||
}
|
||||
|
||||
pub fn init(dtb: usize) {
|
||||
/// Return cmdline.
|
||||
pub fn init(dtb: usize) -> String {
|
||||
info!("DTB: {:#x}", dtb);
|
||||
let header = unsafe { &*(dtb as *const DtbHeader) };
|
||||
let magic = u32::from_be(header.magic);
|
||||
if magic == DEVICE_TREE_MAGIC {
|
||||
let size = u32::from_be(header.size);
|
||||
let dtb_data = unsafe { slice::from_raw_parts(dtb as *const u8, size as usize) };
|
||||
if let Ok(dt) = DeviceTree::load(dtb_data) {
|
||||
//trace!("DTB: {:#x?}", dt);
|
||||
walk_dt_node(&dt.root);
|
||||
}
|
||||
assert_eq!(magic, DEVICE_TREE_MAGIC, "invalid device tree magic number");
|
||||
let size = u32::from_be(header.size);
|
||||
let dtb_data = unsafe { slice::from_raw_parts(dtb as *const u8, size as usize) };
|
||||
let mut cmdline = String::new();
|
||||
if let Ok(dt) = DeviceTree::load(dtb_data) {
|
||||
//trace!("DTB: {:#x?}", dt);
|
||||
walk_dt_node(&dt.root, &mut cmdline);
|
||||
}
|
||||
cmdline
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,8 +97,3 @@ impl BlockDevice for BlockDriverWrapper {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
// Write only once at boot
|
||||
pub static ref CMDLINE: RwLock<String> = RwLock::new(String::new());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,12 +150,6 @@ impl PageTableTrait for PageTableImpl {
|
|||
fn table_phys(&self) -> PhysAddr {
|
||||
self.root_paddr
|
||||
}
|
||||
|
||||
// /// Activate this page table
|
||||
// #[export_name = "hal_pt_activate"]
|
||||
// fn activate(&self) {
|
||||
// unimplemented!()
|
||||
// }
|
||||
}
|
||||
|
||||
/// Set page table.
|
||||
|
|
@ -281,41 +275,6 @@ pub fn putfmt(fmt: Arguments) {
|
|||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref STDIN: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
|
||||
static ref STDIN_CALLBACK: Mutex<Vec<Box<dyn Fn() -> 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(x);
|
||||
STDIN_CALLBACK.lock().retain(|f| !f());
|
||||
}
|
||||
|
||||
#[export_name = "hal_serial_set_callback"]
|
||||
pub fn serial_set_callback(callback: Box<dyn Fn() -> 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 serial_write(s: &str) {
|
||||
putfmt(format_args!("{}", s));
|
||||
}
|
||||
|
||||
/// Get TSC frequency.
|
||||
///
|
||||
/// WARN: This will be very slow on virtual machine since it uses CPUID instruction.
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
#![no_std]
|
||||
#![feature(asm)]
|
||||
#![feature(llvm_asm)]
|
||||
#![feature(global_asm)]
|
||||
#![feature(linkage)]
|
||||
//#![deny(warnings)]
|
||||
|
||||
|
|
@ -41,9 +39,10 @@ use kernel_hal::UserContext;
|
|||
use naive_timer::Timer;
|
||||
use spin::Mutex;
|
||||
|
||||
pub mod arch;
|
||||
mod arch;
|
||||
mod serial;
|
||||
|
||||
pub use self::arch::*;
|
||||
pub use self::{arch::*, serial::*};
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
extern "C" {
|
||||
|
|
@ -190,16 +189,6 @@ pub fn frame_copy(src: PhysAddr, target: PhysAddr) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Zero `target` frame.
|
||||
#[export_name = "hal_frame_zero"]
|
||||
pub fn frame_zero_in_range(target: PhysAddr, start: usize, end: usize) {
|
||||
assert!(start < PAGE_SIZE && end <= PAGE_SIZE);
|
||||
trace!("frame_zero: {:#x?}", target);
|
||||
unsafe {
|
||||
core::ptr::write_bytes(phys_to_virt(target + start) as *mut u8, 0, end - start);
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref NAIVE_TIMER: Mutex<Timer> = Mutex::new(Timer::default());
|
||||
}
|
||||
|
|
@ -209,21 +198,16 @@ pub fn timer_set(deadline: Duration, callback: Box<dyn FnOnce(Duration) + Send +
|
|||
NAIVE_TIMER.lock().add(deadline, callback);
|
||||
}
|
||||
|
||||
#[export_name = "hal_timer_tick"]
|
||||
pub fn timer_tick() {
|
||||
let now = arch::timer_now();
|
||||
NAIVE_TIMER.lock().expire(now);
|
||||
}
|
||||
|
||||
/// Initialize the HAL.
|
||||
pub fn init(config: Config) {
|
||||
pub fn init(config: arch::Config) {
|
||||
unsafe {
|
||||
trapframe::init();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
trace!("hal dtb: {:#x}", config.dtb);
|
||||
|
||||
arch::init(config);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
use spin::Mutex;
|
||||
use alloc::{boxed::Box, collections::VecDeque, vec::Vec};
|
||||
|
||||
lazy_static! {
|
||||
static ref STDIN: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
|
||||
static ref STDIN_CALLBACK: Mutex<Vec<Box<dyn Fn() -> bool + Send + Sync>>> =
|
||||
Mutex::new(Vec::new());
|
||||
}
|
||||
|
||||
/// Put a char by serial interrupt handler.
|
||||
pub fn serial_put(mut x: u8) {
|
||||
if x == b'\r' {
|
||||
x = b'\n';
|
||||
}
|
||||
STDIN.lock().push_back(x);
|
||||
STDIN_CALLBACK.lock().retain(|f| !f());
|
||||
}
|
||||
|
||||
#[export_name = "hal_serial_set_callback"]
|
||||
pub fn serial_set_callback(callback: Box<dyn Fn() -> 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 serial_write(s: &str) {
|
||||
crate::arch::putfmt(format_args!("{}", s));
|
||||
}
|
||||
|
|
@ -12,6 +12,3 @@ bitflags = "1.2"
|
|||
trapframe = "0.8.0"
|
||||
numeric-enum-macro = "0.2"
|
||||
acpi = "1.1"
|
||||
|
||||
#[patch.crates-io]
|
||||
#trapframe = { path = "/home/xly/rust/arch-lib/trapframe-rs" }
|
||||
|
|
|
|||
|
|
@ -70,10 +70,6 @@ pub trait PageTableTrait: Sync + Send {
|
|||
/// Get the physical address of root page table.
|
||||
fn table_phys(&self) -> PhysAddr;
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
/// Activate this page table
|
||||
fn activate(&self);
|
||||
|
||||
fn map_many(
|
||||
&mut self,
|
||||
mut vaddr: VirtAddr,
|
||||
|
|
@ -165,14 +161,6 @@ impl PageTableTrait for PageTable {
|
|||
self.table_phys
|
||||
}
|
||||
|
||||
/// Activate this page table
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_pt_activate"]
|
||||
fn activate(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_pt_unmap_cont"]
|
||||
fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> Result<()> {
|
||||
|
|
@ -300,19 +288,6 @@ pub fn timer_set(_deadline: Duration, _callback: Box<dyn FnOnce(Duration) + Send
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_timer_set_next"]
|
||||
pub fn timer_set_next() {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Check timers, call when timer interrupt happened.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_timer_tick"]
|
||||
pub fn timer_tick() {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub struct InterruptManager {}
|
||||
impl InterruptManager {
|
||||
/// Handle IRQ.
|
||||
|
|
|
|||
|
|
@ -134,17 +134,8 @@ async fn new_thread(thread: CurrentThread) {
|
|||
//Timer
|
||||
if trap_num == 4 || trap_num == 5 {
|
||||
debug!("Timer interrupt: {}", trap_num);
|
||||
|
||||
/*
|
||||
* 已在irq_handle里加入了timer处理函数
|
||||
kernel_hal::timer_set_next();
|
||||
kernel_hal::timer_tick();
|
||||
*/
|
||||
|
||||
kernel_hal::yield_now().await;
|
||||
}
|
||||
|
||||
//kernel_hal::InterruptManager::handle(trap_num as u8);
|
||||
}
|
||||
_ => panic!(
|
||||
"not supported pid: {} interrupt {} from user mode. {:#x?}",
|
||||
|
|
|
|||
|
|
@ -196,9 +196,6 @@ impl Syscall<'_> {
|
|||
};
|
||||
let (entry, sp) = loader.load(&vmar, &data, args, envs, path.clone())?;
|
||||
|
||||
// Activate page table
|
||||
// vmar.activate();
|
||||
|
||||
// Modify exec path
|
||||
proc.set_execute_path(&path);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ user ?=
|
|||
hypervisor ?=
|
||||
smp ?= 1
|
||||
test_filter ?= *.*
|
||||
log ?=
|
||||
|
||||
build_args := -Z build-std=core,alloc --target $(arch).json
|
||||
build_path := target/$(arch)/$(mode)
|
||||
|
|
@ -69,7 +70,8 @@ qemu_opts += \
|
|||
-nographic \
|
||||
-drive file=$(QEMU_DISK),format=qcow2,id=sfs \
|
||||
-device virtio-blk-device,drive=sfs \
|
||||
-kernel $(kernel_bin)
|
||||
-kernel $(kernel_bin) \
|
||||
-append LOG=$(log)
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use {
|
|||
|
||||
pub fn init(level: &str) {
|
||||
static LOGGER: SimpleLogger = SimpleLogger;
|
||||
log::set_logger(&LOGGER).unwrap();
|
||||
let _ = log::set_logger(&LOGGER);
|
||||
log::set_max_level(match level {
|
||||
"error" => LevelFilter::Error,
|
||||
"warn" => LevelFilter::Warn,
|
||||
|
|
@ -37,12 +37,12 @@ macro_rules! with_color {
|
|||
}
|
||||
|
||||
fn print_in_color(args: fmt::Arguments, color_code: u8) {
|
||||
kernel_hal_bare::arch::putfmt(with_color!(args, color_code));
|
||||
kernel_hal_bare::putfmt(with_color!(args, color_code));
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn print(args: fmt::Arguments) {
|
||||
kernel_hal_bare::arch::putfmt(args);
|
||||
kernel_hal_bare::putfmt(args);
|
||||
}
|
||||
|
||||
struct SimpleLogger;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(lang_items)]
|
||||
#![feature(llvm_asm)]
|
||||
#![feature(panic_info_message)]
|
||||
#![deny(unused_must_use)]
|
||||
#![feature(global_asm)]
|
||||
|
|
@ -15,12 +14,9 @@ extern crate log;
|
|||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
extern crate rlibc;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
extern crate rlibc_opt; //Only for x86_64
|
||||
|
||||
extern crate fatfs;
|
||||
|
||||
#[macro_use]
|
||||
mod logging;
|
||||
mod lang;
|
||||
|
|
@ -33,17 +29,17 @@ use rboot::BootInfo;
|
|||
use kernel_hal_bare::{
|
||||
phys_to_virt, remap_the_kernel,
|
||||
virtio::{BlockDriverWrapper, BLK_DRIVERS},
|
||||
BootInfo, GraphicInfo,
|
||||
};
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{string::String, vec::Vec};
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
global_asm!(include_str!("arch/riscv/boot/entry64.asm"));
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _start(boot_info: &BootInfo) -> ! {
|
||||
logging::init(get_log_level(boot_info.cmdline));
|
||||
logging::init(get_value(boot_info.cmdline, "LOG").unwrap_or(""));
|
||||
memory::init_heap();
|
||||
memory::init_frame_allocator(boot_info);
|
||||
|
||||
|
|
@ -83,75 +79,38 @@ fn main(ramfs_data: &[u8], cmdline: &str) -> ! {
|
|||
#[no_mangle]
|
||||
pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
|
||||
let device_tree_vaddr = phys_to_virt(device_tree_paddr);
|
||||
|
||||
let boot_info = BootInfo {
|
||||
memory_map: Vec::new(),
|
||||
physical_memory_offset: 0,
|
||||
graphic_info: GraphicInfo {
|
||||
mode: 0,
|
||||
fb_addr: 0,
|
||||
fb_size: 0,
|
||||
},
|
||||
hartid: hartid as u64,
|
||||
dtb_addr: device_tree_paddr as u64,
|
||||
initramfs_addr: 0,
|
||||
initramfs_size: 0,
|
||||
cmdline: "LOG=warn:TERM=xterm-256color:console.shell=true:virtcon.disable=true",
|
||||
};
|
||||
|
||||
unsafe {
|
||||
memory::clear_bss();
|
||||
}
|
||||
|
||||
logging::init(get_log_level(boot_info.cmdline));
|
||||
warn!("rust_main(), After logging init\n\n");
|
||||
logging::init("info");
|
||||
memory::init_heap();
|
||||
memory::init_frame_allocator(&boot_info);
|
||||
memory::init_frame_allocator();
|
||||
remap_the_kernel(device_tree_vaddr);
|
||||
|
||||
#[cfg(feature = "graphic")]
|
||||
init_framebuffer(boot_info);
|
||||
|
||||
info!("{:#x?}", boot_info);
|
||||
|
||||
kernel_hal_bare::init(kernel_hal_bare::Config {
|
||||
mconfig: 0,
|
||||
dtb: device_tree_vaddr,
|
||||
});
|
||||
|
||||
use alloc::{format, string::ToString};
|
||||
use kernel_hal_bare::virtio::CMDLINE;
|
||||
let cmdline_dt = CMDLINE.read();
|
||||
let mut cmdline = boot_info.cmdline.to_string();
|
||||
|
||||
if !cmdline_dt.is_empty() {
|
||||
cmdline = format!("{}:{}", boot_info.cmdline, cmdline_dt);
|
||||
};
|
||||
warn!("cmdline: {:?}", cmdline);
|
||||
let cmdline = kernel_hal_bare::cmdline();
|
||||
info!("cmdline: {:?}", cmdline);
|
||||
logging::init(get_value(cmdline, "LOG").unwrap_or(""));
|
||||
|
||||
// 正常由bootloader载入文件系统镜像到内存, 这里不用,而使用后面的virtio
|
||||
main(&mut [], &cmdline);
|
||||
}
|
||||
|
||||
use alloc::string::String;
|
||||
use alloc::vec;
|
||||
#[cfg(feature = "linux")]
|
||||
use alloc::vec;
|
||||
fn get_rootproc(cmdline: &str) -> Vec<String> {
|
||||
for opt in cmdline.split(':') {
|
||||
// parse 'key=value'
|
||||
let mut iter = opt.trim().splitn(2, '=');
|
||||
let key = iter.next().expect("failed to parse key");
|
||||
let value = iter.next().expect("failed to parse value");
|
||||
info!("value {}", value);
|
||||
if key == "ROOTPROC" {
|
||||
let mut iter = value.trim().splitn(2, '?');
|
||||
let k1 = iter.next().expect("failed to parse k1");
|
||||
let v1 = iter.next().expect("failed to parse v1");
|
||||
if v1 == "" {
|
||||
return vec![k1.into()];
|
||||
} else {
|
||||
return vec![k1.into(), v1.into()];
|
||||
}
|
||||
if let Some(value) = get_value(cmdline, "ROOTPROC") {
|
||||
let mut iter = value.trim().splitn(2, '?');
|
||||
let k1 = iter.next().expect("failed to parse k1");
|
||||
let v1 = iter.next().expect("failed to parse v1");
|
||||
if v1 == "" {
|
||||
return vec![k1.into()];
|
||||
} else {
|
||||
return vec![k1.into(), v1.into()];
|
||||
}
|
||||
}
|
||||
vec!["/bin/busybox".into(), "sh".into()]
|
||||
|
|
@ -160,9 +119,7 @@ fn get_rootproc(cmdline: &str) -> Vec<String> {
|
|||
#[cfg(feature = "linux")]
|
||||
fn main(ramfs_data: &'static mut [u8], cmdline: &str) -> ! {
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use linux_object::fs::MemBuf;
|
||||
|
|
@ -227,17 +184,20 @@ fn run() -> ! {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_log_level(cmdline: &str) -> &str {
|
||||
fn get_value<'a>(cmdline: &'a str, key: &str) -> Option<&'a str> {
|
||||
for opt in cmdline.split(':') {
|
||||
if opt.is_empty() {
|
||||
continue;
|
||||
}
|
||||
// parse 'key=value'
|
||||
let mut iter = opt.trim().splitn(2, '=');
|
||||
let key = iter.next().expect("failed to parse key");
|
||||
let key0 = iter.next().expect("failed to parse key");
|
||||
let value = iter.next().expect("failed to parse value");
|
||||
if key == "LOG" {
|
||||
return value;
|
||||
if key == key0 {
|
||||
return Some(value);
|
||||
}
|
||||
}
|
||||
""
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(feature = "graphic")]
|
||||
|
|
|
|||
|
|
@ -76,10 +76,7 @@ pub fn init_frame_allocator(boot_info: &BootInfo) {
|
|||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
use kernel_hal_bare::BootInfo;
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub fn init_frame_allocator(boot_info: &BootInfo) {
|
||||
pub fn init_frame_allocator() {
|
||||
use core::ops::Range;
|
||||
|
||||
let mut ba = FRAME_ALLOCATOR.lock();
|
||||
|
|
|
|||
|
|
@ -496,12 +496,6 @@ impl VmAddressRegion {
|
|||
self.flags
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
/// Activate this page table
|
||||
pub fn activate(&self) {
|
||||
self.page_table.lock().activate();
|
||||
}
|
||||
|
||||
/// Dump all mappings recursively.
|
||||
pub fn dump(&self) {
|
||||
let mut guard = self.inner.lock();
|
||||
|
|
|
|||
Loading…
Reference in New Issue