diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-27 16:41:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-27 16:41:54 -0400 |
commit | e28e909c36bb5d6319953822d84df00fce7cbd18 (patch) | |
tree | a4aca971908a7a604c6fdd9a95360728f9f721b3 /arch/arm/kvm | |
parent | dc03c0f9d12d85286d5e3623aa96d5c2a271b8e6 (diff) | |
parent | fabc712866435660f7fa1070e1fabe29eba5bc4c (diff) |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull second batch of KVM updates from Radim Krčmář:
"General:
- move kvm_stat tool from QEMU repo into tools/kvm/kvm_stat (kvm_stat
had nothing to do with QEMU in the first place -- the tool only
interprets debugfs)
- expose per-vm statistics in debugfs and support them in kvm_stat
(KVM always collected per-vm statistics, but they were summarised
into global statistics)
x86:
- fix dynamic APICv (VMX was improperly configured and a guest could
access host's APIC MSRs, CVE-2016-4440)
- minor fixes
ARM changes from Christoffer Dall:
- new vgic reimplementation of our horribly broken legacy vgic
implementation. The two implementations will live side-by-side
(with the new being the configured default) for one kernel release
and then we'll remove the legacy one.
- fix for a non-critical issue with virtual abort injection to guests"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (70 commits)
tools: kvm_stat: Add comments
tools: kvm_stat: Introduce pid monitoring
KVM: Create debugfs dir and stat files for each VM
MAINTAINERS: Add kvm tools
tools: kvm_stat: Powerpc related fixes
tools: Add kvm_stat man page
tools: Add kvm_stat vm monitor script
kvm:vmx: more complete state update on APICv on/off
KVM: SVM: Add more SVM_EXIT_REASONS
KVM: Unify traced vector format
svm: bitwise vs logical op typo
KVM: arm/arm64: vgic-new: Synchronize changes to active state
KVM: arm/arm64: vgic-new: enable build
KVM: arm/arm64: vgic-new: implement mapped IRQ handling
KVM: arm/arm64: vgic-new: Wire up irqfd injection
KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable
KVM: arm/arm64: vgic-new: vgic_init: implement map_resources
KVM: arm/arm64: vgic-new: vgic_init: implement vgic_init
KVM: arm/arm64: vgic-new: vgic_init: implement vgic_create
KVM: arm/arm64: vgic-new: vgic_init: implement kvm_vgic_hyp_init
...
Diffstat (limited to 'arch/arm/kvm')
-rw-r--r-- | arch/arm/kvm/Kconfig | 7 | ||||
-rw-r--r-- | arch/arm/kvm/Makefile | 11 | ||||
-rw-r--r-- | arch/arm/kvm/arm.c | 37 | ||||
-rw-r--r-- | arch/arm/kvm/mmio.c | 24 |
4 files changed, 52 insertions, 27 deletions
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig index 95a000515e43..02abfff68ee5 100644 --- a/arch/arm/kvm/Kconfig +++ b/arch/arm/kvm/Kconfig | |||
@@ -46,6 +46,13 @@ config KVM_ARM_HOST | |||
46 | ---help--- | 46 | ---help--- |
47 | Provides host support for ARM processors. | 47 | Provides host support for ARM processors. |
48 | 48 | ||
49 | config KVM_NEW_VGIC | ||
50 | bool "New VGIC implementation" | ||
51 | depends on KVM | ||
52 | default y | ||
53 | ---help--- | ||
54 | uses the new VGIC implementation | ||
55 | |||
49 | source drivers/vhost/Kconfig | 56 | source drivers/vhost/Kconfig |
50 | 57 | ||
51 | endif # VIRTUALIZATION | 58 | endif # VIRTUALIZATION |
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index eb1bf4309c13..a596b58f6d37 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile | |||
@@ -21,7 +21,18 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/ | |||
21 | obj-y += kvm-arm.o init.o interrupts.o | 21 | obj-y += kvm-arm.o init.o interrupts.o |
22 | obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o | 22 | obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o |
23 | obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o | 23 | obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o |
24 | |||
25 | ifeq ($(CONFIG_KVM_NEW_VGIC),y) | ||
26 | obj-y += $(KVM)/arm/vgic/vgic.o | ||
27 | obj-y += $(KVM)/arm/vgic/vgic-init.o | ||
28 | obj-y += $(KVM)/arm/vgic/vgic-irqfd.o | ||
29 | obj-y += $(KVM)/arm/vgic/vgic-v2.o | ||
30 | obj-y += $(KVM)/arm/vgic/vgic-mmio.o | ||
31 | obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o | ||
32 | obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o | ||
33 | else | ||
24 | obj-y += $(KVM)/arm/vgic.o | 34 | obj-y += $(KVM)/arm/vgic.o |
25 | obj-y += $(KVM)/arm/vgic-v2.o | 35 | obj-y += $(KVM)/arm/vgic-v2.o |
26 | obj-y += $(KVM)/arm/vgic-v2-emul.o | 36 | obj-y += $(KVM)/arm/vgic-v2-emul.o |
37 | endif | ||
27 | obj-y += $(KVM)/arm/arch_timer.o | 38 | obj-y += $(KVM)/arm/arch_timer.o |
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 237d5d82f0af..893941ec98dc 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -455,7 +455,7 @@ static void update_vttbr(struct kvm *kvm) | |||
455 | static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) | 455 | static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) |
456 | { | 456 | { |
457 | struct kvm *kvm = vcpu->kvm; | 457 | struct kvm *kvm = vcpu->kvm; |
458 | int ret; | 458 | int ret = 0; |
459 | 459 | ||
460 | if (likely(vcpu->arch.has_run_once)) | 460 | if (likely(vcpu->arch.has_run_once)) |
461 | return 0; | 461 | return 0; |
@@ -478,9 +478,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) | |||
478 | * interrupts from the virtual timer with a userspace gic. | 478 | * interrupts from the virtual timer with a userspace gic. |
479 | */ | 479 | */ |
480 | if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) | 480 | if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) |
481 | kvm_timer_enable(kvm); | 481 | ret = kvm_timer_enable(vcpu); |
482 | 482 | ||
483 | return 0; | 483 | return ret; |
484 | } | 484 | } |
485 | 485 | ||
486 | bool kvm_arch_intc_initialized(struct kvm *kvm) | 486 | bool kvm_arch_intc_initialized(struct kvm *kvm) |
@@ -488,30 +488,37 @@ bool kvm_arch_intc_initialized(struct kvm *kvm) | |||
488 | return vgic_initialized(kvm); | 488 | return vgic_initialized(kvm); |
489 | } | 489 | } |
490 | 490 | ||
491 | static void kvm_arm_halt_guest(struct kvm *kvm) __maybe_unused; | 491 | void kvm_arm_halt_guest(struct kvm *kvm) |
492 | static void kvm_arm_resume_guest(struct kvm *kvm) __maybe_unused; | ||
493 | |||
494 | static void kvm_arm_halt_guest(struct kvm *kvm) | ||
495 | { | 492 | { |
496 | int i; | 493 | int i; |
497 | struct kvm_vcpu *vcpu; | 494 | struct kvm_vcpu *vcpu; |
498 | 495 | ||
499 | kvm_for_each_vcpu(i, vcpu, kvm) | 496 | kvm_for_each_vcpu(i, vcpu, kvm) |
500 | vcpu->arch.pause = true; | 497 | vcpu->arch.pause = true; |
501 | force_vm_exit(cpu_all_mask); | 498 | kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT); |
499 | } | ||
500 | |||
501 | void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu) | ||
502 | { | ||
503 | vcpu->arch.pause = true; | ||
504 | kvm_vcpu_kick(vcpu); | ||
502 | } | 505 | } |
503 | 506 | ||
504 | static void kvm_arm_resume_guest(struct kvm *kvm) | 507 | void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu) |
508 | { | ||
509 | struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); | ||
510 | |||
511 | vcpu->arch.pause = false; | ||
512 | swake_up(wq); | ||
513 | } | ||
514 | |||
515 | void kvm_arm_resume_guest(struct kvm *kvm) | ||
505 | { | 516 | { |
506 | int i; | 517 | int i; |
507 | struct kvm_vcpu *vcpu; | 518 | struct kvm_vcpu *vcpu; |
508 | 519 | ||
509 | kvm_for_each_vcpu(i, vcpu, kvm) { | 520 | kvm_for_each_vcpu(i, vcpu, kvm) |
510 | struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu); | 521 | kvm_arm_resume_vcpu(vcpu); |
511 | |||
512 | vcpu->arch.pause = false; | ||
513 | swake_up(wq); | ||
514 | } | ||
515 | } | 522 | } |
516 | 523 | ||
517 | static void vcpu_sleep(struct kvm_vcpu *vcpu) | 524 | static void vcpu_sleep(struct kvm_vcpu *vcpu) |
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c index 0f6600f05137..10f80a6c797a 100644 --- a/arch/arm/kvm/mmio.c +++ b/arch/arm/kvm/mmio.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | #include "trace.h" | 24 | #include "trace.h" |
25 | 25 | ||
26 | static void mmio_write_buf(char *buf, unsigned int len, unsigned long data) | 26 | void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data) |
27 | { | 27 | { |
28 | void *datap = NULL; | 28 | void *datap = NULL; |
29 | union { | 29 | union { |
@@ -55,7 +55,7 @@ static void mmio_write_buf(char *buf, unsigned int len, unsigned long data) | |||
55 | memcpy(buf, datap, len); | 55 | memcpy(buf, datap, len); |
56 | } | 56 | } |
57 | 57 | ||
58 | static unsigned long mmio_read_buf(char *buf, unsigned int len) | 58 | unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len) |
59 | { | 59 | { |
60 | unsigned long data = 0; | 60 | unsigned long data = 0; |
61 | union { | 61 | union { |
@@ -66,7 +66,7 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len) | |||
66 | 66 | ||
67 | switch (len) { | 67 | switch (len) { |
68 | case 1: | 68 | case 1: |
69 | data = buf[0]; | 69 | data = *(u8 *)buf; |
70 | break; | 70 | break; |
71 | case 2: | 71 | case 2: |
72 | memcpy(&tmp.hword, buf, len); | 72 | memcpy(&tmp.hword, buf, len); |
@@ -87,11 +87,10 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len) | |||
87 | 87 | ||
88 | /** | 88 | /** |
89 | * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation | 89 | * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation |
90 | * or in-kernel IO emulation | ||
91 | * | ||
90 | * @vcpu: The VCPU pointer | 92 | * @vcpu: The VCPU pointer |
91 | * @run: The VCPU run struct containing the mmio data | 93 | * @run: The VCPU run struct containing the mmio data |
92 | * | ||
93 | * This should only be called after returning from userspace for MMIO load | ||
94 | * emulation. | ||
95 | */ | 94 | */ |
96 | int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) | 95 | int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) |
97 | { | 96 | { |
@@ -104,7 +103,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
104 | if (len > sizeof(unsigned long)) | 103 | if (len > sizeof(unsigned long)) |
105 | return -EINVAL; | 104 | return -EINVAL; |
106 | 105 | ||
107 | data = mmio_read_buf(run->mmio.data, len); | 106 | data = kvm_mmio_read_buf(run->mmio.data, len); |
108 | 107 | ||
109 | if (vcpu->arch.mmio_decode.sign_extend && | 108 | if (vcpu->arch.mmio_decode.sign_extend && |
110 | len < sizeof(unsigned long)) { | 109 | len < sizeof(unsigned long)) { |
@@ -190,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, | |||
190 | len); | 189 | len); |
191 | 190 | ||
192 | trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data); | 191 | trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data); |
193 | mmio_write_buf(data_buf, len, data); | 192 | kvm_mmio_write_buf(data_buf, len, data); |
194 | 193 | ||
195 | ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len, | 194 | ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len, |
196 | data_buf); | 195 | data_buf); |
@@ -206,18 +205,19 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, | |||
206 | run->mmio.is_write = is_write; | 205 | run->mmio.is_write = is_write; |
207 | run->mmio.phys_addr = fault_ipa; | 206 | run->mmio.phys_addr = fault_ipa; |
208 | run->mmio.len = len; | 207 | run->mmio.len = len; |
209 | if (is_write) | ||
210 | memcpy(run->mmio.data, data_buf, len); | ||
211 | 208 | ||
212 | if (!ret) { | 209 | if (!ret) { |
213 | /* We handled the access successfully in the kernel. */ | 210 | /* We handled the access successfully in the kernel. */ |
211 | if (!is_write) | ||
212 | memcpy(run->mmio.data, data_buf, len); | ||
214 | vcpu->stat.mmio_exit_kernel++; | 213 | vcpu->stat.mmio_exit_kernel++; |
215 | kvm_handle_mmio_return(vcpu, run); | 214 | kvm_handle_mmio_return(vcpu, run); |
216 | return 1; | 215 | return 1; |
217 | } else { | ||
218 | vcpu->stat.mmio_exit_user++; | ||
219 | } | 216 | } |
220 | 217 | ||
218 | if (is_write) | ||
219 | memcpy(run->mmio.data, data_buf, len); | ||
220 | vcpu->stat.mmio_exit_user++; | ||
221 | run->exit_reason = KVM_EXIT_MMIO; | 221 | run->exit_reason = KVM_EXIT_MMIO; |
222 | return 0; | 222 | return 0; |
223 | } | 223 | } |