@@ -31,6 +31,7 @@ use crate::core::control_data::{
3131 ConfidentialHart , ConfidentialHartRemoteCommand , ConfidentialVm , ConfidentialVmId , ControlDataStorage , HardwareHart , HypervisorHart ,
3232 ResumableOperation ,
3333} ;
34+ use crate :: core:: interrupt_controller:: InterruptController ;
3435use crate :: error:: Error ;
3536use crate :: non_confidential_flow:: { DeclassifyToHypervisor , NonConfidentialFlow } ;
3637
@@ -118,11 +119,18 @@ impl<'a> ConfidentialFlow<'a> {
118119 hardware_hart : & ' a mut HardwareHart , confidential_vm_id : ConfidentialVmId , confidential_hart_id : usize ,
119120 ) -> Result < ( usize , Self ) , ( & ' a mut HardwareHart , Error ) > {
120121 assert ! ( hardware_hart. confidential_hart( ) . is_dummy( ) ) ;
121- match ControlDataStorage :: try_confidential_vm ( confidential_vm_id, |mut confidential_vm| {
122+ // Now, we are going to change the context between security domains.
123+ // 1) Store the hypervisor hart state that executed on this physical hart to the main memory.
124+ hardware_hart. hypervisor_hart_mut ( ) . save_in_main_memory ( ) ;
125+ match ControlDataStorage :: try_confidential_vm ( confidential_vm_id, |confidential_vm| {
122126 confidential_vm. steal_confidential_hart ( confidential_hart_id, hardware_hart) ?;
123127 Ok ( confidential_vm. allowed_external_interrupts ( ) )
124128 } ) {
125- Ok ( allowed_external_interrupts) => Ok ( ( allowed_external_interrupts, Self { hardware_hart } ) ) ,
129+ Ok ( allowed_external_interrupts) => {
130+ // 2) Load confidential hart state from main memory to the physical hart executing this code.
131+ hardware_hart. confidential_hart_mut ( ) . restore_from_main_memory ( ) ;
132+ Ok ( ( allowed_external_interrupts, Self { hardware_hart } ) )
133+ }
126134 Err ( error) => Err ( ( hardware_hart, error) ) ,
127135 }
128136 }
@@ -134,14 +142,20 @@ impl<'a> ConfidentialFlow<'a> {
134142 let declassifier =
135143 DeclassifyToHypervisor :: EnabledInterrupts ( ExposeEnabledInterrupts :: from_confidential_hart ( self . confidential_hart ( ) ) ) ;
136144
137- ControlDataStorage :: try_confidential_vm ( self . confidential_vm_id ( ) , |mut confidential_vm| {
138- // Run heavy context switch when giving back the confidential hart to the confidential VM.
139- confidential_vm. return_confidential_hart ( self . hardware_hart ) ;
140- Ok ( NonConfidentialFlow :: create ( self . hardware_hart ) . declassify_to_hypervisor_hart ( declassifier) )
145+ // Now, we are going to change the context between security domains.
146+ // 1) Store the confidential hart state that executed on this physical hart to the main memory.
147+ self . hardware_hart . confidential_hart_mut ( ) . save_in_main_memory ( ) ;
148+ let _ = ControlDataStorage :: try_confidential_vm ( self . confidential_vm_id ( ) , |confidential_vm| {
149+ Ok ( confidential_vm. return_confidential_hart ( self . hardware_hart ) )
141150 } )
142151 // Below unwrap is safe because we are in the confidential flow that guarantees that the confidential VM with
143152 // the given id exists in the control data.
144- . unwrap ( )
153+ . unwrap ( ) ;
154+ // Enable memory access control for the hypervisor
155+ unsafe { self . hardware_hart . hypervisor_hart ( ) . enable_hypervisor_memory_protector ( ) } ;
156+ // 2) Load hypervisor hart state from main memory to the physical hart executing this code.
157+ self . hardware_hart . hypervisor_hart_mut ( ) . restore_from_main_memory ( ) ;
158+ NonConfidentialFlow :: create ( self . hardware_hart ) . declassify_to_hypervisor_hart ( declassifier)
145159 }
146160
147161 /// Resumes execution of the confidential hart after the confidential hart was not running on any physical hart.
@@ -162,7 +176,7 @@ impl<'a> ConfidentialFlow<'a> {
162176 // load) to the hypervisor. We must handle the response or resume confidential hart's execution.
163177 use crate :: core:: control_data:: ResumableOperation :: * ;
164178 match self . confidential_hart_mut ( ) . take_resumable_operation ( ) {
165- Some ( SbiRequest ( ) ) => SbiResponse :: from_hypervisor_hart ( self . hypervisor_hart ( ) ) . handle ( self ) ,
179+ Some ( SbiRequest ( ) ) => SbiResponse :: success ( ) . handle ( self ) ,
166180 Some ( ResumeHart ( v) ) => v. handle ( self ) ,
167181 Some ( MmioLoad ( v) ) => MmioLoadResponse :: from_hypervisor_hart ( self . hypervisor_hart ( ) , v) . handle ( self ) ,
168182 Some ( MmioStore ( v) ) => MmioStoreResponse :: from_hypervisor_hart ( self . hypervisor_hart ( ) , v) . handle ( self ) ,
@@ -200,8 +214,7 @@ impl<'a> ConfidentialFlow<'a> {
200214 // We must restore the control and status registers (CSRs) that might have changed during execution of the security monitor.
201215 // We call it here because it is just before exiting to the assembly context switch, so we are sure that these CSRs have their
202216 // final values.
203- let interrupts =
204- self . confidential_hart ( ) . csrs ( ) . hvip . read_from_main_memory ( ) | self . confidential_hart ( ) . csrs ( ) . vsip . read_from_main_memory ( ) ;
217+ let interrupts = self . confidential_hart ( ) . csrs ( ) . hvip . read_from_main_memory ( ) | self . confidential_hart ( ) . csrs ( ) . pending_vssip_irqs ;
205218 let address = self . confidential_hart_mut ( ) . address ( ) ;
206219 self . confidential_hart ( ) . csrs ( ) . hvip . write ( interrupts) ;
207220 self . confidential_hart ( ) . csrs ( ) . sscratch . write ( address) ;
@@ -214,32 +227,44 @@ impl<'a> ConfidentialFlow<'a> {
214227 /// Broadcasts the inter hart request to confidential harts of the currently executing confidential VM. Returns error if sending an IPI
215228 /// to other confidential hart failed or if there is too many pending IPI queued.
216229 pub fn broadcast_remote_command (
217- & mut self , confidential_vm : & mut ConfidentialVm , confidential_hart_remote_command : ConfidentialHartRemoteCommand ,
230+ & mut self , confidential_vm : & ConfidentialVm , confidential_hart_remote_command : ConfidentialHartRemoteCommand ,
218231 ) -> Result < ( ) , Error > {
219232 let sender_confidential_hart_id = self . hardware_hart . confidential_hart ( ) . confidential_hart_id ( ) ;
220233 // check if the remote command is also dedicated for the currently executing confidential hart
221234 if confidential_hart_remote_command. is_hart_selected ( sender_confidential_hart_id) {
222235 self . hardware_hart . confidential_hart_mut ( ) . execute ( & confidential_hart_remote_command) ;
223236 }
224237 // For the time-being, we rely on the OpenSBI's implementation of broadcasting IPIs to hardware harts.
225- self . hardware_hart
226- . opensbi_context ( || confidential_vm. broadcast_remote_command ( sender_confidential_hart_id, confidential_hart_remote_command) )
238+ let hart_mask = confidential_vm. broadcast_remote_command ( sender_confidential_hart_id, confidential_hart_remote_command) ?;
239+ if hart_mask != 0 {
240+ // Confidential harts that should receive an ConfidentialHartRemoteCommand are currently running on a hardware
241+ // harts. We interrupt such hardware harts with IPIs. Consequently, hardware harts running target confidential
242+ // harts will trap into the security monitor, which will execute ConfidentialHartRemoteCommands on the target harts.
243+ self . hardware_hart . opensbi_context ( || {
244+ InterruptController :: try_read ( |controller| controller. send_ipis ( hart_mask, 0 ) ) ?;
245+ Ok ( ( ) )
246+ } ) ?;
247+ }
248+
249+ Ok ( ( ) )
227250 }
228251
229252 /// Processes pending requests from other confidential harts by applying the corresponding state transformation to
230253 /// this confidential hart.
231254 ///
232255 /// This function must only be called when the hypervisor requested resume of confidential hart's execution or when
233256 /// a hardware hart executing a confidential hart is interrupted with the inter-processor-interrupt (IPI).
234- fn process_confidential_hart_remote_commands ( & mut self ) {
235- ControlDataStorage :: try_confidential_vm ( self . confidential_vm_id ( ) , |mut confidential_vm| {
257+ pub fn process_confidential_hart_remote_commands ( & mut self ) -> bool {
258+ let mut requests_processed = false ;
259+ ControlDataStorage :: try_confidential_vm ( self . confidential_vm_id ( ) , |confidential_vm| {
236260 confidential_vm. try_confidential_hart_remote_commands (
237261 self . confidential_hart_id ( ) ,
238262 |ref mut confidential_hart_remote_commands| {
239263 confidential_hart_remote_commands. drain ( ..) . for_each ( |confidential_hart_remote_command| {
240264 // The confidential flow has an ownership of the confidential hart because the confidential hart
241265 // is assigned to the hardware hart.
242266 self . confidential_hart_mut ( ) . execute ( & confidential_hart_remote_command) ;
267+ requests_processed = true ;
243268 } ) ;
244269 Ok ( ( ) )
245270 } ,
@@ -249,6 +274,7 @@ impl<'a> ConfidentialFlow<'a> {
249274 // confidential flow of the finite state machine (FSM) that guarantees it and 2) the processing of inter hart
250275 // requests always succeeds.
251276 . unwrap ( ) ;
277+ requests_processed
252278 }
253279}
254280
0 commit comments