Skip to content

Commit

Permalink
Merge pull request #35 from Alignof/develop
Browse files Browse the repository at this point in the history
Ver 0.4.0
  • Loading branch information
Alignof authored Sep 3, 2024
2 parents a6bea58 + 38d0d01 commit 0cfd705
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hikami"
version = "0.3.0"
version = "0.4.0"
edition = "2021"

[lints.clippy]
Expand Down
4 changes: 4 additions & 0 deletions src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod clint;
mod initrd;
mod pci;
mod plic;
mod rtc;
pub mod uart;
mod virtio;

Expand Down Expand Up @@ -50,6 +51,7 @@ pub struct Devices {
pub plic_context: usize,
pub clint: clint::Clint,
pub pci: pci::Pci,
pub rtc: rtc::Rtc,
}

impl Devices {
Expand All @@ -71,6 +73,7 @@ impl Devices {
self.plic.memmap(),
self.clint.memmap(),
self.pci.memmap(),
self.rtc.memmap(),
]);

device_mapping
Expand Down Expand Up @@ -101,6 +104,7 @@ impl HypervisorData {
.value[0] as usize,
clint: clint::Clint::new(&device_tree, "/soc/clint"),
pci: pci::Pci::new(&device_tree, "/soc/pci"),
rtc: rtc::Rtc::new(&device_tree, "/soc/rtc"),
});
}
}
1 change: 1 addition & 0 deletions src/device/plic.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! PLIC: Platform-Level Interrupt Controller
//! ref: [https://github.com/riscv/riscv-plic-spec/releases/download/1.0.0/riscv-plic-1.0.0.pdf](https://github.com/riscv/riscv-plic-spec/releases/download/1.0.0/riscv-plic-1.0.0.pdf)
use super::{Device, PTE_FLAGS_FOR_DEVICE};
use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap};
Expand Down
47 changes: 47 additions & 0 deletions src/device/rtc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//! RTC: Real Time Clock.
use super::{Device, PTE_FLAGS_FOR_DEVICE};
use crate::memmap::{GuestPhysicalAddress, HostPhysicalAddress, MemoryMap};
use fdt::Fdt;

/// RTC: Real Time Clock.
/// An electronic device that measures the passage of time.
#[derive(Debug)]
pub struct Rtc {
base_addr: HostPhysicalAddress,
size: usize,
}

impl Device for Rtc {
fn new(device_tree: &Fdt, node_path: &str) -> Self {
let region = device_tree
.find_node(node_path)
.unwrap()
.reg()
.unwrap()
.next()
.unwrap();

Rtc {
base_addr: HostPhysicalAddress(region.starting_address as usize),
size: region.size.unwrap(),
}
}

fn size(&self) -> usize {
self.size
}

fn paddr(&self) -> HostPhysicalAddress {
self.base_addr
}

fn memmap(&self) -> MemoryMap {
let vaddr = GuestPhysicalAddress(self.paddr().raw());
MemoryMap::new(
vaddr..vaddr + self.size(),
self.paddr()..self.paddr() + self.size(),
&PTE_FLAGS_FOR_DEVICE,
)
}
}
77 changes: 52 additions & 25 deletions src/h_extension/csrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ macro_rules! set_csr_as {
};
}

/// Set CSR bit from enum.
/// Set CSR bit from enum variant.
#[macro_export]
macro_rules! set_csr_from_enum {
($enum: ident, $csr_number:literal) => {
Expand All @@ -74,14 +74,27 @@ macro_rules! set_csr_from_enum {
};
}

/// Clear CSR bit from enum variant.
#[macro_export]
macro_rules! clear_csr_from_enum {
($enum: ident, $csr_number:literal) => {
#[inline]
pub fn clear(field: $enum) {
unsafe{
core::arch::asm!(concat!("csrrc x0, ", stringify!($csr_number), ", {0}"), in(reg) field as usize);
}
}
};
}

/// VS-level interrupt kind.
pub enum InterruptKind {
pub enum VsInterruptKind {
/// VS-level external interrupts (bit 10)
Vsei = 0b100_0000_0000,
External = 0b100_0000_0000,
/// VS-level timer interrupts (bit 6)
Vsti = 0b100_0000,
Timer = 0b100_0000,
/// VS-level software interrupts (bit 2)
Vssi = 0b100,
Software = 0b100,
}

pub mod vstvec {
Expand Down Expand Up @@ -212,17 +225,43 @@ pub mod hideleg {
write_csr_as!(0x603);
}

pub mod hie {
//! Hypervisor interrupt-enable register.
#![allow(dead_code)]
use super::VsInterruptKind;

const HIE: usize = 0x604;
pub struct Hie {
bits: usize,
}

set_csr_from_enum!(VsInterruptKind, 0x604);
}

pub mod hcounteren {
//! Hypervisor counter enable.
#![allow(dead_code)]

const HCOUNTEREN: usize = 0x606;
pub struct Hcounteren {
bits: usize,
}

set_csr_as!(0x606);
}

pub mod hvip {
//! Hypervisor virtual interrupt pending.
#![allow(dead_code)]
use super::InterruptKind;
use super::VsInterruptKind;

const HVIP: usize = 0x645;
pub struct Hvip {
bits: usize,
}

set_csr_from_enum!(InterruptKind, 0x645);
set_csr_from_enum!(VsInterruptKind, 0x645);
clear_csr_from_enum!(VsInterruptKind, 0x645);

read_csr_as!(Hvip, 0x645);
write_csr_as!(0x645);
Expand Down Expand Up @@ -268,8 +307,8 @@ pub mod henvcfg {
unsafe {
core::arch::asm!(
"
csrs henvcfg, {bits}
",
csrs henvcfg, {bits}
",
bits = in(reg) 1u64 << 63
);
}
Expand All @@ -280,8 +319,8 @@ pub mod henvcfg {
unsafe {
core::arch::asm!(
"
csrs henvcfg, {bits}
",
csrs henvcfg, {bits}
",
bits = in(reg) 1u64 << 7
);
}
Expand All @@ -292,22 +331,10 @@ pub mod henvcfg {
unsafe {
core::arch::asm!(
"
csrs henvcfg, {bits}
",
csrs henvcfg, {bits}
",
bits = in(reg) 1u64 << 6
);
}
}
}

pub mod hcounteren {
//! Hypervisor counter enable.
#![allow(dead_code)]

const HCOUNTEREN: usize = 0x606;
pub struct Hcounteren {
bits: usize,
}

set_csr_as!(0x606);
}
27 changes: 16 additions & 11 deletions src/hypervisor_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use crate::device::Device;
use crate::guest::Guest;
use crate::h_extension::csrs::{
hcounteren, hedeleg, hedeleg::ExceptionKind, henvcfg, hgatp, hgatp::HgatpMode, hideleg,
hstatus, hvip, vsatp, InterruptKind,
hcounteren, hedeleg, hedeleg::ExceptionKind, henvcfg, hgatp, hgatp::HgatpMode, hideleg, hie,
hstatus, hvip, vsatp, VsInterruptKind,
};
use crate::h_extension::instruction::hfence_gvma_all;
use crate::memmap::{
Expand All @@ -17,7 +17,7 @@ use crate::{GUEST_DTB, HYPERVISOR_DATA};
use core::arch::asm;

use elf::{endian::AnyEndian, ElfBytes};
use riscv::register::{sepc, sie, sscratch, sstatus, stvec};
use riscv::register::{sepc, sscratch, sstatus, stvec};

/// Entry point to HS-mode.
#[inline(never)]
Expand All @@ -29,11 +29,15 @@ pub extern "C" fn hstart(hart_id: usize, dtb_addr: usize) -> ! {
assert_ne!(dtb_addr, 0);

// clear all hypervisor interrupts.
hvip::write(0);
hvip::clear(VsInterruptKind::External);
hvip::clear(VsInterruptKind::Timer);
hvip::clear(VsInterruptKind::Software);

// disable address translation.
vsatp::write(0);

// disable hypervisor external interrupt

// enable Sstc extention
henvcfg::set_stce();
henvcfg::set_cbze();
Expand All @@ -42,12 +46,11 @@ pub extern "C" fn hstart(hart_id: usize, dtb_addr: usize) -> ! {
// enable hypervisor counter
hcounteren::set(0xffff_ffff);

// set sie = 0x222
unsafe {
sie::set_ssoft();
sie::set_stimer();
sie::set_sext();
}
// set hie = 0x444
// TODO?: trap VS-mode interrupt.
hie::set(VsInterruptKind::External);
hie::set(VsInterruptKind::Timer);
hie::set(VsInterruptKind::Software);

// specify delegation exception kinds.
hedeleg::write(
Expand All @@ -60,7 +63,9 @@ pub extern "C" fn hstart(hart_id: usize, dtb_addr: usize) -> ! {
);
// specify delegation interrupt kinds.
hideleg::write(
InterruptKind::Vsei as usize | InterruptKind::Vsti as usize | InterruptKind::Vssi as usize,
VsInterruptKind::External as usize
| VsInterruptKind::Timer as usize
| VsInterruptKind::Software as usize,
);

vsmode_setup(hart_id, HostPhysicalAddress(dtb_addr));
Expand Down
6 changes: 3 additions & 3 deletions src/trap/hypervisor_supervisor/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use super::hstrap_exit;
use crate::device::Device;
use crate::h_extension::csrs::{hvip, vsip, InterruptKind};
use crate::h_extension::csrs::{hvip, vsip, VsInterruptKind};
use crate::HYPERVISOR_DATA;
use riscv::register::scause::Interrupt;
use riscv::register::sie;
Expand All @@ -21,10 +21,10 @@ pub unsafe fn trap_interrupt(interrupt_cause: Interrupt) -> ! {
interrupt_addr.write_volatile(0);
}
Interrupt::SupervisorTimer => {
hvip::set(InterruptKind::Vsti);
hvip::set(VsInterruptKind::Timer);
sie::clear_stimer();
}
Interrupt::SupervisorExternal => riscv::asm::wfi(), // wait for interrupt
Interrupt::SupervisorExternal => hvip::set(VsInterruptKind::External),
Interrupt::Unknown => panic!("unknown interrupt type"),
}

Expand Down

0 comments on commit 0cfd705

Please sign in to comment.