References: FATE#309900 # HG changeset patch # User Christoph Egger # Date 1302700499 -3600 # Node ID 3b2182100ba2fa5c4a3a450e473717e2300aa8f1 # Parent 2284c79b606ac14ef5c5bc2c1cce62188b5bd9ee x86/svm/asid: Introduce svm_invlpga() Signed-off-by: Christoph Egger # HG changeset patch # User Andre Przywara # Date 1303117597 -3600 # Node ID e324c4d1dd6eeb9417fec513640ca795bd0f5dd4 # Parent 2c8ad607ece18b4740b9fc4ffe267a0e0893c141 svm: implement INVLPG part of DecodeAssist Newer SVM implementations (Bulldozer) give the desired address on a INVLPG intercept explicitly in the EXITINFO1 field of the VMCB. Use this address to avoid a costly instruction fetch and decode cycle. Signed-off-by: Andre Przywara # HG changeset patch # User Christoph Egger # Date 1305187246 -3600 # Node ID 19d6541c4abec3486c83de76102ec46d7fe22a16 # Parent b6e8e916ed2827fb1329de0de2e23ee5b6b78662 nestedsvm: update rip on invlpga intercept Fixes endless loop. Signed-off-by: Christoph Egger Index: xen-4.1.1-testing/xen/arch/x86/hvm/svm/emulate.c =================================================================== --- xen-4.1.1-testing.orig/xen/arch/x86/hvm/svm/emulate.c +++ xen-4.1.1-testing/xen/arch/x86/hvm/svm/emulate.c @@ -102,6 +102,7 @@ MAKE_INSTR(INT3, 1, 0xcc); MAKE_INSTR(RDTSC, 2, 0x0f, 0x31); MAKE_INSTR(PAUSE, 1, 0x90); MAKE_INSTR(XSETBV, 3, 0x0f, 0x01, 0xd1); +MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf); static const u8 *opc_bytes[INSTR_MAX_COUNT] = { @@ -116,6 +117,7 @@ static const u8 *opc_bytes[INSTR_MAX_COU [INSTR_RDTSC] = OPCODE_RDTSC, [INSTR_PAUSE] = OPCODE_PAUSE, [INSTR_XSETBV] = OPCODE_XSETBV, + [INSTR_INVLPGA] = OPCODE_INVLPGA, }; static int fetch(struct vcpu *v, u8 *buf, unsigned long addr, int len) Index: xen-4.1.1-testing/xen/arch/x86/hvm/svm/svm.c =================================================================== --- xen-4.1.1-testing.orig/xen/arch/x86/hvm/svm/svm.c +++ xen-4.1.1-testing/xen/arch/x86/hvm/svm/svm.c @@ -1650,11 +1650,22 @@ asmlinkage void svm_vmexit_handler(struc break; case VMEXIT_INVLPG: - case VMEXIT_INVLPGA: - if ( !handle_mmio() ) + if ( cpu_has_svm_decode ) + { + svm_invlpg_intercept(vmcb->exitinfo1); + __update_guest_eip(regs, vmcb->nextrip - vmcb->rip); + } + else if ( !handle_mmio() ) hvm_inject_exception(TRAP_gp_fault, 0, 0); break; + case VMEXIT_INVLPGA: + if ( (inst_len = __get_instruction_length(v, INSTR_INVLPGA)) == 0 ) + break; + svm_invlpga(regs->eax, v->arch.hvm_vcpu.asid); + __update_guest_eip(regs, inst_len); + break; + case VMEXIT_VMMCALL: if ( (inst_len = __get_instruction_length(v, INSTR_VMCALL)) == 0 ) break; Index: xen-4.1.1-testing/xen/include/asm-x86/hvm/svm/asid.h =================================================================== --- xen-4.1.1-testing.orig/xen/include/asm-x86/hvm/svm/asid.h +++ xen-4.1.1-testing/xen/include/asm-x86/hvm/svm/asid.h @@ -34,10 +34,7 @@ static inline void svm_asid_g_invlpg(str { #if 0 /* Optimization? */ - asm volatile (".byte 0x0F,0x01,0xDF \n" - : /* output */ - : /* input */ - "a" (g_vaddr), "c"(v->arch.hvm_svm.vmcb->guest_asid) ); + svm_invlpga(g_vaddr, v->arch.hvm_svm.vmcb->guest_asid); #endif /* Safe fallback. Take a new ASID. */ Index: xen-4.1.1-testing/xen/include/asm-x86/hvm/svm/emulate.h =================================================================== --- xen-4.1.1-testing.orig/xen/include/asm-x86/hvm/svm/emulate.h +++ xen-4.1.1-testing/xen/include/asm-x86/hvm/svm/emulate.h @@ -33,6 +33,7 @@ enum instruction_index { INSTR_RDTSC, INSTR_PAUSE, INSTR_XSETBV, + INSTR_INVLPGA, INSTR_MAX_COUNT /* Must be last - Number of instructions supported */ }; Index: xen-4.1.1-testing/xen/include/asm-x86/hvm/svm/svm.h =================================================================== --- xen-4.1.1-testing.orig/xen/include/asm-x86/hvm/svm/svm.h +++ xen-4.1.1-testing/xen/include/asm-x86/hvm/svm/svm.h @@ -62,6 +62,15 @@ static inline void svm_vmsave(void *vmcb : : "a" (__pa(vmcb)) : "memory" ); } +static inline void svm_invlpga(unsigned long vaddr, uint32_t asid) +{ + asm volatile ( + ".byte 0x0f,0x01,0xdf" + : /* output */ + : /* input */ + "a" (vaddr), "c" (asid)); +} + extern u32 svm_feature_flags; #define SVM_FEATURE_NPT 0 /* Nested page table support */