aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/kvm_arm.h11
-rw-r--r--arch/arm/include/asm/kvm_coproc.h14
-rw-r--r--arch/arm/include/asm/kvm_emulate.h6
-rw-r--r--arch/arm/include/asm/kvm_host.h4
-rw-r--r--arch/arm/kvm/Makefile2
-rw-r--r--arch/arm/kvm/arm.c169
-rw-r--r--arch/arm/kvm/coproc.c360
-rw-r--r--arch/arm/kvm/coproc.h153
-rw-r--r--arch/arm/kvm/coproc_a15.c162
-rw-r--r--arch/arm/kvm/emulate.c218
-rw-r--r--arch/arm/kvm/trace.h65
11 files changed, 1160 insertions, 4 deletions
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index c69936b1fc53..9a34c20d41ec 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -70,6 +70,11 @@
70 HCR_SWIO | HCR_TIDCP) 70 HCR_SWIO | HCR_TIDCP)
71#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF) 71#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
72 72
73/* System Control Register (SCTLR) bits */
74#define SCTLR_TE (1 << 30)
75#define SCTLR_EE (1 << 25)
76#define SCTLR_V (1 << 13)
77
73/* Hyp System Control Register (HSCTLR) bits */ 78/* Hyp System Control Register (HSCTLR) bits */
74#define HSCTLR_TE (1 << 30) 79#define HSCTLR_TE (1 << 30)
75#define HSCTLR_EE (1 << 25) 80#define HSCTLR_EE (1 << 25)
@@ -171,6 +176,10 @@
171#define HSR_FSC (0x3f) 176#define HSR_FSC (0x3f)
172#define HSR_FSC_TYPE (0x3c) 177#define HSR_FSC_TYPE (0x3c)
173#define HSR_WNR (1 << 6) 178#define HSR_WNR (1 << 6)
179#define HSR_CV_SHIFT (24)
180#define HSR_CV (1U << HSR_CV_SHIFT)
181#define HSR_COND_SHIFT (20)
182#define HSR_COND (0xfU << HSR_COND_SHIFT)
174 183
175#define FSC_FAULT (0x04) 184#define FSC_FAULT (0x04)
176#define FSC_PERM (0x0c) 185#define FSC_PERM (0x0c)
@@ -197,4 +206,6 @@
197#define HSR_EC_DABT (0x24) 206#define HSR_EC_DABT (0x24)
198#define HSR_EC_DABT_HYP (0x25) 207#define HSR_EC_DABT_HYP (0x25)
199 208
209#define HSR_HVC_IMM_MASK ((1UL << 16) - 1)
210
200#endif /* __ARM_KVM_ARM_H__ */ 211#endif /* __ARM_KVM_ARM_H__ */
diff --git a/arch/arm/include/asm/kvm_coproc.h b/arch/arm/include/asm/kvm_coproc.h
index b6d023deb426..bd1ace030495 100644
--- a/arch/arm/include/asm/kvm_coproc.h
+++ b/arch/arm/include/asm/kvm_coproc.h
@@ -21,4 +21,18 @@
21 21
22void kvm_reset_coprocs(struct kvm_vcpu *vcpu); 22void kvm_reset_coprocs(struct kvm_vcpu *vcpu);
23 23
24struct kvm_coproc_target_table {
25 unsigned target;
26 const struct coproc_reg *table;
27 size_t num;
28};
29void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table);
30
31int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
32int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
33int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
34int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
35int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
36int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
37void kvm_coproc_table_init(void);
24#endif /* __ARM_KVM_COPROC_H__ */ 38#endif /* __ARM_KVM_COPROC_H__ */
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index 17dad674b90f..01a755b80632 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -25,6 +25,12 @@
25u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num); 25u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
26u32 *vcpu_spsr(struct kvm_vcpu *vcpu); 26u32 *vcpu_spsr(struct kvm_vcpu *vcpu);
27 27
28int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run);
29void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr);
30void kvm_inject_undefined(struct kvm_vcpu *vcpu);
31void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
32void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
33
28static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu) 34static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu)
29{ 35{
30 return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc; 36 return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc;
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 7a121089c733..e1d4168d4f19 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -94,6 +94,10 @@ struct kvm_vcpu_arch {
94 * Anything that is not used directly from assembly code goes 94 * Anything that is not used directly from assembly code goes
95 * here. 95 * here.
96 */ 96 */
97 /* dcache set/way operation pending */
98 int last_pcpu;
99 cpumask_t require_dcache_flush;
100
97 /* Interrupt related fields */ 101 /* Interrupt related fields */
98 u32 irq_lines; /* IRQ and FIQ levels */ 102 u32 irq_lines; /* IRQ and FIQ levels */
99 103
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index dfc293f277b3..88edce6c97d4 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -18,4 +18,4 @@ kvm-arm-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
18 18
19obj-y += kvm-arm.o init.o interrupts.o 19obj-y += kvm-arm.o init.o interrupts.o
20obj-y += arm.o guest.o mmu.o emulate.o reset.o 20obj-y += arm.o guest.o mmu.o emulate.o reset.o
21obj-y += coproc.o 21obj-y += coproc.o coproc_a15.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9e9fa4477884..be06c5de51e3 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -36,11 +36,14 @@
36#include <asm/mman.h> 36#include <asm/mman.h>
37#include <asm/cputype.h> 37#include <asm/cputype.h>
38#include <asm/tlbflush.h> 38#include <asm/tlbflush.h>
39#include <asm/cacheflush.h>
39#include <asm/virt.h> 40#include <asm/virt.h>
40#include <asm/kvm_arm.h> 41#include <asm/kvm_arm.h>
41#include <asm/kvm_asm.h> 42#include <asm/kvm_asm.h>
42#include <asm/kvm_mmu.h> 43#include <asm/kvm_mmu.h>
43#include <asm/kvm_emulate.h> 44#include <asm/kvm_emulate.h>
45#include <asm/kvm_coproc.h>
46#include <asm/opcodes.h>
44 47
45#ifdef REQUIRES_VIRT 48#ifdef REQUIRES_VIRT
46__asm__(".arch_extension virt"); 49__asm__(".arch_extension virt");
@@ -294,6 +297,15 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
294{ 297{
295 vcpu->cpu = cpu; 298 vcpu->cpu = cpu;
296 vcpu->arch.vfp_host = this_cpu_ptr(kvm_host_vfp_state); 299 vcpu->arch.vfp_host = this_cpu_ptr(kvm_host_vfp_state);
300
301 /*
302 * Check whether this vcpu requires the cache to be flushed on
303 * this physical CPU. This is a consequence of doing dcache
304 * operations by set/way on this vcpu. We do it here to be in
305 * a non-preemptible section.
306 */
307 if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush))
308 flush_cache_all(); /* We'd really want v7_flush_dcache_all() */
297} 309}
298 310
299void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) 311void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -319,9 +331,16 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
319 return -EINVAL; 331 return -EINVAL;
320} 332}
321 333
334/**
335 * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled
336 * @v: The VCPU pointer
337 *
338 * If the guest CPU is not waiting for interrupts or an interrupt line is
339 * asserted, the CPU is by definition runnable.
340 */
322int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) 341int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
323{ 342{
324 return 0; 343 return !!v->arch.irq_lines;
325} 344}
326 345
327/* Just ensure a guest exit from a particular CPU */ 346/* Just ensure a guest exit from a particular CPU */
@@ -411,6 +430,110 @@ static void update_vttbr(struct kvm *kvm)
411 spin_unlock(&kvm_vmid_lock); 430 spin_unlock(&kvm_vmid_lock);
412} 431}
413 432
433static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
434{
435 /* SVC called from Hyp mode should never get here */
436 kvm_debug("SVC called from Hyp mode shouldn't go here\n");
437 BUG();
438 return -EINVAL; /* Squash warning */
439}
440
441static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
442{
443 trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
444 vcpu->arch.hsr & HSR_HVC_IMM_MASK);
445
446 kvm_inject_undefined(vcpu);
447 return 1;
448}
449
450static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
451