Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ jenkins/__pycache__
jenkins-cli.jar
tools/kconfig/.venv/
tools/kconfig/__pycache__/
kernel_build/
kernel_build/
*.cpio.gz
*.cpio
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ test-pre: download-test-img
chmod +x platform/$(ARCH)/$(BOARD)/test/runner.sh
@echo "added execute permission to test runner.sh for board $(BOARD)"

fmt-test: all
cargo fmt --all -- --check
@echo "cargo fmt check passed!"

fmt: all
cargo fmt --all
@echo "your code has been formatted"
Expand Down
58 changes: 58 additions & 0 deletions platform/riscv64/qemu-plic/configs/zone1-asterinas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"arch": "riscv",
"name": "asterinas",
"zone_id": 1,
"cpus": [
2
],
"memory_regions": [
{
"type": "ram",
"physical_start": "0x80200000",
"virtual_start": "0x80200000",
"size": "0x10000000"
},
{
"type": "io",
"physical_start": "0x10000000",
"virtual_start": "0x10000000",
"size": "0x100"
},
{
"type": "io",
"physical_start": "0x10007000",
"virtual_start": "0x10007000",
"size": "0x1000"
},
{
"type": "ram",
"physical_start": "0x87e00000",
"virtual_start": "0x87e00000",
"size": "0x00200000"
}
],
"interrupts": [
7,
10
],
"ivc_configs": [],
"kernel_filepath": "./asterinas.bin",
"dtb_filepath": "./zone1-asterinas.dtb",
"kernel_load_paddr": "0x84000000",
"dtb_load_paddr": "0x83000000",
"entry_point": "0x84000000",
"modules": [
{
"name": "initramfs",
"filepath": "./initramfs.cpio.gz",
"load_paddr": "0x87e00000"
}
],
"arch_config": {
"plic_base": "0xc000000",
"plic_size": "0x600000"
},
"pci_config": [],
"num_pci_devs": 0,
"alloc_pci_devs": []
}
94 changes: 94 additions & 0 deletions platform/riscv64/qemu-plic/image/dts/zone1-asterinas.dts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/dts-v1/;

/ {
#address-cells = <0x2>;
#size-cells = <0x2>;
model = "asterinas,dummy-virt";
compatible = "asterinas,dummy-virt";

cpus {
#address-cells = <0x1>;
#size-cells = <0x0>;
timebase-frequency = <10000000>;

cpu@2 {
device_type = "cpu";
reg = <0x2>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcsu_sstc";
mmu-type = "riscv,sv48";

cpu2_intc: interrupt-controller {
#interrupt-cells = <0x1>;
interrupt-controller;
compatible = "riscv,cpu-intc";
};
};
};

memory@80200000 {
device_type = "memory";
reg = <0x0 0x80200000 0x0 0x10000000>;
};

reserved-memory {
#address-cells = <0x02>;
#size-cells = <0x02>;
ranges;

opensbi+hvisor@80000000 {
no-map;
reg = <0x00 0x80000000 0x00 0x05000000>;
};

dtbfile@83000000 {
no-map;
reg = <0x00 0x83000000 0x00 0x01000000>;
};

initramfs@87e00000 {
no-map;
reg = <0x00 0x87e00000 0x00 0x00200000>;
};
};

soc {
#address-cells = <0x02>;
#size-cells = <0x02>;
compatible = "simple-bus";
ranges;

plic: interrupt-controller@c000000 {
phandle = <0x03>;
riscv,ndev = <0x5f>;
reg = <0x00 0xc000000 0x00 0x600000>;
interrupts-extended = <&cpu2_intc 11 &cpu2_intc 9>;
interrupt-controller;
compatible = "riscv,plic0";
#interrupt-cells = <0x1>;
};

uart@10000000 {
interrupts = <0x0a>;
interrupt-parent = <&plic>;
clock-frequency = "\08@";
reg = <0x00 0x10000000 0x00 0x100>;
compatible = "ns16550a";
};

virtio_mmio@10007000 {
interrupts = <0x07>;
interrupt-parent = <&plic>;
reg = <0x00 0x10007000 0x00 0x1000>;
compatible = "virtio,mmio";
};
};

chosen {
bootargs = "init=/init console=ttyS0 ostd.log_level=debug";
stdout-path = "serial0:115200n8";
linux,initrd-start = <0x00 0x87e00000>;
linux,initrd-end = <0x00 0x88000000>;
};
};
11 changes: 7 additions & 4 deletions platform/riscv64/qemu-plic/platform.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ FSIMG2 := $(image_dir)/virtdisk/rootfs2.ext4
HVISOR_ENTRY_PA := 0x80200000
zone0_kernel := $(image_dir)/kernel/Image
zone0_dtb := $(image_dir)/dts/zone0.dtb
# zone1_kernel := $(image_dir)/kernel/Image
# zone1_dtb := $(image_dir)/devicetree/linux.dtb
# zone1 (Asterinas) images
# All zone1 images (kernel, dtb, initramfs) are loaded by hvisor-tool from zone0
# See zone1-asterinas.json for the modules configuration
zone1_kernel := $(image_dir)/kernel/asterinas.bin
zone1_dtb := $(image_dir)/dts/zone1-asterinas.dtb

QEMU_ARGS := -machine virt,aclint=on # ,iommu-sys=on # -d trace:*iommu*
QEMU_ARGS += -bios default
Expand All @@ -20,8 +23,8 @@ QEMU_ARGS += -nographic
QEMU_ARGS += -kernel $(hvisor_bin)
QEMU_ARGS += -device loader,file="$(zone0_kernel)",addr=0x90000000,force-raw=on
QEMU_ARGS += -device loader,file="$(zone0_dtb)",addr=0x8f000000,force-raw=on
# QEMU_ARGS += -device loader,file="$(zone1_kernel)",addr=0x84000000,force-raw=on
# QEMU_ARGS += -device loader,file="$(zone1_dtb)",addr=0x83000000,force-raw=on
# zone1 images (kernel, dtb, initramfs) are all loaded by hvisor-tool from zone0
# See zone1-asterinas.json for the modules configuration

QEMU_ARGS += -drive if=none,file=$(FSIMG1),id=hd0,format=raw
# QEMU_ARGS += -device virtio-blk-device,drive=hd0,bus=virtio-mmio-bus.7
Expand Down
6 changes: 3 additions & 3 deletions src/arch/riscv64/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl ArchCpu {
//self.sepc = guest_test as usize as u64;
write_csr!(CSR_SSCRATCH, self as *const _ as usize); //arch cpu pointer
self.sepc = entry;
self.hstatus = 1 << 7 | 2 << 32; // HSTATUS_SPV | HSTATUS_VSXL_64
self.hstatus = 1 << 7 | 2 << 32 | 1 << 56; // HSTATUS_SPV | HSTATUS_VSXL_64 | HSTATUS_SPVTW
#[cfg(aia)]
{
self.hstatus |= 1 << 12; // HSTATUS_VGEIN
Expand All @@ -83,12 +83,12 @@ impl ArchCpu {
if self.sstc {
// hvisor doesn't handle timer interrupt.
set_csr!(CSR_STIMECMP, usize::MAX);
set_csr!(CSR_HENVCFG, 1 << 63);
set_csr!(CSR_HENVCFG, 1 << 63 | 1 << 61); // STCE | ADUE (enable hardware A/D bit update for guest)
set_csr!(CSR_VSTIMECMP, usize::MAX);
} else {
// In megrez board, this instruction is not supported. (illegal instruction)
#[cfg(not(hypervisor_v0_6))]
set_csr!(CSR_HENVCFG, 0);
set_csr!(CSR_HENVCFG, 1 << 61); // ADUE (enable hardware A/D bit update for guest)
}
set_csr!(CSR_HCOUNTEREN, 1 << 1); // HCOUNTEREN_TM
// In VU-mode, a counter is not readable unless the applicable bits are set in both hcounteren and scounteren.
Expand Down
82 changes: 81 additions & 1 deletion src/arch/riscv64/sbi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,24 @@ use sbi_spec::{base, hsm, legacy, rfnc, spi, time};
// Reserved for hvisor-tool.
pub const EID_HVISOR: usize = 0x114514;

// SBI Debug Console Extension (DBCN)
pub const EID_DBCN: usize = 0x4442434E;
pub const DBCN_CONSOLE_WRITE_BYTE: usize = 2;

// SBI System Reset Extension (SRST)
pub const EID_SRST: usize = 0x53525354;
pub const SRST_SYSTEM_RESET: usize = 0;

// Hvisor supported SBI extensions.
pub const NUM_EXT: usize = 6;
pub const NUM_EXT: usize = 8;
pub const EXT_TABLE: [usize; NUM_EXT] = [
base::EID_BASE,
time::EID_TIME,
hsm::EID_HSM,
spi::EID_SPI,
rfnc::EID_RFNC,
EID_DBCN,
EID_SRST,
EID_HVISOR,
];

Expand Down Expand Up @@ -91,6 +101,14 @@ pub fn sbi_vs_handler(current_cpu: &mut ArchCpu) {
EID_HVISOR => {
sbi_ret = sbi_hvisor_handler(current_cpu);
}
// Debug Console Extension (DBCN)
EID_DBCN => {
sbi_ret = sbi_dbcn_handler(fid, current_cpu);
}
// System Reset Extension (SRST)
EID_SRST => {
sbi_ret = sbi_srst_handler(fid, current_cpu);
}
// Note: hvisor don't suggest to use Legacy Extension.
// But for compatibility, we still support some legacy SBI calls.
// Legacy::Console putchar (usually used), temporily don't support other legacy extensions.
Expand Down Expand Up @@ -366,3 +384,65 @@ pub fn sbi_hvisor_handler(current_cpu: &mut ArchCpu) -> SbiRet {
}
}
}

/// SBI Debug Console Extension handler.
/// Directly writes to UART hardware to avoid recursive SBI traps.
pub fn sbi_dbcn_handler(fid: usize, current_cpu: &mut ArchCpu) -> SbiRet {
match fid {
DBCN_CONSOLE_WRITE_BYTE => {
let byte = current_cpu.x[10] as u8;
// Directly write to UART hardware (QEMU virt 16550 at 0x10000000)
const UART0_BASE: usize = 0x1000_0000;
unsafe {
core::ptr::write_volatile(UART0_BASE as *mut u8, byte);
}
SbiRet {
error: RET_SUCCESS,
value: 1, // 1 byte written
}
}
_ => SbiRet {
error: RET_ERR_NOT_SUPPORTED,
value: 0,
},
}
}

/// SBI System Reset Extension handler.
/// Handles guest system reset requests (shutdown/reboot).
pub fn sbi_srst_handler(fid: usize, current_cpu: &mut ArchCpu) -> SbiRet {
if fid != SRST_SYSTEM_RESET {
return SbiRet {
error: RET_ERR_NOT_SUPPORTED,
value: 0,
};
}
let reset_type = current_cpu.x[10] as u32;
let reset_reason = current_cpu.x[11] as u32;
info!(
"SBI SRST: system_reset type={}, reason={}",
reset_type, reset_reason
);
// Use sbi_rt to perform the actual system reset.
// reset_type: 0 = shutdown, 1 = cold reboot, 2 = warm reboot
// reset_reason: 0 = none, 1 = failure, 2 = system failure
use sbi_rt::{ColdReboot, NoReason, Shutdown, SystemFailure, WarmReboot};
let result = match (reset_type, reset_reason) {
(0, 0) => sbi_rt::system_reset(Shutdown, NoReason),
(0, 1) => sbi_rt::system_reset(Shutdown, SystemFailure),
(1, 0) => sbi_rt::system_reset(ColdReboot, NoReason),
(1, 1) => sbi_rt::system_reset(ColdReboot, SystemFailure),
(2, 0) => sbi_rt::system_reset(WarmReboot, NoReason),
(2, 1) => sbi_rt::system_reset(WarmReboot, SystemFailure),
_ => {
return SbiRet {
error: RET_ERR_NOT_SUPPORTED,
value: 0,
}
}
};
SbiRet {
error: result.error,
value: result.value,
}
}
25 changes: 25 additions & 0 deletions src/arch/riscv64/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// Authors:
//
use super::cpu::ArchCpu;
use super::csr::*;
use crate::arch::sbi::sbi_vs_handler;
#[cfg(plic)]
use crate::device::irqchip::plic::{inject_irq, plic_get_hwirq};
Expand All @@ -39,6 +40,7 @@ interrupts_arch_handle=sym interrupts_arch_handle);
pub mod ExceptionType {
pub const ECALL_VU: usize = 8;
pub const ECALL_VS: usize = 10;
pub const INSTRUCTION_GUEST_PAGE_FAULT: usize = 20;
pub const LOAD_GUEST_PAGE_FAULT: usize = 21;
pub const STORE_GUEST_PAGE_FAULT: usize = 23;
}
Expand Down Expand Up @@ -135,6 +137,29 @@ pub fn sync_exception_handler(current_cpu: &mut ArchCpu) {
sbi_vs_handler(current_cpu);
current_cpu.sepc += 4; // For ecall, skip the ecall instruction.
}
ExceptionType::INSTRUCTION_GUEST_PAGE_FAULT => {
trace!("INSTRUCTION_GUEST_PAGE_FAULT");
// When guest hasn't set up its trap vector (vtvec=0), a timer interrupt
// can cause guest to jump to 0x0, leading to instruction page fault.
// Recover by disabling the timer interrupt and resuming from VSEPC.
let guest_vtvec = read_csr!(CSR_VSTVEC);
if guest_vtvec == 0 {
let vsepc = read_csr!(CSR_VSEPC);
warn!(
"Guest trapped to 0x0 (vtvec=0), VSEPC={:#x}. \
Disabling VSTIMECMP and resuming.",
vsepc
);
write_csr!(CSR_VSTIMECMP, usize::MAX);
unsafe {
hvip::clear_vstip();
sie::clear_stimer();
}
current_cpu.sepc = vsepc;
return;
}
guest_page_fault_handler(current_cpu);
}
ExceptionType::LOAD_GUEST_PAGE_FAULT => {
trace!("LOAD_GUEST_PAGE_FAULT");
guest_page_fault_handler(current_cpu);
Expand Down
Loading