From cfbf990b77ba1b967f0df7d477e2e82a40675f05 Mon Sep 17 00:00:00 2001 From: yufeng <321353225@qq.com> Date: Fri, 8 Mar 2024 23:44:05 +0800 Subject: [PATCH] optimize for x86_64 support --- Cargo.lock | 39 ++- Makefile | 2 +- arch/src/aarch64/context.rs | 4 - arch/src/lib.rs | 2 +- arch/src/loongarch64/boot.rs | 2 +- arch/src/loongarch64/console.rs | 13 +- arch/src/loongarch64/context.rs | 4 - arch/src/loongarch64/mod.rs | 7 +- arch/src/riscv64/context.rs | 6 - arch/src/x86_64/consts.rs | 2 + arch/src/x86_64/context.rs | 21 +- arch/src/x86_64/entry.rs | 59 ---- arch/src/x86_64/gdt.rs | 115 +++++++ arch/src/x86_64/interrupt.rs | 453 ++++++++++++++-------------- arch/src/x86_64/mod.rs | 7 +- arch/src/x86_64/multiboot.S | 2 +- arch/src/x86_64/multiboot.rs | 54 +++- arch/src/x86_64/page_table.rs | 27 +- arch/src/x86_64/trap.S | 43 +-- arch/src/x86_64/trap.rs | 40 --- drivers/general-plic/src/lib.rs | 2 +- drivers/kvirtio/Cargo.toml | 4 +- drivers/kvirtio/src/lib.rs | 88 +++++- drivers/kvirtio/src/virtio_blk.rs | 28 +- drivers/kvirtio/src/virtio_input.rs | 16 +- kernel/src/syscall/mod.rs | 2 +- kernel/src/tasks/elf.rs | 4 +- kernel/src/tasks/mod.rs | 2 +- modules/devices/src/lib.rs | 6 +- platforms/riscv64.toml | 14 - 30 files changed, 588 insertions(+), 480 deletions(-) delete mode 100644 arch/src/x86_64/entry.rs create mode 100644 arch/src/x86_64/gdt.rs delete mode 100644 arch/src/x86_64/trap.rs delete mode 100644 platforms/riscv64.toml diff --git a/Cargo.lock b/Cargo.lock index 5c8c05ed..94ea66cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,7 +226,7 @@ dependencies = [ "log", "sync", "timestamp", - "virtio-drivers", + "virtio-drivers 0.3.0", ] [[package]] @@ -570,7 +570,7 @@ dependencies = [ "kheader", "log", "sync", - "virtio-drivers", + "virtio-drivers 0.7.1", ] [[package]] @@ -1113,7 +1113,17 @@ source = "git+https://github.com/rcore-os/virtio-drivers?rev=f1d1cbb#f1d1cbb0079 dependencies = [ "bitflags 1.3.2", "log", - "zerocopy", + "zerocopy 0.6.1", +] + +[[package]] +name = "virtio-drivers" +version = "0.7.1" +source = "git+https://github.com/rcore-os/virtio-drivers?rev=61ece50#61ece509c40f32c03378a7a037ef9863ed5deba7" +dependencies = [ + "bitflags 2.4.2", + "log", + "zerocopy 0.7.32", ] [[package]] @@ -1179,7 +1189,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.3.2", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.32", ] [[package]] @@ -1192,3 +1212,14 @@ dependencies = [ "quote", "syn 1.0.109", ] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] diff --git a/Makefile b/Makefile index 0a9266e3..b21acd3f 100644 --- a/Makefile +++ b/Makefile @@ -127,7 +127,7 @@ flash: k210-build debug: fs-img build @tmux new-session -d \ "$(QEMU_EXEC) -s -S && echo '按任意键继续' && read -n 1" && \ - tmux split-window -h "gdb-multiarch -ex 'file $(KERNEL_ELF)' -ex 'target remote localhost:1234'" && \ + tmux split-window -h "gdb-multiarch $(KERNEL_ELF) -ex 'target remote localhost:1234' -ex 'disp /16i $pc' " && \ tmux -2 attach-session -d clean: diff --git a/arch/src/aarch64/context.rs b/arch/src/aarch64/context.rs index fe05cd88..5dfcff43 100644 --- a/arch/src/aarch64/context.rs +++ b/arch/src/aarch64/context.rs @@ -126,10 +126,6 @@ impl ContextOps for Context { self.regs.x2 = ret; } - fn clear(&mut self) { - *self = Default::default(); - } - #[inline] fn set_tls(&mut self, tls: usize) { self.tpidr = tls diff --git a/arch/src/lib.rs b/arch/src/lib.rs index 56fd9bf4..cfd6d9b5 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -5,6 +5,7 @@ #![feature(stdsimd)] #![feature(const_mut_refs)] #![feature(const_slice_from_raw_parts_mut)] +#![cfg_attr(target_arch = "riscv64", feature(riscv_ext_intrinsics))] extern crate alloc; @@ -60,7 +61,6 @@ pub trait ContextOps { fn syscall_ok(&mut self); fn set_ret(&mut self, ret: usize); - fn clear(&mut self); fn set_tls(&mut self, tls: usize); } diff --git a/arch/src/loongarch64/boot.rs b/arch/src/loongarch64/boot.rs index 29620753..15343079 100644 --- a/arch/src/loongarch64/boot.rs +++ b/arch/src/loongarch64/boot.rs @@ -45,4 +45,4 @@ unsafe extern "C" fn _start() -> ! { entry = sym super::rust_tmp_main, options(noreturn), ) -} \ No newline at end of file +} diff --git a/arch/src/loongarch64/console.rs b/arch/src/loongarch64/console.rs index 92bdb11c..1df391ef 100644 --- a/arch/src/loongarch64/console.rs +++ b/arch/src/loongarch64/console.rs @@ -1,4 +1,3 @@ - use core::fmt::Write; use spin::Mutex; @@ -57,14 +56,6 @@ impl Write for Uart { /// Writes a byte to the console. pub fn console_putchar(c: u8) { - // let mut uart = COM1.lock(); - // match c { - // b'\n' => { - // uart.putchar(b'\r'); - // uart.putchar(b'\n'); - // } - // c => uart.putchar(c), - // } COM1.lock().putchar(c) } @@ -73,7 +64,7 @@ pub fn write_fmt(args: core::fmt::Arguments) { COM1.lock().write_fmt(args).unwrap(); } -/// Reads a byte from the console, or returns [`None`] if no input is available. +/// read a byte, return -1 if nothing exists. pub fn console_getchar() -> u8 { COM1.lock().getchar().unwrap_or(u8::MAX) -} \ No newline at end of file +} diff --git a/arch/src/loongarch64/context.rs b/arch/src/loongarch64/context.rs index fe05cd88..5dfcff43 100644 --- a/arch/src/loongarch64/context.rs +++ b/arch/src/loongarch64/context.rs @@ -126,10 +126,6 @@ impl ContextOps for Context { self.regs.x2 = ret; } - fn clear(&mut self) { - *self = Default::default(); - } - #[inline] fn set_tls(&mut self, tls: usize) { self.tpidr = tls diff --git a/arch/src/loongarch64/mod.rs b/arch/src/loongarch64/mod.rs index d2679d0f..f18f1ef3 100644 --- a/arch/src/loongarch64/mod.rs +++ b/arch/src/loongarch64/mod.rs @@ -7,11 +7,11 @@ mod timer; mod trap; use alloc::vec::Vec; +pub use console::{console_getchar, console_putchar}; pub use consts::*; pub use context::Context; use fdt::Fdt; pub use page_table::*; -pub use console::{console_getchar, console_putchar}; pub use timer::get_time; pub use trap::{enable_external_irq, enable_irq, init_interrupt, trap_pre_handle, user_restore}; @@ -22,7 +22,10 @@ pub fn rust_tmp_main(hart_id: usize) { ArchInterface::init_logging(); allocator::init(); - ArchInterface::add_memory_region(VIRT_ADDR_START | 0x9000_0000, VIRT_ADDR_START | (0x9000_0000 + 0x2f00_0000)); + ArchInterface::add_memory_region( + VIRT_ADDR_START | 0x9000_0000, + VIRT_ADDR_START | (0x9000_0000 + 0x2f00_0000), + ); info!("hart_id: {}", hart_id); ArchInterface::prepare_drivers(); diff --git a/arch/src/riscv64/context.rs b/arch/src/riscv64/context.rs index 6a2dea28..5034b824 100644 --- a/arch/src/riscv64/context.rs +++ b/arch/src/riscv64/context.rs @@ -86,12 +86,6 @@ impl ContextOps for Context { self.x[12] = ret; } - fn clear(&mut self) { - self.x.fill(0); - self.sepc = 0; - self.sstatus = sstatus::read(); - } - #[inline] fn set_tls(&mut self, tls: usize) { self.x[4] = tls; diff --git a/arch/src/x86_64/consts.rs b/arch/src/x86_64/consts.rs index 1713a7c7..9b6add7e 100644 --- a/arch/src/x86_64/consts.rs +++ b/arch/src/x86_64/consts.rs @@ -3,3 +3,5 @@ pub const USER_ADDR_MAX: usize = 0xbf_ffff_ffff; pub const PAGE_SIZE: usize = 4096; pub const PAGE_ITEM_COUNT: usize = 512; pub const SIG_RETURN_ADDR: usize = 0xFFFF_FF80_0000_0000; + +pub const SYSCALL_VECTOR: usize = usize::MAX / 2; diff --git a/arch/src/x86_64/context.rs b/arch/src/x86_64/context.rs index e536e737..7d8e21dd 100644 --- a/arch/src/x86_64/context.rs +++ b/arch/src/x86_64/context.rs @@ -1,5 +1,7 @@ use crate::ContextOps; +use super::gdt::GdtStruct; + /// Saved registers when a trap (interrupt or exception) occurs. #[allow(missing_docs)] #[repr(C)] @@ -21,8 +23,8 @@ pub struct Context { pub r14: usize, pub r15: usize, - // pub fs_base: usize, - // pub gs_base: usize, + pub fs_base: usize, + pub gs_base: usize, // Pushed by `trap.S` pub vector: usize, @@ -40,7 +42,14 @@ impl Context { // 创建上下文信息 #[inline] pub fn new() -> Self { + debug!( + "new_user cs: {:#x}, ss: {:#x}", + GdtStruct::UCODE64_SELECTOR.0, + GdtStruct::UDATA_SELECTOR.0 + ); Self { + cs: GdtStruct::UCODE64_SELECTOR.0 as _, + ss: GdtStruct::UDATA_SELECTOR.0 as _, ..Default::default() } } @@ -107,12 +116,8 @@ impl ContextOps for Context { self.rdx = ret; } - fn clear(&mut self) { - *self = Default::default(); - } - #[inline] - fn set_tls(&mut self, _tls: usize) { - unimplemented!("set tls is unimplemented!") + fn set_tls(&mut self, tls: usize) { + self.fs_base = tls; } } diff --git a/arch/src/x86_64/entry.rs b/arch/src/x86_64/entry.rs deleted file mode 100644 index 2bcd08b4..00000000 --- a/arch/src/x86_64/entry.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::x86_64::rust_tmp_main; -use crate::{BOOT_STACK, STACK_SIZE}; -use core::arch::global_asm; - -use super::VIRT_ADDR_START; - -use x86_64::registers::control::{Cr0Flags, Cr4Flags}; -use x86_64::registers::model_specific::EferFlags; - -/// Flags set in the 'flags' member of the multiboot header. -/// -/// (bits 1, 16: memory information, address fields in header) -const MULTIBOOT_HEADER_FLAGS: usize = 0x0001_0002; - -/// The magic field should contain this. -const MULTIBOOT_HEADER_MAGIC: usize = 0x1BADB002; - -const CR0: u64 = Cr0Flags::PROTECTED_MODE_ENABLE.bits() - | Cr0Flags::MONITOR_COPROCESSOR.bits() - | Cr0Flags::NUMERIC_ERROR.bits() - | Cr0Flags::WRITE_PROTECT.bits() - | Cr0Flags::PAGING.bits(); -const CR4: u64 = Cr4Flags::PHYSICAL_ADDRESS_EXTENSION.bits() - | Cr4Flags::PAGE_GLOBAL.bits() - | if cfg!(feature = "fp_simd") { - Cr4Flags::OSFXSR.bits() | Cr4Flags::OSXMMEXCPT_ENABLE.bits() - } else { - 0 - }; -const EFER: u64 = EferFlags::LONG_MODE_ENABLE.bits() | EferFlags::NO_EXECUTE_ENABLE.bits(); - -global_asm!( - include_str!("multiboot.S"), - mb_hdr_magic = const MULTIBOOT_HEADER_MAGIC, - mb_hdr_flags = const MULTIBOOT_HEADER_FLAGS, - entry = sym rust_tmp_main, - - offset = const VIRT_ADDR_START, - boot_stack_size = const STACK_SIZE, - boot_stack = sym BOOT_STACK, - - cr0 = const CR0, - cr4 = const CR4, - efer_msr = const x86::msr::IA32_EFER, - efer = const EFER, -); - -pub fn switch_to_kernel_page_table() { - unsafe { - core::arch::asm!( - " - .code32 - lea eax, [kernel_page_table - {offset}] - mov cr3, eax - ", - offset = const VIRT_ADDR_START - ); - } -} diff --git a/arch/src/x86_64/gdt.rs b/arch/src/x86_64/gdt.rs new file mode 100644 index 00000000..34a9855b --- /dev/null +++ b/arch/src/x86_64/gdt.rs @@ -0,0 +1,115 @@ +use core::fmt; + +use spin::once::Once; +use x86_64::instructions::tables::{lgdt, load_tss}; +use x86_64::registers::segmentation::{Segment, SegmentSelector, CS}; +use x86_64::structures::gdt::{Descriptor, DescriptorFlags}; +use x86_64::structures::{tss::TaskStateSegment, DescriptorTablePointer}; +use x86_64::{addr::VirtAddr, PrivilegeLevel}; + +#[percpu::def_percpu] +pub(super) static GDT: Once = Once::new(); + +#[percpu::def_percpu] +pub(super) static TSS: Once = Once::new(); + +#[percpu::def_percpu] +pub(super) static PERCPU_KERNEL_STACK: [u8; 0x1000] = [0u8; 0x1000]; + +/// A wrapper of the Global Descriptor Table (GDT) with maximum 16 entries. +#[repr(align(16))] +pub struct GdtStruct { + table: [u64; 16], +} + +#[allow(dead_code)] +impl GdtStruct { + /// Kernel code segment for 32-bit mode. + pub const KCODE32_SELECTOR: SegmentSelector = SegmentSelector::new(1, PrivilegeLevel::Ring0); + /// Kernel code segment for 64-bit mode. + pub const KCODE64_SELECTOR: SegmentSelector = SegmentSelector::new(2, PrivilegeLevel::Ring0); + /// Kernel data segment. + pub const KDATA_SELECTOR: SegmentSelector = SegmentSelector::new(3, PrivilegeLevel::Ring0); + /// User code segment for 32-bit mode. + pub const UCODE32_SELECTOR: SegmentSelector = SegmentSelector::new(4, PrivilegeLevel::Ring3); + /// User data segment. + pub const UDATA_SELECTOR: SegmentSelector = SegmentSelector::new(5, PrivilegeLevel::Ring3); + /// User code segment for 64-bit mode. + pub const UCODE64_SELECTOR: SegmentSelector = SegmentSelector::new(6, PrivilegeLevel::Ring3); + /// TSS segment. + pub const TSS_SELECTOR: SegmentSelector = SegmentSelector::new(7, PrivilegeLevel::Ring0); + + /// Constructs a new GDT struct that filled with the default segment + /// descriptors, including the given TSS segment. + pub fn new(tss: &'static TaskStateSegment) -> Self { + let mut table = [0; 16]; + // first 3 entries are the same as in multiboot.S + table[1] = DescriptorFlags::KERNEL_CODE32.bits(); // 0x00cf9b000000ffff + table[2] = DescriptorFlags::KERNEL_CODE64.bits(); // 0x00af9b000000ffff + table[3] = DescriptorFlags::KERNEL_DATA.bits(); // 0x00cf93000000ffff + table[4] = DescriptorFlags::USER_CODE32.bits(); // 0x00cffb000000ffff + table[5] = DescriptorFlags::USER_DATA.bits(); // 0x00cff3000000ffff + table[6] = DescriptorFlags::USER_CODE64.bits(); // 0x00affb000000ffff + if let Descriptor::SystemSegment(low, high) = Descriptor::tss_segment(tss) { + table[7] = low; + table[8] = high; + } + Self { table } + } + + /// Returns the GDT pointer (base and limit) that can be used in `lgdt` + /// instruction. + pub fn pointer(&self) -> DescriptorTablePointer { + DescriptorTablePointer { + base: VirtAddr::new(self.table.as_ptr() as u64), + limit: (core::mem::size_of_val(&self.table) - 1) as u16, + } + } + + /// Loads the GDT into the CPU (executes the `lgdt` instruction), and + /// updates the code segment register (`CS`). + /// + /// # Safety + /// + /// This function is unsafe because it manipulates the CPU's privileged + /// states. + pub unsafe fn load(&'static self) { + lgdt(&self.pointer()); + CS::set_reg(Self::KCODE64_SELECTOR); + } + + /// Loads the TSS into the CPU (executes the `ltr` instruction). + /// + /// # Safety + /// + /// This function is unsafe because it manipulates the CPU's privileged + /// states. + pub unsafe fn load_tss(&'static self) { + load_tss(Self::TSS_SELECTOR); + } +} + +impl fmt::Debug for GdtStruct { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("GdtStruct") + .field("pointer", &self.pointer()) + .field("table", &self.table) + .finish() + } +} + +pub fn init() { + unsafe { + let tss = TSS.current_ref_raw(); + let gdt = GDT.current_ref_mut_raw(); + tss.call_once(|| TaskStateSegment::new()); + gdt.call_once(|| GdtStruct::new(tss.get_unchecked())); + let gdt = gdt.get_unchecked(); + gdt.load(); + gdt.load_tss(); + + TSS.with_current(|tss| { + tss.get_mut_unchecked().privilege_stack_table[0] = VirtAddr::from_ptr(PERCPU_KERNEL_STACK.current_ptr()); + }); + } +} diff --git a/arch/src/x86_64/interrupt.rs b/arch/src/x86_64/interrupt.rs index ba715469..af7fb6bb 100644 --- a/arch/src/x86_64/interrupt.rs +++ b/arch/src/x86_64/interrupt.rs @@ -1,6 +1,12 @@ use core::arch::{asm, global_asm}; -use crate::{Context, TrapType}; +use x86_64::registers::model_specific::{Efer, EferFlags, KernelGsBase, LStar, SFMask, Star}; +use x86_64::registers::rflags::RFlags; +use x86_64::VirtAddr; + +use x86::{controlregs::cr2, irq::*}; + +use crate::{x86_64::gdt::GdtStruct, Context, TrapType}; global_asm!( r" @@ -27,166 +33,98 @@ global_asm!( " ); -// 内核中断回调 +global_asm!(include_str!("trap.S")); + +#[cfg(target_arch = "x86_64")] +#[no_mangle] +#[percpu::def_percpu] +static USER_RSP: usize = 0; + +#[cfg(target_arch = "x86_64")] #[no_mangle] +#[percpu::def_percpu] +static KERNEL_RSP: usize = 0; + +// 内核中断回调 fn kernel_callback(context: &mut Context) -> usize { - // let scause = scause::read(); - // let stval = stval::read(); - // let int_table = unsafe { interrupt_table() }; - // debug!( - // "内核态中断发生: {:#x} {:?} stval {:#x} sepc: {:#x}", - // scause.bits(), - // scause.cause(), - // stval, - // context.sepc - // ); - // let trap_type = match scause.cause() { - // // 中断异常 - // Trap::Exception(Exception::Breakpoint) => { - // context.sepc += 2; - // TrapType::Breakpoint - // } - // Trap::Exception(Exception::LoadFault) => { - // if stval > VIRT_ADDR_START { - // panic!("kernel error: {:#x}", stval); - // } - // TrapType::Unknown - // } - // // 时钟中断 - // Trap::Interrupt(Interrupt::SupervisorTimer) => { - // timer::set_next_timeout(); - // add_irq(5); - // TrapType::Time - // } - // Trap::Exception(Exception::UserEnvCall) => { - // info!("info syscall: {}", context.x[17]); - // context.sepc += 4; - // TrapType::UserEnvCall - // } - // Trap::Interrupt(Interrupt::SupervisorExternal) => TrapType::SupervisorExternal, - // // // 缺页异常 - // // Trap::Exception(Exception::StorePageFault) => handle_page_fault(context, stval), - // // // 加载页面错误 - // // Trap::Exception(Exception::LoadPageFault) => { - // // panic!("加载权限异常 地址:{:#x}", stval) - // // }, - // // Trap::Exception(Exception::InstructionPageFault) => handle_page_fault(context, stval), - // // // 页面未对齐异常 - // // Trap::Exception(Exception::StoreMisaligned) => { - // // info!("页面未对齐"); - // // } - // // 其他情况,终止当前线程 - // Trap::Exception(Exception::StorePageFault) => TrapType::StorePageFault(stval), - // Trap::Exception(Exception::InstructionPageFault) => TrapType::InstructionPageFault(stval), - // Trap::Exception(Exception::IllegalInstruction) => TrapType::IllegalInstruction(stval), - // _ => { - // // warn!("未知中断"); - // error!( - // "内核态中断发生: {:#x} {:?} stval {:#x} sepc: {:#x}", - // scause.bits(), - // scause.cause(), - // stval, - // context.sepc - // ); - // panic!("未知中断") - // } - // }; - // if let Some(func) = int_table { - // func(context, trap_type); - // } + match context.vector as u8 { + PAGE_FAULT_VECTOR => { + panic!( + "Kernel #PF @ {:#x}, fault_vaddr={:#x}, error_code={:#x}:\n{:#x?}", + context.rip, + unsafe { cr2() }, + context.error_code, + context, + ); + } + BREAKPOINT_VECTOR => debug!("#BP @ {:#x} ", context.rip), + GENERAL_PROTECTION_FAULT_VECTOR => { + panic!( + "#GP @ {:#x}, error_code={:#x}:\n{:#x?}", + context.rip, context.error_code, context + ); + } + // IRQ_VECTOR_START..=IRQ_VECTOR_END => crate::trap::handle_irq_extern(tf.vector as _), + _ => { + panic!( + "Unhandled exception {} (error_code = {:#x}) @ {:#x}:\n{:#x?}", + context.vector, context.error_code, context.rip, context + ); + } + } context as *const Context as usize } -pub fn trap_pre_handle(context: &mut Context) -> TrapType { - // let scause = scause::read(); - // let stval = stval::read(); - // debug!( - // "用户态中断发生: {:#x} {:?} stval {:#x} sepc: {:#x}", - // scause.bits(), - // scause.cause(), - // stval, - // context.sepc - // ); - // match scause.cause() { - // // 中断异常 - // Trap::Exception(Exception::Breakpoint) => { - // context.sepc += 2; - // TrapType::Breakpoint - // } - // Trap::Exception(Exception::LoadFault) => { - // shutdown(); - // } - // // 时钟中断 - // Trap::Interrupt(Interrupt::SupervisorTimer) => { - // timer::set_next_timeout(); - // add_irq(5); - // TrapType::Time - // } - // Trap::Exception(Exception::StorePageFault) => TrapType::StorePageFault(stval), - // Trap::Exception(Exception::InstructionPageFault) => TrapType::InstructionPageFault(stval), - // Trap::Exception(Exception::IllegalInstruction) => { - // TrapType::IllegalInstruction(context.sepc) - // } - // Trap::Exception(Exception::UserEnvCall) => TrapType::UserEnvCall, - // Trap::Exception(Exception::LoadPageFault) => TrapType::LoadPageFault(stval), - // Trap::Interrupt(Interrupt::SupervisorExternal) => TrapType::SupervisorExternal, - // _ => { - // error!( - // "用户态中断发生: {:#x} {:?} stval {:#x} sepc: {:#x}", - // scause.bits(), - // scause.cause(), - // stval, - // context.sepc - // ); - // TrapType::Unknown - // } - // } +pub fn trap_pre_handle(_context: &mut Context) -> TrapType { todo!("todo trap_pre_handle") } #[naked] +#[no_mangle] pub unsafe extern "C" fn kernelvec() { asm!( - // 宏定义 - // r" - // .align 4 - // .altmacro - // .set REG_SIZE, 8 - // .set CONTEXT_SIZE, 34 - // ", - // // 保存寄存器信息 - // " addi sp, sp, CONTEXT_SIZE*-8 - // sd x1, 1*8(sp) - // addi x1, sp, 34*8 - // sd x1, 2*8(sp) - // .set n, 3 - // .rept 29 - // SAVE_N %n - // .set n, n + 1 - // .endr - // ", - // r" csrr t0, sstatus - // csrr t1, sepc - // sd t0, 32*8(sp) - // sd t1, 33*8(sp) - // add a0, x0, sp", - // // 调用内核处理函数 - // " call kernel_callback ", - // // 恢复上下文信息 - // " ld s1, 32*8(sp) - // ld s2, 33*8(sp) - // csrw sstatus, s1 - // csrw sepc, s2 - // ld x1, 1*8(sp) - // .set n, 3 - // .rept 29 - // LOAD_N %n - // .set n, n + 1 - // .endr - // ld x2, 2*8(sp) - // sret - // ", - "", + r" + sub rsp, 16 # push fs_base, gs_base + + push r15 + push r14 + push r13 + push r12 + push r11 + push r10 + push r9 + push r8 + push rdi + push rsi + push rbp + push rbx + push rdx + push rcx + push rax + + mov rdi, rsp + call {trap_handler} + + pop rax + pop rcx + pop rdx + pop rbx + pop rbp + pop rsi + pop rdi + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + add rsp, 32 # pop fs_base, gs_base, vector, error_code + iretq + ", + trap_handler = sym kernel_callback, options(noreturn) ) } @@ -198,23 +136,55 @@ pub extern "C" fn user_restore(context: *mut Context) { asm!( // Save callee saved registers and cs and others. r" + mov ecx, 0xC0000100 + rdmsr + shl rdx, 32 + or rax, rdx + push rax # push fsbase + push rbp push rbx push r12 push r13 push r14 push r15 - mov rax, cs - push rax - mov rcx, ss - push rcx + + mov gs:[offset __PERCPU_KERNEL_RSP], rsp ", - // push fs_base + // Write fs_base and gs_base " mov ecx, 0xC0000100 - rdmsr - mov [rsp + 18*8+4], edx - mov [rsp + 18*8], eax # push fabase + mov edx, [rdi + 15*8+4] + mov eax, [rdi + 15*8] + wrmsr # pop fsbase + mov ecx, 0xC0000102 + mov edx, [rdi + 16*8+4] + mov eax, [rdi + 16*8] + wrmsr # pop gsbase to kernel_gsbase + ", + // push fs_base + " + mov rsp, rdi + pop rax + pop rcx + pop rdx + pop rbx + pop rbp + pop rsi + pop rdi + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + add rsp, 32 # pop fs_base,gs_base,vector,error_code + + swapgs + iretq ", options(noreturn) ) @@ -225,77 +195,108 @@ pub extern "C" fn user_restore(context: *mut Context) { #[no_mangle] pub unsafe extern "C" fn uservec() { asm!( - // r" - // .altmacro - // .align 2 - // .set REG_SIZE, 8 - // .set CONTEXT_SIZE, 34 - // ", - // // a0(x10) 是在 user_restore 时传入的 context 地址. - // // 因此将中断时用户的 寄存器存在这个地方 - // " csrrw sp, sscratch, sp - // sd tp, 0(sp) - // ld tp, 16*8(sp) # 加载从x10保存的 context地址 - // ", - // // 保存 general registers, 除了 sp, tp - // " SAVE_TP_N 1 - // SAVE_TP_N 3 - // .set n, 5 - // .rept 27 - // SAVE_TP_N %n - // .set n, n+1 - // .endr - // ", - // // 保存特殊寄存器信息,sscratch 是用户 sp 地址. - // // 保存 sp 寄存器 - // " csrr t0, sstatus - // csrr t1, sepc - // csrr t2, sscratch - // sd t0, 32*8(tp) - // sd t1, 33*8(tp) - // sd t2, 2*8(tp) - // .word 0x10823827 - // .word 0x10923c27 - // ", - // // fsd fs0, 272(tp) - // // fsd fs1, 280(tp) - // // 保存 tp 寄存器,到此处所有的用户态寄存器已经保存 - // " ld a0, 0(sp) - // sd a0, 4*8(tp) - // ", - // // 恢复内核上下文信息, 仅恢复 callee-saved 寄存器和 ra、gp、tp - // " - // ld gp, 8*2(sp) - // ld tp, 8*3(sp) - // ld s0, 8*4(sp) - // ld s1, 8*5(sp) - // ld s2, 8*6(sp) - // ld s3, 8*7(sp) - // ld s4, 8*8(sp) - // ld s5, 8*9(sp) - // ld s6, 8*10(sp) - // ld s7, 8*11(sp) - // ld s8, 8*12(sp) - // ld s9, 8*13(sp) - // ld s10, 8*14(sp) - // ld s11, 8*15(sp) - // ld ra, 8*17(sp) - - // ld sp, 8(sp) - - // la a0, {kernelvec} - // csrw stvec, a0 - // ", - // // 回收栈 - // " addi sp, sp, 18*8 - // ret - // ", - // kernelvec = sym kernelvec, - "", + r" + mov ecx, 0xC0000100 + rdmsr + mov [rsp + 18*8+4], edx + mov [rsp + 18*8], eax # push fabase + ", options(noreturn) ); } +#[no_mangle] +fn x86_syscall_handler(tf: &mut Context) { + debug!("syscall: {:#x?}", tf); + panic!("syscall_error") + // tf.rax = handle_syscall(tf.get_syscall_num(), tf.get_syscall_args()) as u64; +} + +pub fn init_syscall() { + LStar::write(VirtAddr::new(syscall_entry as usize as _)); + Star::write( + GdtStruct::UCODE64_SELECTOR, + GdtStruct::UDATA_SELECTOR, + GdtStruct::KCODE64_SELECTOR, + GdtStruct::KDATA_SELECTOR, + ) + .unwrap(); + SFMask::write( + RFlags::TRAP_FLAG + | RFlags::INTERRUPT_FLAG + | RFlags::DIRECTION_FLAG + | RFlags::IOPL_LOW + | RFlags::IOPL_HIGH + | RFlags::NESTED_TASK + | RFlags::ALIGNMENT_CHECK, + ); // TF | IF | DF | IOPL | AC | NT (0x47700) + unsafe { + Efer::update(|efer| *efer |= EferFlags::SYSTEM_CALL_EXTENSIONS); + } + KernelGsBase::write(VirtAddr::new(0)); +} + +#[naked] +unsafe extern "C" fn syscall_entry() { + asm!( + r" + swapgs + mov gs:[offset __PERCPU_USER_RSP], rsp + mov rsp, gs:[offset __PERCPU_KERNEL_RSP] + + sub rsp, 8 // skip user_ss + push gs:[offset __PERCPU_USER_RSP] // user_rsp + push r11 // rflags + mov [rsp - 2 * 8], rcx // rip + sub rsp, 6 * 8 // skip until general registers + + push r15 + push r14 + push r13 + push r12 + push r11 + push r10 + push r9 + push r8 + push rdi + push rsi + push rbp + push rbx + push rdx + push rcx + push rax + + mov rdi, rsp + call x86_syscall_handler + + pop rax + pop rcx + pop rdx + pop rbx + pop rbp + pop rsi + pop rdi + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + add rsp, 7 * 8 + mov rcx, [rsp - 5 * 8] // rip + mov r11, [rsp - 3 * 8] // rflags + mov rsp, [rsp - 2 * 8] // user_rsp + + swapgs + sysretq + ", + options(noreturn) + ) +} + #[allow(dead_code)] #[inline(always)] pub fn enable_irq() { @@ -314,6 +315,8 @@ pub fn enable_external_irq() { } pub fn init_interrupt() { + // Test break point. + unsafe { core::arch::asm!("int 3") } enable_irq() } diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index c0cd5240..a05d5425 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -1,20 +1,19 @@ mod consts; mod context; -mod entry; +mod gdt; mod idt; mod interrupt; mod multiboot; mod page_table; mod pic; mod sigtrx; -mod trap; mod uart; use ::multiboot::information::MemoryType; pub use consts::*; pub use context::Context; -pub use entry::switch_to_kernel_page_table; pub use interrupt::*; +pub use multiboot::switch_to_kernel_page_table; pub use page_table::*; pub use uart::*; @@ -41,6 +40,8 @@ fn rust_tmp_main(magic: usize, mboot_ptr: usize) { allocator::init(); percpu::init(1); percpu::set_local_thread_pointer(0); + gdt::init(); + interrupt::init_syscall(); info!( "TEST CPU ID: {} ptr: {:#x}", diff --git a/arch/src/x86_64/multiboot.S b/arch/src/x86_64/multiboot.S index 6975ef95..5741307c 100644 --- a/arch/src/x86_64/multiboot.S +++ b/arch/src/x86_64/multiboot.S @@ -18,7 +18,7 @@ multiboot_header: .int multiboot_header - {offset} # header_addr .int _skernel - {offset} # load_addr .int _load_end - {offset} # load_end - .int _ebss - {offset} # bss_end_addr + .int end - {offset} # bss_end_addr .int _start - {offset} # entry_addr # Common code in 32-bit, prepare states to enter 64-bit. diff --git a/arch/src/x86_64/multiboot.rs b/arch/src/x86_64/multiboot.rs index 99425f74..2e3ef1e0 100644 --- a/arch/src/x86_64/multiboot.rs +++ b/arch/src/x86_64/multiboot.rs @@ -1,10 +1,33 @@ extern crate core; +use crate::x86_64::rust_tmp_main; +use crate::{BOOT_STACK, STACK_SIZE}; +use core::arch::global_asm; use core::{mem, slice}; use multiboot::information::{MemoryManagement, Multiboot, PAddr}; +use x86_64::registers::control::{Cr0Flags, Cr4Flags}; +use x86_64::registers::model_specific::EferFlags; use crate::VIRT_ADDR_START; +/// Flags set in the 'flags' member of the multiboot header. +/// +/// (bits 1, 16: memory information, address fields in header) +const MULTIBOOT_HEADER_FLAGS: usize = 0x0001_0002; + +/// The magic field should contain this. +const MULTIBOOT_HEADER_MAGIC: usize = 0x1BADB002; + +const CR0: u64 = Cr0Flags::PROTECTED_MODE_ENABLE.bits() + | Cr0Flags::MONITOR_COPROCESSOR.bits() + | Cr0Flags::NUMERIC_ERROR.bits() + | Cr0Flags::WRITE_PROTECT.bits() + | Cr0Flags::PAGING.bits(); +const CR4: u64 = Cr4Flags::PHYSICAL_ADDRESS_EXTENSION.bits() | Cr4Flags::PAGE_GLOBAL.bits(); +const EFER: u64 = EferFlags::LONG_MODE_ENABLE.bits() | EferFlags::NO_EXECUTE_ENABLE.bits(); + +static mut MEM: Mem = Mem; + struct Mem; impl MemoryManagement for Mem { @@ -25,10 +48,37 @@ impl MemoryManagement for Mem { } } -static mut MEM: Mem = Mem; - /// mboot_ptr is the initial pointer to the multiboot structure /// provided in %ebx on start-up. pub fn use_multiboot(mboot_ptr: PAddr) -> Option> { unsafe { Multiboot::from_ptr(mboot_ptr, &mut MEM) } } + +global_asm!( + include_str!("multiboot.S"), + mb_hdr_magic = const MULTIBOOT_HEADER_MAGIC, + mb_hdr_flags = const MULTIBOOT_HEADER_FLAGS, + entry = sym rust_tmp_main, + + offset = const VIRT_ADDR_START, + boot_stack_size = const STACK_SIZE, + boot_stack = sym BOOT_STACK, + + cr0 = const CR0, + cr4 = const CR4, + efer_msr = const x86::msr::IA32_EFER, + efer = const EFER, +); + +pub fn switch_to_kernel_page_table() { + unsafe { + core::arch::asm!( + " + .code32 + lea eax, [kernel_page_table - {offset}] + mov cr3, eax + ", + offset = const VIRT_ADDR_START + ); + } +} diff --git a/arch/src/x86_64/page_table.rs b/arch/src/x86_64/page_table.rs index 90e7cbae..e2e3f4ca 100644 --- a/arch/src/x86_64/page_table.rs +++ b/arch/src/x86_64/page_table.rs @@ -18,11 +18,14 @@ impl From for PTFlags { if flags.contains(MappingFlags::U) { res |= Self::US; } - if flags.contains(MappingFlags::A) { - res |= Self::A; - } - if flags.contains(MappingFlags::D) { - res |= Self::D; + // if flags.contains(MappingFlags::A) { + // res |= Self::A; + // } + // if flags.contains(MappingFlags::D) { + // res |= Self::D; + // } + if flags.contains(MappingFlags::X) { + res.remove(Self::XD); } res } @@ -51,12 +54,8 @@ impl PageTable { #[inline] pub fn change(&self) { unsafe { - core::arch::asm!( - " - mov cr3, {} - ", - in(reg) self.0.0 - ); + debug!("page_table: {:#x}", self.0 .0); + core::arch::asm!("mov cr3, {}", in(reg) self.0.0); flush_all(); } } @@ -70,7 +69,7 @@ impl PageTable { if !pml4[pml4_index].is_present() { pml4[pml4_index] = PML4Entry::new( ArchInterface::frame_alloc_persist().to_addr().into(), - PML4Flags::P | PML4Flags::RW, + PML4Flags::P | PML4Flags::RW | PML4Flags::US, ); } @@ -80,7 +79,7 @@ impl PageTable { if !pdpt[pdpt_index].is_present() { pdpt[pdpt_index] = PDPTEntry::new( ArchInterface::frame_alloc_persist().to_addr().into(), - PDPTFlags::P | PDPTFlags::RW, + PDPTFlags::P | PDPTFlags::RW | PDPTFlags::US, ); } @@ -90,7 +89,7 @@ impl PageTable { if !pd[pd_index].is_present() { pd[pd_index] = PDEntry::new( ArchInterface::frame_alloc_persist().to_addr().into(), - PDFlags::P | PDFlags::RW, + PDFlags::P | PDFlags::RW | PDFlags::US, ); } diff --git a/arch/src/x86_64/trap.S b/arch/src/x86_64/trap.S index 518860eb..3d06bd70 100644 --- a/arch/src/x86_64/trap.S +++ b/arch/src/x86_64/trap.S @@ -19,6 +19,7 @@ .endm .section .text +.global trap_from_user .code64 _trap_handlers: .set i, 0 @@ -29,46 +30,10 @@ _trap_handlers: .Ltrap_common: test byte ptr [rsp + 3 * 8], 3 # swap GS if it comes from user space - jnz .Ltrap_from_user - push r15 - push r14 - push r13 - push r12 - push r11 - push r10 - push r9 - push r8 - push rdi - push rsi - push rbp - push rbx - push rdx - push rcx - push rax - - mov rdi, rsp - call x86_trap_handler - - pop rax - pop rcx - pop rdx - pop rbx - pop rbp - pop rsi - pop rdi - pop r8 - pop r9 - pop r10 - pop r11 - pop r12 - pop r13 - pop r14 - pop r15 - - add rsp, 16 # pop vector, error_code - iretq + jnz trap_from_user + jmp kernelvec -.Ltrap_from_user: +trap_from_user: push r15 push r14 push r13 diff --git a/arch/src/x86_64/trap.rs b/arch/src/x86_64/trap.rs deleted file mode 100644 index c1774931..00000000 --- a/arch/src/x86_64/trap.rs +++ /dev/null @@ -1,40 +0,0 @@ -use core::arch::global_asm; - -use x86::{controlregs::cr2, irq::*}; - -use crate::Context; - -global_asm!(include_str!("trap.S")); - -#[no_mangle] -#[percpu::def_percpu] -static KERNEL_RSP: usize = 1; - -#[no_mangle] -fn x86_trap_handler(tf: &mut Context) { - match tf.vector as u8 { - PAGE_FAULT_VECTOR => { - panic!( - "Kernel #PF @ {:#x}, fault_vaddr={:#x}, error_code={:#x}:\n{:#x?}", - tf.rip, - unsafe { cr2() }, - tf.error_code, - tf, - ); - } - BREAKPOINT_VECTOR => debug!("#BP @ {:#x} ", tf.rip), - GENERAL_PROTECTION_FAULT_VECTOR => { - panic!( - "#GP @ {:#x}, error_code={:#x}:\n{:#x?}", - tf.rip, tf.error_code, tf - ); - } - // IRQ_VECTOR_START..=IRQ_VECTOR_END => crate::trap::handle_irq_extern(tf.vector as _), - _ => { - panic!( - "Unhandled exception {} (error_code = {:#x}) @ {:#x}:\n{:#x?}", - tf.vector, tf.error_code, tf.rip, tf - ); - } - } -} diff --git a/drivers/general-plic/src/lib.rs b/drivers/general-plic/src/lib.rs index d1066069..d181ef56 100644 --- a/drivers/general-plic/src/lib.rs +++ b/drivers/general-plic/src/lib.rs @@ -6,7 +6,7 @@ extern crate alloc; mod plic; use alloc::sync::Arc; -use arch::{enable_external_irq, VIRT_ADDR_START}; +use arch::VIRT_ADDR_START; use devices::{ device::{DeviceType, Driver, IntDriver}, driver_define, diff --git a/drivers/kvirtio/Cargo.toml b/drivers/kvirtio/Cargo.toml index 71b65767..f73ad057 100644 --- a/drivers/kvirtio/Cargo.toml +++ b/drivers/kvirtio/Cargo.toml @@ -10,7 +10,7 @@ arch = { path = "../../arch" } fdt = "0.1.5" log = "0.4" sync = { path = "../../modules/sync" } -virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "f1d1cbb"} +virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "61ece50"} kheader = { path = "../../modules/kheader" } devices = { path = "../../modules/devices" } -frame_allocator = { path = "../../modules/frame_allocator" } \ No newline at end of file +frame_allocator = { path = "../../modules/frame_allocator" } diff --git a/drivers/kvirtio/src/lib.rs b/drivers/kvirtio/src/lib.rs index 3264b19e..55e3c6cb 100644 --- a/drivers/kvirtio/src/lib.rs +++ b/drivers/kvirtio/src/lib.rs @@ -16,14 +16,20 @@ use alloc::{sync::Arc, vec::Vec}; use arch::VIRT_ADDR_START; use devices::{ device::{Driver, UnsupportedDriver}, - driver_define, + driver_define, node_to_interrupts, ALL_DEVICES, }; use fdt::node::FdtNode; use virtio_drivers::transport::{ mmio::{MmioTransport, VirtIOHeader}, + pci::{ + bus::{BarInfo, Cam, Command, DeviceFunction, PciRoot}, + virtio_device_type, PciTransport, + }, DeviceType, Transport, }; +use crate::virtio_impl::HalImpl; + pub fn init_mmio(node: &FdtNode) -> Arc { if let Some(reg) = node.reg().and_then(|mut reg| reg.next()) { let paddr = reg.starting_address as usize; @@ -50,9 +56,10 @@ pub fn init_mmio(node: &FdtNode) -> Arc { } fn virtio_device(transport: MmioTransport, node: &FdtNode) -> Arc { + let irqs = node_to_interrupts(node); match transport.device_type() { - DeviceType::Block => virtio_blk::init(transport, node), - DeviceType::Input => virtio_input::init(transport, node), + DeviceType::Block => virtio_blk::init(transport, irqs), + DeviceType::Input => virtio_input::init(transport, irqs), DeviceType::Network => virtio_net::init(transport), device_type => { warn!("Unrecognized virtio device: {:?}", device_type); @@ -61,4 +68,79 @@ fn virtio_device(transport: MmioTransport, node: &FdtNode) -> Arc { } } +fn enumerate_pci(mmconfig_base: *mut u8) { + info!("mmconfig_base = {:#x}", mmconfig_base as usize); + + let mut pci_root = unsafe { PciRoot::new(mmconfig_base, Cam::Ecam) }; + for (device_function, info) in pci_root.enumerate_bus(0) { + let (status, command) = pci_root.get_status_command(device_function); + info!( + "Found {} at {}, status {:?} command {:?}", + info, device_function, status, command + ); + if let Some(virtio_type) = virtio_device_type(&info) { + info!(" VirtIO {:?}", virtio_type); + + // Enable the device to use its BARs. + pci_root.set_command( + device_function, + Command::IO_SPACE | Command::MEMORY_SPACE | Command::BUS_MASTER, + ); + dump_bar_contents(&mut pci_root, device_function, 4); + + let mut transport = + PciTransport::new::(&mut pci_root, device_function).unwrap(); + info!( + "Detected virtio PCI device with device type {:?}, features {:#018x}", + transport.device_type(), + transport.read_device_features(), + ); + virtio_device_probe(transport); + } + } +} + +fn virtio_device_probe(transport: impl Transport + 'static) { + let device = match transport.device_type() { + DeviceType::Block => Some(virtio_blk::init(transport, Vec::new())), + // DeviceType::Input => virtio_input::init(transport, Vec::new()), + // DeviceType::Network => virtio_net(transport), + t => { + warn!("Unrecognized virtio device: {:?}", t); + None + } + }; + + if let Some(device) = device { + info!("is locked: {}", ALL_DEVICES.is_locked()); + ALL_DEVICES.lock().add_device(device); + } +} + +fn dump_bar_contents(root: &mut PciRoot, device_function: DeviceFunction, bar_index: u8) { + let bar_info = root.bar_info(device_function, bar_index).unwrap(); + trace!("Dumping bar {}: {:#x?}", bar_index, bar_info); + if let BarInfo::Memory { address, size, .. } = bar_info { + let start = address as *const u8; + unsafe { + let mut buf = [0u8; 32]; + for i in 0..size / 32 { + let ptr = start.add(i as usize * 32); + core::ptr::copy(ptr, buf.as_mut_ptr(), 32); + if buf.iter().any(|b| *b != 0xff) { + trace!(" {:?}: {:x?}", ptr, buf); + } + } + } + } + trace!("End of dump"); +} + +#[cfg(not(target_arch = "x86_64"))] driver_define!("virtio,mmio", init_mmio); + +#[cfg(target_arch = "x86_64")] +driver_define!({ + enumerate_pci((0xB000_0000usize | VIRT_ADDR_START) as _); + None +}); diff --git a/drivers/kvirtio/src/virtio_blk.rs b/drivers/kvirtio/src/virtio_blk.rs index 3fc1b5b3..0c8a2384 100644 --- a/drivers/kvirtio/src/virtio_blk.rs +++ b/drivers/kvirtio/src/virtio_blk.rs @@ -1,23 +1,22 @@ use alloc::sync::Arc; use alloc::vec::Vec; use devices::device::{BlkDriver, DeviceType, Driver}; -use devices::{node_to_interrupts, register_device_irqs}; -use fdt::node::FdtNode; +use devices::register_device_irqs; use sync::Mutex; use virtio_drivers::device::blk::VirtIOBlk; -use virtio_drivers::transport::mmio::MmioTransport; +use virtio_drivers::transport::Transport; use super::virtio_impl::HalImpl; -pub struct VirtIOBlock { - inner: Mutex>, +pub struct VirtIOBlock { + inner: Mutex>, irqs: Vec, } -unsafe impl Sync for VirtIOBlock {} -unsafe impl Send for VirtIOBlock {} +unsafe impl Sync for VirtIOBlock {} +unsafe impl Send for VirtIOBlock {} -impl Driver for VirtIOBlock { +impl Driver for VirtIOBlock { fn interrupts(&self) -> &[u32] { &self.irqs } @@ -31,29 +30,28 @@ impl Driver for VirtIOBlock { } } -impl BlkDriver for VirtIOBlock { +impl BlkDriver for VirtIOBlock { fn read_block(&self, block_id: usize, buf: &mut [u8]) { self.inner .lock() - .read_block(block_id, buf) + .read_blocks(block_id, buf) .expect("can't read block by virtio block"); } fn write_block(&self, block_id: usize, buf: &[u8]) { self.inner .lock() - .write_block(block_id, buf) + .write_blocks(block_id, buf) .expect("can't write block by virtio block"); } } -pub fn init(transport: MmioTransport, node: &FdtNode) -> Arc { +pub fn init(transport: T, irqs: Vec) -> Arc { let blk_device = Arc::new(VirtIOBlock { inner: Mutex::new( - VirtIOBlk::::new(transport) - .expect("failed to create blk driver"), + VirtIOBlk::::new(transport).expect("failed to create blk driver"), ), - irqs: node_to_interrupts(node), + irqs, }); register_device_irqs(blk_device.clone()); diff --git a/drivers/kvirtio/src/virtio_input.rs b/drivers/kvirtio/src/virtio_input.rs index 19bcb28a..808b759f 100644 --- a/drivers/kvirtio/src/virtio_input.rs +++ b/drivers/kvirtio/src/virtio_input.rs @@ -1,8 +1,7 @@ use alloc::sync::Arc; use alloc::vec::Vec; use devices::device::{DeviceType, Driver, InputDriver}; -use devices::IRQ_MANAGER; -use fdt::node::FdtNode; +use devices::register_device_irqs; use sync::Mutex; use virtio_drivers::device::input::VirtIOInput as VirtIOInputWrapper; use virtio_drivers::transport::mmio::MmioTransport; @@ -45,22 +44,15 @@ impl InputDriver for VirtIOInput { } } -pub fn init(transport: MmioTransport, node: &FdtNode) -> Arc { +pub fn init(transport: MmioTransport, irqs: Vec) -> Arc { let input_device = Arc::new(VirtIOInput { _inner: Mutex::new( VirtIOInputWrapper::::new(transport) .expect("failed to create blk driver"), ), - interrupts: node - .interrupts() - .map(|x| x.map(|x| x as u32).collect()) - .unwrap_or_default(), - }); - node.interrupts().map(|x| { - x.for_each(|x| { - IRQ_MANAGER.lock().insert(x as _, input_device.clone()); - }) + interrupts: irqs, }); + register_device_irqs(input_device.clone()); info!("Initailize virtio-iput device"); input_device } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 06d025b3..7f771ce7 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -10,7 +10,7 @@ mod task; mod time; pub use socket::NET_SERVER; -pub use task::{cache_task_template, exec_with_process}; +pub use task::exec_with_process; use log::warn; diff --git a/kernel/src/tasks/elf.rs b/kernel/src/tasks/elf.rs index aca5be9e..f43fa420 100644 --- a/kernel/src/tasks/elf.rs +++ b/kernel/src/tasks/elf.rs @@ -1,5 +1,5 @@ use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec}; -use arch::{ContextOps, VirtPage, PAGE_SIZE}; +use arch::{Context, ContextOps, VirtPage, PAGE_SIZE}; use executor::{AsyncTask, MemType, UserTask}; use log::warn; use xmas_elf::{ @@ -127,7 +127,7 @@ pub fn init_task_stack( let mut tcb = user_task.tcb.write(); - tcb.cx.clear(); + tcb.cx = Context::new(); tcb.cx.set_sp(0x8000_0000); // stack top; tcb.cx.set_sepc(base + entry_point); tcb.cx.set_tls(tls); diff --git a/kernel/src/tasks/mod.rs b/kernel/src/tasks/mod.rs index 3da348a7..1b7ba4a1 100644 --- a/kernel/src/tasks/mod.rs +++ b/kernel/src/tasks/mod.rs @@ -14,7 +14,7 @@ pub mod elf; mod initproc; pub use async_ops::{ - futex_requeue, futex_wake, NextTick, WaitFutex, WaitHandleAbleSignal, WaitPid, WaitSignal, + futex_requeue, futex_wake, WaitFutex, WaitHandleAbleSignal, WaitPid, WaitSignal, }; pub enum UserTaskControlFlow { diff --git a/modules/devices/src/lib.rs b/modules/devices/src/lib.rs index a950a45c..dc0e84cf 100644 --- a/modules/devices/src/lib.rs +++ b/modules/devices/src/lib.rs @@ -87,14 +87,12 @@ pub fn init_device(device_tree: usize) { /// This function will init drivers #[inline] pub fn prepare_drivers() { - let mut all_devices = ALL_DEVICES.lock(); DRIVERS_INIT.iter().for_each(|f| { - f().map(|device| all_devices.add_device(device)); + f().map(|device| ALL_DEVICES.lock().add_device(device)); }); } pub fn try_to_add_device(node: &FdtNode) { - let mut all_devices = ALL_DEVICES.lock(); let driver_manager = DRIVER_REGS.lock(); if let Some(compatible) = node.compatible() { info!( @@ -104,7 +102,7 @@ pub fn try_to_add_device(node: &FdtNode) { ); for compati in compatible.all() { if let Some(f) = driver_manager.get(compati) { - all_devices.add_device(f(&node)); + ALL_DEVICES.lock().add_device(f(&node)); break; } } diff --git a/platforms/riscv64.toml b/platforms/riscv64.toml deleted file mode 100644 index d93cf61b..00000000 --- a/platforms/riscv64.toml +++ /dev/null @@ -1,14 +0,0 @@ -[base] -arch = "riscv64" -platform = "riscv64-qemu-virt" -family = "riscv64-qemu-virt" - -kernel-paddr = "0x80200000" -kernel-vaddr = "0xffff_ffc0_8020_0000" - -phys-virt-offset = "0xffff_ffc0_0000_0000" - -[config] -allocator = "run" - -[features]