aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/kvm.h1
-rw-r--r--drivers/kvm/kvm_main.c16
2 files changed, 14 insertions, 3 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index f99e89e185b2..41634fde8e13 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -310,6 +310,7 @@ struct kvm_vcpu {
310 int mmio_size; 310 int mmio_size;
311 unsigned char mmio_data[8]; 311 unsigned char mmio_data[8];
312 gpa_t mmio_phys_addr; 312 gpa_t mmio_phys_addr;
313 gva_t mmio_fault_cr2;
313 struct kvm_pio_request pio; 314 struct kvm_pio_request pio;
314 void *pio_data; 315 void *pio_data;
315 316
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index cdf0b176851d..f267dbb52845 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -1186,6 +1186,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
1186 int r; 1186 int r;
1187 int cs_db, cs_l; 1187 int cs_db, cs_l;
1188 1188
1189 vcpu->mmio_fault_cr2 = cr2;
1189 kvm_arch_ops->cache_regs(vcpu); 1190 kvm_arch_ops->cache_regs(vcpu);
1190 1191
1191 kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); 1192 kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
@@ -1804,14 +1805,23 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1804 r = complete_pio(vcpu); 1805 r = complete_pio(vcpu);
1805 if (r) 1806 if (r)
1806 goto out; 1807 goto out;
1807 } else { 1808 } else if (!vcpu->mmio_is_write) {
1808 memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); 1809 memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
1809 vcpu->mmio_read_completed = 1; 1810 vcpu->mmio_read_completed = 1;
1811 vcpu->mmio_needed = 0;
1812 r = emulate_instruction(vcpu, kvm_run,
1813 vcpu->mmio_fault_cr2, 0);
1814 if (r == EMULATE_DO_MMIO) {
1815 /*
1816 * Read-modify-write. Back to userspace.
1817 */
1818 kvm_run->exit_reason = KVM_EXIT_MMIO;
1819 r = 0;
1820 goto out;
1821 }
1810 } 1822 }
1811 } 1823 }
1812 1824
1813 vcpu->mmio_needed = 0;
1814
1815 if (kvm_run->exit_reason == KVM_EXIT_HYPERCALL) { 1825 if (kvm_run->exit_reason == KVM_EXIT_HYPERCALL) {
1816 kvm_arch_ops->cache_regs(vcpu); 1826 kvm_arch_ops->cache_regs(vcpu);
1817 vcpu->regs[VCPU_REGS_RAX] = kvm_run->hypercall.ret; 1827 vcpu->regs[VCPU_REGS_RAX] = kvm_run->hypercall.ret;