Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
2f85419
Implement VSTOPI CSR for RISC-V
KushalMeghani1644 Nov 20, 2025
770334a
Update CHANGELOG.md
KushalMeghani1644 Nov 20, 2025
f2149a3
Add qemu CI
KushalMeghani1644 Nov 14, 2025
105c9f4
Improve QEMU CI
KushalMeghani1644 Nov 14, 2025
ec4e7d4
Fix QEMU CI
KushalMeghani1644 Nov 14, 2025
b92ec05
Fix QEMU CI
KushalMeghani1644 Nov 14, 2025
7d0d8df
Update QEMU CI
KushalMeghani1644 Nov 14, 2025
17d9bed
Fix package issue
KushalMeghani1644 Nov 14, 2025
3637239
Add QEMU CI to add expected hello outputs
KushalMeghani1644 Nov 15, 2025
8567f5f
Fix qemu CI
KushalMeghani1644 Nov 15, 2025
0078ff2
Fix formatting
KushalMeghani1644 Nov 15, 2025
1731bdf
Fix QEMU CI for a clean output ensuring the CI passes
KushalMeghani1644 Nov 28, 2025
2aba7b3
Updated tests to use riscv-semihosting instead of UART
KushalMeghani1644 Nov 28, 2025
7524ed5
Added one test using UART and one test with riscv-semihosting
KushalMeghani1644 Nov 28, 2025
522e17d
Update CHANGELOG.md
KushalMeghani1644 Nov 28, 2025
71b69f5
Update types.toml
KushalMeghani1644 Nov 28, 2025
a31f5fb
Fix UB in heap init example docs
kurtjd Nov 28, 2025
7db26ba
Merge pull request #376 from kurtjd/fix-example-ub
romancardenas Dec 1, 2025
86f649d
Merge pull request #373 from KushalMeghani1644/add-vstopi
romancardenas Dec 1, 2025
4d46022
Fix v-trap core interrupt
kurtjd Nov 30, 2025
297e3d5
Merge pull request #377 from kurtjd/vtrap-isa-panic
romancardenas Dec 2, 2025
19734b6
Update riscv-rt/examples/hello.rs
KushalMeghani1644 Dec 3, 2025
4c9a345
Update riscv-rt/examples/hello.rs
KushalMeghani1644 Dec 3, 2025
c624883
Update riscv-rt/CHANGELOG.md
KushalMeghani1644 Dec 3, 2025
22fe9e3
Update xtask/src/main.rs
KushalMeghani1644 Dec 3, 2025
cfe87db
Address review comments
KushalMeghani1644 Dec 3, 2025
7bc230b
fix formatting
KushalMeghani1644 Dec 3, 2025
f5a08ce
Add expected QEMU CI files
KushalMeghani1644 Dec 3, 2025
e5f4af1
Add qemu CI
KushalMeghani1644 Nov 14, 2025
2deec5b
Improve QEMU CI
KushalMeghani1644 Nov 14, 2025
37111be
Fix QEMU CI
KushalMeghani1644 Nov 14, 2025
388cb8b
Fix QEMU CI
KushalMeghani1644 Nov 14, 2025
2a42ead
Update QEMU CI
KushalMeghani1644 Nov 14, 2025
2cc11f8
Fix package issue
KushalMeghani1644 Nov 14, 2025
1c1abd5
Add QEMU CI to add expected hello outputs
KushalMeghani1644 Nov 15, 2025
62bd0fb
Fix qemu CI
KushalMeghani1644 Nov 15, 2025
0792729
Fix formatting
KushalMeghani1644 Nov 15, 2025
bb8684e
Fix QEMU CI for a clean output ensuring the CI passes
KushalMeghani1644 Nov 28, 2025
eca57eb
Updated tests to use riscv-semihosting instead of UART
KushalMeghani1644 Nov 28, 2025
6c48a60
Added one test using UART and one test with riscv-semihosting
KushalMeghani1644 Nov 28, 2025
66410a1
Update CHANGELOG.md
KushalMeghani1644 Nov 28, 2025
fabc4cd
Update types.toml
KushalMeghani1644 Nov 28, 2025
6bd28fc
Update riscv-rt/examples/hello.rs
KushalMeghani1644 Dec 3, 2025
9288569
Update riscv-rt/examples/hello.rs
KushalMeghani1644 Dec 3, 2025
5a8fd70
Update riscv-rt/CHANGELOG.md
KushalMeghani1644 Dec 3, 2025
1809192
Update xtask/src/main.rs
KushalMeghani1644 Dec 3, 2025
e516f04
Address review comments
KushalMeghani1644 Dec 3, 2025
e8e6847
fix formatting
KushalMeghani1644 Dec 3, 2025
1dab284
Add expected QEMU CI files
KushalMeghani1644 Dec 3, 2025
4cbabfa
Simplify QEMU CI by consolidating golden files and using
KushalMeghani1644 Dec 5, 2025
d56564b
Remove uneeded file
KushalMeghani1644 Dec 5, 2025
1e4763a
resolve conflict
KushalMeghani1644 Dec 5, 2025
7eed218
fix lints
KushalMeghani1644 Dec 5, 2025
de5e0b9
Remove conflicts
KushalMeghani1644 Dec 5, 2025
7fbdf5a
Fix QEMU CI
KushalMeghani1644 Dec 5, 2025
5b4b717
Remove duplicates in code
KushalMeghani1644 Dec 5, 2025
4bede74
Remove uneeded files
KushalMeghani1644 Dec 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/qemu.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: QEMU tests
on:
merge_group:
pull_request:
push:
branches:
- master

env:
CARGO_TERM_COLOR: always

jobs:
testexamples:
name: QEMU run
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
toolchain: [stable]
target-qemu:
- target: riscv32i-unknown-none-elf
qemu: riscv32
- target: riscv32im-unknown-none-elf
qemu: riscv32
- target: riscv32imc-unknown-none-elf
qemu: riscv32
- target: riscv32imac-unknown-none-elf
qemu: riscv32
- target: riscv32imafc-unknown-none-elf
qemu: riscv32
- target: riscv64imac-unknown-none-elf
qemu: riscv64
- target: riscv64gc-unknown-none-elf
qemu: riscv64
example:
- qemu_uart
- qemu_semihosting

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Configure Rust target ${{ matrix.target-qemu.target }}
run: |
rustup toolchain install ${{ matrix.toolchain }}
rustup default ${{ matrix.toolchain }}
rustup target add ${{ matrix.target-qemu.target }}

- name: Cache Dependencies
uses: Swatinem/rust-cache@v2

- name: Install QEMU
run: |
sudo apt update
sudo apt install -y qemu-system-${{ matrix.target-qemu.qemu }}

- name: Run-pass tests
run: cargo run --package xtask -- qemu --target ${{ matrix.target-qemu.target }} --example ${{ matrix.example }}

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ members = [
"riscv-types",
"tests-build",
"tests-trybuild",
"xtask",
]

default-members = [
Expand Down
1 change: 1 addition & 0 deletions ci/expected/qemu_semihosting.run
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello from semihosting!
1 change: 1 addition & 0 deletions ci/expected/qemu_uart.run
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello from UART!
3 changes: 3 additions & 0 deletions riscv-rt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added

- Added examples for CI tests using semihosting and UART
- New `no-mhartid` feature to load 0 to `a0` instead of reading `mhartid`.
- New `no-xtvec` feature that removes interrupt stuff.

Expand All @@ -21,6 +22,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Fixed

- Fix v-trap core interrupt so RISCV_RT_BASE_ISA must be defined
- Fix undefined behavior in heap initialization example documentation
- Fix stack allocation algorithm for multi-core targets without M extension

## [v0.16.0] - 2025-09-08
Expand Down
2 changes: 2 additions & 0 deletions riscv-rt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ defmt = { version = "1.0.1", optional = true }

[dev-dependencies]
panic-halt = "1.0.0"
riscv-semihosting = { path = "../riscv-semihosting", version = "0.2.1" }
riscv = { path = "../riscv", version = "0.15.0", features = ["critical-section-single-hart"] }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This forces us to only test for single-core devices. It is ok for the time being, but we should think of a more versatile way to allow us to test multi-core devices.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to address this ASAP!


[features]
pre-init = []
Expand Down
11 changes: 11 additions & 0 deletions riscv-rt/examples/device_virt.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
MEMORY
{
RAM : ORIGIN = 0x80000000, LENGTH = 16M
}
REGION_ALIAS("REGION_TEXT", RAM);
REGION_ALIAS("REGION_RODATA", RAM);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
REGION_ALIAS("REGION_STACK", RAM);
INCLUDE link.x
22 changes: 22 additions & 0 deletions riscv-rt/examples/qemu_semihosting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! Semihosting example for QEMU
//!
//! This example uses RISC-V semihosting to print output and cleanly exit QEMU.
//! Run with: `qemu-system-riscv32 -machine virt -nographic -semihosting-config enable=on,target=native -bios none -kernel <binary>`

#![no_std]
#![no_main]

extern crate panic_halt;

use riscv_rt::entry;
use riscv_semihosting::{
debug::{self, EXIT_SUCCESS},
hprintln,
};

#[entry]
fn main() -> ! {
hprintln!("Hello from semihosting!");
debug::exit(EXIT_SUCCESS);
loop {}
}
61 changes: 61 additions & 0 deletions riscv-rt/examples/qemu_uart.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//! UART example for QEMU virt machine
Comment thread
KushalMeghani1644 marked this conversation as resolved.
//!
//! This example demonstrates direct UART output on QEMU's virt machine.
//! It writes to the NS16550-compatible UART at 0x1000_0000.

#![no_std]
#![no_main]

extern crate panic_halt;

use riscv_rt::entry;
Comment thread
KushalMeghani1644 marked this conversation as resolved.
use riscv_semihosting::debug::{self, EXIT_SUCCESS};

const UART_BASE: usize = 0x1000_0000;
const UART_THR: usize = UART_BASE;
const UART_IER: usize = UART_BASE + 1;
const UART_FCR: usize = UART_BASE + 2;
const UART_LCR: usize = UART_BASE + 3;
const UART_LSR: usize = UART_BASE + 5;
const LCR_DLAB: u8 = 1 << 7;
const LCR_8N1: u8 = 0x03;
const LSR_THRE: u8 = 1 << 5;

unsafe fn uart_write_reg(off: usize, v: u8) {
(off as *mut u8).write_volatile(v);
}

unsafe fn uart_read_reg(off: usize) -> u8 {
(off as *const u8).read_volatile()
}

fn uart_init() {
unsafe {
uart_write_reg(UART_LCR, LCR_DLAB);
uart_write_reg(UART_THR, 0x01);
uart_write_reg(UART_IER, 0x00);
uart_write_reg(UART_LCR, LCR_8N1);
uart_write_reg(UART_FCR, 0x07);
}
}

fn uart_write_byte(b: u8) {
unsafe {
while (uart_read_reg(UART_LSR) & LSR_THRE) == 0 {}
uart_write_reg(UART_THR, b);
}
}

fn uart_write_str(s: &str) {
for &b in s.as_bytes() {
uart_write_byte(b);
}
}

#[entry]
fn main() -> ! {
uart_init();
uart_write_str("Hello from UART!\n");
debug::exit(EXIT_SUCCESS);
loop {}
Comment thread
KushalMeghani1644 marked this conversation as resolved.
}
4 changes: 3 additions & 1 deletion riscv-rt/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,8 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
/// The argument of the macro must be a path to a variant of an enum that implements the `riscv_rt::CoreInterruptNumber` trait.
///
/// If the `v-trap` feature is enabled, this macro generates the corresponding interrupt trap handler in assembly.
/// This feature relies on the `RISCV_RT_BASE_ISA` environment variable being set to one of
/// `rv32i`, `rv32e`, `rv64i`, or `rv64e`. Otherwise, this will **panic**.
///
/// # Example
///
Expand All @@ -795,7 +797,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn core_interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
let arch = match () {
#[cfg(feature = "v-trap")]
() => RiscvArch::try_from_env(),
() => Some(RiscvArch::try_from_env().expect("RISCV_RT_BASE_ISA must be defined")),
#[cfg(not(feature = "v-trap"))]
() => None,
};
Expand Down
2 changes: 1 addition & 1 deletion riscv-rt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@
//! fn main() {
//! unsafe {
//! let heap_bottom = riscv_rt::heap_start() as usize;
//! let heap_size = &_heap_size as *const u8 as usize;
//! let heap_size = core::ptr::addr_of!(_heap_size) as usize;
//! some_allocator::initialize(heap_bottom, heap_size);
//! }
//! }
Expand Down
1 change: 1 addition & 0 deletions riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added

- Add `vstopi` CSR
- Add `dcsratch0` and `dscratch1` CSRs
- Add new `read-write_csr_as_usize` macro for registers
- Add `dpc` CSR support for RISC-V
Expand Down
1 change: 1 addition & 0 deletions riscv/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub mod sepc;
pub mod sip;
pub mod sscratch;
pub mod stval;
pub mod vstopi;

// Supervisor Protection and Translation
pub mod satp;
Expand Down
69 changes: 69 additions & 0 deletions riscv/src/register/vstopi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//! vstopi register — Virtual Supervisor Top Priority Interrupt (0xEB0)

read_only_csr! {
/// Virtual Supervisor Top Priority Interrupt Register
Vstopi: 0xEB0,
mask: 0x0FFF_00FF,
}

read_only_csr_field! {
Vstopi,
/// Interrupt ID (bits 16..27)
///
/// Identifies the specific interrupt source. A value of 0 indicates no interrupt is pending.
/// Non-zero values correspond to specific interrupt sources as defined by the interrupt controller.
iid: [16:27],
}

read_only_csr_field! {
Vstopi,
/// Interrupt Priority ID (bits 0..7)
///
/// Represents the priority level of the pending interrupt.
/// Lower numerical values indicate higher priority interrupts.
iprio: [0:7],
}

impl Vstopi {
/// Returns true if there is a valid interrupt pending
///
/// When this returns true, both `interrupt_id()` and `priority()` will return meaningful values.
#[inline]
pub fn is_interrupt_pending(&self) -> bool {
self.iid() != 0
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_vstopi_fields() {
let vstopi = Vstopi::from_bits(0);
test_ro_csr_field!(vstopi, iid: [16, 27], 0x0);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x0);

let vstopi = Vstopi::from_bits((0xB << 16) | 5);
test_ro_csr_field!(vstopi, iid: [16, 27], 0xB);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x5);

let vstopi = Vstopi::from_bits((0xFFF << 16) | 0xFF);
test_ro_csr_field!(vstopi, iid: [16, 27], 0xFFF);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0xFF);

let vstopi = Vstopi::from_bits(1 << 16);
test_ro_csr_field!(vstopi, iid: [16, 27], 0x1);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x0);

let vstopi = Vstopi::from_bits(1);
test_ro_csr_field!(vstopi, iid: [16, 27], 0x0);
test_ro_csr_field!(vstopi, iprio: [0, 7], 0x1);
}

#[test]
fn test_vstopi_bitmask() {
let vstopi = Vstopi::from_bits(usize::MAX);
assert_eq!(vstopi.bits(), 0x0FFF_00FFusize);
}
}
2 changes: 1 addition & 1 deletion typos.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[default]
extend-ignore-re = ["[Ss][Ii][Ee]", "[Ss][Xx][Ll]", "[.]?useed[.,:]?", "[Ss][Tt][Ii][Pp]"]
extend-ignore-words-re = ["[Pp]endings", "PENDINGS"]
extend-ignore-words-re = ["[Pp]endings", "PENDINGS", "THR", "THRE"]
7 changes: 7 additions & 0 deletions xtask/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "xtask"
version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = "1"
Loading