Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #78

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open

Dev #78

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
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ loongArch64 = "0.2.4"
[features]
platform_qemu = []
platform_imx8mp = []
default = ["aia"]
plic = []
aia = []

[profile.dev]
panic = "abort"
Expand Down
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Basic settings
ARCH ?= aarch64
ARCH ?= riscv64
LOG ?= info
STATS ?= off
PORT ?= 2333
MODE ?= debug
OBJCOPY ?= rust-objcopy --binary-architecture=$(ARCH)
KDIR ?= ../../linux
FEATURES ?= platform_qemu
IRQ ?= plic

ifeq ($(ARCH),aarch64)
RUSTC_TARGET := aarch64-unknown-none
Expand All @@ -33,7 +34,7 @@ image_dir := images/$(ARCH)

# Build arguments
build_args :=
build_args += --features "$(FEATURES)"
build_args += --features "$(FEATURES)"
build_args += --target $(RUSTC_TARGET)
build_args += -Z build-std=core,alloc
build_args += -Z build-std-features=compiler-builtins-mem
Expand Down
171 changes: 171 additions & 0 deletions images/riscv64/devicetree/linux1-aia.dts
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/dts-v1/;

/ {
#address-cells = <0x2>;
#size-cells = <0x2>;

cpus {
#address-cells = <0x1>;
#size-cells = <0x0>;
timebase-frequency = <10000000>;
cpu@0 {
device_type = "cpu";
reg = <0x0>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcsu_ssaia_sstc";
mmu-type = "riscv,sv39";

cpu0_intc: interrupt-controller {
#interrupt-cells = <0x1>;
interrupt-controller;
compatible = "riscv,cpu-intc";
phandle = <0x04>;
};
};
cpu@1 {
device_type = "cpu";
reg = <0x1>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcsu_ssaia_sstc";
mmu-type = "riscv,sv39";

cpu1_intc: interrupt-controller {
#interrupt-cells = <0x1>;
interrupt-controller;
compatible = "riscv,cpu-intc";
};
};
cpu@2 {
device_type = "cpu";
reg = <0x2>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcsu_ssaia_sstc";
mmu-type = "riscv,sv39";

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

memory@83000000 {
device_type = "memory";
reg = <0x0 0x83000000 0x0 0x1D000000>;
};

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

nonroot@0x83000000 {
no-map;
reg = <0x00 0x83000000 0x00 0x0C000000>;
};

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

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

aplic@d000000 {
phandle = <0x08>;
riscv,num-sources = <0x60>;
reg = <0x00 0xd000000 0x00 0x8000>;
msi-parent = <0x06>;
interrupt-controller;
#interrupt-cells = <0x02>;
compatible = "riscv,aplic";
};

imsics@28000000 {
phandle = <0x06>;
riscv,num-ids = <0xff>;
reg = <0x00 0x28000000 0x00 0x4000>;
interrupts-extended = <
&cpu0_intc 9
&cpu1_intc 9
&cpu2_intc 9
>;
msi-controller;
interrupt-controller;
#interrupt-cells = <0x00>;
compatible = "riscv,imsics";
};

virtio_mmio@10008000 {
interrupts = <0x8 0x04>;
interrupt-parent = <0x08>;
reg = <0x0 0x10008000 0x0 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10005000 {
interrupts = <0x5 0x04>;
interrupt-parent = <0x08>;
reg = <0x0 0x10005000 0x0 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10004000 {
interrupts = <0x4 0x04>;
interrupt-parent = <0x08>;
reg = <0x0 0x10004000 0x0 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10003000 {
interrupts = <0x3 0x04>;
interrupt-parent = <0x08>;
reg = <0x0 0x10003000 0x0 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10002000 {
interrupts = <0x2 0x04>;
interrupt-parent = <0x08>;
reg = <0x0 0x10002000 0x0 0x1000>;
compatible = "virtio,mmio";
};
virtio_mmio@10001000 {
interrupts = <0x1 0x04>;
interrupt-parent = <0x08>;
reg = <0x0 0x10001000 0x0 0x1000>;
compatible = "virtio,mmio";
};
pci@30000000 {
interrupt-map-mask = <0x1800 0x00 0x00 0x07>;
interrupt-map = <0x00 0x00 0x00 0x01 0x09 0x20 0x00 0x00 0x00 0x02 0x09 0x21 0x00 0x00 0x00 0x03 0x09 0x22 0x00 0x00 0x00 0x04 0x09 0x23 0x800 0x00 0x00 0x01 0x09 0x21 0x800 0x00 0x00 0x02 0x09 0x22 0x800 0x00 0x00 0x03 0x09 0x23 0x800 0x00 0x00 0x04 0x09 0x20 0x1000 0x00 0x00 0x01 0x09 0x22 0x1000 0x00 0x00 0x02 0x09 0x23 0x1000 0x00 0x00 0x03 0x09 0x20 0x1000 0x00 0x00 0x04 0x09 0x21 0x1800 0x00 0x00 0x01 0x09 0x23 0x1800 0x00 0x00 0x02 0x09 0x20 0x1800 0x00 0x00 0x03 0x09 0x21 0x1800 0x00 0x00 0x04 0x09 0x22>;
ranges = <0x1000000 0x00 0x00 0x00 0x3000000 0x00 0x10000 0x2000000 0x00 0x40000000 0x00 0x40000000 0x00 0x40000000 0x3000000 0x04 0x00 0x04 0x00 0x04 0x00>;
reg = <0x00 0x30000000 0x00 0x10000000>;
dma-coherent;
bus-range = <0x00 0xff>;
linux,pci-domain = <0x00>;
device_type = "pci";
compatible = "pci-host-ecam-generic";
#size-cells = <0x02>;
#interrupt-cells = <0x01>;
#address-cells = <0x03>;
};
uart@10000000 {
interrupts = <0x0a 0x04>;
interrupt-parent = <0x08>;
clock-frequency = "\08@";
reg = <0x00 0x10000000 0x00 0x100>;
compatible = "ns16550a";
};

};
chosen {
bootargs = "root=/dev/vda rw earlycon console=ttyS0 init=/bin/bash";
};

};
16 changes: 14 additions & 2 deletions scripts/qemu-riscv64.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,35 @@ FSIMG1 := $(image_dir)/virtdisk/rootfs1.ext4
FSIMG2 := $(image_dir)/virtdisk/rootfs-busybox.qcow2
# HVISOR ENTRY
HVISOR_ENTRY_PA := 0x80200000
zone0_kernel := $(image_dir)/kernel/Image
zone0_kernel := $(image_dir)/kernel/Image-aia-6.10
zone0_dtb := $(image_dir)/devicetree/linux1.dtb
zone0_aia_dtb := $(image_dir)/devicetree/linux1-aia.dtb
# zone1_kernel := $(image_dir)/kernel/Image
# zone1_dtb := $(image_dir)/devicetree/linux.dtb

QEMU_ARGS := -machine virt
ifeq ($(IRQ),aia)
QEMU_ARGS := -machine virt,aclint=on,aia=aplic-imsic,aia-guests=1
else ifeq ($(IRQ),plic)
QEMU_ARGS := -machine virt
endif
QEMU_ARGS += -bios default
QEMU_ARGS += -cpu rv64
QEMU_ARGS += -smp 4
QEMU_ARGS += -m 2G
QEMU_ARGS += -nographic

QEMU_ARGS += -kernel $(hvisor_bin)
ifeq ($(IRQ),aia)
QEMU_ARGS += -device loader,file="$(zone0_kernel)",addr=0x90000000,force-raw=on
QEMU_ARGS += -device loader,file="$(zone0_aia_dtb)",addr=0x8f000000,force-raw=on
# QEMU_ARGS += -device loader,file="$(zone1_aia_kernel)",addr=0x84000000,force-raw=on
# QEMU_ARGS += -device loader,file="$(zone1_aia_dtb)",addr=0x83000000,force-raw=on
else ifeq ($(IRQ),plic)
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
endif

QEMU_ARGS += -drive if=none,file=$(FSIMG1),id=X10008000,format=raw
QEMU_ARGS += -device virtio-blk-device,drive=X10008000,bus=virtio-mmio-bus.7
Expand Down
2 changes: 1 addition & 1 deletion src/arch/riscv64/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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 << 12; //HSTATUS_SPV | HSTATUS_VSXL_64 | HSTATUS_VGEIN
self.sstatus = 1 << 8 | 1 << 63 | 3 << 13 | 3 << 15; //SPP
self.stack_top = self.stack_top() as usize;
self.x[10] = cpu_id; //cpu id
Expand Down
106 changes: 74 additions & 32 deletions src/arch/riscv64/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use super::cpu::ArchCpu;
use crate::arch::csr::read_csr;
use crate::arch::csr::*;
use crate::arch::sbi::sbi_vs_handler;
#[cfg(feature = "plic")]
use crate::device::irqchip::plic::{host_plic, vplic_global_emul_handler, vplic_hart_emul_handler};
#[cfg(feature = "aia")]
use crate::device::irqchip::aia::aplic::{host_aplic, vaplic_emul_handler};
use crate::event::check_events;
use crate::memory::{GuestPhysAddr, HostPhysAddr};
use crate::platform::qemu_riscv64::*;
Expand Down Expand Up @@ -87,44 +90,78 @@ pub fn sync_exception_handler(current_cpu: &mut ArchCpu) {
pub fn guest_page_fault_handler(current_cpu: &mut ArchCpu) {
let addr: HostPhysAddr = read_csr!(CSR_HTVAL) << 2;
trace!("guest page fault at {:#x}", addr);
let host_plic_base = host_plic().read().base;
let mut ins_size: usize = 0;
//TODO: get plic addr range from dtb or vpliv object
if addr >= host_plic_base && addr < host_plic_base + PLIC_TOTAL_SIZE {
trace!("PLIC access");
let mut inst: u32 = read_csr!(CSR_HTINST) as u32;
if inst == 0 {
let inst_addr: GuestPhysAddr = current_cpu.sepc;
//load real ins from guest memmory
inst = read_inst(inst_addr);
ins_size = if inst & 0x3 == 3 { 4 } else { 2 };
} else if inst == 0x3020 || inst == 0x3000 {
// TODO: we should reinject this in the guest as a fault access
error!("fault on 1st stage page table walk");
#[cfg(feature = "plic")]{
let host_plic_base = host_plic().read().base;
let mut ins_size: usize = 0;
//TODO: get plic addr range from dtb or vpliv object
if addr >= host_plic_base && addr < host_plic_base + PLIC_TOTAL_SIZE {
trace!("PLIC access");
let mut inst: u32 = read_csr!(CSR_HTINST) as u32;
if inst == 0 {
let inst_addr: GuestPhysAddr = current_cpu.sepc;
//load real ins from guest memmory
inst = read_inst(inst_addr);
ins_size = if inst & 0x3 == 3 { 4 } else { 2 };
} else if inst == 0x3020 || inst == 0x3000 {
// TODO: we should reinject this in the guest as a fault access
error!("fault on 1st stage page table walk");
} else {
// If htinst is valid and is not a pseudo instructon make sure
// the opcode is valid even if it was a compressed instruction,
// but before save the real instruction size.
ins_size = if (inst) & 0x2 == 0 { 2 } else { 4 };
inst = inst | 0b10;
// error!("unhandled guest page fault at {:#x}", addr);
// panic!("inst{:#x}", inst);
}
//TODO: decode inst to real instruction
let (_len, inst) = decode_inst(inst);
if let Some(inst) = inst {
if addr >= host_plic_base + PLIC_GLOBAL_SIZE {
vplic_hart_emul_handler(current_cpu, addr, inst);
} else {
vplic_global_emul_handler(current_cpu, addr, inst);
}
current_cpu.sepc += ins_size;
} else {
error!("Invalid instruction at {:#x}", current_cpu.sepc);
panic!();
}
} else {
// If htinst is valid and is not a pseudo instructon make sure
// the opcode is valid even if it was a compressed instruction,
// but before save the real instruction size.
ins_size = if (inst) & 0x2 == 0 { 2 } else { 4 };
inst = inst | 0b10;
// error!("unhandled guest page fault at {:#x}", addr);
// panic!("inst{:#x}", inst);
panic!("CPU {} unmaped memmory at {:#x}", current_cpu.cpuid, addr);
}
//TODO: decode inst to real instruction
let (_len, inst) = decode_inst(inst);
if let Some(inst) = inst {
if addr >= host_plic_base + PLIC_GLOBAL_SIZE {
vplic_hart_emul_handler(current_cpu, addr, inst);
}
#[cfg(feature = "aia")]{
let host_aplic_base = host_aplic().read().base;
let host_aplic_size = host_aplic().read().size;

if addr >= host_aplic_base && addr < host_aplic_base + host_aplic_size {
trace!("APLIC access");
let mut inst: u32 = read_csr!(CSR_HTINST) as u32;
let mut ins_size: usize = 0;
if inst == 0 {
let inst_addr: GuestPhysAddr = current_cpu.sepc;
inst = read_inst(inst_addr);
ins_size = if inst & 0x3 == 3 { 4 } else { 2 };
} else if inst == 0x3020 || inst == 0x3000 {
error!("fault on 1st stage page table walk");
} else {
vplic_global_emul_handler(current_cpu, addr, inst);
ins_size = if (inst) & 0x2 == 0 { 2 } else { 4 };
inst = inst | 0b10;
// error!("unhandled guest page fault at {:#x}", addr);
}
// let (len, inst) = decode_inst(inst);
let (_, inst) = decode_inst(inst);

if let Some(inst) = inst {
vaplic_emul_handler(current_cpu, addr, inst);
current_cpu.sepc += ins_size;
} else {
error!("Invalid instruction at {:#x}", current_cpu.sepc);
}
current_cpu.sepc += ins_size;
} else {
error!("Invalid instruction at {:#x}", current_cpu.sepc);
panic!();
panic!("CPU {} unmaped memmory at {:#x}", current_cpu.cpuid, addr);
}
} else {
panic!("CPU {} unmaped memmory at {:#x}", current_cpu.cpuid, addr);
}
}
fn read_inst(addr: GuestPhysAddr) -> u32 {
Expand Down Expand Up @@ -200,6 +237,7 @@ pub fn interrupts_arch_handle(current_cpu: &mut ArchCpu) {

/// handle interrupt request(current only external interrupt)
pub fn handle_eirq(current_cpu: &mut ArchCpu) {
#[cfg(feature = "plic")]{
// TODO: handle other irq
// check external interrupt && handle
// sifive plic: context0=>cpu0,M mode,context1=>cpu0,S mode...
Expand All @@ -215,6 +253,10 @@ pub fn handle_eirq(current_cpu: &mut ArchCpu) {
host_plic.write().claim_complete[context_id] = irq;
// set external interrupt pending, which trigger guest interrupt
unsafe { hvip::set_vseip() };
}
#[cfg(feature = "aia")]{
panic!("HS extensional interrupt")
}
}
pub fn handle_ssi(current_cpu: &mut ArchCpu) {
trace!("handle_ssi");
Expand Down
Loading