Skip site navigation (1)Skip section navigation (2)
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>