diff options
-rw-r--r-- | arch/ia64/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 10 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 114 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 31 |
4 files changed, 115 insertions, 42 deletions
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h index c4b4bac3d09e..6d6a5ac48d85 100644 --- a/arch/ia64/include/asm/kvm_host.h +++ b/arch/ia64/include/asm/kvm_host.h | |||
@@ -449,6 +449,8 @@ struct kvm_vcpu_arch { | |||
449 | char log_buf[VMM_LOG_LEN]; | 449 | char log_buf[VMM_LOG_LEN]; |
450 | union context host; | 450 | union context host; |
451 | union context guest; | 451 | union context guest; |
452 | |||
453 | char mmio_data[8]; | ||
452 | }; | 454 | }; |
453 | 455 | ||
454 | struct kvm_vm_stat { | 456 | struct kvm_vm_stat { |
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 9d80ff8d9eff..882ab21a8dcd 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -232,12 +232,12 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
232 | if ((p->addr & PAGE_MASK) == IOAPIC_DEFAULT_BASE_ADDRESS) | 232 | if ((p->addr & PAGE_MASK) == IOAPIC_DEFAULT_BASE_ADDRESS) |
233 | goto mmio; | 233 | goto mmio; |
234 | vcpu->mmio_needed = 1; | 234 | vcpu->mmio_needed = 1; |
235 | vcpu->mmio_phys_addr = kvm_run->mmio.phys_addr = p->addr; | 235 | vcpu->mmio_fragments[0].gpa = kvm_run->mmio.phys_addr = p->addr; |
236 | vcpu->mmio_size = kvm_run->mmio.len = p->size; | 236 | vcpu->mmio_fragments[0].len = kvm_run->mmio.len = p->size; |
237 | vcpu->mmio_is_write = kvm_run->mmio.is_write = !p->dir; | 237 | vcpu->mmio_is_write = kvm_run->mmio.is_write = !p->dir; |
238 | 238 | ||
239 | if (vcpu->mmio_is_write) | 239 | if (vcpu->mmio_is_write) |
240 | memcpy(vcpu->mmio_data, &p->data, p->size); | 240 | memcpy(vcpu->arch.mmio_data, &p->data, p->size); |
241 | memcpy(kvm_run->mmio.data, &p->data, p->size); | 241 | memcpy(kvm_run->mmio.data, &p->data, p->size); |
242 | kvm_run->exit_reason = KVM_EXIT_MMIO; | 242 | kvm_run->exit_reason = KVM_EXIT_MMIO; |
243 | return 0; | 243 | return 0; |
@@ -719,7 +719,7 @@ static void kvm_set_mmio_data(struct kvm_vcpu *vcpu) | |||
719 | struct kvm_mmio_req *p = kvm_get_vcpu_ioreq(vcpu); | 719 | struct kvm_mmio_req *p = kvm_get_vcpu_ioreq(vcpu); |
720 | 720 | ||
721 | if (!vcpu->mmio_is_write) | 721 | if (!vcpu->mmio_is_write) |
722 | memcpy(&p->data, vcpu->mmio_data, 8); | 722 | memcpy(&p->data, vcpu->arch.mmio_data, 8); |
723 | p->state = STATE_IORESP_READY; | 723 | p->state = STATE_IORESP_READY; |
724 | } | 724 | } |
725 | 725 | ||
@@ -739,7 +739,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
739 | } | 739 | } |
740 | 740 | ||
741 | if (vcpu->mmio_needed) { | 741 | if (vcpu->mmio_needed) { |
742 | memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); | 742 | memcpy(vcpu->arch.mmio_data, kvm_run->mmio.data, 8); |
743 | kvm_set_mmio_data(vcpu); | 743 | kvm_set_mmio_data(vcpu); |
744 | vcpu->mmio_read_completed = 1; | 744 | vcpu->mmio_read_completed = 1; |
745 | vcpu->mmio_needed = 0; | 745 | vcpu->mmio_needed = 0; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0d9a57875f0b..4de705cdcafd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -3718,9 +3718,8 @@ struct read_write_emulator_ops { | |||
3718 | static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes) | 3718 | static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes) |
3719 | { | 3719 | { |
3720 | if (vcpu->mmio_read_completed) { | 3720 | if (vcpu->mmio_read_completed) { |
3721 | memcpy(val, vcpu->mmio_data, bytes); | ||
3722 | trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, | 3721 | trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, |
3723 | vcpu->mmio_phys_addr, *(u64 *)val); | 3722 | vcpu->mmio_fragments[0].gpa, *(u64 *)val); |
3724 | vcpu->mmio_read_completed = 0; | 3723 | vcpu->mmio_read_completed = 0; |
3725 | return 1; | 3724 | return 1; |
3726 | } | 3725 | } |
@@ -3756,8 +3755,9 @@ static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
3756 | static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, | 3755 | static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, |
3757 | void *val, int bytes) | 3756 | void *val, int bytes) |
3758 | { | 3757 | { |
3759 | memcpy(vcpu->mmio_data, val, bytes); | 3758 | struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0]; |
3760 | memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8); | 3759 | |
3760 | memcpy(vcpu->run->mmio.data, frag->data, frag->len); | ||
3761 | return X86EMUL_CONTINUE; | 3761 | return X86EMUL_CONTINUE; |
3762 | } | 3762 | } |
3763 | 3763 | ||
@@ -3784,10 +3784,7 @@ static int emulator_read_write_onepage(unsigned long addr, void *val, | |||
3784 | gpa_t gpa; | 3784 | gpa_t gpa; |
3785 | int handled, ret; | 3785 | int handled, ret; |
3786 | bool write = ops->write; | 3786 | bool write = ops->write; |
3787 | 3787 | struct kvm_mmio_fragment *frag; | |
3788 | if (ops->read_write_prepare && | ||
3789 | ops->read_write_prepare(vcpu, val, bytes)) | ||
3790 | return X86EMUL_CONTINUE; | ||
3791 | 3788 | ||
3792 | ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write); | 3789 | ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write); |
3793 | 3790 | ||
@@ -3813,15 +3810,19 @@ mmio: | |||
3813 | bytes -= handled; | 3810 | bytes -= handled; |
3814 | val += handled; | 3811 | val += handled; |
3815 | 3812 | ||
3816 | vcpu->mmio_needed = 1; | 3813 | while (bytes) { |
3817 | vcpu->run->exit_reason = KVM_EXIT_MMIO; | 3814 | unsigned now = min(bytes, 8U); |
3818 | vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa; | ||
3819 | vcpu->mmio_size = bytes; | ||
3820 | vcpu->run->mmio.len = min(vcpu->mmio_size, 8); | ||
3821 | vcpu->run->mmio.is_write = vcpu->mmio_is_write = write; | ||
3822 | vcpu->mmio_index = 0; | ||
3823 | 3815 | ||
3824 | return ops->read_write_exit_mmio(vcpu, gpa, val, bytes); | 3816 | frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; |
3817 | frag->gpa = gpa; | ||
3818 | frag->data = val; | ||
3819 | frag->len = now; | ||
3820 | |||
3821 | gpa += now; | ||
3822 | val += now; | ||
3823 | bytes -= now; | ||
3824 | } | ||
3825 | return X86EMUL_CONTINUE; | ||
3825 | } | 3826 | } |
3826 | 3827 | ||
3827 | int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr, | 3828 | int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr, |
@@ -3830,10 +3831,18 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr, | |||
3830 | struct read_write_emulator_ops *ops) | 3831 | struct read_write_emulator_ops *ops) |
3831 | { | 3832 | { |
3832 | struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); | 3833 | struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); |
3834 | gpa_t gpa; | ||
3835 | int rc; | ||
3836 | |||
3837 | if (ops->read_write_prepare && | ||
3838 | ops->read_write_prepare(vcpu, val, bytes)) | ||
3839 | return X86EMUL_CONTINUE; | ||
3840 | |||
3841 | vcpu->mmio_nr_fragments = 0; | ||
3833 | 3842 | ||
3834 | /* Crossing a page boundary? */ | 3843 | /* Crossing a page boundary? */ |
3835 | if (((addr + bytes - 1) ^ addr) & PAGE_MASK) { | 3844 | if (((addr + bytes - 1) ^ addr) & PAGE_MASK) { |
3836 | int rc, now; | 3845 | int now; |
3837 | 3846 | ||
3838 | now = -addr & ~PAGE_MASK; | 3847 | now = -addr & ~PAGE_MASK; |
3839 | rc = emulator_read_write_onepage(addr, val, now, exception, | 3848 | rc = emulator_read_write_onepage(addr, val, now, exception, |
@@ -3846,8 +3855,25 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr, | |||
3846 | bytes -= now; | 3855 | bytes -= now; |
3847 | } | 3856 | } |
3848 | 3857 | ||
3849 | return emulator_read_write_onepage(addr, val, bytes, exception, | 3858 | rc = emulator_read_write_onepage(addr, val, bytes, exception, |
3850 | vcpu, ops); | 3859 | vcpu, ops); |
3860 | if (rc != X86EMUL_CONTINUE) | ||
3861 | return rc; | ||
3862 | |||
3863 | if (!vcpu->mmio_nr_fragments) | ||
3864 | return rc; | ||
3865 | |||
3866 | gpa = vcpu->mmio_fragments[0].gpa; | ||
3867 | |||
3868 | vcpu->mmio_needed = 1; | ||
3869 | vcpu->mmio_cur_fragment = 0; | ||
3870 | |||
3871 | vcpu->run->mmio.len = vcpu->mmio_fragments[0].len; | ||
3872 | vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write; | ||
3873 | vcpu->run->exit_reason = KVM_EXIT_MMIO; | ||
3874 | vcpu->run->mmio.phys_addr = gpa; | ||
3875 | |||
3876 | return ops->read_write_exit_mmio(vcpu, gpa, val, bytes); | ||
3851 | } | 3877 | } |
3852 | 3878 | ||
3853 | static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt, | 3879 | static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt, |
@@ -5446,33 +5472,55 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
5446 | return r; | 5472 | return r; |
5447 | } | 5473 | } |
5448 | 5474 | ||
5475 | /* | ||
5476 | * Implements the following, as a state machine: | ||
5477 | * | ||
5478 | * read: | ||
5479 | * for each fragment | ||
5480 | * write gpa, len | ||
5481 | * exit | ||
5482 | * copy data | ||
5483 | * execute insn | ||
5484 | * | ||
5485 | * write: | ||
5486 | * for each fragment | ||
5487 | * write gpa, len | ||
5488 | * copy data | ||
5489 | * exit | ||
5490 | */ | ||
5449 | static int complete_mmio(struct kvm_vcpu *vcpu) | 5491 | static int complete_mmio(struct kvm_vcpu *vcpu) |
5450 | { | 5492 | { |
5451 | struct kvm_run *run = vcpu->run; | 5493 | struct kvm_run *run = vcpu->run; |
5494 | struct kvm_mmio_fragment *frag; | ||
5452 | int r; | 5495 | int r; |
5453 | 5496 | ||
5454 | if (!(vcpu->arch.pio.count || vcpu->mmio_needed)) | 5497 | if (!(vcpu->arch.pio.count || vcpu->mmio_needed)) |
5455 | return 1; | 5498 | return 1; |
5456 | 5499 | ||
5457 | if (vcpu->mmio_needed) { | 5500 | if (vcpu->mmio_needed) { |
5458 | vcpu->mmio_needed = 0; | 5501 | /* Complete previous fragment */ |
5502 | frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++]; | ||
5459 | if (!vcpu->mmio_is_write) | 5503 | if (!vcpu->mmio_is_write) |
5460 | memcpy(vcpu->mmio_data + vcpu->mmio_index, | 5504 | memcpy(frag->data, run->mmio.data, frag->len); |
5461 | run->mmio.data, 8); | 5505 | if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) { |
5462 | vcpu->mmio_index += 8; | 5506 | vcpu->mmio_needed = 0; |
5463 | if (vcpu->mmio_index < vcpu->mmio_size) { | 5507 | if (vcpu->mmio_is_write) |
5464 | run->exit_reason = KVM_EXIT_MMIO; | 5508 | return 1; |
5465 | run->mmio.phys_addr = vcpu->mmio_phys_addr + vcpu->mmio_index; | 5509 | vcpu->mmio_read_completed = 1; |
5466 | memcpy(run->mmio.data, vcpu->mmio_data + vcpu->mmio_index, 8); | 5510 | goto done; |
5467 | run->mmio.len = min(vcpu->mmio_size - vcpu->mmio_index, 8); | ||
5468 | run->mmio.is_write = vcpu->mmio_is_write; | ||
5469 | vcpu->mmio_needed = 1; | ||
5470 | return 0; | ||
5471 | } | 5511 | } |
5512 | /* Initiate next fragment */ | ||
5513 | ++frag; | ||
5514 | run->exit_reason = KVM_EXIT_MMIO; | ||
5515 | run->mmio.phys_addr = frag->gpa; | ||
5472 | if (vcpu->mmio_is_write) | 5516 | if (vcpu->mmio_is_write) |
5473 | return 1; | 5517 | memcpy(run->mmio.data, frag->data, frag->len); |
5474 | vcpu->mmio_read_completed = 1; | 5518 | run->mmio.len = frag->len; |
5519 | run->mmio.is_write = vcpu->mmio_is_write; | ||
5520 | return 0; | ||
5521 | |||
5475 | } | 5522 | } |
5523 | done: | ||
5476 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); | 5524 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); |
5477 | r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE); | 5525 | r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE); |
5478 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | 5526 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index a2d00b1bbf54..186ffab0b9f0 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -35,6 +35,20 @@ | |||
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * If we support unaligned MMIO, at most one fragment will be split into two: | ||
39 | */ | ||
40 | #ifdef KVM_UNALIGNED_MMIO | ||
41 | # define KVM_EXTRA_MMIO_FRAGMENTS 1 | ||
42 | #else | ||
43 | # define KVM_EXTRA_MMIO_FRAGMENTS 0 | ||
44 | #endif | ||
45 | |||
46 | #define KVM_USER_MMIO_SIZE 8 | ||
47 | |||
48 | #define KVM_MAX_MMIO_FRAGMENTS \ | ||
49 | (KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS) | ||
50 | |||
51 | /* | ||
38 | * vcpu->requests bit members | 52 | * vcpu->requests bit members |
39 | */ | 53 | */ |
40 | #define KVM_REQ_TLB_FLUSH 0 | 54 | #define KVM_REQ_TLB_FLUSH 0 |
@@ -117,6 +131,16 @@ enum { | |||
117 | EXITING_GUEST_MODE | 131 | EXITING_GUEST_MODE |
118 | }; | 132 | }; |
119 | 133 | ||
134 | /* | ||
135 | * Sometimes a large or cross-page mmio needs to be broken up into separate | ||
136 | * exits for userspace servicing. | ||
137 | */ | ||
138 | struct kvm_mmio_fragment { | ||
139 | gpa_t gpa; | ||
140 | void *data; | ||
141 | unsigned len; | ||
142 | }; | ||
143 | |||
120 | struct kvm_vcpu { | 144 | struct kvm_vcpu { |
121 | struct kvm *kvm; | 145 | struct kvm *kvm; |
122 | #ifdef CONFIG_PREEMPT_NOTIFIERS | 146 | #ifdef CONFIG_PREEMPT_NOTIFIERS |
@@ -144,10 +168,9 @@ struct kvm_vcpu { | |||
144 | int mmio_needed; | 168 | int mmio_needed; |
145 | int mmio_read_completed; | 169 | int mmio_read_completed; |
146 | int mmio_is_write; | 170 | int mmio_is_write; |
147 | int mmio_size; | 171 | int mmio_cur_fragment; |
148 | int mmio_index; | 172 | int mmio_nr_fragments; |
149 | unsigned char mmio_data[KVM_MMIO_SIZE]; | 173 | struct kvm_mmio_fragment mmio_fragments[KVM_MAX_MMIO_FRAGMENTS]; |
150 | gpa_t mmio_phys_addr; | ||
151 | #endif | 174 | #endif |
152 | 175 | ||
153 | #ifdef CONFIG_KVM_ASYNC_PF | 176 | #ifdef CONFIG_KVM_ASYNC_PF |