Bläddra i källkod

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm:
  KVM: disable writeback for 0x0f 0x01 instructions.
  KVM: Fix removal of nx capability from guest cpuid
  Revert "KVM: Avoid useless memory write when possible"
  KVM: Fix unlikely kvm_create vs decache_vcpus_on_cpu race
  KVM: Correctly handle writes crossing a page boundary
Linus Torvalds 18 år sedan
förälder
incheckning
a9417357cf
2 ändrade filer med 33 tillägg och 13 borttagningar
  1. 31 13
      drivers/kvm/kvm_main.c
  2. 2 0
      drivers/kvm/x86_emulate.c

+ 31 - 13
drivers/kvm/kvm_main.c

@@ -297,9 +297,6 @@ static struct kvm *kvm_create_vm(void)
 	kvm_io_bus_init(&kvm->pio_bus);
 	spin_lock_init(&kvm->lock);
 	INIT_LIST_HEAD(&kvm->active_mmu_pages);
-	spin_lock(&kvm_lock);
-	list_add(&kvm->vm_list, &vm_list);
-	spin_unlock(&kvm_lock);
 	kvm_io_bus_init(&kvm->mmio_bus);
 	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
 		struct kvm_vcpu *vcpu = &kvm->vcpus[i];
@@ -309,6 +306,9 @@ static struct kvm *kvm_create_vm(void)
 		vcpu->kvm = kvm;
 		vcpu->mmu.root_hpa = INVALID_PAGE;
 	}
+	spin_lock(&kvm_lock);
+	list_add(&kvm->vm_list, &vm_list);
+	spin_unlock(&kvm_lock);
 	return kvm;
 }
 
@@ -1070,18 +1070,16 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
 		return 0;
 	mark_page_dirty(vcpu->kvm, gpa >> PAGE_SHIFT);
 	virt = kmap_atomic(page, KM_USER0);
-	if (memcmp(virt + offset_in_page(gpa), val, bytes)) {
-		kvm_mmu_pte_write(vcpu, gpa, virt + offset, val, bytes);
-		memcpy(virt + offset_in_page(gpa), val, bytes);
-	}
+	kvm_mmu_pte_write(vcpu, gpa, virt + offset, val, bytes);
+	memcpy(virt + offset_in_page(gpa), val, bytes);
 	kunmap_atomic(virt, KM_USER0);
 	return 1;
 }
 
-static int emulator_write_emulated(unsigned long addr,
-				   const void *val,
-				   unsigned int bytes,
-				   struct x86_emulate_ctxt *ctxt)
+static int emulator_write_emulated_onepage(unsigned long addr,
+					   const void *val,
+					   unsigned int bytes,
+					   struct x86_emulate_ctxt *ctxt)
 {
 	struct kvm_vcpu      *vcpu = ctxt->vcpu;
 	struct kvm_io_device *mmio_dev;
@@ -1113,6 +1111,26 @@ static int emulator_write_emulated(unsigned long addr,
 	return X86EMUL_CONTINUE;
 }
 
+static int emulator_write_emulated(unsigned long addr,
+				   const void *val,
+				   unsigned int bytes,
+				   struct x86_emulate_ctxt *ctxt)
+{
+	/* Crossing a page boundary? */
+	if (((addr + bytes - 1) ^ addr) & PAGE_MASK) {
+		int rc, now;
+
+		now = -addr & ~PAGE_MASK;
+		rc = emulator_write_emulated_onepage(addr, val, now, ctxt);
+		if (rc != X86EMUL_CONTINUE)
+			return rc;
+		addr += now;
+		val += now;
+		bytes -= now;
+	}
+	return emulator_write_emulated_onepage(addr, val, bytes, ctxt);
+}
+
 static int emulator_cmpxchg_emulated(unsigned long addr,
 				     const void *old,
 				     const void *new,
@@ -2414,9 +2432,9 @@ static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
 			break;
 		}
 	}
-	if (entry && (entry->edx & EFER_NX) && !(efer & EFER_NX)) {
+	if (entry && (entry->edx & (1 << 20)) && !(efer & EFER_NX)) {
 		entry->edx &= ~(1 << 20);
-		printk(KERN_INFO ": guest NX capability removed\n");
+		printk(KERN_INFO "kvm: guest NX capability removed\n");
 	}
 }
 

+ 2 - 0
drivers/kvm/x86_emulate.c

@@ -1178,6 +1178,8 @@ pop_instruction:
 twobyte_insn:
 	switch (b) {
 	case 0x01: /* lgdt, lidt, lmsw */
+		/* Disable writeback. */
+		no_wb = 1;
 		switch (modrm_reg) {
 			u16 size;
 			unsigned long address;