Date: Wed, 11 Jun 2014 12:25:32 GMT From: mihai@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r269399 - in soc2014/mihai/bhyve-icache-head/sys/amd64: include vmm Message-ID: <201406111225.s5BCPWsY072485@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mihai Date: Wed Jun 11 12:25:32 2014 New Revision: 269399 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=269399 Log: sys: amd64: vmm: vmm.c: fix locking issues when caching/deleting instructions Modified: soc2014/mihai/bhyve-icache-head/sys/amd64/include/vmm_instruction_cache.h soc2014/mihai/bhyve-icache-head/sys/amd64/vmm/vmm.c Modified: soc2014/mihai/bhyve-icache-head/sys/amd64/include/vmm_instruction_cache.h ============================================================================== --- soc2014/mihai/bhyve-icache-head/sys/amd64/include/vmm_instruction_cache.h Wed Jun 11 11:27:44 2014 (r269398) +++ soc2014/mihai/bhyve-icache-head/sys/amd64/include/vmm_instruction_cache.h Wed Jun 11 12:25:32 2014 (r269399) @@ -39,4 +39,10 @@ struct vie *vie); int vm_inst_cache_delete(struct vm *vm, uint64_t rip, uint64_t cr3); +#define vm_inst_cache_lock_init(vm) sx_init(&vm->inst_cache_lock, "VM INST CACHE LOCK") +#define vm_inst_cache_xlock(vm) sx_xlock(&vm->inst_cache_lock) +#define vm_inst_cache_slock(vm) sx_slock(&vm->inst_cache_lock) +#define vm_inst_cache_unlock(vm) sx_unlock(&vm->inst_cache_lock) +#define vm_inst_cache_lock_destroy(vm) sx_destroy(&vm->inst_cache_lock) + #endif /* _VMM_INSTRUCTION_EMUL_H_ */ Modified: soc2014/mihai/bhyve-icache-head/sys/amd64/vmm/vmm.c ============================================================================== --- soc2014/mihai/bhyve-icache-head/sys/amd64/vmm/vmm.c Wed Jun 11 11:27:44 2014 (r269398) +++ soc2014/mihai/bhyve-icache-head/sys/amd64/vmm/vmm.c Wed Jun 11 12:25:32 2014 (r269399) @@ -145,6 +145,8 @@ volatile cpuset_t suspended_cpus; volatile cpuset_t halted_cpus; + + struct sx inst_cache_lock; }; static int vmm_initialized; @@ -371,6 +373,8 @@ vm->vatpic = vatpic_init(vm); vm->vatpit = vatpit_init(vm); + vm_inst_cache_lock_init(vm); + for (i = 0; i < VM_MAXCPU; i++) { vcpu_init(vm, i); guest_msrs_init(vm, i); @@ -407,6 +411,8 @@ vatpic_cleanup(vm->vatpic); vioapic_cleanup(vm->vioapic); + vm_inst_cache_lock_destroy(vm); + for (i = 0; i < vm->num_mem_segs; i++) vm_free_mem_seg(vm, &vm->mem_segs[i]); @@ -1099,21 +1105,18 @@ struct vm_map *map; struct vcpu *vcpu; struct vm_exit *vme; + bool inst_cache_locked; vcpu = &vm->vcpu[vcpuid]; vme = &vcpu->exitinfo; + inst_cache_locked = false; ftype = vme->u.paging.fault_type; KASSERT(ftype == VM_PROT_READ || ftype == VM_PROT_WRITE || ftype == VM_PROT_EXECUTE, ("vm_handle_paging: invalid fault_type %d", ftype)); - if (ftype == VM_PROT_WRITE) { - /* Remove all the instructions that resides in this page */ - vm_inst_cache_delete(vm, vme->u.paging.gpa, vme->u.paging.cr3); - } - - +again: if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) { rv = pmap_emulate_accessed_dirty(vmspace_pmap(vm->vmspace), vme->u.paging.gpa, ftype); @@ -1123,14 +1126,32 @@ map = &vm->vmspace->vm_map; rv = vm_fault(map, vme->u.paging.gpa, ftype, VM_FAULT_NORMAL); + + if (rv == KERN_PROTECTION_FAILURE) { + /* + * Try to resolve the fault again after evicting any related + * instructions from the cache. This may cause the readonly + * restrictions to go away. + */ + if (!inst_cache_locked) { + inst_cache_locked = true; + vm_inst_cache_xlock(vm); + vm_inst_cache_delete(vm, vme->u.paging.gpa, vme->u.paging.cr3); + goto again; + } + } VCPU_CTR3(vm, vcpuid, "vm_handle_paging rv = %d, gpa = %#lx, " "ftype = %d", rv, vme->u.paging.gpa, ftype); +done: + if (inst_cache_locked) + vm_inst_cache_unlock(vm); + if (rv != KERN_SUCCESS) return (EFAULT); -done: - /* restart execution at the faulting instruction */ + + /* restart execution at the faulting instruction */ vme->inst_length = 0; return (0); @@ -1163,7 +1184,10 @@ vie = &vme->u.inst_emul.vie; /* Check to see if the instruction is cached */ + vm_inst_cache_slock(vm); if (vm_inst_cache_lookup(vm, rip, cr3, vie)) { + vm_inst_cache_unlock(vm); + vie_init(vie); /* Fetch, decode and emulate the faulting instruction */ @@ -1174,9 +1198,11 @@ if (vmm_decode_instruction(vm, vcpuid, gla, cpu_mode, vie) != 0) return (EFAULT); + vm_inst_cache_xlock(vm); /* Cache decoded instruction for further use */ vm_inst_cache_add(vm, rip, cr3, paging_mode, vie); } + vm_inst_cache_unlock(vm); /* return to userland unless this is an in-kernel emulated device */ if (gpa >= DEFAULT_APIC_BASE && gpa < DEFAULT_APIC_BASE + PAGE_SIZE) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406111225.s5BCPWsY072485>