diff options
-rw-r--r-- | drivers/kvm/kvm.h | 1 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 16 |
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; |