Skip to content

Commit 521c500

Browse files
authored
Support RISC-V 64-bit architecture (riscv64) for AXVisor to boot ArceOS (#66)
* feat: support riscv64 axvisor * feat: refactor IRQ handling and update memory configurations for RISC-V platform
1 parent e7595a2 commit 521c500

25 files changed

Lines changed: 320 additions & 70 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ axstd = { version = "=0.3.0-preview.3", features = [
7171
"smp",
7272
"hv",
7373
]}
74+
axhal = { version = "=0.3.0-preview.3", features = ["paging", "irq", "smp", "hv"] }
7475

7576
# System dependent modules provided by ArceOS-Hypervisor (bare-metal only)
7677
axaddrspace = "0.3.0"
@@ -122,7 +123,9 @@ aarch64-cpu-ext = "0.1"
122123
arm-gic-driver = {version = "0.17", features = ["rdif"]}
123124

124125
[target.'cfg(target_arch = "riscv64")'.dependencies]
125-
axplat-riscv64-qemu-virt = "0.3.1-pre.6"
126+
axplat-riscv64-qemu-virt = { path = "platform/riscv64-qemu-virt" }
127+
riscv_vcpu = "0.3"
128+
riscv_vplic = "0.2.2"
126129

127130
# xtask dependencies (only used on host platforms)
128131
[target.'cfg(any(windows, unix))'.dependencies]

configs/vms/arceos-riscv64-qemu-smp1.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ dtb_load_addr = 0x8220_0000
4040
# Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`).
4141
# For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`.
4242
memory_regions = [
43-
[0x8000_0000, 0x800_0000, 0x7, 0], # System RAM 1G MAP_ALLOC
43+
[0x8000_0000, 0x400_0000, 0x7, 0], # System RAM 64M MAP_ALLOC
4444
]
4545

4646
#

doc/qemu-quickstart.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ After booting, you will enter the Rust user shell (`>>` prompt). Type `usertests
110110

111111
> **Note**: NimbOS requires VT-x/KVM. If `/dev/kvm` does not exist or has insufficient permissions, you will get a `Permission denied` error. WSL2 requires nested virtualization support in the kernel to use KVM.
112112
113+
### ArceOS (RISC-V64)
114+
115+
```bash
116+
./scripts/setup_qemu.sh arceos-riscv64
117+
118+
cargo xtask qemu \
119+
--build-config configs/board/qemu-riscv64.toml \
120+
--qemu-config .github/workflows/qemu-riscv64.toml \
121+
--vmconfigs tmp/vmconfigs/arceos-riscv64-qemu-smp1.generated.toml
122+
```
123+
124+
Success indicator: `Hello, world!` appears in the output.
125+
126+
`qemu-riscv64` currently supports the RISC-V ArceOS guest path. Cross-ISA boot such as `riscv64 AxVisor -> aarch64 ArceOS` is not wired up in the current hypervisor stack.
127+
113128
## 5. What Does setup_qemu.sh Do?
114129

115130
The script automates three steps, eliminating manual work:

doc/qemu-quickstart_cn.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ cargo xtask qemu \
110110

111111
> **注意**:NimbOS 依赖 VT-x/KVM。如果 `/dev/kvm` 不存在或权限不足,会报 `Permission denied` 错误。WSL2 需要内核支持嵌套虚拟化才能使用 KVM。
112112
113+
### ArceOS(RISC-V64)
114+
115+
```bash
116+
./scripts/setup_qemu.sh arceos-riscv64
117+
118+
cargo xtask qemu \
119+
--build-config configs/board/qemu-riscv64.toml \
120+
--qemu-config .github/workflows/qemu-riscv64.toml \
121+
--vmconfigs tmp/vmconfigs/arceos-riscv64-qemu-smp1.generated.toml
122+
```
123+
124+
启动成功标志:输出中出现 `Hello, world!`
125+
126+
当前 `qemu-riscv64` 这条快速启动链路支持的是 RISC-V 版 ArceOS Guest。像 `riscv64 AxVisor -> aarch64 ArceOS` 这样的跨 ISA 启动,在现有 hypervisor 栈里还没有接通。
127+
113128
## 5. setup_qemu.sh 做了什么
114129

115130
该脚本自动完成以下三步,省去手动操作:

platform/riscv64-qemu-virt/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ sbi-rt = { version = "0.0.3", features = ["legacy"] }
2424
uart_16550 = "0.4.0"
2525

2626
axconfig-macros = "0.2"
27-
axcpu = { version = "0.3.0-preview.8", features = ["arm-el2"] }
28-
axplat = "0.3.1-pre.6"
27+
axcpu = { workspace = true }
28+
axplat = { workspace = true }
2929
axvisor_api = "0.3"
30-
crate_interface = "0.3"
30+
crate_interface = { workspace = true }
3131

3232
[package.metadata.docs.rs]
3333
targets = ["riscv64gc-unknown-none-elf"]

platform/riscv64-qemu-virt/axconfig.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ package = "axplat-riscv64-qemu-virt" # str
99
# Platform configs
1010
#
1111
[plat]
12-
# Number of CPUs.
13-
cpu-num = 4 # uint
12+
# Maximum number of CPUs.
13+
max-cpu-num = 4 # uint
1414
# Base address of the whole physical memory.
1515
phys-memory-base = 0x8000_0000 # uint
16-
# Size of the whole physical memory. (8GB)
17-
phys-memory-size = 0x1_0000_0000 # uint
16+
# Size of the whole physical memory. (128M)
17+
phys-memory-size = 0x800_0000 # uint
1818
# Base physical address of the kernel image.
1919
kernel-base-paddr = 0x8020_0000 # uint
2020
# Base virtual address of the kernel image.
@@ -102,4 +102,4 @@ plic-paddr = 0x0c00_0000 # uint
102102
# compatible = "ns16550a";
103103
# };
104104
uart-paddr = 0x1000_0000 # uint
105-
uart-irq = 0x0a # uint
105+
uart-irq = 0x0a # uint

platform/riscv64-qemu-virt/src/boot.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ static mut BOOT_STACK: [u8; BOOT_STACK_SIZE] = [0; BOOT_STACK_SIZE];
77
#[unsafe(link_section = ".data")]
88
static mut BOOT_PT_SV39: Aligned4K<[u64; 512]> = Aligned4K::new([0; 512]);
99

10+
const DTB_HEADER_MAGIC: u32 = 0xd00d_feed;
11+
const DTB_TOTAL_SIZE_OFFSET: usize = 4;
12+
const DTB_RELOC_BUF_SIZE: usize = 0x40_000;
13+
14+
#[unsafe(link_section = ".data")]
15+
static mut DTB_RELOC_BUF: Aligned4K<[u8; DTB_RELOC_BUF_SIZE]> =
16+
Aligned4K::new([0; DTB_RELOC_BUF_SIZE]);
17+
1018
#[allow(clippy::identity_op)] // (0x0 << 10) here makes sense because it's an address
1119
unsafe fn init_boot_page_table() {
1220
unsafe {
@@ -34,11 +42,41 @@ unsafe fn init_mmu() {
3442
}
3543
}
3644

45+
unsafe fn relocate_dtb(dtb_paddr: usize) -> usize {
46+
if dtb_paddr == 0 {
47+
return 0;
48+
}
49+
50+
let header_ptr = dtb_paddr as *const u8;
51+
let magic = unsafe { core::ptr::read_unaligned(header_ptr.cast::<u32>()) };
52+
let total_size =
53+
unsafe { core::ptr::read_unaligned(header_ptr.add(DTB_TOTAL_SIZE_OFFSET).cast::<u32>()) };
54+
55+
let magic = u32::from_be(magic);
56+
let total_size = u32::from_be(total_size) as usize;
57+
58+
assert_eq!(magic, DTB_HEADER_MAGIC, "invalid DTB magic: {magic:#x}");
59+
assert!(
60+
total_size <= DTB_RELOC_BUF_SIZE,
61+
"DTB too large: {total_size:#x} > buffer {DTB_RELOC_BUF_SIZE:#x}"
62+
);
63+
64+
unsafe {
65+
core::ptr::copy_nonoverlapping(
66+
header_ptr,
67+
(&raw mut DTB_RELOC_BUF).cast::<u8>(),
68+
total_size,
69+
);
70+
}
71+
72+
&raw const DTB_RELOC_BUF as usize
73+
}
74+
3775
/// The earliest entry point for the primary CPU.
3876
#[unsafe(naked)]
3977
#[unsafe(no_mangle)]
4078
#[unsafe(link_section = ".text.boot")]
41-
unsafe extern "C" fn _start() -> ! {
79+
unsafe extern fn _start() -> ! {
4280
// PC = 0x8020_0000
4381
// a0 = hartid
4482
// a1 = dtb
@@ -49,6 +87,10 @@ unsafe extern "C" fn _start() -> ! {
4987
li t0, {boot_stack_size}
5088
add sp, sp, t0 // setup boot stack
5189
90+
mv a0, s1
91+
call {relocate_dtb}
92+
mv s1, a0
93+
5294
call {init_boot_page_table}
5395
call {init_mmu} // setup boot page table and enabel MMU
5496
@@ -66,6 +108,7 @@ unsafe extern "C" fn _start() -> ! {
66108
boot_stack = sym BOOT_STACK,
67109
init_boot_page_table = sym init_boot_page_table,
68110
init_mmu = sym init_mmu,
111+
relocate_dtb = sym relocate_dtb,
69112
entry = sym axplat::call_main,
70113
)
71114
}

platform/riscv64-qemu-virt/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub mod config {
3131
}
3232

3333
pub const fn cpu_count() -> usize {
34-
config::plat::CPU_NUM
34+
config::plat::MAX_CPU_NUM
3535
}
3636

3737
pub const fn plic_base() -> usize {

platform/riscv64-qemu-virt/src/power.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,9 @@ impl PowerIf for PowerImpl {
2929
axcpu::asm::halt();
3030
}
3131
}
32+
33+
/// Get the number of CPU cores available on this platform.
34+
fn cpu_num() -> usize {
35+
crate::config::plat::MAX_CPU_NUM
36+
}
3237
}

0 commit comments

Comments
 (0)