Merge tag 'kvmarm-for-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm...
authorPaolo Bonzini <pbonzini@redhat.com>
Fri, 22 Feb 2019 16:45:05 +0000 (17:45 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 22 Feb 2019 16:45:05 +0000 (17:45 +0100)
KVM/arm updates for Linux v5.1

- A number of pre-nested code rework
- Direct physical timer assignment on VHE systems
- kvm_call_hyp type safety enforcement
- Set/Way cache sanitisation for 32bit guests
- Build system cleanups
- A bunch of janitorial fixes

33 files changed:
MAINTAINERS
arch/arm/include/asm/arch_gicv3.h
arch/arm/include/asm/kvm_emulate.h
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/kvm_hyp.h
arch/arm/include/asm/kvm_mmu.h
arch/arm/kvm/Makefile
arch/arm/kvm/coproc.c
arch/arm/kvm/hyp/cp15-sr.c
arch/arm/kvm/hyp/hyp-entry.S
arch/arm/kvm/hyp/switch.c
arch/arm/kvm/hyp/tlb.c
arch/arm/kvm/interrupts.S
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/sysreg.h
arch/arm64/kvm/Makefile
arch/arm64/kvm/debug.c
arch/arm64/kvm/hyp.S
arch/arm64/kvm/hyp/hyp-entry.S
arch/arm64/kvm/hyp/sysreg-sr.c
arch/arm64/kvm/sys_regs.c
drivers/clocksource/arm_arch_timer.c
include/clocksource/arm_arch_timer.h
include/kvm/arm_arch_timer.h
virt/kvm/arm/arch_timer.c
virt/kvm/arm/arm.c
virt/kvm/arm/hyp/vgic-v3-sr.c
virt/kvm/arm/mmu.c
virt/kvm/arm/trace.h
virt/kvm/arm/vgic/vgic-v3.c

index 9919840..8347269 100644 (file)
@@ -8304,29 +8304,25 @@ S:      Maintained
 F:     arch/x86/include/asm/svm.h
 F:     arch/x86/kvm/svm.c
 
-KERNEL VIRTUAL MACHINE FOR ARM (KVM/arm)
+KERNEL VIRTUAL MACHINE FOR ARM/ARM64 (KVM/arm, KVM/arm64)
 M:     Christoffer Dall <christoffer.dall@arm.com>
 M:     Marc Zyngier <marc.zyngier@arm.com>
+R:     James Morse <james.morse@arm.com>
+R:     Julien Thierry <julien.thierry@arm.com>
+R:     Suzuki K Pouloze <suzuki.poulose@arm.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     kvmarm@lists.cs.columbia.edu
 W:     http://systems.cs.columbia.edu/projects/kvm-arm
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
-S:     Supported
+S:     Maintained
 F:     arch/arm/include/uapi/asm/kvm*
 F:     arch/arm/include/asm/kvm*
 F:     arch/arm/kvm/
-F:     virt/kvm/arm/
-F:     include/kvm/arm_*
-
-KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
-M:     Christoffer Dall <christoffer.dall@arm.com>
-M:     Marc Zyngier <marc.zyngier@arm.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-L:     kvmarm@lists.cs.columbia.edu
-S:     Maintained
 F:     arch/arm64/include/uapi/asm/kvm*
 F:     arch/arm64/include/asm/kvm*
 F:     arch/arm64/kvm/
+F:     virt/kvm/arm/
+F:     include/kvm/arm_*
 
 KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
 M:     James Hogan <jhogan@kernel.org>
index 0bd5307..bdc8770 100644 (file)
@@ -54,7 +54,7 @@
 #define ICH_VTR                                __ACCESS_CP15(c12, 4, c11, 1)
 #define ICH_MISR                       __ACCESS_CP15(c12, 4, c11, 2)
 #define ICH_EISR                       __ACCESS_CP15(c12, 4, c11, 3)
-#define ICH_ELSR                       __ACCESS_CP15(c12, 4, c11, 5)
+#define ICH_ELRSR                      __ACCESS_CP15(c12, 4, c11, 5)
 #define ICH_VMCR                       __ACCESS_CP15(c12, 4, c11, 7)
 
 #define __LR0(x)                       __ACCESS_CP15(c12, 4, c12, x)
@@ -151,7 +151,7 @@ CPUIF_MAP(ICH_HCR, ICH_HCR_EL2)
 CPUIF_MAP(ICH_VTR, ICH_VTR_EL2)
 CPUIF_MAP(ICH_MISR, ICH_MISR_EL2)
 CPUIF_MAP(ICH_EISR, ICH_EISR_EL2)
-CPUIF_MAP(ICH_ELSR, ICH_ELSR_EL2)
+CPUIF_MAP(ICH_ELRSR, ICH_ELRSR_EL2)
 CPUIF_MAP(ICH_VMCR, ICH_VMCR_EL2)
 CPUIF_MAP(ICH_AP0R3, ICH_AP0R3_EL2)
 CPUIF_MAP(ICH_AP0R2, ICH_AP0R2_EL2)
index 77121b7..8927cae 100644 (file)
@@ -265,6 +265,14 @@ static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu)
        }
 }
 
+static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
+{
+       if (kvm_vcpu_trap_is_iabt(vcpu))
+               return false;
+
+       return kvm_vcpu_dabt_iswrite(vcpu);
+}
+
 static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK;
index ca56537..8073267 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmio.h>
 #include <asm/fpstate.h>
+#include <asm/smp_plat.h>
 #include <kvm/arm_arch_timer.h>
 
 #define __KVM_HAVE_ARCH_INTC_INITIALIZED
@@ -56,10 +57,13 @@ int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
 void kvm_reset_coprocs(struct kvm_vcpu *vcpu);
 
-struct kvm_arch {
-       /* VTTBR value associated with below pgd and vmid */
-       u64    vttbr;
+struct kvm_vmid {
+       /* The VMID generation used for the virt. memory system */
+       u64    vmid_gen;
+       u32    vmid;
+};
 
+struct kvm_arch {
        /* The last vcpu id that ran on each physical CPU */
        int __percpu *last_vcpu_ran;
 
@@ -69,11 +73,11 @@ struct kvm_arch {
         */
 
        /* The VMID generation used for the virt. memory system */
-       u64    vmid_gen;
-       u32    vmid;
+       struct kvm_vmid vmid;
 
        /* Stage-2 page table */
        pgd_t *pgd;
+       phys_addr_t pgd_phys;
 
        /* Interrupt controller */
        struct vgic_dist        vgic;
@@ -147,6 +151,13 @@ struct kvm_cpu_context {
 
 typedef struct kvm_cpu_context kvm_cpu_context_t;
 
+static inline void kvm_init_host_cpu_context(kvm_cpu_context_t *cpu_ctxt,
+                                            int cpu)
+{
+       /* The host's MPIDR is immutable, so let's set it up at boot time */
+       cpu_ctxt->cp15[c0_MPIDR] = cpu_logical_map(cpu);
+}
+
 struct kvm_vcpu_arch {
        struct kvm_cpu_context ctxt;
 
@@ -214,7 +225,35 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
 int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
 int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
 int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
-unsigned long kvm_call_hyp(void *hypfn, ...);
+
+unsigned long __kvm_call_hyp(void *hypfn, ...);
+
+/*
+ * The has_vhe() part doesn't get emitted, but is used for type-checking.
+ */
+#define kvm_call_hyp(f, ...)                                           \
+       do {                                                            \
+               if (has_vhe()) {                                        \
+                       f(__VA_ARGS__);                                 \
+               } else {                                                \
+                       __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__); \
+               }                                                       \
+       } while(0)
+
+#define kvm_call_hyp_ret(f, ...)                                       \
+       ({                                                              \
+               typeof(f(__VA_ARGS__)) ret;                             \
+                                                                       \
+               if (has_vhe()) {                                        \
+                       ret = f(__VA_ARGS__);                           \
+               } else {                                                \
+                       ret = __kvm_call_hyp(kvm_ksym_ref(f),           \
+                                            ##__VA_ARGS__);            \
+               }                                                       \
+                                                                       \
+               ret;                                                    \
+       })
+
 void force_vm_exit(const cpumask_t *mask);
 int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
                              struct kvm_vcpu_events *events);
@@ -265,7 +304,7 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
         * compliant with the PCS!).
         */
 
-       kvm_call_hyp((void*)hyp_stack_ptr, vector_ptr, pgd_ptr);
+       __kvm_call_hyp((void*)hyp_stack_ptr, vector_ptr, pgd_ptr);
 }
 
 static inline void __cpu_init_stage2(void)
index e93a0ca..87bcd18 100644 (file)
@@ -40,6 +40,7 @@
 #define TTBR1          __ACCESS_CP15_64(1, c2)
 #define VTTBR          __ACCESS_CP15_64(6, c2)
 #define PAR            __ACCESS_CP15_64(0, c7)
+#define CNTP_CVAL      __ACCESS_CP15_64(2, c14)
 #define CNTV_CVAL      __ACCESS_CP15_64(3, c14)
 #define CNTVOFF                __ACCESS_CP15_64(4, c14)
 
@@ -85,6 +86,7 @@
 #define TID_PRIV       __ACCESS_CP15(c13, 0, c0, 4)
 #define HTPIDR         __ACCESS_CP15(c13, 4, c0, 2)
 #define CNTKCTL                __ACCESS_CP15(c14, 0, c1, 0)
+#define CNTP_CTL       __ACCESS_CP15(c14, 0, c2, 1)
 #define CNTV_CTL       __ACCESS_CP15(c14, 0, c3, 1)
 #define CNTHCTL                __ACCESS_CP15(c14, 4, c1, 0)
 
@@ -94,6 +96,8 @@
 #define read_sysreg_el0(r)             read_sysreg(r##_el0)
 #define write_sysreg_el0(v, r)         write_sysreg(v, r##_el0)
 
+#define cntp_ctl_el0                   CNTP_CTL
+#define cntp_cval_el0                  CNTP_CVAL
 #define cntv_ctl_el0                   CNTV_CTL
 #define cntv_cval_el0                  CNTV_CVAL
 #define cntvoff_el2                    CNTVOFF
index 3a875fc..2de96a1 100644 (file)
@@ -421,9 +421,14 @@ static inline int hyp_map_aux_data(void)
 
 static inline void kvm_set_ipa_limit(void) {}
 
-static inline bool kvm_cpu_has_cnp(void)
+static __always_inline u64 kvm_get_vttbr(struct kvm *kvm)
 {
-       return false;
+       struct kvm_vmid *vmid = &kvm->arch.vmid;
+       u64 vmid_field, baddr;
+
+       baddr = kvm->arch.pgd_phys;
+       vmid_field = (u64)vmid->vmid << VTTBR_VMID_SHIFT;
+       return kvm_phys_to_vttbr(baddr) | vmid_field;
 }
 
 #endif /* !__ASSEMBLY__ */
index 48de846..531e59f 100644 (file)
@@ -8,9 +8,8 @@ ifeq ($(plus_virt),+virt)
        plus_virt_def := -DREQUIRES_VIRT=1
 endif
 
-ccflags-y += -Iarch/arm/kvm -Ivirt/kvm/arm/vgic
-CFLAGS_arm.o := -I. $(plus_virt_def)
-CFLAGS_mmu.o := -I.
+ccflags-y += -I $(srctree)/$(src) -I $(srctree)/virt/kvm/arm/vgic
+CFLAGS_arm.o := $(plus_virt_def)
 
 AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
 AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
index 222c163..5186336 100644 (file)
@@ -293,15 +293,16 @@ static bool access_cntp_tval(struct kvm_vcpu *vcpu,
                             const struct coproc_params *p,
                             const struct coproc_reg *r)
 {
-       u64 now = kvm_phys_timer_read();
-       u64 val;
+       u32 val;
 
        if (p->is_write) {
                val = *vcpu_reg(vcpu, p->Rt1);
-               kvm_arm_timer_set_reg(vcpu, KVM_REG_ARM_PTIMER_CVAL, val + now);
+               kvm_arm_timer_write_sysreg(vcpu,
+                                          TIMER_PTIMER, TIMER_REG_TVAL, val);
        } else {
-               val = kvm_arm_timer_get_reg(vcpu, KVM_REG_ARM_PTIMER_CVAL);
-               *vcpu_reg(vcpu, p->Rt1) = val - now;
+               val = kvm_arm_timer_read_sysreg(vcpu,
+                                               TIMER_PTIMER, TIMER_REG_TVAL);
+               *vcpu_reg(vcpu, p->Rt1) = val;
        }
 
        return true;
@@ -315,9 +316,11 @@ static bool access_cntp_ctl(struct kvm_vcpu *vcpu,
 
        if (p->is_write) {
                val = *vcpu_reg(vcpu, p->Rt1);
-               kvm_arm_timer_set_reg(vcpu, KVM_REG_ARM_PTIMER_CTL, val);
+               kvm_arm_timer_write_sysreg(vcpu,
+                                          TIMER_PTIMER, TIMER_REG_CTL, val);
        } else {
-               val = kvm_arm_timer_get_reg(vcpu, KVM_REG_ARM_PTIMER_CTL);
+               val = kvm_arm_timer_read_sysreg(vcpu,
+                                               TIMER_PTIMER, TIMER_REG_CTL);
                *vcpu_reg(vcpu, p->Rt1) = val;
        }
 
@@ -333,9 +336,11 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu,
        if (p->is_write) {
                val = (u64)*vcpu_reg(vcpu, p->Rt2) << 32;
                val |= *vcpu_reg(vcpu, p->Rt1);
-               kvm_arm_timer_set_reg(vcpu, KVM_REG_ARM_PTIMER_CVAL, val);
+               kvm_arm_timer_write_sysreg(vcpu,
+                                          TIMER_PTIMER, TIMER_REG_CVAL, val);
        } else {
-               val = kvm_arm_timer_get_reg(vcpu, KVM_REG_ARM_PTIMER_CVAL);
+               val = kvm_arm_timer_read_sysreg(vcpu,
+                                               TIMER_PTIMER, TIMER_REG_CVAL);
                *vcpu_reg(vcpu, p->Rt1) = val;
                *vcpu_reg(vcpu, p->Rt2) = val >> 32;
        }
index c478281..8bf895e 100644 (file)
@@ -27,7 +27,6 @@ static u64 *cp15_64(struct kvm_cpu_context *ctxt, int idx)
 
 void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
 {
-       ctxt->cp15[c0_MPIDR]            = read_sysreg(VMPIDR);
        ctxt->cp15[c0_CSSELR]           = read_sysreg(CSSELR);
        ctxt->cp15[c1_SCTLR]            = read_sysreg(SCTLR);
        ctxt->cp15[c1_CPACR]            = read_sysreg(CPACR);
index aa3f9a9..6ed3cf2 100644 (file)
@@ -176,7 +176,7 @@ THUMB(      orr     lr, lr, #PSR_T_BIT      )
        msr     spsr_cxsf, lr
        ldr     lr, =panic
        msr     ELR_hyp, lr
-       ldr     lr, =kvm_call_hyp
+       ldr     lr, =__kvm_call_hyp
        clrex
        eret
 ENDPROC(__hyp_do_panic)
index acf1c37..3b058a5 100644 (file)
@@ -77,7 +77,7 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
 static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
 {
        struct kvm *kvm = kern_hyp_va(vcpu->kvm);
-       write_sysreg(kvm->arch.vttbr, VTTBR);
+       write_sysreg(kvm_get_vttbr(kvm), VTTBR);
        write_sysreg(vcpu->arch.midr, VPIDR);
 }
 
index c0edd45..8e4afba 100644 (file)
@@ -41,7 +41,7 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
 
        /* Switch to requested VMID */
        kvm = kern_hyp_va(kvm);
-       write_sysreg(kvm->arch.vttbr, VTTBR);
+       write_sysreg(kvm_get_vttbr(kvm), VTTBR);
        isb();
 
        write_sysreg(0, TLBIALLIS);
@@ -61,7 +61,7 @@ void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
        struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
 
        /* Switch to requested VMID */
-       write_sysreg(kvm->arch.vttbr, VTTBR);
+       write_sysreg(kvm_get_vttbr(kvm), VTTBR);
        isb();
 
        write_sysreg(0, TLBIALL);
index 80a1d6c..a08e641 100644 (file)
@@ -42,7 +42,7 @@
  *   r12:     caller save
  *   rest:    callee save
  */
-ENTRY(kvm_call_hyp)
+ENTRY(__kvm_call_hyp)
        hvc     #0
        bx      lr
-ENDPROC(kvm_call_hyp)
+ENDPROC(__kvm_call_hyp)
index 506386a..d384279 100644 (file)
@@ -77,6 +77,10 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
         */
        if (!vcpu_el1_is_32bit(vcpu))
                vcpu->arch.hcr_el2 |= HCR_TID3;
+
+       if (cpus_have_const_cap(ARM64_MISMATCHED_CACHE_TYPE) ||
+           vcpu_el1_is_32bit(vcpu))
+               vcpu->arch.hcr_el2 |= HCR_TID2;
 }
 
 static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
@@ -331,6 +335,14 @@ static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
        return ESR_ELx_SYS64_ISS_RT(esr);
 }
 
+static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
+{
+       if (kvm_vcpu_trap_is_iabt(vcpu))
+               return false;
+
+       return kvm_vcpu_dabt_iswrite(vcpu);
+}
+
 static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 {
        return vcpu_read_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
index 7732d0b..444dd1c 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/kvm.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmio.h>
+#include <asm/smp_plat.h>
 #include <asm/thread_info.h>
 
 #define __KVM_HAVE_ARCH_INTC_INITIALIZED
@@ -56,16 +57,19 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
 int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext);
 void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start);
 
-struct kvm_arch {
+struct kvm_vmid {
        /* The VMID generation used for the virt. memory system */
        u64    vmid_gen;
        u32    vmid;
+};
+
+struct kvm_arch {
+       struct kvm_vmid vmid;
 
        /* stage2 entry level table */
        pgd_t *pgd;
+       phys_addr_t pgd_phys;
 
-       /* VTTBR value associated with above pgd and vmid */
-       u64    vttbr;
        /* VTCR_EL2 value for this VM */
        u64    vtcr;
 
@@ -370,7 +374,36 @@ void kvm_arm_halt_guest(struct kvm *kvm);
 void kvm_arm_resume_guest(struct kvm *kvm);
 
 u64 __kvm_call_hyp(void *hypfn, ...);
-#define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
+
+/*
+ * The couple of isb() below are there to guarantee the same behaviour
+ * on VHE as on !VHE, where the eret to EL1 acts as a context
+ * synchronization event.
+ */
+#define kvm_call_hyp(f, ...)                                           \
+       do {                                                            \
+               if (has_vhe()) {                                        \
+                       f(__VA_ARGS__);                                 \
+                       isb();                                          \
+               } else {                                                \
+                       __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__); \
+               }                                                       \
+       } while(0)
+
+#define kvm_call_hyp_ret(f, ...)                                       \
+       ({                                                              \
+               typeof(f(__VA_ARGS__)) ret;                             \
+                                                                       \
+               if (has_vhe()) {                                        \
+                       ret = f(__VA_ARGS__);                           \
+                       isb();                                          \
+               } else {                                                \
+                       ret = __kvm_call_hyp(kvm_ksym_ref(f),           \
+                                            ##__VA_ARGS__);            \
+               }                                                       \
+                                                                       \
+               ret;                                                    \
+       })
 
 void force_vm_exit(const cpumask_t *mask);
 void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
@@ -389,6 +422,13 @@ struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
 
 DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
 
+static inline void kvm_init_host_cpu_context(kvm_cpu_context_t *cpu_ctxt,
+                                            int cpu)
+{
+       /* The host's MPIDR is immutable, so let's set it up at boot time */
+       cpu_ctxt->sys_regs[MPIDR_EL1] = cpu_logical_map(cpu);
+}
+
 void __kvm_enable_ssbs(void);
 
 static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
index a80a7ef..4da765f 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/compiler.h>
 #include <linux/kvm_host.h>
 #include <asm/alternative.h>
+#include <asm/kvm_mmu.h>
 #include <asm/sysreg.h>
 
 #define __hyp_text __section(.hyp.text) notrace
@@ -163,7 +164,7 @@ void __noreturn __hyp_do_panic(unsigned long, ...);
 static __always_inline void __hyp_text __load_guest_stage2(struct kvm *kvm)
 {
        write_sysreg(kvm->arch.vtcr, vtcr_el2);
-       write_sysreg(kvm->arch.vttbr, vttbr_el2);
+       write_sysreg(kvm_get_vttbr(kvm), vttbr_el2);
 
        /*
         * ARM erratum 1165522 requires the actual execution of the above
index 8af4b1b..b0742a1 100644 (file)
@@ -138,7 +138,8 @@ static inline unsigned long __kern_hyp_va(unsigned long v)
        })
 
 /*
- * We currently only support a 40bit IPA.
+ * We currently support using a VM-specified IPA size. For backward
+ * compatibility, the default IPA size is fixed to 40bits.
  */
 #define KVM_PHYS_SHIFT (40)
 
@@ -591,9 +592,15 @@ static inline u64 kvm_vttbr_baddr_mask(struct kvm *kvm)
        return vttbr_baddr_mask(kvm_phys_shift(kvm), kvm_stage2_levels(kvm));
 }
 
-static inline bool kvm_cpu_has_cnp(void)
+static __always_inline u64 kvm_get_vttbr(struct kvm *kvm)
 {
-       return system_supports_cnp();
+       struct kvm_vmid *vmid = &kvm->arch.vmid;
+       u64 vmid_field, baddr;
+       u64 cnp = system_supports_cnp() ? VTTBR_CNP_BIT : 0;
+
+       baddr = kvm->arch.pgd_phys;
+       vmid_field = (u64)vmid->vmid << VTTBR_VMID_SHIFT;
+       return kvm_phys_to_vttbr(baddr) | vmid_field | cnp;
 }
 
 #endif /* __ASSEMBLY__ */
index 72dc4c0..5b267de 100644 (file)
 
 #define SYS_CNTKCTL_EL1                        sys_reg(3, 0, 14, 1, 0)
 
+#define SYS_CCSIDR_EL1                 sys_reg(3, 1, 0, 0, 0)
 #define SYS_CLIDR_EL1                  sys_reg(3, 1, 0, 0, 1)
 #define SYS_AIDR_EL1                   sys_reg(3, 1, 0, 0, 7)
 
 #define SYS_CNTP_CTL_EL0               sys_reg(3, 3, 14, 2, 1)
 #define SYS_CNTP_CVAL_EL0              sys_reg(3, 3, 14, 2, 2)
 
+#define SYS_AARCH32_CNTP_TVAL          sys_reg(0, 0, 14, 2, 0)
+#define SYS_AARCH32_CNTP_CTL           sys_reg(0, 0, 14, 2, 1)
+#define SYS_AARCH32_CNTP_CVAL          sys_reg(0, 2, 0, 14, 0)
+
 #define __PMEV_op2(n)                  ((n) & 0x7)
 #define __CNTR_CRm(n)                  (0x8 | (((n) >> 3) & 0x3))
 #define SYS_PMEVCNTRn_EL0(n)           sys_reg(3, 3, 14, __CNTR_CRm(n), __PMEV_op2(n))
 #define SYS_ICH_VTR_EL2                        sys_reg(3, 4, 12, 11, 1)
 #define SYS_ICH_MISR_EL2               sys_reg(3, 4, 12, 11, 2)
 #define SYS_ICH_EISR_EL2               sys_reg(3, 4, 12, 11, 3)
-#define SYS_ICH_ELSR_EL2               sys_reg(3, 4, 12, 11, 5)
+#define SYS_ICH_ELRSR_EL2              sys_reg(3, 4, 12, 11, 5)
 #define SYS_ICH_VMCR_EL2               sys_reg(3, 4, 12, 11, 7)
 
 #define __SYS__LR0_EL2(x)              sys_reg(3, 4, 12, 12, x)
index 0f2a135..690e033 100644 (file)
@@ -3,9 +3,7 @@
 # Makefile for Kernel-based Virtual Machine module
 #
 
-ccflags-y += -Iarch/arm64/kvm -Ivirt/kvm/arm/vgic
-CFLAGS_arm.o := -I.
-CFLAGS_mmu.o := -I.
+ccflags-y += -I $(srctree)/$(src) -I $(srctree)/virt/kvm/arm/vgic
 
 KVM=../../../virt/kvm
 
index f39801e..fd917d6 100644 (file)
@@ -76,7 +76,7 @@ static void restore_guest_debug_regs(struct kvm_vcpu *vcpu)
 
 void kvm_arm_init_debug(void)
 {
-       __this_cpu_write(mdcr_el2, kvm_call_hyp(__kvm_get_mdcr_el2));
+       __this_cpu_write(mdcr_el2, kvm_call_hyp_ret(__kvm_get_mdcr_el2));
 }
 
 /**
index 952f6cb..2845aa6 100644 (file)
@@ -40,9 +40,6 @@
  * arch/arm64/kernel/hyp_stub.S.
  */
 ENTRY(__kvm_call_hyp)
-alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
        hvc     #0
        ret
-alternative_else_nop_endif
-       b       __vhe_hyp_call
 ENDPROC(__kvm_call_hyp)
index 73c1b48..2b1e686 100644 (file)
        ldr     lr, [sp], #16
 .endm
 
-ENTRY(__vhe_hyp_call)
-       do_el2_call
-       /*
-        * We used to rely on having an exception return to get
-        * an implicit isb. In the E2H case, we don't have it anymore.
-        * rather than changing all the leaf functions, just do it here
-        * before returning to the rest of the kernel.
-        */
-       isb
-       ret
-ENDPROC(__vhe_hyp_call)
-
 el1_sync:                              // Guest trapped into EL2
 
        mrs     x0, esr_el2
index 68d6f7c..2498f86 100644 (file)
@@ -52,7 +52,6 @@ static void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
 
 static void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
 {
-       ctxt->sys_regs[MPIDR_EL1]       = read_sysreg(vmpidr_el2);
        ctxt->sys_regs[CSSELR_EL1]      = read_sysreg(csselr_el1);
        ctxt->sys_regs[SCTLR_EL1]       = read_sysreg_el1(sctlr);
        ctxt->sys_regs[ACTLR_EL1]       = read_sysreg(actlr_el1);
index e3e3722..a398d04 100644 (file)
@@ -965,6 +965,10 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
        return true;
 }
 
+#define reg_to_encoding(x)                                             \
+       sys_reg((u32)(x)->Op0, (u32)(x)->Op1,                           \
+               (u32)(x)->CRn, (u32)(x)->CRm, (u32)(x)->Op2);
+
 /* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
 #define DBG_BCR_BVR_WCR_WVR_EL1(n)                                     \
        { SYS_DESC(SYS_DBGBVRn_EL1(n)),                                 \
@@ -986,44 +990,38 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
        { SYS_DESC(SYS_PMEVTYPERn_EL0(n)),                                      \
          access_pmu_evtyper, reset_unknown, (PMEVTYPER0_EL0 + n), }
 
-static bool access_cntp_tval(struct kvm_vcpu *vcpu,
-               struct sys_reg_params *p,
-               const struct sys_reg_desc *r)
+static bool access_arch_timer(struct kvm_vcpu *vcpu,
+                             struct sys_reg_params *p,
+                             const struct sys_reg_desc *r)
 {
-       u64 now = kvm_phys_timer_read();
-       u64 cval;
+       enum kvm_arch_timers tmr;
+       enum kvm_arch_timer_regs treg;
+       u64 reg = reg_to_encoding(r);
 
-       if (p->is_write) {
-               kvm_arm_timer_set_reg(vcpu, KVM_REG_ARM_PTIMER_CVAL,
-                                     p->regval + now);
-       } else {
-               cval = kvm_arm_timer_get_reg(vcpu, KVM_REG_ARM_PTIMER_CVAL);
-               p->regval = cval - now;
+       switch (reg) {
+       case SYS_CNTP_TVAL_EL0:
+       case SYS_AARCH32_CNTP_TVAL:
+               tmr = TIMER_PTIMER;
+               treg = TIMER_REG_TVAL;
+               break;
+       case SYS_CNTP_CTL_EL0:
+       case SYS_AARCH32_CNTP_CTL:
+               tmr = TIMER_PTIMER;
+               treg = TIMER_REG_CTL;
+               break;
+       case SYS_CNTP_CVAL_EL0:
+       case SYS_AARCH32_CNTP_CVAL:
+               tmr = TIMER_PTIMER;
+               treg = TIMER_REG_CVAL;
+               break;
+       default:
+               BUG();
        }
 
-       return true;
-}
-
-static bool access_cntp_ctl(struct kvm_vcpu *vcpu,
-               struct sys_reg_params *p,
-               const struct sys_reg_desc *r)
-{
-       if (p->is_write)
-               kvm_arm_timer_set_reg(vcpu, KVM_REG_ARM_PTIMER_CTL, p->regval);
-       else
-               p->regval = kvm_arm_timer_get_reg(vcpu, KVM_REG_ARM_PTIMER_CTL);
-
-       return true;
-}
-
-static bool access_cntp_cval(struct kvm_vcpu *vcpu,
-               struct sys_reg_params *p,
-               const struct sys_reg_desc *r)
-{
        if (p->is_write)
-               kvm_arm_timer_set_reg(vcpu, KVM_REG_ARM_PTIMER_CVAL, p->regval);
+               kvm_arm_timer_write_sysreg(vcpu, tmr, treg, p->regval);
        else
-               p->regval = kvm_arm_timer_get_reg(vcpu, KVM_REG_ARM_PTIMER_CVAL);
+               p->regval = kvm_arm_timer_read_sysreg(vcpu, tmr, treg);
 
        return true;
 }
@@ -1148,6 +1146,64 @@ static int set_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
        return __set_id_reg(rd, uaddr, true);
 }
 
+static bool access_ctr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                      const struct sys_reg_desc *r)
+{
+       if (p->is_write)
+               return write_to_read_only(vcpu, p, r);
+
+       p->regval = read_sanitised_ftr_reg(SYS_CTR_EL0);
+       return true;
+}
+
+static bool access_clidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                        const struct sys_reg_desc *r)
+{
+       if (p->is_write)
+               return write_to_read_only(vcpu, p, r);
+
+       p->regval = read_sysreg(clidr_el1);
+       return true;
+}
+
+static bool access_csselr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                         const struct sys_reg_desc *r)
+{
+       if (p->is_write)
+               vcpu_write_sys_reg(vcpu, p->regval, r->reg);
+       else
+               p->regval = vcpu_read_sys_reg(vcpu, r->reg);
+       return true;
+}
+
+static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                         const struct sys_reg_desc *r)
+{
+       u32 csselr;
+
+       if (p->is_write)
+               return write_to_read_only(vcpu, p, r);
+
+       csselr = vcpu_read_sys_reg(vcpu, CSSELR_EL1);
+       p->regval = get_ccsidr(csselr);
+
+       /*
+        * Guests should not be doing cache operations by set/way at all, and
+        * for this reason, we trap them and attempt to infer the intent, so
+        * that we can flush the entire guest's address space at the appropriate
+        * time.
+        * To prevent this trapping from causing performance problems, let's
+        * expose the geometry of all data and unified caches (which are
+        * guaranteed to be PIPT and thus non-aliasing) as 1 set and 1 way.
+        * [If guests should attempt to infer aliasing properties from the
+        * geometry (which is not permitted by the architecture), they would
+        * only do so for virtually indexed caches.]
+        */
+       if (!(csselr & 1)) // data or unified cache
+               p->regval &= ~GENMASK(27, 3);
+       return true;
+}
+
 /* sys_reg_desc initialiser for known cpufeature ID registers */
 #define ID_SANITISED(name) {                   \
        SYS_DESC(SYS_##name),                   \
@@ -1365,7 +1421,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
        { SYS_DESC(SYS_CNTKCTL_EL1), NULL, reset_val, CNTKCTL_EL1, 0},
 
-       { SYS_DESC(SYS_CSSELR_EL1), NULL, reset_unknown, CSSELR_EL1 },
+       { SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
+       { SYS_DESC(SYS_CLIDR_EL1), access_clidr },
+       { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
+       { SYS_DESC(SYS_CTR_EL0), access_ctr },
 
        { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, },
        { SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
@@ -1388,9 +1447,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
        { SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 },
 
-       { SYS_DESC(SYS_CNTP_TVAL_EL0), access_cntp_tval },
-       { SYS_DESC(SYS_CNTP_CTL_EL0), access_cntp_ctl },
-       { SYS_DESC(SYS_CNTP_CVAL_EL0), access_cntp_cval },
+       { SYS_DESC(SYS_CNTP_TVAL_EL0), access_arch_timer },
+       { SYS_DESC(SYS_CNTP_CTL_EL0), access_arch_timer },
+       { SYS_DESC(SYS_CNTP_CVAL_EL0), access_arch_timer },
 
        /* PMEVCNTRn_EL0 */
        PMU_PMEVCNTR_EL0(0),
@@ -1464,7 +1523,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
        { SYS_DESC(SYS_DACR32_EL2), NULL, reset_unknown, DACR32_EL2 },
        { SYS_DESC(SYS_IFSR32_EL2), NULL, reset_unknown, IFSR32_EL2 },
-       { SYS_DESC(SYS_FPEXC32_EL2), NULL, reset_val, FPEXC32_EL2, 0x70 },
+       { SYS_DESC(SYS_FPEXC32_EL2), NULL, reset_val, FPEXC32_EL2, 0x700 },
 };
 
 static bool trap_dbgidr(struct kvm_vcpu *vcpu,
@@ -1665,6 +1724,7 @@ static const struct sys_reg_desc cp14_64_regs[] = {
  * register).
  */
 static const struct sys_reg_desc cp15_regs[] = {
+       { Op1( 0), CRn( 0), CRm( 0), Op2( 1), access_ctr },
        { Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_vm_reg, NULL, c1_SCTLR },
        { Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
        { Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
@@ -1711,10 +1771,9 @@ static const struct sys_reg_desc cp15_regs[] = {
 
        { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID },
 
-       /* CNTP_TVAL */
-       { Op1( 0), CRn(14), CRm( 2), Op2( 0), access_cntp_tval },
-       /* CNTP_CTL */
-       { Op1( 0), CRn(14), CRm( 2), Op2( 1), access_cntp_ctl },
+       /* Arch Tmers */
+       { SYS_DESC(SYS_AARCH32_CNTP_TVAL), access_arch_timer },
+       { SYS_DESC(SYS_AARCH32_CNTP_CTL), access_arch_timer },
 
        /* PMEVCNTRn */
        PMU_PMEVCNTR(0),
@@ -1782,6 +1841,10 @@ static const struct sys_reg_desc cp15_regs[] = {
        PMU_PMEVTYPER(30),
        /* PMCCFILTR */
        { Op1(0), CRn(14), CRm(15), Op2(7), access_pmu_evtyper },
+
+       { Op1(1), CRn( 0), CRm( 0), Op2(0), access_ccsidr },
+       { Op1(1), CRn( 0), CRm( 0), Op2(1), access_clidr },
+       { Op1(2), CRn( 0), CRm( 0), Op2(0), access_csselr, NULL, c0_CSSELR },
 };
 
 static const struct sys_reg_desc cp15_64_regs[] = {
@@ -1791,7 +1854,7 @@ static const struct sys_reg_desc cp15_64_regs[] = {
        { Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 },
        { Op1( 1), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_ASGI1R */
        { Op1( 2), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_SGI0R */
-       { Op1( 2), CRn( 0), CRm(14), Op2( 0), access_cntp_cval },
+       { SYS_DESC(SYS_AARCH32_CNTP_CVAL),    access_arch_timer },
 };
 
 /* Target specific emulation tables */
@@ -1820,30 +1883,19 @@ static const struct sys_reg_desc *get_target_table(unsigned target,
        }
 }
 
-#define reg_to_match_value(x)                                          \
-       ({                                                              \
-               unsigned long val;                                      \
-               val  = (x)->Op0 << 14;                                  \
-               val |= (x)->Op1 << 11;                                  \
-               val |= (x)->CRn << 7;                                   \
-               val |= (x)->CRm << 3;                                   \
-               val |= (x)->Op2;                                        \
-               val;                                                    \
-        })
-
 static int match_sys_reg(const void *key, const void *elt)
 {
        const unsigned long pval = (unsigned long)key;
        const struct sys_reg_desc *r = elt;
 
-       return pval - reg_to_match_value(r);
+       return pval - reg_to_encoding(r);
 }
 
 static const struct sys_reg_desc *find_reg(const struct sys_reg_params *params,
                                         const struct sys_reg_desc table[],
                                         unsigned int num)
 {
-       unsigned long pval = reg_to_match_value(params);
+       unsigned long pval = reg_to_encoding(params);
 
        return bsearch((void *)pval, table, num, sizeof(table[0]), match_sys_reg);
 }
@@ -2206,11 +2258,15 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
        }
 
 FUNCTION_INVARIANT(midr_el1)
-FUNCTION_INVARIANT(ctr_el0)
 FUNCTION_INVARIANT(revidr_el1)
 FUNCTION_INVARIANT(clidr_el1)
 FUNCTION_INVARIANT(aidr_el1)
 
+static void get_ctr_el0(struct kvm_vcpu *v, const struct sys_reg_desc *r)
+{
+       ((struct sys_reg_desc *)r)->val = read_sanitised_ftr_reg(SYS_CTR_EL0);
+}
+
 /* ->val is filled in by kvm_sys_reg_table_init() */
 static struct sys_reg_desc invariant_sys_regs[] = {
        { SYS_DESC(SYS_MIDR_EL1), NULL, get_midr_el1 },
index 9a7d4dc..b9243e2 100644 (file)
@@ -1206,6 +1206,13 @@ static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void)
        return ARCH_TIMER_PHYS_SECURE_PPI;
 }
 
+static void __init arch_timer_populate_kvm_info(void)
+{
+       arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+       if (is_kernel_in_hyp_mode())
+               arch_timer_kvm_info.physical_irq = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI];
+}
+
 static int __init arch_timer_of_init(struct device_node *np)
 {
        int i, ret;
@@ -1220,7 +1227,7 @@ static int __init arch_timer_of_init(struct device_node *np)
        for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
                arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
-       arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+       arch_timer_populate_kvm_info();
 
        rate = arch_timer_get_cntfrq();
        arch_timer_of_configure_rate(rate, np);
@@ -1550,7 +1557,7 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
        arch_timer_ppi[ARCH_TIMER_HYP_PPI] =
                acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI);
 
-       arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+       arch_timer_populate_kvm_info();
 
        /*
         * When probing via ACPI, we have no mechanism to override the sysreg
index 349e595..702967d 100644 (file)
@@ -74,6 +74,7 @@ enum arch_timer_spi_nr {
 struct arch_timer_kvm_info {
        struct timecounter timecounter;
        int virtual_irq;
+       int physical_irq;
 };
 
 struct arch_timer_mem_frame {
index 3377135..05a18dd 100644 (file)
 #include <linux/clocksource.h>
 #include <linux/hrtimer.h>
 
+enum kvm_arch_timers {
+       TIMER_PTIMER,
+       TIMER_VTIMER,
+       NR_KVM_TIMERS
+};
+
+enum kvm_arch_timer_regs {
+       TIMER_REG_CNT,
+       TIMER_REG_CVAL,
+       TIMER_REG_TVAL,
+       TIMER_REG_CTL,
+};
+
 struct arch_timer_context {
+       struct kvm_vcpu                 *vcpu;
+
        /* Registers: control register, timer value */
        u32                             cnt_ctl;
        u64                             cnt_cval;
@@ -30,30 +45,36 @@ struct arch_timer_context {
        /* Timer IRQ */
        struct kvm_irq_level            irq;
 
+       /* Virtual offset */
+       u64                             cntvoff;
+
+       /* Emulated Timer (may be unused) */
+       struct hrtimer                  hrtimer;
+
        /*
-        * We have multiple paths which can save/restore the timer state
-        * onto the hardware, so we need some way of keeping track of
-        * where the latest state is.
-        *
-        * loaded == true:  State is loaded on the hardware registers.
-        * loaded == false: State is stored in memory.
+        * We have multiple paths which can save/restore the timer state onto
+        * the hardware, so we need some way of keeping track of where the
+        * latest state is.
         */
-       bool                    loaded;
+       bool                            loaded;
 
-       /* Virtual offset */
-       u64                     cntvoff;
+       /* Duplicated state from arch_timer.c for convenience */
+       u32                             host_timer_irq;
+       u32                             host_timer_irq_flags;
+};
+
+struct timer_map {
+       struct arch_timer_context *direct_vtimer;
+       struct arch_timer_context *direct_ptimer;
+       struct arch_timer_context *emul_ptimer;
 };
 
 struct arch_timer_cpu {
-       struct arch_timer_context       vtimer;
-       struct arch_timer_context       ptimer;
+       struct arch_timer_context timers[NR_KVM_TIMERS];
 
        /* Background timer used when the guest is not running */
        struct hrtimer                  bg_timer;
 
-       /* Physical timer emulation */
-       struct hrtimer                  phys_timer;
-
        /* Is the timer enabled */
        bool                    enabled;
 };
@@ -76,9 +97,6 @@ int kvm_arm_timer_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr);
 
 bool kvm_timer_is_pending(struct kvm_vcpu *vcpu);
 
-void kvm_timer_schedule(struct kvm_vcpu *vcpu);
-void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
-
 u64 kvm_phys_timer_read(void);
 
 void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu);
@@ -88,7 +106,19 @@ void kvm_timer_init_vhe(void);
 
 bool kvm_arch_timer_get_input_level(int vintid);
 
-#define vcpu_vtimer(v) (&(v)->arch.timer_cpu.vtimer)
-#define vcpu_ptimer(v) (&(v)->arch.timer_cpu.ptimer)
+#define vcpu_timer(v)  (&(v)->arch.timer_cpu)
+#define vcpu_get_timer(v,t)    (&vcpu_timer(v)->timers[(t)])
+#define vcpu_vtimer(v) (&(v)->arch.timer_cpu.timers[TIMER_VTIMER])
+#define vcpu_ptimer(v) (&(v)->arch.timer_cpu.timers[TIMER_PTIMER])
+
+#define arch_timer_ctx_index(ctx)      ((ctx) - vcpu_timer((ctx)->vcpu)->timers)
+
+u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu,
+                             enum kvm_arch_timers tmr,
+                             enum kvm_arch_timer_regs treg);
+void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu,
+                               enum kvm_arch_timers tmr,
+                               enum kvm_arch_timer_regs treg,
+                               u64 val);
 
 #endif
index b07ac46..3417f2d 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
+#include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
 
 #include <kvm/arm_vgic.h>
@@ -34,7 +35,9 @@
 
 static struct timecounter *timecounter;
 static unsigned int host_vtimer_irq;
+static unsigned int host_ptimer_irq;
 static u32 host_vtimer_irq_flags;
+static u32 host_ptimer_irq_flags;
 
 static DEFINE_STATIC_KEY_FALSE(has_gic_active_state);
 
@@ -52,12 +55,34 @@ static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx);
 static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
                                 struct arch_timer_context *timer_ctx);
 static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx);
+static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
+                               struct arch_timer_context *timer,
+                               enum kvm_arch_timer_regs treg,
+                               u64 val);
+static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
+                             struct arch_timer_context *timer,
+                             enum kvm_arch_timer_regs treg);
 
 u64 kvm_phys_timer_read(void)
 {
        return timecounter->cc->read(timecounter->cc);
 }
 
+static void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map)
+{
+       if (has_vhe()) {
+               map->direct_vtimer = vcpu_vtimer(vcpu);
+               map->direct_ptimer = vcpu_ptimer(vcpu);
+               map->emul_ptimer = NULL;
+       } else {
+               map->direct_vtimer = vcpu_vtimer(vcpu);
+               map->direct_ptimer = NULL;
+               map->emul_ptimer = vcpu_ptimer(vcpu);
+       }
+
+       trace_kvm_get_timer_map(vcpu->vcpu_id, map);
+}
+
 static inline bool userspace_irqchip(struct kvm *kvm)
 {
        return static_branch_unlikely(&userspace_irqchip_in_use) &&
@@ -78,20 +103,27 @@ static void soft_timer_cancel(struct hrtimer *hrt)
 static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
 {
        struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id;
-       struct arch_timer_context *vtimer;
+       struct arch_timer_context *ctx;
+       struct timer_map map;
 
        /*
         * We may see a timer interrupt after vcpu_put() has been called which
         * sets the CPU's vcpu pointer to NULL, because even though the timer
-        * has been disabled in vtimer_save_state(), the hardware interrupt
+        * has been disabled in timer_save_state(), the hardware interrupt
         * signal may not have been retired from the interrupt controller yet.
         */
        if (!vcpu)
                return IRQ_HANDLED;
 
-       vtimer = vcpu_vtimer(vcpu);
-       if (kvm_timer_should_fire(vtimer))
-               kvm_timer_update_irq(vcpu, true, vtimer);
+       get_timer_map(vcpu, &map);
+
+       if (irq == host_vtimer_irq)
+               ctx = map.direct_vtimer;
+       else
+               ctx = map.direct_ptimer;
+
+       if (kvm_timer_should_fire(ctx))
+               kvm_timer_update_irq(vcpu, true, ctx);
 
        if (userspace_irqchip(vcpu->kvm) &&
            !static_branch_unlikely(&has_gic_active_state))
@@ -122,7 +154,9 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
 
 static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
 {
-       return !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
+       WARN_ON(timer_ctx && timer_ctx->loaded);
+       return timer_ctx &&
+              !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
                (timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
 }
 
@@ -132,21 +166,22 @@ static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
  */
 static u64 kvm_timer_earliest_exp(struct kvm_vcpu *vcpu)
 {
-       u64 min_virt = ULLONG_MAX, min_phys = ULLONG_MAX;
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+       u64 min_delta = ULLONG_MAX;
+       int i;
 
-       if (kvm_timer_irq_can_fire(vtimer))
-               min_virt = kvm_timer_compute_delta(vtimer);
+       for (i = 0; i < NR_KVM_TIMERS; i++) {
+               struct arch_timer_context *ctx = &vcpu->arch.timer_cpu.timers[i];
 
-       if (kvm_timer_irq_can_fire(ptimer))
-               min_phys = kvm_timer_compute_delta(ptimer);
+               WARN(ctx->loaded, "timer %d loaded\n", i);
+               if (kvm_timer_irq_can_fire(ctx))
+                       min_delta = min(min_delta, kvm_timer_compute_delta(ctx));
+       }
 
        /* If none of timers can fire, then return 0 */
-       if ((min_virt == ULLONG_MAX) && (min_phys == ULLONG_MAX))
+       if (min_delta == ULLONG_MAX)
                return 0;
 
-       return min(min_virt, min_phys);
+       return min_delta;
 }
 
 static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt)
@@ -173,41 +208,58 @@ static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt)
        return HRTIMER_NORESTART;
 }
 
-static enum hrtimer_restart kvm_phys_timer_expire(struct hrtimer *hrt)
+static enum hrtimer_restart kvm_hrtimer_expire(struct hrtimer *hrt)
 {
-       struct arch_timer_context *ptimer;
-       struct arch_timer_cpu *timer;
+       struct arch_timer_context *ctx;
        struct kvm_vcpu *vcpu;
        u64 ns;
 
-       timer = container_of(hrt, struct arch_timer_cpu, phys_timer);
-       vcpu = container_of(timer, struct kvm_vcpu, arch.timer_cpu);
-       ptimer = vcpu_ptimer(vcpu);
+       ctx = container_of(hrt, struct arch_timer_context, hrtimer);
+       vcpu = ctx->vcpu;
+
+       trace_kvm_timer_hrtimer_expire(ctx);
 
        /*
         * Check that the timer has really expired from the guest's
         * PoV (NTP on the host may have forced it to expire
         * early). If not ready, schedule for a later time.
         */
-       ns = kvm_timer_compute_delta(ptimer);
+       ns = kvm_timer_compute_delta(ctx);
        if (unlikely(ns)) {
                hrtimer_forward_now(hrt, ns_to_ktime(ns));
                return HRTIMER_RESTART;
        }
 
-       kvm_timer_update_irq(vcpu, true, ptimer);
+       kvm_timer_update_irq(vcpu, true, ctx);
        return HRTIMER_NORESTART;
 }
 
 static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
 {
+       enum kvm_arch_timers index;
        u64 cval, now;
 
+       if (!timer_ctx)
+               return false;
+
+       index = arch_timer_ctx_index(timer_ctx);
+
        if (timer_ctx->loaded) {
-               u32 cnt_ctl;
+               u32 cnt_ctl = 0;
+
+               switch (index) {
+               case TIMER_VTIMER:
+                       cnt_ctl = read_sysreg_el0(cntv_ctl);
+                       break;
+               case TIMER_PTIMER:
+                       cnt_ctl = read_sysreg_el0(cntp_ctl);
+                       break;
+               case NR_KVM_TIMERS:
+                       /* GCC is braindead */
+                       cnt_ctl = 0;
+                       break;
+               }
 
-               /* Only the virtual timer can be loaded so far */
-               cnt_ctl = read_sysreg_el0(cntv_ctl);
                return  (cnt_ctl & ARCH_TIMER_CTRL_ENABLE) &&
                        (cnt_ctl & ARCH_TIMER_CTRL_IT_STAT) &&
                       !(cnt_ctl & ARCH_TIMER_CTRL_IT_MASK);
@@ -224,13 +276,13 @@ static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
 
 bool kvm_timer_is_pending(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+       struct timer_map map;
 
-       if (kvm_timer_should_fire(vtimer))
-               return true;
+       get_timer_map(vcpu, &map);
 
-       return kvm_timer_should_fire(ptimer);
+       return kvm_timer_should_fire(map.direct_vtimer) ||
+              kvm_timer_should_fire(map.direct_ptimer) ||
+              kvm_timer_should_fire(map.emul_ptimer);
 }
 
 /*
@@ -269,77 +321,70 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
        }
 }
 
-/* Schedule the background timer for the emulated timer. */
-static void phys_timer_emulate(struct kvm_vcpu *vcpu)
+static void timer_emulate(struct arch_timer_context *ctx)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+       bool should_fire = kvm_timer_should_fire(ctx);
+
+       trace_kvm_timer_emulate(ctx, should_fire);
+
+       if (should_fire) {
+               kvm_timer_update_irq(ctx->vcpu, true, ctx);
+               return;
+       }
 
        /*
         * If the timer can fire now, we don't need to have a soft timer
         * scheduled for the future.  If the timer cannot fire at all,
         * then we also don't need a soft timer.
         */
-       if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) {
-               soft_timer_cancel(&timer->phys_timer);
+       if (!kvm_timer_irq_can_fire(ctx)) {
+               soft_timer_cancel(&ctx->hrtimer);
                return;
        }
 
-       soft_timer_start(&timer->phys_timer, kvm_timer_compute_delta(ptimer));
+       soft_timer_start(&ctx->hrtimer, kvm_timer_compute_delta(ctx));
 }
 
-/*
- * Check if there was a change in the timer state, so that we should either
- * raise or lower the line level to the GIC or schedule a background timer to
- * emulate the physical timer.
- */
-static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
+static void timer_save_state(struct arch_timer_context *ctx)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
-       bool level;
+       struct arch_timer_cpu *timer = vcpu_timer(ctx->vcpu);
+       enum kvm_arch_timers index = arch_timer_ctx_index(ctx);
+       unsigned long flags;
 
-       if (unlikely(!timer->enabled))
+       if (!timer->enabled)
                return;
 
-       /*
-        * The vtimer virtual interrupt is a 'mapped' interrupt, meaning part
-        * of its lifecycle is offloaded to the hardware, and we therefore may
-        * not have lowered the irq.level value before having to signal a new
-        * interrupt, but have to signal an interrupt every time the level is
-        * asserted.
-        */
-       level = kvm_timer_should_fire(vtimer);
-       kvm_timer_update_irq(vcpu, level, vtimer);
+       local_irq_save(flags);
 
-       phys_timer_emulate(vcpu);
+       if (!ctx->loaded)
+               goto out;
 
-       if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
-               kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
-}
+       switch (index) {
+       case TIMER_VTIMER:
+               ctx->cnt_ctl = read_sysreg_el0(cntv_ctl);
+               ctx->cnt_cval = read_sysreg_el0(cntv_cval);
 
-static void vtimer_save_state(struct kvm_vcpu *vcpu)
-{
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       unsigned long flags;
+               /* Disable the timer */
+               write_sysreg_el0(0, cntv_ctl);
+               isb();
 
-       local_irq_save(flags);
+               break;
+       case TIMER_PTIMER:
+               ctx->cnt_ctl = read_sysreg_el0(cntp_ctl);
+               ctx->cnt_cval = read_sysreg_el0(cntp_cval);
 
-       if (!vtimer->loaded)
-               goto out;
+               /* Disable the timer */
+               write_sysreg_el0(0, cntp_ctl);
+               isb();
 
-       if (timer->enabled) {
-               vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
-               vtimer->cnt_cval = read_sysreg_el0(cntv_cval);
+               break;
+       case NR_KVM_TIMERS:
+               BUG();
        }
 
-       /* Disable the virtual timer */
-       write_sysreg_el0(0, cntv_ctl);
-       isb();
+       trace_kvm_timer_save_state(ctx);
 
-       vtimer->loaded = false;
+       ctx->loaded = false;
 out:
        local_irq_restore(flags);
 }
@@ -349,67 +394,72 @@ out:
  * thread is removed from its waitqueue and made runnable when there's a timer
  * interrupt to handle.
  */
-void kvm_timer_schedule(struct kvm_vcpu *vcpu)
+static void kvm_timer_blocking(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
-
-       vtimer_save_state(vcpu);
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
+       struct timer_map map;
 
-       /*
-        * No need to schedule a background timer if any guest timer has
-        * already expired, because kvm_vcpu_block will return before putting
-        * the thread to sleep.
-        */
-       if (kvm_timer_should_fire(vtimer) || kvm_timer_should_fire(ptimer))
-               return;
+       get_timer_map(vcpu, &map);
 
        /*
-        * If both timers are not capable of raising interrupts (disabled or
+        * If no timers are capable of raising interrupts (disabled or
         * masked), then there's no more work for us to do.
         */
-       if (!kvm_timer_irq_can_fire(vtimer) && !kvm_timer_irq_can_fire(ptimer))
+       if (!kvm_timer_irq_can_fire(map.direct_vtimer) &&
+           !kvm_timer_irq_can_fire(map.direct_ptimer) &&
+           !kvm_timer_irq_can_fire(map.emul_ptimer))
                return;
 
        /*
-        * The guest timers have not yet expired, schedule a background timer.
+        * At least one guest time will expire. Schedule a background timer.
         * Set the earliest expiration time among the guest timers.
         */
        soft_timer_start(&timer->bg_timer, kvm_timer_earliest_exp(vcpu));
 }
 
-static void vtimer_restore_state(struct kvm_vcpu *vcpu)
+static void kvm_timer_unblocking(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
+
+       soft_timer_cancel(&timer->bg_timer);
+}
+
+static void timer_restore_state(struct arch_timer_context *ctx)
+{
+       struct arch_timer_cpu *timer = vcpu_timer(ctx->vcpu);
+       enum kvm_arch_timers index = arch_timer_ctx_index(ctx);
        unsigned long flags;
 
+       if (!timer->enabled)
+               return;
+
        local_irq_save(flags);
 
-       if (vtimer->loaded)
+       if (ctx->loaded)
                goto out;
 
-       if (timer->enabled) {
-               write_sysreg_el0(vtimer->cnt_cval, cntv_cval);
+       switch (index) {
+       case TIMER_VTIMER:
+               write_sysreg_el0(ctx->cnt_cval, cntv_cval);
                isb();
-               write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);
+               write_sysreg_el0(ctx->cnt_ctl, cntv_ctl);
+               break;
+       case TIMER_PTIMER:
+               write_sysreg_el0(ctx->cnt_cval, cntp_cval);
+               isb();
+               write_sysreg_el0(ctx->cnt_ctl, cntp_ctl);
+               break;
+       case NR_KVM_TIMERS:
+               BUG();
        }
 
-       vtimer->loaded = true;
+       trace_kvm_timer_restore_state(ctx);
+
+       ctx->loaded = true;
 out:
        local_irq_restore(flags);
 }
 
-void kvm_timer_unschedule(struct kvm_vcpu *vcpu)
-{
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-
-       vtimer_restore_state(vcpu);
-
-       soft_timer_cancel(&timer->bg_timer);
-}
-
 static void set_cntvoff(u64 cntvoff)
 {
        u32 low = lower_32_bits(cntvoff);
@@ -425,23 +475,32 @@ static void set_cntvoff(u64 cntvoff)
        kvm_call_hyp(__kvm_timer_set_cntvoff, low, high);
 }
 
-static inline void set_vtimer_irq_phys_active(struct kvm_vcpu *vcpu, bool active)
+static inline void set_timer_irq_phys_active(struct arch_timer_context *ctx, bool active)
 {
        int r;
-       r = irq_set_irqchip_state(host_vtimer_irq, IRQCHIP_STATE_ACTIVE, active);
+       r = irq_set_irqchip_state(ctx->host_timer_irq, IRQCHIP_STATE_ACTIVE, active);
        WARN_ON(r);
 }
 
-static void kvm_timer_vcpu_load_gic(struct kvm_vcpu *vcpu)
+static void kvm_timer_vcpu_load_gic(struct arch_timer_context *ctx)
 {
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       bool phys_active;
+       struct kvm_vcpu *vcpu = ctx->vcpu;
+       bool phys_active = false;
+
+       /*
+        * Update the timer output so that it is likely to match the
+        * state we're about to restore. If the timer expires between
+        * this point and the register restoration, we'll take the
+        * interrupt anyway.
+        */
+       kvm_timer_update_irq(ctx->vcpu, kvm_timer_should_fire(ctx), ctx);
 
        if (irqchip_in_kernel(vcpu->kvm))
-               phys_active = kvm_vgic_map_is_active(vcpu, vtimer->irq.irq);
-       else
-               phys_active = vtimer->irq.level;
-       set_vtimer_irq_phys_active(vcpu, phys_active);
+               phys_active = kvm_vgic_map_is_active(vcpu, ctx->irq.irq);
+
+       phys_active |= ctx->irq.level;
+
+       set_timer_irq_phys_active(ctx, phys_active);
 }
 
 static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
@@ -466,28 +525,32 @@ static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
 
 void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
+       struct timer_map map;
 
        if (unlikely(!timer->enabled))
                return;
 
-       if (static_branch_likely(&has_gic_active_state))
-               kvm_timer_vcpu_load_gic(vcpu);
-       else
+       get_timer_map(vcpu, &map);
+
+       if (static_branch_likely(&has_gic_active_state)) {
+               kvm_timer_vcpu_load_gic(map.direct_vtimer);
+               if (map.direct_ptimer)
+                       kvm_timer_vcpu_load_gic(map.direct_ptimer);
+       } else {
                kvm_timer_vcpu_load_nogic(vcpu);
+       }
 
-       set_cntvoff(vtimer->cntvoff);
+       set_cntvoff(map.direct_vtimer->cntvoff);
 
-       vtimer_restore_state(vcpu);
+       kvm_timer_unblocking(vcpu);
 
-       /* Set the background timer for the physical timer emulation. */
-       phys_timer_emulate(vcpu);
+       timer_restore_state(map.direct_vtimer);
+       if (map.direct_ptimer)
+               timer_restore_state(map.direct_ptimer);
 
-       /* If the timer fired while we weren't running, inject it now */
-       if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
-               kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
+       if (map.emul_ptimer)
+               timer_emulate(map.emul_ptimer);
 }
 
 bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu)
@@ -509,15 +572,20 @@ bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu)
 
 void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
+       struct timer_map map;
 
        if (unlikely(!timer->enabled))
                return;
 
-       vtimer_save_state(vcpu);
+       get_timer_map(vcpu, &map);
+
+       timer_save_state(map.direct_vtimer);
+       if (map.direct_ptimer)
+               timer_save_state(map.direct_ptimer);
 
        /*
-        * Cancel the physical timer emulation, because the only case where we
+        * Cancel soft timer emulation, because the only case where we
         * need it after a vcpu_put is in the context of a sleeping VCPU, and
         * in that case we already factor in the deadline for the physical
         * timer when scheduling the bg_timer.
@@ -525,7 +593,11 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
         * In any case, we re-schedule the hrtimer for the physical timer when
         * coming back to the VCPU thread in kvm_timer_vcpu_load().
         */
-       soft_timer_cancel(&timer->phys_timer);
+       if (map.emul_ptimer)
+               soft_timer_cancel(&map.emul_ptimer->hrtimer);
+
+       if (swait_active(kvm_arch_vcpu_wq(vcpu)))
+               kvm_timer_blocking(vcpu);
 
        /*
         * The kernel may decide to run userspace after calling vcpu_put, so
@@ -534,8 +606,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
         * counter of non-VHE case. For VHE, the virtual counter uses a fixed
         * virtual offset of zero, so no need to zero CNTVOFF_EL2 register.
         */
-       if (!has_vhe())
-               set_cntvoff(0);
+       set_cntvoff(0);
 }
 
 /*
@@ -550,7 +621,7 @@ static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu)
        if (!kvm_timer_should_fire(vtimer)) {
                kvm_timer_update_irq(vcpu, false, vtimer);
                if (static_branch_likely(&has_gic_active_state))
-                       set_vtimer_irq_phys_active(vcpu, false);
+                       set_timer_irq_phys_active(vtimer, false);
                else
                        enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
        }
@@ -558,7 +629,7 @@ static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu)
 
 void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
 
        if (unlikely(!timer->enabled))
                return;
@@ -569,9 +640,10 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
 
 int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
+       struct timer_map map;
+
+       get_timer_map(vcpu, &map);
 
        /*
         * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8
@@ -579,12 +651,22 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
         * resets the timer to be disabled and unmasked and is compliant with
         * the ARMv7 architecture.
         */
-       vtimer->cnt_ctl = 0;
-       ptimer->cnt_ctl = 0;
-       kvm_timer_update_state(vcpu);
+       vcpu_vtimer(vcpu)->cnt_ctl = 0;
+       vcpu_ptimer(vcpu)->cnt_ctl = 0;
 
-       if (timer->enabled && irqchip_in_kernel(vcpu->kvm))
-               kvm_vgic_reset_mapped_irq(vcpu, vtimer->irq.irq);
+       if (timer->enabled) {
+               kvm_timer_update_irq(vcpu, false, vcpu_vtimer(vcpu));
+               kvm_timer_update_irq(vcpu, false, vcpu_ptimer(vcpu));
+
+               if (irqchip_in_kernel(vcpu->kvm)) {
+                       kvm_vgic_reset_mapped_irq(vcpu, map.direct_vtimer->irq.irq);
+                       if (map.direct_ptimer)
+                               kvm_vgic_reset_mapped_irq(vcpu, map.direct_ptimer->irq.irq);
+               }
+       }
+
+       if (map.emul_ptimer)
+               soft_timer_cancel(&map.emul_ptimer->hrtimer);
 
        return 0;
 }
@@ -610,56 +692,76 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
 
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
        struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
        struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
 
        /* Synchronize cntvoff across all vtimers of a VM. */
        update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
-       vcpu_ptimer(vcpu)->cntvoff = 0;
+       ptimer->cntvoff = 0;
 
        hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
        timer->bg_timer.function = kvm_bg_timer_expire;
 
-       hrtimer_init(&timer->phys_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
-       timer->phys_timer.function = kvm_phys_timer_expire;
+       hrtimer_init(&vtimer->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       hrtimer_init(&ptimer->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       vtimer->hrtimer.function = kvm_hrtimer_expire;
+       ptimer->hrtimer.function = kvm_hrtimer_expire;
 
        vtimer->irq.irq = default_vtimer_irq.irq;
        ptimer->irq.irq = default_ptimer_irq.irq;
+
+       vtimer->host_timer_irq = host_vtimer_irq;
+       ptimer->host_timer_irq = host_ptimer_irq;
+
+       vtimer->host_timer_irq_flags = host_vtimer_irq_flags;
+       ptimer->host_timer_irq_flags = host_ptimer_irq_flags;
+
+       vtimer->vcpu = vcpu;
+       ptimer->vcpu = vcpu;
 }
 
 static void kvm_timer_init_interrupt(void *info)
 {
        enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
+       enable_percpu_irq(host_ptimer_irq, host_ptimer_irq_flags);
 }
 
 int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
 {
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+       struct arch_timer_context *timer;
+       bool level;
 
        switch (regid) {
        case KVM_REG_ARM_TIMER_CTL:
-               vtimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT;
+               timer = vcpu_vtimer(vcpu);
+               kvm_arm_timer_write(vcpu, timer, TIMER_REG_CTL, value);
                break;
        case KVM_REG_ARM_TIMER_CNT:
+               timer = vcpu_vtimer(vcpu);
                update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
                break;
        case KVM_REG_ARM_TIMER_CVAL:
-               vtimer->cnt_cval = value;
+               timer = vcpu_vtimer(vcpu);
+               kvm_arm_timer_write(vcpu, timer, TIMER_REG_CVAL, value);
                break;
        case KVM_REG_ARM_PTIMER_CTL:
-               ptimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT;
+               timer = vcpu_ptimer(vcpu);
+               kvm_arm_timer_write(vcpu, timer, TIMER_REG_CTL, value);
                break;
        case KVM_REG_ARM_PTIMER_CVAL:
-               ptimer->cnt_cval = value;
+               timer = vcpu_ptimer(vcpu);
+               kvm_arm_timer_write(vcpu, timer, TIMER_REG_CVAL, value);
                break;
 
        default:
                return -1;
        }
 
-       kvm_timer_update_state(vcpu);
+       level = kvm_timer_should_fire(timer);
+       kvm_timer_update_irq(vcpu, level, timer);
+       timer_emulate(timer);
+
        return 0;
 }
 
@@ -679,26 +781,113 @@ static u64 read_timer_ctl(struct arch_timer_context *timer)
 
 u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
 {
-       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-
        switch (regid) {
        case KVM_REG_ARM_TIMER_CTL:
-               return read_timer_ctl(vtimer);
+               return kvm_arm_timer_read(vcpu,
+                                         vcpu_vtimer(vcpu), TIMER_REG_CTL);
        case KVM_REG_ARM_TIMER_CNT:
-               return kvm_phys_timer_read() - vtimer->cntvoff;
+               return kvm_arm_timer_read(vcpu,
+                                         vcpu_vtimer(vcpu), TIMER_REG_CNT);
        case KVM_REG_ARM_TIMER_CVAL:
-               return vtimer->cnt_cval;
+               return kvm_arm_timer_read(vcpu,
+                                         vcpu_vtimer(vcpu), TIMER_REG_CVAL);
        case KVM_REG_ARM_PTIMER_CTL:
-               return read_timer_ctl(ptimer);
-       case KVM_REG_ARM_PTIMER_CVAL:
-               return ptimer->cnt_cval;
+               return kvm_arm_timer_read(vcpu,
+                                         vcpu_ptimer(vcpu), TIMER_REG_CTL);
        case KVM_REG_ARM_PTIMER_CNT:
-               return kvm_phys_timer_read();
+               return kvm_arm_timer_read(vcpu,
+                                         vcpu_vtimer(vcpu), TIMER_REG_CNT);
+       case KVM_REG_ARM_PTIMER_CVAL:
+               return kvm_arm_timer_read(vcpu,
+                                         vcpu_ptimer(vcpu), TIMER_REG_CVAL);
        }
        return (u64)-1;
 }
 
+static u64 kvm_arm_timer_read(struct kvm_vcpu *vcpu,
+                             struct arch_timer_context *timer,
+                             enum kvm_arch_timer_regs treg)
+{
+       u64 val;
+
+       switch (treg) {
+       case TIMER_REG_TVAL:
+               val = kvm_phys_timer_read() - timer->cntvoff - timer->cnt_cval;
+               break;
+
+       case TIMER_REG_CTL:
+               val = read_timer_ctl(timer);
+               break;
+
+       case TIMER_REG_CVAL:
+               val = timer->cnt_cval;
+               break;
+
+       case TIMER_REG_CNT:
+               val = kvm_phys_timer_read() - timer->cntvoff;
+               break;
+
+       default:
+               BUG();
+       }
+
+       return val;
+}
+
+u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu,
+                             enum kvm_arch_timers tmr,
+                             enum kvm_arch_timer_regs treg)
+{
+       u64 val;
+
+       preempt_disable();
+       kvm_timer_vcpu_put(vcpu);
+
+       val = kvm_arm_timer_read(vcpu, vcpu_get_timer(vcpu, tmr), treg);
+
+       kvm_timer_vcpu_load(vcpu);
+       preempt_enable();
+
+       return val;
+}
+
+static void kvm_arm_timer_write(struct kvm_vcpu *vcpu,
+                               struct arch_timer_context *timer,
+                               enum kvm_arch_timer_regs treg,
+                               u64 val)
+{
+       switch (treg) {
+       case TIMER_REG_TVAL:
+               timer->cnt_cval = val - kvm_phys_timer_read() - timer->cntvoff;
+               break;
+
+       case TIMER_REG_CTL:
+               timer->cnt_ctl = val & ~ARCH_TIMER_CTRL_IT_STAT;
+               break;
+
+       case TIMER_REG_CVAL:
+               timer->cnt_cval = val;
+               break;
+
+       default:
+               BUG();
+       }
+}
+
+void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu,
+                               enum kvm_arch_timers tmr,
+                               enum kvm_arch_timer_regs treg,
+                               u64 val)
+{
+       preempt_disable();
+       kvm_timer_vcpu_put(vcpu);
+
+       kvm_arm_timer_write(vcpu, vcpu_get_timer(vcpu, tmr), treg, val);
+
+       kvm_timer_vcpu_load(vcpu);
+       preempt_enable();
+}
+
 static int kvm_timer_starting_cpu(unsigned int cpu)
 {
        kvm_timer_init_interrupt(NULL);
@@ -724,6 +913,8 @@ int kvm_timer_hyp_init(bool has_gic)
                return -ENODEV;
        }
 
+       /* First, do the virtual EL1 timer irq */
+
        if (info->virtual_irq <= 0) {
                kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n",
                        info->virtual_irq);
@@ -734,15 +925,15 @@ int kvm_timer_hyp_init(bool has_gic)
        host_vtimer_irq_flags = irq_get_trigger_type(host_vtimer_irq);
        if (host_vtimer_irq_flags != IRQF_TRIGGER_HIGH &&
            host_vtimer_irq_flags != IRQF_TRIGGER_LOW) {
-               kvm_err("Invalid trigger for IRQ%d, assuming level low\n",
+               kvm_err("Invalid trigger for vtimer IRQ%d, assuming level low\n",
                        host_vtimer_irq);
                host_vtimer_irq_flags = IRQF_TRIGGER_LOW;
        }
 
        err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler,
-                                "kvm guest timer", kvm_get_running_vcpus());
+                                "kvm guest vtimer", kvm_get_running_vcpus());
        if (err) {
-               kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n",
+               kvm_err("kvm_arch_timer: can't request vtimer interrupt %d (%d)\n",
                        host_vtimer_irq, err);
                return err;
        }
@@ -760,6 +951,43 @@ int kvm_timer_hyp_init(bool has_gic)
 
        kvm_debug("virtual timer IRQ%d\n", host_vtimer_irq);
 
+       /* Now let's do the physical EL1 timer irq */
+
+       if (info->physical_irq > 0) {
+               host_ptimer_irq = info->physical_irq;
+               host_ptimer_irq_flags = irq_get_trigger_type(host_ptimer_irq);
+               if (host_ptimer_irq_flags != IRQF_TRIGGER_HIGH &&
+                   host_ptimer_irq_flags != IRQF_TRIGGER_LOW) {
+                       kvm_err("Invalid trigger for ptimer IRQ%d, assuming level low\n",
+                               host_ptimer_irq);
+                       host_ptimer_irq_flags = IRQF_TRIGGER_LOW;
+               }
+
+               err = request_percpu_irq(host_ptimer_irq, kvm_arch_timer_handler,
+                                        "kvm guest ptimer", kvm_get_running_vcpus());
+               if (err) {
+                       kvm_err("kvm_arch_timer: can't request ptimer interrupt %d (%d)\n",
+                               host_ptimer_irq, err);
+                       return err;
+               }
+
+               if (has_gic) {
+                       err = irq_set_vcpu_affinity(host_ptimer_irq,
+                                                   kvm_get_running_vcpus());
+                       if (err) {
+                               kvm_err("kvm_arch_timer: error setting vcpu affinity\n");
+                               goto out_free_irq;
+                       }
+               }
+
+               kvm_debug("physical timer IRQ%d\n", host_ptimer_irq);
+       } else if (has_vhe()) {
+               kvm_err("kvm_arch_timer: invalid physical timer IRQ: %d\n",
+                       info->physical_irq);
+               err = -ENODEV;
+               goto out_free_irq;
+       }
+
        cpuhp_setup_state(CPUHP_AP_KVM_ARM_TIMER_STARTING,
                          "kvm/arm/timer:starting", kvm_timer_starting_cpu,
                          kvm_timer_dying_cpu);
@@ -771,7 +999,7 @@ out_free_irq:
 
 void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
 
        soft_timer_cancel(&timer->bg_timer);
 }
@@ -807,16 +1035,18 @@ bool kvm_arch_timer_get_input_level(int vintid)
 
        if (vintid == vcpu_vtimer(vcpu)->irq.irq)
                timer = vcpu_vtimer(vcpu);
+       else if (vintid == vcpu_ptimer(vcpu)->irq.irq)
+               timer = vcpu_ptimer(vcpu);
        else
-               BUG(); /* We only map the vtimer so far */
+               BUG();
 
        return kvm_timer_should_fire(timer);
 }
 
 int kvm_timer_enable(struct kvm_vcpu *vcpu)
 {
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+       struct arch_timer_cpu *timer = vcpu_timer(vcpu);
+       struct timer_map map;
        int ret;
 
        if (timer->enabled)
@@ -834,19 +1064,33 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
                return -EINVAL;
        }
 
-       ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq,
+       get_timer_map(vcpu, &map);
+
+       ret = kvm_vgic_map_phys_irq(vcpu,
+                                   map.direct_vtimer->host_timer_irq,
+                                   map.direct_vtimer->irq.irq,
                                    kvm_arch_timer_get_input_level);
        if (ret)
                return ret;
 
+       if (map.direct_ptimer) {
+               ret = kvm_vgic_map_phys_irq(vcpu,
+                                           map.direct_ptimer->host_timer_irq,
+                                           map.direct_ptimer->irq.irq,
+                                           kvm_arch_timer_get_input_level);
+       }
+
+       if (ret)
+               return ret;
+
 no_vgic:
        timer->enabled = 1;
        return 0;
 }
 
 /*
- * On VHE system, we only need to configure trap on physical timer and counter
- * accesses in EL0 and EL1 once, not for every world switch.
+ * On VHE system, we only need to configure the EL2 timer trap register once,
+ * not for every world switch.
  * The host kernel runs at EL2 with HCR_EL2.TGE == 1,
  * and this makes those bits have no effect for the host kernel execution.
  */
@@ -857,11 +1101,11 @@ void kvm_timer_init_vhe(void)
        u64 val;
 
        /*
-        * Disallow physical timer access for the guest.
-        * Physical counter access is allowed.
+        * VHE systems allow the guest direct access to the EL1 physical
+        * timer/counter.
         */
        val = read_sysreg(cnthctl_el2);
-       val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift);
+       val |= (CNTHCTL_EL1PCEN << cnthctl_shift);
        val |= (CNTHCTL_EL1PCTEN << cnthctl_shift);
        write_sysreg(val, cnthctl_el2);
 }
index 9e350fd..8de5504 100644 (file)
@@ -65,7 +65,6 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu);
 /* The VMID used in the VTTBR */
 static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
 static u32 kvm_next_vmid;
-static unsigned int kvm_vmid_bits __read_mostly;
 static DEFINE_SPINLOCK(kvm_vmid_lock);
 
 static bool vgic_present;
@@ -142,7 +141,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        kvm_vgic_early_init(kvm);
 
        /* Mark the initial VMID generation invalid */
-       kvm->arch.vmid_gen = 0;
+       kvm->arch.vmid.vmid_gen = 0;
 
        /* The maximum number of VCPUs is limited by the host's GIC model */
        kvm->arch.max_vcpus = vgic_present ?
@@ -336,13 +335,11 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 
 void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
 {
-       kvm_timer_schedule(vcpu);
        kvm_vgic_v4_enable_doorbell(vcpu);
 }
 
 void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
 {
-       kvm_timer_unschedule(vcpu);
        kvm_vgic_v4_disable_doorbell(vcpu);
 }
 
@@ -472,37 +469,31 @@ void force_vm_exit(const cpumask_t *mask)
 
 /**
  * need_new_vmid_gen - check that the VMID is still valid
- * @kvm: The VM's VMID to check
+ * @vmid: The VMID to check
  *
  * return true if there is a new generation of VMIDs being used
  *
- * The hardware supports only 256 values with the value zero reserved for the
- * host, so we check if an assigned value belongs to a previous generation,
- * which which requires us to assign a new value. If we're the first to use a
- * VMID for the new generation, we must flush necessary caches and TLBs on all
- * CPUs.
+ * The hardware supports a limited set of values with the value zero reserved
+ * for the host, so we check if an assigned value belongs to a previous
+ * generation, which which requires us to assign a new value. If we're the
+ * first to use a VMID for the new generation, we must flush necessary caches
+ * and TLBs on all CPUs.
  */
-static bool need_new_vmid_gen(struct kvm *kvm)
+static bool need_new_vmid_gen(struct kvm_vmid *vmid)
 {
        u64 current_vmid_gen = atomic64_read(&kvm_vmid_gen);
        smp_rmb(); /* Orders read of kvm_vmid_gen and kvm->arch.vmid */
-       return unlikely(READ_ONCE(kvm->arch.vmid_gen) != current_vmid_gen);
+       return unlikely(READ_ONCE(vmid->vmid_gen) != current_vmid_gen);
 }
 
 /**
- * update_vttbr - Update the VTTBR with a valid VMID before the guest runs
- * @kvm        The guest that we are about to run
- *
- * Called from kvm_arch_vcpu_ioctl_run before entering the guest to ensure the
- * VM has a valid VMID, otherwise assigns a new one and flushes corresponding
- * caches and TLBs.
+ * update_vmid - Update the vmid with a valid VMID for the current generation
+ * @kvm: The guest that struct vmid belongs to
+ * @vmid: The stage-2 VMID information struct
  */
-static void update_vttbr(struct kvm *kvm)
+static void update_vmid(struct kvm_vmid *vmid)
 {
-       phys_addr_t pgd_phys;
-       u64 vmid, cnp = kvm_cpu_has_cnp() ? VTTBR_CNP_BIT : 0;
-
-       if (!need_new_vmid_gen(kvm))
+       if (!need_new_vmid_gen(vmid))
                return;
 
        spin_lock(&kvm_vmid_lock);
@@ -512,7 +503,7 @@ static void update_vttbr(struct kvm *kvm)
         * already allocated a valid vmid for this vm, then this vcpu should
         * use the same vmid.
         */
-       if (!need_new_vmid_gen(kvm)) {
+       if (!need_new_vmid_gen(vmid)) {
                spin_unlock(&kvm_vmid_lock);
                return;
        }
@@ -536,18 +527,12 @@ static void update_vttbr(struct kvm *kvm)
                kvm_call_hyp(__kvm_flush_vm_context);
        }
 
-       kvm->arch.vmid = kvm_next_vmid;
+       vmid->vmid = kvm_next_vmid;
        kvm_next_vmid++;
-       kvm_next_vmid &= (1 << kvm_vmid_bits) - 1;
-
-       /* update vttbr to be used with the new vmid */
-       pgd_phys = virt_to_phys(kvm->arch.pgd);
-       BUG_ON(pgd_phys & ~kvm_vttbr_baddr_mask(kvm));
-       vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits);
-       kvm->arch.vttbr = kvm_phys_to_vttbr(pgd_phys) | vmid | cnp;
+       kvm_next_vmid &= (1 << kvm_get_vmid_bits()) - 1;
 
        smp_wmb();
-       WRITE_ONCE(kvm->arch.vmid_gen, atomic64_read(&kvm_vmid_gen));
+       WRITE_ONCE(vmid->vmid_gen, atomic64_read(&kvm_vmid_gen));
 
        spin_unlock(&kvm_vmid_lock);
 }
@@ -690,7 +675,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                 */
                cond_resched();
 
-               update_vttbr(vcpu->kvm);
+               update_vmid(&vcpu->kvm->arch.vmid);
 
                check_vcpu_requests(vcpu);
 
@@ -739,7 +724,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                 */
                smp_store_mb(vcpu->mode, IN_GUEST_MODE);
 
-               if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) ||
+               if (ret <= 0 || need_new_vmid_gen(&vcpu->kvm->arch.vmid) ||
                    kvm_request_pending(vcpu)) {
                        vcpu->mode = OUTSIDE_GUEST_MODE;
                        isb(); /* Ensure work in x_flush_hwstate is committed */
@@ -765,7 +750,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                        ret = kvm_vcpu_run_vhe(vcpu);
                        kvm_arm_vhe_guest_exit();
                } else {
-                       ret = kvm_call_hyp(__kvm_vcpu_run_nvhe, vcpu);
+                       ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu);
                }
 
                vcpu->mode = OUTSIDE_GUEST_MODE;
@@ -1417,10 +1402,6 @@ static inline void hyp_cpu_pm_exit(void)
 
 static int init_common_resources(void)
 {
-       /* set size of VMID supported by CPU */
-       kvm_vmid_bits = kvm_get_vmid_bits();
-       kvm_info("%d-bit VMID\n", kvm_vmid_bits);
-
        kvm_set_ipa_limit();
 
        return 0;
@@ -1561,6 +1542,7 @@ static int init_hyp_mode(void)
                kvm_cpu_context_t *cpu_ctxt;
 
                cpu_ctxt = per_cpu_ptr(&kvm_host_cpu_state, cpu);
+               kvm_init_host_cpu_context(cpu_ctxt, cpu);
                err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1, PAGE_HYP);
 
                if (err) {
@@ -1571,7 +1553,7 @@ static int init_hyp_mode(void)
 
        err = hyp_map_aux_data();
        if (err)
-               kvm_err("Cannot map host auxilary data: %d\n", err);
+               kvm_err("Cannot map host auxiliary data: %d\n", err);
 
        return 0;
 
index 9652c45..264d92d 100644 (file)
@@ -226,7 +226,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
                int i;
                u32 elrsr;
 
-               elrsr = read_gicreg(ICH_ELSR_EL2);
+               elrsr = read_gicreg(ICH_ELRSR_EL2);
 
                write_gicreg(cpu_if->vgic_hcr & ~ICH_HCR_EN, ICH_HCR_EL2);
 
index e0355e0..f8bfc73 100644 (file)
@@ -908,6 +908,7 @@ int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size,
  */
 int kvm_alloc_stage2_pgd(struct kvm *kvm)
 {
+       phys_addr_t pgd_phys;
        pgd_t *pgd;
 
        if (kvm->arch.pgd != NULL) {
@@ -920,7 +921,12 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
        if (!pgd)
                return -ENOMEM;
 
+       pgd_phys = virt_to_phys(pgd);
+       if (WARN_ON(pgd_phys & ~kvm_vttbr_baddr_mask(kvm)))
+               return -EINVAL;
+
        kvm->arch.pgd = pgd;
+       kvm->arch.pgd_phys = pgd_phys;
        return 0;
 }
 
@@ -1008,6 +1014,7 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
                unmap_stage2_range(kvm, 0, kvm_phys_size(kvm));
                pgd = READ_ONCE(kvm->arch.pgd);
                kvm->arch.pgd = NULL;
+               kvm->arch.pgd_phys = 0;
        }
        spin_unlock(&kvm->mmu_lock);
 
@@ -1396,14 +1403,6 @@ static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap)
        return false;
 }
 
-static bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
-{
-       if (kvm_vcpu_trap_is_iabt(vcpu))
-               return false;
-
-       return kvm_vcpu_dabt_iswrite(vcpu);
-}
-
 /**
  * stage2_wp_ptes - write protect PMD range
  * @pmd:       pointer to pmd entry
@@ -1598,14 +1597,13 @@ static void kvm_send_hwpoison_signal(unsigned long address,
 static bool fault_supports_stage2_pmd_mappings(struct kvm_memory_slot *memslot,
                                               unsigned long hva)
 {
-       gpa_t gpa_start, gpa_end;
+       gpa_t gpa_start;
        hva_t uaddr_start, uaddr_end;
        size_t size;
 
        size = memslot->npages * PAGE_SIZE;
 
        gpa_start = memslot->base_gfn << PAGE_SHIFT;
-       gpa_end = gpa_start + size;
 
        uaddr_start = memslot->userspace_addr;
        uaddr_end = uaddr_start + size;
index 3828bea..204d210 100644 (file)
@@ -2,6 +2,7 @@
 #if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_KVM_H
 
+#include <kvm/arm_arch_timer.h>
 #include <linux/tracepoint.h>
 
 #undef TRACE_SYSTEM
@@ -262,10 +263,114 @@ TRACE_EVENT(kvm_timer_update_irq,
                  __entry->vcpu_id, __entry->irq, __entry->level)
 );
 
+TRACE_EVENT(kvm_get_timer_map,
+       TP_PROTO(unsigned long vcpu_id, struct timer_map *map),
+       TP_ARGS(vcpu_id, map),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,          vcpu_id )
+               __field(        int,                    direct_vtimer   )
+               __field(        int,                    direct_ptimer   )
+               __field(        int,                    emul_ptimer     )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_id                = vcpu_id;
+               __entry->direct_vtimer          = arch_timer_ctx_index(map->direct_vtimer);
+               __entry->direct_ptimer =
+                       (map->direct_ptimer) ? arch_timer_ctx_index(map->direct_ptimer) : -1;
+               __entry->emul_ptimer =
+                       (map->emul_ptimer) ? arch_timer_ctx_index(map->emul_ptimer) : -1;
+       ),
+
+       TP_printk("VCPU: %ld, dv: %d, dp: %d, ep: %d",
+                 __entry->vcpu_id,
+                 __entry->direct_vtimer,
+                 __entry->direct_ptimer,
+                 __entry->emul_ptimer)
+);
+
+TRACE_EVENT(kvm_timer_save_state,
+       TP_PROTO(struct arch_timer_context *ctx),
+       TP_ARGS(ctx),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,          ctl             )
+               __field(        unsigned long long,     cval            )
+               __field(        int,                    timer_idx       )
+       ),
+
+       TP_fast_assign(
+               __entry->ctl                    = ctx->cnt_ctl;
+               __entry->cval                   = ctx->cnt_cval;
+               __entry->timer_idx              = arch_timer_ctx_index(ctx);
+       ),
+
+       TP_printk("   CTL: %#08lx CVAL: %#16llx arch_timer_ctx_index: %d",
+                 __entry->ctl,
+                 __entry->cval,
+                 __entry->timer_idx)
+);
+
+TRACE_EVENT(kvm_timer_restore_state,
+       TP_PROTO(struct arch_timer_context *ctx),
+       TP_ARGS(ctx),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,          ctl             )
+               __field(        unsigned long long,     cval            )
+               __field(        int,                    timer_idx       )
+       ),
+
+       TP_fast_assign(
+               __entry->ctl                    = ctx->cnt_ctl;
+               __entry->cval                   = ctx->cnt_cval;
+               __entry->timer_idx              = arch_timer_ctx_index(ctx);
+       ),
+
+       TP_printk("CTL: %#08lx CVAL: %#16llx arch_timer_ctx_index: %d",
+                 __entry->ctl,
+                 __entry->cval,
+                 __entry->timer_idx)
+);
+
+TRACE_EVENT(kvm_timer_hrtimer_expire,
+       TP_PROTO(struct arch_timer_context *ctx),
+       TP_ARGS(ctx),
+
+       TP_STRUCT__entry(
+               __field(        int,                    timer_idx       )
+       ),
+
+       TP_fast_assign(
+               __entry->timer_idx              = arch_timer_ctx_index(ctx);
+       ),
+
+       TP_printk("arch_timer_ctx_index: %d", __entry->timer_idx)
+);
+
+TRACE_EVENT(kvm_timer_emulate,
+       TP_PROTO(struct arch_timer_context *ctx, bool should_fire),
+       TP_ARGS(ctx, should_fire),
+
+       TP_STRUCT__entry(
+               __field(        int,                    timer_idx       )
+               __field(        bool,                   should_fire     )
+       ),
+
+       TP_fast_assign(
+               __entry->timer_idx              = arch_timer_ctx_index(ctx);
+               __entry->should_fire            = should_fire;
+       ),
+
+       TP_printk("arch_timer_ctx_index: %d (should_fire: %d)",
+                 __entry->timer_idx, __entry->should_fire)
+);
+
 #endif /* _TRACE_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH ../../../virt/kvm/arm
+#define TRACE_INCLUDE_PATH ../../virt/kvm/arm
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace
 
index 9c0dd23..67f9815 100644 (file)
@@ -589,7 +589,7 @@ early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
  */
 int vgic_v3_probe(const struct gic_kvm_info *info)
 {
-       u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+       u32 ich_vtr_el2 = kvm_call_hyp_ret(__vgic_v3_get_ich_vtr_el2);
        int ret;
 
        /*
@@ -679,7 +679,7 @@ void vgic_v3_put(struct kvm_vcpu *vcpu)
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
 
        if (likely(cpu_if->vgic_sre))
-               cpu_if->vgic_vmcr = kvm_call_hyp(__vgic_v3_read_vmcr);
+               cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr);
 
        kvm_call_hyp(__vgic_v3_save_aprs, vcpu);