Skip to content

Commit 8247d52

Browse files
authored
Unify ACE and OpenSBI hart state to get rid of unnecessary memory load/store when delegating calls to OpenSBI (#84)
Signed-off-by: Wojciech Ozga <[email protected]>
1 parent e380242 commit 8247d52

File tree

11 files changed

+48
-130
lines changed

11 files changed

+48
-130
lines changed

security-monitor/src/confidential_flow/finite_state_machine.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,14 +216,8 @@ impl<'a> ConfidentialFlow<'a> {
216216
pub fn broadcast_remote_command(
217217
&mut self, confidential_vm: &mut ConfidentialVm, confidential_hart_remote_command: ConfidentialHartRemoteCommand,
218218
) -> Result<(), Error> {
219-
// Hack: For the time-being, we rely on the OpenSBI's implementation of physical IPIs. To use OpenSBI functions we
220-
// must set the mscratch register to the value expected by OpenSBI. We do it here, because we have access to the `HardwareHart`
221-
// that knows the original value of the mscratch expected by OpenSBI.
222-
self.hardware_hart.swap_mscratch();
223-
let result = confidential_vm.broadcast_remote_command(confidential_hart_remote_command);
224-
// We must revert the content of mscratch back to the value expected by our context switched.
225-
self.hardware_hart.swap_mscratch();
226-
result
219+
// For the time-being, we rely on the OpenSBI's implementation of broadcasting IPIs to hardware harts.
220+
self.hardware_hart.opensbi_context(|| confidential_vm.broadcast_remote_command(confidential_hart_remote_command))
227221
}
228222

229223
/// Processes pending requests from other confidential harts by applying the corresponding state transformation to

security-monitor/src/core/architecture/riscv/control_status_registers.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,19 @@ use crate::core::control_data::{DigestType, MeasurementDigest};
1111
use core::arch::asm;
1212

1313
/// Represents all control status registers (CSRs) accessible to modes less privileged than M-mode.
14+
#[repr(C)]
1415
pub struct ControlStatusRegisters {
1516
pub mepc: ReadWriteRiscvCsr<CSR_MEPC>,
17+
pub mstatus: ReadWriteRiscvCsr<CSR_MSTATUS>,
18+
// Safety: Architectural hart state must be bitwise equal to corresponding OpenSBI structure.
19+
// For that reason, this structure is layouted according to C convention and it starts
20+
// with mepc and mstatus. When updating to new version of OpenSBI, make sure that
21+
// CSRs' order in this structure is correct.
1622
pub mcause: ReadWriteRiscvCsr<CSR_MCAUSE>,
1723
pub medeleg: ReadWriteRiscvCsr<CSR_MEDELEG>,
1824
pub mideleg: ReadWriteRiscvCsr<CSR_MIDELEG>,
1925
pub mie: ReadWriteRiscvCsr<CSR_MIE>,
2026
pub mip: ReadRiscvCsr<CSR_MIP>,
21-
pub mstatus: ReadWriteRiscvCsr<CSR_MSTATUS>,
2227
pub mtinst: ReadWriteRiscvCsr<CSR_MTINST>,
2328
pub mtval: ReadWriteRiscvCsr<CSR_MTVAL>,
2429
pub mtval2: ReadWriteRiscvCsr<CSR_MTVAL2>,
@@ -71,12 +76,12 @@ impl ControlStatusRegisters {
7176
pub fn empty() -> Self {
7277
let mut csrs = Self {
7378
mepc: ReadWriteRiscvCsr::new(),
79+
mstatus: ReadWriteRiscvCsr::new(),
7480
mcause: ReadWriteRiscvCsr::new(),
7581
medeleg: ReadWriteRiscvCsr::new(),
7682
mideleg: ReadWriteRiscvCsr::new(),
7783
mie: ReadWriteRiscvCsr::new(),
7884
mip: ReadRiscvCsr::new(),
79-
mstatus: ReadWriteRiscvCsr::new(),
8085
mtinst: ReadWriteRiscvCsr::new(),
8186
mtval: ReadWriteRiscvCsr::new(),
8287
mtval2: ReadWriteRiscvCsr::new(),
@@ -127,11 +132,11 @@ impl ControlStatusRegisters {
127132

128133
pub fn save_in_main_memory(&mut self) {
129134
self.mepc.save_in_main_memory();
135+
self.mstatus.save_in_main_memory();
130136
self.mcause.save_in_main_memory();
131137
self.medeleg.save_in_main_memory();
132138
self.mideleg.save_in_main_memory();
133139
self.mie.save_in_main_memory();
134-
self.mstatus.save_in_main_memory();
135140
self.mtinst.save_in_main_memory();
136141
self.mtval.save_in_main_memory();
137142
self.mtval2.save_in_main_memory();
@@ -182,11 +187,11 @@ impl ControlStatusRegisters {
182187

183188
pub fn restore_from_main_memory(&self) {
184189
self.mepc.restore_from_main_memory();
190+
self.mstatus.restore_from_main_memory();
185191
self.mcause.restore_from_main_memory();
186192
self.medeleg.restore_from_main_memory();
187193
self.mideleg.restore_from_main_memory();
188194
self.mie.restore_from_main_memory();
189-
self.mstatus.restore_from_main_memory();
190195
self.mtinst.restore_from_main_memory();
191196
self.mtval.restore_from_main_memory();
192197
self.mtval2.restore_from_main_memory();

security-monitor/src/core/control_data/hardware_hart.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ impl HardwareHart {
5656
self.previous_mscratch = current_mscratch;
5757
}
5858

59+
pub fn opensbi_context<F>(&mut self, function: F) -> Result<(), crate::error::Error>
60+
where F: FnOnce() -> Result<(), crate::error::Error> {
61+
self.swap_mscratch();
62+
let result = function();
63+
self.swap_mscratch();
64+
result
65+
}
66+
5967
pub fn confidential_hart(&self) -> &ConfidentialHart {
6068
&self.confidential_hart
6169
}

security-monitor/src/core/control_data/hypervisor_hart.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ impl HypervisorHart {
109109
&self.hypervisor_hart_state
110110
}
111111

112+
pub fn hypervisor_hart_state_mut(&mut self) -> &mut HartArchitecturalState {
113+
&mut self.hypervisor_hart_state
114+
}
115+
112116
pub fn shared_memory(&self) -> &NaclSharedMemory {
113117
&self.shared_memory
114118
}

security-monitor/src/non_confidential_flow/apply_to_hypervisor.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22
// SPDX-FileContributor: Wojciech Ozga <[email protected]>, IBM Research - Zurich
33
// SPDX-License-Identifier: Apache-2.0
44
use crate::non_confidential_flow::handlers::nested_acceleration_extension::NaclSetupSharedMemory;
5-
use crate::non_confidential_flow::handlers::opensbi::DelegateToOpensbi;
65
use crate::non_confidential_flow::handlers::supervisor_binary_interface::SbiResponse;
76

87
/// Transformation of the hypervisor state created as a result of processing an SBI request from the hypervisor.
98
pub enum ApplyToHypervisorHart {
109
SbiResponse(SbiResponse),
11-
OpenSbiResponse(DelegateToOpensbi),
1210
SetSharedMemory(NaclSetupSharedMemory),
1311
}

security-monitor/src/non_confidential_flow/finite_state_machine.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,19 @@ use crate::non_confidential_flow::handlers::cove_host_extension::{
1515
DestroyConfidentialVm, GetSecurityMonitorInfo, PromoteToConfidentialVm, RunConfidentialHart,
1616
};
1717
use crate::non_confidential_flow::handlers::nested_acceleration_extension::{NaclProbeFeature, NaclSetupSharedMemory};
18-
use crate::non_confidential_flow::handlers::opensbi::{DelegateToOpensbi, ProbeSbiExtension};
19-
use crate::non_confidential_flow::handlers::supervisor_binary_interface::InvalidCall;
18+
use crate::non_confidential_flow::handlers::supervisor_binary_interface::{InvalidCall, ProbeSbiExtension};
2019
use crate::non_confidential_flow::{ApplyToHypervisorHart, DeclassifyToHypervisor};
20+
use opensbi_sys::sbi_trap_regs;
2121

2222
extern "C" {
2323
/// To ensure safety, specify all possible valid states that KVM expects to see and prove that security monitor
2424
/// never returns to KVM with other state. For example, only a subset of exceptions/interrupts can be handled by KVM.
2525
/// KVM kill the vcpu if it receives unexpected exception because it does not know what to do with it.
2626
fn exit_to_hypervisor_asm() -> !;
27+
28+
/// Currently, we rely on OpenSBI to handle some of the interrupts or exceptions. Below function is the entry point
29+
/// to OpenSBI trap handler.
30+
fn sbi_trap_handler(regs: *mut sbi_trap_regs) -> *mut sbi_trap_regs;
2731
}
2832

2933
/// Represents the non-confidential part of the finite state machine (FSM), implementing router and exit nodes. It encapsulates the
@@ -55,15 +59,9 @@ impl<'a> NonConfidentialFlow<'a> {
5559
// hardware hart's dump area in main memory. This area in main memory is exclusively owned by the physical hart executing this code.
5660
// Specifically, every physical hart has its own are in the main memory and its `mscratch` register stores the address. See the
5761
// `initialization` procedure for more details.
58-
let flow = unsafe { Self::create(hart_ptr.as_mut().expect(Self::CTX_SWITCH_ERROR_MSG)) };
62+
let mut flow = unsafe { Self::create(hart_ptr.as_mut().expect(Self::CTX_SWITCH_ERROR_MSG)) };
5963
match TrapCause::from_hart_architectural_state(flow.hypervisor_hart().hypervisor_hart_state()) {
60-
Interrupt => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
61-
IllegalInstruction => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
62-
LoadAddressMisaligned => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
63-
LoadAccessFault => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
64-
StoreAddressMisaligned => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
65-
StoreAccessFault => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
66-
HsEcall(Base(ProbeExtension)) => ProbeSbiExtension::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
64+
HsEcall(Base(ProbeExtension)) => ProbeSbiExtension::from_hypervisor_hart(flow.hypervisor_hart_mut()).handle(flow),
6765
HsEcall(Covh(TsmGetInfo)) => GetSecurityMonitorInfo::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
6866
HsEcall(Covh(PromoteToTvm)) => PromoteToConfidentialVm::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
6967
HsEcall(Covh(TvmVcpuRun)) => RunConfidentialHart::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
@@ -72,12 +70,21 @@ impl<'a> NonConfidentialFlow<'a> {
7270
HsEcall(Nacl(ProbeFeature)) => NaclProbeFeature::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
7371
HsEcall(Nacl(SetupSharedMemory)) => NaclSetupSharedMemory::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
7472
HsEcall(Nacl(_)) => InvalidCall::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
75-
HsEcall(_) => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
76-
MachineEcall => DelegateToOpensbi::from_hypervisor_hart(flow.hypervisor_hart()).handle(flow),
77-
trap_reason => panic!("Bug: Incorrect interrupt delegation configuration: {:?}", trap_reason),
73+
_ => flow.delegate_to_opensbi(),
7874
}
7975
}
8076

77+
pub fn delegate_to_opensbi(self) -> ! {
78+
// Safety: We play with fire here. We must statically make sure that OpenSBI's input structure is bitwise same as ACE's hart state.
79+
let trap_regs = self.hardware_hart.hypervisor_hart_mut().hypervisor_hart_state_mut() as *mut _ as *mut sbi_trap_regs;
80+
let _ = self.hardware_hart.opensbi_context(|| {
81+
Ok(unsafe {
82+
sbi_trap_handler(trap_regs);
83+
})
84+
});
85+
unsafe { exit_to_hypervisor_asm() }
86+
}
87+
8188
/// Tries to traverse to confidential flow of the finite state machine (FSM). Returns error if the identifier of a confidential VM or
8289
/// hart are incorrect or cannot be scheduled for execution.
8390
pub fn into_confidential_flow(
@@ -113,18 +120,11 @@ impl<'a> NonConfidentialFlow<'a> {
113120
pub(super) fn apply_and_exit_to_hypervisor(mut self, transformation: ApplyToHypervisorHart) -> ! {
114121
match transformation {
115122
ApplyToHypervisorHart::SbiResponse(v) => v.apply_to_hypervisor_hart(self.hypervisor_hart_mut()),
116-
ApplyToHypervisorHart::OpenSbiResponse(v) => v.apply_to_hypervisor_hart(self.hypervisor_hart_mut()),
117123
ApplyToHypervisorHart::SetSharedMemory(v) => v.apply_to_hypervisor_hart(self.hypervisor_hart_mut()),
118124
}
119125
unsafe { exit_to_hypervisor_asm() }
120126
}
121127

122-
/// Swaps the mscratch register value with the original mascratch value used by OpenSBI. This function must be
123-
/// called before executing any OpenSBI function. We can remove this once we get rid of the OpenSBI firmware.
124-
pub fn swap_mscratch(&mut self) {
125-
self.hardware_hart.swap_mscratch()
126-
}
127-
128128
pub fn shared_memory(&self) -> &NaclSharedMemory {
129129
self.hypervisor_hart().shared_memory()
130130
}

security-monitor/src/non_confidential_flow/handlers/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@
33
// SPDX-License-Identifier: Apache-2.0
44
pub mod cove_host_extension;
55
pub mod nested_acceleration_extension;
6-
pub mod opensbi;
76
pub mod supervisor_binary_interface;

security-monitor/src/non_confidential_flow/handlers/opensbi/delegate_to_opensbi.rs

Lines changed: 0 additions & 79 deletions
This file was deleted.

security-monitor/src/non_confidential_flow/handlers/opensbi/mod.rs

Lines changed: 0 additions & 8 deletions
This file was deleted.

security-monitor/src/non_confidential_flow/handlers/supervisor_binary_interface/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// SPDX-FileContributor: Wojciech Ozga <[email protected]>, IBM Research - Zurich
33
// SPDX-License-Identifier: Apache-2.0
44
pub use invalid_call::InvalidCall;
5+
pub use probe_sbi_extension::ProbeSbiExtension;
56
pub use response::SbiResponse;
67

78
mod invalid_call;
9+
mod probe_sbi_extension;
810
mod response;

0 commit comments

Comments
 (0)