Skip to content

Commit

Permalink
Cleaning
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 Jun 24, 2024
1 parent 74179b1 commit 1eb612b
Show file tree
Hide file tree
Showing 17 changed files with 115 additions and 196 deletions.
10 changes: 2 additions & 8 deletions hypervisor/patches/linux/6.3-rc4/0002-ace.patch
Original file line number Diff line number Diff line change
Expand Up @@ -614,10 +614,10 @@ index 44a3b06d0593..42f3571361a0 100644
}
diff --git a/arch/riscv/kvm/vcpu_sbi_covh.c b/arch/riscv/kvm/vcpu_sbi_covh.c
new file mode 100644
index 000000000000..84be3d509c1e
index 000000000000..17e8331bb404
--- /dev/null
+++ b/arch/riscv/kvm/vcpu_sbi_covh.c
@@ -0,0 +1,91 @@
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 IBM.
Expand Down Expand Up @@ -667,19 +667,13 @@ index 000000000000..84be3d509c1e
+static int kvm_riscv_cove_promote_to_tvm(struct kvm_vcpu *vcpu,
+ unsigned long fdt_address,
+ unsigned long tap_addr) {
+ struct kvm_memory_slot *memslot;
+ int rc;
+
+ preload_pages(vcpu);
+ rc = kvm_riscv_cove_vm_single_step_init(vcpu, fdt_address, tap_addr);
+ if (rc)
+ goto done;
+
+ memslot = search_memslots(kvm_memslots(vcpu->kvm),
+ kernel_map.phys_addr, true);
+ if (memslot)
+ kvm_arch_flush_shadow_memslot(vcpu->kvm, memslot);
+
+ vcpu->kvm->arch.vm_type = KVM_VM_TYPE_RISCV_COVE;
+done:
+ return rc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl AllowExternalInterrupt {

pub fn handle(self, confidential_flow: ConfidentialFlow) -> ! {
match ControlDataStorage::try_confidential_vm(confidential_flow.confidential_vm_id(), |mut confidential_vm| {
Ok(confidential_vm.set_allowed_external_interrupts(self.interrupt_id))
Ok(confidential_vm.allow_external_interrupt(self.interrupt_id))
}) {
Ok(_) => confidential_flow
.set_resumable_operation(ResumableOperation::SbiRequest())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ impl MmioStoreRequest {
let mtval = confidential_hart.csrs().mtval.read();
let mtval2 = confidential_hart.csrs().mtval2.read();

// According to the RISC-V privilege spec, mtinst encodes faulted instruction (bit 0 is 1) or a pseudo instruction
// According to the RISC-V privilege spec, mtinst encodes faulted instruction when bit 0 is 1.
// Otherwise it is a pseudo instruction.
assert!(mtinst & 0x1 > 0);
let instruction = mtinst | 0x3;
let instruction_length = if is_bit_enabled(mtinst, 1) { riscv_decode::instruction_length(instruction as u16) } else { 2 };
Expand Down
7 changes: 1 addition & 6 deletions security-monitor/src/core/architecture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,5 @@ pub mod riscv;

#[inline]
pub fn is_bit_enabled(register_value: usize, bit_index: usize) -> bool {
are_bits_enabled(register_value, 1 << bit_index)
}

#[inline]
pub fn are_bits_enabled(register_value: usize, bit_mask: usize) -> bool {
register_value & bit_mask > 0
register_value & (1 << bit_index) > 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,6 @@ pub fn decode_result_register(mtinst: usize) -> Result<GeneralPurposeRegister, E
Err(Error::InvalidCompressedRiscvInstruction(mtinst))
}
}
}?;
Ok(GeneralPurposeRegister::from_index(register_index as usize).ok_or(Error::InvalidCompressedRiscvInstruction(mtinst))?)
}? as usize;
Ok(GeneralPurposeRegister::try_from(register_index).map_err(|_| Error::InvalidCompressedRiscvInstruction(mtinst))?)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use alloc::vec::Vec;
use core::ops::Range;

#[repr(C)]
pub struct GeneralPurposeRegisters(pub [usize; Self::LEN]);
pub struct GeneralPurposeRegisters([usize; Self::LEN]);

impl GeneralPurposeRegisters {
const LEN: usize = 32;
Expand All @@ -15,16 +15,12 @@ impl GeneralPurposeRegisters {
Self([0; Self::LEN])
}

pub fn clone(&self) -> Self {
Self(Self::iter().map(|x| self.0[x]).collect::<Vec<_>>().try_into().unwrap_or([0; Self::LEN]))
}

pub fn write(&mut self, register: GeneralPurposeRegister, value: usize) {
self.0[register.index()] = value;
self.0[Into::<usize>::into(register)] = value;
}

pub fn read(&self, register: GeneralPurposeRegister) -> usize {
self.0[register.index()]
self.0[Into::<usize>::into(register)]
}

/// Extends the measurement digest with the context of all GPRs.
Expand Down Expand Up @@ -79,46 +75,49 @@ pub enum GeneralPurposeRegister {
t6,
}

impl GeneralPurposeRegister {
pub fn index(self) -> usize {
impl Into<usize> for GeneralPurposeRegister {
fn into(self) -> usize {
self as usize
}
}

pub fn from_index(index: usize) -> Option<Self> {
match index {
0 => Some(GeneralPurposeRegister::zero),
1 => Some(GeneralPurposeRegister::ra),
2 => Some(GeneralPurposeRegister::sp),
3 => Some(GeneralPurposeRegister::gp),
4 => Some(GeneralPurposeRegister::tp),
5 => Some(GeneralPurposeRegister::t0),
6 => Some(GeneralPurposeRegister::t1),
7 => Some(GeneralPurposeRegister::t2),
8 => Some(GeneralPurposeRegister::s0),
9 => Some(GeneralPurposeRegister::s1),
10 => Some(GeneralPurposeRegister::a0),
11 => Some(GeneralPurposeRegister::a1),
12 => Some(GeneralPurposeRegister::a2),
13 => Some(GeneralPurposeRegister::a3),
14 => Some(GeneralPurposeRegister::a4),
15 => Some(GeneralPurposeRegister::a5),
16 => Some(GeneralPurposeRegister::a6),
17 => Some(GeneralPurposeRegister::a7),
18 => Some(GeneralPurposeRegister::s2),
19 => Some(GeneralPurposeRegister::s3),
20 => Some(GeneralPurposeRegister::s4),
21 => Some(GeneralPurposeRegister::s5),
22 => Some(GeneralPurposeRegister::s6),
23 => Some(GeneralPurposeRegister::s7),
24 => Some(GeneralPurposeRegister::s8),
25 => Some(GeneralPurposeRegister::s9),
26 => Some(GeneralPurposeRegister::s10),
27 => Some(GeneralPurposeRegister::s11),
28 => Some(GeneralPurposeRegister::t3),
29 => Some(GeneralPurposeRegister::t4),
30 => Some(GeneralPurposeRegister::t5),
31 => Some(GeneralPurposeRegister::t6),
_ => None,
impl TryFrom<usize> for GeneralPurposeRegister {
type Error = crate::error::Error;
fn try_from(value: usize) -> Result<Self, Self::Error> {
match value {
0 => Ok(GeneralPurposeRegister::zero),
1 => Ok(GeneralPurposeRegister::ra),
2 => Ok(GeneralPurposeRegister::sp),
3 => Ok(GeneralPurposeRegister::gp),
4 => Ok(GeneralPurposeRegister::tp),
5 => Ok(GeneralPurposeRegister::t0),
6 => Ok(GeneralPurposeRegister::t1),
7 => Ok(GeneralPurposeRegister::t2),
8 => Ok(GeneralPurposeRegister::s0),
9 => Ok(GeneralPurposeRegister::s1),
10 => Ok(GeneralPurposeRegister::a0),
11 => Ok(GeneralPurposeRegister::a1),
12 => Ok(GeneralPurposeRegister::a2),
13 => Ok(GeneralPurposeRegister::a3),
14 => Ok(GeneralPurposeRegister::a4),
15 => Ok(GeneralPurposeRegister::a5),
16 => Ok(GeneralPurposeRegister::a6),
17 => Ok(GeneralPurposeRegister::a7),
18 => Ok(GeneralPurposeRegister::s2),
19 => Ok(GeneralPurposeRegister::s3),
20 => Ok(GeneralPurposeRegister::s4),
21 => Ok(GeneralPurposeRegister::s5),
22 => Ok(GeneralPurposeRegister::s6),
23 => Ok(GeneralPurposeRegister::s7),
24 => Ok(GeneralPurposeRegister::s8),
25 => Ok(GeneralPurposeRegister::s9),
26 => Ok(GeneralPurposeRegister::s10),
27 => Ok(GeneralPurposeRegister::s11),
28 => Ok(GeneralPurposeRegister::t3),
29 => Ok(GeneralPurposeRegister::t4),
30 => Ok(GeneralPurposeRegister::t5),
31 => Ok(GeneralPurposeRegister::t6),
_ => Err(crate::error::Error::InvalidGprId()),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,7 @@
pub enum HartLifecycleState {
Started,
Stopped,
// StartPending is never used because the security monitor starts the hart directly and only informs a hypervisor
// about it for the bookkeeping purposes.
// StartPending,
//
// StopPending is never used because the security monitor stops the hart directly and only informs a hypervisor
// about it for the bookkeeping purposes.
// StopPending,
Suspended,
//
// SuspendPending is never used because the security monitor stops the hart directly and only informs a hypervisor
// about it for the bookkeeping purposes.
// SuspendPending,
//
// ResumePending is never used because the security monitor stops the hart directly and only informs a hypervisor
// about it for the bookkeeping purposes.
// ResumePending,
//
// PoweredOff state does not exist in the SBI's HSM extension. We use it to represent a confidential hart that has
// been shutdown and cannot be used anymore. When all confidential harts are powered off the confidential VM can be
// removed from the control data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,18 @@ impl NaclSharedMemory {
self.write_at_offset(Self::SCRATCH_SPACE_SIZE + Self::csr_index(csr_code) * core::mem::size_of::<usize>(), value);
}

pub fn gpr(&self, gpr: GeneralPurposeRegister) -> usize {
self.read_at_offset(core::mem::size_of::<usize>() * gpr.index())
pub fn gpr(&self, register: GeneralPurposeRegister) -> usize {
self.read_at_offset(core::mem::size_of::<usize>() * Into::<usize>::into(register))
}

pub fn write_gpr(&self, gpr: GeneralPurposeRegister, value: usize) {
self.write_at_offset(core::mem::size_of::<usize>() * gpr.index(), value);
pub fn write_gpr(&self, register: GeneralPurposeRegister, value: usize) {
self.write_at_offset(core::mem::size_of::<usize>() * Into::<usize>::into(register), value);
}

pub fn gprs(&self) -> GeneralPurposeRegisters {
let mut gprs = GeneralPurposeRegisters::empty();
GeneralPurposeRegisters::iter().for_each(|index| {
let gpr = GeneralPurposeRegister::from_index(index).unwrap();
let gpr = GeneralPurposeRegister::try_from(index).unwrap();
let value = self.gpr(gpr);
gprs.write(gpr, value);
});
Expand Down
3 changes: 3 additions & 0 deletions security-monitor/src/core/architecture/riscv/specification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ pub const STVEC_MODE_VECTORED: usize = 0b11;
pub const CSR_FFLAGS: u16 = 0x1;
pub const CSR_FRM: u16 = 0x2;
pub const CSR_FCSR: u16 = 0x3;

pub const CSR_VSTART: u16 = 0x8;
pub const CSR_VXSAT: u16 = 0x9;
pub const CSR_VXRM: u16 = 0xa;
pub const CSR_VCSR: u16 = 0xf;

pub const CSR_SEED: u16 = 0x15;
pub const CSR_CYCLE: u16 = 0xc00;
pub const CSR_TIME: u16 = 0xc01;
Expand Down Expand Up @@ -342,6 +344,7 @@ pub const CSR_MHPMCOUNTER28H: u16 = 0xb9c;
pub const CSR_MHPMCOUNTER29H: u16 = 0xb9d;
pub const CSR_MHPMCOUNTER30H: u16 = 0xb9e;
pub const CSR_MHPMCOUNTER31H: u16 = 0xb9f;

pub const CAUSE_MISALIGNED_FETCH: u8 = 0x0;
pub const CAUSE_FETCH_ACCESS: u8 = 0x1;
pub const CAUSE_ILLEGAL_INSTRUCTION: u8 = 0x2;
Expand Down
11 changes: 6 additions & 5 deletions security-monitor/src/core/control_data/confidential_hart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ impl ConfidentialHart {
self.id
}

// Returns the id of the hardware hart executing the confidential hart.
pub fn hardware_hart_id(&self) -> Option<usize> {
self.confidential_vm_id.map_or_else(|| Some(self.id), |_| None)
}

pub fn gprs(&self) -> &GeneralPurposeRegisters {
self.confidential_hart_state.gprs()
}
Expand Down Expand Up @@ -280,21 +285,17 @@ impl ConfidentialHart {
pub fn transition_from_stopped_to_started(&mut self, start_address: usize, opaque: usize) -> Result<(), Error> {
ensure_not!(self.is_dummy(), Error::HartAlreadyRunning())?;
ensure!(self.lifecycle_state == HartLifecycleState::Stopped, Error::CannotStartNotStoppedHart())?;
let confidential_hart_id = self.id;

// Let's set up the confidential hart initial state so that it can be run
self.lifecycle_state = HartLifecycleState::Started;

// Following the SBI documentation of the function `hart start` in the HSM extension, only vsatp, vsstatus.SIE,
// a0, a1 have defined values, all other registers are in an undefined state. The hart will start
// executing in the supervisor mode with disabled MMU (vsatp=0).
self.confidential_hart_state.csrs_mut().vsatp.save_value_in_main_memory(0);
// start the new confidential hart with interrupts disabled
self.confidential_hart_state.csrs_mut().mstatus.disable_bit_on_saved_value(CSR_MSTATUS_SPIE);
self.confidential_hart_state.csrs_mut().mstatus.disable_bit_on_saved_value(CSR_MSTATUS_MPIE);

self.confidential_hart_state.csrs_mut().vsstatus.disable_bit_on_saved_value(CSR_STATUS_SIE);
self.confidential_hart_state.gprs_mut().write(GeneralPurposeRegister::a0, confidential_hart_id);
self.confidential_hart_state.gprs_mut().write(GeneralPurposeRegister::a0, self.id);
self.confidential_hart_state.gprs_mut().write(GeneralPurposeRegister::a1, opaque);
self.confidential_hart_state.csrs_mut().mepc.save_value_in_main_memory(start_address);
Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::core::control_data::ConfidentialHart;
/// Represents a command that must be executed on a confidential hart. Typically this is an inter hart request that was sent from one
/// confidential hart (sender) to another confidential hart (receiver), both sender and receiver belong to the same confidential VM.
/// However, there might also be commands that are originating from the hypervisor (e.g., injection of an external interrupt). All these
/// command preserve the same semantics: they originate from the outside of the hart, the receiver might be currently running or not. If the
/// receiver hart is running, it is interrupted (IPI) and executes the command. If the hart is not running, the command is buffered and
/// command preserve the same semantics: they originate from the outside of the hart and the receiver might be currently running or not. If
/// the receiver hart is running, it is interrupted (IPI) and executes the command. If the hart is not running, the command is buffered and
/// executed on the next time the receiver is scheduled to run.
#[derive(Clone)]
pub enum ConfidentialHartRemoteCommand {
Expand Down
Loading

0 comments on commit 1eb612b

Please sign in to comment.