Skip to content

Commit

Permalink
Add 64-bit RISC-V support
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Kröning <[email protected]>
Signed-off-by: Martin Kröning <[email protected]>
  • Loading branch information
simonschoening and mkroening committed Jul 21, 2023
1 parent a4d3b79 commit 12f1f20
Show file tree
Hide file tree
Showing 37 changed files with 5,281 additions and 5 deletions.
72 changes: 69 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ bitflags = "1.3"
crossbeam-utils = { version = "0.8", default-features = false }
dyn-clone = "1.0"
hashbrown = { version = "0.13", default-features = false }
hermit-entry = { version = "0.9", features = ["kernel"] }
hermit-sync = "0.1.2"
include-transformed = { version = "0.2", optional = true }
linked_list_allocator = { version = "0.10", default-features = false }
Expand All @@ -87,6 +86,9 @@ futures-lite = { version = "1.11", default-features = false, optional = true }
async-task = { version = "4.3", default-features = false, optional = true }
lock_api = "0.4"

[target.'cfg(not(target_arch = "riscv64"))'.dependencies]
hermit-entry = { version = "0.9", features = ["kernel"] }

[dependencies.smoltcp]
version = "0.8"
optional = true
Expand Down Expand Up @@ -120,10 +122,19 @@ x86 = { version = "0.52", default-features = false }
version = "0.0.7"
default-features = false

[target.'cfg(target_arch = "riscv64")'.dependencies]
riscv = "0.10"
trapframe = "0.9"
fdt = "0.1"
tock-registers = "0.8"

[workspace]
members = [
"xtask",
]
exclude = [
"hermit-builtins",
]

[patch.crates-io]
hermit-sync = { path = "../../hermit-sync" }
26 changes: 26 additions & 0 deletions src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#[cfg(target_arch = "aarch64")]
pub mod aarch64;

#[cfg(target_arch = "riscv64")]
pub mod riscv;

#[cfg(target_arch = "x86_64")]
pub mod x86_64;

Expand Down Expand Up @@ -29,6 +32,29 @@ pub use crate::arch::aarch64::kernel::{
};
#[cfg(target_arch = "aarch64")]
pub use crate::arch::aarch64::*;
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::kernel::core_local;
#[cfg(target_arch = "riscv64")]
use crate::arch::riscv::kernel::core_local::core_scheduler;
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::kernel::interrupts;
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::kernel::processor;
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::kernel::processor::{set_oneshot_timer, wakeup_core};
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::kernel::scheduler;
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::kernel::switch;
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::kernel::systemtime::get_boot_time;
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::kernel::{
application_processor_init, boot_application_processors, boot_processor_init,
get_processor_count, message_output_init, output_message_buf, output_message_byte,
};
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv::*;
#[cfg(target_arch = "x86_64")]
pub use crate::arch::x86_64::kernel::apic::{set_oneshot_timer, wakeup_core};
#[cfg(all(target_arch = "x86_64", target_os = "none", feature = "smp"))]
Expand Down
138 changes: 138 additions & 0 deletions src/arch/riscv/kernel/core_local.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
use core::arch::asm;

use crate::arch::riscv::kernel::BOOT_INFO;
use crate::scheduler::{CoreId, PerCoreScheduler};

#[no_mangle]
pub static mut CORE_LOCAL: CoreLocal = CoreLocal::new(0);

#[derive(Debug)]
pub struct CoreLocal {
/// ID of the current Core.
core_id: CoreLocalVariable,
/// Scheduler of the current Core.
scheduler: CoreLocalVariable,
/// start address of the kernel stack
pub kernel_stack: CoreLocalVariable,
}

impl CoreLocal {
pub const fn new(core_id: CoreId) -> Self {
Self {
core_id: CoreLocalVariable::new(core_id as usize),
scheduler: CoreLocalVariable::new(0),
kernel_stack: CoreLocalVariable::new(0),
}
}
}

#[derive(Debug)]
#[repr(C)]
pub struct CoreLocalVariable {
data: usize,
}

pub trait CoreLocalVariableMethods {
unsafe fn get(&self) -> usize;
unsafe fn set(&mut self, value: usize);
}

impl CoreLocalVariable {
const fn new(value: usize) -> Self {
Self { data: value }
}

#[inline]
unsafe fn offset(&self) -> usize {
let base = &CORE_LOCAL as *const _ as usize;
let field = self as *const _ as usize;
field - base
}
}

// Treat all per-core variables as 64-bit variables by default. This is true for u64, usize, pointers.
// Implement the CoreLocalVariableMethods trait functions using 64-bit memory moves.
// The functions are implemented as default functions, which can be overriden in specialized implementations of the trait.
impl CoreLocalVariableMethods for CoreLocalVariable {
#[inline]
#[cfg(feature = "smp")]
default unsafe fn get(&self) -> usize {
let mut value: usize;
let mut offset = self.offset();
asm!(
"add {offset}, {offset}, gp",
"ld {value}, 0({offset})",
value = out(reg) value,
offset = inout(reg) offset, // This has to be "inout" to work with the "release" profile?
);
value
}

#[inline]
#[cfg(not(feature = "smp"))]
default unsafe fn get(&self) -> usize {
self.data
}

#[inline]
#[cfg(feature = "smp")]
default unsafe fn set(&mut self, value: usize) {
let mut offset = self.offset();
asm!(
"add {offset}, {offset}, gp",
"sd {value}, 0({offset})",
value = in(reg) value,
offset = inout(reg) offset, // This has to be "inout" to work with the "release" profile?
);
}

#[inline]
#[cfg(not(feature = "smp"))]
default unsafe fn set(&mut self, value: usize) {
self.data = value;
}
}

#[inline]
pub fn core_id() -> CoreId {
unsafe { CORE_LOCAL.core_id.get() as u32 }
}

#[inline]
pub fn core_scheduler() -> &'static mut PerCoreScheduler {
unsafe { &mut *(CORE_LOCAL.scheduler.get() as *mut PerCoreScheduler) }
}

#[inline]
pub fn set_core_scheduler(scheduler: *mut PerCoreScheduler) {
unsafe {
CORE_LOCAL.scheduler.set(scheduler as usize);
}
}

#[inline(always)]
pub fn get_kernel_stack() -> u64 {
unsafe { CORE_LOCAL.kernel_stack.get() as u64 }
}

#[inline]
pub fn set_kernel_stack(addr: u64) {
unsafe { CORE_LOCAL.kernel_stack.set(addr as usize) }
}

pub fn init() {
unsafe {
// Store the address to the CoreLocal structure allocated for this core in gp.
let mut address = core::ptr::read_volatile(&(*BOOT_INFO).current_percore_address);
if address == 0 {
address = &CORE_LOCAL as *const _ as u64;
}

asm!(
"mv gp, {address}",
address = in(reg) address,
);

//println!("core local address: {:x}, {:x?}", address, *(address as *const CoreLocal));
}
}
Loading

0 comments on commit 12f1f20

Please sign in to comment.