Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.2
xen
23238-svm-decode-assist-insn-fetch.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 23238-svm-decode-assist-insn-fetch.patch of Package xen
References: FATE#309900 # HG changeset patch # User Keir Fraser <keir@xen.org> # Date 1303130170 -3600 # Node ID 60f5df2afcbbe1e8d8438c2b7b8223d9d2102e06 # Parent 381ab77db71a4739b8a4f4fdad4ef3504999f998 svm: implement instruction fetch part of DecodeAssist (on #PF/#NPF) Newer SVM implementations (Bulldozer) copy up to 15 bytes from the instruction stream into the VMCB when a #PF or #NPF exception is intercepted. This patch makes use of this information if available. This saves us from a) traversing the guest's page tables, b) mapping the guest's memory and c) copy the instructions from there into the hypervisor's address space. This speeds up #NPF intercepts quite a lot and avoids cache and TLB trashing. Signed-off-by: Andre Przywara <andre.przywara@amd.com> Signed-off-by: Keir Fraser <keir@xen.org> Index: xen-4.1.2-testing/xen/arch/x86/hvm/emulate.c =================================================================== --- xen-4.1.2-testing.orig/xen/arch/x86/hvm/emulate.c +++ xen-4.1.2-testing/xen/arch/x86/hvm/emulate.c @@ -996,6 +996,8 @@ int hvm_emulate_one( hvmemul_ctxt->insn_buf_eip = regs->eip; hvmemul_ctxt->insn_buf_bytes = + hvm_get_insn_bytes(curr, hvmemul_ctxt->insn_buf) + ? : (hvm_virtual_to_linear_addr( x86_seg_cs, &hvmemul_ctxt->seg_reg[x86_seg_cs], regs->eip, sizeof(hvmemul_ctxt->insn_buf), Index: xen-4.1.2-testing/xen/arch/x86/hvm/svm/svm.c =================================================================== --- xen-4.1.2-testing.orig/xen/arch/x86/hvm/svm/svm.c +++ xen-4.1.2-testing/xen/arch/x86/hvm/svm/svm.c @@ -603,6 +603,21 @@ static void svm_set_rdtsc_exiting(struct vmcb_set_general1_intercepts(vmcb, general1_intercepts); } +static unsigned int svm_get_insn_bytes(struct vcpu *v, uint8_t *buf) +{ + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + unsigned int len = v->arch.hvm_svm.cached_insn_len; + + if ( len != 0 ) + { + /* Latch and clear the cached instruction. */ + memcpy(buf, vmcb->guest_ins, 15); + v->arch.hvm_svm.cached_insn_len = 0; + } + + return len; +} + static void svm_init_hypercall_page(struct domain *d, void *hypercall_page) { char *p; @@ -1448,7 +1463,8 @@ static struct hvm_function_table __read_ .msr_read_intercept = svm_msr_read_intercept, .msr_write_intercept = svm_msr_write_intercept, .invlpg_intercept = svm_invlpg_intercept, - .set_rdtsc_exiting = svm_set_rdtsc_exiting + .set_rdtsc_exiting = svm_set_rdtsc_exiting, + .get_insn_bytes = svm_get_insn_bytes }; asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) @@ -1554,7 +1570,12 @@ asmlinkage void svm_vmexit_handler(struc (unsigned long)regs->ecx, (unsigned long)regs->edx, (unsigned long)regs->esi, (unsigned long)regs->edi); - if ( paging_fault(va, regs) ) + if ( cpu_has_svm_decode ) + v->arch.hvm_svm.cached_insn_len = vmcb->guest_ins_len & 0xf; + rc = paging_fault(va, regs); + v->arch.hvm_svm.cached_insn_len = 0; + + if ( rc ) { if ( trace_will_trace_event(TRC_SHADOW) ) break; @@ -1720,7 +1741,10 @@ asmlinkage void svm_vmexit_handler(struc case VMEXIT_NPF: perfc_incra(svmexits, VMEXIT_NPF_PERFC); regs->error_code = vmcb->exitinfo1; + if ( cpu_has_svm_decode ) + v->arch.hvm_svm.cached_insn_len = vmcb->guest_ins_len & 0xf; svm_do_nested_pgfault(vmcb->exitinfo2); + v->arch.hvm_svm.cached_insn_len = 0; break; case VMEXIT_IRET: { Index: xen-4.1.2-testing/xen/include/asm-x86/hvm/hvm.h =================================================================== --- xen-4.1.2-testing.orig/xen/include/asm-x86/hvm/hvm.h +++ xen-4.1.2-testing/xen/include/asm-x86/hvm/hvm.h @@ -132,6 +132,9 @@ struct hvm_function_table { int (*cpu_up)(void); void (*cpu_down)(void); + /* Copy up to 15 bytes from cached instruction bytes at current rIP. */ + unsigned int (*get_insn_bytes)(struct vcpu *v, uint8_t *buf); + /* Instruction intercepts: non-void return values are X86EMUL codes. */ void (*cpuid_intercept)( unsigned int *eax, unsigned int *ebx, @@ -328,6 +331,11 @@ static inline void hvm_cpu_down(void) hvm_funcs.cpu_down(); } +static inline unsigned int hvm_get_insn_bytes(struct vcpu *v, uint8_t *buf) +{ + return (hvm_funcs.get_insn_bytes ? hvm_funcs.get_insn_bytes(v, buf) : 0); +} + enum hvm_task_switch_reason { TSW_jmp, TSW_iret, TSW_call_or_int }; void hvm_task_switch( uint16_t tss_sel, enum hvm_task_switch_reason taskswitch_reason, Index: xen-4.1.2-testing/xen/include/asm-x86/hvm/svm/vmcb.h =================================================================== --- xen-4.1.2-testing.orig/xen/include/asm-x86/hvm/svm/vmcb.h +++ xen-4.1.2-testing/xen/include/asm-x86/hvm/svm/vmcb.h @@ -498,6 +498,9 @@ struct arch_svm_struct { int launch_core; bool_t vmcb_in_sync; /* VMCB sync'ed with VMSAVE? */ + /* VMCB has a cached instruction from #PF/#NPF Decode Assist? */ + uint8_t cached_insn_len; /* Zero if no cached instruction. */ + /* Upper four bytes are undefined in the VMCB, therefore we can't * use the fields in the VMCB. Write a 64bit value and then read a 64bit * value is fine unless there's a VMRUN/VMEXIT in between which clears
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor