Add more docs to kernel-hal

This commit is contained in:
Yuekai Jia 2021-10-26 17:53:07 +08:00
parent 67a0468df0
commit 91d57d4409
37 changed files with 117 additions and 32 deletions

View File

@ -69,7 +69,7 @@ jobs:
with: with:
command: build command: build
use-cross: true use-cross: true
args: -p zircon-loader --target aarch64-unknown-linux-gnu --workspace --exclude linux-syscall --exclude linux-loader --exclude zcore args: --target aarch64-unknown-linux-gnu --workspace --exclude linux-syscall --exclude linux-loader --exclude zcore
build-user: build-user:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}

View File

@ -1,4 +1,6 @@
/// Configuration of HAL. //! Kernel configuration.
/// Kernel configuration passed by kernel when calls [`crate::primary_init_early()`].
#[derive(Debug)] #[derive(Debug)]
pub struct KernelConfig { pub struct KernelConfig {
pub phys_mem_start: usize, pub phys_mem_start: usize,

View File

@ -1,3 +1,5 @@
//! Context switch.
use riscv::register::scause::{Exception, Trap}; use riscv::register::scause::{Exception, Trap};
use riscv::register::{scause, stval}; use riscv::register::{scause, stval};

View File

@ -1,3 +1,5 @@
//! CPU information.
hal_fn_impl! { hal_fn_impl! {
impl mod crate::hal_fn::cpu { impl mod crate::hal_fn::cpu {
fn cpu_frequency() -> u16 { fn cpu_frequency() -> u16 {

View File

@ -1,3 +1,5 @@
//! Interrupts management.
use riscv::{asm, register::sstatus}; use riscv::{asm, register::sstatus};
hal_fn_impl! { hal_fn_impl! {

View File

@ -1,3 +1,5 @@
//! Virutal memory operations.
use core::fmt::{Debug, Formatter, Result}; use core::fmt::{Debug, Formatter, Result};
use core::slice; use core::slice;
@ -124,7 +126,7 @@ hal_fn_impl! {
bitflags::bitflags! { bitflags::bitflags! {
/// Possible flags for a page table entry. /// Possible flags for a page table entry.
pub struct PTF: usize { struct PTF: usize {
const VALID = 1 << 0; const VALID = 1 << 0;
const READABLE = 1 << 1; const READABLE = 1 << 1;
const WRITABLE = 1 << 2; const WRITABLE = 1 << 2;
@ -181,6 +183,7 @@ impl From<PTF> for MMUFlags {
const PHYS_ADDR_MASK: u64 = 0x003f_ffff_ffff_fc00; // 10..54 const PHYS_ADDR_MASK: u64 = 0x003f_ffff_ffff_fc00; // 10..54
/// Sv39 and Sv48 page table entry.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(transparent)] #[repr(transparent)]
pub struct Rv64PTE(u64); pub struct Rv64PTE(u64);
@ -228,5 +231,5 @@ impl Debug for Rv64PTE {
} }
} }
/// Sv39: Page-Based 39-bit Virtual-Memory System /// Sv39: Page-Based 39-bit Virtual-Memory System.
pub type PageTable = PageTableImpl<PageTableLevel3, Rv64PTE>; pub type PageTable = PageTableImpl<PageTableLevel3, Rv64PTE>;

View File

@ -1,7 +1,9 @@
//! Kernel configuration.
use uefi::proto::console::gop::ModeInfo; use uefi::proto::console::gop::ModeInfo;
use uefi::table::boot::MemoryDescriptor; use uefi::table::boot::MemoryDescriptor;
/// Configuration of HAL. /// Kernel configuration passed by kernel when calls [`crate::primary_init_early()`].
#[derive(Debug)] #[derive(Debug)]
pub struct KernelConfig { pub struct KernelConfig {
pub cmdline: &'static str, pub cmdline: &'static str,

View File

@ -1,3 +1,5 @@
//! Context switch.
use bitflags::bitflags; use bitflags::bitflags;
use x86_64::registers::control::Cr2; use x86_64::registers::control::Cr2;

View File

@ -1,3 +1,5 @@
//! CPU information.
use raw_cpuid::CpuId; use raw_cpuid::CpuId;
lazy_static! { lazy_static! {

View File

@ -1,3 +1,5 @@
//! Interrupts management.
use core::ops::Range; use core::ops::Range;
use crate::drivers::all_irq; use crate::drivers::all_irq;

View File

@ -1,3 +1,5 @@
//! Functions only available on x86 platforms.
use x86_64::instructions::port::Port; use x86_64::instructions::port::Port;
/// IO Port in instruction /// IO Port in instruction

View File

@ -1,3 +1,5 @@
//! Virutal memory operations.
use core::fmt::{Debug, Formatter, Result}; use core::fmt::{Debug, Formatter, Result};
use core::{convert::TryFrom, slice}; use core::{convert::TryFrom, slice};
@ -105,6 +107,7 @@ impl From<PTF> for MMUFlags {
const PHYS_ADDR_MASK: u64 = 0x000f_ffff_ffff_f000; // 12..52 const PHYS_ADDR_MASK: u64 = 0x000f_ffff_ffff_f000; // 12..52
/// Page table entry on x86.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(transparent)] #[repr(transparent)]
pub struct X86PTE(u64); pub struct X86PTE(u64);
@ -155,4 +158,5 @@ impl Debug for X86PTE {
} }
} }
/// The 4-level page table on x86.
pub type PageTable = PageTableImpl<PageTableLevel4, X86PTE>; pub type PageTable = PageTableImpl<PageTableLevel4, X86PTE>;

View File

@ -1,3 +1,5 @@
//! Bootstrap and initialization.
use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER}; use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER};
hal_fn_impl! { hal_fn_impl! {

View File

@ -1,3 +1,5 @@
//! Physical memory operations.
use alloc::vec::Vec; use alloc::vec::Vec;
use core::ops::Range; use core::ops::Range;

View File

@ -1,3 +1,5 @@
//! Thread spawning.
use alloc::boxed::Box; use alloc::boxed::Box;
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use core::{future::Future, pin::Pin}; use core::{future::Future, pin::Pin};

View File

@ -1,3 +1,5 @@
//! Time and clock functions.
use alloc::boxed::Box; use alloc::boxed::Box;
use core::time::Duration; use core::time::Duration;

View File

@ -2,8 +2,13 @@
use crate::PAGE_SIZE; use crate::PAGE_SIZE;
/// Physical address.
pub type PhysAddr = usize; pub type PhysAddr = usize;
/// Virtual address.
pub type VirtAddr = usize; pub type VirtAddr = usize;
/// Device address.
pub type DevVAddr = usize; pub type DevVAddr = usize;
pub const fn align_down(addr: usize) -> usize { pub const fn align_down(addr: usize) -> usize {

View File

@ -1,3 +1,5 @@
//! Console input and output.
use crate::drivers; use crate::drivers;
use core::fmt::{Arguments, Result, Write}; use core::fmt::{Arguments, Result, Write};
use spin::Mutex; use spin::Mutex;
@ -41,17 +43,26 @@ cfg_if! {
} }
} }
/// Print format string and its arguments to serial. /// Writes a string slice into the serial.
pub fn serial_write_str(s: &str) {
SERIAL_WRITER.lock().write_str(s).unwrap();
}
/// Writes formatted data into the serial.
pub fn serial_write_fmt(fmt: Arguments) { pub fn serial_write_fmt(fmt: Arguments) {
SERIAL_WRITER.lock().write_fmt(fmt).unwrap(); SERIAL_WRITER.lock().write_fmt(fmt).unwrap();
} }
/// Print format string and its arguments to serial. /// Writes a string slice into the graphic console.
pub fn serial_write(s: &str) { #[allow(unused_variables)]
SERIAL_WRITER.lock().write_str(s).unwrap(); pub fn graphic_console_write_str(s: &str) {
#[cfg(feature = "graphic")]
if let Some(cons) = GRAPHIC_CONSOLE.try_get() {
cons.lock().write_str(s).unwrap();
}
} }
/// Print format string and its arguments to graphic console. /// Writes formatted data into the graphic console.
#[allow(unused_variables)] #[allow(unused_variables)]
pub fn graphic_console_write_fmt(fmt: Arguments) { pub fn graphic_console_write_fmt(fmt: Arguments) {
#[cfg(feature = "graphic")] #[cfg(feature = "graphic")]
@ -60,32 +71,24 @@ pub fn graphic_console_write_fmt(fmt: Arguments) {
} }
} }
/// Print format string and its arguments to graphic console. /// Writes a string slice into the serial, and the graphic console if it exists.
#[allow(unused_variables)] pub fn console_write_str(s: &str) {
pub fn graphic_console_write(s: &str) { serial_write_str(s);
#[cfg(feature = "graphic")] graphic_console_write_str(s);
if let Some(cons) = GRAPHIC_CONSOLE.try_get() {
cons.lock().write_str(s).unwrap();
}
} }
/// Print format string and its arguments to serial and graphic console (if exists). /// Writes formatted data into the serial, and the graphic console if it exists.
pub fn console_write_fmt(fmt: Arguments) { pub fn console_write_fmt(fmt: Arguments) {
serial_write_fmt(fmt); serial_write_fmt(fmt);
graphic_console_write_fmt(fmt); graphic_console_write_fmt(fmt);
} }
/// Print a string to serial and graphic console (if exists).
pub fn console_write(s: &str) {
serial_write(s);
graphic_console_write(s);
}
/// Read buffer data from console (serial). /// Read buffer data from console (serial).
pub async fn console_read(buf: &mut [u8]) -> usize { pub async fn console_read(buf: &mut [u8]) -> usize {
super::future::SerialReadFuture::new(buf).await super::future::SerialReadFuture::new(buf).await
} }
/// The POSIX `winsize` structure.
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, Default)] #[derive(Clone, Copy, Default)]
pub struct ConsoleWinSize { pub struct ConsoleWinSize {

View File

@ -10,6 +10,7 @@ pub struct HalError;
pub type HalResult<T = ()> = core::result::Result<T, HalError>; pub type HalResult<T = ()> = core::result::Result<T, HalError>;
bitflags! { bitflags! {
/// Generic memory flags.
pub struct MMUFlags: usize { pub struct MMUFlags: usize {
#[allow(clippy::identity_op)] #[allow(clippy::identity_op)]
const CACHE_1 = 1 << 0; const CACHE_1 = 1 << 0;
@ -25,6 +26,7 @@ bitflags! {
numeric_enum! { numeric_enum! {
#[repr(u32)] #[repr(u32)]
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
/// Generic cache policy.
pub enum CachePolicy { pub enum CachePolicy {
Cached = 0, Cached = 0,
Uncached = 1, Uncached = 1,
@ -32,8 +34,8 @@ numeric_enum! {
WriteCombining = 3, WriteCombining = 3,
} }
} }
pub const CACHE_POLICY_MASK: u32 = 3;
/// The smallest size of a page (4K).
pub const PAGE_SIZE: usize = super::vm::PageSize::Size4K as usize; pub const PAGE_SIZE: usize = super::vm::PageSize::Size4K as usize;
pub use super::addr::{DevVAddr, PhysAddr, VirtAddr}; pub use super::addr::{DevVAddr, PhysAddr, VirtAddr};

View File

@ -2,6 +2,7 @@ use alloc::vec::Vec;
use crate::{PhysAddr, KHANDLER, PAGE_SIZE}; use crate::{PhysAddr, KHANDLER, PAGE_SIZE};
/// A 4K size physical frame.
#[derive(Debug)] #[derive(Debug)]
pub struct PhysFrame { pub struct PhysFrame {
paddr: PhysAddr, paddr: PhysAddr,

View File

@ -1,3 +1,5 @@
//! Read/write user space pointer.
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::fmt::{Debug, Formatter}; use core::fmt::{Debug, Formatter};

View File

@ -1,5 +1,6 @@
use crate::{addr::is_aligned, MMUFlags, PhysAddr, VirtAddr}; use crate::{addr::is_aligned, MMUFlags, PhysAddr, VirtAddr};
/// Errors may occur during address translation.
#[derive(Debug)] #[derive(Debug)]
pub enum PagingError { pub enum PagingError {
NoMemory, NoMemory,
@ -7,9 +8,13 @@ pub enum PagingError {
AlreadyMapped, AlreadyMapped,
} }
/// Address translation result.
pub type PagingResult<T = ()> = Result<T, PagingError>; pub type PagingResult<T = ()> = Result<T, PagingError>;
/// The [`PagingError::NotMapped`] can be ignored.
pub trait IgnoreNotMappedErr { pub trait IgnoreNotMappedErr {
/// If self is `Err(PagingError::NotMapped`, ignores the error and returns
/// `Ok(())`, otherwise remain unchanged.
fn ignore(self) -> PagingResult; fn ignore(self) -> PagingResult;
} }
@ -22,6 +27,7 @@ impl<T> IgnoreNotMappedErr for PagingResult<T> {
} }
} }
/// Possible page size (4K, 2M, 1G).
#[repr(usize)] #[repr(usize)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum PageSize { pub enum PageSize {
@ -30,6 +36,7 @@ pub enum PageSize {
Size1G = 0x4000_0000, Size1G = 0x4000_0000,
} }
/// A 4K, 2M or 1G size page.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Page { pub struct Page {
pub vaddr: VirtAddr, pub vaddr: VirtAddr,
@ -61,6 +68,7 @@ impl Page {
} }
} }
/// A generic page table abstraction.
pub trait GenericPageTable: Sync + Send { pub trait GenericPageTable: Sync + Send {
/// Get the physical address of root page table. /// Get the physical address of root page table.
fn table_phys(&self) -> PhysAddr; fn table_phys(&self) -> PhysAddr;

View File

@ -1,3 +1,5 @@
//! Device drivers.
use alloc::{sync::Arc, vec::Vec}; use alloc::{sync::Arc, vec::Vec};
use core::convert::From; use core::convert::From;

View File

@ -5,6 +5,7 @@ use crate::drivers::prelude::{IrqHandler, IrqPolarity, IrqTriggerMode};
use crate::{common, HalResult, KernelConfig, KernelHandler, MMUFlags, PhysAddr, VirtAddr}; use crate::{common, HalResult, KernelConfig, KernelHandler, MMUFlags, PhysAddr, VirtAddr};
hal_fn_def! { hal_fn_def! {
/// Bootstrap and initialization.
pub mod boot { pub mod boot {
/// The kernel command line. /// The kernel command line.
pub fn cmdline() -> String { "".into() } pub fn cmdline() -> String { "".into() }
@ -27,6 +28,7 @@ hal_fn_def! {
pub fn secondary_init() {} pub fn secondary_init() {}
} }
/// CPU information.
pub mod cpu { pub mod cpu {
/// Current CPU ID. /// Current CPU ID.
pub fn cpu_id() -> u8 { 0 } pub fn cpu_id() -> u8 { 0 }
@ -35,6 +37,7 @@ hal_fn_def! {
pub fn cpu_frequency() -> u16 { 3000 } pub fn cpu_frequency() -> u16 { 3000 }
} }
/// Physical memory operations.
pub mod mem: common::mem { pub mod mem: common::mem {
/// Convert physical address to virtual address. /// Convert physical address to virtual address.
pub(crate) fn phys_to_virt(paddr: PhysAddr) -> VirtAddr; pub(crate) fn phys_to_virt(paddr: PhysAddr) -> VirtAddr;
@ -58,6 +61,7 @@ hal_fn_def! {
pub fn frame_flush(target: PhysAddr); pub fn frame_flush(target: PhysAddr);
} }
/// Virutal memory operations.
pub mod vm: common::vm { pub mod vm: common::vm {
/// Read current VM token. (e.g. CR3, SATP, ...) /// Read current VM token. (e.g. CR3, SATP, ...)
pub fn current_vmtoken() -> PhysAddr; pub fn current_vmtoken() -> PhysAddr;
@ -72,6 +76,7 @@ hal_fn_def! {
pub(crate) fn pt_clone_kernel_space(dst_pt_root: PhysAddr, src_pt_root: PhysAddr); pub(crate) fn pt_clone_kernel_space(dst_pt_root: PhysAddr, src_pt_root: PhysAddr);
} }
/// Interrupts management.
pub mod interrupt { pub mod interrupt {
/// Suspend the CPU (also enable interrupts) and wait for an interrupt /// Suspend the CPU (also enable interrupts) and wait for an interrupt
/// to occurs, then disable interrupts. /// to occurs, then disable interrupts.
@ -119,6 +124,7 @@ hal_fn_def! {
pub(crate) fn console_write_early(_s: &str) {} pub(crate) fn console_write_early(_s: &str) {}
} }
/// Context switch.
pub mod context: common::context { pub mod context: common::context {
/// Enter user mode. /// Enter user mode.
pub fn context_run(context: &mut UserContext) { pub fn context_run(context: &mut UserContext) {
@ -139,6 +145,7 @@ hal_fn_def! {
pub fn fetch_page_fault_info(info_reg: usize) -> (VirtAddr, MMUFlags); pub fn fetch_page_fault_info(info_reg: usize) -> (VirtAddr, MMUFlags);
} }
/// Thread spawning.
pub mod thread: common::thread { pub mod thread: common::thread {
/// Spawn a new thread. /// Spawn a new thread.
pub fn spawn(future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, vmtoken: usize); pub fn spawn(future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, vmtoken: usize);
@ -146,10 +153,11 @@ hal_fn_def! {
/// Set tid and pid of current task. /// Set tid and pid of current task.
pub fn set_tid(tid: u64, pid: u64); pub fn set_tid(tid: u64, pid: u64);
/// Get tid and pid of current task.] /// Get tid and pid of current task.
pub fn get_tid() -> (u64, u64); pub fn get_tid() -> (u64, u64);
} }
/// Time and clock functions.
pub mod timer { pub mod timer {
/// Get current time. /// Get current time.
/// TODO: use `Instant` as return type. /// TODO: use `Instant` as return type.
@ -168,6 +176,7 @@ hal_fn_def! {
pub(crate) fn timer_tick(); pub(crate) fn timer_tick();
} }
/// Random number generator.
pub mod rand { pub mod rand {
/// Fill random bytes to the buffer /// Fill random bytes to the buffer
#[allow(unused_variables)] #[allow(unused_variables)]
@ -194,6 +203,7 @@ hal_fn_def! {
} }
} }
/// VDSO constants.
pub mod vdso: common::vdso { pub mod vdso: common::vdso {
/// Get platform specific information. /// Get platform specific information.
pub fn vdso_constants() -> VdsoConstants { pub fn vdso_constants() -> VdsoConstants {

View File

@ -2,6 +2,7 @@
use crate::{utils::init_once::InitOnce, MMUFlags, PhysAddr, VirtAddr}; use crate::{utils::init_once::InitOnce, MMUFlags, PhysAddr, VirtAddr};
/// Functions implemented in the kernel and used by HAL funtions.
pub trait KernelHandler: Send + Sync + 'static { pub trait KernelHandler: Send + Sync + 'static {
/// Allocate one physical frame. /// Allocate one physical frame.
fn frame_alloc(&self) -> Option<PhysAddr> { fn frame_alloc(&self) -> Option<PhysAddr> {

View File

@ -1,3 +1,5 @@
//! Bootstrap and initialization.
use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER}; use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER};
hal_fn_impl! { hal_fn_impl! {

View File

@ -1,3 +1,5 @@
/// Configuration of HAL. //! Kernel configuration.
/// Kernel configuration passed by kernel when calls [`crate::primary_init_early()`].
#[derive(Debug)] #[derive(Debug)]
pub struct KernelConfig; pub struct KernelConfig;

View File

@ -1,3 +1,5 @@
//! Physical memory operations.
use alloc::vec::Vec; use alloc::vec::Vec;
use core::ops::Range; use core::ops::Range;

View File

@ -1,3 +1,5 @@
//! Functions only available on the libos mode.
#[cfg(feature = "graphic")] #[cfg(feature = "graphic")]
pub fn run_graphic_service() { pub fn run_graphic_service() {
use crate::drivers::{all_display, all_input}; use crate::drivers::{all_display, all_input};

View File

@ -1,3 +1,5 @@
//! Thread spawning.
use async_std::task_local; use async_std::task_local;
use core::{cell::Cell, future::Future, pin::Pin}; use core::{cell::Cell, future::Future, pin::Pin};

View File

@ -1,3 +1,5 @@
//! Time and clock functions.
use async_std::task; use async_std::task;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};

View File

@ -1,3 +1,5 @@
//! VDSO constants.
hal_fn_impl! { hal_fn_impl! {
impl mod crate::hal_fn::vdso { impl mod crate::hal_fn::vdso {
fn vdso_constants() -> VdsoConstants { fn vdso_constants() -> VdsoConstants {

View File

@ -1,3 +1,5 @@
//! Virutal memory operations.
use super::mem::{MOCK_PHYS_MEM, PMEM_MAP_VADDR, PMEM_SIZE}; use super::mem::{MOCK_PHYS_MEM, PMEM_MAP_VADDR, PMEM_SIZE};
use crate::{addr::is_aligned, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE}; use crate::{addr::is_aligned, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE};
@ -9,7 +11,7 @@ hal_fn_impl! {
} }
} }
/// Page Table /// Dummy page table implemented by `mmap`, `munmap`, and `mprotect`.
pub struct PageTable; pub struct PageTable;
impl PageTable { impl PageTable {

View File

@ -1,12 +1,14 @@
macro_rules! hal_fn_def { macro_rules! hal_fn_def {
( (
$( $(
$(#[$inner:ident $($args:tt)*])*
$vis:vis mod $mod_name:ident $( : $base:path )? { $vis:vis mod $mod_name:ident $( : $base:path )? {
$($fn:tt)* $($fn:tt)*
} }
)+ )+
) => { ) => {
$( $(
$(#[$inner $($args)*])*
$vis mod $mod_name { $vis mod $mod_name {
#![allow(unused_imports)] #![allow(unused_imports)]
$( pub use $base::*; )? $( pub use $base::*; )?

View File

@ -152,7 +152,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::console::console_write(s); kernel_hal::console::console_write_str(s);
Ok(buf.len()) Ok(buf.len())
} }
fn poll(&self) -> Result<PollStatus> { fn poll(&self) -> Result<PollStatus> {

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::console::console_write(core::str::from_utf8(&data).unwrap()); kernel_hal::console::console_write_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::console::console_write(&data); kernel_hal::console::console_write_str(&data);
if data.as_bytes().last() != Some(&b'\n') { if data.as_bytes().last() != Some(&b'\n') {
kernel_hal::console::console_write("\n"); kernel_hal::console::console_write_str("\n");
} }
Ok(()) Ok(())
} }