Skip to content

Commit

Permalink
fix timer
Browse files Browse the repository at this point in the history
Signed-off-by: Wojciech Ozga <woz@zurich.ibm.com>
  • Loading branch information
wojciechozga committed Jan 26, 2025
1 parent c055a10 commit 6898d7c
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 92 deletions.
57 changes: 2 additions & 55 deletions security-monitor/src/confidential_flow/finite_state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,36 +81,6 @@ impl<'a> ConfidentialFlow<'a> {
ShutdownRequest::from_confidential_hart(flow.confidential_hart()).handle(flow)
}

use crate::core::architecture::specification::*;
// let sie = flow.confidential_hart_mut().csrs_mut().hie.read();
// flow.confidential_hart_mut().csrs_mut().hie.read_and_set_bits(MIE_VSSIP_MASK | MIE_VSTIP_MASK | MIE_VSEIP_MASK);
// flow.confidential_hart_mut().csrs_mut().vstip = flow.confidential_hart().confidential_hart_state().csrs().hip.read();

if flow.confidential_hart().confidential_hart_state().csrs().hvip.read() & MIE_VSSIP_MASK == 0 {
if flow.confidential_hart_mut().csrs_mut().vstip & MIE_VSSIP_MASK > 0 {
flow.confidential_hart_mut().csrs_mut().vstip &= !MIE_VSSIP_MASK;
}
}
// if flow.confidential_hart().confidential_hart_state().csrs().hvip.read() & MIE_VSTIP_MASK == 0 {
// if flow.confidential_hart_mut().csrs_mut().vstip & MIE_VSTIP_MASK > 0 {
flow.confidential_hart_mut().csrs_mut().vstip &= !MIE_VSTIP_MASK;
// }
// }
if flow.confidential_hart().confidential_hart_state().csrs().hvip.read() & MIE_VSEIP_MASK == 0 {
if flow.confidential_hart_mut().csrs_mut().vstip & MIE_VSEIP_MASK > 0 {
flow.confidential_hart_mut().csrs_mut().vstip &= !MIE_VSEIP_MASK;
}
}
// debug!(
// "mepc={:x} hip={:x} hie={:x} vsie={:x} IE={:x}",
// flow.confidential_hart_mut().csrs_mut().mepc.read_from_main_memory(),
// flow.confidential_hart().confidential_hart_state().csrs().hip.read(),
// flow.confidential_hart().confidential_hart_state().csrs().hie.read(),
// flow.confidential_hart().confidential_hart_state().csrs().vsie.read(),
// flow.confidential_hart().confidential_hart_state().csrs().vsstatus.read() & 0x100010,
// );
// flow.confidential_hart_mut().csrs_mut().hie.write(sie);

match TrapCause::from_hart_architectural_state(flow.confidential_hart().confidential_hart_state()) {
Interrupt => HandleInterrupt::from_confidential_hart(flow.confidential_hart()).handle(flow),
IllegalInstruction => DelegateToConfidentialVm::from_confidential_hart(flow.confidential_hart()).handle(flow),
Expand Down Expand Up @@ -253,33 +223,10 @@ impl<'a> ConfidentialFlow<'a> {
// We must restore the control and status registers (CSRs) that might have changed during execution of the security monitor.
// We call it here because it is just before exiting to the assembly context switch, so we are sure that these CSRs have their
// final values.
let interrupts = (self.confidential_hart().csrs().hvip.read_from_main_memory()
| self.confidential_hart().csrs().vsip.read_from_main_memory()
| self.confidential_hart().csrs().vstip)
let interrupts = (self.confidential_hart().csrs().hvip.read_from_main_memory() | self.confidential_hart().csrs().vstip)
& self.confidential_hart().csrs().allowed_external_interrupts;

use crate::core::architecture::specification::*;

self.confidential_hart().csrs().hvip.write(interrupts);
let address = self.confidential_hart_mut().address();

use crate::core::architecture::specification::*;
// if self.confidential_hart().csrs().vsstatus.read() & 0x10 > 0 {
let i2 = interrupts & (self.confidential_hart().csrs().vsie.read() << 1);
self.confidential_hart().csrs().hvip.write(i2);
// debug!("exit_to_confidential_hart with VSTIP {:x}", interrupts);
// self.confidential_hart_mut().csrs_mut().vstip = 0;
// }
// debug!(
// "exit_to_confidential_hart with VSTIP {:x} vsip={:x} vsip={:x}",
// interrupts,
// self.confidential_hart().csrs().vsip.read(),
// self.confidential_hart().csrs().vsie.read()
// );

if self.confidential_hart_mut().csrs_mut().hvip.read() & MIE_VSTIP_MASK > 0 {
debug!("inject timer");
}

self.confidential_hart().csrs().sscratch.write(address);
unsafe { exit_to_confidential_hart_asm() }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ pub struct ExposeEnabledInterrupts {

impl ExposeEnabledInterrupts {
pub fn from_confidential_hart(confidential_hart: &ConfidentialHart) -> Self {
Self { vsie: confidential_hart.csrs().vsie.read(), vstimecmp: confidential_hart.csrs().vstimecmp }
Self {
vsie: confidential_hart.csrs().vsie.read(),
vstimecmp: confidential_hart.csrs().vstimecmp, // vstimecmp: confidential_hart.sstc().vstimecmp.read(),
}
}

pub fn declassify_to_hypervisor_hart(&self, hypervisor_hart: &mut HypervisorHart) {
// if self.vstimecmp < usize::MAX - 1 {
// debug!("self.vstimecmp reflected to hypervisor {:x}", self.vstimecmp);
// }
hypervisor_hart.shared_memory_mut().write_csr(CSR_VSIE.into(), self.vsie);
hypervisor_hart.shared_memory_mut().write_csr(CSR_VSTIMECMP.into(), self.vstimecmp);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,12 @@ impl HandleInterrupt {
// confidential_flow.confidential_hart_mut().csrs().mepc.read_from_main_memory()
// );
if self.pending_interrupts & MIE_SSIP_MASK > 0 {
// // debug!("MIE_SSIP_MASK");
// // // One of the reasons why the confidential hart was interrupted with SSIP is that it got an
// // `ConfidentialHartRemoteCommand` from // another confidential hart. If this is the case, we must process all
// // queued requests before resuming confidential // hart's execution. This is done as part of the procedure that
// // resumes confidential hart execution.
// One of the reasons why the confidential hart was interrupted with SSIP is that it got an `ConfidentialHartRemoteCommand` from
// another confidential hart. If this is the case, we must process all queued requests before resuming confidential hart's execution.
// This is done as part of the procedure that resumes confidential hart execution.
confidential_flow.confidential_hart_mut().csrs_mut().mip.read_and_clear_bits(MIE_SSIP_MASK);
confidential_flow.resume_confidential_hart_execution();
} else if self.pending_interrupts & MIE_MTIP_MASK > 0 {
} else if self.pending_interrupts & MIE_MTIP_MASK > 0 || self.pending_interrupts & MIE_VSTIP_MASK > 0 {
let stimecmp = confidential_flow.confidential_hart_mut().csrs_mut().stimecmp;
let is_vstip = TimerController::try_write(|controller| {
let mtime = controller.read_mtime();
Expand All @@ -47,12 +46,11 @@ impl HandleInterrupt {
Ok(report_vs_interrupt)
})
.unwrap_or(false);
// if is_vstip {
// debug!("handle interrupt VSTIP");
// confidential_flow.resume_confidential_hart_execution();
// } else {
confidential_flow.into_non_confidential_flow().declassify_and_exit_to_hypervisor(DeclassifyToHypervisor::Interrupt(self))
// }
if is_vstip {
confidential_flow.resume_confidential_hart_execution();
} else {
confidential_flow.into_non_confidential_flow().declassify_and_exit_to_hypervisor(DeclassifyToHypervisor::Interrupt(self))
}
} else {
// The only interrupts that we can see here are:
// * M-mode timer that the security monitor set to preemt execution of a confidential VM
Expand Down
17 changes: 13 additions & 4 deletions security-monitor/src/core/control_data/confidential_hart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,28 @@ pub struct ConfidentialHart {
impl ConfidentialHart {
/// Configuration of RISC-V exceptions for confidential hart
const EXCEPTION_DELEGATION: usize = (1 << CAUSE_MISALIGNED_FETCH)
| (1 << CAUSE_ILLEGAL_INSTRUCTION)
| (1 << 1)
| (1 << 2)
| (1 << 3)
| (1 << 4)
| (1 << 5)
| (1 << 6)
| (1 << 7)
| (1 << CAUSE_BREAKPOINT)
| (1 << CAUSE_STORE_ACCESS)
| (1 << CAUSE_USER_ECALL)
| (1 << CAUSE_FETCH_PAGE_FAULT)
| (1 << CAUSE_LOAD_PAGE_FAULT)
| (1 << CAUSE_STORE_PAGE_FAULT);
const INITIAL_MSTATUS: usize =
((1 << CSR_MSTATUS_MPV) | (1 << CSR_MSTATUS_MPP) | (1 << CSR_MSTATUS_SIE) | (1 << CSR_MSTATUS_SPIE)) & !(1 << CSR_MSTATUS_MPIE);
const INITIAL_HSTATUS: usize = (1 << CSR_HSTATUS_VTW) | (1 << CSR_HSTATUS_SPVP) | (1 << CSR_HSTATUS_UXL);
((1 << CSR_MSTATUS_MPV) | (1 << CSR_MSTATUS_MPP) | (1 << CSR_MSTATUS_SIE) | (1 << CSR_MSTATUS_SPIE) | (1 << CSR_SSTATUS_FS))
& !(1 << CSR_MSTATUS_MPIE);
const INITIAL_HSTATUS: usize = (1 << CSR_HSTATUS_VTW) | (1 << CSR_HSTATUS_SPVP) | (1 << CSR_HSTATUS_UXL) | (1 << CSR_SSTATUS_FS);
const INITIAL_SSTATUS: usize = (1 << CSR_SSTATUS_SPIE) | (1 << CSR_SSTATUS_UXL);
/// Configuration of delegation of RISC-V interrupts that will trap directly in the confidential hart. All other interrupts will trap in
/// the security monitor.
const INTERRUPT_DELEGATION: usize = MIE_VSSIP_MASK | MIE_VSTIP_MASK | MIE_VSEIP_MASK;
const INTERRUPT_DELEGATION: usize = MIE_VSSIP_MASK | MIE_VSTIP_MASK | MIE_VSEIP_MASK | 1 << 12;

/// Constructs a dummy hart. This dummy hart carries no confidential information. It is used to indicate that a real
/// confidential hart has been assigned to a hardware hart for execution. A dummy confidential hart has the id of the hardware hart it
Expand Down Expand Up @@ -88,7 +97,7 @@ impl ConfidentialHart {
// the `vsie` register reflects `hie`, so we set up `hie` allowing only VS-level interrupts
confidential_hart_state.csrs_mut().hie.save_value_in_main_memory(Self::INTERRUPT_DELEGATION);
// Allow only hypervisor's timer interrupts to preemt confidential VM's execution
confidential_hart_state.csrs_mut().mie.save_value_in_main_memory(MIE_STIP_MASK | MIE_MTIP_MASK);
confidential_hart_state.csrs_mut().mie.save_value_in_main_memory(MIE_STIP_MASK | MIE_MTIP_MASK | MIE_SSIP_MASK);
confidential_hart_state.csrs_mut().htimedelta.save_value_in_main_memory(htimedelta);
// Setup the M-mode trap handler to the security monitor's entry point
confidential_hart_state.csrs_mut().mtvec.save_value_in_main_memory(enter_from_confidential_hart_asm as usize);
Expand Down
23 changes: 7 additions & 16 deletions security-monitor/src/core/timer_controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ impl<'a> TimerController {
}

pub fn set_next_event_for_vs_mode(&mut self, confidential_flow: &mut ConfidentialFlow, ncycle: usize) {
// let old_timer = self.read_m_timer(confidential_flow);
let stimecmp = confidential_flow.confidential_hart_mut().csrs_mut().stimecmp;
let vstimecmp = confidential_flow.confidential_hart_mut().csrs_mut().vstimecmp;

debug!("set timer time={:x} new={:x} s={:x} vs={:x}", self.read_mtime(), ncycle, stimecmp, vstimecmp);
confidential_flow.confidential_hart_mut().csrs_mut().vstimecmp = ncycle;
if self.is_vs_timer_running(confidential_flow) {
self.set_vs_timer(confidential_flow, ncycle);
Expand Down Expand Up @@ -61,10 +56,10 @@ impl<'a> TimerController {
vstimecmp > 0 && mtime >= vstimecmp
}

pub fn handle_vs_interrupt(&mut self, mut confidential_flow: &mut ConfidentialFlow) {
debug!("Inject VSTIP");
pub fn handle_vs_interrupt(&mut self, confidential_flow: &mut ConfidentialFlow) {
// debug!("Inject VSTIP");
confidential_flow.confidential_hart_mut().csrs_mut().vstip |= MIE_VSTIP_MASK;
confidential_flow.confidential_hart_mut().csrs_mut().vstimecmp = usize::MAX - 1;
// confidential_flow.confidential_hart_mut().csrs_mut().vstimecmp = usize::MAX - 1;
}

pub fn store_vs_timer(&mut self, confidential_flow: &mut ConfidentialFlow) {
Expand Down Expand Up @@ -110,27 +105,23 @@ impl<'a> TimerController {
pub fn set_vs_timer(&self, confidential_flow: &mut ConfidentialFlow, ncycle: usize) {
// debug!("Restore VS timer {:x}", ncycle);
self.set_m_timer(confidential_flow, ncycle);
confidential_flow.confidential_hart_mut().csrs_mut().mip.read_and_clear_bits(MIE_VSTIP_MASK);
confidential_flow.confidential_hart_mut().csrs_mut().mie.read_and_set_bits(MIE_MTIP_MASK);
confidential_flow.confidential_hart_mut().csrs_mut().mie.read_and_set_bits(MIE_VSTIP_MASK);
confidential_flow.confidential_hart_mut().csrs_mut().vstip &= !MIE_VSTIP_MASK;
confidential_flow.confidential_hart_mut().csrs_mut().mip.read_and_clear_bits(MIE_MTIP_MASK);
}

pub fn set_s_timer(&self, confidential_flow: &mut ConfidentialFlow, ncycle: usize) {
// debug!("Restore S timer {:x}", ncycle);
self.set_m_timer(confidential_flow, ncycle);
confidential_flow.confidential_hart_mut().csrs_mut().mip.read_and_clear_bits(MIE_STIP_MASK);
confidential_flow.confidential_hart_mut().csrs_mut().mie.read_and_set_bits(MIE_MTIP_MASK);
confidential_flow.confidential_hart_mut().csrs_mut().mie.read_and_set_bits(MIE_STIP_MASK);
confidential_flow.confidential_hart_mut().csrs_mut().mip.read_and_clear_bits(MIE_MTIP_MASK);
}

pub fn read_mtime(&self) -> usize {
CSR.time.read()
}

fn read_m_timer(&self, confidential_flow: &mut ConfidentialFlow) -> usize {
let mut m_timer = 0;
confidential_flow.swap_mscratch();
m_timer = (unsafe { sbi_timer_value() }) as usize;
let m_timer = (unsafe { sbi_timer_value() }) as usize;
confidential_flow.swap_mscratch();
m_timer
}
Expand Down
2 changes: 1 addition & 1 deletion tools/ace_run_hypervisor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ echo "Number of cores assigned to the guest: ${SMP}"
${QEMU_CMD} ${DEBUG_OPTIONS} \
-m ${MEMORY} \
${INTERACTIVE} \
-machine virt -cpu rv64,sstc=false \
-machine virt -cpu rv64,sstc=false,f=true \
-bios none \
-kernel ${KERNEL} \
-global virtio-mmio.force-legacy=false \
Expand Down

0 comments on commit 6898d7c

Please sign in to comment.