@@ -105,6 +105,15 @@ static bool is_guest_irq_enabled(struct acrn_vcpu *vcpu)
105
105
return status ;
106
106
}
107
107
108
+ static inline bool is_nmi_injectable (void )
109
+ {
110
+ uint64_t guest_state ;
111
+
112
+ guest_state = exec_vmread32 (VMX_GUEST_INTERRUPTIBILITY_INFO );
113
+
114
+ return ((guest_state & (HV_ARCH_VCPU_BLOCKED_BY_STI |
115
+ HV_ARCH_VCPU_BLOCKED_BY_MOVSS | HV_ARCH_VCPU_BLOCKED_BY_NMI )) == 0UL );
116
+ }
108
117
void vcpu_make_request (struct acrn_vcpu * vcpu , uint16_t eventid )
109
118
{
110
119
bitmap_set_lock (eventid , & vcpu -> arch .pending_req );
@@ -286,6 +295,7 @@ void vcpu_inject_extint(struct acrn_vcpu *vcpu)
286
295
void vcpu_inject_nmi (struct acrn_vcpu * vcpu )
287
296
{
288
297
vcpu_make_request (vcpu , ACRN_REQUEST_NMI );
298
+ signal_event (& vcpu -> events [VCPU_EVENT_VIRTUAL_INTERRUPT ]);
289
299
}
290
300
291
301
/* Inject general protection exception(#GP) to guest */
@@ -401,11 +411,17 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
401
411
injected = vcpu_inject_hi_exception (vcpu );
402
412
if (!injected ) {
403
413
/* inject NMI before maskable hardware interrupt */
414
+
404
415
if (bitmap_test_and_clear_lock (ACRN_REQUEST_NMI , pending_req_bits )) {
405
- /* Inject NMI vector = 2 */
406
- exec_vmwrite32 (VMX_ENTRY_INT_INFO_FIELD ,
407
- VMX_INT_INFO_VALID | (VMX_INT_TYPE_NMI << 8U ) | IDT_NMI );
408
- injected = true;
416
+ if (is_nmi_injectable ()) {
417
+ /* Inject NMI vector = 2 */
418
+ exec_vmwrite32 (VMX_ENTRY_INT_INFO_FIELD ,
419
+ VMX_INT_INFO_VALID | (VMX_INT_TYPE_NMI << 8U ) | IDT_NMI );
420
+ injected = true;
421
+ } else {
422
+ /* keep the NMI request for next vmexit */
423
+ bitmap_set_lock (ACRN_REQUEST_NMI , pending_req_bits );
424
+ }
409
425
} else {
410
426
/* handling pending vector injection:
411
427
* there are many reason inject failed, we need re-inject again
@@ -442,7 +458,13 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
442
458
* deliver is disabled.
443
459
*/
444
460
if (!arch -> irq_window_enabled ) {
461
+ /*
462
+ * TODO: Currently, NMI exiting and virtual NMIs are not enabled,
463
+ * so use interrupt window to inject NMI.
464
+ * After enable virtual NMIs, we can use NMI-Window
465
+ */
445
466
if (bitmap_test (ACRN_REQUEST_EXTINT , pending_req_bits ) ||
467
+ bitmap_test (ACRN_REQUEST_NMI , pending_req_bits ) ||
446
468
vlapic_has_pending_delivery_intr (vcpu )) {
447
469
tmp = exec_vmread32 (VMX_PROC_VM_EXEC_CONTROLS );
448
470
tmp |= VMX_PROCBASED_CTLS_IRQ_WIN ;
0 commit comments