Skip to content

Commit

Permalink
Add crate axhal_plat & axhal_plat_macros
Browse files Browse the repository at this point in the history
  • Loading branch information
equation314 committed Jan 8, 2025
1 parent ff44ac0 commit 626455d
Show file tree
Hide file tree
Showing 13 changed files with 502 additions and 5 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,13 @@ jobs:
contents: write
env:
default-branch: ${{ format('refs/heads/{0}', github.event.repository.default_branch) }}
RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs
RUSTDOCFLAGS: -Zunstable-options --enable-index-page -D rustdoc::broken_intra_doc_links -D missing-docs
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- name: Build docs
continue-on-error: ${{ github.ref != env.default-branch && github.event_name != 'pull_request' }}
run: |
cargo doc --no-deps --all-features
printf '<meta http-equiv="refresh" content="0;url=%s/index.html">' $(cargo tree | head -1 | cut -d' ' -f1) > target/doc/index.html
run: cargo doc --no-deps --all-features
- name: Deploy to Github Pages
if: ${{ github.ref == env.default-branch }}
uses: JamesIves/github-pages-deploy-action@v4
Expand Down
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ resolver = "2"

members = [
"axhal_cpu",
"axhal_plat",
"axhal_plat_macros",
]

[workspace.package]
edition = "2024"
authors = ["Yuekai Jia <equation618@gmail.com>"]
authors = [
"Yuekai Jia <equation618@gmail.com>",
"yanjuguang <coolyanjg@163.com>",
"Su Mingxian <aarkegz@gmail.com>",
"RobertYuan <634954435@qq.com>",
"hky1999 <keyang.hu@qq.com>",
]
license = "GPL-3.0-or-later OR Apache-2.0 OR MulanPSL-2.0"
homepage = "https://github.com/arceos-org/arceos"
documentation = "https://arceos-org.github.io/axhal_crates"
Expand Down
19 changes: 19 additions & 0 deletions axhal_plat/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "axhal_plat"
version = "0.1.0"
description = "This crate defines unified interfaces for various hardware platforms."
documentation = "https://docs.rs/axhal_plat"
keywords = ["arceos", "hal", "hardware-abstraction-layer"]
categories = ["embedded", "no-std", "hardware-support", "os"]
edition.workspace = true
authors.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true

[dependencies]
memory_addr = "0.3"
bitflags = "2.6"
crate_interface = "0.1"
handler_table = "0.1"
axhal_plat_macros = { path = "../axhal_plat_macros", version = "0.1.0" }
3 changes: 3 additions & 0 deletions axhal_plat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# axhal-plat

This crate defines unified interfaces for various hardware platforms.
45 changes: 45 additions & 0 deletions axhal_plat/src/console.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! Console input and output.
use core::fmt::{Arguments, Result, Write};

/// Console input and output interface.
#[def_plat_interface]
pub trait ConsoleIf {
/// Writes bytes to the console from input u8 slice.
fn write_bytes(bytes: &[u8]);

/// Reads bytes from the console into the given mutable slice.
/// Returns the number of bytes read.
fn read_bytes(bytes: &mut [u8]) -> usize;
}

struct EarlyConsole;

impl Write for EarlyConsole {
fn write_str(&mut self, s: &str) -> Result {
write_bytes(s.as_bytes());
Ok(())
}
}

/// Simple console print operation.
#[macro_export]
macro_rules! console_print {
($($arg:tt)*) => {
$crate::console::__simple_print(format_args!($($arg)*));
}
}

/// Simple console print operation, with a newline.
#[macro_export]
macro_rules! console_println {
() => { $crate::ax_print!("\n") };
($($arg:tt)*) => {
$crate::console::__simple_print(format_args!("{}\n", format_args!($($arg)*)));
}
}

#[doc(hidden)]
pub fn __simple_print(fmt: Arguments) {
EarlyConsole.write_fmt(fmt).unwrap();
}
11 changes: 11 additions & 0 deletions axhal_plat/src/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Platform initialization.
/// Platform initialization interface.
#[def_plat_interface]
pub trait InitIf {
/// Initializes the platform devices for the primary CPU.
fn platform_init();

/// Initializes the platform devices for secondary CPUs.
fn platform_init_secondary();
}
30 changes: 30 additions & 0 deletions axhal_plat/src/irq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! Interrupt request (IRQ) handling.
pub use handler_table::HandlerTable;

/// The type if an IRQ handler.
pub type IrqHandler = handler_table::Handler;

/// IRQ management interface.
#[def_plat_interface]
pub trait IrqIf {
/// Enables or disables the given IRQ.
fn set_enable(vector: usize, enabled: bool);

/// Registers an IRQ handler for the given IRQ.
///
/// Returns `true` if the handler is successfully registered.
fn register(vector: usize, handler: IrqHandler) -> bool;

/// Unregisters the IRQ handler for the given IRQ.
///
/// Returns the existing handler if it is registered, `None` otherwise.
fn unregister(vector: usize) -> Option<IrqHandler>;

/// Handles the IRQ.
///
/// This function is called by the common interrupt handler. It should look
/// up in the IRQ handler table and calls the corresponding handler. If
/// necessary, it also acknowledges the interrupt controller after handling.
fn handle(vector: usize);
}
35 changes: 35 additions & 0 deletions axhal_plat/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#![no_std]
#![doc = include_str!("../README.md")]

#[macro_use]
extern crate axhal_plat_macros;

pub mod console;
pub mod init;
pub mod irq;
pub mod mem;
pub mod power;
pub mod time;

pub use axhal_plat_macros::{main, secondary_main};
pub use crate_interface::impl_interface as impl_plat_interface;

#[doc(hidden)]
pub mod __priv {
pub use crate_interface::{call_interface, def_interface};
}

/// Call the function decorated by [`crate::main`] for the primary core.
pub fn call_main(cpu_hw_id: usize, dtb: usize) -> ! {
unsafe { __axhal_plat_main(cpu_hw_id, dtb) }
}

/// Call the function decorated by [`crate::secondary_main`] for secondary cores.
pub fn call_secondary_main(cpu_hw_id: usize) -> ! {
unsafe { __axhal_plat_secondary_main(cpu_hw_id) }
}

unsafe extern "Rust" {
fn __axhal_plat_main(cpu_hw_id: usize, dtb: usize) -> !;
fn __axhal_plat_secondary_main(cpu_hw_id: usize) -> !;
}
81 changes: 81 additions & 0 deletions axhal_plat/src/mem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//! Physical memory information.
use core::fmt;

use memory_addr::{PhysAddr, PhysAddrRange};

bitflags::bitflags! {
/// The flags of a physical memory region.
#[derive(Clone, Copy)]
pub struct MemRegionFlags: usize {
/// Readable.
const READ = 1 << 0;
/// Writable.
const WRITE = 1 << 1;
/// Executable.
const EXECUTE = 1 << 2;
/// Device memory. (e.g., MMIO regions)
const DEVICE = 1 << 4;
/// Uncachable memory. (e.g., framebuffer)
const UNCACHED = 1 << 5;
/// Reserved memory, do not use for allocation.
const RESERVED = 1 << 6;
/// Free memory for allocation.
const FREE = 1 << 7;
}
}

impl fmt::Debug for MemRegionFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}

/// A physical memory region.
#[derive(Debug, Clone, Copy)]
pub struct PhysMemRegion {
/// The start physical address of the region.
pub paddr: PhysAddr,
/// The size in bytes of the region.
pub size: usize,
/// The region flags, see [`MemRegionFlags`].
pub flags: MemRegionFlags,
/// The region name, used for identification.
pub name: &'static str,
}

impl PhysMemRegion {
/// Returns a [`PhysAddrRange`] that represents its physical address range.
pub fn pa_range(&self) -> PhysAddrRange {
PhysAddrRange::from_start_size(self.paddr, self.size)
}
}

/// Fills the `.bss` section with zeros.
///
/// It requires the symbols `_sbss` and `_ebss` to be defined in the linker script.
///
/// # Safety
///
/// This function is unsafe because it writes `.bss` section directly.
pub unsafe fn clear_bss() {
unsafe {
core::slice::from_raw_parts_mut(_sbss as usize as *mut u8, _ebss as usize - _sbss as usize)
.fill(0);
}
}

unsafe extern "C" {
fn _sbss();
fn _ebss();
}

/// Physical memory interface.
#[def_plat_interface]
pub trait MemIf {
/// Returns all normal memory (RAM) regions on the platform.
fn ram_regions() -> &'static [PhysMemRegion];

/// Returns all device memory (MMIO) regions on the platform.
fn mmio_regions() -> &'static [PhysMemRegion];
}
14 changes: 14 additions & 0 deletions axhal_plat/src/power.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! Power management.
/// Power management interface.
#[def_plat_interface]
pub trait PowerIf {
/// Bootstraps the given CPU with the given initial stack (in physical address).
///
/// Where `cpu_id` is the logical CPU ID (0, 1, ..., N-1, N is the number of
/// CPU cores on the platform).
fn cpu_boot(cpu_id: usize, stack_top_paddr: usize);

/// Shutdown the whole system, including all CPUs.
fn system_off() -> !;
}
73 changes: 73 additions & 0 deletions axhal_plat/src/time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Time-related operations.
pub use core::time::Duration;

/// A measurement of the system clock.
///
/// Currently, it reuses the [`core::time::Duration`] type. But it does not
/// represent a duration, but a clock time.
pub type TimeValue = Duration;

/// Number of milliseconds in a second.
pub const MILLIS_PER_SEC: u64 = 1_000;
/// Number of microseconds in a second.
pub const MICROS_PER_SEC: u64 = 1_000_000;
/// Number of nanoseconds in a second.
pub const NANOS_PER_SEC: u64 = 1_000_000_000;
/// Number of nanoseconds in a millisecond.
pub const NANOS_PER_MILLIS: u64 = 1_000_000;
/// Number of nanoseconds in a microsecond.
pub const NANOS_PER_MICROS: u64 = 1_000;

/// Time-related interfaces.
#[def_plat_interface]
pub trait TimeIf {
/// Returns the current clock time in hardware ticks.
fn current_ticks() -> u64;

/// Converts hardware ticks to nanoseconds.
fn ticks_to_nanos(ticks: u64) -> u64;

/// Converts nanoseconds to hardware ticks.
fn nanos_to_ticks(nanos: u64) -> u64;

/// Return epoch offset in nanoseconds (wall time offset to monotonic clock start).
fn epochoffset_nanos() -> u64;

/// Set a one-shot timer.
///
/// A timer interrupt will be triggered at the specified monotonic time deadline (in nanoseconds).
fn set_oneshot_timer(deadline_ns: u64);
}

/// Returns nanoseconds elapsed since system boot.
pub fn monotonic_time_nanos() -> u64 {
ticks_to_nanos(current_ticks())
}

/// Returns the time elapsed since system boot in [`TimeValue`].
pub fn monotonic_time() -> TimeValue {
TimeValue::from_nanos(monotonic_time_nanos())
}

/// Returns nanoseconds elapsed since epoch (also known as realtime).
pub fn wall_time_nanos() -> u64 {
monotonic_time_nanos() + epochoffset_nanos()
}

/// Returns the time elapsed since epoch (also known as realtime) in [`TimeValue`].
pub fn wall_time() -> TimeValue {
TimeValue::from_nanos(monotonic_time_nanos() + epochoffset_nanos())
}

/// Busy waiting for the given duration.
pub fn busy_wait(dur: Duration) {
busy_wait_until(wall_time() + dur);
}

/// Busy waiting until reaching the given deadline.
pub fn busy_wait_until(deadline: TimeValue) {
while wall_time() < deadline {
core::hint::spin_loop();
}
}
23 changes: 23 additions & 0 deletions axhal_plat_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "axhal_plat_macros"
version = "0.1.0"
description = "Unified operations for various hardware platforms"
documentation = "https://docs.rs/axhal_plat_macros"
keywords = ["arceos", "hal", "hardware-abstraction-layer", "macros"]
categories = ["development-tools::procedural-macro-helpers"]
edition.workspace = true
authors.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true

[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "2.0", features = ["full"] }

[dev-dependencies]
crate_interface = "0.1"

[lib]
proc-macro = true
Loading

0 comments on commit 626455d

Please sign in to comment.