aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-27 16:41:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-27 16:41:54 -0400
commite28e909c36bb5d6319953822d84df00fce7cbd18 (patch)
treea4aca971908a7a604c6fdd9a95360728f9f721b3 /arch/arm/kvm
parentdc03c0f9d12d85286d5e3623aa96d5c2a271b8e6 (diff)
parentfabc712866435660f7fa1070e1fabe29eba5bc4c (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/Kconfig7
-rw-r--r--arch/arm/kvm/Makefile11
-rw-r--r--arch/arm/kvm/arm.c37
-rw-r--r--arch/arm/kvm/mmio.c24
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
49config KVM_NEW_VGIC
50 bool "New VGIC implementation"
51 depends on KVM
52 default y
53 ---help---
54 uses the new VGIC implementation
55
49source drivers/vhost/Kconfig 56source drivers/vhost/Kconfig
50 57
51endif # VIRTUALIZATION 58endif # 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/
21obj-y += kvm-arm.o init.o interrupts.o 21obj-y += kvm-arm.o init.o interrupts.o
22obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o 22obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
23obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o 23obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
24
25ifeq ($(CONFIG_KVM_NEW_VGIC),y)
26obj-y += $(KVM)/arm/vgic/vgic.o
27obj-y += $(KVM)/arm/vgic/vgic-init.o
28obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
29obj-y += $(KVM)/arm/vgic/vgic-v2.o
30obj-y += $(KVM)/arm/vgic/vgic-mmio.o
31obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
32obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
33else
24obj-y += $(KVM)/arm/vgic.o 34obj-y += $(KVM)/arm/vgic.o
25obj-y += $(KVM)/arm/vgic-v2.o 35obj-y += $(KVM)/arm/vgic-v2.o
26obj-y += $(KVM)/arm/vgic-v2-emul.o 36obj-y += $(KVM)/arm/vgic-v2-emul.o
37endif
27obj-y += $(KVM)/arm/arch_timer.o 38obj-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)
455static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) 455static 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
486bool kvm_arch_intc_initialized(struct kvm *kvm) 486bool 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
491static void kvm_arm_halt_guest(struct kvm *kvm) __maybe_unused; 491void kvm_arm_halt_guest(struct kvm *kvm)
492static void kvm_arm_resume_guest(struct kvm *kvm) __maybe_unused;
493
494static 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
501void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu)
502{
503 vcpu->arch.pause = true;
504 kvm_vcpu_kick(vcpu);
502} 505}
503 506
504static void kvm_arm_resume_guest(struct kvm *kvm) 507void 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
515void 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
517static void vcpu_sleep(struct kvm_vcpu *vcpu) 524static 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
26static void mmio_write_buf(char *buf, unsigned int len, unsigned long data) 26void 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
58static unsigned long mmio_read_buf(char *buf, unsigned int len) 58unsigned 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 */
96int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) 95int 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}