Skip to content

Commit

Permalink
feat: integrate 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 Nov 2, 2023
1 parent ac29025 commit 15dbbe1
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 13 deletions.
13 changes: 13 additions & 0 deletions src/drivers/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,16 @@ pub(crate) extern "x86-interrupt" fn network_irqhandler(_stack_frame: ExceptionS

core_scheduler().reschedule();
}

#[cfg(target_arch = "riscv64")]
pub fn network_irqhandler() {
use crate::scheduler::PerCoreSchedulerExt;

debug!("Receive network interrupt");

// PLIC end of interrupt
crate::arch::kernel::interrupts::external_eoi();
let _ = _irqhandler();

core_scheduler().reschedule();
}
3 changes: 3 additions & 0 deletions src/drivers/net/virtio_net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use zerocopy::AsBytes;

use self::constants::{FeatureSet, Features, NetHdrFlag, NetHdrGSO, Status, MAX_NUM_VQ};
use self::error::VirtioNetError;
#[cfg(not(target_arch = "riscv64"))]
use crate::arch::kernel::core_local::increment_irq_counter;
use crate::config::VIRTIO_MAX_QUEUE_SIZE;
#[cfg(not(feature = "pci"))]
Expand Down Expand Up @@ -462,6 +463,7 @@ pub(crate) struct VirtioNetDriver {
pub(super) send_vqs: TxQueues,

pub(super) num_vqs: u16,
#[cfg_attr(target_arch = "riscv64", allow(dead_code))]
pub(super) irq: InterruptLine,
pub(super) mtu: u16,
pub(super) checksums: ChecksumCapabilities,
Expand Down Expand Up @@ -648,6 +650,7 @@ impl NetworkDriver for VirtioNetDriver {
}

fn handle_interrupt(&mut self) -> bool {
#[cfg(not(target_arch = "riscv64"))]
increment_irq_counter(32 + self.irq);

let result = if self.isr_stat.is_interrupt() {
Expand Down
1 change: 1 addition & 0 deletions src/drivers/virtio/transport/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ pub(crate) fn init_device(
info!("Virtio network driver initialized.");
// Install interrupt handler
irq_install_handler(irq_no, network_irqhandler);
#[cfg(not(target_arch = "riscv64"))]
add_irq_name(irq_no, "virtio_net");

Ok(VirtioDriver::Network(virt_net_drv))
Expand Down
5 changes: 5 additions & 0 deletions src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub fn init() {
struct Cli {
#[allow(dead_code)]
image_path: Option<String>,
#[cfg(not(target_arch = "riscv64"))]
freq: Option<u16>,
env_vars: HashMap<String, String, RandomState>,
args: Vec<String>,
Expand All @@ -36,6 +37,7 @@ pub fn is_uhyve() -> bool {
impl Default for Cli {
fn default() -> Self {
let mut image_path = None;
#[cfg(not(target_arch = "riscv64"))]
let mut freq = None;
let mut env_vars = HashMap::<String, String, RandomState>::with_hasher(
RandomState::with_seeds(0, 0, 0, 0),
Expand All @@ -53,6 +55,7 @@ impl Default for Cli {
};
while let Some(word) = words.next() {
match word.as_str() {
#[cfg(not(target_arch = "riscv64"))]
"-freq" => {
let s = expect_arg(words.next(), word.as_str());
freq = Some(s.parse().unwrap());
Expand Down Expand Up @@ -81,6 +84,7 @@ impl Default for Cli {

Self {
image_path,
#[cfg(not(target_arch = "riscv64"))]
freq,
env_vars,
args,
Expand All @@ -89,6 +93,7 @@ impl Default for Cli {
}

/// CPU Frequency in MHz if given through the -freq command-line parameter.
#[cfg(not(target_arch = "riscv64"))]
pub fn freq() -> Option<u16> {
CLI.get().unwrap().freq
}
Expand Down
7 changes: 7 additions & 0 deletions src/executor/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ fn start_endpoint() -> u16 {
(value % (u16::MAX as u64)).try_into().unwrap()
}

#[cfg(target_arch = "riscv64")]
fn start_endpoint() -> u16 {
(riscv::register::time::read64() % (u16::MAX as u64))
.try_into()
.unwrap()
}

#[inline]
pub(crate) fn now() -> Instant {
let microseconds = arch::processor::get_timer_ticks() + arch::get_boot_time();
Expand Down
8 changes: 8 additions & 0 deletions src/fd/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use alloc::sync::Arc;
use core::ffi::{c_void, CStr};
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
use core::ptr;
use core::sync::atomic::{AtomicI32, Ordering};

Expand Down Expand Up @@ -164,6 +165,13 @@ fn uhyve_send<T>(port: u16, data: &mut T) {
}
}

/// forward a request to the hypervisor uhyve
#[inline]
#[cfg(target_arch = "riscv64")]
fn uhyve_send<T>(_port: u16, _data: &mut T) {
todo!()
}

fn open_flags_to_perm(flags: i32, mode: u32) -> FilePerms {
let mut perms = FilePerms {
raw: flags as u32,
Expand Down
18 changes: 16 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
#![warn(clippy::uninlined_format_args)]
#![warn(clippy::transmute_ptr_to_ptr)]
#![allow(clippy::missing_safety_doc)]
#![cfg_attr(target_arch = "aarch64", allow(incomplete_features))]
#![cfg_attr(
any(target_arch = "aarch64", target_arch = "riscv64"),
allow(incomplete_features)
)]
#![cfg_attr(target_arch = "x86_64", feature(abi_x86_interrupt))]
#![cfg_attr(target_arch = "riscv64", feature(offset_of))]
#![feature(allocator_api)]
#![feature(asm_const)]
#![feature(core_intrinsics)]
Expand All @@ -19,7 +23,10 @@
#![feature(pointer_is_aligned)]
#![feature(ptr_from_ref)]
#![feature(slice_from_ptr_range)]
#![cfg_attr(target_arch = "aarch64", feature(specialization))]
#![cfg_attr(
any(target_arch = "aarch64", target_arch = "riscv64"),
feature(specialization)
)]
#![feature(strict_provenance)]
#![cfg_attr(target_os = "none", no_std)]
#![cfg_attr(target_os = "none", feature(custom_test_frameworks))]
Expand Down Expand Up @@ -268,6 +275,10 @@ extern "C" fn initd(_arg: usize) {
arch::init_drivers();
crate::executor::init();

// Initialize MMIO Drivers if on riscv64
#[cfg(target_arch = "riscv64")]
riscv64::kernel::init_drivers();

syscalls::init();
fd::init();
#[cfg(feature = "fs")]
Expand Down Expand Up @@ -320,6 +331,8 @@ fn boot_processor_main() -> ! {
});
info!("tls_info = {:#x?}", kernel::boot_info().load_info.tls_info);
arch::boot_processor_init();

#[cfg(not(target_arch = "riscv64"))]
scheduler::add_current_core();

if !env::is_uhyve() {
Expand Down Expand Up @@ -354,6 +367,7 @@ fn boot_processor_main() -> ! {
#[cfg(all(target_os = "none", feature = "smp"))]
fn application_processor_main() -> ! {
arch::application_processor_init();
#[cfg(not(target_arch = "riscv64"))]
scheduler::add_current_core();

info!("Entering idle loop for application processor");
Expand Down
1 change: 1 addition & 0 deletions src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ macro_rules! infoheader {
}};
}

#[cfg_attr(target_arch = "riscv64", allow(unused))]
macro_rules! infoentry {
($str:expr, $rhs:expr) => (infoentry!($str, "{}", $rhs));
($str:expr, $($arg:tt)+) => (::log::info!("{:25}{}", concat!($str, ":"), format_args!($($arg)+)));
Expand Down
11 changes: 9 additions & 2 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ macro_rules! dbg {
/// let ret = f(arg);
/// ```
#[allow(unused_macro_rules)]
#[cfg(not(feature = "newlib"))]
#[cfg(not(any(
target_arch = "riscv64",
all(target_arch = "x86_64", feature = "newlib")
)))]
macro_rules! kernel_function {
($f:ident()) => {
$crate::arch::switch::kernel_function0($f)
Expand Down Expand Up @@ -105,7 +108,11 @@ macro_rules! kernel_function {

// TODO: Properly switch kernel stack with newlib
// https://github.com/hermit-os/kernel/issues/471
#[cfg(all(target_arch = "x86_64", feature = "newlib"))]
// TODO: Switch kernel stack on RISC-V
#[cfg(any(
target_arch = "riscv64",
all(target_arch = "x86_64", feature = "newlib")
))]
macro_rules! kernel_function {
($f:ident($($x:tt)*)) => {{
$f($($x)*)
Expand Down
10 changes: 5 additions & 5 deletions src/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use hermit_sync::Lazy;
#[cfg(feature = "newlib")]
use hermit_sync::OnceCell;

#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
use crate::arch::mm::paging::HugePageSize;
#[cfg(target_arch = "x86_64")]
use crate::arch::mm::paging::PageTableEntryFlagsExt;
Expand Down Expand Up @@ -82,7 +82,7 @@ pub(crate) fn init() {
let reserved_space = (npage_3tables + npage_2tables + npage_1tables)
* BasePageSize::SIZE as usize
+ LargePageSize::SIZE as usize;
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
let has_1gib_pages = arch::processor::supports_1gib_pages();
let has_2mib_pages = arch::processor::supports_2mib_pages();

Expand Down Expand Up @@ -152,7 +152,7 @@ pub(crate) fn init() {
virt_addr
);

#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
if has_1gib_pages && virt_size > HugePageSize::SIZE as usize {
// Mount large pages to the next huge page boundary
let npages = (virt_addr.align_up_to_huge_page().as_usize() - virt_addr.as_usize())
Expand All @@ -169,14 +169,14 @@ pub(crate) fn init() {
map_size = virt_size;
}

#[cfg(not(target_arch = "x86_64"))]
#[cfg(not(any(target_arch = "x86_64", target_arch = "riscv64")))]
{
map_addr = virt_addr;
map_size = virt_size;
}
}

#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
if has_1gib_pages
&& map_size > HugePageSize::SIZE as usize
&& map_addr.is_aligned(HugePageSize::SIZE)
Expand Down
42 changes: 39 additions & 3 deletions src/scheduler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ use core::sync::atomic::{AtomicU32, Ordering};

use crossbeam_utils::Backoff;
use hermit_sync::{without_interrupts, *};
#[cfg(target_arch = "riscv64")]
use riscv::register::sstatus;

use crate::arch;
use crate::arch::core_local::*;
use crate::arch::interrupts;
#[cfg(target_arch = "riscv64")]
use crate::arch::switch::switch_to_task;
#[cfg(target_arch = "x86_64")]
use crate::arch::switch::{switch_to_fpu_owner, switch_to_task};
use crate::kernel::scheduler::TaskStacks;
Expand Down Expand Up @@ -142,6 +146,11 @@ impl PerCoreSchedulerExt for &mut PerCoreScheduler {
interrupts::enable();
}

#[cfg(target_arch = "riscv64")]
fn reschedule(self) {
without_interrupts(|| self.scheduler());
}

#[cfg(any(feature = "tcp", feature = "udp"))]
fn add_network_timer(self, wakeup_time: Option<u64>) {
without_interrupts(|| {
Expand Down Expand Up @@ -357,7 +366,7 @@ impl PerCoreScheduler {

/// Returns `true` if a reschedule is required
#[inline]
#[cfg(all(target_arch = "x86_64", feature = "smp"))]
#[cfg(all(any(target_arch = "x86_64", target_arch = "riscv64"), feature = "smp"))]
pub fn is_scheduling(&self) -> bool {
self.current_task.borrow().prio < self.ready_queue.get_highest_priority()
}
Expand Down Expand Up @@ -492,6 +501,17 @@ impl PerCoreScheduler {
})
}

#[cfg(target_arch = "riscv64")]
pub fn set_current_kernel_stack(&self) {
let current_task_borrowed = self.current_task.borrow();

let stack = (current_task_borrowed.stacks.get_kernel_stack()
+ current_task_borrowed.stacks.get_kernel_stack_size()
- TaskStacks::MARKER_SIZE)
.as_u64();
CoreLocal::get().kernel_stack.set(stack);
}

/// Save the FPU context for the current FPU owner and restore it for the current task,
/// which wants to use the FPU now.
#[cfg(target_arch = "x86_64")]
Expand All @@ -517,7 +537,7 @@ impl PerCoreScheduler {
}
}

#[cfg(all(target_arch = "x86_64", feature = "smp"))]
#[cfg(all(any(target_arch = "x86_64", target_arch = "riscv64"), feature = "smp"))]
pub fn check_input(&mut self) {
let mut input_locked = CoreLocal::get().scheduler_input.lock();

Expand Down Expand Up @@ -648,10 +668,26 @@ impl PerCoreScheduler {
unsafe { *last_stack_pointer },
new_stack_pointer
);
self.current_task = task;
#[cfg(not(target_arch = "riscv64"))]
{
self.current_task = task;
}

// Finally return the context of the new task.
#[cfg(not(target_arch = "riscv64"))]
return Some(last_stack_pointer);

#[cfg(target_arch = "riscv64")]
{
if sstatus::read().fs() == sstatus::FS::Dirty {
self.current_task.borrow_mut().last_fpu_state.save();
}
task.borrow().last_fpu_state.restore();
self.current_task = task;
unsafe {
switch_to_task(last_stack_pointer, new_stack_pointer.as_usize());
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/scheduler/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ impl PriorityTaskQueue {
}

/// Returns the highest priority of all available task
#[cfg(all(target_arch = "x86_64", feature = "smp"))]
#[cfg(all(any(target_arch = "x86_64", target_arch = "riscv64"), feature = "smp"))]
pub fn get_highest_priority(&self) -> Priority {
if let Some(i) = msb(self.prio_bitmap) {
Priority::from(i.try_into().unwrap())
Expand Down
1 change: 1 addition & 0 deletions src/syscalls/entropy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ unsafe extern "C" fn __sys_read_entropy(buf: *mut u8, len: usize, flags: u32) ->
/// * `-EINVAL` if `flags` contains unknown flags.
/// * `-ENOSYS` if the system does not support random data generation.
#[no_mangle]
#[cfg_attr(target_arch = "riscv64", allow(unsafe_op_in_unsafe_fn))] // FIXME
pub unsafe extern "C" fn sys_read_entropy(buf: *mut u8, len: usize, flags: u32) -> isize {
kernel_function!(__sys_read_entropy(buf, len, flags))
}
Expand Down
7 changes: 7 additions & 0 deletions src/syscalls/interfaces/uhyve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ pub(crate) fn uhyve_send<T>(port: u16, data: &mut T) {
}
}

/// forward a request to the hypervisor uhyve
#[inline]
#[cfg(target_arch = "riscv64")]
fn uhyve_send<T>(_port: u16, _data: &mut T) {
todo!()
}

const MAX_ARGC_ENVC: usize = 128;

#[repr(C, packed)]
Expand Down

0 comments on commit 15dbbe1

Please sign in to comment.