Skip to content

Commit

Permalink
Add remote fence extension; document fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
luojia65 committed Feb 23, 2021
1 parent e7292b9 commit 6e06b4e
Show file tree
Hide file tree
Showing 12 changed files with 287 additions and 42 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -7,8 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- S-level Illegal instruction exception is now delegated into S-level software handler
- Support RFENCE extension in RustSBI framework
- Added a test kernel to test SBI function on RustSBI implementations
- Support framework for RFENCE extension

### Modified
- Function `rustsbi::ecall` now require 5 input parameters
Expand Down
3 changes: 2 additions & 1 deletion platform/k210/src/main.rs
Expand Up @@ -155,14 +155,15 @@ fn main() -> ! {
fn max_hart_id(&self) -> usize {
1
}
fn send_ipi_many(&mut self, hart_mask: rustsbi::HartMask) {
fn send_ipi_many(&mut self, hart_mask: rustsbi::HartMask) -> rustsbi::SbiRet {
use k210_hal::clint::msip;
for i in 0..=1 {
if hart_mask.has_bit(i) {
msip::set_ipi(i);
msip::clear_ipi(i);
}
}
rustsbi::SbiRet::ok(0)
}
}
use rustsbi::init_ipi;
Expand Down
2 changes: 1 addition & 1 deletion platform/qemu/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rustsbi-qemu"
version = "0.1.0"
version = "0.2.0"
authors = ["luojia65 <me@luojia.cc>"]
edition = "2018"
publish = false
Expand Down
4 changes: 3 additions & 1 deletion platform/qemu/src/hal/clint.rs
@@ -1,4 +1,5 @@
// 这部分其实是运行时提供的,不应该做到实现库里面
use rustsbi::SbiRet;

pub struct Clint {
base: usize,
Expand Down Expand Up @@ -48,12 +49,13 @@ impl Ipi for Clint {
*crate::MAX_HART_ID.lock()
}

fn send_ipi_many(&mut self, hart_mask: HartMask) {
fn send_ipi_many(&mut self, hart_mask: HartMask) -> SbiRet {
for i in 0..=self.max_hart_id() {
if hart_mask.has_bit(i) {
self.send_soft(i);
}
}
SbiRet::ok(0)
}
}

Expand Down
3 changes: 2 additions & 1 deletion rustsbi/src/ecall.rs
Expand Up @@ -109,7 +109,8 @@ const SBI_ERR_NOT_SUPPORTED: usize = usize::from_ne_bytes(isize::to_ne_bytes(-2)
// const SBI_ERR_ALREADY_AVAILABLE: usize = usize::from_ne_bytes(isize::to_ne_bytes(-6));

impl SbiRet {
pub(crate) fn ok(value: usize) -> SbiRet {
/// Return success SBI state with given value.
pub fn ok(value: usize) -> SbiRet {
SbiRet {
error: SBI_SUCCESS,
value,
Expand Down
10 changes: 7 additions & 3 deletions rustsbi/src/ecall/ipi.rs
Expand Up @@ -14,7 +14,11 @@ pub fn handle_ecall_ipi(function: usize, param0: usize, param1: usize) -> SbiRet

#[inline]
fn send_ipi(hart_mask: usize, hart_mask_base: usize) -> SbiRet {
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id()) };
send_ipi_many(hart_mask);
SbiRet::ok(0)
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
send_ipi_many(hart_mask)
}
10 changes: 7 additions & 3 deletions rustsbi/src/ecall/legacy.rs
Expand Up @@ -19,11 +19,15 @@ pub fn console_getchar() -> SbiRet {

#[inline]
pub fn send_ipi(hart_mask_addr: usize) -> SbiRet {
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
// note(unsafe): if any load fault, should be handled by user or supervisor
// base hart should be 0 on legacy
let hart_mask = unsafe { HartMask::from_addr(hart_mask_addr, 0, max_hart_id()) };
send_ipi_many(hart_mask);
SbiRet::ok(0) // the return value 0 is ignored in legacy
let hart_mask = unsafe { HartMask::from_addr(hart_mask_addr, 0, max_hart_id) };
send_ipi_many(hart_mask)
}

#[inline]
Expand Down
78 changes: 57 additions & 21 deletions rustsbi/src/ecall/rfence.rs
@@ -1,4 +1,7 @@
use super::SbiRet;
use crate::rfence;
use crate::hart_mask::HartMask;
use crate::ipi::max_hart_id;

const FUNCTION_RFENCE_REMOTE_FENCE_I: usize = 0x0;
const FUNCTION_RFENCE_REMOTE_SFENCE_VMA: usize = 0x1;
Expand All @@ -22,51 +25,84 @@ pub fn handle_ecall_rfence(function: usize, param0: usize, param1: usize, param2
}
}

// If None = max_hart_id(), that means IPI extension is not supported.
// In RustSBI, RFENCE support requires an IPI support is implemented.
// If platform does not provide IPI support, RustSBI will disable RFENCE
// interface access from supervisor level.

#[inline]
fn remote_fence_i(hart_mask: usize, hart_mask_base: usize) -> SbiRet {
// todo
drop((hart_mask, hart_mask_base));
SbiRet::not_supported()
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
rfence::remote_fence_i(hart_mask)
}

#[inline]
fn remote_sfence_vma(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize) -> SbiRet {
// todo
drop((hart_mask, hart_mask_base, start_addr, size));
SbiRet::not_supported()
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
rfence::remote_sfence_vma(hart_mask, start_addr, size)
}

#[inline]
fn remote_sfence_vma_asid(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize, asid: usize) -> SbiRet {
// todo
drop((hart_mask, hart_mask_base, start_addr, size, asid));
SbiRet::not_supported()
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
rfence::remote_sfence_vma_asid(hart_mask, start_addr, size, asid)
}

#[inline]
fn remote_hfence_gvma_vmid(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize, vmid: usize) -> SbiRet {
// todo
drop((hart_mask, hart_mask_base, start_addr, size, vmid));
SbiRet::not_supported()
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
rfence::remote_hfence_gvma_vmid(hart_mask, start_addr, size, vmid)
}

#[inline]
fn remote_hfence_gvma(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize) -> SbiRet {
// todo
drop((hart_mask, hart_mask_base, start_addr, size));
SbiRet::not_supported()
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
rfence::remote_hfence_gvma(hart_mask, start_addr, size)
}

#[inline]
fn remote_hfence_vvma_asid(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize, asid: usize) -> SbiRet {
// todo
drop((hart_mask, hart_mask_base, start_addr, size, asid));
SbiRet::not_supported()
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
rfence::remote_hfence_vvma_asid(hart_mask, start_addr, size, asid)
}

#[inline]
fn remote_hfence_vvma(hart_mask: usize, hart_mask_base: usize, start_addr: usize, size: usize) -> SbiRet {
// todo
drop((hart_mask, hart_mask_base, start_addr, size));
SbiRet::not_supported()
let max_hart_id = if let Some(id) = max_hart_id() {
id
} else {
return SbiRet::not_supported()
};
let hart_mask = unsafe { HartMask::from_addr(hart_mask, hart_mask_base, max_hart_id) };
rfence::remote_hfence_vvma(hart_mask, start_addr, size)
}
17 changes: 10 additions & 7 deletions rustsbi/src/ipi.rs
@@ -1,4 +1,5 @@
use crate::hart_mask::HartMask;
use crate::ecall::SbiRet;

/// Inter-processor interrupt support
pub trait Ipi: Send {
Expand All @@ -7,7 +8,7 @@ pub trait Ipi: Send {
/// Send an inter-processor interrupt to all the harts defined in `hart_mask`.
///
/// Interprocessor interrupts manifest at the receiving harts as the supervisor software interrupts.
fn send_ipi_many(&mut self, hart_mask: HartMask);
fn send_ipi_many(&mut self, hart_mask: HartMask) -> SbiRet;
}

use alloc::boxed::Box;
Expand All @@ -27,16 +28,18 @@ pub(crate) fn probe_ipi() -> bool {
IPI.lock().as_ref().is_some()
}

pub(crate) fn send_ipi_many(hart_mask: HartMask) {
pub(crate) fn send_ipi_many(hart_mask: HartMask) -> SbiRet {
if let Some(ipi) = IPI.lock().as_mut() {
ipi.send_ipi_many(hart_mask)
} else {
SbiRet::not_supported()
}
}

pub(crate) fn max_hart_id() -> usize {
loop {
if let Some(ipi) = IPI.lock().as_ref() {
return ipi.max_hart_id();
}
pub(crate) fn max_hart_id() -> Option<usize> {
if let Some(ipi) = IPI.lock().as_ref() {
Some(ipi.max_hart_id())
} else {
None
}
}
8 changes: 8 additions & 0 deletions rustsbi/src/legacy_stdio.rs
Expand Up @@ -119,6 +119,10 @@ pub fn _print(args: fmt::Arguments) {
}

/// Prints to the legacy debug console.
///
/// This is only supported when there exists legacy extension;
/// otherwise platform caller should use an early kernel input/output device
/// declared in platform specific hardware.
#[macro_export(local_inner_macros)]
macro_rules! print {
($($arg:tt)*) => ({
Expand All @@ -127,6 +131,10 @@ macro_rules! print {
}

/// Prints to the legacy debug console, with a newline.
///
/// This is only supported when there exists legacy extension;
/// otherwise platform caller should use an early kernel input/output device
/// declared in platform specific hardware.
#[macro_export(local_inner_macros)]
macro_rules! println {
($fmt: literal $(, $($arg: tt)+)?) => {
Expand Down
1 change: 1 addition & 0 deletions rustsbi/src/lib.rs
Expand Up @@ -58,3 +58,4 @@ pub use logo::LOGO;
pub use privileged::enter_privileged;
pub use reset::{init_reset, Reset};
pub use timer::{init_timer, Timer};
pub use rfence::{init_rfence as init_remote_fence, Rfence as Fence};

0 comments on commit 6e06b4e

Please sign in to comment.