|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 1/5] x86/nestedsvm: update vmrun without pending or deferred flag
From: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
Signed-off-by: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
---
xen/arch/x86/hvm/svm/entry.S | 48 +++++++++++++++++++++++--------
xen/arch/x86/hvm/svm/nestedhvm.h | 1 +
xen/arch/x86/hvm/svm/nestedsvm.c | 31 +++++++++++++++++++-
xen/arch/x86/hvm/svm/svm.c | 11 +++++--
xen/arch/x86/x86_64/asm-offsets.c | 1 +
5 files changed, 77 insertions(+), 15 deletions(-)
diff --git a/xen/arch/x86/hvm/svm/entry.S b/xen/arch/x86/hvm/svm/entry.S
index d9613a2a8fed..59d865635fd5 100644
--- a/xen/arch/x86/hvm/svm/entry.S
+++ b/xen/arch/x86/hvm/svm/entry.S
@@ -28,31 +28,51 @@ FUNC(svm_asm_do_resume)
GET_CURRENT(bx)
.Lsvm_do_resume:
call svm_intr_assist
- call nsvm_vcpu_switch
- ASSERT_NOT_IN_ATOMIC
- mov VCPU_processor(%rbx),%eax
- lea irq_stat+IRQSTAT_softirq_pending(%rip),%rdx
+ /*
+ * The nested p2m repair below may need to take nestedp2m_lock and
+ * issue synchronous cross-CPU TLB flush IPIs, doing this with
+ * interrupts disabled can deadlock.
+ */
xor %ecx,%ecx
- shl $IRQSTAT_shift,%eax
- cli
- cmp %ecx,(%rdx,%rax,1)
- jne .Lsvm_process_softirqs
-
cmp %cl,VCPU_nsvm_hap_enabled(%rbx)
UNLIKELY_START(ne, nsvm_hap)
+ cmpb $0,VCPU_nhvm_guestmode(%rbx)
+ UNLIKELY_DONE(z, nsvm_hap)
+ cmpb $0,VCPU_nhvm_stale_np2m(%rbx)
+ jne .Lsvm_update_nestedp2m
cmp %rcx,VCPU_nhvm_p2m(%rbx)
sete %al
test VCPU_nhvm_guestmode(%rbx),%al
UNLIKELY_DONE(z, nsvm_hap)
+.Lsvm_update_nestedp2m:
/*
- * Someone shot down our nested p2m table; go round again
- * and nsvm_vcpu_switch() will fix it for us.
+ * The nested p2m table is stale, fix it here.
*/
- sti
+ mov %rbx,%rdi
+ call nsvm_vcpu_update_nestedp2m
jmp .Lsvm_do_resume
__UNLIKELY_END(nsvm_hap)
+ ASSERT_NOT_IN_ATOMIC
+
+ mov VCPU_processor(%rbx),%eax
+ lea irq_stat+IRQSTAT_softirq_pending(%rip),%rdx
+ xor %ecx,%ecx
+ shl $IRQSTAT_shift,%eax
+ cli
+ cmp %ecx,(%rdx,%rax,1)
+ jne .Lsvm_process_softirqs
+
+ cmp %cl,VCPU_nsvm_hap_enabled(%rbx)
+ je .Lsvm_vmenter
+ cmpb $0,VCPU_nhvm_guestmode(%rbx)
+ je .Lsvm_vmenter
+ cmpb $0,VCPU_nhvm_stale_np2m(%rbx)
+ jne .Lsvm_retry_nestedp2m
+
+.Lsvm_vmenter:
+
call svm_vmenter_helper
clgi
@@ -148,4 +168,8 @@ __UNLIKELY_END(nsvm_hap)
sti
call do_softirq
jmp .Lsvm_do_resume
+
+.Lsvm_retry_nestedp2m:
+ sti
+ jmp .Lsvm_do_resume
END(svm_asm_do_resume)
diff --git a/xen/arch/x86/hvm/svm/nestedhvm.h b/xen/arch/x86/hvm/svm/nestedhvm.h
index 9bb04a043430..e22ef259c171 100644
--- a/xen/arch/x86/hvm/svm/nestedhvm.h
+++ b/xen/arch/x86/hvm/svm/nestedhvm.h
@@ -41,6 +41,7 @@ void cf_check nsvm_vcpu_destroy(struct vcpu *v);
int cf_check nsvm_vcpu_initialise(struct vcpu *v);
int cf_check nsvm_vcpu_reset(struct vcpu *v);
int nsvm_vcpu_vmrun(struct vcpu *v, struct cpu_user_regs *regs);
+void nsvm_vcpu_update_nestedp2m(struct vcpu *v);
int cf_check nsvm_vcpu_vmexit_event(struct vcpu *v,
const struct x86_event *event);
uint64_t cf_check nsvm_vcpu_hostcr3(struct vcpu *v);
diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c
index a8b15d6eae05..171b32be2416 100644
--- a/xen/arch/x86/hvm/svm/nestedsvm.c
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c
@@ -361,6 +361,35 @@ static void nestedsvm_vmcb_set_nestedp2m(struct vcpu *v,
n2vmcb->_h_cr3 = pagetable_get_paddr(p2m_get_pagetable(p2m));
}
+void nsvm_vcpu_update_nestedp2m(struct vcpu *v)
+{
+ struct nestedvcpu *nv;
+ struct nestedsvm *svm;
+ struct p2m_domain *p2m;
+
+ ASSERT(v != NULL);
+
+ nv = &vcpu_nestedhvm(v);
+ svm = &vcpu_nestedsvm(v);
+
+ if ( !nestedhvm_paging_mode_hap(v) )
+ return;
+
+ p2m = p2m_get_nestedp2m(v);
+
+ /*
+ * This may happen if we've handled VMEXIT_NPF at the same time as a
+ * nested flush IPI from another CPU. We've got a different P2M so the
+ * host CR3 needs updating.
+ */
+ if ( svm->ns_vmcb_hostcr3 != vmcb_get_h_cr3(nv->nv_vvmcx) ||
+ vmcb_get_h_cr3(nv->nv_n2vmcx) !=
+ pagetable_get_paddr(p2m_get_pagetable(p2m)) )
+ nestedsvm_vmcb_set_nestedp2m(v, nv->nv_vvmcx, nv->nv_n2vmcx);
+
+ nv->stale_np2m = false;
+}
+
static int nsvm_vmcb_prepare4vmrun(struct vcpu *v, struct cpu_user_regs *regs)
{
struct nestedvcpu *nv = &vcpu_nestedhvm(v);
@@ -516,7 +545,7 @@ static int nsvm_vmcb_prepare4vmrun(struct vcpu *v, struct
cpu_user_regs *regs)
/* host nested paging + guest nested paging. */
vmcb_set_np(n2vmcb, true);
- nestedsvm_vmcb_set_nestedp2m(v, ns_vmcb, n2vmcb);
+ nsvm_vcpu_update_nestedp2m(v);
/* hvm_set_cr3() below sets v->arch.hvm.guest_cr[3] for us. */
rc = hvm_set_cr3(ns_vmcb->_cr3, false, true);
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index e6a0edcf71ab..fc447d24d67e 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -2118,6 +2118,8 @@ static void
svm_vmexit_do_vmrun(struct cpu_user_regs *regs,
struct vcpu *v, uint64_t vmcbaddr)
{
+ int rc;
+
if ( !nsvm_efer_svm_enabled(v) )
{
hvm_inject_hw_exception(X86_EXC_UD, X86_EVENT_NO_EC);
@@ -2131,8 +2133,13 @@ svm_vmexit_do_vmrun(struct cpu_user_regs *regs,
return;
}
- vcpu_nestedhvm(v).nv_vmentry_pending = 1;
- return;
+ rc = nsvm_vcpu_vmrun(v, regs);
+ if ( rc )
+ {
+ if ( nestedsvm_vcpu_vmexit(v, regs, VMEXIT_INVALID, 0, 0) ==
+ NESTEDHVM_VMEXIT_FATALERROR )
+ domain_crash(v->domain);
+ }
}
static struct page_info *
diff --git a/xen/arch/x86/x86_64/asm-offsets.c
b/xen/arch/x86/x86_64/asm-offsets.c
index baf266ab8013..772d1959e5a5 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -129,6 +129,7 @@ void __dummy__(void)
OFFSET(VCPU_nhvm_guestmode, struct vcpu, arch.hvm.nvcpu.nv_guestmode);
OFFSET(VCPU_nhvm_p2m, struct vcpu, arch.hvm.nvcpu.nv_p2m);
+ OFFSET(VCPU_nhvm_stale_np2m, struct vcpu, arch.hvm.nvcpu.stale_np2m);
OFFSET(VCPU_nsvm_hap_enabled, struct vcpu,
arch.hvm.nvcpu.u.nsvm.ns_hap_enabled);
BLANK();
#endif
--
2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |