# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1260281667 0
# Node ID 7f611de6b93cc4cbec0530548a85953afa845315
# Parent 2d92ad3ef517208240aa3d00e22516cf885ef351
hvm: Share ASID logic between VMX and SVM.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/hvm/asid.c | 6 +-
xen/arch/x86/hvm/hvm.c | 2
xen/arch/x86/hvm/svm/svm.c | 13 ----
xen/arch/x86/hvm/svm/vmcb.c | 3 -
xen/arch/x86/hvm/vmx/entry.S | 2
xen/arch/x86/hvm/vmx/vmcs.c | 12 +++-
xen/arch/x86/hvm/vmx/vmx.c | 111 +++++++++++++------------------------
xen/include/asm-x86/hvm/asid.h | 6 +-
xen/include/asm-x86/hvm/hvm.h | 18 ++----
xen/include/asm-x86/hvm/svm/asid.h | 2
xen/include/asm-x86/hvm/vmx/vmcs.h | 2
xen/include/asm-x86/hvm/vmx/vmx.h | 12 ----
12 files changed, 73 insertions(+), 116 deletions(-)
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/arch/x86/hvm/asid.c
--- a/xen/arch/x86/hvm/asid.c Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/arch/x86/hvm/asid.c Tue Dec 08 14:14:27 2009 +0000
@@ -20,7 +20,9 @@
#include <xen/config.h>
#include <xen/init.h>
#include <xen/lib.h>
-#include <xen/perfc.h>
+#include <xen/sched.h>
+#include <xen/smp.h>
+#include <xen/percpu.h>
#include <asm/hvm/asid.h>
/*
@@ -80,7 +82,7 @@ void hvm_asid_init(int nasids)
data->next_asid = 1;
}
-void hvm_asid_invalidate_asid(struct vcpu *v)
+void hvm_asid_flush_vcpu(struct vcpu *v)
{
v->arch.hvm_vcpu.asid_generation = 0;
}
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/arch/x86/hvm/hvm.c Tue Dec 08 14:14:27 2009 +0000
@@ -756,6 +756,8 @@ int hvm_vcpu_initialise(struct vcpu *v)
{
int rc;
+ hvm_asid_flush_vcpu(v);
+
if ( cpu_has_xsave )
{
/* XSAVE/XRSTOR requires the save area be 64-byte-boundary aligned. */
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c Tue Dec 08 14:14:27 2009 +0000
@@ -424,7 +424,7 @@ static void svm_update_guest_cr(struct v
break;
case 3:
vmcb->cr3 = v->arch.hvm_vcpu.hw_cr[3];
- hvm_asid_invalidate_asid(v);
+ hvm_asid_flush_vcpu(v);
break;
case 4:
vmcb->cr4 = HVM_CR4_HOST_MASK;
@@ -453,14 +453,6 @@ static void svm_update_guest_efer(struct
svm_intercept_msr(v, MSR_IA32_SYSENTER_CS, lma);
svm_intercept_msr(v, MSR_IA32_SYSENTER_ESP, lma);
svm_intercept_msr(v, MSR_IA32_SYSENTER_EIP, lma);
-}
-
-static void svm_flush_guest_tlbs(void)
-{
- /* Roll over the CPU's ASID generation, so it gets a clean TLB when we
- * next VMRUN. (If ASIDs are disabled, the whole TLB is flushed on
- * VMRUN anyway). */
- hvm_asid_flush_core();
}
static void svm_sync_vmcb(struct vcpu *v)
@@ -704,7 +696,7 @@ static void svm_do_resume(struct vcpu *v
hvm_migrate_timers(v);
/* Migrating to another ASID domain. Request a new ASID. */
- hvm_asid_invalidate_asid(v);
+ hvm_asid_flush_vcpu(v);
}
/* Reflect the vlapic's TPR in the hardware vtpr */
@@ -1250,7 +1242,6 @@ static struct hvm_function_table __read_
.update_host_cr3 = svm_update_host_cr3,
.update_guest_cr = svm_update_guest_cr,
.update_guest_efer = svm_update_guest_efer,
- .flush_guest_tlbs = svm_flush_guest_tlbs,
.set_tsc_offset = svm_set_tsc_offset,
.inject_exception = svm_inject_exception,
.init_hypercall_page = svm_init_hypercall_page,
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/arch/x86/hvm/svm/vmcb.c Tue Dec 08 14:14:27 2009 +0000
@@ -113,9 +113,6 @@ static int construct_vmcb(struct vcpu *v
{
struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
struct vmcb_struct *vmcb = arch_svm->vmcb;
-
- /* TLB control, and ASID assigment. */
- hvm_asid_invalidate_asid(v);
vmcb->general1_intercepts =
GENERAL1_INTERCEPT_INTR | GENERAL1_INTERCEPT_NMI |
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/arch/x86/hvm/vmx/entry.S
--- a/xen/arch/x86/hvm/vmx/entry.S Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/arch/x86/hvm/vmx/entry.S Tue Dec 08 14:14:27 2009 +0000
@@ -142,9 +142,9 @@ vmx_asm_do_vmentry:
call_with_regs(vmx_enter_realmode)
.Lvmx_not_realmode:
+ call vmx_vmenter_helper
mov VCPU_hvm_guest_cr2(r(bx)),r(ax)
mov r(ax),%cr2
- call vmx_trace_vmentry
lea UREGS_rip(r(sp)),r(di)
mov $GUEST_RIP,%eax
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Tue Dec 08 14:14:27 2009 +0000
@@ -400,9 +400,12 @@ int vmx_cpu_up(void)
BUG();
}
+ hvm_asid_init(cpu_has_vmx_vpid ? (1u << VMCS_VPID_WIDTH) : 0);
+
ept_sync_all();
- vpid_sync_all();
+ if ( cpu_has_vmx_vpid )
+ vpid_sync_all();
return 1;
}
@@ -558,6 +561,9 @@ static int construct_vmcs(struct vcpu *v
v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control;
+
+ /* Disable VPID for now: we decide when to enable it on VMENTER. */
+ v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
if ( paging_mode_hap(d) )
{
@@ -736,7 +742,7 @@ static int construct_vmcs(struct vcpu *v
}
if ( cpu_has_vmx_vpid )
- __vmwrite(VIRTUAL_PROCESSOR_ID, v->arch.hvm_vmx.vpid);
+ __vmwrite(VIRTUAL_PROCESSOR_ID, v->arch.hvm_vcpu.asid);
if ( cpu_has_vmx_pat && paging_mode_hap(d) )
{
@@ -946,7 +952,7 @@ void vmx_do_resume(struct vcpu *v)
hvm_migrate_timers(v);
hvm_migrate_pirqs(v);
vmx_set_host_env(v);
- vpid_sync_vcpu_all(v);
+ hvm_asid_flush_vcpu(v);
}
debug_state = v->domain->debugger_attached;
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Dec 08 14:14:27 2009 +0000
@@ -60,8 +60,6 @@ static void vmx_ctxt_switch_to(struct vc
static int vmx_alloc_vlapic_mapping(struct domain *d);
static void vmx_free_vlapic_mapping(struct domain *d);
-static int vmx_alloc_vpid(struct vcpu *v);
-static void vmx_free_vpid(struct vcpu *v);
static void vmx_install_vlapic_mapping(struct vcpu *v);
static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr);
static void vmx_update_guest_efer(struct vcpu *v);
@@ -104,9 +102,6 @@ static int vmx_vcpu_initialise(struct vc
spin_lock_init(&v->arch.hvm_vmx.vmcs_lock);
- if ( (rc = vmx_alloc_vpid(v)) != 0 )
- return rc;
-
v->arch.schedule_tail = vmx_do_resume;
v->arch.ctxt_switch_from = vmx_ctxt_switch_from;
v->arch.ctxt_switch_to = vmx_ctxt_switch_to;
@@ -116,7 +111,6 @@ static int vmx_vcpu_initialise(struct vc
dprintk(XENLOG_WARNING,
"Failed to create VMCS for vcpu %d: err=%d.\n",
v->vcpu_id, rc);
- vmx_free_vpid(v);
return rc;
}
@@ -136,7 +130,6 @@ static void vmx_vcpu_destroy(struct vcpu
vmx_destroy_vmcs(v);
vpmu_destroy(v);
passive_domain_destroy(v);
- vmx_free_vpid(v);
}
#ifdef __x86_64__
@@ -1168,7 +1161,7 @@ static void vmx_update_guest_cr(struct v
}
__vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr[3]);
- vpid_sync_vcpu_all(v);
+ hvm_asid_flush_vcpu(v);
break;
case 4:
v->arch.hvm_vcpu.hw_cr[4] = HVM_CR4_HOST_MASK;
@@ -1212,19 +1205,6 @@ static void vmx_update_guest_efer(struct
if ( v == current )
write_efer((read_efer() & ~EFER_SCE) |
(v->arch.hvm_vcpu.guest_efer & EFER_SCE));
-}
-
-static void vmx_flush_guest_tlbs(void)
-{
- /*
- * If VPID (i.e. tagged TLB support) is not enabled, the fact that
- * we're in Xen at all means any guest will have a clean TLB when
- * it's next run, because VMRESUME will flush it for us.
- *
- * If enabled, we invalidate all translations associated with all
- * VPID values.
- */
- vpid_sync_all();
}
static void __ept_sync_domain(void *info)
@@ -1358,7 +1338,7 @@ static void vmx_set_uc_mode(struct vcpu
if ( paging_mode_hap(v->domain) )
ept_change_entry_emt_with_range(
v->domain, 0, v->domain->arch.p2m->max_mapped_pfn);
- vpid_sync_all();
+ hvm_asid_flush_vcpu(v);
}
static void vmx_set_info_guest(struct vcpu *v)
@@ -1405,7 +1385,6 @@ static struct hvm_function_table __read_
.update_host_cr3 = vmx_update_host_cr3,
.update_guest_cr = vmx_update_guest_cr,
.update_guest_efer = vmx_update_guest_efer,
- .flush_guest_tlbs = vmx_flush_guest_tlbs,
.set_tsc_offset = vmx_set_tsc_offset,
.inject_exception = vmx_inject_exception,
.init_hypercall_page = vmx_init_hypercall_page,
@@ -1424,9 +1403,6 @@ static struct hvm_function_table __read_
.set_rdtsc_exiting = vmx_set_rdtsc_exiting
};
-static unsigned long *vpid_bitmap;
-#define VPID_BITMAP_SIZE (1u << VMCS_VPID_WIDTH)
-
void start_vmx(void)
{
static bool_t bootstrapped;
@@ -1460,17 +1436,6 @@ void start_vmx(void)
if ( cpu_has_vmx_ept )
vmx_function_table.hap_supported = 1;
-
- if ( cpu_has_vmx_vpid )
- {
- vpid_bitmap = xmalloc_array(
- unsigned long, BITS_TO_LONGS(VPID_BITMAP_SIZE));
- BUG_ON(vpid_bitmap == NULL);
- memset(vpid_bitmap, 0, BITS_TO_LONGS(VPID_BITMAP_SIZE) * sizeof(long));
-
- /* VPID 0 is used by VMX root mode (the hypervisor). */
- __set_bit(0, vpid_bitmap);
- }
setup_vmcs_dump();
@@ -1584,7 +1549,7 @@ static void vmx_invlpg_intercept(unsigne
{
struct vcpu *curr = current;
HVMTRACE_LONG_2D(INVLPG, /*invlpga=*/ 0, TRC_PAR_LONG(vaddr));
- if ( paging_invlpg(curr, vaddr) )
+ if ( paging_invlpg(curr, vaddr) && cpu_has_vmx_vpid )
vpid_sync_vcpu_gva(curr, vaddr);
}
@@ -1929,36 +1894,6 @@ static void vmx_free_vlapic_mapping(stru
unsigned long mfn = d->arch.hvm_domain.vmx.apic_access_mfn;
if ( mfn != 0 )
free_xenheap_page(mfn_to_virt(mfn));
-}
-
-static int vmx_alloc_vpid(struct vcpu *v)
-{
- int idx;
-
- if ( !cpu_has_vmx_vpid )
- return 0;
-
- do {
- idx = find_first_zero_bit(vpid_bitmap, VPID_BITMAP_SIZE);
- if ( idx >= VPID_BITMAP_SIZE )
- {
- dprintk(XENLOG_WARNING, "VMX VPID space exhausted.\n");
- return -EBUSY;
- }
- }
- while ( test_and_set_bit(idx, vpid_bitmap) );
-
- v->arch.hvm_vmx.vpid = idx;
- return 0;
-}
-
-static void vmx_free_vpid(struct vcpu *v)
-{
- if ( !cpu_has_vmx_vpid )
- return;
-
- if ( v->arch.hvm_vmx.vpid )
- clear_bit(v->arch.hvm_vmx.vpid, vpid_bitmap);
}
static void vmx_install_vlapic_mapping(struct vcpu *v)
@@ -2675,8 +2610,44 @@ asmlinkage void vmx_vmexit_handler(struc
}
}
-asmlinkage void vmx_trace_vmentry(void)
-{
+asmlinkage void vmx_vmenter_helper(void)
+{
+ struct vcpu *curr = current;
+ u32 new_asid, old_asid;
+ bool_t need_flush;
+
+ if ( !cpu_has_vmx_vpid )
+ goto out;
+
+ old_asid = curr->arch.hvm_vcpu.asid;
+ need_flush = hvm_asid_handle_vmenter();
+ new_asid = curr->arch.hvm_vcpu.asid;
+
+ if ( unlikely(new_asid != old_asid) )
+ {
+ __vmwrite(VIRTUAL_PROCESSOR_ID, new_asid);
+ if ( !old_asid && new_asid )
+ {
+ /* VPID was disabled: now enabled. */
+ curr->arch.hvm_vmx.secondary_exec_control |=
+ SECONDARY_EXEC_ENABLE_VPID;
+ __vmwrite(SECONDARY_VM_EXEC_CONTROL,
+ curr->arch.hvm_vmx.secondary_exec_control);
+ }
+ else if ( old_asid && !new_asid )
+ {
+ /* VPID was enabled: now disabled. */
+ curr->arch.hvm_vmx.secondary_exec_control &=
+ ~SECONDARY_EXEC_ENABLE_VPID;
+ __vmwrite(SECONDARY_VM_EXEC_CONTROL,
+ curr->arch.hvm_vmx.secondary_exec_control);
+ }
+ }
+
+ if ( unlikely(need_flush) )
+ vpid_sync_all();
+
+ out:
HVMTRACE_ND (VMENTRY, 1/*cycles*/, 0, 0, 0, 0, 0, 0, 0);
}
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/include/asm-x86/hvm/asid.h
--- a/xen/include/asm-x86/hvm/asid.h Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/include/asm-x86/hvm/asid.h Tue Dec 08 14:14:27 2009 +0000
@@ -21,14 +21,14 @@
#define __ASM_X86_HVM_ASID_H__
#include <xen/config.h>
-#include <xen/sched.h>
-#include <asm/processor.h>
+
+struct vcpu;
/* Initialise ASID management for the current physical CPU. */
void hvm_asid_init(int nasids);
/* Invalidate a VCPU's current ASID allocation: forces re-allocation. */
-void hvm_asid_invalidate_asid(struct vcpu *v);
+void hvm_asid_flush_vcpu(struct vcpu *v);
/* Flush all ASIDs on this processor core. */
void hvm_asid_flush_core(void);
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/include/asm-x86/hvm/hvm.h Tue Dec 08 14:14:27 2009 +0000
@@ -23,6 +23,7 @@
#include <asm/current.h>
#include <asm/x86_emulate.h>
+#include <asm/hvm/asid.h>
#include <public/domctl.h>
#include <public/hvm/save.h>
@@ -99,13 +100,6 @@ struct hvm_function_table {
*/
void (*update_guest_cr)(struct vcpu *v, unsigned int cr);
void (*update_guest_efer)(struct vcpu *v);
-
- /*
- * Called to ensure than all guest-specific mappings in a tagged TLB
- * are flushed; does *not* flush Xen's TLB entries, and on
- * processors without a tagged TLB it will be a noop.
- */
- void (*flush_guest_tlbs)(void);
void (*set_tsc_offset)(struct vcpu *v, u64 offset);
@@ -201,11 +195,15 @@ static inline void hvm_update_guest_efer
hvm_funcs.update_guest_efer(v);
}
-static inline void
-hvm_flush_guest_tlbs(void)
+/*
+ * Called to ensure than all guest-specific mappings in a tagged TLB are
+ * flushed; does *not* flush Xen's TLB entries, and on processors without a
+ * tagged TLB it will be a noop.
+ */
+static inline void hvm_flush_guest_tlbs(void)
{
if ( hvm_enabled )
- hvm_funcs.flush_guest_tlbs();
+ hvm_asid_flush_core();
}
void hvm_hypercall_page_initialise(struct domain *d,
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/include/asm-x86/hvm/svm/asid.h
--- a/xen/include/asm-x86/hvm/svm/asid.h Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/include/asm-x86/hvm/svm/asid.h Tue Dec 08 14:14:27 2009 +0000
@@ -41,7 +41,7 @@ static inline void svm_asid_g_invlpg(str
#endif
/* Safe fallback. Take a new ASID. */
- hvm_asid_invalidate_asid(v);
+ hvm_asid_flush_vcpu(v);
}
#endif /* __ASM_X86_HVM_SVM_ASID_H__ */
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Dec 08 14:14:27 2009 +0000
@@ -89,8 +89,6 @@ struct arch_vmx_struct {
/* Cache of cpu execution control. */
u32 exec_control;
u32 secondary_exec_control;
-
- u16 vpid;
/* PMU */
struct vpmu_struct vpmu;
diff -r 2d92ad3ef517 -r 7f611de6b93c xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Tue Dec 08 10:33:08 2009 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Tue Dec 08 14:14:27 2009 +0000
@@ -314,20 +314,12 @@ void ept_sync_domain(struct domain *d);
static inline void vpid_sync_vcpu_gva(struct vcpu *v, unsigned long gva)
{
- if ( cpu_has_vmx_vpid )
- __invvpid(0, v->arch.hvm_vmx.vpid, (u64)gva);
-}
-
-static inline void vpid_sync_vcpu_all(struct vcpu *v)
-{
- if ( cpu_has_vmx_vpid )
- __invvpid(1, v->arch.hvm_vmx.vpid, 0);
+ __invvpid(0, v->arch.hvm_vcpu.asid, (u64)gva);
}
static inline void vpid_sync_all(void)
{
- if ( cpu_has_vmx_vpid )
- __invvpid(2, 0, 0);
+ __invvpid(2, 0, 0);
}
static inline void __vmxoff(void)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|