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"] #[export_name = "hal_serial_write"]
pub fn serial_write(s: &str) { pub fn print_str(s: &str) {
//putfmt(format_args!("{}", s)); //putfmt(format_args!("{}", s));
putfmt_uart(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); *FRAME_BUFFER.write() = Some(fb_info);
} }
#[export_name = "hal_mice_set_callback"] #[export_name = "hal_mouse_set_callback"]
pub fn mice_set_callback(_callback: Box<dyn Fn([u8; 3]) + Send + Sync>) { 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()); Mutex::new(Vec::new());
} }
#[export_name = "hal_mice_set_callback"] #[export_name = "hal_mouse_set_callback"]
pub fn mice_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) { pub fn mouse_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
MOUSE_CALLBACK.lock().push(callback); MOUSE_CALLBACK.lock().push(callback);
} }

View File

@ -324,7 +324,7 @@ pub fn serial_read(buf: &mut [u8]) -> usize {
} }
#[export_name = "hal_serial_write"] #[export_name = "hal_serial_write"]
pub fn serial_write(s: &str) { pub fn print_str(s: &str) {
putfmt(format_args!("{}", s)); 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; pub struct HalError;
/// The result type returned by HAL functions. /// 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! { bitflags! {
pub struct MMUFlags: usize { pub struct MMUFlags: usize {
@ -32,7 +32,6 @@ numeric_enum! {
} }
pub const CACHE_POLICY_MASK: u32 = 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; 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 defs;
pub(super) mod fb; pub(super) mod fb;
pub mod addr;
pub mod context; pub mod context;
pub mod future; pub mod future;
pub mod memory; pub mod memory;
pub mod paging; pub mod paging;
pub mod user; pub mod user;
pub mod vdso; 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 { pub trait PageTableTrait: Sync + Send {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`. /// 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 core::fmt::{Debug, Error, Formatter};
use git_version::git_version;
/// This struct contains constants that are initialized by the kernel /// This struct contains constants that are initialized by the kernel
/// once at boot time. From the vDSO code's perspective, they are /// once at boot time. From the vDSO code's perspective, they are
@ -69,3 +70,28 @@ impl Debug for VersionString {
Ok(()) 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; 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! { cfg_if::cfg_if! {
if #[cfg(feature = "libos")] { if #[cfg(feature = "libos")] {
#[macro_use]
extern crate log;
mod libos; mod libos;
pub use self::libos::*; pub use self::libos::*;
} else { } else {
mod unimp; mod libos;
pub use self::unimp::*; 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 use trapframe::syscall_fn_entry as syscall_entry;
pub fn context_run(context: &mut UserContext) { hal_fn_impl! {
context.run_fncall(); 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,59 +74,63 @@ struct FbBitfield {
msb_right: u32, msb_right: u32,
} }
pub fn init() { hal_fn_impl! {
const FBIOGET_VSCREENINFO: u64 = 0x4600; impl mod crate::defs::dev::fb {
const FBIOGET_FSCREENINFO: u64 = 0x4602; fn init() {
const FBIOGET_VSCREENINFO: u64 = 0x4600;
const FBIOGET_FSCREENINFO: u64 = 0x4602;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
let fbfd = unsafe { libc::open("/dev/fb0".as_ptr(), libc::O_RDWR) }; let fbfd = unsafe { libc::open("/dev/fb0".as_ptr(), libc::O_RDWR) };
#[cfg(not(target_arch = "aarch64"))] #[cfg(not(target_arch = "aarch64"))]
let fbfd = unsafe { libc::open("/dev/fb0".as_ptr() as *const i8, libc::O_RDWR) }; let fbfd = unsafe { libc::open("/dev/fb0".as_ptr() as *const i8, libc::O_RDWR) };
if fbfd < 0 { if fbfd < 0 {
return; 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::<libc::c_void>(),
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);
}
} }
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::<libc::c_void>(),
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);
} }

View File

@ -82,15 +82,19 @@ fn init_mice() {
}); });
} }
pub fn mice_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) { hal_fn_impl! {
MOUSE_CALLBACK.lock().unwrap().push(callback); 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 kbd_set_callback(callback: Box<dyn Fn(u16, i32) + Send + Sync>) { fn mouse_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
KBD_CALLBACK.lock().unwrap().push(callback); MOUSE_CALLBACK.lock().unwrap().push(callback);
} }
pub fn init() { fn init() {
init_kbd(); init_kbd();
init_mice(); init_mice();
}
}
} }

View File

@ -1,69 +1,71 @@
use super::mem_common::{ensure_mmap_pmem, phys_to_virt, AVAILABLE_FRAMES, PMEM_SIZE}; use super::mem_common::{ensure_mmap_pmem, phys_to_virt, AVAILABLE_FRAMES, PMEM_SIZE};
use crate::{PhysAddr, PAGE_SIZE}; use crate::{PhysAddr, PAGE_SIZE};
pub use crate::common::memory::*; 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());
}
}
/// Read physical memory from `paddr` to `buf`. /// Write physical memory to `paddr` from `buf`.
pub fn pmem_read(paddr: PhysAddr, buf: &mut [u8]) { fn pmem_write(paddr: PhysAddr, buf: &[u8]) {
trace!("pmem read: paddr={:#x}, len={:#x}", paddr, buf.len()); trace!("pmem write: paddr={:#x}, len={:#x}", paddr, buf.len());
assert!(paddr + buf.len() <= PMEM_SIZE); assert!(paddr + buf.len() <= PMEM_SIZE);
ensure_mmap_pmem(); ensure_mmap_pmem();
unsafe { unsafe {
(phys_to_virt(paddr) as *const u8).copy_to_nonoverlapping(buf.as_mut_ptr(), buf.len()); buf.as_ptr()
.copy_to_nonoverlapping(phys_to_virt(paddr) as _, buf.len());
}
}
/// 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
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);
}
}
fn frame_flush(_target: PhysAddr) {
// do nothing
}
fn frame_alloc() -> Option<PhysAddr> {
let ret = AVAILABLE_FRAMES.lock().unwrap().pop_front();
trace!("frame alloc: {:?}", ret);
ret
}
fn frame_alloc_contiguous(_size: usize, _align_log2: usize) -> Option<PhysAddr> {
unimplemented!()
}
fn frame_dealloc(paddr: PhysAddr) {
trace!("frame dealloc: {:?}", paddr);
AVAILABLE_FRAMES.lock().unwrap().push_back(paddr);
}
fn zero_frame_addr() -> PhysAddr {
0
}
} }
} }
/// 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<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> {
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
}

View File

@ -1,7 +1,6 @@
mod mem_common; mod mem_common;
pub mod context; pub mod context;
pub mod cpu;
pub mod memory; pub mod memory;
pub mod paging; pub mod paging;
pub mod serial; pub mod serial;
@ -9,17 +8,16 @@ pub mod thread;
pub mod timer; pub mod timer;
pub mod vdso; pub mod vdso;
#[path = "../unimp/interrupt.rs"] pub use super::defs::{cpu, interrupt, rand};
pub mod interrupt;
#[path = "../unimp/rand.rs"] hal_fn_impl_default!(rand, interrupt, cpu);
pub mod rand;
cfg_if::cfg_if! { cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] { if #[cfg(target_os = "linux")] {
pub mod dev; pub mod dev;
} else { } else {
#[path = "../unimp/dev/mod.rs"] pub use super::defs::dev;
pub mod 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 std::os::unix::io::AsRawFd;
use super::mem_common::{mmap, FRAME_FILE}; 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::*; pub use crate::common::paging::*;
@ -22,8 +22,8 @@ impl PageTable {
impl PageTableTrait for PageTable { impl PageTableTrait for PageTable {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`. /// Map the page of `vaddr` to the frame of `paddr` with `flags`.
fn map(&mut self, vaddr: VirtAddr, paddr: PhysAddr, flags: MMUFlags) -> HalResult<()> { fn map(&mut self, vaddr: VirtAddr, paddr: PhysAddr, flags: MMUFlags) -> HalResult<()> {
debug_assert!(page_aligned(vaddr)); debug_assert!(is_aligned(vaddr));
debug_assert!(page_aligned(paddr)); debug_assert!(is_aligned(paddr));
let prot = flags.to_mmap_prot(); let prot = flags.to_mmap_prot();
mmap(FRAME_FILE.as_raw_fd(), paddr, PAGE_SIZE, vaddr, prot); mmap(FRAME_FILE.as_raw_fd(), paddr, PAGE_SIZE, vaddr, prot);
Ok(()) Ok(())
@ -36,7 +36,7 @@ impl PageTableTrait for PageTable {
/// Change the `flags` of the page of `vaddr`. /// Change the `flags` of the page of `vaddr`.
fn protect(&mut self, vaddr: VirtAddr, flags: MMUFlags) -> HalResult<()> { 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 prot = flags.to_mmap_prot();
let ret = unsafe { libc::mprotect(vaddr as _, PAGE_SIZE, prot) }; let ret = unsafe { libc::mprotect(vaddr as _, PAGE_SIZE, prot) };
assert_eq!(ret, 0, "failed to mprotect: {:?}", Error::last_os_error()); 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. /// Query the physical address which the page of `vaddr` maps to.
fn query(&mut self, vaddr: VirtAddr) -> HalResult<PhysAddr> { fn query(&mut self, vaddr: VirtAddr) -> HalResult<PhysAddr> {
debug_assert!(page_aligned(vaddr)); debug_assert!(is_aligned(vaddr));
unimplemented!() unimplemented!()
} }
@ -58,17 +58,13 @@ impl PageTableTrait for PageTable {
if pages == 0 { if pages == 0 {
return Ok(()); return Ok(());
} }
debug_assert!(page_aligned(vaddr)); debug_assert!(is_aligned(vaddr));
let ret = unsafe { libc::munmap(vaddr as _, PAGE_SIZE * pages) }; let ret = unsafe { libc::munmap(vaddr as _, PAGE_SIZE * pages) };
assert_eq!(ret, 0, "failed to munmap: {:?}", Error::last_os_error()); assert_eq!(ret, 0, "failed to munmap: {:?}", Error::last_os_error());
Ok(()) Ok(())
} }
} }
fn page_aligned(x: VirtAddr) -> bool {
x % PAGE_SIZE == 0
}
trait FlagsExt { trait FlagsExt {
fn to_mmap_prot(&self) -> libc::c_int; fn to_mmap_prot(&self) -> libc::c_int;
} }

View File

@ -8,26 +8,28 @@ lazy_static! {
Mutex::new(Vec::new()); Mutex::new(Vec::new());
} }
/// Put a char by serial interrupt handler. hal_fn_impl! {
pub fn serial_put(x: u8) { impl mod crate::defs::serial {
STDIN.lock().unwrap().push_back(x); fn serial_put(x: u8) {
STDIN_CALLBACK.lock().unwrap().retain(|f| !f()); 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); 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 mut stdin = STDIN.lock().unwrap();
let len = stdin.len().min(buf.len()); let len = stdin.len().min(buf.len());
for c in &mut buf[..len] { for c in &mut buf[..len] {
*c = stdin.pop_front().unwrap(); *c = stdin.pop_front().unwrap();
}
len
}
fn print_fmt(fmt: core::fmt::Arguments) {
eprint!("{}", fmt);
}
} }
len
}
/// Output a char to console.
pub fn serial_write(s: &str) {
eprint!("{}", s);
} }

View File

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

View File

@ -1,21 +1,25 @@
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
/// Get current time. hal_fn_impl! {
pub fn timer_now() -> Duration { impl mod crate::defs::timer {
SystemTime::now() /// Get current time.
.duration_since(SystemTime::UNIX_EPOCH) fn timer_now() -> Duration {
.unwrap() 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>) {
std::thread::spawn(move || {
let now = timer_now();
if deadline > now {
std::thread::sleep(deadline - now);
} }
callback(timer_now());
}); /// 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 {
std::thread::sleep(deadline - now);
}
callback(timer_now());
});
}
}
} }

View File

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

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

View File

@ -16,7 +16,7 @@ impl InputMiceInode {
pub fn new() -> Self { pub fn new() -> Self {
let data = Arc::new(Mutex::new(VecDeque::with_capacity(MAX_QUEUE))); let data = Arc::new(Mutex::new(VecDeque::with_capacity(MAX_QUEUE)));
let data_clone = data.clone(); 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(); let mut queue = data_clone.lock();
while queue.len() >= MAX_QUEUE { while queue.len() >= MAX_QUEUE {
queue.pop_front(); queue.pop_front();

View File

@ -132,7 +132,7 @@ impl INode for Stdout {
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> { fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
// we do not care the utf-8 things, we just want to print it! // we do not care the utf-8 things, we just want to print it!
let s = unsafe { core::str::from_utf8_unchecked(buf) }; let s = unsafe { core::str::from_utf8_unchecked(buf) };
kernel_hal::serial::serial_write(s); kernel_hal::serial::print_str(s);
Ok(buf.len()) Ok(buf.len())
} }
fn poll(&self) -> Result<PollStatus> { 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); let len = kernel_hal_bare::serial_read(&mut buffer);
for c in &buffer[..len] { for c in &buffer[..len] {
STDIN.push((*c).into()); 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 false
} }

View File

@ -241,7 +241,7 @@ async fn new_thread(thread: CurrentThread) {
if error_code & 0x10 != 0 { if error_code & 0x10 != 0 {
flags.insert(MMUFlags::EXECUTE) flags.insert(MMUFlags::EXECUTE)
} }
let fault_vaddr = kernel_hal::fetch_fault_vaddr(); let fault_vaddr = kernel_hal::context::fetch_fault_vaddr();
info!( info!(
"page fault from user mode {:#x} {:#x?} {:?}", "page fault from user mode {:#x} {:#x?} {:?}",
fault_vaddr, error_code, flags 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 { pub fn sys_debug_write(&self, buf: UserInPtr<u8>, len: usize) -> ZxResult {
info!("debug.write: buf=({:?}; {:#x})", buf, len); info!("debug.write: buf=({:?}; {:#x})", buf, len);
let data = buf.read_array(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(()) Ok(())
} }

View File

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