Skip to content

Commit

Permalink
Merge pull request #800 from hermit-os/riscv64
Browse files Browse the repository at this point in the history
feat: add 64-bit RISC-V support
  • Loading branch information
mkroening authored Nov 2, 2023
2 parents eab3fd3 + a7b2ae5 commit 0efe37a
Show file tree
Hide file tree
Showing 40 changed files with 4,540 additions and 18 deletions.
15 changes: 12 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Check each feature
run: cargo hack check --package hermit-kernel --each-feature --no-dev-deps --target x86_64-unknown-none
run: cargo hack check --package hermit-kernel --each-feature --skip gem-net --no-dev-deps --target x86_64-unknown-none
env:
RUSTFLAGS:

Expand Down Expand Up @@ -125,14 +125,20 @@ jobs:
working-directory: kernel
strategy:
matrix:
arch: [x86_64, aarch64]
arch: [x86_64, aarch64, riscv64]
package: [rusty_demo, httpd, testudp, hello_world]
netdev: [none, virtio-net-pci, rtl8139]
profile: [dev, release]
exclude:
# microvm (Firecracker) test does not run on aarch64
- arch: riscv64
package: httpd
- arch: riscv64
package: testudp
# microvm (Firecracker) test does not run on aarch64 or riscv64
- package: hello_world
arch: aarch64
- package: hello_world
arch: riscv64
# rtl8139 support does not build on aarch64
- arch: aarch64
netdev: rtl8139
Expand All @@ -155,6 +161,9 @@ jobs:
packages: qemu-system-x86 libcap-ng-dev libseccomp-dev socat
- arch: aarch64
packages: qemu-system-aarch64
- arch: riscv64
packages: qemu-system-misc
flags: --no-default-features

- arch: x86_64
package: rusty_demo
Expand Down
72 changes: 70 additions & 2 deletions Cargo.lock

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

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ dhcpv4 = [
]
fs = ["pci"]
fsgsbase = []
gem-net = ["tcp"]
newlib = []
pci = []
rtl8139 = ["tcp", "pci"]
Expand Down Expand Up @@ -124,6 +125,12 @@ aarch64 = { version = "0.0", default-features = false }
arm-gic = { version = "0.1" }
hermit-dtb = { version = "0.1" }

[target.'cfg(target_arch = "riscv64")'.dependencies]
fdt = "0.1"
riscv = "0.10"
sbi = "0.2"
trapframe = "0.9"

[dev-dependencies]
float-cmp = "0.9"
num-traits = { version = "0.2", default-features = false }
Expand Down
19 changes: 19 additions & 0 deletions src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,24 @@ cfg_if::cfg_if! {
message_output_init,
output_message_buf,
};
} else if #[cfg(target_arch = "riscv64")] {
pub mod riscv64;
pub use self::riscv64::*;

#[cfg(feature = "smp")]
pub use self::riscv64::kernel::application_processor_init;
pub use self::riscv64::kernel::processor::{self, set_oneshot_timer, wakeup_core};
pub use self::riscv64::kernel::systemtime::get_boot_time;
pub use self::riscv64::kernel::{
boot_application_processors,
boot_processor_init,
core_local,
get_processor_count,
interrupts,
message_output_init,
output_message_buf,
scheduler,
switch,
};
}
}
89 changes: 89 additions & 0 deletions src/arch/riscv64/kernel/core_local.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::arch::asm;
use core::cell::{Cell, RefCell, RefMut};
use core::ptr;
use core::sync::atomic::Ordering;

#[cfg(feature = "smp")]
use hermit_sync::InterruptTicketMutex;

use crate::arch::riscv64::kernel::CPU_ONLINE;
use crate::executor::task::AsyncTask;
#[cfg(feature = "smp")]
use crate::scheduler::SchedulerInput;
use crate::scheduler::{CoreId, PerCoreScheduler};

pub struct CoreLocal {
/// ID of the current Core.
core_id: CoreId,
/// Scheduler of the current Core.
scheduler: Cell<*mut PerCoreScheduler>,
/// start address of the kernel stack
pub kernel_stack: Cell<u64>,
/// Queue of async tasks
async_tasks: RefCell<Vec<AsyncTask>>,
/// Queues to handle incoming requests from the other cores
#[cfg(feature = "smp")]
pub scheduler_input: InterruptTicketMutex<SchedulerInput>,
}

impl CoreLocal {
pub fn install() {
unsafe {
let raw: *const Self;
asm!("mv {}, gp", out(reg) raw);
debug_assert_eq!(raw, ptr::null());

let core_id = dbg!(CPU_ONLINE.load(Ordering::Relaxed));

let this = Self {
core_id,
scheduler: Cell::new(ptr::null_mut()),
kernel_stack: Cell::new(0),
async_tasks: RefCell::new(Vec::new()),
#[cfg(feature = "smp")]
scheduler_input: InterruptTicketMutex::new(SchedulerInput::new()),
};
let this = if core_id == 0 {
take_static::take_static! {
static FIRST_CORE_LOCAL: Option<CoreLocal> = None;
}
FIRST_CORE_LOCAL.take().unwrap().insert(this)
} else {
Box::leak(Box::new(this))
};

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

#[inline]
pub fn get() -> &'static Self {
unsafe {
let raw: *const Self;
asm!("mv {}, gp", out(reg) raw);
debug_assert_ne!(raw, ptr::null());
&*raw
}
}
}

#[inline]
pub fn core_id() -> CoreId {
CoreLocal::get().core_id
}

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

#[inline]
pub fn set_core_scheduler(scheduler: *mut PerCoreScheduler) {
CoreLocal::get().scheduler.set(scheduler);
}

pub(crate) fn async_tasks() -> RefMut<'static, Vec<AsyncTask>> {
CoreLocal::get().async_tasks.borrow_mut()
}
Loading

0 comments on commit 0efe37a

Please sign in to comment.