Skip to content

Commit 75c710f

Browse files
Merge pull request #378 from KushalMeghani1644/add-qemu-ci-v2
Add QEMU CI support
2 parents f669c67 + 5873f97 commit 75c710f

File tree

12 files changed

+330
-1
lines changed

12 files changed

+330
-1
lines changed

.github/workflows/qemu.yaml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: QEMU tests
2+
on:
3+
merge_group:
4+
pull_request:
5+
push:
6+
branches:
7+
- master
8+
9+
env:
10+
CARGO_TERM_COLOR: always
11+
12+
jobs:
13+
testexamples:
14+
name: QEMU run
15+
runs-on: ubuntu-24.04
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
toolchain: [stable]
20+
target-qemu:
21+
- target: riscv32i-unknown-none-elf
22+
qemu: riscv32
23+
- target: riscv32im-unknown-none-elf
24+
qemu: riscv32
25+
- target: riscv32imc-unknown-none-elf
26+
qemu: riscv32
27+
- target: riscv32imac-unknown-none-elf
28+
qemu: riscv32
29+
- target: riscv32imafc-unknown-none-elf
30+
qemu: riscv32
31+
- target: riscv64imac-unknown-none-elf
32+
qemu: riscv64
33+
- target: riscv64gc-unknown-none-elf
34+
qemu: riscv64
35+
example:
36+
- qemu_uart
37+
- qemu_semihosting
38+
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@v4
42+
43+
- name: Configure Rust target ${{ matrix.target-qemu.target }}
44+
run: |
45+
rustup toolchain install ${{ matrix.toolchain }}
46+
rustup default ${{ matrix.toolchain }}
47+
rustup target add ${{ matrix.target-qemu.target }}
48+
49+
- name: Cache Dependencies
50+
uses: Swatinem/rust-cache@v2
51+
52+
- name: Install QEMU
53+
run: |
54+
sudo apt update
55+
sudo apt install -y qemu-system-${{ matrix.target-qemu.qemu }}
56+
57+
- name: Run-pass tests
58+
run: cargo run --package xtask -- qemu --target ${{ matrix.target-qemu.target }} --example ${{ matrix.example }}
59+

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ members = [
1111
"riscv-types",
1212
"tests-build",
1313
"tests-trybuild",
14+
"xtask",
1415
]
1516

1617
default-members = [

ci/expected/qemu_semihosting.run

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello from semihosting!

ci/expected/qemu_uart.run

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello from UART!

riscv-rt/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Added
1111

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

riscv-rt/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ defmt = { version = "1.0.1", optional = true }
3232

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

3638
[features]
3739
pre-init = []

riscv-rt/examples/device_virt.x

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
MEMORY
2+
{
3+
RAM : ORIGIN = 0x80000000, LENGTH = 16M
4+
}
5+
REGION_ALIAS("REGION_TEXT", RAM);
6+
REGION_ALIAS("REGION_RODATA", RAM);
7+
REGION_ALIAS("REGION_DATA", RAM);
8+
REGION_ALIAS("REGION_BSS", RAM);
9+
REGION_ALIAS("REGION_HEAP", RAM);
10+
REGION_ALIAS("REGION_STACK", RAM);
11+
INCLUDE link.x
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//! Semihosting example for QEMU
2+
//!
3+
//! This example uses RISC-V semihosting to print output and cleanly exit QEMU.
4+
//! Run with: `qemu-system-riscv32 -machine virt -nographic -semihosting-config enable=on,target=native -bios none -kernel <binary>`
5+
6+
#![no_std]
7+
#![no_main]
8+
9+
extern crate panic_halt;
10+
11+
use riscv_rt::entry;
12+
use riscv_semihosting::{
13+
debug::{self, EXIT_SUCCESS},
14+
hprintln,
15+
};
16+
17+
#[entry]
18+
fn main() -> ! {
19+
hprintln!("Hello from semihosting!");
20+
debug::exit(EXIT_SUCCESS);
21+
loop {}
22+
}

riscv-rt/examples/qemu_uart.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//! UART example for QEMU virt machine
2+
//!
3+
//! This example demonstrates direct UART output on QEMU's virt machine.
4+
//! It writes to the NS16550-compatible UART at 0x1000_0000.
5+
6+
#![no_std]
7+
#![no_main]
8+
9+
extern crate panic_halt;
10+
11+
use riscv_rt::entry;
12+
use riscv_semihosting::debug::{self, EXIT_SUCCESS};
13+
14+
const UART_BASE: usize = 0x1000_0000;
15+
const UART_THR: usize = UART_BASE;
16+
const UART_IER: usize = UART_BASE + 1;
17+
const UART_FCR: usize = UART_BASE + 2;
18+
const UART_LCR: usize = UART_BASE + 3;
19+
const UART_LSR: usize = UART_BASE + 5;
20+
const LCR_DLAB: u8 = 1 << 7;
21+
const LCR_8N1: u8 = 0x03;
22+
const LSR_THRE: u8 = 1 << 5;
23+
24+
unsafe fn uart_write_reg(off: usize, v: u8) {
25+
(off as *mut u8).write_volatile(v);
26+
}
27+
28+
unsafe fn uart_read_reg(off: usize) -> u8 {
29+
(off as *const u8).read_volatile()
30+
}
31+
32+
fn uart_init() {
33+
unsafe {
34+
uart_write_reg(UART_LCR, LCR_DLAB);
35+
uart_write_reg(UART_THR, 0x01);
36+
uart_write_reg(UART_IER, 0x00);
37+
uart_write_reg(UART_LCR, LCR_8N1);
38+
uart_write_reg(UART_FCR, 0x07);
39+
}
40+
}
41+
42+
fn uart_write_byte(b: u8) {
43+
unsafe {
44+
while (uart_read_reg(UART_LSR) & LSR_THRE) == 0 {}
45+
uart_write_reg(UART_THR, b);
46+
}
47+
}
48+
49+
fn uart_write_str(s: &str) {
50+
for &b in s.as_bytes() {
51+
uart_write_byte(b);
52+
}
53+
}
54+
55+
#[entry]
56+
fn main() -> ! {
57+
uart_init();
58+
uart_write_str("Hello from UART!\n");
59+
debug::exit(EXIT_SUCCESS);
60+
loop {}
61+
}

typos.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[default]
22
extend-ignore-re = ["[Ss][Ii][Ee]", "[Ss][Xx][Ll]", "[.]?useed[.,:]?", "[Ss][Tt][Ii][Pp]"]
3-
extend-ignore-words-re = ["[Pp]endings", "PENDINGS"]
3+
extend-ignore-words-re = ["[Pp]endings", "PENDINGS", "THR", "THRE"]

0 commit comments

Comments
 (0)