diff options
| -rw-r--r-- | arch/arm/include/asm/kvm_arm.h | 11 | ||||
| -rw-r--r-- | arch/arm/include/asm/kvm_coproc.h | 14 | ||||
| -rw-r--r-- | arch/arm/include/asm/kvm_emulate.h | 6 | ||||
| -rw-r--r-- | arch/arm/include/asm/kvm_host.h | 4 | ||||
| -rw-r--r-- | arch/arm/kvm/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/kvm/arm.c | 169 | ||||
| -rw-r--r-- | arch/arm/kvm/coproc.c | 360 | ||||
| -rw-r--r-- | arch/arm/kvm/coproc.h | 153 | ||||
| -rw-r--r-- | arch/arm/kvm/coproc_a15.c | 162 | ||||
| -rw-r--r-- | arch/arm/kvm/emulate.c | 218 | ||||
| -rw-r--r-- | arch/arm/kvm/trace.h | 65 |
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 | ||
| 22 | void kvm_reset_coprocs(struct kvm_vcpu *vcpu); | 22 | void kvm_reset_coprocs(struct kvm_vcpu *vcpu); |
| 23 | 23 | ||
| 24 | struct kvm_coproc_target_table { | ||
| 25 | unsigned target; | ||
| 26 | const struct coproc_reg *table; | ||
| 27 | size_t num; | ||
| 28 | }; | ||
| 29 | void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table); | ||
| 30 | |||
| 31 | int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
| 32 | int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
| 33 | int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
| 34 | int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
| 35 | int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
| 36 | int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
| 37 | void 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 @@ | |||
| 25 | u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num); | 25 | u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num); |
| 26 | u32 *vcpu_spsr(struct kvm_vcpu *vcpu); | 26 | u32 *vcpu_spsr(struct kvm_vcpu *vcpu); |
| 27 | 27 | ||
| 28 | int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run); | ||
| 29 | void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr); | ||
| 30 | void kvm_inject_undefined(struct kvm_vcpu *vcpu); | ||
| 31 | void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); | ||
| 32 | void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); | ||
| 33 | |||
| 28 | static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu) | 34 | static 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 | ||
| 19 | obj-y += kvm-arm.o init.o interrupts.o | 19 | obj-y += kvm-arm.o init.o interrupts.o |
| 20 | obj-y += arm.o guest.o mmu.o emulate.o reset.o | 20 | obj-y += arm.o guest.o mmu.o emulate.o reset.o |
| 21 | obj-y += coproc.o | 21 | obj-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 | ||
| 299 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) | 311 | void 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 | */ | ||
| 322 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) | 341 | int 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 | ||
| 433 | static 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 | |||
| 441 | static 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 | |||
| 450 | static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
| 451 | |||
