diff --git a/Cargo.toml b/Cargo.toml index d499aa0e..37d9b9a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,8 @@ members = [ "zircon-object", "zircon-loader", "linux-object", - "zircon-syscall", + "zircon-syscall", "linux-loader", - "kernel-hal-unix", "kernel-hal", ] @@ -14,5 +13,5 @@ exclude = [ "zCore", "rboot", "linux-syscall", - "kernel-hal-bare", + "kernel-hal-bare", ] diff --git a/Makefile b/Makefile index 2198f39a..f8a95869 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ riscv-image: rcore-fs-fuse riscv-rootfs @echo building riscv.img @rcore-fs-fuse zCore/riscv64.img riscv_rootfs zip @qemu-img resize -f raw zCore/riscv64.img +5M - + clean: cargo clean find zCore -maxdepth 1 -name "*.img" -delete diff --git a/kernel-hal-bare/src/arch/riscv/interrupt.rs b/kernel-hal-bare/src/arch/riscv/interrupt.rs index 04a0f3c1..be583213 100644 --- a/kernel-hal-bare/src/arch/riscv/interrupt.rs +++ b/kernel-hal-bare/src/arch/riscv/interrupt.rs @@ -146,7 +146,7 @@ fn page_fault(stval: usize, tf: &mut TrapFrame) { let vaddr = stval; use crate::PageTableImpl; - use kernel_hal::{MMUFlags, PageTableTrait}; + use kernel_hal::{MMUFlags, paging::PageTableTrait}; use riscv::addr::{Page, PhysAddr, VirtAddr}; use riscv::paging::{PageTableFlags as PTF, Rv39PageTable, *}; diff --git a/kernel-hal-bare/src/arch/riscv/mod.rs b/kernel-hal-bare/src/arch/riscv/mod.rs index 4fd3854d..5b332639 100644 --- a/kernel-hal-bare/src/arch/riscv/mod.rs +++ b/kernel-hal-bare/src/arch/riscv/mod.rs @@ -1,8 +1,6 @@ use super::super::*; -use kernel_hal::{ - ColorDepth, ColorFormat, FramebufferInfo, HalError, PageTableTrait, PhysAddr, VirtAddr, - FRAME_BUFFER, -}; +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, *}; diff --git a/kernel-hal-bare/src/arch/x86_64/mod.rs b/kernel-hal-bare/src/arch/x86_64/mod.rs index 4b8d3bf4..d76f4f6e 100644 --- a/kernel-hal-bare/src/arch/x86_64/mod.rs +++ b/kernel-hal-bare/src/arch/x86_64/mod.rs @@ -9,9 +9,8 @@ use { core::ptr::NonNull, core::time::Duration, git_version::git_version, - kernel_hal::{ - ColorDepth, ColorFormat, FramebufferInfo, HalError, PageTableTrait, Result, FRAME_BUFFER, - }, + kernel_hal::dev::fb::{ColorDepth, ColorFormat, FramebufferInfo, FRAME_BUFFER}, + kernel_hal::{HalError, paging::PageTableTrait, HalResult as Result}, rcore_console::{Console, ConsoleOnGraphic, DrawTarget, Pixel, Rgb888, Size}, spin::Mutex, uart_16550::SerialPort, diff --git a/kernel-hal-bare/src/lib.rs b/kernel-hal-bare/src/lib.rs index 2851eeb4..6db8fe16 100644 --- a/kernel-hal-bare/src/lib.rs +++ b/kernel-hal-bare/src/lib.rs @@ -35,9 +35,9 @@ use core::{ pin::Pin, task::{Context, Poll}, }; -use kernel_hal::defs::*; +use kernel_hal::{VirtAddr, PhysAddr, PAGE_SIZE, CachePolicy, MMUFlags}; use kernel_hal::vdso::*; -use kernel_hal::UserContext; +use kernel_hal::context::UserContext; use naive_timer::Timer; use spin::Mutex; diff --git a/kernel-hal-unix/Cargo.toml b/kernel-hal-unix/Cargo.toml deleted file mode 100644 index 057bc141..00000000 --- a/kernel-hal-unix/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "kernel-hal-unix" -version = "0.1.0" -authors = ["Runji Wang "] -edition = "2018" -description = "Kernel HAL implementation on Linux and macOS." - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -log = "0.4" -libc = "0.2" -tempfile = "3" -bitflags = "1.2" -lazy_static = "1.4" -kernel-hal = { path = "../kernel-hal" } -async-std = "1.9" -git-version = "0.3" -trapframe = "0.8.0" diff --git a/kernel-hal-unix/src/lib.rs b/kernel-hal-unix/src/lib.rs deleted file mode 100644 index 84e09537..00000000 --- a/kernel-hal-unix/src/lib.rs +++ /dev/null @@ -1,676 +0,0 @@ -#![feature(asm)] -#![feature(linkage)] -#![deny(warnings)] - -#[macro_use] -extern crate log; - -extern crate alloc; - -use { - alloc::collections::VecDeque, - async_std::task_local, - core::{cell::Cell, future::Future, pin::Pin}, - git_version::git_version, - kernel_hal::PageTableTrait, - lazy_static::lazy_static, - std::fmt::{Debug, Formatter}, - std::fs::{File, OpenOptions}, - std::io::Error, - std::os::unix::io::AsRawFd, - std::sync::Mutex, - std::time::{Duration, SystemTime}, - tempfile::tempdir, -}; - -pub use kernel_hal::defs::*; -use kernel_hal::vdso::*; -pub use kernel_hal::*; -use std::io::Read; -pub use trapframe::syscall_fn_entry as syscall_entry; - -#[cfg(target_os = "macos")] -include!("macos.rs"); - -#[repr(C)] -pub struct Thread { - thread: usize, -} - -impl Thread { - #[export_name = "hal_thread_spawn"] - pub fn spawn( - future: Pin + Send + 'static>>, - _vmtoken: usize, - ) -> Self { - async_std::task::spawn(future); - Thread { thread: 0 } - } - - #[export_name = "hal_thread_set_tid"] - pub fn set_tid(tid: u64, pid: u64) { - TID.with(|x| x.set(tid)); - PID.with(|x| x.set(pid)); - } - - #[export_name = "hal_thread_get_tid"] - pub fn get_tid() -> (u64, u64) { - (TID.with(|x| x.get()), PID.with(|x| x.get())) - } -} - -task_local! { - static TID: Cell = Cell::new(0); - static PID: Cell = Cell::new(0); -} - -#[export_name = "hal_context_run"] -unsafe fn context_run(context: &mut UserContext) { - context.run_fncall(); -} - -/// Page Table -#[repr(C)] -pub struct PageTable { - table_phys: PhysAddr, -} - -impl PageTable { - /// Create a new `PageTable`. - #[allow(clippy::new_without_default)] - #[export_name = "hal_pt_new"] - pub fn new() -> Self { - PageTable { table_phys: 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<()> { - debug_assert!(page_aligned(vaddr)); - debug_assert!(page_aligned(paddr)); - let prot = flags.to_mmap_prot(); - mmap(FRAME_FILE.as_raw_fd(), paddr, PAGE_SIZE, vaddr, prot); - Ok(()) - } - - /// Unmap the page of `vaddr`. - #[export_name = "hal_pt_unmap"] - fn unmap(&mut self, vaddr: VirtAddr) -> Result<()> { - self.unmap_cont(vaddr, 1) - } - - /// Change the `flags` of the page of `vaddr`. - #[export_name = "hal_pt_protect"] - fn protect(&mut self, vaddr: VirtAddr, flags: MMUFlags) -> Result<()> { - debug_assert!(page_aligned(vaddr)); - let prot = flags.to_mmap_prot(); - let ret = unsafe { libc::mprotect(vaddr as _, PAGE_SIZE, prot) }; - assert_eq!(ret, 0, "failed to mprotect: {:?}", Error::last_os_error()); - Ok(()) - } - - /// Query the physical address which the page of `vaddr` maps to. - #[export_name = "hal_pt_query"] - fn query(&mut self, vaddr: VirtAddr) -> Result { - debug_assert!(page_aligned(vaddr)); - unimplemented!() - } - - /// Get the physical address of root page table. - #[export_name = "hal_pt_table_phys"] - fn table_phys(&self) -> PhysAddr { - self.table_phys - } - - #[export_name = "hal_pt_unmap_cont"] - fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> Result<()> { - if pages == 0 { - return Ok(()); - } - debug_assert!(page_aligned(vaddr)); - let ret = unsafe { libc::munmap(vaddr as _, PAGE_SIZE * pages) }; - assert_eq!(ret, 0, "failed to munmap: {:?}", Error::last_os_error()); - Ok(()) - } -} - -#[repr(C)] -pub struct PhysFrame { - paddr: PhysAddr, -} - -impl Debug for PhysFrame { - fn fmt(&self, f: &mut Formatter<'_>) -> core::result::Result<(), std::fmt::Error> { - write!(f, "PhysFrame({:#x})", self.paddr) - } -} - -lazy_static! { - static ref AVAILABLE_FRAMES: Mutex> = - Mutex::new((PAGE_SIZE..PMEM_SIZE).step_by(PAGE_SIZE).collect()); -} - -impl PhysFrame { - #[export_name = "hal_frame_alloc"] - pub fn alloc() -> Option { - let ret = AVAILABLE_FRAMES - .lock() - .unwrap() - .pop_front() - .map(|paddr| PhysFrame { paddr }); - trace!("frame alloc: {:?}", ret); - ret - } - #[export_name = "hal_zero_frame_paddr"] - pub fn zero_frame_addr() -> PhysAddr { - 0 - } -} - -impl Drop for PhysFrame { - #[export_name = "hal_frame_dealloc"] - fn drop(&mut self) { - trace!("frame dealloc: {:?}", self); - AVAILABLE_FRAMES.lock().unwrap().push_back(self.paddr); - } -} - -fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { - /// Map physical memory from here. - const PMEM_BASE: VirtAddr = 0x8_0000_0000; - - PMEM_BASE + paddr -} - -/// Ensure physical memory are mmapped and accessible. -fn ensure_mmap_pmem() { - FRAME_FILE.as_raw_fd(); -} - -/// Read physical memory from `paddr` to `buf`. -#[export_name = "hal_pmem_read"] -pub fn pmem_read(paddr: PhysAddr, buf: &mut [u8]) { - trace!("pmem read: paddr={:#x}, len={:#x}", paddr, buf.len()); - assert!(paddr + buf.len() <= PMEM_SIZE); - ensure_mmap_pmem(); - unsafe { - (phys_to_virt(paddr) as *const u8).copy_to_nonoverlapping(buf.as_mut_ptr(), buf.len()); - } -} - -/// Write physical memory to `paddr` from `buf`. -#[export_name = "hal_pmem_write"] -pub fn pmem_write(paddr: PhysAddr, buf: &[u8]) { - trace!("pmem write: paddr={:#x}, len={:#x}", paddr, buf.len()); - assert!(paddr + buf.len() <= PMEM_SIZE); - ensure_mmap_pmem(); - unsafe { - buf.as_ptr() - .copy_to_nonoverlapping(phys_to_virt(paddr) as _, buf.len()); - } -} - -/// Zero physical memory at `[paddr, paddr + len)` -#[export_name = "hal_pmem_zero"] -pub fn pmem_zero(paddr: PhysAddr, len: usize) { - trace!("pmem_zero: addr={:#x}, len={:#x}", paddr, len); - assert!(paddr + len <= PMEM_SIZE); - ensure_mmap_pmem(); - unsafe { - core::ptr::write_bytes(phys_to_virt(paddr) as *mut u8, 0, len); - } -} - -/// Copy content of `src` frame to `target` frame -#[export_name = "hal_frame_copy"] -pub fn frame_copy(src: PhysAddr, target: PhysAddr) { - trace!("frame_copy: {:#x} <- {:#x}", target, src); - assert!(src + PAGE_SIZE <= PMEM_SIZE && target + PAGE_SIZE <= PMEM_SIZE); - ensure_mmap_pmem(); - unsafe { - let buf = phys_to_virt(src) as *const u8; - buf.copy_to_nonoverlapping(phys_to_virt(target) as _, PAGE_SIZE); - } -} - -/// Flush the physical frame. -#[export_name = "hal_frame_flush"] -pub fn frame_flush(_target: PhysAddr) { - // do nothing -} - -const PAGE_SIZE: usize = 0x1000; - -fn page_aligned(x: VirtAddr) -> bool { - x % PAGE_SIZE == 0 -} - -const PMEM_SIZE: usize = 0x4000_0000; // 1GiB - -lazy_static! { - static ref FRAME_FILE: File = create_pmem_file(); -} - -fn create_pmem_file() -> File { - let dir = tempdir().expect("failed to create pmem dir"); - let path = dir.path().join("pmem"); - - // workaround on macOS to avoid permission denied. - // see https://jiege.ch/software/2020/02/07/macos-mmap-exec/ for analysis on this problem. - #[cfg(target_os = "macos")] - std::mem::forget(dir); - - let file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .expect("failed to create pmem file"); - file.set_len(PMEM_SIZE as u64) - .expect("failed to resize file"); - trace!("create pmem file: path={:?}, size={:#x}", path, PMEM_SIZE); - let prot = libc::PROT_READ | libc::PROT_WRITE; - mmap(file.as_raw_fd(), 0, PMEM_SIZE, phys_to_virt(0), prot); - file -} - -/// Mmap frame file `fd` to `vaddr`. -fn mmap(fd: libc::c_int, offset: usize, len: usize, vaddr: VirtAddr, prot: libc::c_int) { - // workaround on macOS to write text section. - #[cfg(target_os = "macos")] - let prot = if prot & libc::PROT_EXEC != 0 { - prot | libc::PROT_WRITE - } else { - prot - }; - - let ret = unsafe { - let flags = libc::MAP_SHARED | libc::MAP_FIXED; - libc::mmap(vaddr as _, len, prot, flags, fd, offset as _) - } as usize; - trace!( - "mmap file: fd={}, offset={:#x}, len={:#x}, vaddr={:#x}, prot={:#b}", - fd, - offset, - len, - vaddr, - prot, - ); - assert_eq!(ret, vaddr, "failed to mmap: {:?}", Error::last_os_error()); -} - -trait FlagsExt { - fn to_mmap_prot(&self) -> libc::c_int; -} - -impl FlagsExt for MMUFlags { - fn to_mmap_prot(&self) -> libc::c_int { - let mut flags = 0; - if self.contains(MMUFlags::READ) { - flags |= libc::PROT_READ; - } - if self.contains(MMUFlags::WRITE) { - flags |= libc::PROT_WRITE; - } - if self.contains(MMUFlags::EXECUTE) { - flags |= libc::PROT_EXEC; - } - flags - } -} - -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(x: u8) { - STDIN.lock().unwrap().push_back(x); - STDIN_CALLBACK.lock().unwrap().retain(|f| !f()); -} - -#[export_name = "hal_serial_set_callback"] -pub fn serial_set_callback(callback: Box bool + Send + Sync>) { - STDIN_CALLBACK.lock().unwrap().push(callback); -} - -#[export_name = "hal_serial_read"] -pub fn serial_read(buf: &mut [u8]) -> usize { - let mut stdin = STDIN.lock().unwrap(); - let len = stdin.len().min(buf.len()); - for c in &mut buf[..len] { - *c = stdin.pop_front().unwrap(); - } - len -} - -/// Output a char to console. -#[export_name = "hal_serial_write"] -pub fn serial_write(s: &str) { - eprint!("{}", s); -} - -/// Get current time. -#[export_name = "hal_timer_now"] -pub fn timer_now() -> Duration { - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() -} - -/// Set a new timer. -/// -/// After `deadline`, the `callback` will be called. -#[export_name = "hal_timer_set"] -pub fn timer_set(deadline: Duration, callback: Box) { - std::thread::spawn(move || { - let now = timer_now(); - if deadline > now { - std::thread::sleep(deadline - now); - } - callback(timer_now()); - }); -} - -#[export_name = "hal_vdso_constants"] -pub fn vdso_constants() -> VdsoConstants { - let tsc_frequency = 3000u16; - let mut constants = VdsoConstants { - max_num_cpus: 1, - features: Features { - cpu: 0, - hw_breakpoint_count: 0, - hw_watchpoint_count: 0, - }, - dcache_line_size: 0, - icache_line_size: 0, - ticks_per_second: tsc_frequency as u64 * 1_000_000, - ticks_to_mono_numerator: 1000, - ticks_to_mono_denominator: tsc_frequency as u32, - physmem: PMEM_SIZE as u64, - version_string_len: 0, - version_string: Default::default(), - }; - constants.set_version_string(git_version!( - prefix = "git-", - args = ["--always", "--abbrev=40", "--dirty=-dirty"] - )); - constants -} - -#[export_name = "hal_current_pgtable"] -pub fn current_page_table() -> usize { - 0 -} - -/// Initialize the HAL. -/// -/// This function must be called at the beginning. -pub fn init() { - #[cfg(target_os = "macos")] - unsafe { - register_sigsegv_handler(); - } - // spawn a thread to read stdin - // TODO: raw mode - std::thread::spawn(|| { - for i in std::io::stdin().bytes() { - serial_put(i.unwrap()); - } - }); -} - -pub fn init_framebuffer() { - const FBIOGET_VSCREENINFO: u64 = 0x4600; - const FBIOGET_FSCREENINFO: u64 = 0x4602; - - #[cfg(target_arch = "aarch64")] - let fbfd = unsafe { libc::open("/dev/fb0".as_ptr(), libc::O_RDWR) }; - #[cfg(not(target_arch = "aarch64"))] - let fbfd = unsafe { libc::open("/dev/fb0".as_ptr() as *const i8, libc::O_RDWR) }; - if fbfd < 0 { - return; - } - - #[repr(C)] - #[derive(Debug, Default)] - struct FbFixScreeninfo { - id: [u8; 16], - smem_start: u64, - smem_len: u32, - type_: u32, - type_aux: u32, - visual: u32, - xpanstep: u16, - ypanstep: u16, - ywrapstep: u16, - line_length: u32, - mmio_start: u64, - mmio_len: u32, - accel: u32, - capabilities: u16, - reserved: [u16; 2], - } - - impl FbFixScreeninfo { - pub fn size(&self) -> u32 { - self.smem_len - } - } - - #[repr(C)] - #[derive(Debug, Default)] - struct FbVarScreeninfo { - xres: u32, - yres: u32, - xres_virtual: u32, - yres_virtual: u32, - xoffset: u32, - yoffset: u32, - bits_per_pixel: u32, - grayscale: u32, - red: FbBitfield, - green: FbBitfield, - blue: FbBitfield, - transp: FbBitfield, - nonstd: u32, - activate: u32, - height: u32, - width: u32, - accel_flags: u32, - pixclock: u32, - left_margin: u32, - right_margin: u32, - upper_margin: u32, - lower_margin: u32, - hsync_len: u32, - vsync_len: u32, - sync: u32, - vmode: u32, - rotate: u32, - colorspace: u32, - reserved: [u32; 4], - } - - impl FbVarScreeninfo { - pub fn resolution(&self) -> (u32, u32) { - (self.xres, self.yres) - } - } - - #[repr(C)] - #[derive(Debug, Default)] - pub struct FbBitfield { - offset: u32, - length: u32, - msb_right: u32, - } - - let mut vinfo = FbVarScreeninfo::default(); - if unsafe { libc::ioctl(fbfd, FBIOGET_VSCREENINFO, &mut vinfo) } < 0 { - return; - } - - let mut finfo = FbFixScreeninfo::default(); - if unsafe { libc::ioctl(fbfd, FBIOGET_FSCREENINFO, &mut finfo) } < 0 { - return; - } - - let size = finfo.size() as usize; - let addr = unsafe { - libc::mmap( - std::ptr::null_mut::(), - size, - libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_SHARED, - fbfd, - 0, - ) - }; - if (addr as isize) < 0 { - return; - } - - let (width, height) = vinfo.resolution(); - let addr = addr as 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), - paddr: addr, - vaddr: addr, - screen_size: size, - }; - *FRAME_BUFFER.write() = Some(fb_info); -} - -type MouseCallbackFn = dyn Fn([u8; 3]) + Send + Sync; -type KBDCallbackFn = dyn Fn(u16, i32) + Send + Sync; - -lazy_static! { - static ref MOUSE_CALLBACK: Mutex>> = Mutex::new(Vec::new()); - static ref KBD_CALLBACK: Mutex>> = Mutex::new(Vec::new()); -} - -#[export_name = "hal_mice_set_callback"] -pub fn mice_set_callback(callback: Box) { - MOUSE_CALLBACK.lock().unwrap().push(callback); -} - -#[export_name = "hal_kbd_set_callback"] -pub fn kbd_set_callback(callback: Box) { - KBD_CALLBACK.lock().unwrap().push(callback); -} - -fn init_kbd() { - let fd = std::fs::File::open("/dev/input/event1").expect("Failed to open input event device."); - // ?? - /* let inputfd = unsafe { - libc::open( - "/dev/input/event1".as_ptr() as *const i8, - libc::O_RDONLY /* | libc::O_NONBLOCK */, - ) - }; */ - if fd.as_raw_fd() < 0 { - return; - } - - #[repr(C)] - #[derive(Debug, Copy, Clone, Default)] - pub struct TimeVal { - pub sec: usize, - pub usec: usize, - } - #[repr(C)] - #[derive(Debug, Copy, Clone, Default)] - struct InputEvent { - time: TimeVal, - type_: u16, - code: u16, - value: i32, - } - - std::thread::spawn(move || { - use core::mem::{size_of, transmute, transmute_copy}; - let ev = InputEvent::default(); - const LEN: usize = size_of::(); - let mut buf: [u8; LEN] = unsafe { transmute(ev) }; - loop { - std::thread::sleep(std::time::Duration::from_millis(8)); - let ret = - unsafe { libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, LEN) }; - if ret < 0 { - break; - } - let ev: InputEvent = unsafe { transmute_copy(&buf) }; - if ev.type_ == 1 { - KBD_CALLBACK.lock().unwrap().iter().for_each(|callback| { - callback(ev.code, ev.value); - }); - } - } - }); -} - -fn init_mice() { - let fd = std::fs::File::open("/dev/input/mice").expect("Failed to open input event device."); - if fd.as_raw_fd() < 0 { - return; - } - - std::thread::spawn(move || { - let mut buf = [0u8; 3]; - loop { - std::thread::sleep(std::time::Duration::from_millis(8)); - let ret = - unsafe { libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, 3) }; - if ret < 0 { - break; - } - MOUSE_CALLBACK.lock().unwrap().iter().for_each(|callback| { - callback(buf); - }); - } - }); -} - -pub fn init_input() { - init_kbd(); - init_mice(); -} - -#[cfg(test)] -mod tests { - use super::*; - - /// A valid virtual address base to mmap. - const VBASE: VirtAddr = 0x2_00000000; - - #[test] - fn map_unmap() { - let mut pt = PageTable::new(); - let flags = MMUFlags::READ | MMUFlags::WRITE; - // map 2 pages to 1 frame - pt.map(VBASE, 0x1000, flags).unwrap(); - pt.map(VBASE + 0x1000, 0x1000, flags).unwrap(); - - unsafe { - const MAGIC: usize = 0xdead_beaf; - (VBASE as *mut usize).write(MAGIC); - assert_eq!(((VBASE + 0x1000) as *mut usize).read(), MAGIC); - } - - pt.unmap(VBASE + 0x1000).unwrap(); - } -} diff --git a/kernel-hal/Cargo.toml b/kernel-hal/Cargo.toml index 5262300e..af7c0ecb 100644 --- a/kernel-hal/Cargo.toml +++ b/kernel-hal/Cargo.toml @@ -1,18 +1,54 @@ [package] name = "kernel-hal" version = "0.1.0" -authors = ["Runji Wang "] +authors = ["Runji Wang ", "Yuekai Jia "] edition = "2018" description = "Kernel HAL interface definations." # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +libos = ["async-std"] + [dependencies] +log = "0.4" bitflags = "1.2" trapframe = "0.8.0" numeric-enum-macro = "0.2" -acpi = "1.1" spin = "0.7" +git-version = "0.3" +cfg-if = "1.0" +acpi = "1.1" -#[patch.crates-io] -#trapframe = { path = "/home/xly/rust/arch-lib/trapframe-rs" } +# LibOS mode +[target.'cfg(not(target_os = "none"))'.dependencies] +riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" } +libc = "0.2" +tempfile = "3" +lazy_static = "1.4" +async-std = { version = "1.9", optional = true } + +# Bare-metal mode +[target.'cfg(target_os = "none")'.dependencies] +# executor = { git = "https://github.com/rcore-os/executor.git", rev = "a2d02ee9" } +# naive-timer = "0.1.0" +# lazy_static = { version = "1.4", features = ["spin_no_std"] } +# 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" } + +# Bare-metal mode on x86_64 +[target.'cfg(all(target_os = "none", 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" } +# x86-smpboot = { git = "https://github.com/rcore-os/x86-smpboot", rev = "43ffedf" } +# rcore-console = { git = "https://github.com/rcore-os/rcore-console", default-features = false, rev = "a980897b" } +# ps2-mouse = { git = "https://github.com/YXL76/ps2-mouse", branch = "feat" } + +# 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" diff --git a/kernel-hal/src/context.rs b/kernel-hal/src/common/context.rs similarity index 95% rename from kernel-hal/src/context.rs rename to kernel-hal/src/common/context.rs index fba3d415..27bb4b26 100644 --- a/kernel-hal/src/context.rs +++ b/kernel-hal/src/common/context.rs @@ -1,5 +1,7 @@ use core::fmt; +pub use trapframe::{GeneralRegs, UserContext}; + #[repr(C, align(16))] #[derive(Debug, Copy, Clone)] pub struct VectorRegs { diff --git a/kernel-hal/src/common/defs.rs b/kernel-hal/src/common/defs.rs new file mode 100644 index 00000000..6d35cd7b --- /dev/null +++ b/kernel-hal/src/common/defs.rs @@ -0,0 +1,38 @@ +use bitflags::bitflags; +use numeric_enum_macro::numeric_enum; + +/// The error type which is returned from HAL functions. +#[derive(Debug)] +pub struct HalError; + +/// The result type returned by HAL functions. +pub type HalResult = core::result::Result; + +bitflags! { + pub struct MMUFlags: usize { + #[allow(clippy::identity_op)] + const CACHE_1 = 1 << 0; + const CACHE_2 = 1 << 1; + const READ = 1 << 2; + const WRITE = 1 << 3; + const EXECUTE = 1 << 4; + const USER = 1 << 5; + const RXW = Self::READ.bits | Self::WRITE.bits | Self::EXECUTE.bits; + } +} +numeric_enum! { + #[repr(u32)] + #[derive(Debug, PartialEq, Clone, Copy)] + pub enum CachePolicy { + Cached = 0, + Uncached = 1, + UncachedDevice = 2, + WriteCombining = 3, + } +} +pub const CACHE_POLICY_MASK: u32 = 3; + +pub type PhysAddr = usize; +pub type VirtAddr = usize; +pub type DevVAddr = usize; +pub const PAGE_SIZE: usize = 0x1000; diff --git a/kernel-hal/src/fb.rs b/kernel-hal/src/common/fb.rs similarity index 100% rename from kernel-hal/src/fb.rs rename to kernel-hal/src/common/fb.rs diff --git a/kernel-hal/src/future.rs b/kernel-hal/src/common/future.rs similarity index 88% rename from kernel-hal/src/future.rs rename to kernel-hal/src/common/future.rs index 1a3bcc8e..41c5ea18 100644 --- a/kernel-hal/src/future.rs +++ b/kernel-hal/src/common/future.rs @@ -1,4 +1,3 @@ -use crate::timer_now; use alloc::boxed::Box; use core::future::Future; use core::pin::Pin; @@ -44,12 +43,12 @@ impl Future for SleepFuture { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { - if timer_now() >= self.deadline { + if crate::timer::timer_now() >= self.deadline { return Poll::Ready(()); } if self.deadline.as_nanos() < i64::max_value() as u128 { let waker = cx.waker().clone(); - crate::timer_set(self.deadline, Box::new(move |_| waker.wake())); + crate::timer::timer_set(self.deadline, Box::new(move |_| waker.wake())); } Poll::Pending } @@ -68,11 +67,11 @@ impl Future for SerialFuture { fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { let mut buf = [0u8]; - if crate::serial_read(&mut buf) != 0 { + if crate::serial::serial_read(&mut buf) != 0 { return Poll::Ready(buf[0]); } let waker = cx.waker().clone(); - crate::serial_set_callback(Box::new({ + crate::serial::serial_set_callback(Box::new({ move || { waker.wake_by_ref(); true diff --git a/kernel-hal/src/common/memory.rs b/kernel-hal/src/common/memory.rs new file mode 100644 index 00000000..393b9a7f --- /dev/null +++ b/kernel-hal/src/common/memory.rs @@ -0,0 +1,43 @@ +use alloc::vec::Vec; + +use crate::{PhysAddr, PAGE_SIZE}; + +#[repr(C)] +#[derive(Debug)] +pub struct PhysFrame { + paddr: PhysAddr, +} + +impl PhysFrame { + pub fn alloc() -> Option { + crate::memory::frame_alloc().map(|paddr| Self { paddr }) + } + + pub fn alloc_contiguous_base(size: usize, align_log2: usize) -> Option { + crate::memory::frame_alloc_contiguous(size, align_log2) + } + + pub fn alloc_contiguous(size: usize, align_log2: usize) -> Vec { + Self::alloc_contiguous_base(size, align_log2).map_or(Vec::new(), |base| { + (0..size) + .map(|i| PhysFrame { + paddr: base + i * PAGE_SIZE, + }) + .collect() + }) + } + + pub fn addr(&self) -> PhysAddr { + self.paddr + } + + pub fn zero_frame_addr() -> PhysAddr { + crate::memory::zero_frame_addr() + } +} + +impl Drop for PhysFrame { + fn drop(&mut self) { + crate::memory::frame_dealloc(self.paddr) + } +} diff --git a/kernel-hal/src/common/mod.rs b/kernel-hal/src/common/mod.rs new file mode 100644 index 00000000..f371af86 --- /dev/null +++ b/kernel-hal/src/common/mod.rs @@ -0,0 +1,11 @@ +pub(super) mod defs; +pub(super) mod fb; + +pub mod context; +pub mod future; +pub mod memory; +pub mod paging; +pub mod user; +pub mod vdso; + +pub use defs::*; diff --git a/kernel-hal/src/common/paging.rs b/kernel-hal/src/common/paging.rs new file mode 100644 index 00000000..d29233eb --- /dev/null +++ b/kernel-hal/src/common/paging.rs @@ -0,0 +1,57 @@ +use super::{HalResult, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE}; + +pub trait PageTableTrait: Sync + Send { + /// Map the page of `vaddr` to the frame of `paddr` with `flags`. + fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> HalResult<()>; + + /// Unmap the page of `vaddr`. + fn unmap(&mut self, _vaddr: VirtAddr) -> HalResult<()>; + + /// Change the `flags` of the page of `vaddr`. + fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> HalResult<()>; + + /// Query the physical address which the page of `vaddr` maps to. + fn query(&mut self, _vaddr: VirtAddr) -> HalResult; + + /// 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, + paddrs: &[PhysAddr], + flags: MMUFlags, + ) -> HalResult<()> { + for &paddr in paddrs { + self.map(vaddr, paddr, flags)?; + vaddr += PAGE_SIZE; + } + Ok(()) + } + + fn map_cont( + &mut self, + mut vaddr: VirtAddr, + paddr: PhysAddr, + pages: usize, + flags: MMUFlags, + ) -> HalResult<()> { + for i in 0..pages { + let paddr = paddr + i * PAGE_SIZE; + self.map(vaddr, paddr, flags)?; + vaddr += PAGE_SIZE; + } + Ok(()) + } + + fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> HalResult<()> { + for i in 0..pages { + self.unmap(vaddr + i * PAGE_SIZE)?; + } + Ok(()) + } +} diff --git a/kernel-hal/src/user.rs b/kernel-hal/src/common/user.rs similarity index 100% rename from kernel-hal/src/user.rs rename to kernel-hal/src/common/user.rs diff --git a/kernel-hal/src/vdso.rs b/kernel-hal/src/common/vdso.rs similarity index 100% rename from kernel-hal/src/vdso.rs rename to kernel-hal/src/common/vdso.rs diff --git a/kernel-hal/src/dummy.rs b/kernel-hal/src/dummy.rs deleted file mode 100644 index 235f9d46..00000000 --- a/kernel-hal/src/dummy.rs +++ /dev/null @@ -1,485 +0,0 @@ -use super::*; -use crate::vdso::VdsoConstants; -use acpi::Acpi; -use alloc::boxed::Box; -use alloc::vec::Vec; -use core::future::Future; -use core::ops::FnOnce; -use core::pin::Pin; -use core::time::Duration; - -type ThreadId = usize; - -/// The error type which is returned from HAL functions. -#[derive(Debug)] -pub struct HalError; - -/// The result type returned by HAL functions. -pub type Result = core::result::Result; - -#[repr(C)] -pub struct Thread { - id: ThreadId, -} - -impl Thread { - /// Spawn a new thread. - #[linkage = "weak"] - #[export_name = "hal_thread_spawn"] - pub fn spawn( - _future: Pin + Send + 'static>>, - _vmtoken: usize, - ) -> Self { - unimplemented!() - } - - /// Set tid and pid of current task. - #[linkage = "weak"] - #[export_name = "hal_thread_set_tid"] - pub fn set_tid(_tid: u64, _pid: u64) { - unimplemented!() - } - - /// Get tid and pid of current task. - #[linkage = "weak"] - #[export_name = "hal_thread_get_tid"] - pub fn get_tid() -> (u64, u64) { - unimplemented!() - } -} - -#[linkage = "weak"] -#[export_name = "hal_context_run"] -pub fn context_run(_context: &mut UserContext) { - unimplemented!() -} - -pub trait PageTableTrait: Sync + Send { - /// Map the page of `vaddr` to the frame of `paddr` with `flags`. - fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> Result<()>; - - /// Unmap the page of `vaddr`. - fn unmap(&mut self, _vaddr: VirtAddr) -> Result<()>; - - /// Change the `flags` of the page of `vaddr`. - fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> Result<()>; - - /// Query the physical address which the page of `vaddr` maps to. - fn query(&mut self, _vaddr: VirtAddr) -> Result; - - /// 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, - paddrs: &[PhysAddr], - flags: MMUFlags, - ) -> Result<()> { - for &paddr in paddrs { - self.map(vaddr, paddr, flags)?; - vaddr += PAGE_SIZE; - } - Ok(()) - } - - fn map_cont( - &mut self, - mut vaddr: VirtAddr, - paddr: PhysAddr, - pages: usize, - flags: MMUFlags, - ) -> Result<()> { - for i in 0..pages { - let paddr = paddr + i * PAGE_SIZE; - self.map(vaddr, paddr, flags)?; - vaddr += PAGE_SIZE; - } - Ok(()) - } - - fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> Result<()> { - for i in 0..pages { - self.unmap(vaddr + i * PAGE_SIZE)?; - } - Ok(()) - } -} - -/// Page Table -#[repr(C)] -pub struct PageTable { - table_phys: PhysAddr, -} - -impl PageTable { - /// Get current page table - #[linkage = "weak"] - #[export_name = "hal_pt_current"] - pub fn current() -> Self { - unimplemented!() - } - - /// Create a new `PageTable`. - #[allow(clippy::new_without_default)] - #[linkage = "weak"] - #[export_name = "hal_pt_new"] - pub fn new() -> Self { - unimplemented!() - } -} - -impl PageTableTrait for PageTable { - /// Map the page of `vaddr` to the frame of `paddr` with `flags`. - #[linkage = "weak"] - #[export_name = "hal_pt_map"] - fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> Result<()> { - unimplemented!() - } - /// Unmap the page of `vaddr`. - #[linkage = "weak"] - #[export_name = "hal_pt_unmap"] - fn unmap(&mut self, _vaddr: VirtAddr) -> Result<()> { - unimplemented!() - } - /// Change the `flags` of the page of `vaddr`. - #[linkage = "weak"] - #[export_name = "hal_pt_protect"] - fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> Result<()> { - unimplemented!() - } - /// Query the physical address which the page of `vaddr` maps to. - #[linkage = "weak"] - #[export_name = "hal_pt_query"] - fn query(&mut self, _vaddr: VirtAddr) -> Result { - unimplemented!() - } - /// Get the physical address of root page table. - #[linkage = "weak"] - #[export_name = "hal_pt_table_phys"] - fn table_phys(&self) -> PhysAddr { - 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<()> { - for i in 0..pages { - self.unmap(vaddr + i * PAGE_SIZE)?; - } - Ok(()) - } -} - -#[repr(C)] -pub struct PhysFrame { - paddr: PhysAddr, -} - -impl PhysFrame { - #[linkage = "weak"] - #[export_name = "hal_frame_alloc"] - pub fn alloc() -> Option { - unimplemented!() - } - - #[linkage = "weak"] - #[export_name = "hal_frame_alloc_contiguous"] - pub fn alloc_contiguous_base(_size: usize, _align_log2: usize) -> Option { - unimplemented!() - } - - pub fn alloc_contiguous(size: usize, align_log2: usize) -> Vec { - PhysFrame::alloc_contiguous_base(size, align_log2).map_or(Vec::new(), |base| { - (0..size) - .map(|i| PhysFrame { - paddr: base + i * PAGE_SIZE, - }) - .collect() - }) - } - - pub fn addr(&self) -> PhysAddr { - self.paddr - } - - #[linkage = "weak"] - #[export_name = "hal_zero_frame_paddr"] - pub fn zero_frame_addr() -> PhysAddr { - unimplemented!() - } -} - -impl Drop for PhysFrame { - #[linkage = "weak"] - #[export_name = "hal_frame_dealloc"] - fn drop(&mut self) { - unimplemented!() - } -} - -/// Read physical memory from `paddr` to `buf`. -#[linkage = "weak"] -#[export_name = "hal_pmem_read"] -pub fn pmem_read(_paddr: PhysAddr, _buf: &mut [u8]) { - unimplemented!() -} - -/// Write physical memory to `paddr` from `buf`. -#[linkage = "weak"] -#[export_name = "hal_pmem_write"] -pub fn pmem_write(_paddr: PhysAddr, _buf: &[u8]) { - unimplemented!() -} - -/// Zero physical memory at `[paddr, paddr + len)` -#[linkage = "weak"] -#[export_name = "hal_pmem_zero"] -pub fn pmem_zero(_paddr: PhysAddr, _len: usize) { - unimplemented!() -} - -/// Copy content of `src` frame to `target` frame. -#[linkage = "weak"] -#[export_name = "hal_frame_copy"] -pub fn frame_copy(_src: PhysAddr, _target: PhysAddr) { - unimplemented!() -} - -/// Flush the physical frame. -#[linkage = "weak"] -#[export_name = "hal_frame_flush"] -pub fn frame_flush(_target: PhysAddr) { - unimplemented!() -} - -/// Register a callback of serial readable event. -#[linkage = "weak"] -#[export_name = "hal_serial_set_callback"] -pub fn serial_set_callback(_callback: Box bool + Send + Sync>) { - unimplemented!() -} - -/// Read a string from console. -#[linkage = "weak"] -#[export_name = "hal_serial_read"] -pub fn serial_read(_buf: &mut [u8]) -> usize { - unimplemented!() -} - -/// Output a string to console. -#[linkage = "weak"] -#[export_name = "hal_serial_write"] -pub fn serial_write(_s: &str) { - unimplemented!() -} - -/// Get current time. -#[linkage = "weak"] -#[export_name = "hal_timer_now"] -pub fn timer_now() -> Duration { - unimplemented!() -} - -/// Set a new timer. After `deadline`, the `callback` will be called. -#[linkage = "weak"] -#[export_name = "hal_timer_set"] -pub fn timer_set(_deadline: Duration, _callback: Box) { - 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 { - /// Enable IRQ. - #[linkage = "weak"] - #[export_name = "hal_irq_enable"] - pub fn enable_irq(_vector: u32) { - unimplemented!() - } - /// Disable IRQ. - #[linkage = "weak"] - #[export_name = "hal_irq_disable"] - pub fn disable_irq(_vector: u32) { - unimplemented!() - } - /// Is a valid IRQ number. - #[linkage = "weak"] - #[export_name = "hal_irq_isvalid"] - pub fn is_valid_irq(_vector: u32) -> bool { - unimplemented!() - } - - /// Configure the specified interrupt vector. If it is invoked, it muust be - /// invoked prior to interrupt registration. - #[linkage = "weak"] - #[export_name = "hal_irq_configure"] - pub fn configure_irq(_vector: u32, _trig_mode: bool, _polarity: bool) -> bool { - unimplemented!() - } - /// Add an interrupt handle to an IRQ - #[linkage = "weak"] - #[export_name = "hal_irq_register_handler"] - pub fn register_irq_handler(_vector: u32, _handle: Box) -> Option { - unimplemented!() - } - /// Remove the interrupt handle to an IRQ - #[linkage = "weak"] - #[export_name = "hal_irq_unregister_handler"] - pub fn unregister_irq_handler(_vector: u32) -> bool { - unimplemented!() - } - /// Handle IRQ. - #[linkage = "weak"] - #[export_name = "hal_irq_handle"] - pub fn handle_irq(_vector: u32) { - unimplemented!() - } - - /// Method used for platform allocation of blocks of MSI and MSI-X compatible - /// IRQ targets. - #[linkage = "weak"] - #[export_name = "hal_msi_allocate_block"] - pub fn msi_allocate_block(_irq_num: u32) -> Option<(usize, usize)> { - unimplemented!() - } - /// Method used to free a block of MSI IRQs previously allocated by msi_alloc_block(). - /// This does not unregister IRQ handlers. - #[linkage = "weak"] - #[export_name = "hal_msi_free_block"] - pub fn msi_free_block(_irq_start: u32, _irq_num: u32) { - unimplemented!() - } - /// Register a handler function for a given msi_id within an msi_block_t. Passing a - /// NULL handler will effectively unregister a handler for a given msi_id within the - /// block. - #[linkage = "weak"] - #[export_name = "hal_msi_register_handler"] - pub fn msi_register_handler( - _irq_start: u32, - _irq_num: u32, - _msi_id: u32, - _handle: Box, - ) { - unimplemented!() - } -} - -/// Get platform specific information. -#[linkage = "weak"] -#[export_name = "hal_vdso_constants"] -pub fn vdso_constants() -> VdsoConstants { - unimplemented!() -} - -/// Get fault address of the last page fault. -#[linkage = "weak"] -#[export_name = "fetch_fault_vaddr"] -pub fn fetch_fault_vaddr() -> VirtAddr { - unimplemented!() -} - -#[linkage = "weak"] -#[export_name = "fetch_trap_num"] -pub fn fetch_trap_num(_context: &UserContext) -> usize { - unimplemented!() -} - -/// Get physical address of `acpi_rsdp` and `smbios` on x86_64. -#[linkage = "weak"] -#[export_name = "hal_pc_firmware_tables"] -pub fn pc_firmware_tables() -> (u64, u64) { - unimplemented!() -} - -/// Get ACPI Table -#[linkage = "weak"] -#[export_name = "hal_acpi_table"] -pub fn get_acpi_table() -> Option { - unimplemented!() -} - -/// IO Ports access on x86 platform -#[linkage = "weak"] -#[export_name = "hal_outpd"] -pub fn outpd(_port: u16, _value: u32) { - unimplemented!() -} - -#[linkage = "weak"] -#[export_name = "hal_inpd"] -pub fn inpd(_port: u16) -> u32 { - unimplemented!() -} - -/// Get local APIC ID -#[linkage = "weak"] -#[export_name = "hal_apic_local_id"] -pub fn apic_local_id() -> u8 { - unimplemented!() -} - -/// Fill random bytes to the buffer -#[cfg(target_arch = "x86_64")] -pub fn fill_random(buf: &mut [u8]) { - // TODO: optimize - for x in buf.iter_mut() { - let mut r = 0; - unsafe { - core::arch::x86_64::_rdrand16_step(&mut r); - } - *x = r as _; - } -} - -#[cfg(target_arch = "aarch64")] -pub fn fill_random(_buf: &mut [u8]) { - // TODO -} - -#[cfg(target_arch = "riscv64")] -pub fn fill_random(_buf: &mut [u8]) { - // TODO -} - -#[linkage = "weak"] -#[export_name = "hal_current_pgtable"] -pub fn current_page_table() -> usize { - unimplemented!() -} - -#[linkage = "weak"] -#[export_name = "hal_mice_set_callback"] -pub fn mice_set_callback(_callback: Box) { - unimplemented!() -} - -#[linkage = "weak"] -#[export_name = "hal_kbd_set_callback"] -pub fn kbd_set_callback(_callback: Box) { - unimplemented!() -} diff --git a/kernel-hal/src/lib.rs b/kernel-hal/src/lib.rs index a2009143..5bbf7a7c 100644 --- a/kernel-hal/src/lib.rs +++ b/kernel-hal/src/lib.rs @@ -1,55 +1,23 @@ //! Hardware Abstraction Layer -#![no_std] -#![feature(linkage)] +#![cfg_attr(not(feature = "libos"), no_std)] +#![feature(asm)] #![deny(warnings)] extern crate alloc; -pub mod defs { - use bitflags::bitflags; - use numeric_enum_macro::numeric_enum; +mod common; - bitflags! { - pub struct MMUFlags: usize { - #[allow(clippy::identity_op)] - const CACHE_1 = 1 << 0; - const CACHE_2 = 1 << 1; - const READ = 1 << 2; - const WRITE = 1 << 3; - const EXECUTE = 1 << 4; - const USER = 1 << 5; - const RXW = Self::READ.bits | Self::WRITE.bits | Self::EXECUTE.bits; - } - } - numeric_enum! { - #[repr(u32)] - #[derive(Debug, PartialEq, Clone, Copy)] - pub enum CachePolicy { - Cached = 0, - Uncached = 1, - UncachedDevice = 2, - WriteCombining = 3, - } - } - pub const CACHE_POLICY_MASK: u32 = 3; +pub use common::{defs::*, future, user}; - pub type PhysAddr = usize; - pub type VirtAddr = usize; - pub type DevVAddr = usize; - pub const PAGE_SIZE: usize = 0x1000; +cfg_if::cfg_if! { + if #[cfg(feature = "libos")] { + #[macro_use] + extern crate log; + mod libos; + pub use self::libos::*; + } else { + mod unimp; + pub use self::unimp::*; + } } - -mod context; -mod dummy; -mod fb; -mod future; -pub mod user; -pub mod vdso; - -pub use self::context::*; -pub use self::defs::*; -pub use self::dummy::*; -pub use self::fb::*; -pub use self::future::*; -pub use trapframe::{GeneralRegs, UserContext}; diff --git a/kernel-hal/src/libos/context.rs b/kernel-hal/src/libos/context.rs new file mode 100644 index 00000000..0ff70f0a --- /dev/null +++ b/kernel-hal/src/libos/context.rs @@ -0,0 +1,17 @@ +pub use crate::common::context::*; + +pub use trapframe::syscall_fn_entry as syscall_entry; + +pub fn context_run(context: &mut UserContext) { + context.run_fncall(); +} + +/// Get fault address of the last page fault. +pub fn fetch_fault_vaddr() -> crate::VirtAddr { + unimplemented!() +} + +/// Get the trap number when trap. +pub fn fetch_trap_num(_context: &UserContext) -> usize { + unimplemented!() +} diff --git a/kernel-hal/src/libos/cpu.rs b/kernel-hal/src/libos/cpu.rs new file mode 100644 index 00000000..ec6bd3b3 --- /dev/null +++ b/kernel-hal/src/libos/cpu.rs @@ -0,0 +1,3 @@ +pub fn u8() -> u8 { + 0 +} diff --git a/kernel-hal/src/libos/dev/fb.rs b/kernel-hal/src/libos/dev/fb.rs new file mode 100644 index 00000000..6bfe7b2f --- /dev/null +++ b/kernel-hal/src/libos/dev/fb.rs @@ -0,0 +1,132 @@ +pub use crate::common::fb::*; + +#[repr(C)] +#[derive(Debug, Default)] +struct FbFixScreeninfo { + id: [u8; 16], + smem_start: u64, + smem_len: u32, + type_: u32, + type_aux: u32, + visual: u32, + xpanstep: u16, + ypanstep: u16, + ywrapstep: u16, + line_length: u32, + mmio_start: u64, + mmio_len: u32, + accel: u32, + capabilities: u16, + reserved: [u16; 2], +} + +impl FbFixScreeninfo { + pub fn size(&self) -> u32 { + self.smem_len + } +} + +#[repr(C)] +#[derive(Debug, Default)] +struct FbVarScreeninfo { + xres: u32, + yres: u32, + xres_virtual: u32, + yres_virtual: u32, + xoffset: u32, + yoffset: u32, + bits_per_pixel: u32, + grayscale: u32, + red: FbBitfield, + green: FbBitfield, + blue: FbBitfield, + transp: FbBitfield, + nonstd: u32, + activate: u32, + height: u32, + width: u32, + accel_flags: u32, + pixclock: u32, + left_margin: u32, + right_margin: u32, + upper_margin: u32, + lower_margin: u32, + hsync_len: u32, + vsync_len: u32, + sync: u32, + vmode: u32, + rotate: u32, + colorspace: u32, + reserved: [u32; 4], +} + +impl FbVarScreeninfo { + pub fn resolution(&self) -> (u32, u32) { + (self.xres, self.yres) + } +} + +#[repr(C)] +#[derive(Debug, Default)] +struct FbBitfield { + offset: u32, + length: u32, + msb_right: u32, +} + +pub fn init() { + const FBIOGET_VSCREENINFO: u64 = 0x4600; + const FBIOGET_FSCREENINFO: u64 = 0x4602; + + #[cfg(target_arch = "aarch64")] + let fbfd = unsafe { libc::open("/dev/fb0".as_ptr(), libc::O_RDWR) }; + #[cfg(not(target_arch = "aarch64"))] + let fbfd = unsafe { libc::open("/dev/fb0".as_ptr() as *const i8, libc::O_RDWR) }; + if fbfd < 0 { + return; + } + + let mut vinfo = FbVarScreeninfo::default(); + if unsafe { libc::ioctl(fbfd, FBIOGET_VSCREENINFO, &mut vinfo) } < 0 { + return; + } + + let mut finfo = FbFixScreeninfo::default(); + if unsafe { libc::ioctl(fbfd, FBIOGET_FSCREENINFO, &mut finfo) } < 0 { + return; + } + + let size = finfo.size() as usize; + let addr = unsafe { + libc::mmap( + std::ptr::null_mut::(), + size, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_SHARED, + fbfd, + 0, + ) + }; + if (addr as isize) < 0 { + return; + } + + let (width, height) = vinfo.resolution(); + let addr = addr as 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), + paddr: addr, + vaddr: addr, + screen_size: size, + }; + *FRAME_BUFFER.write() = Some(fb_info); +} diff --git a/kernel-hal/src/libos/dev/input.rs b/kernel-hal/src/libos/dev/input.rs new file mode 100644 index 00000000..942f94c7 --- /dev/null +++ b/kernel-hal/src/libos/dev/input.rs @@ -0,0 +1,96 @@ +use lazy_static::lazy_static; +use std::os::unix::io::AsRawFd; +use std::sync::Mutex; + +type MouseCallbackFn = dyn Fn([u8; 3]) + Send + Sync; +type KBDCallbackFn = dyn Fn(u16, i32) + Send + Sync; + +lazy_static! { + static ref MOUSE_CALLBACK: Mutex>> = Mutex::new(Vec::new()); + static ref KBD_CALLBACK: Mutex>> = Mutex::new(Vec::new()); +} + +fn init_kbd() { + let fd = std::fs::File::open("/dev/input/event1").expect("Failed to open input event device."); + // ?? + /* let inputfd = unsafe { + libc::open( + "/dev/input/event1".as_ptr() as *const i8, + libc::O_RDONLY /* | libc::O_NONBLOCK */, + ) + }; */ + if fd.as_raw_fd() < 0 { + return; + } + + #[repr(C)] + #[derive(Debug, Copy, Clone, Default)] + pub struct TimeVal { + pub sec: usize, + pub usec: usize, + } + #[repr(C)] + #[derive(Debug, Copy, Clone, Default)] + struct InputEvent { + time: TimeVal, + type_: u16, + code: u16, + value: i32, + } + + std::thread::spawn(move || { + use core::mem::{size_of, transmute, transmute_copy}; + let ev = InputEvent::default(); + const LEN: usize = size_of::(); + let mut buf: [u8; LEN] = unsafe { transmute(ev) }; + loop { + std::thread::sleep(std::time::Duration::from_millis(8)); + let ret = + unsafe { libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, LEN) }; + if ret < 0 { + break; + } + let ev: InputEvent = unsafe { transmute_copy(&buf) }; + if ev.type_ == 1 { + KBD_CALLBACK.lock().unwrap().iter().for_each(|callback| { + callback(ev.code, ev.value); + }); + } + } + }); +} + +fn init_mice() { + let fd = std::fs::File::open("/dev/input/mice").expect("Failed to open input event device."); + if fd.as_raw_fd() < 0 { + return; + } + + std::thread::spawn(move || { + let mut buf = [0u8; 3]; + loop { + std::thread::sleep(std::time::Duration::from_millis(8)); + let ret = + unsafe { libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, 3) }; + if ret < 0 { + break; + } + MOUSE_CALLBACK.lock().unwrap().iter().for_each(|callback| { + callback(buf); + }); + } + }); +} + +pub fn mice_set_callback(callback: Box) { + MOUSE_CALLBACK.lock().unwrap().push(callback); +} + +pub fn kbd_set_callback(callback: Box) { + KBD_CALLBACK.lock().unwrap().push(callback); +} + +pub fn init() { + init_kbd(); + init_mice(); +} diff --git a/kernel-hal/src/libos/dev/mod.rs b/kernel-hal/src/libos/dev/mod.rs new file mode 100644 index 00000000..087d3867 --- /dev/null +++ b/kernel-hal/src/libos/dev/mod.rs @@ -0,0 +1,2 @@ +pub mod fb; +pub mod input; diff --git a/kernel-hal-unix/src/macos.rs b/kernel-hal/src/libos/macos.rs similarity index 100% rename from kernel-hal-unix/src/macos.rs rename to kernel-hal/src/libos/macos.rs diff --git a/kernel-hal/src/libos/mem_common.rs b/kernel-hal/src/libos/mem_common.rs new file mode 100644 index 00000000..ad35546f --- /dev/null +++ b/kernel-hal/src/libos/mem_common.rs @@ -0,0 +1,77 @@ +use alloc::collections::VecDeque; +use lazy_static::lazy_static; +use std::fs::{File, OpenOptions}; +use std::io::Error; +use std::os::unix::io::AsRawFd; +use std::sync::Mutex; + +use crate::{PhysAddr, VirtAddr, PAGE_SIZE}; + +/// Map physical memory from here. +pub(super) const PMEM_SIZE: usize = 0x4000_0000; // 1GiB + +lazy_static! { + pub(super) static ref FRAME_FILE: File = create_pmem_file(); + pub(super) static ref AVAILABLE_FRAMES: Mutex> = + Mutex::new((PAGE_SIZE..PMEM_SIZE).step_by(PAGE_SIZE).collect()); +} + +pub(super) fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { + /// Map physical memory from here. + const PMEM_BASE: VirtAddr = 0x8_0000_0000; + + PMEM_BASE + paddr +} + +/// Ensure physical memory are mmapped and accessible. +pub(super) fn ensure_mmap_pmem() { + FRAME_FILE.as_raw_fd(); +} + +pub(super) fn create_pmem_file() -> File { + let dir = tempfile::tempdir().expect("failed to create pmem dir"); + let path = dir.path().join("pmem"); + + // workaround on macOS to avoid permission denied. + // see https://jiege.ch/software/2020/02/07/macos-mmap-exec/ for analysis on this problem. + #[cfg(target_os = "macos")] + std::mem::forget(dir); + + let file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&path) + .expect("failed to create pmem file"); + file.set_len(PMEM_SIZE as u64) + .expect("failed to resize file"); + trace!("create pmem file: path={:?}, size={:#x}", path, PMEM_SIZE); + let prot = libc::PROT_READ | libc::PROT_WRITE; + mmap(file.as_raw_fd(), 0, PMEM_SIZE, phys_to_virt(0), prot); + file +} + +/// Mmap frame file `fd` to `vaddr`. +pub(super) fn mmap(fd: libc::c_int, offset: usize, len: usize, vaddr: VirtAddr, prot: libc::c_int) { + // workaround on macOS to write text section. + #[cfg(target_os = "macos")] + let prot = if prot & libc::PROT_EXEC != 0 { + prot | libc::PROT_WRITE + } else { + prot + }; + + let ret = unsafe { + let flags = libc::MAP_SHARED | libc::MAP_FIXED; + libc::mmap(vaddr as _, len, prot, flags, fd, offset as _) + } as usize; + trace!( + "mmap file: fd={}, offset={:#x}, len={:#x}, vaddr={:#x}, prot={:#b}", + fd, + offset, + len, + vaddr, + prot, + ); + assert_eq!(ret, vaddr, "failed to mmap: {:?}", Error::last_os_error()); +} diff --git a/kernel-hal/src/libos/memory.rs b/kernel-hal/src/libos/memory.rs new file mode 100644 index 00000000..79394122 --- /dev/null +++ b/kernel-hal/src/libos/memory.rs @@ -0,0 +1,69 @@ +use super::mem_common::{ensure_mmap_pmem, phys_to_virt, AVAILABLE_FRAMES, PMEM_SIZE}; +use crate::{PhysAddr, PAGE_SIZE}; + +pub use crate::common::memory::*; + +/// Read physical memory from `paddr` to `buf`. +pub fn pmem_read(paddr: PhysAddr, buf: &mut [u8]) { + trace!("pmem read: paddr={:#x}, len={:#x}", paddr, buf.len()); + assert!(paddr + buf.len() <= PMEM_SIZE); + ensure_mmap_pmem(); + unsafe { + (phys_to_virt(paddr) as *const u8).copy_to_nonoverlapping(buf.as_mut_ptr(), buf.len()); + } +} + +/// Write physical memory to `paddr` from `buf`. +pub fn pmem_write(paddr: PhysAddr, buf: &[u8]) { + trace!("pmem write: paddr={:#x}, len={:#x}", paddr, buf.len()); + assert!(paddr + buf.len() <= PMEM_SIZE); + ensure_mmap_pmem(); + unsafe { + buf.as_ptr() + .copy_to_nonoverlapping(phys_to_virt(paddr) as _, buf.len()); + } +} + +/// Zero physical memory at `[paddr, paddr + len)` +pub fn pmem_zero(paddr: PhysAddr, len: usize) { + trace!("pmem_zero: addr={:#x}, len={:#x}", paddr, len); + assert!(paddr + len <= PMEM_SIZE); + ensure_mmap_pmem(); + unsafe { + core::ptr::write_bytes(phys_to_virt(paddr) as *mut u8, 0, len); + } +} + +/// Copy content of `src` frame to `target` frame +pub fn frame_copy(src: PhysAddr, target: PhysAddr) { + trace!("frame_copy: {:#x} <- {:#x}", target, src); + assert!(src + PAGE_SIZE <= PMEM_SIZE && target + PAGE_SIZE <= PMEM_SIZE); + ensure_mmap_pmem(); + unsafe { + let buf = phys_to_virt(src) as *const u8; + buf.copy_to_nonoverlapping(phys_to_virt(target) as _, PAGE_SIZE); + } +} + +pub fn frame_flush(_target: PhysAddr) { + // do nothing +} + +pub fn frame_alloc() -> Option { + let ret = AVAILABLE_FRAMES.lock().unwrap().pop_front(); + trace!("frame alloc: {:?}", ret); + ret +} + +pub fn frame_alloc_contiguous(_size: usize, _align_log2: usize) -> Option { + unimplemented!() +} + +pub fn frame_dealloc(paddr: PhysAddr) { + trace!("frame dealloc: {:?}", paddr); + AVAILABLE_FRAMES.lock().unwrap().push_back(paddr); +} + +pub fn zero_frame_addr() -> PhysAddr { + 0 +} diff --git a/kernel-hal/src/libos/mod.rs b/kernel-hal/src/libos/mod.rs new file mode 100644 index 00000000..4f6b8c7e --- /dev/null +++ b/kernel-hal/src/libos/mod.rs @@ -0,0 +1,50 @@ +mod mem_common; + +pub mod context; +pub mod cpu; +pub mod memory; +pub mod paging; +pub mod serial; +pub mod thread; +pub mod timer; +pub mod vdso; + +#[path = "../unimp/interrupt.rs"] +pub mod interrupt; +#[path = "../unimp/rand.rs"] +pub mod rand; + +cfg_if::cfg_if! { + if #[cfg(target_os = "linux")] { + pub mod dev; + } else { + #[path = "../unimp/dev/mod.rs"] + pub mod dev; + } +} + +#[cfg(target_os = "macos")] +include!("macos.rs"); + +/// Initialize the HAL. +/// +/// This function must be called at the beginning. +pub fn init() { + #[cfg(target_os = "macos")] + unsafe { + register_sigsegv_handler(); + } + // spawn a thread to read stdin + // TODO: raw mode + use std::io::Read; + std::thread::spawn(|| { + for i in std::io::stdin().bytes() { + serial::serial_put(i.unwrap()); + } + }); +} + +// FIXME +#[path = "../unimp/misc.rs"] +mod misc; +pub use misc::*; diff --git a/kernel-hal/src/libos/paging.rs b/kernel-hal/src/libos/paging.rs new file mode 100644 index 00000000..bc626505 --- /dev/null +++ b/kernel-hal/src/libos/paging.rs @@ -0,0 +1,115 @@ +use std::io::Error; +use std::os::unix::io::AsRawFd; + +use super::mem_common::{mmap, FRAME_FILE}; +use crate::{HalResult, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE}; + +pub use crate::common::paging::*; + +pub struct PageTable; + +impl PageTable { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + PageTable + } + + pub fn current() -> Self { + PageTable + } +} + +impl PageTableTrait for PageTable { + /// Map the page of `vaddr` to the frame of `paddr` with `flags`. + fn map(&mut self, vaddr: VirtAddr, paddr: PhysAddr, flags: MMUFlags) -> HalResult<()> { + debug_assert!(page_aligned(vaddr)); + debug_assert!(page_aligned(paddr)); + let prot = flags.to_mmap_prot(); + mmap(FRAME_FILE.as_raw_fd(), paddr, PAGE_SIZE, vaddr, prot); + Ok(()) + } + + /// Unmap the page of `vaddr`. + fn unmap(&mut self, vaddr: VirtAddr) -> HalResult<()> { + self.unmap_cont(vaddr, 1) + } + + /// Change the `flags` of the page of `vaddr`. + fn protect(&mut self, vaddr: VirtAddr, flags: MMUFlags) -> HalResult<()> { + debug_assert!(page_aligned(vaddr)); + let prot = flags.to_mmap_prot(); + let ret = unsafe { libc::mprotect(vaddr as _, PAGE_SIZE, prot) }; + assert_eq!(ret, 0, "failed to mprotect: {:?}", Error::last_os_error()); + Ok(()) + } + + /// Query the physical address which the page of `vaddr` maps to. + fn query(&mut self, vaddr: VirtAddr) -> HalResult { + debug_assert!(page_aligned(vaddr)); + unimplemented!() + } + + /// Get the physical address of root page table. + fn table_phys(&self) -> PhysAddr { + 0 + } + + fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> HalResult<()> { + if pages == 0 { + return Ok(()); + } + debug_assert!(page_aligned(vaddr)); + let ret = unsafe { libc::munmap(vaddr as _, PAGE_SIZE * pages) }; + assert_eq!(ret, 0, "failed to munmap: {:?}", Error::last_os_error()); + Ok(()) + } +} + +fn page_aligned(x: VirtAddr) -> bool { + x % PAGE_SIZE == 0 +} + +trait FlagsExt { + fn to_mmap_prot(&self) -> libc::c_int; +} + +impl FlagsExt for MMUFlags { + fn to_mmap_prot(&self) -> libc::c_int { + let mut flags = 0; + if self.contains(MMUFlags::READ) { + flags |= libc::PROT_READ; + } + if self.contains(MMUFlags::WRITE) { + flags |= libc::PROT_WRITE; + } + if self.contains(MMUFlags::EXECUTE) { + flags |= libc::PROT_EXEC; + } + flags + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// A valid virtual address base to mmap. + const VBASE: VirtAddr = 0x2_00000000; + + #[test] + fn map_unmap() { + let mut pt = PageTable::new(); + let flags = MMUFlags::READ | MMUFlags::WRITE; + // map 2 pages to 1 frame + pt.map(VBASE, 0x1000, flags).unwrap(); + pt.map(VBASE + 0x1000, 0x1000, flags).unwrap(); + + unsafe { + const MAGIC: usize = 0xdead_beaf; + (VBASE as *mut usize).write(MAGIC); + assert_eq!(((VBASE + 0x1000) as *mut usize).read(), MAGIC); + } + + pt.unmap(VBASE + 0x1000).unwrap(); + } +} diff --git a/kernel-hal/src/libos/serial.rs b/kernel-hal/src/libos/serial.rs new file mode 100644 index 00000000..4bec441b --- /dev/null +++ b/kernel-hal/src/libos/serial.rs @@ -0,0 +1,33 @@ +use lazy_static::lazy_static; +use std::collections::VecDeque; +use std::sync::Mutex; + +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. +pub fn serial_put(x: u8) { + STDIN.lock().unwrap().push_back(x); + STDIN_CALLBACK.lock().unwrap().retain(|f| !f()); +} + +pub fn serial_set_callback(callback: Box bool + Send + Sync>) { + STDIN_CALLBACK.lock().unwrap().push(callback); +} + +pub fn serial_read(buf: &mut [u8]) -> usize { + let mut stdin = STDIN.lock().unwrap(); + let len = stdin.len().min(buf.len()); + for c in &mut buf[..len] { + *c = stdin.pop_front().unwrap(); + } + len +} + +/// Output a char to console. +pub fn serial_write(s: &str) { + eprint!("{}", s); +} diff --git a/kernel-hal/src/libos/thread.rs b/kernel-hal/src/libos/thread.rs new file mode 100644 index 00000000..1fc66846 --- /dev/null +++ b/kernel-hal/src/libos/thread.rs @@ -0,0 +1,20 @@ +use async_std::task_local; +use core::{cell::Cell, future::Future, pin::Pin}; + +task_local! { + static TID: Cell = Cell::new(0); + static PID: Cell = Cell::new(0); +} + +pub fn spawn(future: Pin + Send + 'static>>, _vmtoken: usize) { + async_std::task::spawn(future); +} + +pub fn set_tid(tid: u64, pid: u64) { + TID.with(|x| x.set(tid)); + PID.with(|x| x.set(pid)); +} + +pub fn get_tid() -> (u64, u64) { + (TID.with(|x| x.get()), PID.with(|x| x.get())) +} diff --git a/kernel-hal/src/libos/timer.rs b/kernel-hal/src/libos/timer.rs new file mode 100644 index 00000000..173d4d55 --- /dev/null +++ b/kernel-hal/src/libos/timer.rs @@ -0,0 +1,21 @@ +use std::time::{Duration, SystemTime}; + +/// Get current time. +pub fn timer_now() -> Duration { + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() +} + +/// Set a new timer. +/// +/// After `deadline`, the `callback` will be called. +pub fn timer_set(deadline: Duration, callback: Box) { + std::thread::spawn(move || { + let now = timer_now(); + if deadline > now { + std::thread::sleep(deadline - now); + } + callback(timer_now()); + }); +} diff --git a/kernel-hal/src/libos/vdso.rs b/kernel-hal/src/libos/vdso.rs new file mode 100644 index 00000000..0356b4d2 --- /dev/null +++ b/kernel-hal/src/libos/vdso.rs @@ -0,0 +1,30 @@ +use git_version::git_version; + +use super::mem_common::PMEM_SIZE; + +pub use crate::common::vdso::*; + +pub fn vdso_constants() -> VdsoConstants { + let tsc_frequency = 3000u16; + let mut constants = VdsoConstants { + max_num_cpus: 1, + features: Features { + cpu: 0, + hw_breakpoint_count: 0, + hw_watchpoint_count: 0, + }, + dcache_line_size: 0, + icache_line_size: 0, + ticks_per_second: tsc_frequency as u64 * 1_000_000, + ticks_to_mono_numerator: 1000, + ticks_to_mono_denominator: tsc_frequency as u32, + physmem: PMEM_SIZE as u64, + version_string_len: 0, + version_string: Default::default(), + }; + constants.set_version_string(git_version!( + prefix = "git-", + args = ["--always", "--abbrev=40", "--dirty=-dirty"] + )); + constants +} diff --git a/kernel-hal/src/unimp/context.rs b/kernel-hal/src/unimp/context.rs new file mode 100644 index 00000000..b8817bf9 --- /dev/null +++ b/kernel-hal/src/unimp/context.rs @@ -0,0 +1,15 @@ +pub use crate::common::context::*; + +pub fn context_run(_context: &mut UserContext) { + unimplemented!() +} + +/// Get fault address of the last page fault. +pub fn fetch_fault_vaddr() -> crate::VirtAddr { + unimplemented!() +} + +/// Get the trap number when trap. +pub fn fetch_trap_num(_context: &UserContext) -> usize { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/cpu.rs b/kernel-hal/src/unimp/cpu.rs new file mode 100644 index 00000000..bb996897 --- /dev/null +++ b/kernel-hal/src/unimp/cpu.rs @@ -0,0 +1,3 @@ +pub fn cpu_id() -> u8 { + 0 +} diff --git a/kernel-hal/src/unimp/dev/fb.rs b/kernel-hal/src/unimp/dev/fb.rs new file mode 100644 index 00000000..f5af892b --- /dev/null +++ b/kernel-hal/src/unimp/dev/fb.rs @@ -0,0 +1,5 @@ +pub use crate::common::fb::*; + +pub fn init() { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/dev/input.rs b/kernel-hal/src/unimp/dev/input.rs new file mode 100644 index 00000000..cb4d18b3 --- /dev/null +++ b/kernel-hal/src/unimp/dev/input.rs @@ -0,0 +1,13 @@ +use alloc::boxed::Box; + +pub fn kbd_set_callback(_callback: Box) { + unimplemented!() +} + +pub fn mice_set_callback(_callback: Box) { + unimplemented!() +} + +pub fn init() { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/dev/mod.rs b/kernel-hal/src/unimp/dev/mod.rs new file mode 100644 index 00000000..087d3867 --- /dev/null +++ b/kernel-hal/src/unimp/dev/mod.rs @@ -0,0 +1,2 @@ +pub mod fb; +pub mod input; diff --git a/kernel-hal/src/unimp/interrupt.rs b/kernel-hal/src/unimp/interrupt.rs new file mode 100644 index 00000000..96528329 --- /dev/null +++ b/kernel-hal/src/unimp/interrupt.rs @@ -0,0 +1,61 @@ +use alloc::boxed::Box; + +/// Enable IRQ. +pub fn enable_irq(_vector: u32) { + unimplemented!() +} + +/// Disable IRQ. +pub fn disable_irq(_vector: u32) { + unimplemented!() +} + +/// Is a valid IRQ number. +pub fn is_valid_irq(_vector: u32) -> bool { + unimplemented!() +} + +/// Configure the specified interrupt vector. If it is invoked, it muust be +/// invoked prior to interrupt registration. +pub fn configure_irq(_vector: u32, _trig_mode: bool, _polarity: bool) -> bool { + unimplemented!() +} + +/// Add an interrupt handle to an IRQ +pub fn register_irq_handler(_vector: u32, _handle: Box) -> Option { + unimplemented!() +} + +/// Remove the interrupt handle to an IRQ +pub fn unregister_irq_handler(_vector: u32) -> bool { + unimplemented!() +} + +/// Handle IRQ. +pub fn handle_irq(_vector: u32) { + unimplemented!() +} + +/// Method used for platform allocation of blocks of MSI and MSI-X compatible +/// IRQ targets. +pub fn msi_allocate_block(_irq_num: u32) -> Option<(usize, usize)> { + unimplemented!() +} + +/// Method used to free a block of MSI IRQs previously allocated by msi_alloc_block(). +/// This does not unregister IRQ handlers. +pub fn msi_free_block(_irq_start: u32, _irq_num: u32) { + unimplemented!() +} + +/// Register a handler function for a given msi_id within an msi_block_t. Passing a +/// NULL handler will effectively unregister a handler for a given msi_id within the +/// block. +pub fn msi_register_handler( + _irq_start: u32, + _irq_num: u32, + _msi_id: u32, + _handle: Box, +) { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/memory.rs b/kernel-hal/src/unimp/memory.rs new file mode 100644 index 00000000..7bbbb2fb --- /dev/null +++ b/kernel-hal/src/unimp/memory.rs @@ -0,0 +1,44 @@ +use crate::PhysAddr; + +pub use crate::common::memory::*; + +/// Read physical memory from `paddr` to `buf`. +pub fn pmem_read(_paddr: PhysAddr, _buf: &mut [u8]) { + unimplemented!() +} + +/// Write physical memory to `paddr` from `buf`. +pub fn pmem_write(_paddr: PhysAddr, _buf: &[u8]) { + unimplemented!() +} + +/// Zero physical memory at `[paddr, paddr + len)`. +pub fn pmem_zero(_paddr: PhysAddr, _len: usize) { + unimplemented!() +} + +/// Copy content of `src` frame to `target` frame. +pub fn frame_copy(_src: PhysAddr, _target: PhysAddr) { + unimplemented!() +} + +/// Flush the physical frame. +pub fn frame_flush(_target: PhysAddr) { + unimplemented!() +} + +pub fn frame_alloc() -> Option { + unimplemented!() +} + +pub fn frame_alloc_contiguous(_size: usize, _align_log2: usize) -> Option { + unimplemented!() +} + +pub fn frame_dealloc(_paddr: PhysAddr) { + unimplemented!() +} + +pub fn zero_frame_addr() -> PhysAddr { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/misc.rs b/kernel-hal/src/unimp/misc.rs new file mode 100644 index 00000000..f7ab2319 --- /dev/null +++ b/kernel-hal/src/unimp/misc.rs @@ -0,0 +1,35 @@ +use crate::{context::UserContext, VirtAddr}; +use acpi::Acpi; + +/// Get fault address of the last page fault. +pub fn fetch_fault_vaddr() -> VirtAddr { + unimplemented!() +} + +pub fn fetch_trap_num(_context: &UserContext) -> usize { + unimplemented!() +} + +/// Get physical address of `acpi_rsdp` and `smbios` on x86_64. +pub fn pc_firmware_tables() -> (u64, u64) { + unimplemented!() +} + +/// Get ACPI Table +pub fn get_acpi_table() -> Option { + unimplemented!() +} + +/// IO Ports access on x86 platform +pub fn outpd(_port: u16, _value: u32) { + unimplemented!() +} + +pub fn inpd(_port: u16) -> u32 { + unimplemented!() +} + +/// Get local APIC ID +pub fn apic_local_id() -> u8 { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/mod.rs b/kernel-hal/src/unimp/mod.rs new file mode 100644 index 00000000..3c9b6899 --- /dev/null +++ b/kernel-hal/src/unimp/mod.rs @@ -0,0 +1,21 @@ +pub mod context; +pub mod cpu; +pub mod dev; +pub mod interrupt; +pub mod memory; +pub mod misc; +pub mod paging; +pub mod rand; +pub mod serial; +pub mod thread; +pub mod timer; +pub mod vdso; + +pub use self::misc::*; // FIXME + +/// Initialize the HAL. +/// +/// This function must be called at the beginning. +pub fn init() { + unimplemented!(); +} diff --git a/kernel-hal/src/unimp/paging.rs b/kernel-hal/src/unimp/paging.rs new file mode 100644 index 00000000..e4e65069 --- /dev/null +++ b/kernel-hal/src/unimp/paging.rs @@ -0,0 +1,50 @@ +use crate::{HalResult, MMUFlags, PhysAddr, VirtAddr}; + +pub use crate::common::paging::*; + +pub struct PageTable; + +impl PageTable { + /// Create a new `PageTable`. + pub fn new() -> Self { + PageTable + } + + /// Get the current root page table physical address. (e.g. CR3, SATP, ...) + pub fn current() -> Self { + unimplemented!(); + } +} + +impl PageTableTrait for PageTable { + /// Map the page of `vaddr` to the frame of `paddr` with `flags`. + fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> HalResult<()> { + unimplemented!(); + } + + /// Unmap the page of `vaddr`. + fn unmap(&mut self, _vaddr: VirtAddr) -> HalResult<()> { + unimplemented!(); + } + + /// Change the `flags` of the page of `vaddr`. + fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> HalResult<()> { + unimplemented!(); + } + + /// Query the physical address which the page of `vaddr` maps to. + fn query(&mut self, _vaddr: VirtAddr) -> HalResult { + unimplemented!(); + } + + /// Get the physical address of root page table. + fn table_phys(&self) -> PhysAddr { + unimplemented!(); + } + + #[cfg(target_arch = "riscv64")] + /// Activate this page table + fn activate(&self) { + unimplemented!(); + } +} diff --git a/kernel-hal/src/unimp/rand.rs b/kernel-hal/src/unimp/rand.rs new file mode 100644 index 00000000..00528e89 --- /dev/null +++ b/kernel-hal/src/unimp/rand.rs @@ -0,0 +1,18 @@ +/// Fill random bytes to the buffer +#[allow(unused_variables)] +pub fn fill_random(buf: &mut [u8]) { + cfg_if::cfg_if! { + if #[cfg(target_arch = "x86_64")] { + // TODO: optimize + for x in buf.iter_mut() { + let mut r = 0; + unsafe { + core::arch::x86_64::_rdrand16_step(&mut r); + } + *x = r as _; + } + } else { + unimplemented!() + } + } +} diff --git a/kernel-hal/src/unimp/serial.rs b/kernel-hal/src/unimp/serial.rs new file mode 100644 index 00000000..b009b66c --- /dev/null +++ b/kernel-hal/src/unimp/serial.rs @@ -0,0 +1,21 @@ +use alloc::boxed::Box; + +/// Put a char by serial interrupt handler. +pub fn serial_put(_x: u8) { + unimplemented!() +} + +/// Register a callback of serial readable event. +pub fn serial_set_callback(_callback: Box bool + Send + Sync>) { + unimplemented!() +} + +/// Read a string from console. +pub fn serial_read(_buf: &mut [u8]) -> usize { + unimplemented!() +} + +/// Output a string to console. +pub fn serial_write(_s: &str) { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/thread.rs b/kernel-hal/src/unimp/thread.rs new file mode 100644 index 00000000..3be76b86 --- /dev/null +++ b/kernel-hal/src/unimp/thread.rs @@ -0,0 +1,18 @@ +use alloc::boxed::Box; +use core::future::Future; +use core::pin::Pin; + +/// Spawn a new thread. +pub fn spawn(_future: Pin + Send + 'static>>, _vmtoken: usize) { + unimplemented!() +} + +/// Set tid and pid of current task. +pub fn set_tid(_tid: u64, _pid: u64) { + unimplemented!() +} + +/// Get tid and pid of current task.] +pub fn get_tid() -> (u64, u64) { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/timer.rs b/kernel-hal/src/unimp/timer.rs new file mode 100644 index 00000000..07c4d5e6 --- /dev/null +++ b/kernel-hal/src/unimp/timer.rs @@ -0,0 +1,21 @@ +use alloc::boxed::Box; +use core::time::Duration; + +/// Get current time. +pub fn timer_now() -> Duration { + unimplemented!() +} + +/// Set a new timer. After `deadline`, the `callback` will be called. +pub fn timer_set(_deadline: Duration, _callback: Box) { + unimplemented!() +} + +pub fn timer_set_next() { + unimplemented!() +} + +/// Check timers, call when timer interrupt happened. +pub fn timer_tick() { + unimplemented!() +} diff --git a/kernel-hal/src/unimp/vdso.rs b/kernel-hal/src/unimp/vdso.rs new file mode 100644 index 00000000..112591ae --- /dev/null +++ b/kernel-hal/src/unimp/vdso.rs @@ -0,0 +1,5 @@ +pub use crate::common::vdso::*; + +pub fn vdso_constants() -> VdsoConstants { + unimplemented!() +} diff --git a/linux-loader/Cargo.toml b/linux-loader/Cargo.toml index d0ae18d4..ff99230c 100644 --- a/linux-loader/Cargo.toml +++ b/linux-loader/Cargo.toml @@ -16,10 +16,10 @@ zircon-object = { path = "../zircon-object" } kernel-hal = { path = "../kernel-hal" } rcore-fs-hostfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2", optional = true } env_logger = { version = "0.8", optional = true } -kernel-hal-unix = { path = "../kernel-hal-unix", optional = true } async-std = { version = "1.9", features = ["attributes"], optional = true } [features] -default = ["std"] -std = ["env_logger", "async-std", "kernel-hal-unix", "rcore-fs-hostfs", "zircon-object/aspace-separate"] -graphic = ["std"] +default = ["std", "libos"] +libos = ["kernel-hal/libos"] +std = ["env_logger", "async-std", "rcore-fs-hostfs", "zircon-object/aspace-separate"] +graphic = ["std", "linux-object/graphic"] diff --git a/linux-loader/src/lib.rs b/linux-loader/src/lib.rs index e4c35c72..a25f8572 100644 --- a/linux-loader/src/lib.rs +++ b/linux-loader/src/lib.rs @@ -23,10 +23,10 @@ use { }; #[cfg(target_arch = "riscv64")] -use {kernel_hal::UserContext, zircon_object::object::KernelObject}; +use {kernel_hal::context::UserContext, zircon_object::object::KernelObject}; #[cfg(target_arch = "x86_64")] -use kernel_hal::GeneralRegs; +use kernel_hal::context::GeneralRegs; /// Create and run main Linux process pub fn run(args: Vec, envs: Vec, rootfs: Arc) -> Arc { @@ -35,7 +35,7 @@ pub fn run(args: Vec, envs: Vec, rootfs: Arc) -> let thread = Thread::create_linux(&proc).unwrap(); let loader = LinuxElfLoader { #[cfg(feature = "std")] - syscall_entry: kernel_hal_unix::syscall_entry as usize, + syscall_entry: kernel_hal::context::syscall_entry as usize, #[cfg(not(feature = "std"))] syscall_entry: 0, stack_pages: 8, @@ -57,7 +57,8 @@ pub fn run(args: Vec, envs: Vec, rootfs: Arc) -> let path = args[0].clone(); debug!("Linux process: {:?}", path); - let pg_token = kernel_hal::current_page_table(); + use kernel_hal::paging::PageTableTrait; + let pg_token = kernel_hal::paging::PageTable::current().table_phys(); debug!("current pgt = {:#x}", pg_token); //调用zircon-object/src/task/thread.start设置好要执行的thread let (entry, sp) = loader.load(&proc.vmar(), &data, args, envs, path).unwrap(); @@ -86,7 +87,7 @@ async fn new_thread(thread: CurrentThread) { // run trace!("go to user: {:#x?}", cx); - kernel_hal::context_run(&mut cx); + kernel_hal::context::context_run(&mut cx); trace!("back from user: {:#x?}", cx); // handle trap/interrupt/syscall @@ -94,13 +95,13 @@ async fn new_thread(thread: CurrentThread) { match cx.trap_num { 0x100 => handle_syscall(&thread, &mut cx.general).await, 0x20..=0x3f => { - kernel_hal::InterruptManager::handle_irq(cx.trap_num as u32); + kernel_hal::interrupt::handle_irq(cx.trap_num as u32); if cx.trap_num == 0x20 { - kernel_hal::yield_now().await; + kernel_hal::future::yield_now().await; } } 0xe => { - let vaddr = kernel_hal::fetch_fault_vaddr(); + let vaddr = kernel_hal::context::fetch_fault_vaddr(); let flags = if cx.error_code & 0x2 == 0 { MMUFlags::READ } else { @@ -129,7 +130,7 @@ async fn new_thread(thread: CurrentThread) { match trap_num { //Irq 0 | 4 | 5 | 8 | 9 => { - kernel_hal::InterruptManager::handle_irq(trap_num as u32); + kernel_hal::interrupt::handle_irq(trap_num as u32); //Timer if trap_num == 4 || trap_num == 5 { @@ -141,10 +142,10 @@ async fn new_thread(thread: CurrentThread) { kernel_hal::timer_tick(); */ - kernel_hal::yield_now().await; + kernel_hal::future::yield_now().await; } - //kernel_hal::InterruptManager::handle_irq(trap_num as u32); + //kernel_hal::interrupt::handle_irq(trap_num as u32); } _ => panic!( "not supported pid: {} interrupt {} from user mode. {:#x?}", @@ -204,7 +205,7 @@ async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) { let mut syscall = Syscall { thread, #[cfg(feature = "std")] - syscall_entry: kernel_hal_unix::syscall_entry as usize, + syscall_entry: kernel_hal::context::syscall_entry as usize, #[cfg(not(feature = "std"))] syscall_entry: 0, thread_fn, @@ -234,7 +235,7 @@ async fn handle_syscall(thread: &CurrentThread, cx: &mut UserContext) { let mut syscall = Syscall { thread, #[cfg(feature = "std")] - syscall_entry: kernel_hal_unix::syscall_entry as usize, + syscall_entry: kernel_hal::context::syscall_entry as usize, #[cfg(not(feature = "std"))] syscall_entry: 0, context: cx, diff --git a/linux-loader/src/main.rs b/linux-loader/src/main.rs index 614799b8..5e380260 100644 --- a/linux-loader/src/main.rs +++ b/linux-loader/src/main.rs @@ -15,16 +15,16 @@ async fn main() { // init loggger for debug init_logger(); // init HAL implementation on unix - kernel_hal_unix::init(); + kernel_hal::init(); #[cfg(feature = "graphic")] { - kernel_hal_unix::init_framebuffer(); - kernel_hal_unix::init_input(); + kernel_hal::dev::fb::init(); + kernel_hal::dev::input::init(); } - kernel_hal::serial_set_callback(Box::new({ + kernel_hal::serial::serial_set_callback(Box::new({ move || { let mut buffer = [0; 255]; - let len = kernel_hal::serial_read(&mut buffer); + let len = kernel_hal::serial::serial_read(&mut buffer); for c in &buffer[..len] { STDIN.push((*c).into()); } @@ -70,7 +70,7 @@ mod tests { /// test with cmd line async fn test(cmdline: &str) -> i64 { - kernel_hal_unix::init(); + kernel_hal::init(); let args: Vec = cmdline.split(' ').map(|s| s.into()).collect(); let envs = diff --git a/linux-object/Cargo.toml b/linux-object/Cargo.toml index d4ddcbd0..73b44ac9 100644 --- a/linux-object/Cargo.toml +++ b/linux-object/Cargo.toml @@ -7,6 +7,9 @@ description = "Linux kernel objects" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +graphic = [] + [dependencies] async-trait = "0.1" log = "0.4" @@ -24,3 +27,4 @@ rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" } rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" } rcore-fs-mountfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" } rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" } +cfg-if = "1.0" diff --git a/linux-object/src/fs/fbdev.rs b/linux-object/src/fs/fbdev.rs index 85ed662a..571ff3af 100644 --- a/linux-object/src/fs/fbdev.rs +++ b/linux-object/src/fs/fbdev.rs @@ -1,7 +1,7 @@ //! Implement INode for framebuffer use core::any::Any; -use kernel_hal::{ColorFormat, FramebufferInfo, FRAME_BUFFER}; +use kernel_hal::dev::fb::{ColorFormat, FramebufferInfo, FRAME_BUFFER}; use rcore_fs::vfs::*; diff --git a/linux-object/src/fs/input/event.rs b/linux-object/src/fs/input/event.rs index a98fb06c..64a090d9 100644 --- a/linux-object/src/fs/input/event.rs +++ b/linux-object/src/fs/input/event.rs @@ -3,6 +3,7 @@ use alloc::{boxed::Box, collections::VecDeque, sync::Arc}; use core::any::Any; use spin::Mutex; +use kernel_hal::dev::input; use rcore_fs::vfs::*; /// input device @@ -18,7 +19,7 @@ impl InputEventInode { pub fn new(id: usize) -> Self { let data = Arc::new(Mutex::new(VecDeque::with_capacity(MAX_QUEUE))); let data_clone = data.clone(); - kernel_hal::kbd_set_callback(Box::new(move |code, value| { + input::kbd_set_callback(Box::new(move |code, value| { let mut queue = data_clone.lock(); while queue.len() >= MAX_QUEUE { queue.pop_front(); diff --git a/linux-object/src/fs/input/mice.rs b/linux-object/src/fs/input/mice.rs index 0e4361ae..f16ef46d 100644 --- a/linux-object/src/fs/input/mice.rs +++ b/linux-object/src/fs/input/mice.rs @@ -2,6 +2,7 @@ use alloc::{boxed::Box, collections::VecDeque, sync::Arc}; use core::any::Any; use spin::Mutex; +use kernel_hal::dev::input; use rcore_fs::vfs::*; /// mice device @@ -15,7 +16,7 @@ impl InputMiceInode { pub fn new() -> Self { let data = Arc::new(Mutex::new(VecDeque::with_capacity(MAX_QUEUE))); let data_clone = data.clone(); - kernel_hal::mice_set_callback(Box::new(move |data| { + input::mice_set_callback(Box::new(move |data| { let mut queue = data_clone.lock(); while queue.len() >= MAX_QUEUE { queue.pop_front(); diff --git a/linux-object/src/fs/mod.rs b/linux-object/src/fs/mod.rs index b4cf5d15..986d7215 100644 --- a/linux-object/src/fs/mod.rs +++ b/linux-object/src/fs/mod.rs @@ -8,10 +8,8 @@ use rcore_fs_mountfs::MountFS; use rcore_fs_ramfs::RamFS; pub use self::device::*; -pub use self::fbdev::*; pub use self::fcntl::*; pub use self::file::*; -pub use self::input::*; pub use self::pipe::*; pub use self::pseudo::*; pub use self::random::*; @@ -26,16 +24,23 @@ use downcast_rs::impl_downcast; use zircon_object::object::*; mod device; -mod fbdev; mod fcntl; mod file; -mod input; mod ioctl; mod pipe; mod pseudo; mod random; mod stdio; +cfg_if::cfg_if! { + if #[cfg(feature = "graphic")] { + mod fbdev; + mod input; + pub use self::input::*; + pub use self::fbdev::*; + } +} + #[async_trait] /// Generic file interface /// @@ -123,17 +128,21 @@ pub fn create_root_fs(rootfs: Arc) -> Arc { devfs .add("urandom", Arc::new(RandomINode::new(true))) .expect("failed to mknod /dev/urandom"); - devfs - .add("fb0", Arc::new(Fbdev::default())) - .expect("failed to mknod /dev/fb0"); - // TODO /dev/input/event0 - devfs - .add("input-event0", Arc::new(InputEventInode::new(0))) - .expect("failed to mknod /dev/input-event0"); - // TODO /dev/input/mice - devfs - .add("input-mice", Arc::new(InputMiceInode::default())) - .expect("failed to mknod /dev/input-mice"); + + #[cfg(feature = "graphic")] + { + devfs + .add("fb0", Arc::new(Fbdev::default())) + .expect("failed to mknod /dev/fb0"); + // TODO /dev/input/event0 + devfs + .add("input-event0", Arc::new(InputEventInode::new(0))) + .expect("failed to mknod /dev/input-event0"); + // TODO /dev/input/mice + devfs + .add("input-mice", Arc::new(InputMiceInode::default())) + .expect("failed to mknod /dev/input-mice"); + } // mount DevFS at /dev let dev = root.find(true, "dev").unwrap_or_else(|_| { diff --git a/linux-object/src/fs/stdio.rs b/linux-object/src/fs/stdio.rs index 30844375..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_write(s); + kernel_hal::serial::serial_write(s); Ok(buf.len()) } fn poll(&self) -> Result { diff --git a/linux-object/src/time.rs b/linux-object/src/time.rs index b0a72114..2874d3b8 100644 --- a/linux-object/src/time.rs +++ b/linux-object/src/time.rs @@ -2,7 +2,6 @@ use alloc::sync::Arc; use core::time::Duration; -use kernel_hal::timer_now; use rcore_fs::vfs::*; /// TimeSpec struct for clock_gettime, similar to Timespec @@ -39,7 +38,7 @@ impl TimeVal { impl TimeSpec { /// create TimeSpec pub fn now() -> TimeSpec { - let time = timer_now(); + let time = kernel_hal::timer::timer_now(); TimeSpec { sec: time.as_secs() as usize, nsec: (time.as_nanos() % 1_000_000_000) as usize, diff --git a/linux-syscall/src/file/poll.rs b/linux-syscall/src/file/poll.rs index 6084fd89..3ca11c64 100644 --- a/linux-syscall/src/file/poll.rs +++ b/linux-syscall/src/file/poll.rs @@ -12,7 +12,7 @@ use core::mem::size_of; use core::pin::Pin; use core::task::{Context, Poll}; use core::time::Duration; -use kernel_hal::timer_set; +use kernel_hal::timer::timer_set; use linux_object::fs::FileDesc; use linux_object::time::*; diff --git a/linux-syscall/src/lib.rs b/linux-syscall/src/lib.rs index cae97a53..8671fcab 100644 --- a/linux-syscall/src/lib.rs +++ b/linux-syscall/src/lib.rs @@ -8,7 +8,7 @@ //! let mut syscall = Syscall { //! thread, //! #[cfg(feature = "std")] -//! syscall_entry: kernel_hal_unix::syscall_entry as usize, +//! syscall_entry: kernel_hal::context::syscall_entry as usize, //! #[cfg(not(feature = "std"))] //! syscall_entry: 0, //! thread_fn, @@ -32,13 +32,13 @@ use { self::consts::SyscallType as Sys, alloc::sync::Arc, core::convert::TryFrom, - kernel_hal::{user::*, GeneralRegs}, + kernel_hal::{context::GeneralRegs, user::*}, linux_object::{error::*, fs::FileDesc, process::*}, zircon_object::{object::*, task::*, vm::VirtAddr}, }; #[cfg(target_arch = "riscv64")] -use kernel_hal::UserContext; +use kernel_hal::context::UserContext; mod consts { // generated from syscall.h.in diff --git a/linux-syscall/src/misc.rs b/linux-syscall/src/misc.rs index 4bf87388..fb340915 100644 --- a/linux-syscall/src/misc.rs +++ b/linux-syscall/src/misc.rs @@ -132,7 +132,7 @@ impl Syscall<'_> { pub fn sys_getrandom(&mut self, mut buf: UserOutPtr, len: usize, flag: u32) -> SysResult { info!("getrandom: buf: {:?}, len: {:?}, flag {:?}", buf, len, flag); let mut buffer = vec![0u8; len]; - kernel_hal::fill_random(&mut buffer); + kernel_hal::rand::fill_random(&mut buffer); buf.write_array(&buffer[..len])?; Ok(len) } diff --git a/linux-syscall/src/task.rs b/linux-syscall/src/task.rs index d6b4c0a5..0fd79f5a 100644 --- a/linux-syscall/src/task.rs +++ b/linux-syscall/src/task.rs @@ -297,7 +297,7 @@ impl Syscall<'_> { pub async fn sys_nanosleep(&self, req: UserInPtr) -> SysResult { info!("nanosleep: deadline={:?}", req); let req = req.read()?; - kernel_hal::sleep_until(req.into()).await; + kernel_hal::future::sleep_until(req.into()).await; Ok(0) } diff --git a/zCore/Cargo.toml b/zCore/Cargo.toml index f21931c6..76a53f80 100644 --- a/zCore/Cargo.toml +++ b/zCore/Cargo.toml @@ -22,6 +22,7 @@ lto = true log = "0.4" spin = "0.7" buddy_system_allocator = "0.7" +kernel-hal = { path = "../kernel-hal" } kernel-hal-bare = { path = "../kernel-hal-bare" } lazy_static = { version = "1.4", features = ["spin_no_std" ] } bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "03bd9909" } diff --git a/zCore/src/logging.rs b/zCore/src/logging.rs index 30dd687d..3dc83e89 100644 --- a/zCore/src/logging.rs +++ b/zCore/src/logging.rs @@ -62,7 +62,7 @@ impl Log for SimpleLogger { "[{:?} {:>5} {} {}:{}] {}\n", kernel_hal_bare::timer_now(), record.level(), - kernel_hal_bare::apic_local_id(), + kernel_hal::cpu::cpu_id(), pid, tid, record.args() diff --git a/zircon-loader/Cargo.toml b/zircon-loader/Cargo.toml index a4c809ec..f0e83c6a 100644 --- a/zircon-loader/Cargo.toml +++ b/zircon-loader/Cargo.toml @@ -15,10 +15,9 @@ zircon-syscall = { path = "../zircon-syscall" } kernel-hal = { path = "../kernel-hal" } env_logger = { version = "0.8", optional = true } structopt = { version = "0.3", default-features = false, optional = true } -kernel-hal-unix = { path = "../kernel-hal-unix", optional = true } async-std = { version = "1.9", features = ["attributes"], optional = true } [features] -default = ["std"] -std = ["env_logger", "structopt", "async-std", "kernel-hal-unix", - "zircon-object/aspace-separate", "zircon-syscall/std"] +default = ["std", "libos"] +libos = ["kernel-hal/libos"] +std = ["env_logger", "structopt", "async-std", "zircon-object/aspace-separate", "zircon-syscall/std"] diff --git a/zircon-loader/src/kcounter.rs b/zircon-loader/src/kcounter.rs index 4b76f079..2c844f06 100644 --- a/zircon-loader/src/kcounter.rs +++ b/zircon-loader/src/kcounter.rs @@ -34,8 +34,8 @@ pub fn create_kcounter_vmo() -> (Arc, Arc) { fn kcounters_arena_start(); fn kcounters_arena_end(); } - use kernel_hal::PageTableTrait; - let mut pgtable = kernel_hal::PageTable::current(); + use kernel_hal::paging::{PageTable, PageTableTrait}; + let mut pgtable = PageTable::current(); let paddr = pgtable.query(kcounters_arena_start as usize).unwrap(); assert_eq!( kcounters_arena_start as usize / PAGE_SIZE, diff --git a/zircon-loader/src/lib.rs b/zircon-loader/src/lib.rs index db5e9e24..880ed85e 100644 --- a/zircon-loader/src/lib.rs +++ b/zircon-loader/src/lib.rs @@ -83,7 +83,7 @@ pub fn run_userboot(images: &Images>, cmdline: &str) -> Arc>, cmdline: &str) -> Arc handle_syscall(&thread).await, 0x20..=0x3f => { - kernel_hal::InterruptManager::handle_irq(trap_num as u32); + kernel_hal::interrupt::handle_irq(trap_num as u32); if trap_num == 0x20 { EXCEPTIONS_TIMER.add(1); - kernel_hal::yield_now().await; + kernel_hal::future::yield_now().await; } } 0xe => { diff --git a/zircon-loader/src/main.rs b/zircon-loader/src/main.rs index 48925e7c..f84277b6 100644 --- a/zircon-loader/src/main.rs +++ b/zircon-loader/src/main.rs @@ -23,7 +23,7 @@ struct Opt { #[async_std::main] async fn main() { - kernel_hal_unix::init(); + kernel_hal::init(); init_logger(); let opt = Opt::from_args(); @@ -53,7 +53,7 @@ fn init_logger() { use log::Level; use std::io::Write; - let (tid, pid) = kernel_hal::Thread::get_tid(); + let (tid, pid) = kernel_hal::thread::get_tid(); let mut style = buf.style(); match record.level() { Level::Trace => style.set_color(Color::Black).set_intense(true), @@ -62,7 +62,7 @@ fn init_logger() { Level::Warn => style.set_color(Color::Yellow), Level::Error => style.set_color(Color::Red).set_bold(true), }; - let now = kernel_hal_unix::timer_now(); + let now = kernel_hal::timer::timer_now(); let level = style.value(record.level()); let args = record.args(); writeln!(buf, "[{:?} {:>5} {}:{}] {}", now, level, pid, tid, args) @@ -76,7 +76,7 @@ mod tests { #[async_std::test] async fn userboot() { - kernel_hal_unix::init(); + kernel_hal::init(); let opt = Opt { #[cfg(target_arch = "x86_64")] diff --git a/zircon-object/Cargo.toml b/zircon-object/Cargo.toml index ff972e24..7cc4ef87 100644 --- a/zircon-object/Cargo.toml +++ b/zircon-object/Cargo.toml @@ -29,5 +29,4 @@ cfg-if = "1.0" #rvm = { git = "https://github.com/rcore-os/RVM", rev = "382fc60", optional = true } [dev-dependencies] -kernel-hal-unix = { path = "../kernel-hal-unix" } async-std = { version = "1.9", features = ["attributes", "unstable"] } diff --git a/zircon-object/src/debuglog.rs b/zircon-object/src/debuglog.rs index 144c7ed5..a38facc4 100644 --- a/zircon-object/src/debuglog.rs +++ b/zircon-object/src/debuglog.rs @@ -3,7 +3,6 @@ use { super::*, crate::object::*, alloc::{sync::Arc, vec::Vec}, - kernel_hal::timer_now, lazy_static::lazy_static, spin::Mutex, }; @@ -111,7 +110,7 @@ impl DlogBuffer { datalen: data.len() as u16, severity, flags: flags as u8, - timestamp: timer_now().as_nanos() as u64, + timestamp: kernel_hal::timer::timer_now().as_nanos() as u64, pid, tid, }; diff --git a/zircon-object/src/dev/interrupt/event_interrupt.rs b/zircon-object/src/dev/interrupt/event_interrupt.rs index 5d79d11e..f41cb2bb 100644 --- a/zircon-object/src/dev/interrupt/event_interrupt.rs +++ b/zircon-object/src/dev/interrupt/event_interrupt.rs @@ -1,4 +1,4 @@ -use kernel_hal::InterruptManager; +use kernel_hal::interrupt; use {super::*, spin::Mutex}; pub struct EventInterrupt { @@ -25,14 +25,14 @@ impl InterruptTrait for EventInterrupt { fn mask(&self) { let inner = self.inner.lock(); if inner.register { - InterruptManager::disable_irq(self.vector as u32); + interrupt::disable_irq(self.vector as u32); } } fn unmask(&self) { let inner = self.inner.lock(); if inner.register { - InterruptManager::enable_irq(self.vector as u32); + interrupt::enable_irq(self.vector as u32); } } @@ -41,7 +41,7 @@ impl InterruptTrait for EventInterrupt { if inner.register { return Err(ZxError::ALREADY_BOUND); } - if InterruptManager::register_irq_handler(self.vector, handle).is_some() { + if interrupt::register_irq_handler(self.vector, handle).is_some() { inner.register = true; Ok(()) } else { @@ -54,7 +54,7 @@ impl InterruptTrait for EventInterrupt { if !inner.register { return Ok(()); } - if InterruptManager::unregister_irq_handler(self.vector) { + if interrupt::unregister_irq_handler(self.vector) { inner.register = false; Ok(()) } else { diff --git a/zircon-object/src/dev/interrupt/mod.rs b/zircon-object/src/dev/interrupt/mod.rs index 066a03f9..c5457713 100644 --- a/zircon-object/src/dev/interrupt/mod.rs +++ b/zircon-object/src/dev/interrupt/mod.rs @@ -293,7 +293,7 @@ impl Interrupt { } if inner.timestamp == 0 { // Not sure ZX_CLOCK_MONOTONIC or ZX_CLOCK_UTC - inner.timestamp = kernel_hal::timer_now().as_nanos() as i64; + inner.timestamp = kernel_hal::timer::timer_now().as_nanos() as i64; } match &inner.port { Some(port) => { diff --git a/zircon-object/src/dev/pci/caps.rs b/zircon-object/src/dev/pci/caps.rs index 9cacdebe..cd990832 100644 --- a/zircon-object/src/dev/pci/caps.rs +++ b/zircon-object/src/dev/pci/caps.rs @@ -3,7 +3,7 @@ use crate::{ZxError, ZxResult}; use alloc::boxed::Box; use core::convert::TryFrom; -use kernel_hal::InterruptManager; +use kernel_hal::interrupt; use spin::*; /// Enumeration for PCI capabilities. @@ -46,8 +46,7 @@ impl PciMsiBlock { if irq_num == 0 || irq_num > 32 { return Err(ZxError::INVALID_ARGS); } - let (start, size) = - InterruptManager::msi_allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?; + let (start, size) = interrupt::msi_allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?; Ok(PciMsiBlock { target_addr: (0xFEE0_0000 | 0x08) & !0x4, target_data: start as u32, @@ -57,12 +56,12 @@ impl PciMsiBlock { }) } pub fn free(&self) { - InterruptManager::msi_free_block(self.base_irq, self.num_irq) + interrupt::msi_free_block(self.base_irq, self.num_irq) } pub fn register_handler(&self, msi_id: u32, handle: Box) { assert!(self.allocated); assert!(msi_id < self.num_irq); - InterruptManager::msi_register_handler(self.base_irq, self.num_irq, msi_id, handle); + interrupt::msi_register_handler(self.base_irq, self.num_irq, msi_id, handle); } } diff --git a/zircon-object/src/dev/pci/nodes.rs b/zircon-object/src/dev/pci/nodes.rs index e8da4d53..58ee57e5 100644 --- a/zircon-object/src/dev/pci/nodes.rs +++ b/zircon-object/src/dev/pci/nodes.rs @@ -13,7 +13,7 @@ use crate::{vm::PAGE_SIZE, ZxError, ZxResult}; use alloc::sync::{Arc, Weak}; use alloc::{boxed::Box, vec::Vec}; -use kernel_hal::InterruptManager; +use kernel_hal::interrupt; use numeric_enum_macro::numeric_enum; use region_alloc::RegionAllocator; use spin::{Mutex, MutexGuard}; @@ -192,13 +192,13 @@ impl SharedLegacyIrqHandler { /// Create a new SharedLegacyIrqHandler. pub fn create(irq_id: u32) -> Option> { info!("SharedLegacyIrqHandler created for {:#x?}", irq_id); - InterruptManager::disable_irq(irq_id); + interrupt::disable_irq(irq_id); let handler = Arc::new(SharedLegacyIrqHandler { irq_id, device_handler: Mutex::new(Vec::new()), }); let handler_copy = handler.clone(); - if InterruptManager::register_irq_handler(irq_id, Box::new(move || handler_copy.handle())) + if interrupt::register_irq_handler(irq_id, Box::new(move || handler_copy.handle())) .is_some() { Some(handler) @@ -211,7 +211,7 @@ impl SharedLegacyIrqHandler { pub fn handle(&self) { let device_handler = self.device_handler.lock(); if device_handler.is_empty() { - InterruptManager::disable_irq(self.irq_id); + interrupt::disable_irq(self.irq_id); return; } for dev in device_handler.iter() { @@ -260,7 +260,7 @@ impl SharedLegacyIrqHandler { let is_first = device_handler.is_empty(); device_handler.push(device); if is_first { - InterruptManager::enable_irq(self.irq_id); + interrupt::enable_irq(self.irq_id); } } pub fn remove_device(&self, device: Arc) { @@ -272,7 +272,7 @@ impl SharedLegacyIrqHandler { let mut device_handler = self.device_handler.lock(); device_handler.retain(|h| Arc::ptr_eq(h, &device)); if device_handler.is_empty() { - InterruptManager::disable_irq(self.irq_id); + interrupt::disable_irq(self.irq_id); } } } diff --git a/zircon-object/src/dev/pci/pci_init_args.rs b/zircon-object/src/dev/pci/pci_init_args.rs index f80791cf..388a1231 100644 --- a/zircon-object/src/dev/pci/pci_init_args.rs +++ b/zircon-object/src/dev/pci/pci_init_args.rs @@ -45,17 +45,17 @@ pub const PCI_INIT_ARG_MAX_SIZE: usize = core::mem::size_of::(); -use kernel_hal::InterruptManager; +use kernel_hal::interrupt; impl PciInitArgsHeader { pub fn configure_interrupt(&mut self) -> ZxResult { for i in 0..self.num_irqs as usize { let irq = &mut self.irqs[i]; let global_irq = irq.global_irq; - if !InterruptManager::is_valid_irq(global_irq) { + if !interrupt::is_valid_irq(global_irq) { irq.global_irq = PCI_NO_IRQ_MAPPING; self.dev_pin_to_global_irq.remove_irq(global_irq); - } else if !InterruptManager::configure_irq( + } else if !interrupt::configure_irq( global_irq, irq.level_triggered, /* Trigger mode */ irq.active_high, /* Polarity */ diff --git a/zircon-object/src/signal/timer.rs b/zircon-object/src/signal/timer.rs index fcdfef12..a852831e 100644 --- a/zircon-object/src/signal/timer.rs +++ b/zircon-object/src/signal/timer.rs @@ -73,7 +73,7 @@ impl Timer { inner.deadline = Some(deadline); self.base.signal_clear(Signal::SIGNALED); let me = Arc::downgrade(self); - kernel_hal::timer_set( + kernel_hal::timer::timer_set( deadline, Box::new(move |now| me.upgrade().map(|timer| timer.touch(now)).unwrap_or(())), ); @@ -100,7 +100,7 @@ impl Timer { #[cfg(test)] mod tests { use super::*; - use kernel_hal::timer_now; + use kernel_hal::timer::timer_now; #[test] fn one_shot() { diff --git a/zircon-object/src/task/exception.rs b/zircon-object/src/task/exception.rs index 6f964ef3..a19f27e8 100644 --- a/zircon-object/src/task/exception.rs +++ b/zircon-object/src/task/exception.rs @@ -1,6 +1,6 @@ use { super::*, crate::ipc::*, crate::object::*, alloc::sync::Arc, alloc::vec, alloc::vec::Vec, - core::mem::size_of, futures::channel::oneshot, kernel_hal::UserContext, spin::Mutex, + core::mem::size_of, futures::channel::oneshot, kernel_hal::context::UserContext, spin::Mutex, }; /// Kernel-owned exception channel endpoint. @@ -157,7 +157,7 @@ impl ExceptionContext { ExceptionContext { vector: cx.trap_num as u64, err_code: cx.error_code as u64, - cr2: kernel_hal::fetch_fault_vaddr() as u64, + cr2: kernel_hal::context::fetch_fault_vaddr() as u64, } } #[cfg(target_arch = "aarch64")] diff --git a/zircon-object/src/task/process.rs b/zircon-object/src/task/process.rs index 520305f9..fd7ec0eb 100644 --- a/zircon-object/src/task/process.rs +++ b/zircon-object/src/task/process.rs @@ -143,7 +143,7 @@ impl Process { /// # use std::sync::Arc; /// # use zircon_object::task::*; /// # use zircon_object::object::*; - /// # kernel_hal_unix::init(); + /// # kernel_hal::init(); /// # async_std::task::block_on(async { /// let job = Job::root(); /// let proc = Process::create(&job, "proc").unwrap(); diff --git a/zircon-object/src/task/suspend_token.rs b/zircon-object/src/task/suspend_token.rs index f3d2674f..9d3247a9 100644 --- a/zircon-object/src/task/suspend_token.rs +++ b/zircon-object/src/task/suspend_token.rs @@ -13,7 +13,7 @@ use { /// # use std::sync::Arc; /// # use zircon_object::task::*; /// # use zircon_object::object::{KernelObject, Signal}; -/// # kernel_hal_unix::init(); +/// # kernel_hal::init(); /// let job = Job::root(); /// let proc = Process::create(&job, "proc").unwrap(); /// let thread = Thread::create(&proc, "thread").unwrap(); diff --git a/zircon-object/src/task/thread.rs b/zircon-object/src/task/thread.rs index a217c7e3..1d6ecf90 100644 --- a/zircon-object/src/task/thread.rs +++ b/zircon-object/src/task/thread.rs @@ -14,7 +14,8 @@ use { time::Duration, }, futures::{channel::oneshot::*, future::FutureExt, pin_mut, select_biased}, - kernel_hal::{sleep_until, GeneralRegs, UserContext}, + kernel_hal::context::{GeneralRegs, UserContext}, + // kernel_hal::future::sleep_until, spin::Mutex, }; @@ -193,7 +194,7 @@ impl Thread { /// ``` /// # use std::sync::Arc; /// # use zircon_object::task::*; - /// # kernel_hal_unix::init(); + /// # kernel_hal::init(); /// let job = Job::root(); /// let proc = Process::create(&job, "proc").unwrap(); /// // create a thread with extension info @@ -272,7 +273,7 @@ impl Thread { inner.change_state(ThreadState::Running, &self.base); } let vmtoken = self.proc().vmar().table_phys(); - kernel_hal::Thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken); + kernel_hal::thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken); Ok(()) } @@ -289,7 +290,7 @@ impl Thread { inner.change_state(ThreadState::Running, &self.base); } let vmtoken = self.proc().vmar().table_phys(); - kernel_hal::Thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken); + kernel_hal::thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken); Ok(()) } @@ -313,7 +314,7 @@ impl Thread { inner.change_state(ThreadState::Running, &self.base); } let vmtoken = self.proc().vmar().table_phys(); - kernel_hal::Thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken); + kernel_hal::thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken); Ok(()) } @@ -602,14 +603,14 @@ impl CurrentThread { select_biased! { ret = future.fuse() => ret.into_result(), _ = killed.fuse() => Err(ZxError::STOP), - _ = sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT), + _ = kernel_hal::future::sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT), _ = cancel_token.fuse() => Err(ZxError::CANCELED), } } else { select_biased! { ret = future.fuse() => ret.into_result(), _ = killed.fuse() => Err(ZxError::STOP), - _ = sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT), + _ = kernel_hal::future::sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT), } }; let mut inner = self.inner.lock(); @@ -765,7 +766,7 @@ pub struct ThreadInfo { mod tests { use super::job::Job; use super::*; - use kernel_hal::timer_now; + use kernel_hal::timer::timer_now; #[test] fn create() { @@ -781,7 +782,7 @@ mod tests { #[async_std::test] async fn start() { - kernel_hal_unix::init(); + kernel_hal::init(); let root_job = Job::root(); let proc = Process::create(&root_job, "proc").expect("failed to create process"); let thread = Thread::create(&proc, "thread").expect("failed to create thread"); diff --git a/zircon-object/src/task/thread/thread_state.rs b/zircon-object/src/task/thread/thread_state.rs index 514c0185..f8af5a31 100644 --- a/zircon-object/src/task/thread/thread_state.rs +++ b/zircon-object/src/task/thread/thread_state.rs @@ -1,5 +1,5 @@ use crate::{ZxError, ZxResult}; -use kernel_hal::UserContext; +use kernel_hal::context::UserContext; use numeric_enum_macro::numeric_enum; numeric_enum! { diff --git a/zircon-object/src/vm/vmar.rs b/zircon-object/src/vm/vmar.rs index 433fc34c..172a0197 100644 --- a/zircon-object/src/vm/vmar.rs +++ b/zircon-object/src/vm/vmar.rs @@ -1,6 +1,6 @@ use { super::*, crate::object::*, alloc::sync::Arc, alloc::vec, alloc::vec::Vec, bitflags::bitflags, - kernel_hal::PageTableTrait, spin::Mutex, + kernel_hal::paging::PageTableTrait, spin::Mutex, }; bitflags! { @@ -78,7 +78,7 @@ impl VmAddressRegion { addr, size, parent: None, - page_table: Arc::new(Mutex::new(kernel_hal::PageTable::new())), //hal PageTable + page_table: Arc::new(Mutex::new(kernel_hal::paging::PageTable::new())), //hal PageTable inner: Mutex::new(Some(VmarInner::default())), }) } @@ -94,7 +94,7 @@ impl VmAddressRegion { addr: kernel_vmar_base, size: kernel_vmar_size, parent: None, - page_table: Arc::new(Mutex::new(kernel_hal::PageTable::new())), + page_table: Arc::new(Mutex::new(kernel_hal::paging::PageTable::new())), inner: Mutex::new(Some(VmarInner::default())), }) } diff --git a/zircon-object/src/vm/vmo/paged.rs b/zircon-object/src/vm/vmo/paged.rs index 25798b4b..4cb65c5f 100644 --- a/zircon-object/src/vm/vmo/paged.rs +++ b/zircon-object/src/vm/vmo/paged.rs @@ -8,7 +8,7 @@ use { core::ops::Range, core::sync::atomic::*, hashbrown::HashMap, - kernel_hal::{frame_flush, PhysFrame, PAGE_SIZE}, + kernel_hal::{memory::PhysFrame, PAGE_SIZE}, spin::{Mutex, MutexGuard}, }; @@ -188,7 +188,7 @@ impl VMObjectPaged { let (_guard, mut inner) = vmo.get_inner_mut(); inner.contiguous = true; for (i, f) in frames.drain(0..).enumerate() { - kernel_hal::pmem_zero(f.addr(), PAGE_SIZE); + kernel_hal::memory::pmem_zero(f.addr(), PAGE_SIZE); let mut state = PageState::new(f); state.pin_count += 1; inner.frames.insert(i, state); @@ -225,7 +225,7 @@ impl VMObjectTrait for VMObjectPaged { return Err(ZxError::BAD_STATE); } inner.for_each_page(offset, buf.len(), MMUFlags::READ, |paddr, buf_range| { - kernel_hal::pmem_read(paddr, &mut buf[buf_range]); + kernel_hal::memory::pmem_read(paddr, &mut buf[buf_range]); }) } @@ -235,7 +235,7 @@ impl VMObjectTrait for VMObjectPaged { return Err(ZxError::BAD_STATE); } inner.for_each_page(offset, buf.len(), MMUFlags::WRITE, |paddr, buf_range| { - kernel_hal::pmem_write(paddr, &buf[buf_range]); + kernel_hal::memory::pmem_write(paddr, &buf[buf_range]); }) } @@ -259,7 +259,7 @@ impl VMObjectTrait for VMObjectPaged { } else if inner.committed_pages_in_range(block.block, block.block + 1) != 0 { // check whether this page is initialized, otherwise nothing should be done let paddr = inner.commit_page(block.block, MMUFlags::WRITE)?; - kernel_hal::pmem_zero(paddr + block.begin, block.len()); + kernel_hal::memory::pmem_zero(paddr + block.begin, block.len()); } } inner.release_unwanted_pages_in_parent(unwanted); @@ -371,7 +371,7 @@ impl VMObjectTrait for VMObjectPaged { } if inner.cache_policy == CachePolicy::Cached && policy != CachePolicy::Cached { for (_, value) in inner.frames.iter() { - frame_flush(value.frame.addr()); + kernel_hal::memory::frame_flush(value.frame.addr()); } } inner.cache_policy = policy; @@ -528,7 +528,7 @@ impl VMObjectPagedInner { // lazy allocate zero frame // 这里会调用HAL层的hal_frame_alloc, 请注意实现该函数时参数要一样 let target_frame = PhysFrame::alloc().ok_or(ZxError::NO_MEMORY)?; - kernel_hal::pmem_zero(target_frame.addr(), PAGE_SIZE); + kernel_hal::memory::pmem_zero(target_frame.addr(), PAGE_SIZE); if out_of_range { // can never be a hidden vmo assert!(!self.type_.is_hidden()); @@ -607,7 +607,7 @@ impl VMObjectPagedInner { } else if flags.contains(MMUFlags::WRITE) && child_tag.is_split() { // copy-on-write let target_frame = PhysFrame::alloc().ok_or(ZxError::NO_MEMORY)?; - kernel_hal::frame_copy(frame.frame.addr(), target_frame.addr()); + kernel_hal::memory::frame_copy(frame.frame.addr(), target_frame.addr()); frame.tag = child_tag; return Ok(CommitResult::CopyOnWrite(target_frame, true)); } diff --git a/zircon-object/src/vm/vmo/physical.rs b/zircon-object/src/vm/vmo/physical.rs index 89888df8..70d5faae 100644 --- a/zircon-object/src/vm/vmo/physical.rs +++ b/zircon-object/src/vm/vmo/physical.rs @@ -39,21 +39,21 @@ impl VMObjectTrait for VMObjectPhysical { fn read(&self, offset: usize, buf: &mut [u8]) -> ZxResult { let _ = self.data_lock.lock(); assert!(offset + buf.len() <= self.len()); - kernel_hal::pmem_read(self.paddr + offset, buf); + kernel_hal::memory::pmem_read(self.paddr + offset, buf); Ok(()) } fn write(&self, offset: usize, buf: &[u8]) -> ZxResult { let _ = self.data_lock.lock(); assert!(offset + buf.len() <= self.len()); - kernel_hal::pmem_write(self.paddr + offset, buf); + kernel_hal::memory::pmem_write(self.paddr + offset, buf); Ok(()) } fn zero(&self, offset: usize, len: usize) -> ZxResult { let _ = self.data_lock.lock(); assert!(offset + len <= self.len()); - kernel_hal::pmem_zero(self.paddr + offset, len); + kernel_hal::memory::pmem_zero(self.paddr + offset, len); Ok(()) } diff --git a/zircon-syscall/src/cprng.rs b/zircon-syscall/src/cprng.rs index ffaaf98e..1e936dbd 100644 --- a/zircon-syscall/src/cprng.rs +++ b/zircon-syscall/src/cprng.rs @@ -1,16 +1,16 @@ use super::*; impl Syscall<'_> { - /// Draw random bytes from the kernel CPRNG. + /// Draw random bytes from the kernel CPRNG. /// - /// This data should be suitable for cryptographic applications. + /// This data should be suitable for cryptographic applications. /// /// Clients that require a large volume of randomness should consider using these bytes to seed a user-space random number generator for better performance. pub fn sys_cprng_draw_once(&self, mut buf: UserOutPtr, len: usize) -> ZxResult { info!("cprng_draw_once: buf=({:?}; {:?})", buf, len); let mut res = vec![0u8; len]; // Fill random bytes to the buffer - kernel_hal::fill_random(&mut res); + kernel_hal::rand::fill_random(&mut res); buf.write_array(&res)?; Ok(()) } diff --git a/zircon-syscall/src/debug.rs b/zircon-syscall/src/debug.rs index 682c3f03..941d81c0 100644 --- a/zircon-syscall/src/debug.rs +++ b/zircon-syscall/src/debug.rs @@ -2,15 +2,15 @@ use super::*; use zircon_object::dev::*; impl Syscall<'_> { - /// Write debug info to the serial port. + /// Write debug info to the serial port. 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_write(core::str::from_utf8(&data).unwrap()); + kernel_hal::serial::serial_write(core::str::from_utf8(&data).unwrap()); Ok(()) } - /// Read debug info from the serial port. + /// Read debug info from the serial port. pub async fn sys_debug_read( &self, handle: HandleValue, @@ -31,7 +31,7 @@ impl Syscall<'_> { // let len = kernel_hal::serial_read(&mut vec); // buf.write_array(&vec[..len])?; // actual.write(len as u32)?; - let c = kernel_hal::serial_getchar().await; + let c = kernel_hal::future::serial_getchar().await; buf.write_array(&[c])?; actual.write(1)?; Ok(()) diff --git a/zircon-syscall/src/debuglog.rs b/zircon-syscall/src/debuglog.rs index 7675ac69..2baa1833 100644 --- a/zircon-syscall/src/debuglog.rs +++ b/zircon-syscall/src/debuglog.rs @@ -4,7 +4,7 @@ use { }; impl Syscall<'_> { - /// Create a kernel managed debuglog reader or writer. + /// Create a kernel managed debuglog reader or writer. pub fn sys_debuglog_create( &self, rsrc: HandleValue, @@ -32,7 +32,7 @@ impl Syscall<'_> { Ok(()) } - /// Write log entry to debuglog. + /// Write log entry to debuglog. pub fn sys_debuglog_write( &self, handle_value: HandleValue, @@ -54,15 +54,15 @@ 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_write(&data); + kernel_hal::serial::serial_write(&data); if data.as_bytes().last() != Some(&b'\n') { - kernel_hal::serial_write("\n"); + kernel_hal::serial::serial_write("\n"); } Ok(()) } #[allow(unsafe_code)] - /// Read log entries from debuglog. + /// Read log entries from debuglog. pub fn sys_debuglog_read( &self, handle_value: HandleValue, diff --git a/zircon-syscall/src/time.rs b/zircon-syscall/src/time.rs index f0bcbaff..5ae43ef0 100644 --- a/zircon-syscall/src/time.rs +++ b/zircon-syscall/src/time.rs @@ -5,7 +5,7 @@ use { sync::atomic::{AtomicU64, Ordering}, time::Duration, }, - kernel_hal::{sleep_until, timer_now, yield_now}, + kernel_hal::timer::timer_now, zircon_object::{dev::*, task::*}, }; @@ -16,7 +16,7 @@ const ZX_CLOCK_UTC: u32 = 1; const ZX_CLOCK_THREAD: u32 = 2; impl Syscall<'_> { - /// Create a new clock object. + /// Create a new clock object. pub fn sys_clock_create( &self, _options: u64, @@ -27,10 +27,10 @@ impl Syscall<'_> { Ok(()) } - /// Acquire the current time. - /// - /// + Returns the current time of clock_id via `time`. - /// + Returns whether `clock_id` was valid. + /// Acquire the current time. + /// + /// + Returns the current time of clock_id via `time`. + /// + Returns whether `clock_id` was valid. pub fn sys_clock_get(&self, clock_id: u32, mut time: UserOutPtr) -> ZxResult { info!("clock.get: id={}", clock_id); match clock_id { @@ -50,7 +50,7 @@ impl Syscall<'_> { } } - /// Perform a basic read of the clock. + /// Perform a basic read of the clock. pub fn sys_clock_read(&self, handle: HandleValue, mut now: UserOutPtr) -> ZxResult { info!("clock.read: handle={:#x?}", handle); warn!("ignore clock handle"); @@ -89,16 +89,16 @@ impl Syscall<'_> { } /// Sleep for some number of nanoseconds. - /// + /// /// A `deadline` value less than or equal to 0 immediately yields the thread. pub async fn sys_nanosleep(&self, deadline: Deadline) -> ZxResult { info!("nanosleep: deadline={:?}", deadline); if deadline.0 <= 0 { - yield_now().await; + kernel_hal::future::yield_now().await; } else { self.thread .blocking_run( - sleep_until(deadline.into()), + kernel_hal::future::sleep_until(deadline.into()), ThreadState::BlockedSleeping, Deadline::forever().into(), None,