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:
command: build
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:
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)]
pub struct KernelConfig {
pub phys_mem_start: usize,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,5 @@
//! Virutal memory operations.
use core::fmt::{Debug, Formatter, Result};
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
/// Page table entry on x86.
#[derive(Clone, Copy)]
#[repr(transparent)]
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>;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@ pub struct HalError;
pub type HalResult<T = ()> = core::result::Result<T, HalError>;
bitflags! {
/// Generic memory flags.
pub struct MMUFlags: usize {
#[allow(clippy::identity_op)]
const CACHE_1 = 1 << 0;
@ -25,6 +26,7 @@ bitflags! {
numeric_enum! {
#[repr(u32)]
#[derive(Debug, PartialEq, Clone, Copy)]
/// Generic cache policy.
pub enum CachePolicy {
Cached = 0,
Uncached = 1,
@ -32,8 +34,8 @@ numeric_enum! {
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 use super::addr::{DevVAddr, PhysAddr, VirtAddr};

View File

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

View File

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

View File

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

View File

@ -1,3 +1,5 @@
//! Device drivers.
use alloc::{sync::Arc, vec::Vec};
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};
hal_fn_def! {
/// Bootstrap and initialization.
pub mod boot {
/// The kernel command line.
pub fn cmdline() -> String { "".into() }
@ -27,6 +28,7 @@ hal_fn_def! {
pub fn secondary_init() {}
}
/// CPU information.
pub mod cpu {
/// Current CPU ID.
pub fn cpu_id() -> u8 { 0 }
@ -35,6 +37,7 @@ hal_fn_def! {
pub fn cpu_frequency() -> u16 { 3000 }
}
/// Physical memory operations.
pub mod mem: common::mem {
/// Convert physical address to virtual address.
pub(crate) fn phys_to_virt(paddr: PhysAddr) -> VirtAddr;
@ -58,6 +61,7 @@ hal_fn_def! {
pub fn frame_flush(target: PhysAddr);
}
/// Virutal memory operations.
pub mod vm: common::vm {
/// Read current VM token. (e.g. CR3, SATP, ...)
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);
}
/// Interrupts management.
pub mod interrupt {
/// Suspend the CPU (also enable interrupts) and wait for an interrupt
/// to occurs, then disable interrupts.
@ -119,6 +124,7 @@ hal_fn_def! {
pub(crate) fn console_write_early(_s: &str) {}
}
/// Context switch.
pub mod context: common::context {
/// Enter user mode.
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);
}
/// Thread spawning.
pub mod thread: common::thread {
/// Spawn a new thread.
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.
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);
}
/// Time and clock functions.
pub mod timer {
/// Get current time.
/// TODO: use `Instant` as return type.
@ -168,6 +176,7 @@ hal_fn_def! {
pub(crate) fn timer_tick();
}
/// Random number generator.
pub mod rand {
/// Fill random bytes to the buffer
#[allow(unused_variables)]
@ -194,6 +203,7 @@ hal_fn_def! {
}
}
/// VDSO constants.
pub mod vdso: common::vdso {
/// Get platform specific information.
pub fn vdso_constants() -> VdsoConstants {

View File

@ -2,6 +2,7 @@
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 {
/// Allocate one physical frame.
fn frame_alloc(&self) -> Option<PhysAddr> {

View File

@ -1,3 +1,5 @@
//! Bootstrap and initialization.
use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER};
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)]
pub struct KernelConfig;

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,5 @@
//! VDSO constants.
hal_fn_impl! {
impl mod crate::hal_fn::vdso {
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 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;
impl PageTable {

View File

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

View File

@ -152,7 +152,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::console::console_write(s);
kernel_hal::console::console_write_str(s);
Ok(buf.len())
}
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 {
info!("debug.write: buf=({:?}; {:#x})", buf, 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(())
}

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