]> Git Repo - linux.git/commitdiff
Merge tag 'kvmarm-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm...
authorPaolo Bonzini <[email protected]>
Sun, 9 Aug 2020 16:58:23 +0000 (12:58 -0400)
committerPaolo Bonzini <[email protected]>
Sun, 9 Aug 2020 16:58:23 +0000 (12:58 -0400)
KVM/arm64 updates for Linux 5.9:

- Split the VHE and nVHE hypervisor code bases, build the EL2 code
  separately, allowing for the VHE code to now be built with instrumentation

- Level-based TLB invalidation support

- Restructure of the vcpu register storage to accomodate the NV code

- Pointer Authentication available for guests on nVHE hosts

- Simplification of the system register table parsing

- MMU cleanups and fixes

- A number of post-32bit cleanups and other fixes

12 files changed:
1  2 
arch/arm64/Kconfig
arch/arm64/include/asm/kvm_coproc.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/handle_exit.c
arch/arm64/kvm/hyp/nvhe/hyp-init.S
arch/arm64/kvm/mmio.c
arch/arm64/kvm/mmu.c
arch/arm64/kvm/reset.c
arch/arm64/kvm/sys_regs.c

diff --combined arch/arm64/Kconfig
index e11b4ea061279ea161a0ed713c8d6a20800a3693,12739999f19cee63512dd8c94fa273220b6b91ec..6d232837cbeee8abb0c5a9c37b05c8566260156f
@@@ -118,7 -118,6 +118,7 @@@ config ARM6
        select GENERIC_STRNLEN_USER
        select GENERIC_TIME_VSYSCALL
        select GENERIC_GETTIMEOFDAY
 +      select GENERIC_VDSO_TIME_NS
        select HANDLE_DOMAIN_IRQ
        select HARDIRQS_SW_RESEND
        select HAVE_PCI
        select HAVE_CMPXCHG_DOUBLE
        select HAVE_CMPXCHG_LOCAL
        select HAVE_CONTEXT_TRACKING
 -      select HAVE_COPY_THREAD_TLS
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS
@@@ -1182,22 -1182,6 +1182,6 @@@ config HARDEN_BRANCH_PREDICTO
  
          If unsure, say Y.
  
- config HARDEN_EL2_VECTORS
-       bool "Harden EL2 vector mapping against system register leak" if EXPERT
-       default y
-       help
-         Speculation attacks against some high-performance processors can
-         be used to leak privileged information such as the vector base
-         register, resulting in a potential defeat of the EL2 layout
-         randomization.
-         This config option will map the vectors to a fixed location,
-         independent of the EL2 code mapping, so that revealing VBAR_EL2
-         to an attacker does not give away any extra information. This
-         only gets enabled on affected CPUs.
-         If unsure, say Y.
  config ARM64_SSBD
        bool "Speculative Store Bypass Disable" if EXPERT
        default y
@@@ -1327,8 -1311,6 +1311,8 @@@ config SWP_EMULATIO
          ARMv8 obsoletes the use of A32 SWP/SWPB instructions such that
          they are always undefined. Say Y here to enable software
          emulation of these instructions for userspace using LDXR/STXR.
 +        This feature can be controlled at runtime with the abi.swp
 +        sysctl which is disabled by default.
  
          In some older versions of glibc [<=2.8] SWP is used during futex
          trylock() operations with the assumption that the code will not
@@@ -1355,8 -1337,7 +1339,8 @@@ config CP15_BARRIER_EMULATIO
          Say Y here to enable software emulation of these
          instructions for AArch32 userspace code. When this option is
          enabled, CP15 barrier usage is traced which can help
 -        identify software that needs updating.
 +        identify software that needs updating. This feature can be
 +        controlled at runtime with the abi.cp15_barrier sysctl.
  
          If unsure, say Y
  
@@@ -1367,8 -1348,7 +1351,8 @@@ config SETEND_EMULATIO
          AArch32 EL0, and is deprecated in ARMv8.
  
          Say Y here to enable software emulation of the instruction
 -        for AArch32 userspace code.
 +        for AArch32 userspace code. This feature can be controlled
 +        at runtime with the abi.setend sysctl.
  
          Note: All the cpus on the system must have mixed endian support at EL0
          for this feature to be enabled. If a new CPU - which doesn't support mixed
@@@ -1520,7 -1500,6 +1504,6 @@@ menu "ARMv8.3 architectural features
  config ARM64_PTR_AUTH
        bool "Enable support for pointer authentication"
        default y
-       depends on !KVM || ARM64_VHE
        depends on (CC_HAS_SIGN_RETURN_ADDRESS || CC_HAS_BRANCH_PROT_PAC_RET) && AS_HAS_PAC
        # Modern compilers insert a .note.gnu.property section note for PAC
        # which is only understood by binutils starting with version 2.33.1.
  
          The feature is detected at runtime. If the feature is not present in
          hardware it will not be advertised to userspace/KVM guest nor will it
-         be enabled. However, KVM guest also require VHE mode and hence
-         CONFIG_ARM64_VHE=y option to use this feature.
+         be enabled.
  
          If the feature is present on the boot CPU but not on a late CPU, then
          the late CPU will be parked. Also, if the boot CPU does not have
@@@ -1600,20 -1578,6 +1582,20 @@@ config ARM64_AMU_EXT
          correctly reflect reality. Most commonly, the value read will be 0,
          indicating that the counter is not enabled.
  
 +config AS_HAS_ARMV8_4
 +      def_bool $(cc-option,-Wa$(comma)-march=armv8.4-a)
 +
 +config ARM64_TLB_RANGE
 +      bool "Enable support for tlbi range feature"
 +      default y
 +      depends on AS_HAS_ARMV8_4
 +      help
 +        ARMv8.4-TLBI provides TLBI invalidation instruction that apply to a
 +        range of input addresses.
 +
 +        The feature introduces new assembly instructions, and they were
 +        support when binutils >= 2.30.
 +
  endmenu
  
  menu "ARMv8.5 architectural features"
index 454373704b8a0ee628d57435181fa8fc18680581,147f3a77e6a520fd80a418739d6b75963a851fb3..d6bb40122fdbe8b63ac76b8cf0e2bdad4e0f306f
@@@ -19,20 -19,12 +19,12 @@@ struct kvm_sys_reg_table 
        size_t num;
  };
  
- struct kvm_sys_reg_target_table {
-       struct kvm_sys_reg_table table64;
-       struct kvm_sys_reg_table table32;
- };
- void kvm_register_target_sys_reg_table(unsigned int target,
-                                      struct kvm_sys_reg_target_table *table);
 -int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
 -int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
 -int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 -int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
 -int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 -int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run);
 +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu);
 +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu);
 +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu);
 +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu);
 +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu);
 +int kvm_handle_sys_reg(struct kvm_vcpu *vcpu);
  
  #define kvm_coproc_table_init kvm_sys_reg_table_init
  void kvm_sys_reg_table_init(void);
index f81151ad3d3cd4f8394147d25de02d082b4a48eb,e1a32c0707bbfa19c50f52dccc1f68b4a38add5b..65568b23868a1f6fea3936d267d805a15a02575c
@@@ -66,19 -66,34 +66,34 @@@ struct kvm_vmid 
        u32    vmid;
  };
  
- struct kvm_arch {
+ struct kvm_s2_mmu {
        struct kvm_vmid vmid;
  
-       /* stage2 entry level table */
-       pgd_t *pgd;
-       phys_addr_t pgd_phys;
-       /* VTCR_EL2 value for this VM */
-       u64    vtcr;
+       /*
+        * stage2 entry level table
+        *
+        * Two kvm_s2_mmu structures in the same VM can point to the same
+        * pgd here.  This happens when running a guest using a
+        * translation regime that isn't affected by its own stage-2
+        * translation, such as a non-VHE hypervisor running at vEL2, or
+        * for vEL1/EL0 with vHCR_EL2.VM == 0.  In that case, we use the
+        * canonical stage-2 page tables.
+        */
+       pgd_t           *pgd;
+       phys_addr_t     pgd_phys;
  
        /* The last vcpu id that ran on each physical CPU */
        int __percpu *last_vcpu_ran;
  
+       struct kvm *kvm;
+ };
+ struct kvm_arch {
+       struct kvm_s2_mmu mmu;
+       /* VTCR_EL2 value for this VM */
+       u64    vtcr;
        /* The maximum number of vCPUs depends on the used GIC model */
        int max_vcpus;
  
        bool return_nisv_io_abort_to_user;
  };
  
 -#define KVM_NR_MEM_OBJS     40
 -
 -/*
 - * We don't want allocation failures within the mmu code, so we preallocate
 - * enough memory for a single page fault in a cache.
 - */
 -struct kvm_mmu_memory_cache {
 -      int nobjs;
 -      void *objects[KVM_NR_MEM_OBJS];
 -};
 -
  struct kvm_vcpu_fault_info {
        u32 esr_el2;            /* Hyp Syndrom Register */
        u64 far_el2;            /* Hyp Fault Address Register */
@@@ -159,6 -185,16 +174,16 @@@ enum vcpu_sysreg 
        APGAKEYLO_EL1,
        APGAKEYHI_EL1,
  
+       ELR_EL1,
+       SP_EL1,
+       SPSR_EL1,
+       CNTVOFF_EL2,
+       CNTV_CVAL_EL0,
+       CNTV_CTL_EL0,
+       CNTP_CVAL_EL0,
+       CNTP_CTL_EL0,
        /* 32bit specific registers. Keep them at the end of the range */
        DACR32_EL2,     /* Domain Access Control Register */
        IFSR32_EL2,     /* Instruction Fault Status Register */
  #define NR_COPRO_REGS (NR_SYS_REGS * 2)
  
  struct kvm_cpu_context {
-       struct kvm_regs gp_regs;
+       struct user_pt_regs regs;       /* sp = sp_el0 */
+       u64     spsr_abt;
+       u64     spsr_und;
+       u64     spsr_irq;
+       u64     spsr_fiq;
+       struct user_fpsimd_state fp_regs;
        union {
                u64 sys_regs[NR_SYS_REGS];
                u32 copro[NR_COPRO_REGS];
@@@ -243,6 -287,9 +276,9 @@@ struct kvm_vcpu_arch 
        void *sve_state;
        unsigned int sve_max_vl;
  
+       /* Stage 2 paging state used by the hardware on next switch */
+       struct kvm_s2_mmu *hw_mmu;
        /* HYP configuration */
        u64 hcr_el2;
        u32 mdcr_el2;
        struct vcpu_reset_state reset_state;
  
        /* True when deferrable sysregs are loaded on the physical CPU,
-        * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
+        * see kvm_vcpu_load_sysregs_vhe and kvm_vcpu_put_sysregs_vhe. */
        bool sysregs_loaded_on_cpu;
  
        /* Guest PV state */
  #define vcpu_has_sve(vcpu) (system_supports_sve() && \
                            ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE))
  
 -#define vcpu_has_ptrauth(vcpu)        ((system_supports_address_auth() || \
 -                                system_supports_generic_auth()) && \
 -                               ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_PTRAUTH))
 +#ifdef CONFIG_ARM64_PTR_AUTH
 +#define vcpu_has_ptrauth(vcpu)                                                \
 +      ((cpus_have_final_cap(ARM64_HAS_ADDRESS_AUTH) ||                \
 +        cpus_have_final_cap(ARM64_HAS_GENERIC_AUTH)) &&               \
 +       (vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_PTRAUTH)
 +#else
 +#define vcpu_has_ptrauth(vcpu)                false
 +#endif
  
- #define vcpu_gp_regs(v)               (&(v)->arch.ctxt.gp_regs)
+ #define vcpu_gp_regs(v)               (&(v)->arch.ctxt.regs)
  
  /*
-  * Only use __vcpu_sys_reg if you know you want the memory backed version of a
-  * register, and not the one most recently accessed by a running VCPU.  For
-  * example, for userspace access or for system registers that are never context
-  * switched, but only emulated.
+  * Only use __vcpu_sys_reg/ctxt_sys_reg if you know you want the
+  * memory backed version of a register, and not the one most recently
+  * accessed by a running VCPU.  For example, for userspace access or
+  * for system registers that are never context switched, but only
+  * emulated.
   */
- #define __vcpu_sys_reg(v,r)   ((v)->arch.ctxt.sys_regs[(r)])
+ #define __ctxt_sys_reg(c,r)   (&(c)->sys_regs[(r)])
+ #define ctxt_sys_reg(c,r)     (*__ctxt_sys_reg(c,r))
+ #define __vcpu_sys_reg(v,r)   (ctxt_sys_reg(&(v)->arch.ctxt, (r)))
  
  u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg);
  void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg);
@@@ -442,6 -489,18 +483,18 @@@ void kvm_arm_resume_guest(struct kvm *k
  
  u64 __kvm_call_hyp(void *hypfn, ...);
  
+ #define kvm_call_hyp_nvhe(f, ...)                                     \
+       do {                                                            \
+               DECLARE_KVM_NVHE_SYM(f);                                \
+               __kvm_call_hyp(kvm_ksym_ref_nvhe(f), ##__VA_ARGS__);    \
+       } while(0)
+ #define kvm_call_hyp_nvhe_ret(f, ...)                                 \
+       ({                                                              \
+               DECLARE_KVM_NVHE_SYM(f);                                \
+               __kvm_call_hyp(kvm_ksym_ref_nvhe(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
                        f(__VA_ARGS__);                                 \
                        isb();                                          \
                } else {                                                \
-                       __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__); \
+                       kvm_call_hyp_nvhe(f, ##__VA_ARGS__);            \
                }                                                       \
        } while(0)
  
                        ret = f(__VA_ARGS__);                           \
                        isb();                                          \
                } else {                                                \
-                       ret = __kvm_call_hyp(kvm_ksym_ref(f),           \
-                                            ##__VA_ARGS__);            \
+                       ret = kvm_call_hyp_nvhe_ret(f, ##__VA_ARGS__);  \
                }                                                       \
                                                                        \
                ret;                                                    \
  void force_vm_exit(const cpumask_t *mask);
  void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
  
 -int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
 -              int exception_index);
 -void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run,
 -                     int exception_index);
 +int handle_exit(struct kvm_vcpu *vcpu, int exception_index);
 +void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index);
  
  /* MMIO helpers */
  void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
  unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
  
 -int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 -int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 -               phys_addr_t fault_ipa);
 +int kvm_handle_mmio_return(struct kvm_vcpu *vcpu);
 +int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa);
  
  int kvm_perf_init(void);
  int kvm_perf_teardown(void);
@@@ -518,7 -579,7 +570,7 @@@ DECLARE_PER_CPU(kvm_host_data_t, kvm_ho
  static inline void kvm_init_host_cpu_context(struct kvm_cpu_context *cpu_ctxt)
  {
        /* The host's MPIDR is immutable, so let's set it up at boot time */
-       cpu_ctxt->sys_regs[MPIDR_EL1] = read_cpuid_mpidr();
+       ctxt_sys_reg(cpu_ctxt, MPIDR_EL1) = read_cpuid_mpidr();
  }
  
  static inline bool kvm_arch_requires_vhe(void)
@@@ -619,8 -680,8 +671,8 @@@ static inline int kvm_arm_have_ssbd(voi
        }
  }
  
- void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu);
- void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu);
+ void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu);
+ void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu);
  
  int kvm_set_ipa_limit(void);
  
index 40be8f6c7351dc1b16884a6b147111deda9f33d2,22157ded04ca149007f34ed195308450526b49c7..189839c3706ac526f8a0a73d23e76ff3899a8843
@@@ -134,12 -134,12 +134,12 @@@ int create_hyp_exec_mappings(phys_addr_
  void free_hyp_pgds(void);
  
  void stage2_unmap_vm(struct kvm *kvm);
- int kvm_alloc_stage2_pgd(struct kvm *kvm);
- void kvm_free_stage2_pgd(struct kvm *kvm);
+ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu);
+ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu);
  int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
                          phys_addr_t pa, unsigned long size, bool writable);
  
 -int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run);
 +int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);
  
  void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu);
  
@@@ -577,13 -577,13 +577,13 @@@ static inline u64 kvm_vttbr_baddr_mask(
        return vttbr_baddr_mask(kvm_phys_shift(kvm), kvm_stage2_levels(kvm));
  }
  
- static __always_inline u64 kvm_get_vttbr(struct kvm *kvm)
+ static __always_inline u64 kvm_get_vttbr(struct kvm_s2_mmu *mmu)
  {
-       struct kvm_vmid *vmid = &kvm->arch.vmid;
+       struct kvm_vmid *vmid = &mmu->vmid;
        u64 vmid_field, baddr;
        u64 cnp = system_supports_cnp() ? VTTBR_CNP_BIT : 0;
  
-       baddr = kvm->arch.pgd_phys;
+       baddr = mmu->pgd_phys;
        vmid_field = (u64)vmid->vmid << VTTBR_VMID_SHIFT;
        return kvm_phys_to_vttbr(baddr) | vmid_field | cnp;
  }
   * Must be called from hyp code running at EL2 with an updated VTTBR
   * and interrupts disabled.
   */
- static __always_inline void __load_guest_stage2(struct kvm *kvm)
+ static __always_inline void __load_guest_stage2(struct kvm_s2_mmu *mmu)
  {
-       write_sysreg(kvm->arch.vtcr, vtcr_el2);
-       write_sysreg(kvm_get_vttbr(kvm), vttbr_el2);
+       write_sysreg(kern_hyp_va(mmu->kvm)->arch.vtcr, vtcr_el2);
+       write_sysreg(kvm_get_vttbr(mmu), vttbr_el2);
  
        /*
         * ARM errata 1165522 and 1530923 require the actual execution of the
index 79728bfb5351ffd9cdf258ab9c1c366b0cac3e0f,04729b71c851fa6146d4a8ce9f58abf531f4f2cf..6bd1d3ad037ad492634416f16d4022015acab125
@@@ -472,7 -472,12 +472,7 @@@ static boo
  has_cortex_a76_erratum_1463225(const struct arm64_cpu_capabilities *entry,
                               int scope)
  {
 -      u32 midr = read_cpuid_id();
 -      /* Cortex-A76 r0p0 - r3p1 */
 -      struct midr_range range = MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 1);
 -
 -      WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
 -      return is_midr_in_range(midr, &range) && is_kernel_in_hyp_mode();
 +      return is_affected_midr_range_list(entry, scope) && is_kernel_in_hyp_mode();
  }
  #endif
  
@@@ -632,7 -637,7 +632,7 @@@ has_neoverse_n1_erratum_1542419(const s
        return is_midr_in_range(midr, &range) && has_dic;
  }
  
- #if defined(CONFIG_HARDEN_EL2_VECTORS)
+ #ifdef CONFIG_RANDOMIZE_BASE
  
  static const struct midr_range ca57_a72[] = {
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
@@@ -723,8 -728,6 +723,8 @@@ static const struct midr_range erratum_
        MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 1),
        /* Neoverse-N1 r0p0 to r3p1 */
        MIDR_RANGE(MIDR_NEOVERSE_N1, 0, 0, 3, 1),
 +      /* Kryo4xx Gold (rcpe to rfpf) => (r0p0 to r3p1) */
 +      MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xf),
        {},
  };
  #endif
@@@ -769,23 -772,11 +769,23 @@@ static const struct midr_range erratum_
  #ifdef CONFIG_ARM64_ERRATUM_1530923
        /* Cortex A55 r0p0 to r2p0 */
        MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 2, 0),
 +      /* Kryo4xx Silver (rdpe => r1p0) */
 +      MIDR_REV(MIDR_QCOM_KRYO_4XX_SILVER, 0xd, 0xe),
  #endif
        {},
  };
  #endif
  
 +#ifdef CONFIG_ARM64_ERRATUM_1463225
 +static const struct midr_range erratum_1463225[] = {
 +      /* Cortex-A76 r0p0 - r3p1 */
 +      MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 1),
 +      /* Kryo4xx Gold (rcpe to rfpf) => (r0p0 to r3p1) */
 +      MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xf),
 +      {},
 +};
 +#endif
 +
  const struct arm64_cpu_capabilities arm64_errata[] = {
  #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
        {
                .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
                .matches = check_branch_predictor,
        },
- #ifdef CONFIG_HARDEN_EL2_VECTORS
+ #ifdef CONFIG_RANDOMIZE_BASE
        {
                .desc = "EL2 vector hardening",
                .capability = ARM64_HARDEN_EL2_VECTORS,
                .capability = ARM64_WORKAROUND_1463225,
                .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
                .matches = has_cortex_a76_erratum_1463225,
 +              .midr_range_list = erratum_1463225,
        },
  #endif
  #ifdef CONFIG_CAVIUM_TX2_ERRATUM_219
diff --combined arch/arm64/kvm/arm.c
index 73e12869afe39b5688e985d0f06d5760137979e5,98f05bdac3c1b65e01b67f70479f60ec4036f442..691d21e4c717e19821dc843818496a69509493ad
@@@ -106,22 -106,15 +106,15 @@@ static int kvm_arm_default_max_vcpus(vo
   */
  int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
  {
-       int ret, cpu;
+       int ret;
  
        ret = kvm_arm_setup_stage2(kvm, type);
        if (ret)
                return ret;
  
-       kvm->arch.last_vcpu_ran = alloc_percpu(typeof(*kvm->arch.last_vcpu_ran));
-       if (!kvm->arch.last_vcpu_ran)
-               return -ENOMEM;
-       for_each_possible_cpu(cpu)
-               *per_cpu_ptr(kvm->arch.last_vcpu_ran, cpu) = -1;
-       ret = kvm_alloc_stage2_pgd(kvm);
+       ret = kvm_init_stage2_mmu(kvm, &kvm->arch.mmu);
        if (ret)
-               goto out_fail_alloc;
+               return ret;
  
        ret = create_hyp_mappings(kvm, kvm + 1, PAGE_HYP);
        if (ret)
  
        kvm_vgic_early_init(kvm);
  
-       /* Mark the initial VMID generation invalid */
-       kvm->arch.vmid.vmid_gen = 0;
        /* The maximum number of VCPUs is limited by the host's GIC model */
        kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();
  
        return ret;
  out_free_stage2_pgd:
-       kvm_free_stage2_pgd(kvm);
- out_fail_alloc:
-       free_percpu(kvm->arch.last_vcpu_ran);
-       kvm->arch.last_vcpu_ran = NULL;
+       kvm_free_stage2_pgd(&kvm->arch.mmu);
        return ret;
  }
  
@@@ -160,9 -147,6 +147,6 @@@ void kvm_arch_destroy_vm(struct kvm *kv
  
        kvm_vgic_destroy(kvm);
  
-       free_percpu(kvm->arch.last_vcpu_ran);
-       kvm->arch.last_vcpu_ran = NULL;
        for (i = 0; i < KVM_MAX_VCPUS; ++i) {
                if (kvm->vcpus[i]) {
                        kvm_vcpu_destroy(kvm->vcpus[i]);
@@@ -270,8 -254,6 +254,8 @@@ int kvm_arch_vcpu_create(struct kvm_vcp
        vcpu->arch.target = -1;
        bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
  
 +      vcpu->arch.mmu_page_cache.gfp_zero = __GFP_ZERO;
 +
        /* Set up the timer */
        kvm_timer_vcpu_init(vcpu);
  
  
        kvm_arm_pvtime_vcpu_init(&vcpu->arch);
  
+       vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu;
        err = kvm_vgic_vcpu_init(vcpu);
        if (err)
                return err;
@@@ -336,16 -320,18 +322,18 @@@ void kvm_arch_vcpu_unblocking(struct kv
  
  void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
  {
+       struct kvm_s2_mmu *mmu;
        int *last_ran;
  
-       last_ran = this_cpu_ptr(vcpu->kvm->arch.last_vcpu_ran);
+       mmu = vcpu->arch.hw_mmu;
+       last_ran = this_cpu_ptr(mmu->last_vcpu_ran);
  
        /*
         * We might get preempted before the vCPU actually runs, but
         * over-invalidation doesn't affect correctness.
         */
        if (*last_ran != vcpu->vcpu_id) {
-               kvm_call_hyp(__kvm_tlb_flush_local_vmid, vcpu);
+               kvm_call_hyp(__kvm_tlb_flush_local_vmid, mmu);
                *last_ran = vcpu->vcpu_id;
        }
  
  
        kvm_vgic_load(vcpu);
        kvm_timer_vcpu_load(vcpu);
-       kvm_vcpu_load_sysregs(vcpu);
+       if (has_vhe())
+               kvm_vcpu_load_sysregs_vhe(vcpu);
        kvm_arch_vcpu_load_fp(vcpu);
        kvm_vcpu_pmu_restore_guest(vcpu);
        if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
  void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
  {
        kvm_arch_vcpu_put_fp(vcpu);
-       kvm_vcpu_put_sysregs(vcpu);
+       if (has_vhe())
+               kvm_vcpu_put_sysregs_vhe(vcpu);
        kvm_timer_vcpu_put(vcpu);
        kvm_vgic_put(vcpu);
        kvm_vcpu_pmu_restore_host(vcpu);
@@@ -468,7 -456,6 +458,6 @@@ static bool need_new_vmid_gen(struct kv
  
  /**
   * 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_vmid(struct kvm_vmid *vmid)
@@@ -660,7 -647,7 +649,7 @@@ int kvm_arch_vcpu_ioctl_run(struct kvm_
                return ret;
  
        if (run->exit_reason == KVM_EXIT_MMIO) {
 -              ret = kvm_handle_mmio_return(vcpu, run);
 +              ret = kvm_handle_mmio_return(vcpu);
                if (ret)
                        return ret;
        }
                 */
                cond_resched();
  
-               update_vmid(&vcpu->kvm->arch.vmid);
+               update_vmid(&vcpu->arch.hw_mmu->vmid);
  
                check_vcpu_requests(vcpu);
  
                 */
                smp_store_mb(vcpu->mode, IN_GUEST_MODE);
  
-               if (ret <= 0 || need_new_vmid_gen(&vcpu->kvm->arch.vmid) ||
+               if (ret <= 0 || need_new_vmid_gen(&vcpu->arch.hw_mmu->vmid) ||
                    kvm_request_pending(vcpu)) {
                        vcpu->mode = OUTSIDE_GUEST_MODE;
                        isb(); /* Ensure work in x_flush_hwstate is committed */
                        kvm_pmu_sync_hwstate(vcpu);
                        if (static_branch_unlikely(&userspace_irqchip_in_use))
-                               kvm_timer_sync_hwstate(vcpu);
+                               kvm_timer_sync_user(vcpu);
                        kvm_vgic_sync_hwstate(vcpu);
                        local_irq_enable();
                        preempt_enable();
                trace_kvm_entry(*vcpu_pc(vcpu));
                guest_enter_irqoff();
  
-               if (has_vhe()) {
-                       ret = kvm_vcpu_run_vhe(vcpu);
-               } else {
-                       ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu);
-               }
+               ret = kvm_call_hyp_ret(__kvm_vcpu_run, vcpu);
  
                vcpu->mode = OUTSIDE_GUEST_MODE;
                vcpu->stat.exits++;
                 * timer virtual interrupt state.
                 */
                if (static_branch_unlikely(&userspace_irqchip_in_use))
-                       kvm_timer_sync_hwstate(vcpu);
+                       kvm_timer_sync_user(vcpu);
  
                kvm_arch_vcpu_ctxsync_fp(vcpu);
  
                trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
  
                /* Exit types that need handling before we can be preempted */
 -              handle_exit_early(vcpu, run, ret);
 +              handle_exit_early(vcpu, ret);
  
                preempt_enable();
  
 -              ret = handle_exit(vcpu, run, ret);
 +              ret = handle_exit(vcpu, ret);
        }
  
        /* Tell userspace about in-kernel device output levels */
@@@ -1287,7 -1270,7 +1272,7 @@@ static void cpu_init_hyp_mode(void
         * so that we can use adr_l to access per-cpu variables in EL2.
         */
        tpidr_el2 = ((unsigned long)this_cpu_ptr(&kvm_host_data) -
-                    (unsigned long)kvm_ksym_ref(kvm_host_data));
+                    (unsigned long)kvm_ksym_ref(&kvm_host_data));
  
        pgd_ptr = kvm_mmu_get_httbr();
        hyp_stack_ptr = __this_cpu_read(kvm_arm_hyp_stack_page) + PAGE_SIZE;
         */
        if (this_cpu_has_cap(ARM64_SSBS) &&
            arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) {
-               kvm_call_hyp(__kvm_enable_ssbs);
+               kvm_call_hyp_nvhe(__kvm_enable_ssbs);
        }
  }
  
index 1df3beafd73fc544d26dc5f644e90db14ba81a48,98ab331399826122e7170451486137e344647d2a..fe6c7d79309d6724825ee7429b2cb0bc944beb4d
@@@ -25,7 -25,7 +25,7 @@@
  #define CREATE_TRACE_POINTS
  #include "trace_handle_exit.h"
  
 -typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
 +typedef int (*exit_handle_fn)(struct kvm_vcpu *);
  
  static void kvm_handle_guest_serror(struct kvm_vcpu *vcpu, u32 esr)
  {
@@@ -33,7 -33,7 +33,7 @@@
                kvm_inject_vabt(vcpu);
  }
  
 -static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int handle_hvc(struct kvm_vcpu *vcpu)
  {
        int ret;
  
@@@ -50,7 -50,7 +50,7 @@@
        return ret;
  }
  
 -static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int handle_smc(struct kvm_vcpu *vcpu)
  {
        /*
         * "If an SMC instruction executed at Non-secure EL1 is
@@@ -69,7 -69,7 +69,7 @@@
   * Guest access to FP/ASIMD registers are routed to this handler only
   * when the system doesn't support FP/ASIMD.
   */
 -static int handle_no_fpsimd(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int handle_no_fpsimd(struct kvm_vcpu *vcpu)
  {
        kvm_inject_undefined(vcpu);
        return 1;
@@@ -87,9 -87,9 +87,9 @@@
   * world-switches and schedule other host processes until there is an
   * incoming IRQ or FIQ to the VM.
   */
 -static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int kvm_handle_wfx(struct kvm_vcpu *vcpu)
  {
-       if (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WFx_ISS_WFE) {
+       if (kvm_vcpu_get_esr(vcpu) & ESR_ELx_WFx_ISS_WFE) {
                trace_kvm_wfx_arm64(*vcpu_pc(vcpu), true);
                vcpu->stat.wfe_exit_stat++;
                kvm_vcpu_on_spin(vcpu, vcpu_mode_priv(vcpu));
   * kvm_handle_guest_debug - handle a debug exception instruction
   *
   * @vcpu:     the vcpu pointer
 - * @run:      access to the kvm_run structure for results
   *
   * We route all debug exceptions through the same handler. If both the
   * guest and host are using the same debug facilities it will be up to
   * userspace to re-inject the correct exception for guest delivery.
   *
 - * @return: 0 (while setting run->exit_reason), -1 for error
 + * @return: 0 (while setting vcpu->run->exit_reason), -1 for error
   */
 -static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu)
  {
-       u32 hsr = kvm_vcpu_get_hsr(vcpu);
 +      struct kvm_run *run = vcpu->run;
+       u32 esr = kvm_vcpu_get_esr(vcpu);
        int ret = 0;
  
        run->exit_reason = KVM_EXIT_DEBUG;
-       run->debug.arch.hsr = hsr;
+       run->debug.arch.hsr = esr;
  
-       switch (ESR_ELx_EC(hsr)) {
+       switch (ESR_ELx_EC(esr)) {
        case ESR_ELx_EC_WATCHPT_LOW:
                run->debug.arch.far = vcpu->arch.fault.far_el2;
                /* fall through */
        case ESR_ELx_EC_BRK64:
                break;
        default:
-               kvm_err("%s: un-handled case hsr: %#08x\n",
-                       __func__, (unsigned int) hsr);
+               kvm_err("%s: un-handled case esr: %#08x\n",
+                       __func__, (unsigned int) esr);
                ret = -1;
                break;
        }
        return ret;
  }
  
 -static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu)
  {
-       u32 hsr = kvm_vcpu_get_hsr(vcpu);
+       u32 esr = kvm_vcpu_get_esr(vcpu);
  
-       kvm_pr_unimpl("Unknown exception class: hsr: %#08x -- %s\n",
-                     hsr, esr_get_class_string(hsr));
+       kvm_pr_unimpl("Unknown exception class: esr: %#08x -- %s\n",
+                     esr, esr_get_class_string(esr));
  
        kvm_inject_undefined(vcpu);
        return 1;
  }
  
 -static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int handle_sve(struct kvm_vcpu *vcpu)
  {
        /* Until SVE is supported for guests: */
        kvm_inject_undefined(vcpu);
   * a NOP). If we get here, it is that we didn't fixup ptrauth on exit, and all
   * that we can do is give the guest an UNDEF.
   */
 -static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu)
  {
        kvm_inject_undefined(vcpu);
        return 1;
@@@ -200,10 -200,10 +200,10 @@@ static exit_handle_fn arm_exit_handlers
  
  static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
  {
-       u32 hsr = kvm_vcpu_get_hsr(vcpu);
-       u8 hsr_ec = ESR_ELx_EC(hsr);
+       u32 esr = kvm_vcpu_get_esr(vcpu);
+       u8 esr_ec = ESR_ELx_EC(esr);
  
-       return arm_exit_handlers[hsr_ec];
+       return arm_exit_handlers[esr_ec];
  }
  
  /*
   * KVM_EXIT_DEBUG, otherwise userspace needs to complete its
   * emulation first.
   */
 -static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +static int handle_trap_exceptions(struct kvm_vcpu *vcpu)
  {
        int handled;
  
                exit_handle_fn exit_handler;
  
                exit_handler = kvm_get_exit_handler(vcpu);
 -              handled = exit_handler(vcpu, run);
 +              handled = exit_handler(vcpu);
        }
  
        return handled;
   * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
   * proper exit to userspace.
   */
 -int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
 -                     int exception_index)
 +int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
  {
 +      struct kvm_run *run = vcpu->run;
 +
        if (ARM_SERROR_PENDING(exception_index)) {
-               u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
+               u8 esr_ec = ESR_ELx_EC(kvm_vcpu_get_esr(vcpu));
  
                /*
                 * HVC/SMC already have an adjusted PC, which we need
                 * to correct in order to return to after having
                 * injected the SError.
                 */
-               if (hsr_ec == ESR_ELx_EC_HVC32 || hsr_ec == ESR_ELx_EC_HVC64 ||
-                   hsr_ec == ESR_ELx_EC_SMC32 || hsr_ec == ESR_ELx_EC_SMC64) {
+               if (esr_ec == ESR_ELx_EC_HVC32 || esr_ec == ESR_ELx_EC_HVC64 ||
+                   esr_ec == ESR_ELx_EC_SMC32 || esr_ec == ESR_ELx_EC_SMC64) {
                        u32 adj =  kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2;
                        *vcpu_pc(vcpu) -= adj;
                }
        case ARM_EXCEPTION_EL1_SERROR:
                return 1;
        case ARM_EXCEPTION_TRAP:
 -              return handle_trap_exceptions(vcpu, run);
 +              return handle_trap_exceptions(vcpu);
        case ARM_EXCEPTION_HYP_GONE:
                /*
                 * EL2 has been reset to the hyp-stub. This happens when a guest
  }
  
  /* For exit types that need handling before we can be preempted */
 -void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run,
 -                     int exception_index)
 +void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
  {
        if (ARM_SERROR_PENDING(exception_index)) {
                if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN)) {
        exception_index = ARM_EXCEPTION_CODE(exception_index);
  
        if (exception_index == ARM_EXCEPTION_EL1_SERROR)
-               kvm_handle_guest_serror(vcpu, kvm_vcpu_get_hsr(vcpu));
+               kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
  }
index 0000000000000000000000000000000000000000,1587d146726abae1dff01b4ea3fc38a9ce9189eb..d9434e90c06d763d4f8a17dd3c0669b48f2b8dc4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,168 +1,172 @@@
 -reset:
+ /* SPDX-License-Identifier: GPL-2.0-only */
+ /*
+  * Copyright (C) 2012,2013 - ARM Ltd
+  * Author: Marc Zyngier <[email protected]>
+  */
+ #include <linux/linkage.h>
++#include <asm/alternative.h>
+ #include <asm/assembler.h>
+ #include <asm/kvm_arm.h>
+ #include <asm/kvm_mmu.h>
+ #include <asm/pgtable-hwdef.h>
+ #include <asm/sysreg.h>
+ #include <asm/virt.h>
+       .text
+       .pushsection    .hyp.idmap.text, "ax"
+       .align  11
+ SYM_CODE_START(__kvm_hyp_init)
+       ventry  __invalid               // Synchronous EL2t
+       ventry  __invalid               // IRQ EL2t
+       ventry  __invalid               // FIQ EL2t
+       ventry  __invalid               // Error EL2t
+       ventry  __invalid               // Synchronous EL2h
+       ventry  __invalid               // IRQ EL2h
+       ventry  __invalid               // FIQ EL2h
+       ventry  __invalid               // Error EL2h
+       ventry  __do_hyp_init           // Synchronous 64-bit EL1
+       ventry  __invalid               // IRQ 64-bit EL1
+       ventry  __invalid               // FIQ 64-bit EL1
+       ventry  __invalid               // Error 64-bit EL1
+       ventry  __invalid               // Synchronous 32-bit EL1
+       ventry  __invalid               // IRQ 32-bit EL1
+       ventry  __invalid               // FIQ 32-bit EL1
+       ventry  __invalid               // Error 32-bit EL1
+ __invalid:
+       b       .
+       /*
+        * x0: HYP pgd
+        * x1: HYP stack
+        * x2: HYP vectors
+        * x3: per-CPU offset
+        */
+ __do_hyp_init:
+       /* Check for a stub HVC call */
+       cmp     x0, #HVC_STUB_HCALL_NR
+       b.lo    __kvm_handle_stub_hvc
+       phys_to_ttbr x4, x0
+ alternative_if ARM64_HAS_CNP
+       orr     x4, x4, #TTBR_CNP_BIT
+ alternative_else_nop_endif
+       msr     ttbr0_el2, x4
+       mrs     x4, tcr_el1
+       mov_q   x5, TCR_EL2_MASK
+       and     x4, x4, x5
+       mov     x5, #TCR_EL2_RES1
+       orr     x4, x4, x5
+       /*
+        * The ID map may be configured to use an extended virtual address
+        * range. This is only the case if system RAM is out of range for the
+        * currently configured page size and VA_BITS, in which case we will
+        * also need the extended virtual range for the HYP ID map, or we won't
+        * be able to enable the EL2 MMU.
+        *
+        * However, at EL2, there is only one TTBR register, and we can't switch
+        * between translation tables *and* update TCR_EL2.T0SZ at the same
+        * time. Bottom line: we need to use the extended range with *both* our
+        * translation tables.
+        *
+        * So use the same T0SZ value we use for the ID map.
+        */
+       ldr_l   x5, idmap_t0sz
+       bfi     x4, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
+       /*
+        * Set the PS bits in TCR_EL2.
+        */
+       tcr_compute_pa_size x4, #TCR_EL2_PS_SHIFT, x5, x6
+       msr     tcr_el2, x4
+       mrs     x4, mair_el1
+       msr     mair_el2, x4
+       isb
+       /* Invalidate the stale TLBs from Bootloader */
+       tlbi    alle2
+       dsb     sy
+       /*
+        * Preserve all the RES1 bits while setting the default flags,
+        * as well as the EE bit on BE. Drop the A flag since the compiler
+        * is allowed to generate unaligned accesses.
+        */
+       mov_q   x4, (SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A))
+ CPU_BE(       orr     x4, x4, #SCTLR_ELx_EE)
+ alternative_if ARM64_HAS_ADDRESS_AUTH
+       mov_q   x5, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \
+                    SCTLR_ELx_ENDA | SCTLR_ELx_ENDB)
+       orr     x4, x4, x5
+ alternative_else_nop_endif
+       msr     sctlr_el2, x4
+       isb
+       /* Set the stack and new vectors */
+       kern_hyp_va     x1
+       mov     sp, x1
+       msr     vbar_el2, x2
+       /* Set tpidr_el2 for use by HYP */
+       msr     tpidr_el2, x3
+       /* Hello, World! */
+       eret
+ SYM_CODE_END(__kvm_hyp_init)
+ SYM_CODE_START(__kvm_handle_stub_hvc)
+       cmp     x0, #HVC_SOFT_RESTART
+       b.ne    1f
+       /* This is where we're about to jump, staying at EL2 */
+       msr     elr_el2, x1
+       mov     x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT | PSR_MODE_EL2h)
+       msr     spsr_el2, x0
+       /* Shuffle the arguments, and don't come back */
+       mov     x0, x2
+       mov     x1, x3
+       mov     x2, x4
+       b       reset
+ 1:    cmp     x0, #HVC_RESET_VECTORS
+       b.ne    1f
 -       * Reset kvm back to the hyp stub. Do not clobber x0-x4 in
 -       * case we coming via HVC_SOFT_RESTART.
++
+       /*
 -      mov     x0, xzr
++       * Set the HVC_RESET_VECTORS return code before entering the common
++       * path so that we do not clobber x0-x2 in case we are coming via
++       * HVC_SOFT_RESTART.
+        */
++      mov     x0, xzr
++reset:
++      /* Reset kvm back to the hyp stub. */
+       mrs     x5, sctlr_el2
+       mov_q   x6, SCTLR_ELx_FLAGS
+       bic     x5, x5, x6              // Clear SCTL_M and etc
+       pre_disable_mmu_workaround
+       msr     sctlr_el2, x5
+       isb
+       /* Install stub vectors */
+       adr_l   x5, __hyp_stub_vectors
+       msr     vbar_el2, x5
+       eret
+ 1:    /* Bad stub call */
+       mov_q   x0, HVC_STUB_ERR
+       eret
+ SYM_CODE_END(__kvm_handle_stub_hvc)
+       .popsection
diff --combined arch/arm64/kvm/mmio.c
index 158fbe68261109bdbde8a7df9c3b9f9716ba593c,58de2ae4f6bb40e92a780b5d29edd083cd5c49d2..6a2826f1bf5e99532a08969be845022a2c8e2f76
@@@ -77,8 -77,9 +77,8 @@@ unsigned long kvm_mmio_read_buf(const v
   *                         or in-kernel IO emulation
   *
   * @vcpu: The VCPU pointer
 - * @run:  The VCPU run struct containing the mmio data
   */
 -int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
  {
        unsigned long data;
        unsigned int len;
@@@ -91,8 -92,6 +91,8 @@@
        vcpu->mmio_needed = 0;
  
        if (!kvm_vcpu_dabt_iswrite(vcpu)) {
 +              struct kvm_run *run = vcpu->run;
 +
                len = kvm_vcpu_dabt_get_as(vcpu);
                data = kvm_mmio_read_buf(run->mmio.data, len);
  
        return 0;
  }
  
 -int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 -               phys_addr_t fault_ipa)
 +int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
  {
 +      struct kvm_run *run = vcpu->run;
        unsigned long data;
        unsigned long rt;
        int ret;
                return -ENOSYS;
        }
  
-       /* Page table accesses IO mem: tell guest to fix its TTBR */
-       if (kvm_vcpu_dabt_iss1tw(vcpu)) {
-               kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
-               return 1;
-       }
        /*
         * Prepare MMIO operation. First decode the syndrome data we get
         * from the CPU. Then try if some in-kernel emulation feels
                if (!is_write)
                        memcpy(run->mmio.data, data_buf, len);
                vcpu->stat.mmio_exit_kernel++;
 -              kvm_handle_mmio_return(vcpu, run);
 +              kvm_handle_mmio_return(vcpu);
                return 1;
        }
  
diff --combined arch/arm64/kvm/mmu.c
index 7a7ddc4558a7697a69ca42b581f11a82e02788dd,05e0e03fbdf80131bf9a34ce646f75f7638860b5..0121ef2c7c8d2f720a9377257058bf090228811c
@@@ -55,12 -55,13 +55,13 @@@ static bool memslot_is_logging(struct k
   */
  void kvm_flush_remote_tlbs(struct kvm *kvm)
  {
-       kvm_call_hyp(__kvm_tlb_flush_vmid, kvm);
+       kvm_call_hyp(__kvm_tlb_flush_vmid, &kvm->arch.mmu);
  }
  
- static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
+ static void kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa,
+                                  int level)
  {
-       kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
+       kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ipa, level);
  }
  
  /*
@@@ -90,74 -91,112 +91,80 @@@ static bool kvm_is_device_pfn(unsigned 
  
  /**
   * stage2_dissolve_pmd() - clear and flush huge PMD entry
-  * @kvm:      pointer to kvm structure.
+  * @mmu:      pointer to mmu structure to operate on
   * @addr:     IPA
   * @pmd:      pmd pointer for IPA
   *
   * Function clears a PMD entry, flushes addr 1st and 2nd stage TLBs.
   */
- static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd)
+ static void stage2_dissolve_pmd(struct kvm_s2_mmu *mmu, phys_addr_t addr, pmd_t *pmd)
  {
        if (!pmd_thp_or_huge(*pmd))
                return;
  
        pmd_clear(pmd);
-       kvm_tlb_flush_vmid_ipa(kvm, addr);
+       kvm_tlb_flush_vmid_ipa(mmu, addr, S2_PMD_LEVEL);
        put_page(virt_to_page(pmd));
  }
  
  /**
   * stage2_dissolve_pud() - clear and flush huge PUD entry
-  * @kvm:      pointer to kvm structure.
+  * @mmu:      pointer to mmu structure to operate on
   * @addr:     IPA
   * @pud:      pud pointer for IPA
   *
   * Function clears a PUD entry, flushes addr 1st and 2nd stage TLBs.
   */
- static void stage2_dissolve_pud(struct kvm *kvm, phys_addr_t addr, pud_t *pudp)
+ static void stage2_dissolve_pud(struct kvm_s2_mmu *mmu, phys_addr_t addr, pud_t *pudp)
  {
+       struct kvm *kvm = mmu->kvm;
        if (!stage2_pud_huge(kvm, *pudp))
                return;
  
        stage2_pud_clear(kvm, pudp);
-       kvm_tlb_flush_vmid_ipa(kvm, addr);
+       kvm_tlb_flush_vmid_ipa(mmu, addr, S2_PUD_LEVEL);
        put_page(virt_to_page(pudp));
  }
  
- static void clear_stage2_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr)
 -static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
 -                                int min, int max)
 -{
 -      void *page;
 -
 -      BUG_ON(max > KVM_NR_MEM_OBJS);
 -      if (cache->nobjs >= min)
 -              return 0;
 -      while (cache->nobjs < max) {
 -              page = (void *)__get_free_page(GFP_PGTABLE_USER);
 -              if (!page)
 -                      return -ENOMEM;
 -              cache->objects[cache->nobjs++] = page;
 -      }
 -      return 0;
 -}
 -
 -static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc)
 -{
 -      while (mc->nobjs)
 -              free_page((unsigned long)mc->objects[--mc->nobjs]);
 -}
 -
 -static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
 -{
 -      void *p;
 -
 -      BUG_ON(!mc || !mc->nobjs);
 -      p = mc->objects[--mc->nobjs];
 -      return p;
 -}
 -
+ static void clear_stage2_pgd_entry(struct kvm_s2_mmu *mmu, pgd_t *pgd, phys_addr_t addr)
  {
+       struct kvm *kvm = mmu->kvm;
        p4d_t *p4d_table __maybe_unused = stage2_p4d_offset(kvm, pgd, 0UL);
        stage2_pgd_clear(kvm, pgd);
-       kvm_tlb_flush_vmid_ipa(kvm, addr);
+       kvm_tlb_flush_vmid_ipa(mmu, addr, S2_NO_LEVEL_HINT);
        stage2_p4d_free(kvm, p4d_table);
        put_page(virt_to_page(pgd));
  }
  
- static void clear_stage2_p4d_entry(struct kvm *kvm, p4d_t *p4d, phys_addr_t addr)
+ static void clear_stage2_p4d_entry(struct kvm_s2_mmu *mmu, p4d_t *p4d, phys_addr_t addr)
  {
+       struct kvm *kvm = mmu->kvm;
        pud_t *pud_table __maybe_unused = stage2_pud_offset(kvm, p4d, 0);
        stage2_p4d_clear(kvm, p4d);
-       kvm_tlb_flush_vmid_ipa(kvm, addr);
+       kvm_tlb_flush_vmid_ipa(mmu, addr, S2_NO_LEVEL_HINT);
        stage2_pud_free(kvm, pud_table);
        put_page(virt_to_page(p4d));
  }
  
- static void clear_stage2_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
+ static void clear_stage2_pud_entry(struct kvm_s2_mmu *mmu, pud_t *pud, phys_addr_t addr)
  {
+       struct kvm *kvm = mmu->kvm;
        pmd_t *pmd_table __maybe_unused = stage2_pmd_offset(kvm, pud, 0);
        VM_BUG_ON(stage2_pud_huge(kvm, *pud));
        stage2_pud_clear(kvm, pud);
-       kvm_tlb_flush_vmid_ipa(kvm, addr);
+       kvm_tlb_flush_vmid_ipa(mmu, addr, S2_NO_LEVEL_HINT);
        stage2_pmd_free(kvm, pmd_table);
        put_page(virt_to_page(pud));
  }
  
- static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
+ static void clear_stage2_pmd_entry(struct kvm_s2_mmu *mmu, pmd_t *pmd, phys_addr_t addr)
  {
        pte_t *pte_table = pte_offset_kernel(pmd, 0);
        VM_BUG_ON(pmd_thp_or_huge(*pmd));
        pmd_clear(pmd);
-       kvm_tlb_flush_vmid_ipa(kvm, addr);
+       kvm_tlb_flush_vmid_ipa(mmu, addr, S2_NO_LEVEL_HINT);
        free_page((unsigned long)pte_table);
        put_page(virt_to_page(pmd));
  }
@@@ -223,7 -262,7 +230,7 @@@ static inline void kvm_pgd_populate(pgd
   * we then fully enforce cacheability of RAM, no matter what the guest
   * does.
   */
- static void unmap_stage2_ptes(struct kvm *kvm, pmd_t *pmd,
+ static void unmap_stage2_ptes(struct kvm_s2_mmu *mmu, pmd_t *pmd,
                       phys_addr_t addr, phys_addr_t end)
  {
        phys_addr_t start_addr = addr;
                        pte_t old_pte = *pte;
  
                        kvm_set_pte(pte, __pte(0));
-                       kvm_tlb_flush_vmid_ipa(kvm, addr);
+                       kvm_tlb_flush_vmid_ipa(mmu, addr, S2_PTE_LEVEL);
  
                        /* No need to invalidate the cache for device mappings */
                        if (!kvm_is_device_pfn(pte_pfn(old_pte)))
                }
        } while (pte++, addr += PAGE_SIZE, addr != end);
  
-       if (stage2_pte_table_empty(kvm, start_pte))
-               clear_stage2_pmd_entry(kvm, pmd, start_addr);
+       if (stage2_pte_table_empty(mmu->kvm, start_pte))
+               clear_stage2_pmd_entry(mmu, pmd, start_addr);
  }
  
- static void unmap_stage2_pmds(struct kvm *kvm, pud_t *pud,
+ static void unmap_stage2_pmds(struct kvm_s2_mmu *mmu, pud_t *pud,
                       phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        phys_addr_t next, start_addr = addr;
        pmd_t *pmd, *start_pmd;
  
                                pmd_t old_pmd = *pmd;
  
                                pmd_clear(pmd);
-                               kvm_tlb_flush_vmid_ipa(kvm, addr);
+                               kvm_tlb_flush_vmid_ipa(mmu, addr, S2_PMD_LEVEL);
  
                                kvm_flush_dcache_pmd(old_pmd);
  
                                put_page(virt_to_page(pmd));
                        } else {
-                               unmap_stage2_ptes(kvm, pmd, addr, next);
+                               unmap_stage2_ptes(mmu, pmd, addr, next);
                        }
                }
        } while (pmd++, addr = next, addr != end);
  
        if (stage2_pmd_table_empty(kvm, start_pmd))
-               clear_stage2_pud_entry(kvm, pud, start_addr);
+               clear_stage2_pud_entry(mmu, pud, start_addr);
  }
  
- static void unmap_stage2_puds(struct kvm *kvm, p4d_t *p4d,
+ static void unmap_stage2_puds(struct kvm_s2_mmu *mmu, p4d_t *p4d,
                       phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        phys_addr_t next, start_addr = addr;
        pud_t *pud, *start_pud;
  
                                pud_t old_pud = *pud;
  
                                stage2_pud_clear(kvm, pud);
-                               kvm_tlb_flush_vmid_ipa(kvm, addr);
+                               kvm_tlb_flush_vmid_ipa(mmu, addr, S2_PUD_LEVEL);
                                kvm_flush_dcache_pud(old_pud);
                                put_page(virt_to_page(pud));
                        } else {
-                               unmap_stage2_pmds(kvm, pud, addr, next);
+                               unmap_stage2_pmds(mmu, pud, addr, next);
                        }
                }
        } while (pud++, addr = next, addr != end);
  
        if (stage2_pud_table_empty(kvm, start_pud))
-               clear_stage2_p4d_entry(kvm, p4d, start_addr);
+               clear_stage2_p4d_entry(mmu, p4d, start_addr);
  }
  
- static void unmap_stage2_p4ds(struct kvm *kvm, pgd_t *pgd,
+ static void unmap_stage2_p4ds(struct kvm_s2_mmu *mmu, pgd_t *pgd,
                       phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        phys_addr_t next, start_addr = addr;
        p4d_t *p4d, *start_p4d;
  
        do {
                next = stage2_p4d_addr_end(kvm, addr, end);
                if (!stage2_p4d_none(kvm, *p4d))
-                       unmap_stage2_puds(kvm, p4d, addr, next);
+                       unmap_stage2_puds(mmu, p4d, addr, next);
        } while (p4d++, addr = next, addr != end);
  
        if (stage2_p4d_table_empty(kvm, start_p4d))
-               clear_stage2_pgd_entry(kvm, pgd, start_addr);
+               clear_stage2_pgd_entry(mmu, pgd, start_addr);
  }
  
  /**
   * destroying the VM), otherwise another faulting VCPU may come in and mess
   * with things behind our backs.
   */
- static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
+ static void unmap_stage2_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64 size)
  {
+       struct kvm *kvm = mmu->kvm;
        pgd_t *pgd;
        phys_addr_t addr = start, end = start + size;
        phys_addr_t next;
        assert_spin_locked(&kvm->mmu_lock);
        WARN_ON(size & ~PAGE_MASK);
  
-       pgd = kvm->arch.pgd + stage2_pgd_index(kvm, addr);
+       pgd = mmu->pgd + stage2_pgd_index(kvm, addr);
        do {
                /*
                 * Make sure the page table is still active, as another thread
                 * could have possibly freed the page table, while we released
                 * the lock.
                 */
-               if (!READ_ONCE(kvm->arch.pgd))
+               if (!READ_ONCE(mmu->pgd))
                        break;
                next = stage2_pgd_addr_end(kvm, addr, end);
                if (!stage2_pgd_none(kvm, *pgd))
-                       unmap_stage2_p4ds(kvm, pgd, addr, next);
+                       unmap_stage2_p4ds(mmu, pgd, addr, next);
                /*
                 * If the range is too large, release the kvm->mmu_lock
                 * to prevent starvation and lockup detector warnings.
        } while (pgd++, addr = next, addr != end);
  }
  
- static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
+ static void stage2_flush_ptes(struct kvm_s2_mmu *mmu, pmd_t *pmd,
                              phys_addr_t addr, phys_addr_t end)
  {
        pte_t *pte;
        } while (pte++, addr += PAGE_SIZE, addr != end);
  }
  
- static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud,
+ static void stage2_flush_pmds(struct kvm_s2_mmu *mmu, pud_t *pud,
                              phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        pmd_t *pmd;
        phys_addr_t next;
  
                        if (pmd_thp_or_huge(*pmd))
                                kvm_flush_dcache_pmd(*pmd);
                        else
-                               stage2_flush_ptes(kvm, pmd, addr, next);
+                               stage2_flush_ptes(mmu, pmd, addr, next);
                }
        } while (pmd++, addr = next, addr != end);
  }
  
- static void stage2_flush_puds(struct kvm *kvm, p4d_t *p4d,
+ static void stage2_flush_puds(struct kvm_s2_mmu *mmu, p4d_t *p4d,
                              phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        pud_t *pud;
        phys_addr_t next;
  
                        if (stage2_pud_huge(kvm, *pud))
                                kvm_flush_dcache_pud(*pud);
                        else
-                               stage2_flush_pmds(kvm, pud, addr, next);
+                               stage2_flush_pmds(mmu, pud, addr, next);
                }
        } while (pud++, addr = next, addr != end);
  }
  
- static void stage2_flush_p4ds(struct kvm *kvm, pgd_t *pgd,
+ static void stage2_flush_p4ds(struct kvm_s2_mmu *mmu, pgd_t *pgd,
                              phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        p4d_t *p4d;
        phys_addr_t next;
  
        do {
                next = stage2_p4d_addr_end(kvm, addr, end);
                if (!stage2_p4d_none(kvm, *p4d))
-                       stage2_flush_puds(kvm, p4d, addr, next);
+                       stage2_flush_puds(mmu, p4d, addr, next);
        } while (p4d++, addr = next, addr != end);
  }
  
  static void stage2_flush_memslot(struct kvm *kvm,
                                 struct kvm_memory_slot *memslot)
  {
+       struct kvm_s2_mmu *mmu = &kvm->arch.mmu;
        phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT;
        phys_addr_t end = addr + PAGE_SIZE * memslot->npages;
        phys_addr_t next;
        pgd_t *pgd;
  
-       pgd = kvm->arch.pgd + stage2_pgd_index(kvm, addr);
+       pgd = mmu->pgd + stage2_pgd_index(kvm, addr);
        do {
                next = stage2_pgd_addr_end(kvm, addr, end);
                if (!stage2_pgd_none(kvm, *pgd))
-                       stage2_flush_p4ds(kvm, pgd, addr, next);
+                       stage2_flush_p4ds(mmu, pgd, addr, next);
  
                if (next != end)
                        cond_resched_lock(&kvm->mmu_lock);
@@@ -964,21 -1011,23 +979,23 @@@ int create_hyp_exec_mappings(phys_addr_
  }
  
  /**
-  * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation.
-  * @kvm:      The KVM struct pointer for the VM.
+  * kvm_init_stage2_mmu - Initialise a S2 MMU strucrure
+  * @kvm:      The pointer to the KVM structure
+  * @mmu:      The pointer to the s2 MMU structure
   *
   * Allocates only the stage-2 HW PGD level table(s) of size defined by
-  * stage2_pgd_size(kvm).
+  * stage2_pgd_size(mmu->kvm).
   *
   * Note we don't need locking here as this is only called when the VM is
   * created, which can only be done once.
   */
- int kvm_alloc_stage2_pgd(struct kvm *kvm)
+ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu)
  {
        phys_addr_t pgd_phys;
        pgd_t *pgd;
+       int cpu;
  
-       if (kvm->arch.pgd != NULL) {
+       if (mmu->pgd != NULL) {
                kvm_err("kvm_arch already initialized?\n");
                return -EINVAL;
        }
        if (WARN_ON(pgd_phys & ~kvm_vttbr_baddr_mask(kvm)))
                return -EINVAL;
  
-       kvm->arch.pgd = pgd;
-       kvm->arch.pgd_phys = pgd_phys;
+       mmu->last_vcpu_ran = alloc_percpu(typeof(*mmu->last_vcpu_ran));
+       if (!mmu->last_vcpu_ran) {
+               free_pages_exact(pgd, stage2_pgd_size(kvm));
+               return -ENOMEM;
+       }
+       for_each_possible_cpu(cpu)
+               *per_cpu_ptr(mmu->last_vcpu_ran, cpu) = -1;
+       mmu->kvm = kvm;
+       mmu->pgd = pgd;
+       mmu->pgd_phys = pgd_phys;
+       mmu->vmid.vmid_gen = 0;
        return 0;
  }
  
@@@ -1032,7 -1093,7 +1061,7 @@@ static void stage2_unmap_memslot(struc
  
                if (!(vma->vm_flags & VM_PFNMAP)) {
                        gpa_t gpa = addr + (vm_start - memslot->userspace_addr);
-                       unmap_stage2_range(kvm, gpa, vm_end - vm_start);
+                       unmap_stage2_range(&kvm->arch.mmu, gpa, vm_end - vm_start);
                }
                hva = vm_end;
        } while (hva < reg_end);
@@@ -1064,43 -1125,38 +1093,38 @@@ void stage2_unmap_vm(struct kvm *kvm
        srcu_read_unlock(&kvm->srcu, idx);
  }
  
- /**
-  * kvm_free_stage2_pgd - free all stage-2 tables
-  * @kvm:      The KVM struct pointer for the VM.
-  *
-  * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all
-  * underlying level-2 and level-3 tables before freeing the actual level-1 table
-  * and setting the struct pointer to NULL.
-  */
- void kvm_free_stage2_pgd(struct kvm *kvm)
+ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
  {
+       struct kvm *kvm = mmu->kvm;
        void *pgd = NULL;
  
        spin_lock(&kvm->mmu_lock);
-       if (kvm->arch.pgd) {
-               unmap_stage2_range(kvm, 0, kvm_phys_size(kvm));
-               pgd = READ_ONCE(kvm->arch.pgd);
-               kvm->arch.pgd = NULL;
-               kvm->arch.pgd_phys = 0;
+       if (mmu->pgd) {
+               unmap_stage2_range(mmu, 0, kvm_phys_size(kvm));
+               pgd = READ_ONCE(mmu->pgd);
+               mmu->pgd = NULL;
        }
        spin_unlock(&kvm->mmu_lock);
  
        /* Free the HW pgd, one page at a time */
-       if (pgd)
+       if (pgd) {
                free_pages_exact(pgd, stage2_pgd_size(kvm));
+               free_percpu(mmu->last_vcpu_ran);
+       }
  }
  
- static p4d_t *stage2_get_p4d(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+ static p4d_t *stage2_get_p4d(struct kvm_s2_mmu *mmu, struct kvm_mmu_memory_cache *cache,
                             phys_addr_t addr)
  {
+       struct kvm *kvm = mmu->kvm;
        pgd_t *pgd;
        p4d_t *p4d;
  
-       pgd = kvm->arch.pgd + stage2_pgd_index(kvm, addr);
+       pgd = mmu->pgd + stage2_pgd_index(kvm, addr);
        if (stage2_pgd_none(kvm, *pgd)) {
                if (!cache)
                        return NULL;
 -              p4d = mmu_memory_cache_alloc(cache);
 +              p4d = kvm_mmu_memory_cache_alloc(cache);
                stage2_pgd_populate(kvm, pgd, p4d);
                get_page(virt_to_page(pgd));
        }
        return stage2_p4d_offset(kvm, pgd, addr);
  }
  
- static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+ static pud_t *stage2_get_pud(struct kvm_s2_mmu *mmu, struct kvm_mmu_memory_cache *cache,
                             phys_addr_t addr)
  {
+       struct kvm *kvm = mmu->kvm;
        p4d_t *p4d;
        pud_t *pud;
  
-       p4d = stage2_get_p4d(kvm, cache, addr);
+       p4d = stage2_get_p4d(mmu, cache, addr);
        if (stage2_p4d_none(kvm, *p4d)) {
                if (!cache)
                        return NULL;
 -              pud = mmu_memory_cache_alloc(cache);
 +              pud = kvm_mmu_memory_cache_alloc(cache);
                stage2_p4d_populate(kvm, p4d, pud);
                get_page(virt_to_page(p4d));
        }
        return stage2_pud_offset(kvm, p4d, addr);
  }
  
- static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+ static pmd_t *stage2_get_pmd(struct kvm_s2_mmu *mmu, struct kvm_mmu_memory_cache *cache,
                             phys_addr_t addr)
  {
+       struct kvm *kvm = mmu->kvm;
        pud_t *pud;
        pmd_t *pmd;
  
-       pud = stage2_get_pud(kvm, cache, addr);
+       pud = stage2_get_pud(mmu, cache, addr);
        if (!pud || stage2_pud_huge(kvm, *pud))
                return NULL;
  
        if (stage2_pud_none(kvm, *pud)) {
                if (!cache)
                        return NULL;
 -              pmd = mmu_memory_cache_alloc(cache);
 +              pmd = kvm_mmu_memory_cache_alloc(cache);
                stage2_pud_populate(kvm, pud, pmd);
                get_page(virt_to_page(pud));
        }
        return stage2_pmd_offset(kvm, pud, addr);
  }
  
- static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
-                              *cache, phys_addr_t addr, const pmd_t *new_pmd)
+ static int stage2_set_pmd_huge(struct kvm_s2_mmu *mmu,
+                              struct kvm_mmu_memory_cache *cache,
+                              phys_addr_t addr, const pmd_t *new_pmd)
  {
        pmd_t *pmd, old_pmd;
  
  retry:
-       pmd = stage2_get_pmd(kvm, cache, addr);
+       pmd = stage2_get_pmd(mmu, cache, addr);
        VM_BUG_ON(!pmd);
  
        old_pmd = *pmd;
                 * get handled accordingly.
                 */
                if (!pmd_thp_or_huge(old_pmd)) {
-                       unmap_stage2_range(kvm, addr & S2_PMD_MASK, S2_PMD_SIZE);
+                       unmap_stage2_range(mmu, addr & S2_PMD_MASK, S2_PMD_SIZE);
                        goto retry;
                }
                /*
                 */
                WARN_ON_ONCE(pmd_pfn(old_pmd) != pmd_pfn(*new_pmd));
                pmd_clear(pmd);
-               kvm_tlb_flush_vmid_ipa(kvm, addr);
+               kvm_tlb_flush_vmid_ipa(mmu, addr, S2_PMD_LEVEL);
        } else {
                get_page(virt_to_page(pmd));
        }
        return 0;
  }
  
- static int stage2_set_pud_huge(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+ static int stage2_set_pud_huge(struct kvm_s2_mmu *mmu,
+                              struct kvm_mmu_memory_cache *cache,
                               phys_addr_t addr, const pud_t *new_pudp)
  {
+       struct kvm *kvm = mmu->kvm;
        pud_t *pudp, old_pud;
  
  retry:
-       pudp = stage2_get_pud(kvm, cache, addr);
+       pudp = stage2_get_pud(mmu, cache, addr);
        VM_BUG_ON(!pudp);
  
        old_pud = *pudp;
                 * the range for this block and retry.
                 */
                if (!stage2_pud_huge(kvm, old_pud)) {
-                       unmap_stage2_range(kvm, addr & S2_PUD_MASK, S2_PUD_SIZE);
+                       unmap_stage2_range(mmu, addr & S2_PUD_MASK, S2_PUD_SIZE);
                        goto retry;
                }
  
                WARN_ON_ONCE(kvm_pud_pfn(old_pud) != kvm_pud_pfn(*new_pudp));
                stage2_pud_clear(kvm, pudp);
-               kvm_tlb_flush_vmid_ipa(kvm, addr);
+               kvm_tlb_flush_vmid_ipa(mmu, addr, S2_PUD_LEVEL);
        } else {
                get_page(virt_to_page(pudp));
        }
   * leaf-entry is returned in the appropriate level variable - pudpp,
   * pmdpp, ptepp.
   */
- static bool stage2_get_leaf_entry(struct kvm *kvm, phys_addr_t addr,
+ static bool stage2_get_leaf_entry(struct kvm_s2_mmu *mmu, phys_addr_t addr,
                                  pud_t **pudpp, pmd_t **pmdpp, pte_t **ptepp)
  {
+       struct kvm *kvm = mmu->kvm;
        pud_t *pudp;
        pmd_t *pmdp;
        pte_t *ptep;
        *pmdpp = NULL;
        *ptepp = NULL;
  
-       pudp = stage2_get_pud(kvm, NULL, addr);
+       pudp = stage2_get_pud(mmu, NULL, addr);
        if (!pudp || stage2_pud_none(kvm, *pudp) || !stage2_pud_present(kvm, *pudp))
                return false;
  
        return true;
  }
  
- static bool stage2_is_exec(struct kvm *kvm, phys_addr_t addr, unsigned long sz)
 -static bool stage2_is_exec(struct kvm_s2_mmu *mmu, phys_addr_t addr)
++static bool stage2_is_exec(struct kvm_s2_mmu *mmu, phys_addr_t addr, unsigned long sz)
  {
        pud_t *pudp;
        pmd_t *pmdp;
        pte_t *ptep;
        bool found;
  
-       found = stage2_get_leaf_entry(kvm, addr, &pudp, &pmdp, &ptep);
+       found = stage2_get_leaf_entry(mmu, addr, &pudp, &pmdp, &ptep);
        if (!found)
                return false;
  
        if (pudp)
 -              return kvm_s2pud_exec(pudp);
 +              return sz <= PUD_SIZE && kvm_s2pud_exec(pudp);
        else if (pmdp)
 -              return kvm_s2pmd_exec(pmdp);
 +              return sz <= PMD_SIZE && kvm_s2pmd_exec(pmdp);
        else
 -              return kvm_s2pte_exec(ptep);
 +              return sz == PAGE_SIZE && kvm_s2pte_exec(ptep);
  }
  
- static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+ static int stage2_set_pte(struct kvm_s2_mmu *mmu,
+                         struct kvm_mmu_memory_cache *cache,
                          phys_addr_t addr, const pte_t *new_pte,
                          unsigned long flags)
  {
+       struct kvm *kvm = mmu->kvm;
        pud_t *pud;
        pmd_t *pmd;
        pte_t *pte, old_pte;
        VM_BUG_ON(logging_active && !cache);
  
        /* Create stage-2 page table mapping - Levels 0 and 1 */
-       pud = stage2_get_pud(kvm, cache, addr);
+       pud = stage2_get_pud(mmu, cache, addr);
        if (!pud) {
                /*
                 * Ignore calls from kvm_set_spte_hva for unallocated
         * on to allocate page.
         */
        if (logging_active)
-               stage2_dissolve_pud(kvm, addr, pud);
+               stage2_dissolve_pud(mmu, addr, pud);
  
        if (stage2_pud_none(kvm, *pud)) {
                if (!cache)
                        return 0; /* ignore calls from kvm_set_spte_hva */
 -              pmd = mmu_memory_cache_alloc(cache);
 +              pmd = kvm_mmu_memory_cache_alloc(cache);
                stage2_pud_populate(kvm, pud, pmd);
                get_page(virt_to_page(pud));
        }
         * allocate page.
         */
        if (logging_active)
-               stage2_dissolve_pmd(kvm, addr, pmd);
+               stage2_dissolve_pmd(mmu, addr, pmd);
  
        /* Create stage-2 page mappings - Level 2 */
        if (pmd_none(*pmd)) {
                if (!cache)
                        return 0; /* ignore calls from kvm_set_spte_hva */
 -              pte = mmu_memory_cache_alloc(cache);
 +              pte = kvm_mmu_memory_cache_alloc(cache);
                kvm_pmd_populate(pmd, pte);
                get_page(virt_to_page(pmd));
        }
                        return 0;
  
                kvm_set_pte(pte, __pte(0));
-               kvm_tlb_flush_vmid_ipa(kvm, addr);
+               kvm_tlb_flush_vmid_ipa(mmu, addr, S2_PTE_LEVEL);
        } else {
                get_page(virt_to_page(pte));
        }
@@@ -1437,7 -1501,7 +1469,7 @@@ int kvm_phys_addr_ioremap(struct kvm *k
        phys_addr_t addr, end;
        int ret = 0;
        unsigned long pfn;
 -      struct kvm_mmu_memory_cache cache = { 0, };
 +      struct kvm_mmu_memory_cache cache = { 0, __GFP_ZERO, NULL, };
  
        end = (guest_ipa + size + PAGE_SIZE - 1) & PAGE_MASK;
        pfn = __phys_to_pfn(pa);
                if (writable)
                        pte = kvm_s2pte_mkwrite(pte);
  
 -              ret = mmu_topup_memory_cache(&cache,
 -                                           kvm_mmu_cache_min_pages(kvm),
 -                                           KVM_NR_MEM_OBJS);
 +              ret = kvm_mmu_topup_memory_cache(&cache,
 +                                               kvm_mmu_cache_min_pages(kvm));
                if (ret)
                        goto out;
                spin_lock(&kvm->mmu_lock);
-               ret = stage2_set_pte(kvm, &cache, addr, &pte,
-                                               KVM_S2PTE_FLAG_IS_IOMAP);
+               ret = stage2_set_pte(&kvm->arch.mmu, &cache, addr, &pte,
+                                    KVM_S2PTE_FLAG_IS_IOMAP);
                spin_unlock(&kvm->mmu_lock);
                if (ret)
                        goto out;
        }
  
  out:
 -      mmu_free_memory_cache(&cache);
 +      kvm_mmu_free_memory_cache(&cache);
        return ret;
  }
  
@@@ -1493,9 -1558,10 +1525,10 @@@ static void stage2_wp_ptes(pmd_t *pmd, 
   * @addr:     range start address
   * @end:      range end address
   */
- static void stage2_wp_pmds(struct kvm *kvm, pud_t *pud,
+ static void stage2_wp_pmds(struct kvm_s2_mmu *mmu, pud_t *pud,
                           phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        pmd_t *pmd;
        phys_addr_t next;
  
  
  /**
   * stage2_wp_puds - write protect P4D range
-  * @pgd:      pointer to pgd entry
+  * @p4d:      pointer to p4d entry
   * @addr:     range start address
   * @end:      range end address
   */
- static void  stage2_wp_puds(struct kvm *kvm, p4d_t *p4d,
+ static void  stage2_wp_puds(struct kvm_s2_mmu *mmu, p4d_t *p4d,
                            phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        pud_t *pud;
        phys_addr_t next;
  
                                if (!kvm_s2pud_readonly(pud))
                                        kvm_set_s2pud_readonly(pud);
                        } else {
-                               stage2_wp_pmds(kvm, pud, addr, next);
+                               stage2_wp_pmds(mmu, pud, addr, next);
                        }
                }
        } while (pud++, addr = next, addr != end);
   * @addr:     range start address
   * @end:      range end address
   */
- static void  stage2_wp_p4ds(struct kvm *kvm, pgd_t *pgd,
+ static void  stage2_wp_p4ds(struct kvm_s2_mmu *mmu, pgd_t *pgd,
                            phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        p4d_t *p4d;
        phys_addr_t next;
  
        do {
                next = stage2_p4d_addr_end(kvm, addr, end);
                if (!stage2_p4d_none(kvm, *p4d))
-                       stage2_wp_puds(kvm, p4d, addr, next);
+                       stage2_wp_puds(mmu, p4d, addr, next);
        } while (p4d++, addr = next, addr != end);
  }
  
   * @addr:     Start address of range
   * @end:      End address of range
   */
- static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
+ static void stage2_wp_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, phys_addr_t end)
  {
+       struct kvm *kvm = mmu->kvm;
        pgd_t *pgd;
        phys_addr_t next;
  
-       pgd = kvm->arch.pgd + stage2_pgd_index(kvm, addr);
+       pgd = mmu->pgd + stage2_pgd_index(kvm, addr);
        do {
                /*
                 * Release kvm_mmu_lock periodically if the memory region is
                 * the lock.
                 */
                cond_resched_lock(&kvm->mmu_lock);
-               if (!READ_ONCE(kvm->arch.pgd))
+               if (!READ_ONCE(mmu->pgd))
                        break;
                next = stage2_pgd_addr_end(kvm, addr, end);
                if (stage2_pgd_present(kvm, *pgd))
-                       stage2_wp_p4ds(kvm, pgd, addr, next);
+                       stage2_wp_p4ds(mmu, pgd, addr, next);
        } while (pgd++, addr = next, addr != end);
  }
  
@@@ -1617,7 -1686,7 +1653,7 @@@ void kvm_mmu_wp_memory_region(struct kv
        end = (memslot->base_gfn + memslot->npages) << PAGE_SHIFT;
  
        spin_lock(&kvm->mmu_lock);
-       stage2_wp_range(kvm, start, end);
+       stage2_wp_range(&kvm->arch.mmu, start, end);
        spin_unlock(&kvm->mmu_lock);
        kvm_flush_remote_tlbs(kvm);
  }
@@@ -1641,7 -1710,7 +1677,7 @@@ static void kvm_mmu_write_protect_pt_ma
        phys_addr_t start = (base_gfn +  __ffs(mask)) << PAGE_SHIFT;
        phys_addr_t end = (base_gfn + __fls(mask) + 1) << PAGE_SHIFT;
  
-       stage2_wp_range(kvm, start, end);
+       stage2_wp_range(&kvm->arch.mmu, start, end);
  }
  
  /*
@@@ -1804,6 -1873,7 +1840,7 @@@ static int user_mem_abort(struct kvm_vc
        pgprot_t mem_type = PAGE_S2;
        bool logging_active = memslot_is_logging(memslot);
        unsigned long vma_pagesize, flags = 0;
+       struct kvm_s2_mmu *mmu = vcpu->arch.hw_mmu;
  
        write_fault = kvm_is_write_fault(vcpu);
        exec_fault = kvm_vcpu_trap_is_iabt(vcpu);
        mmap_read_unlock(current->mm);
  
        /* We need minimum second+third level pages */
 -      ret = mmu_topup_memory_cache(memcache, kvm_mmu_cache_min_pages(kvm),
 -                                   KVM_NR_MEM_OBJS);
 +      ret = kvm_mmu_topup_memory_cache(memcache, kvm_mmu_cache_min_pages(kvm));
        if (ret)
                return ret;
  
         * execute permissions, and we preserve whatever we have.
         */
        needs_exec = exec_fault ||
 -              (fault_status == FSC_PERM && stage2_is_exec(mmu, fault_ipa));
 +              (fault_status == FSC_PERM &&
-                stage2_is_exec(kvm, fault_ipa, vma_pagesize));
++               stage2_is_exec(mmu, fault_ipa, vma_pagesize));
  
        if (vma_pagesize == PUD_SIZE) {
                pud_t new_pud = kvm_pfn_pud(pfn, mem_type);
                if (needs_exec)
                        new_pud = kvm_s2pud_mkexec(new_pud);
  
-               ret = stage2_set_pud_huge(kvm, memcache, fault_ipa, &new_pud);
+               ret = stage2_set_pud_huge(mmu, memcache, fault_ipa, &new_pud);
        } else if (vma_pagesize == PMD_SIZE) {
                pmd_t new_pmd = kvm_pfn_pmd(pfn, mem_type);
  
                if (needs_exec)
                        new_pmd = kvm_s2pmd_mkexec(new_pmd);
  
-               ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
+               ret = stage2_set_pmd_huge(mmu, memcache, fault_ipa, &new_pmd);
        } else {
                pte_t new_pte = kvm_pfn_pte(pfn, mem_type);
  
                if (needs_exec)
                        new_pte = kvm_s2pte_mkexec(new_pte);
  
-               ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, flags);
+               ret = stage2_set_pte(mmu, memcache, fault_ipa, &new_pte, flags);
        }
  
  out_unlock:
@@@ -1990,7 -2060,7 +2027,7 @@@ static void handle_access_fault(struct 
  
        spin_lock(&vcpu->kvm->mmu_lock);
  
-       if (!stage2_get_leaf_entry(vcpu->kvm, fault_ipa, &pud, &pmd, &pte))
+       if (!stage2_get_leaf_entry(vcpu->arch.hw_mmu, fault_ipa, &pud, &pmd, &pte))
                goto out;
  
        if (pud) {              /* HugeTLB */
@@@ -2016,6 -2086,7 +2053,6 @@@ out
  /**
   * kvm_handle_guest_abort - handles all 2nd stage aborts
   * @vcpu:     the VCPU pointer
 - * @run:      the kvm_run structure
   *
   * Any abort that gets to the host is almost guaranteed to be caused by a
   * missing second stage translation table entry, which can mean that either the
   * space. The distinction is based on the IPA causing the fault and whether this
   * memory region has been registered as standard RAM by user space.
   */
 -int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
  {
        unsigned long fault_status;
        phys_addr_t fault_ipa;
        is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
  
        /* Synchronous External Abort? */
-       if (kvm_vcpu_dabt_isextabt(vcpu)) {
+       if (kvm_vcpu_abt_issea(vcpu)) {
                /*
                 * For RAS the host kernel may handle this abort.
                 * There is no need to pass the error into the guest.
                 */
-               if (!kvm_handle_guest_sea(fault_ipa, kvm_vcpu_get_hsr(vcpu)))
-                       return 1;
-               if (unlikely(!is_iabt)) {
+               if (kvm_handle_guest_sea(fault_ipa, kvm_vcpu_get_esr(vcpu)))
                        kvm_inject_vabt(vcpu);
-                       return 1;
-               }
+               return 1;
        }
  
-       trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu),
+       trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_esr(vcpu),
                              kvm_vcpu_get_hfar(vcpu), fault_ipa);
  
        /* Check the stage-2 fault is trans. fault or write fault */
                kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
                        kvm_vcpu_trap_get_class(vcpu),
                        (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
-                       (unsigned long)kvm_vcpu_get_hsr(vcpu));
+                       (unsigned long)kvm_vcpu_get_esr(vcpu));
                return -EFAULT;
        }
  
        hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
        write_fault = kvm_is_write_fault(vcpu);
        if (kvm_is_error_hva(hva) || (write_fault && !writable)) {
+               /*
+                * The guest has put either its instructions or its page-tables
+                * somewhere it shouldn't have. Userspace won't be able to do
+                * anything about this (there's no syndrome for a start), so
+                * re-inject the abort back into the guest.
+                */
                if (is_iabt) {
-                       /* Prefetch Abort on I/O address */
                        ret = -ENOEXEC;
                        goto out;
                }
  
+               if (kvm_vcpu_dabt_iss1tw(vcpu)) {
+                       kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
+                       ret = 1;
+                       goto out_unlock;
+               }
                /*
                 * Check for a cache maintenance operation. Since we
                 * ended-up here, we know it is outside of any memory
                 * So let's assume that the guest is just being
                 * cautious, and skip the instruction.
                 */
-               if (kvm_vcpu_dabt_is_cm(vcpu)) {
+               if (kvm_is_error_hva(hva) && kvm_vcpu_dabt_is_cm(vcpu)) {
                        kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
                        ret = 1;
                        goto out_unlock;
                 * of the page size.
                 */
                fault_ipa |= kvm_vcpu_get_hfar(vcpu) & ((1 << 12) - 1);
 -              ret = io_mem_abort(vcpu, run, fault_ipa);
 +              ret = io_mem_abort(vcpu, fault_ipa);
                goto out_unlock;
        }
  
@@@ -2163,14 -2242,14 +2208,14 @@@ static int handle_hva_to_gpa(struct kv
  
  static int kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data)
  {
-       unmap_stage2_range(kvm, gpa, size);
+       unmap_stage2_range(&kvm->arch.mmu, gpa, size);
        return 0;
  }
  
  int kvm_unmap_hva_range(struct kvm *kvm,
                        unsigned long start, unsigned long end)
  {
-       if (!kvm->arch.pgd)
+       if (!kvm->arch.mmu.pgd)
                return 0;
  
        trace_kvm_unmap_hva_range(start, end);
@@@ -2190,7 -2269,7 +2235,7 @@@ static int kvm_set_spte_handler(struct 
         * therefore stage2_set_pte() never needs to clear out a huge PMD
         * through this calling path.
         */
-       stage2_set_pte(kvm, NULL, gpa, pte, 0);
+       stage2_set_pte(&kvm->arch.mmu, NULL, gpa, pte, 0);
        return 0;
  }
  
@@@ -2201,7 -2280,7 +2246,7 @@@ int kvm_set_spte_hva(struct kvm *kvm, u
        kvm_pfn_t pfn = pte_pfn(pte);
        pte_t stage2_pte;
  
-       if (!kvm->arch.pgd)
+       if (!kvm->arch.mmu.pgd)
                return 0;
  
        trace_kvm_set_spte_hva(hva);
@@@ -2224,7 -2303,7 +2269,7 @@@ static int kvm_age_hva_handler(struct k
        pte_t *pte;
  
        WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PUD_SIZE);
-       if (!stage2_get_leaf_entry(kvm, gpa, &pud, &pmd, &pte))
+       if (!stage2_get_leaf_entry(&kvm->arch.mmu, gpa, &pud, &pmd, &pte))
                return 0;
  
        if (pud)
@@@ -2242,7 -2321,7 +2287,7 @@@ static int kvm_test_age_hva_handler(str
        pte_t *pte;
  
        WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PUD_SIZE);
-       if (!stage2_get_leaf_entry(kvm, gpa, &pud, &pmd, &pte))
+       if (!stage2_get_leaf_entry(&kvm->arch.mmu, gpa, &pud, &pmd, &pte))
                return 0;
  
        if (pud)
  
  int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)
  {
-       if (!kvm->arch.pgd)
+       if (!kvm->arch.mmu.pgd)
                return 0;
        trace_kvm_age_hva(start, end);
        return handle_hva_to_gpa(kvm, start, end, kvm_age_hva_handler, NULL);
  
  int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
  {
-       if (!kvm->arch.pgd)
+       if (!kvm->arch.mmu.pgd)
                return 0;
        trace_kvm_test_age_hva(hva);
        return handle_hva_to_gpa(kvm, hva, hva + PAGE_SIZE,
  
  void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu)
  {
 -      mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
 +      kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
  }
  
  phys_addr_t kvm_mmu_get_httbr(void)
@@@ -2476,7 -2555,7 +2521,7 @@@ int kvm_arch_prepare_memory_region(stru
  
        spin_lock(&kvm->mmu_lock);
        if (ret)
-               unmap_stage2_range(kvm, mem->guest_phys_addr, mem->memory_size);
+               unmap_stage2_range(&kvm->arch.mmu, mem->guest_phys_addr, mem->memory_size);
        else
                stage2_flush_memslot(kvm, memslot);
        spin_unlock(&kvm->mmu_lock);
@@@ -2495,7 -2574,7 +2540,7 @@@ void kvm_arch_memslots_updated(struct k
  
  void kvm_arch_flush_shadow_all(struct kvm *kvm)
  {
-       kvm_free_stage2_pgd(kvm);
+       kvm_free_stage2_pgd(&kvm->arch.mmu);
  }
  
  void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
        phys_addr_t size = slot->npages << PAGE_SHIFT;
  
        spin_lock(&kvm->mmu_lock);
-       unmap_stage2_range(kvm, gpa, size);
+       unmap_stage2_range(&kvm->arch.mmu, gpa, size);
        spin_unlock(&kvm->mmu_lock);
  }
  
diff --combined arch/arm64/kvm/reset.c
index 6ed36be51b4b2d432889b4f22e3098484cdcc8a5,92c3bba048ffe430bc1773feaf6f7e527e5f551f..ee33875c5c2af9e02014552f894662ea086197f0
@@@ -42,6 -42,11 +42,11 @@@ static u32 kvm_ipa_limit
  #define VCPU_RESET_PSTATE_SVC (PSR_AA32_MODE_SVC | PSR_AA32_A_BIT | \
                                 PSR_AA32_I_BIT | PSR_AA32_F_BIT)
  
+ static bool system_has_full_ptr_auth(void)
+ {
+       return system_supports_address_auth() && system_supports_generic_auth();
+ }
  /**
   * kvm_arch_vm_ioctl_check_extension
   *
@@@ -80,8 -85,7 +85,7 @@@ int kvm_arch_vm_ioctl_check_extension(s
                break;
        case KVM_CAP_ARM_PTRAUTH_ADDRESS:
        case KVM_CAP_ARM_PTRAUTH_GENERIC:
-               r = has_vhe() && system_supports_address_auth() &&
-                                system_supports_generic_auth();
+               r = system_has_full_ptr_auth();
                break;
        default:
                r = 0;
@@@ -205,19 -209,14 +209,14 @@@ static void kvm_vcpu_reset_sve(struct k
  
  static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
  {
-       /* Support ptrauth only if the system supports these capabilities. */
-       if (!has_vhe())
-               return -EINVAL;
-       if (!system_supports_address_auth() ||
-           !system_supports_generic_auth())
-               return -EINVAL;
        /*
         * For now make sure that both address/generic pointer authentication
-        * features are requested by the userspace together.
+        * features are requested by the userspace together and the system
+        * supports these capabilities.
         */
        if (!test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
-           !test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features))
+           !test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features) ||
+           !system_has_full_ptr_auth())
                return -EINVAL;
  
        vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_PTRAUTH;
   */
  int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
  {
 -      int ret = -EINVAL;
 +      int ret;
        bool loaded;
        u32 pstate;
  
  
        if (test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
            test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features)) {
 -              if (kvm_vcpu_enable_ptrauth(vcpu))
 +              if (kvm_vcpu_enable_ptrauth(vcpu)) {
 +                      ret = -EINVAL;
                        goto out;
 +              }
        }
  
        switch (vcpu->arch.target) {
        default:
                if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
 -                      if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1))
 +                      if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1)) {
 +                              ret = -EINVAL;
                                goto out;
 +                      }
                        pstate = VCPU_RESET_PSTATE_SVC;
                } else {
                        pstate = VCPU_RESET_PSTATE_EL1;
  
        /* Reset core registers */
        memset(vcpu_gp_regs(vcpu), 0, sizeof(*vcpu_gp_regs(vcpu)));
-       vcpu_gp_regs(vcpu)->regs.pstate = pstate;
+       vcpu_gp_regs(vcpu)->pstate = pstate;
  
        /* Reset system registers */
        kvm_reset_sys_regs(vcpu);
index 138961d7ebe391e2f22453ad2520cfe82fd42b52,1fbab5f066bf534235e2b4722723978ef27c8bdd..077293b5115fa06e6005d9cad8faafc8915a73f0
@@@ -94,6 -94,7 +94,7 @@@ static bool __vcpu_read_sys_reg_from_cp
        case TPIDR_EL1:         *val = read_sysreg_s(SYS_TPIDR_EL1);    break;
        case AMAIR_EL1:         *val = read_sysreg_s(SYS_AMAIR_EL12);   break;
        case CNTKCTL_EL1:       *val = read_sysreg_s(SYS_CNTKCTL_EL12); break;
+       case ELR_EL1:           *val = read_sysreg_s(SYS_ELR_EL12);     break;
        case PAR_EL1:           *val = read_sysreg_s(SYS_PAR_EL1);      break;
        case DACR32_EL2:        *val = read_sysreg_s(SYS_DACR32_EL2);   break;
        case IFSR32_EL2:        *val = read_sysreg_s(SYS_IFSR32_EL2);   break;
@@@ -133,6 -134,7 +134,7 @@@ static bool __vcpu_write_sys_reg_to_cpu
        case TPIDR_EL1:         write_sysreg_s(val, SYS_TPIDR_EL1);     break;
        case AMAIR_EL1:         write_sysreg_s(val, SYS_AMAIR_EL12);    break;
        case CNTKCTL_EL1:       write_sysreg_s(val, SYS_CNTKCTL_EL12);  break;
+       case ELR_EL1:           write_sysreg_s(val, SYS_ELR_EL12);      break;
        case PAR_EL1:           write_sysreg_s(val, SYS_PAR_EL1);       break;
        case DACR32_EL2:        write_sysreg_s(val, SYS_DACR32_EL2);    break;
        case IFSR32_EL2:        write_sysreg_s(val, SYS_IFSR32_EL2);    break;
@@@ -242,6 -244,25 +244,25 @@@ static bool access_vm_reg(struct kvm_vc
        return true;
  }
  
+ static bool access_actlr(struct kvm_vcpu *vcpu,
+                        struct sys_reg_params *p,
+                        const struct sys_reg_desc *r)
+ {
+       if (p->is_write)
+               return ignore_write(vcpu, p);
+       p->regval = vcpu_read_sys_reg(vcpu, ACTLR_EL1);
+       if (p->is_aarch32) {
+               if (r->Op2 & 2)
+                       p->regval = upper_32_bits(p->regval);
+               else
+                       p->regval = lower_32_bits(p->regval);
+       }
+       return true;
+ }
  /*
   * Trap handler for the GICv3 SGI generation system register.
   * Forward the request to the VGIC emulation.
@@@ -615,6 -636,12 +636,12 @@@ static void reset_amair_el1(struct kvm_
        vcpu_write_sys_reg(vcpu, amair, AMAIR_EL1);
  }
  
+ static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+ {
+       u64 actlr = read_sysreg(actlr_el1);
+       vcpu_write_sys_reg(vcpu, actlr, ACTLR_EL1);
+ }
  static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
  {
        u64 mpidr;
@@@ -1024,9 -1051,9 +1051,9 @@@ static bool access_amu(struct kvm_vcpu 
  
  /* Macro to expand the AMU counter and type registers*/
  #define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), access_amu }
 -#define AMU_AMEVTYPE0_EL0(n) { SYS_DESC(SYS_AMEVTYPE0_EL0(n)), access_amu }
 +#define AMU_AMEVTYPER0_EL0(n) { SYS_DESC(SYS_AMEVTYPER0_EL0(n)), access_amu }
  #define AMU_AMEVCNTR1_EL0(n) { SYS_DESC(SYS_AMEVCNTR1_EL0(n)), access_amu }
 -#define AMU_AMEVTYPE1_EL0(n) { SYS_DESC(SYS_AMEVTYPE1_EL0(n)), access_amu }
 +#define AMU_AMEVTYPER1_EL0(n) { SYS_DESC(SYS_AMEVTYPER1_EL0(n)), access_amu }
  
  static bool trap_ptrauth(struct kvm_vcpu *vcpu,
                         struct sys_reg_params *p,
@@@ -1518,6 -1545,7 +1545,7 @@@ static const struct sys_reg_desc sys_re
        ID_UNALLOCATED(7,7),
  
        { SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 },
+       { SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 },
        { SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
        { SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility },
        { SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
        AMU_AMEVCNTR0_EL0(13),
        AMU_AMEVCNTR0_EL0(14),
        AMU_AMEVCNTR0_EL0(15),
 -      AMU_AMEVTYPE0_EL0(0),
 -      AMU_AMEVTYPE0_EL0(1),
 -      AMU_AMEVTYPE0_EL0(2),
 -      AMU_AMEVTYPE0_EL0(3),
 -      AMU_AMEVTYPE0_EL0(4),
 -      AMU_AMEVTYPE0_EL0(5),
 -      AMU_AMEVTYPE0_EL0(6),
 -      AMU_AMEVTYPE0_EL0(7),
 -      AMU_AMEVTYPE0_EL0(8),
 -      AMU_AMEVTYPE0_EL0(9),
 -      AMU_AMEVTYPE0_EL0(10),
 -      AMU_AMEVTYPE0_EL0(11),
 -      AMU_AMEVTYPE0_EL0(12),
 -      AMU_AMEVTYPE0_EL0(13),
 -      AMU_AMEVTYPE0_EL0(14),
 -      AMU_AMEVTYPE0_EL0(15),
 +      AMU_AMEVTYPER0_EL0(0),
 +      AMU_AMEVTYPER0_EL0(1),
 +      AMU_AMEVTYPER0_EL0(2),
 +      AMU_AMEVTYPER0_EL0(3),
 +      AMU_AMEVTYPER0_EL0(4),
 +      AMU_AMEVTYPER0_EL0(5),
 +      AMU_AMEVTYPER0_EL0(6),
 +      AMU_AMEVTYPER0_EL0(7),
 +      AMU_AMEVTYPER0_EL0(8),
 +      AMU_AMEVTYPER0_EL0(9),
 +      AMU_AMEVTYPER0_EL0(10),
 +      AMU_AMEVTYPER0_EL0(11),
 +      AMU_AMEVTYPER0_EL0(12),
 +      AMU_AMEVTYPER0_EL0(13),
 +      AMU_AMEVTYPER0_EL0(14),
 +      AMU_AMEVTYPER0_EL0(15),
        AMU_AMEVCNTR1_EL0(0),
        AMU_AMEVCNTR1_EL0(1),
        AMU_AMEVCNTR1_EL0(2),
        AMU_AMEVCNTR1_EL0(13),
        AMU_AMEVCNTR1_EL0(14),
        AMU_AMEVCNTR1_EL0(15),
 -      AMU_AMEVTYPE1_EL0(0),
 -      AMU_AMEVTYPE1_EL0(1),
 -      AMU_AMEVTYPE1_EL0(2),
 -      AMU_AMEVTYPE1_EL0(3),
 -      AMU_AMEVTYPE1_EL0(4),
 -      AMU_AMEVTYPE1_EL0(5),
 -      AMU_AMEVTYPE1_EL0(6),
 -      AMU_AMEVTYPE1_EL0(7),
 -      AMU_AMEVTYPE1_EL0(8),
 -      AMU_AMEVTYPE1_EL0(9),
 -      AMU_AMEVTYPE1_EL0(10),
 -      AMU_AMEVTYPE1_EL0(11),
 -      AMU_AMEVTYPE1_EL0(12),
 -      AMU_AMEVTYPE1_EL0(13),
 -      AMU_AMEVTYPE1_EL0(14),
 -      AMU_AMEVTYPE1_EL0(15),
 +      AMU_AMEVTYPER1_EL0(0),
 +      AMU_AMEVTYPER1_EL0(1),
 +      AMU_AMEVTYPER1_EL0(2),
 +      AMU_AMEVTYPER1_EL0(3),
 +      AMU_AMEVTYPER1_EL0(4),
 +      AMU_AMEVTYPER1_EL0(5),
 +      AMU_AMEVTYPER1_EL0(6),
 +      AMU_AMEVTYPER1_EL0(7),
 +      AMU_AMEVTYPER1_EL0(8),
 +      AMU_AMEVTYPER1_EL0(9),
 +      AMU_AMEVTYPER1_EL0(10),
 +      AMU_AMEVTYPER1_EL0(11),
 +      AMU_AMEVTYPER1_EL0(12),
 +      AMU_AMEVTYPER1_EL0(13),
 +      AMU_AMEVTYPER1_EL0(14),
 +      AMU_AMEVTYPER1_EL0(15),
  
        { SYS_DESC(SYS_CNTP_TVAL_EL0), access_arch_timer },
        { SYS_DESC(SYS_CNTP_CTL_EL0), access_arch_timer },
@@@ -1957,6 -1985,8 +1985,8 @@@ static const struct sys_reg_desc cp14_6
  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( 1), CRm( 0), Op2( 1), access_actlr },
+       { Op1( 0), CRn( 1), CRm( 0), Op2( 3), access_actlr },
        { 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 },
        { Op1( 0), CRn( 2), CRm( 0), Op2( 2), access_vm_reg, NULL, c2_TTBCR },
@@@ -2109,36 -2139,6 +2139,6 @@@ static int check_sysreg_table(const str
        return 0;
  }
  
- /* Target specific emulation tables */
- static struct kvm_sys_reg_target_table *target_tables[KVM_ARM_NUM_TARGETS];
- void kvm_register_target_sys_reg_table(unsigned int target,
-                                      struct kvm_sys_reg_target_table *table)
- {
-       if (check_sysreg_table(table->table64.table, table->table64.num, false) ||
-           check_sysreg_table(table->table32.table, table->table32.num, true))
-               return;
-       target_tables[target] = table;
- }
- /* Get specific register table for this target. */
- static const struct sys_reg_desc *get_target_table(unsigned target,
-                                                  bool mode_is_64,
-                                                  size_t *num)
- {
-       struct kvm_sys_reg_target_table *table;
-       table = target_tables[target];
-       if (mode_is_64) {
-               *num = table->table64.num;
-               return table->table64.table;
-       } else {
-               *num = table->table32.num;
-               return table->table32.table;
-       }
- }
  static int match_sys_reg(const void *key, const void *elt)
  {
        const unsigned long pval = (unsigned long)key;
@@@ -2156,7 -2156,7 +2156,7 @@@ static const struct sys_reg_desc *find_
        return bsearch((void *)pval, table, num, sizeof(table[0]), match_sys_reg);
  }
  
 -int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu)
  {
        kvm_inject_undefined(vcpu);
        return 1;
@@@ -2220,10 -2220,10 +2220,10 @@@ static int emulate_cp(struct kvm_vcpu *
  static void unhandled_cp_access(struct kvm_vcpu *vcpu,
                                struct sys_reg_params *params)
  {
-       u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
+       u8 esr_ec = kvm_vcpu_trap_get_class(vcpu);
        int cp = -1;
  
-       switch(hsr_ec) {
+       switch (esr_ec) {
        case ESR_ELx_EC_CP15_32:
        case ESR_ELx_EC_CP15_64:
                cp = 15;
   */
  static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
                            const struct sys_reg_desc *global,
-                           size_t nr_global,
-                           const struct sys_reg_desc *target_specific,
-                           size_t nr_specific)
+                           size_t nr_global)
  {
        struct sys_reg_params params;
-       u32 hsr = kvm_vcpu_get_hsr(vcpu);
+       u32 esr = kvm_vcpu_get_esr(vcpu);
        int Rt = kvm_vcpu_sys_get_rt(vcpu);
-       int Rt2 = (hsr >> 10) & 0x1f;
+       int Rt2 = (esr >> 10) & 0x1f;
  
        params.is_aarch32 = true;
        params.is_32bit = false;
-       params.CRm = (hsr >> 1) & 0xf;
-       params.is_write = ((hsr & 1) == 0);
+       params.CRm = (esr >> 1) & 0xf;
+       params.is_write = ((esr & 1) == 0);
  
        params.Op0 = 0;
-       params.Op1 = (hsr >> 16) & 0xf;
+       params.Op1 = (esr >> 16) & 0xf;
        params.Op2 = 0;
        params.CRn = 0;
  
        }
  
        /*
-        * Try to emulate the coprocessor access using the target
-        * specific table first, and using the global table afterwards.
-        * If either of the tables contains a handler, handle the
+        * If the table contains a handler, handle the
         * potential register operation in the case of a read and return
         * with success.
         */
-       if (!emulate_cp(vcpu, &params, target_specific, nr_specific) ||
-           !emulate_cp(vcpu, &params, global, nr_global)) {
+       if (!emulate_cp(vcpu, &params, global, nr_global)) {
                /* Split up the value between registers for the read side */
                if (!params.is_write) {
                        vcpu_set_reg(vcpu, Rt, lower_32_bits(params.regval));
   */
  static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
                            const struct sys_reg_desc *global,
-                           size_t nr_global,
-                           const struct sys_reg_desc *target_specific,
-                           size_t nr_specific)
+                           size_t nr_global)
  {
        struct sys_reg_params params;
-       u32 hsr = kvm_vcpu_get_hsr(vcpu);
+       u32 esr = kvm_vcpu_get_esr(vcpu);
        int Rt  = kvm_vcpu_sys_get_rt(vcpu);
  
        params.is_aarch32 = true;
        params.is_32bit = true;
-       params.CRm = (hsr >> 1) & 0xf;
+       params.CRm = (esr >> 1) & 0xf;
        params.regval = vcpu_get_reg(vcpu, Rt);
-       params.is_write = ((hsr & 1) == 0);
-       params.CRn = (hsr >> 10) & 0xf;
+       params.is_write = ((esr & 1) == 0);
+       params.CRn = (esr >> 10) & 0xf;
        params.Op0 = 0;
-       params.Op1 = (hsr >> 14) & 0x7;
-       params.Op2 = (hsr >> 17) & 0x7;
+       params.Op1 = (esr >> 14) & 0x7;
+       params.Op2 = (esr >> 17) & 0x7;
  
-       if (!emulate_cp(vcpu, &params, target_specific, nr_specific) ||
-           !emulate_cp(vcpu, &params, global, nr_global)) {
+       if (!emulate_cp(vcpu, &params, global, nr_global)) {
                if (!params.is_write)
                        vcpu_set_reg(vcpu, Rt, params.regval);
                return 1;
        return 1;
  }
  
 -int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu)
  {
-       const struct sys_reg_desc *target_specific;
-       size_t num;
-       target_specific = get_target_table(vcpu->arch.target, false, &num);
-       return kvm_handle_cp_64(vcpu,
-                               cp15_64_regs, ARRAY_SIZE(cp15_64_regs),
-                               target_specific, num);
+       return kvm_handle_cp_64(vcpu, cp15_64_regs, ARRAY_SIZE(cp15_64_regs));
  }
  
 -int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu)
  {
-       const struct sys_reg_desc *target_specific;
-       size_t num;
-       target_specific = get_target_table(vcpu->arch.target, false, &num);
-       return kvm_handle_cp_32(vcpu,
-                               cp15_regs, ARRAY_SIZE(cp15_regs),
-                               target_specific, num);
+       return kvm_handle_cp_32(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
  }
  
 -int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu)
  {
-       return kvm_handle_cp_64(vcpu,
-                               cp14_64_regs, ARRAY_SIZE(cp14_64_regs),
-                               NULL, 0);
+       return kvm_handle_cp_64(vcpu, cp14_64_regs, ARRAY_SIZE(cp14_64_regs));
  }
  
 -int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu)
  {
-       return kvm_handle_cp_32(vcpu,
-                               cp14_regs, ARRAY_SIZE(cp14_regs),
-                               NULL, 0);
+       return kvm_handle_cp_32(vcpu, cp14_regs, ARRAY_SIZE(cp14_regs));
  }
  
  static bool is_imp_def_sys_reg(struct sys_reg_params *params)
  static int emulate_sys_reg(struct kvm_vcpu *vcpu,
                           struct sys_reg_params *params)
  {
-       size_t num;
-       const struct sys_reg_desc *table, *r;
+       const struct sys_reg_desc *r;
  
-       table = get_target_table(vcpu->arch.target, true, &num);
-       /* Search target-specific then generic table. */
-       r = find_reg(params, table, num);
-       if (!r)
-               r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
+       r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
  
        if (likely(r)) {
                perform_access(vcpu, params, r);
        return 1;
  }
  
- static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
-                               const struct sys_reg_desc *table, size_t num)
+ /**
+  * kvm_reset_sys_regs - sets system registers to reset value
+  * @vcpu: The VCPU pointer
+  *
+  * This function finds the right table above and sets the registers on the
+  * virtual CPU struct to their architecturally defined reset values.
+  */
+ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
  {
        unsigned long i;
  
-       for (i = 0; i < num; i++)
-               if (table[i].reset)
-                       table[i].reset(vcpu, &table[i]);
+       for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++)
+               if (sys_reg_descs[i].reset)
+                       sys_reg_descs[i].reset(vcpu, &sys_reg_descs[i]);
  }
  
  /**
   * kvm_handle_sys_reg -- handles a mrs/msr trap on a guest sys_reg access
   * @vcpu: The VCPU pointer
 - * @run:  The kvm_run struct
   */
 -int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
 +int kvm_handle_sys_reg(struct kvm_vcpu *vcpu)
  {
        struct sys_reg_params params;
-       unsigned long esr = kvm_vcpu_get_hsr(vcpu);
+       unsigned long esr = kvm_vcpu_get_esr(vcpu);
        int Rt = kvm_vcpu_sys_get_rt(vcpu);
        int ret;
  
@@@ -2491,8 -2468,7 +2467,7 @@@ const struct sys_reg_desc *find_reg_by_
  static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
                                                    u64 id)
  {
-       size_t num;
-       const struct sys_reg_desc *table, *r;
+       const struct sys_reg_desc *r;
        struct sys_reg_params params;
  
        /* We only do sys_reg for now. */
        if (!index_to_params(id, &params))
                return NULL;
  
-       table = get_target_table(vcpu->arch.target, true, &num);
-       r = find_reg(&params, table, num);
-       if (!r)
-               r = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
+       r = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
  
        /* Not saved in the sys_reg array and not otherwise accessible? */
        if (r && !(r->reg || r->get_user))
@@@ -2805,35 -2778,17 +2777,17 @@@ static int walk_one_sys_reg(const struc
  /* Assumed ordered tables, see kvm_sys_reg_table_init. */
  static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
  {
-       const struct sys_reg_desc *i1, *i2, *end1, *end2;
+       const struct sys_reg_desc *i2, *end2;
        unsigned int total = 0;
-       size_t num;
        int err;
  
-       /* We check for duplicates here, to allow arch-specific overrides. */
-       i1 = get_target_table(vcpu->arch.target, true, &num);
-       end1 = i1 + num;
        i2 = sys_reg_descs;
        end2 = sys_reg_descs + ARRAY_SIZE(sys_reg_descs);
  
-       BUG_ON(i1 == end1 || i2 == end2);
-       /* Walk carefully, as both tables may refer to the same register. */
-       while (i1 || i2) {
-               int cmp = cmp_sys_reg(i1, i2);
-               /* target-specific overrides generic entry. */
-               if (cmp <= 0)
-                       err = walk_one_sys_reg(vcpu, i1, &uind, &total);
-               else
-                       err = walk_one_sys_reg(vcpu, i2, &uind, &total);
+       while (i2 != end2) {
+               err = walk_one_sys_reg(vcpu, i2++, &uind, &total);
                if (err)
                        return err;
-               if (cmp <= 0 && ++i1 == end1)
-                       i1 = NULL;
-               if (cmp >= 0 && ++i2 == end2)
-                       i2 = NULL;
        }
        return total;
  }
@@@ -2900,22 -2855,3 +2854,3 @@@ void kvm_sys_reg_table_init(void
        /* Clear all higher bits. */
        cache_levels &= (1 << (i*3))-1;
  }
- /**
-  * kvm_reset_sys_regs - sets system registers to reset value
-  * @vcpu: The VCPU pointer
-  *
-  * This function finds the right table above and sets the registers on the
-  * virtual CPU struct to their architecturally defined reset values.
-  */
- void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
- {
-       size_t num;
-       const struct sys_reg_desc *table;
-       /* Generic chip reset first (so target could override). */
-       reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
-       table = get_target_table(vcpu->arch.target, true, &num);
-       reset_sys_reg_descs(vcpu, table, num);
- }
This page took 0.20938 seconds and 4 git commands to generate.