kernel_hal: add macros to generate default functions automatically

This commit is contained in:
Yuekai Jia 2021-09-04 16:16:47 +08:00
parent 937c86f01d
commit 3b0e3296e8
44 changed files with 643 additions and 597 deletions

View File

@ -413,7 +413,7 @@ pub fn serial_read(buf: &mut [u8]) -> usize {
}
#[export_name = "hal_serial_write"]
pub fn serial_write(s: &str) {
pub fn print_str(s: &str) {
//putfmt(format_args!("{}", s));
putfmt_uart(format_args!("{}", s));
}
@ -631,8 +631,8 @@ pub fn init_framebuffer(width: u32, height: u32, addr: usize, size: usize) {
*FRAME_BUFFER.write() = Some(fb_info);
}
#[export_name = "hal_mice_set_callback"]
pub fn mice_set_callback(_callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
#[export_name = "hal_mouse_set_callback"]
pub fn mouse_set_callback(_callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
//
}

View File

@ -22,8 +22,8 @@ lazy_static! {
Mutex::new(Vec::new());
}
#[export_name = "hal_mice_set_callback"]
pub fn mice_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
#[export_name = "hal_mouse_set_callback"]
pub fn mouse_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
MOUSE_CALLBACK.lock().push(callback);
}

View File

@ -324,7 +324,7 @@ pub fn serial_read(buf: &mut [u8]) -> usize {
}
#[export_name = "hal_serial_write"]
pub fn serial_write(s: &str) {
pub fn print_str(s: &str) {
putfmt(format_args!("{}", s));
}

View File

@ -0,0 +1,27 @@
//! Definition of phyical, virtual addresses and helper functions.
use crate::PAGE_SIZE;
pub type PhysAddr = usize;
pub type VirtAddr = usize;
pub type DevVAddr = usize;
pub const fn align_down(addr: usize) -> usize {
addr & !(PAGE_SIZE - 1)
}
pub const fn align_up(addr: usize) -> usize {
(addr + PAGE_SIZE - 1) & !(PAGE_SIZE - 1)
}
pub const fn is_aligned(addr: usize) -> bool {
page_offset(addr) == 0
}
pub const fn page_count(size: usize) -> usize {
align_up(size) / PAGE_SIZE
}
pub const fn page_offset(addr: usize) -> usize {
addr & (PAGE_SIZE - 1)
}

View File

@ -6,7 +6,7 @@ use numeric_enum_macro::numeric_enum;
pub struct HalError;
/// The result type returned by HAL functions.
pub type HalResult<T> = core::result::Result<T, HalError>;
pub type HalResult<T = ()> = core::result::Result<T, HalError>;
bitflags! {
pub struct MMUFlags: usize {
@ -32,7 +32,6 @@ numeric_enum! {
}
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;
pub use super::addr::{DevVAddr, PhysAddr, VirtAddr};

View File

@ -1,11 +1,10 @@
pub(super) mod defs;
pub(super) mod fb;
pub mod addr;
pub mod context;
pub mod future;
pub mod memory;
pub mod paging;
pub mod user;
pub mod vdso;
pub use defs::*;

View File

@ -1,4 +1,4 @@
use super::{HalResult, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE};
use crate::{HalResult, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE};
pub trait PageTableTrait: Sync + Send {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.

View File

@ -1,4 +1,5 @@
use core::fmt::{Debug, Error, Formatter};
use git_version::git_version;
/// This struct contains constants that are initialized by the kernel
/// once at boot time. From the vDSO code's perspective, they are
@ -69,3 +70,28 @@ impl Debug for VersionString {
Ok(())
}
}
pub(crate) fn vdso_constants_template() -> VdsoConstants {
let frequency = crate::cpu::cpu_frequency();
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: frequency as u64 * 1_000_000,
ticks_to_mono_numerator: 1000,
ticks_to_mono_denominator: frequency as u32,
physmem: 0,
version_string_len: 0,
version_string: Default::default(),
};
constants.set_version_string(git_version!(
prefix = "git-",
args = ["--always", "--abbrev=40", "--dirty=-dirty"]
));
constants
}

178
kernel-hal/src/defs.rs Normal file
View File

@ -0,0 +1,178 @@
use alloc::boxed::Box;
use core::{fmt::Arguments, future::Future, pin::Pin, time::Duration};
use crate::{common, PhysAddr, VirtAddr};
hal_fn_def! {
pub mod cpu {
/// Current CPU ID.
fn cpu_id() -> u8 { 0 }
/// Current CPU frequency.
fn cpu_frequency() -> u16 { 3000 }
}
pub mod memory: common::memory {
/// Read physical memory from `paddr` to `buf`.
fn pmem_read(paddr: PhysAddr, buf: &mut [u8]);
/// Write physical memory to `paddr` from `buf`.
fn pmem_write(paddr: PhysAddr, buf: &[u8]);
/// Zero physical memory at `[paddr, paddr + len)`.
fn pmem_zero(paddr: PhysAddr, len: usize);
/// Copy content of `src` frame to `target` frame.
fn frame_copy(src: PhysAddr, target: PhysAddr);
/// Flush the physical frame.
fn frame_flush(target: PhysAddr);
/// Allocate one physical frame.
fn frame_alloc() -> Option<PhysAddr>;
/// Allocate contiguous physical frames of totally `size` bytes.
fn frame_alloc_contiguous(size: usize, align_log2: usize) -> Option<PhysAddr>;
/// Deallocate a physical frame.
fn frame_dealloc(paddr: PhysAddr);
/// Get the physical frame contains all zeros.
fn zero_frame_addr() -> PhysAddr;
}
pub mod interrupt {
/// Enable IRQ.
fn enable_irq(vector: u32);
/// Disable IRQ.
fn disable_irq(vector: u32);
/// Is a valid IRQ number.
fn is_valid_irq(vector: u32) -> bool;
/// Configure the specified interrupt vector. If it is invoked, it muust be
/// invoked prior to interrupt registration.
fn configure_irq(vector: u32, trig_mode: bool, polarity: bool) -> bool;
/// Add an interrupt handle to an IRQ
fn register_irq_handler(vector: u32, handler: Box<dyn Fn() + Send + Sync>) -> Option<u32>;
/// Remove the interrupt handle to an IRQ
fn unregister_irq_handler(vector: u32) -> bool;
/// Handle IRQ.
fn handle_irq(vector: u32);
/// Method used for platform allocation of blocks of MSI and MSI-X compatible
/// IRQ targets.
fn msi_allocate_block(irq_num: u32) -> Option<(usize, usize)>;
/// Method used to free a block of MSI IRQs previously allocated by msi_alloc_block().
/// This does not unregister IRQ handlers.
fn msi_free_block(irq_start: u32, irq_num: u32);
/// 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.
fn msi_register_handler(irq_start: u32, irq_num: u32, msi_id: u32, handler: Box<dyn Fn() + Send + Sync>);
}
pub mod context: common::context {
/// Enter user mode.
fn context_run(context: &mut UserContext);
/// Get fault address of the last page fault.
fn fetch_fault_vaddr() -> VirtAddr;
/// Get the trap number when trap.
fn fetch_trap_num(context: &UserContext) -> usize;
}
pub mod thread {
/// Spawn a new thread.
fn spawn(future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, vmtoken: usize);
/// Set tid and pid of current task.
fn set_tid(tid: u64, pid: u64);
/// Get tid and pid of current task.]
fn get_tid() -> (u64, u64);
}
pub mod timer {
/// Get current time.
fn timer_now() -> Duration;
/// Set a new timer. After `deadline`, the `callback` will be called.
fn timer_set(deadline: Duration, callback: Box<dyn FnOnce(Duration) + Send + Sync>);
/// Check timers, call when timer interrupt happened.
fn timer_tick();
}
pub mod serial {
/// Register a callback of serial readable event.
fn serial_set_callback(callback: Box<dyn Fn() -> bool + Send + Sync>);
/// Put a char to serial buffer.
fn serial_put(x: u8);
/// Read a string from serial buffer.
fn serial_read(buf: &mut [u8]) -> usize;
/// Print format string and its arguments to console.
fn print_fmt(fmt: Arguments);
/// Print a string to console.
fn print_str(s: &str) {
print_fmt(format_args!("{}", s));
}
}
pub mod rand {
/// Fill random bytes to the buffer
#[allow(unused_variables)]
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!()
}
}
}
}
pub mod vdso: common::vdso {
/// Get platform specific information.
fn vdso_constants() -> VdsoConstants;
}
}
pub mod dev {
hal_fn_def! {
pub mod fb: crate::common::fb {
/// Initialize framebuffer.
fn init();
}
pub mod input {
/// Initialize input devices.
fn init();
/// Setup the callback when a keyboard event occurs.
fn kbd_set_callback(callback: Box<dyn Fn(u16, i32) + Send + Sync>);
/// Setup the callback when a mouse event occurs.
fn mouse_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>);
}
}
}

View File

@ -6,18 +6,23 @@
extern crate alloc;
mod common;
#[macro_use]
extern crate log;
pub use common::{defs::*, future, user};
#[macro_use]
mod macros;
mod common;
mod defs;
pub use common::{addr, defs::*, future, user};
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 libos;
pub use self::libos::*;
}
}

View File

@ -1,17 +1,9 @@
pub use crate::common::context::*;
pub use trapframe::syscall_fn_entry as syscall_entry;
pub fn context_run(context: &mut UserContext) {
hal_fn_impl! {
impl mod crate::defs::context {
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!()
}
}
}

View File

@ -1,3 +0,0 @@
pub fn u8() -> u8 {
0
}

View File

@ -74,7 +74,9 @@ struct FbBitfield {
msb_right: u32,
}
pub fn init() {
hal_fn_impl! {
impl mod crate::defs::dev::fb {
fn init() {
const FBIOGET_VSCREENINFO: u64 = 0x4600;
const FBIOGET_FSCREENINFO: u64 = 0x4602;
@ -129,4 +131,6 @@ pub fn init() {
screen_size: size,
};
*FRAME_BUFFER.write() = Some(fb_info);
}
}
}

View File

@ -82,15 +82,19 @@ fn init_mice() {
});
}
pub fn mice_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
MOUSE_CALLBACK.lock().unwrap().push(callback);
}
pub fn kbd_set_callback(callback: Box<dyn Fn(u16, i32) + Send + Sync>) {
hal_fn_impl! {
impl mod crate::defs::dev::input {
fn kbd_set_callback(callback: Box<dyn Fn(u16, i32) + Send + Sync>) {
KBD_CALLBACK.lock().unwrap().push(callback);
}
}
pub fn init() {
fn mouse_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
MOUSE_CALLBACK.lock().unwrap().push(callback);
}
fn init() {
init_kbd();
init_mice();
}
}
}

View File

@ -1,20 +1,20 @@
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]) {
hal_fn_impl! {
impl mod crate::defs::memory {
/// Read physical memory from `paddr` to `buf`.
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]) {
/// Write physical memory to `paddr` from `buf`.
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();
@ -22,20 +22,20 @@ pub fn pmem_write(paddr: PhysAddr, buf: &[u8]) {
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) {
/// Zero physical memory at `[paddr, paddr + len)`
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) {
/// Copy content of `src` frame to `target` frame
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();
@ -43,27 +43,29 @@ pub fn frame_copy(src: PhysAddr, target: PhysAddr) {
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) {
fn frame_flush(_target: PhysAddr) {
// do nothing
}
}
pub fn frame_alloc() -> Option<PhysAddr> {
fn frame_alloc() -> Option<PhysAddr> {
let ret = AVAILABLE_FRAMES.lock().unwrap().pop_front();
trace!("frame alloc: {:?}", ret);
ret
}
}
pub fn frame_alloc_contiguous(_size: usize, _align_log2: usize) -> Option<PhysAddr> {
fn frame_alloc_contiguous(_size: usize, _align_log2: usize) -> Option<PhysAddr> {
unimplemented!()
}
}
pub fn frame_dealloc(paddr: PhysAddr) {
fn frame_dealloc(paddr: PhysAddr) {
trace!("frame dealloc: {:?}", paddr);
AVAILABLE_FRAMES.lock().unwrap().push_back(paddr);
}
}
pub fn zero_frame_addr() -> PhysAddr {
fn zero_frame_addr() -> PhysAddr {
0
}
}
}

View File

@ -1,7 +1,6 @@
mod mem_common;
pub mod context;
pub mod cpu;
pub mod memory;
pub mod paging;
pub mod serial;
@ -9,17 +8,16 @@ pub mod thread;
pub mod timer;
pub mod vdso;
#[path = "../unimp/interrupt.rs"]
pub mod interrupt;
#[path = "../unimp/rand.rs"]
pub mod rand;
pub use super::defs::{cpu, interrupt, rand};
hal_fn_impl_default!(rand, interrupt, cpu);
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
pub mod dev;
} else {
#[path = "../unimp/dev/mod.rs"]
pub mod dev;
pub use super::defs::dev;
hal_fn_impl_default!(dev::fb, dev::input);
}
}
@ -43,8 +41,3 @@ pub fn init() {
}
});
}
// FIXME
#[path = "../unimp/misc.rs"]
mod misc;
pub use misc::*;

View File

@ -2,7 +2,7 @@ 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};
use crate::{addr::is_aligned, HalResult, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE};
pub use crate::common::paging::*;
@ -22,8 +22,8 @@ impl 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));
debug_assert!(is_aligned(vaddr));
debug_assert!(is_aligned(paddr));
let prot = flags.to_mmap_prot();
mmap(FRAME_FILE.as_raw_fd(), paddr, PAGE_SIZE, vaddr, prot);
Ok(())
@ -36,7 +36,7 @@ impl PageTableTrait for PageTable {
/// Change the `flags` of the page of `vaddr`.
fn protect(&mut self, vaddr: VirtAddr, flags: MMUFlags) -> HalResult<()> {
debug_assert!(page_aligned(vaddr));
debug_assert!(is_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());
@ -45,7 +45,7 @@ impl PageTableTrait for PageTable {
/// Query the physical address which the page of `vaddr` maps to.
fn query(&mut self, vaddr: VirtAddr) -> HalResult<PhysAddr> {
debug_assert!(page_aligned(vaddr));
debug_assert!(is_aligned(vaddr));
unimplemented!()
}
@ -58,17 +58,13 @@ impl PageTableTrait for PageTable {
if pages == 0 {
return Ok(());
}
debug_assert!(page_aligned(vaddr));
debug_assert!(is_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;
}

View File

@ -8,26 +8,28 @@ lazy_static! {
Mutex::new(Vec::new());
}
/// Put a char by serial interrupt handler.
pub fn serial_put(x: u8) {
hal_fn_impl! {
impl mod crate::defs::serial {
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<dyn Fn() -> bool + Send + Sync>) {
fn serial_set_callback(callback: Box<dyn Fn() -> bool + Send + Sync>) {
STDIN_CALLBACK.lock().unwrap().push(callback);
}
}
pub fn serial_read(buf: &mut [u8]) -> usize {
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);
fn print_fmt(fmt: core::fmt::Arguments) {
eprint!("{}", fmt);
}
}
}

View File

@ -6,15 +6,19 @@ task_local! {
static PID: Cell<u64> = Cell::new(0);
}
pub fn spawn(future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, _vmtoken: usize) {
hal_fn_impl! {
impl mod crate::defs::thread {
fn spawn(future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, _vmtoken: usize) {
async_std::task::spawn(future);
}
}
pub fn set_tid(tid: u64, pid: u64) {
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) {
fn get_tid() -> (u64, u64) {
(TID.with(|x| x.get()), PID.with(|x| x.get()))
}
}
}

View File

@ -1,16 +1,18 @@
use std::time::{Duration, SystemTime};
/// Get current time.
pub fn timer_now() -> Duration {
hal_fn_impl! {
impl mod crate::defs::timer {
/// Get current time.
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<dyn FnOnce(Duration) + Send + Sync>) {
/// Set a new timer.
///
/// After `deadline`, the `callback` will be called.
fn timer_set(deadline: Duration, callback: Box<dyn FnOnce(Duration) + Send + Sync>) {
std::thread::spawn(move || {
let now = timer_now();
if deadline > now {
@ -18,4 +20,6 @@ pub fn timer_set(deadline: Duration, callback: Box<dyn FnOnce(Duration) + Send +
}
callback(timer_now());
});
}
}
}

View File

@ -1,30 +1,9 @@
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"]
));
hal_fn_impl! {
impl mod crate::defs::vdso {
fn vdso_constants() -> VdsoConstants {
let mut constants = vdso_constants_template();
constants.physmem = super::mem_common::PMEM_SIZE as u64;
constants
}
}
}

167
kernel-hal/src/macros.rs Normal file
View File

@ -0,0 +1,167 @@
macro_rules! hal_fn_def {
(
$(
$vis:vis mod $mod_name:ident $( : $base:path )? {
$($fn:tt)*
}
)+
) => {
$(
$vis mod $mod_name {
#![allow(unused_imports)]
$( pub use $base::*; )?
use super::*;
pub(crate) trait __HalTrait {
__hal_fn_default_imp! {
$($fn)*
}
}
pub(crate) struct __HalImpl;
__hal_fn_export! {
$($fn)*
}
}
)+
};
() => {};
}
macro_rules! hal_fn_impl {
(
$(
impl mod $mod_name:ident$(::$mod_name_more:ident)* {
$($fn:item)*
}
)+
) => {
$(
__hal_fn_impl_no_export! {
impl mod $mod_name$(::$mod_name_more)* {
$($fn)*
}
}
pub use $mod_name$(::$mod_name_more)*::*;
)+
};
() => {};
}
macro_rules! hal_fn_impl_default {
(
$( $mod_name:ident$(::$mod_name_more:ident)* ),*
) => {
__hal_fn_impl_no_export! {
$( impl mod $mod_name$(::$mod_name_more)* {} )*
}
}
}
macro_rules! __hal_fn_default_imp {
(
$(#[$inner:ident $($args:tt)*])*
fn $fn:ident ( $($arg:ident : $type:ty),* ) $( -> $ret:ty )?;
$($tail:tt)*
) => {
$(#[$inner $($args)*])*
#[allow(unused_variables)]
fn $fn ( $($arg : $type),* ) $( -> $ret )? {
unimplemented!();
}
__hal_fn_default_imp! {
$($tail)*
}
};
(
$(#[$inner:ident $($args:tt)*])*
fn $fn:ident ( $($arg:ident : $type:ty),* ) $( -> $ret:ty )? $body:block
$($tail:tt)*
) => {
$(#[$inner $($args)*])*
fn $fn ( $($arg : $type),* ) $( -> $ret )? $body
__hal_fn_default_imp! {
$($tail)*
}
};
() => {};
}
macro_rules! __hal_fn_export {
(
$(#[$inner:ident $($args:tt)*])*
fn $fn:ident ( $($arg:ident : $type:ty),* ) $( -> $ret:ty )?;
$($tail:tt)*
) => {
$(#[$inner $($args)*])*
#[allow(dead_code)]
pub fn $fn ( $($arg : $type),* ) $( -> $ret )? {
__HalImpl::$fn( $($arg),* )
}
__hal_fn_export! {
$($tail)*
}
};
(
$(#[$inner:ident $($args:tt)*])*
fn $fn:ident ( $($arg:ident : $type:ty),* ) $( -> $ret:ty )? $body:block
$($tail:tt)*
) => {
$(#[$inner $($args)*])*
#[allow(dead_code)]
pub fn $fn ( $($arg : $type),* ) $( -> $ret )? {
__HalImpl::$fn( $($arg),* )
}
__hal_fn_export! {
$($tail)*
}
};
() => {};
}
macro_rules! __hal_fn_impl_no_export {
(
$(
impl mod $mod_name:ident$(::$mod_name_more:ident)* {
$($fn:item)*
}
)+
) => {
$(
impl $mod_name$(::$mod_name_more)*::__HalTrait for $mod_name$(::$mod_name_more)*::__HalImpl {
$($fn)*
}
)+
};
() => {};
}
#[cfg(test)]
mod test {
mod base {
pub const BASE: usize = 0x2333;
}
hal_fn_def! {
mod mod0: self::base {
fn test() -> f32 { 1.0 }
}
mod mod1 {
fn foo() -> usize { 0 }
fn bar(a: usize) -> usize { a }
fn unimp();
}
}
hal_fn_impl! {
impl mod self::mod1 {
fn foo() -> usize { 233 }
}
}
hal_fn_impl_default!(mod0);
#[test]
fn test_hal_fn_marco() {
assert_eq!(mod0::BASE, 0x2333);
assert_eq!(mod0::test(), 1.0);
assert_eq!(mod1::foo(), 233);
assert_eq!(mod1::bar(0), 0);
// base::unimp(); // unimplemented!
}
}

View File

@ -1,15 +0,0 @@
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!()
}

View File

@ -1,3 +0,0 @@
pub fn cpu_id() -> u8 {
0
}

View File

@ -1,5 +0,0 @@
pub use crate::common::fb::*;
pub fn init() {
unimplemented!()
}

View File

@ -1,13 +0,0 @@
use alloc::boxed::Box;
pub fn kbd_set_callback(_callback: Box<dyn Fn(u16, i32) + Send + Sync>) {
unimplemented!()
}
pub fn mice_set_callback(_callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
unimplemented!()
}
pub fn init() {
unimplemented!()
}

View File

@ -1,2 +0,0 @@
pub mod fb;
pub mod input;

View File

@ -1,61 +0,0 @@
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<dyn Fn() + Send + Sync>) -> Option<u32> {
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<dyn Fn() + Send + Sync>,
) {
unimplemented!()
}

View File

@ -1,44 +0,0 @@
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<PhysAddr> {
unimplemented!()
}
pub fn frame_alloc_contiguous(_size: usize, _align_log2: usize) -> Option<PhysAddr> {
unimplemented!()
}
pub fn frame_dealloc(_paddr: PhysAddr) {
unimplemented!()
}
pub fn zero_frame_addr() -> PhysAddr {
unimplemented!()
}

View File

@ -1,35 +0,0 @@
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<Acpi> {
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!()
}

View File

@ -1,21 +0,0 @@
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!();
}

View File

@ -1,50 +0,0 @@
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<PhysAddr> {
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!();
}
}

View File

@ -1,18 +0,0 @@
/// 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!()
}
}
}

View File

@ -1,21 +0,0 @@
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<dyn Fn() -> 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!()
}

View File

@ -1,18 +0,0 @@
use alloc::boxed::Box;
use core::future::Future;
use core::pin::Pin;
/// Spawn a new thread.
pub fn spawn(_future: Pin<Box<dyn Future<Output = ()> + 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!()
}

View File

@ -1,21 +0,0 @@
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<dyn FnOnce(Duration) + Send + Sync>) {
unimplemented!()
}
pub fn timer_set_next() {
unimplemented!()
}
/// Check timers, call when timer interrupt happened.
pub fn timer_tick() {
unimplemented!()
}

View File

@ -1,5 +0,0 @@
pub use crate::common::vdso::*;
pub fn vdso_constants() -> VdsoConstants {
unimplemented!()
}

View File

@ -158,7 +158,7 @@ async fn new_thread(thread: CurrentThread) {
8 => handle_syscall(&thread, &mut cx).await,
// PageFault
12 | 13 | 15 => {
let vaddr = kernel_hal::fetch_fault_vaddr();
let vaddr = kernel_hal::context::fetch_fault_vaddr();
//注意这里flags没有包含WRITE权限后面handle会移除写权限
let flags = if trap_num == 15 {

View File

@ -16,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();
input::mice_set_callback(Box::new(move |data| {
input::mouse_set_callback(Box::new(move |data| {
let mut queue = data_clone.lock();
while queue.len() >= MAX_QUEUE {
queue.pop_front();

View File

@ -132,7 +132,7 @@ impl INode for Stdout {
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
// 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::serial_write(s);
kernel_hal::serial::print_str(s);
Ok(buf.len())
}
fn poll(&self) -> Result<PollStatus> {

View File

@ -186,7 +186,7 @@ fn main(ramfs_data: &'static mut [u8], cmdline: &str) -> ! {
let len = kernel_hal_bare::serial_read(&mut buffer);
for c in &buffer[..len] {
STDIN.push((*c).into());
// kernel_hal_bare::serial_write(alloc::format!("{}", *c as char).as_str());
// kernel_hal_bare::print_str(alloc::format!("{}", *c as char).as_str());
}
false
}

View File

@ -241,7 +241,7 @@ async fn new_thread(thread: CurrentThread) {
if error_code & 0x10 != 0 {
flags.insert(MMUFlags::EXECUTE)
}
let fault_vaddr = kernel_hal::fetch_fault_vaddr();
let fault_vaddr = kernel_hal::context::fetch_fault_vaddr();
info!(
"page fault from user mode {:#x} {:#x?} {:?}",
fault_vaddr, error_code, flags

View File

@ -6,7 +6,7 @@ impl Syscall<'_> {
pub fn sys_debug_write(&self, buf: UserInPtr<u8>, len: usize) -> ZxResult {
info!("debug.write: buf=({:?}; {:#x})", buf, len);
let data = buf.read_array(len)?;
kernel_hal::serial::serial_write(core::str::from_utf8(&data).unwrap());
kernel_hal::serial::print_str(core::str::from_utf8(&data).unwrap());
Ok(())
}

View File

@ -54,9 +54,9 @@ impl Syscall<'_> {
let dlog = proc.get_object_with_rights::<DebugLog>(handle_value, Rights::WRITE)?;
dlog.write(Severity::Info, options, self.thread.id(), proc.id(), &data);
// print to kernel console
kernel_hal::serial::serial_write(&data);
kernel_hal::serial::print_str(&data);
if data.as_bytes().last() != Some(&b'\n') {
kernel_hal::serial::serial_write("\n");
kernel_hal::serial::print_str("\n");
}
Ok(())
}