|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 1/3] x86/hvm: don't let EFLAGS.IF block NMI/#MC due to nested state
From: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
nhvm_interrupt_blocked() reports why an interrupt is blocked, but both
callers, nestedsvm_vcpu_interrupt() and hvm_interrupt_blocked(), treat any
reason as blocking every event source. EFLAGS.IF (hvm_intblk_rflags_ie)
doesn't mask NMI or #MC, so NMI/#MC get held pending needlessly, e.g. when
L1 sets V_INTR_MASKING and L1's IF is clear.
Have nhvm_interrupt_blocked() take the intack and report no block for
NMI/#MC when the reason is hvm_intblk_rflags_ie.
nvmx_intr_blocked() used hvm_intblk_rflags_ie for vmexit/vmentry in
progress and a valid VM_ENTRY_INTR_INFO. Those block every event source
and have nothing to do with RFLAGS.IF, so report hvm_intblk_arch instead.
This doesn't change behaviour as all callers only compare against
hvm_intblk_none and hvm_intblk_tpr.
Signed-off-by: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
---
v3:
* Use nhvm_interrupt_blocked() in nvmx_intr_intercept() instead of calling
nvmx_intr_blocked() directly, so the NMI/#MC exemption applies to VMX
too, as suggested by Ross.
* Rebased on staging.
xen/arch/x86/hvm/hvm.c | 2 +-
xen/arch/x86/hvm/svm/nestedsvm.c | 2 +-
xen/arch/x86/hvm/vmx/intr.c | 8 ++++----
xen/arch/x86/include/asm/hvm/hvm.h | 12 ++++++++++--
4 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ef9c7cd05777..8fd095a4f8e6 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3897,7 +3897,7 @@ enum hvm_intblk hvm_interrupt_blocked(struct vcpu *v,
struct hvm_intack intack)
if ( nestedhvm_enabled(v->domain) ) {
enum hvm_intblk intr;
- intr = nhvm_interrupt_blocked(v);
+ intr = nhvm_interrupt_blocked(v, intack);
if ( intr != hvm_intblk_none )
return intr;
}
diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c
index d970869cfd96..40c7717c5572 100644
--- a/xen/arch/x86/hvm/svm/nestedsvm.c
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c
@@ -1417,7 +1417,7 @@ nestedsvm_vcpu_interrupt(struct vcpu *v, const struct
hvm_intack intack)
uint64_t exitinfo2 = 0;
ASSERT(nestedhvm_vcpu_in_guestmode(v));
- intr = nhvm_interrupt_blocked(v);
+ intr = nhvm_interrupt_blocked(v, intack);
if ( intr != hvm_intblk_none )
return NSVM_INTR_MASKED;
diff --git a/xen/arch/x86/hvm/vmx/intr.c b/xen/arch/x86/hvm/vmx/intr.c
index 6c220c4c2e49..a6099420fda5 100644
--- a/xen/arch/x86/hvm/vmx/intr.c
+++ b/xen/arch/x86/hvm/vmx/intr.c
@@ -142,18 +142,18 @@ enum hvm_intblk cf_check nvmx_intr_blocked(struct vcpu *v)
{
if ( nvcpu->nv_vmexit_pending ||
nvcpu->nv_vmswitch_in_progress )
- r = hvm_intblk_rflags_ie;
+ r = hvm_intblk_arch;
else
{
unsigned long intr_info;
__vmread(VM_ENTRY_INTR_INFO, &intr_info);
if ( intr_info & INTR_INFO_VALID_MASK )
- r = hvm_intblk_rflags_ie;
+ r = hvm_intblk_arch;
}
}
else if ( nvcpu->nv_vmentry_pending )
- r = hvm_intblk_rflags_ie;
+ r = hvm_intblk_arch;
return r;
}
@@ -167,7 +167,7 @@ static int nvmx_intr_intercept(struct vcpu *v, struct
hvm_intack intack)
hvm_interrupt_blocked(v, intack) == hvm_intblk_tpr )
return 1;
- if ( nvmx_intr_blocked(v) != hvm_intblk_none )
+ if ( nhvm_interrupt_blocked(v, intack) != hvm_intblk_none )
{
vmx_enable_intr_window(v, intack);
return 1;
diff --git a/xen/arch/x86/include/asm/hvm/hvm.h
b/xen/arch/x86/include/asm/hvm/hvm.h
index 9bf2064925fa..b10937e229cf 100644
--- a/xen/arch/x86/include/asm/hvm/hvm.h
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
@@ -678,9 +678,17 @@ static inline bool nhvm_vmcx_hap_enabled(struct vcpu *v)
}
/* interrupt */
-static inline enum hvm_intblk nhvm_interrupt_blocked(struct vcpu *v)
+static inline enum hvm_intblk nhvm_interrupt_blocked(
+ struct vcpu *v, const struct hvm_intack intack)
{
- return alternative_call(hvm_funcs.nhvm_intr_blocked, v);
+ enum hvm_intblk intr = alternative_call(hvm_funcs.nhvm_intr_blocked, v);
+
+ /* EFLAGS.IF doesn't mask NMI or #MC. */
+ if ( intr == hvm_intblk_rflags_ie &&
+ (intack.source == hvm_intsrc_nmi || intack.source == hvm_intsrc_mce) )
+ return hvm_intblk_none;
+
+ return intr;
}
static inline int nhvm_hap_walk_L1_p2m(
--
2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |