Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Nov 2015 22:47:13 +0000 (14:47 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Nov 2015 22:47:13 +0000 (14:47 -0800)
Pull arm64 updates from Catalin Marinas:

 - "genirq: Introduce generic irq migration for cpu hotunplugged" patch
   merged from tip/irq/for-arm to allow the arm64-specific part to be
   upstreamed via the arm64 tree

 - CPU feature detection reworked to cope with heterogeneous systems
   where CPUs may not have exactly the same features.  The features
   reported by the kernel via internal data structures or ELF_HWCAP are
   delayed until all the CPUs are up (and before user space starts)

 - Support for 16KB pages, with the additional bonus of a 36-bit VA
   space, though the latter only depending on EXPERT

 - Implement native {relaxed, acquire, release} atomics for arm64

 - New ASID allocation algorithm which avoids IPI on roll-over, together
   with TLB invalidation optimisations (using local vs global where
   feasible)

 - KASan support for arm64

 - EFI_STUB clean-up and isolation for the kernel proper (required by
   KASan)

 - copy_{to,from,in}_user optimisations (sharing the memcpy template)

 - perf: moving arm64 to the arm32/64 shared PMU framework

 - L1_CACHE_BYTES increased to 128 to accommodate Cavium hardware

 - Support for the contiguous PTE hint on kernel mapping (16 consecutive
   entries may be able to use a single TLB entry)

 - Generic CONFIG_HZ now used on arm64

 - defconfig updates

* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (91 commits)
  arm64/efi: fix libstub build under CONFIG_MODVERSIONS
  ARM64: Enable multi-core scheduler support by default
  arm64/efi: move arm64 specific stub C code to libstub
  arm64: page-align sections for DEBUG_RODATA
  arm64: Fix build with CONFIG_ZONE_DMA=n
  arm64: Fix compat register mappings
  arm64: Increase the max granular size
  arm64: remove bogus TASK_SIZE_64 check
  arm64: make Timer Interrupt Frequency selectable
  arm64/mm: use PAGE_ALIGNED instead of IS_ALIGNED
  arm64: cachetype: fix definitions of ICACHEF_* flags
  arm64: cpufeature: declare enable_cpu_capabilities as static
  genirq: Make the cpuhotplug migration code less noisy
  arm64: Constify hwcap name string arrays
  arm64/kvm: Make use of the system wide safe values
  arm64/debug: Make use of the system wide safe value
  arm64: Move FP/ASIMD hwcap handling to common code
  arm64/HWCAP: Use system wide safe values
  arm64/capabilities: Make use of system wide safe value
  arm64: Delay cpu feature capability checks
  ...

22 files changed:
1  2 
Documentation/arm/uefi.txt
Documentation/arm64/booting.txt
MAINTAINERS
arch/arm64/Kconfig
arch/arm64/Makefile
arch/arm64/include/asm/atomic.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/efi.c
arch/arm64/kernel/head.S
arch/arm64/kernel/setup.c
arch/arm64/kernel/suspend.c
arch/arm64/kvm/Kconfig
arch/arm64/mm/fault.c
arch/arm64/mm/proc.S
drivers/firmware/efi/Makefile
drivers/firmware/efi/libstub/arm64-stub.c

index 7b3fdfe0f7ba37a7ff6a0e46cfec18e1fcfbe68e,7f1bed8872f3d73361f143d8131ff5d29fedb848..6543a0adea8a9741798570108719c5e968c25088
@@@ -58,5 -58,5 +58,3 @@@ linux,uefi-mmap-desc-size | 32-bit | Si
  --------------------------------------------------------------------------------
  linux,uefi-mmap-desc-ver  | 32-bit | Version of the mmap descriptor format.
  --------------------------------------------------------------------------------
- linux,uefi-stub-kern-ver  | string | Copy of linux_banner from build.
- --------------------------------------------------------------------------------
 -
 -For verbose debug messages, specify 'uefi_debug' on the kernel command line.
Simple merge
diff --cc MAINTAINERS
Simple merge
Simple merge
Simple merge
index 1e247ac2601af41012823f0a639e2f9393af6d0b,5e13ad76a2493ad1458943338cade910e77d979d..f3a3586a421c8869d6e88219c686491d71e2ecd5
  #define ATOMIC_INIT(i)        { (i) }
  
  #define atomic_read(v)                        READ_ONCE((v)->counter)
 -#define atomic_set(v, i)              (((v)->counter) = (i))
 +#define atomic_set(v, i)              WRITE_ONCE(((v)->counter), (i))
+ #define atomic_add_return_relaxed     atomic_add_return_relaxed
+ #define atomic_add_return_acquire     atomic_add_return_acquire
+ #define atomic_add_return_release     atomic_add_return_release
+ #define atomic_add_return             atomic_add_return
+ #define atomic_inc_return_relaxed(v)  atomic_add_return_relaxed(1, (v))
+ #define atomic_inc_return_acquire(v)  atomic_add_return_acquire(1, (v))
+ #define atomic_inc_return_release(v)  atomic_add_return_release(1, (v))
+ #define atomic_inc_return(v)          atomic_add_return(1, (v))
+ #define atomic_sub_return_relaxed     atomic_sub_return_relaxed
+ #define atomic_sub_return_acquire     atomic_sub_return_acquire
+ #define atomic_sub_return_release     atomic_sub_return_release
+ #define atomic_sub_return             atomic_sub_return
+ #define atomic_dec_return_relaxed(v)  atomic_sub_return_relaxed(1, (v))
+ #define atomic_dec_return_acquire(v)  atomic_sub_return_acquire(1, (v))
+ #define atomic_dec_return_release(v)  atomic_sub_return_release(1, (v))
+ #define atomic_dec_return(v)          atomic_sub_return(1, (v))
+ #define atomic_xchg_relaxed(v, new)   xchg_relaxed(&((v)->counter), (new))
+ #define atomic_xchg_acquire(v, new)   xchg_acquire(&((v)->counter), (new))
+ #define atomic_xchg_release(v, new)   xchg_release(&((v)->counter), (new))
  #define atomic_xchg(v, new)           xchg(&((v)->counter), (new))
+ #define atomic_cmpxchg_relaxed(v, old, new)                           \
+       cmpxchg_relaxed(&((v)->counter), (old), (new))
+ #define atomic_cmpxchg_acquire(v, old, new)                           \
+       cmpxchg_acquire(&((v)->counter), (old), (new))
+ #define atomic_cmpxchg_release(v, old, new)                           \
+       cmpxchg_release(&((v)->counter), (old), (new))
  #define atomic_cmpxchg(v, old, new)   cmpxchg(&((v)->counter), (old), (new))
  
  #define atomic_inc(v)                 atomic_add(1, (v))
Simple merge
index 100a3d1b17c854d6c1a2c465b56ad8f101ab5efa,31678b2f295f242fc03d461dd92f52de0388d9c9..1a5949364ed0f43eee2be4b61c3497fe4fdbbb7b
        (0xf                    << MIDR_ARCHITECTURE_SHIFT) | \
        ((partnum)              << MIDR_PARTNUM_SHIFT))
  
 -#define ARM_CPU_IMP_ARM               0x41
 -#define ARM_CPU_IMP_APM               0x50
 +#define ARM_CPU_IMP_ARM                       0x41
 +#define ARM_CPU_IMP_APM                       0x50
 +#define ARM_CPU_IMP_CAVIUM            0x43
  
 -#define ARM_CPU_PART_AEM_V8   0xD0F
 -#define ARM_CPU_PART_FOUNDATION       0xD00
 -#define ARM_CPU_PART_CORTEX_A57       0xD07
 -#define ARM_CPU_PART_CORTEX_A53       0xD03
 +#define ARM_CPU_PART_AEM_V8           0xD0F
 +#define ARM_CPU_PART_FOUNDATION               0xD00
 +#define ARM_CPU_PART_CORTEX_A57               0xD07
 +#define ARM_CPU_PART_CORTEX_A53               0xD03
  
 -#define APM_CPU_PART_POTENZA  0x000
 +#define APM_CPU_PART_POTENZA          0x000
 +
 +#define CAVIUM_CPU_PART_THUNDERX      0x0A1
  
- #define ID_AA64MMFR0_BIGENDEL0_SHIFT  16
- #define ID_AA64MMFR0_BIGENDEL0_MASK   (0xf << ID_AA64MMFR0_BIGENDEL0_SHIFT)
- #define ID_AA64MMFR0_BIGENDEL0(mmfr0) \
-       (((mmfr0) & ID_AA64MMFR0_BIGENDEL0_MASK) >> ID_AA64MMFR0_BIGENDEL0_SHIFT)
- #define ID_AA64MMFR0_BIGEND_SHIFT     8
- #define ID_AA64MMFR0_BIGEND_MASK      (0xf << ID_AA64MMFR0_BIGEND_SHIFT)
- #define ID_AA64MMFR0_BIGEND(mmfr0)    \
-       (((mmfr0) & ID_AA64MMFR0_BIGEND_MASK) >> ID_AA64MMFR0_BIGEND_SHIFT)
  #ifndef __ASSEMBLY__
  
  /*
Simple merge
Simple merge
Simple merge
index 305f30dc9e633fe86947621e54d802744e59df52,504526fa81299eeb3a7c127e73a54c1a85a7383a..52f0d7a5a1c2e0ea0629d51da7204723bd531f66
  #include <linux/types.h>
  #include <asm/cpu.h>
  #include <asm/cpufeature.h>
+ #include <asm/cpu_ops.h>
  #include <asm/processor.h>
+ #include <asm/sysreg.h>
+ unsigned long elf_hwcap __read_mostly;
+ EXPORT_SYMBOL_GPL(elf_hwcap);
+ #ifdef CONFIG_COMPAT
+ #define COMPAT_ELF_HWCAP_DEFAULT      \
+                               (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
+                                COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
+                                COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
+                                COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
+                                COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\
+                                COMPAT_HWCAP_LPAE)
+ unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
+ unsigned int compat_elf_hwcap2 __read_mostly;
+ #endif
+ DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
+ #define ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
+       {                                               \
+               .strict = STRICT,                       \
+               .type = TYPE,                           \
+               .shift = SHIFT,                         \
+               .width = WIDTH,                         \
+               .safe_val = SAFE_VAL,                   \
+       }
+ #define ARM64_FTR_END                                 \
+       {                                               \
+               .width = 0,                             \
+       }
+ static struct arm64_ftr_bits ftr_id_aa64isar0[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 24, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_ATOMICS_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_CRC32_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA2_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA1_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_AES_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 4, 0), /* RAZ */
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
+       /* Linux doesn't care about the EL3 */
+       ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, ID_AA64PFR0_EL3_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL2_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
+       /* Linux shouldn't care about secure memory */
+       ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_BIGENDEL_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_ASID_SHIFT, 4, 0),
+       /*
+        * Differing PARange is fine as long as all peripherals and memory are mapped
+        * within the minimum PARange of all CPUs
+        */
+       ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_PARANGE_SHIFT, 4, 0),
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_PAN_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_LOR_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_HPD_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_VHE_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_VMIDBITS_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_HADBS_SHIFT, 4, 0),
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_ctr[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1),        /* RAO */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 3, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0),  /* CWG */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0),   /* ERG */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1),   /* DminLine */
+       /*
+        * Linux can handle differing I-cache policies. Userspace JITs will
+        * make use of *minLine
+        */
+       ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, 0),     /* L1Ip */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 10, 0),        /* RAZ */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0),    /* IminLine */
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_id_mmfr0[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 4, 0),        /* InnerShr */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 24, 4, 0),        /* FCSE */
+       ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, 20, 4, 0),        /* AuxReg */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 16, 4, 0),        /* TCM */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 12, 4, 0),        /* ShareLvl */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 8, 4, 0), /* OuterShr */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 4, 0), /* PMSA */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 4, 0), /* VMSA */
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6),
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_mvfr2[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 8, 24, 0),        /* RAZ */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 4, 0),         /* FPMisc */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 4, 0),         /* SIMDMisc */
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_dczid[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 5, 27, 0),        /* RAZ */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 1, 1),         /* DZP */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0),    /* BS */
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_id_isar5[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_ISAR5_RDM_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 20, 4, 0),        /* RAZ */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_ISAR5_CRC32_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_ISAR5_SHA2_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_ISAR5_SHA1_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_ISAR5_AES_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_ISAR5_SEVL_SHIFT, 4, 0),
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_id_mmfr4[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 8, 24, 0),        /* RAZ */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 4, 0),         /* ac2 */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 4, 0),         /* RAZ */
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_id_pfr0[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 16, 16, 0),       /* RAZ */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 12, 4, 0),        /* State3 */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 8, 4, 0),         /* State2 */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 4, 0),         /* State1 */
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 4, 0),         /* State0 */
+       ARM64_FTR_END,
+ };
+ /*
+  * Common ftr bits for a 32bit register with all hidden, strict
+  * attributes, with 4bit feature fields and a default safe value of
+  * 0. Covers the following 32bit registers:
+  * id_isar[0-4], id_mmfr[1-3], id_pfr1, mvfr[0-1]
+  */
+ static struct arm64_ftr_bits ftr_generic_32bits[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 24, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 12, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 8, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0),
+       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0),
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_generic[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 64, 0),
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_generic32[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 32, 0),
+       ARM64_FTR_END,
+ };
+ static struct arm64_ftr_bits ftr_aa64raz[] = {
+       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 64, 0),
+       ARM64_FTR_END,
+ };
+ #define ARM64_FTR_REG(id, table)              \
+       {                                       \
+               .sys_id = id,                   \
+               .name = #id,                    \
+               .ftr_bits = &((table)[0]),      \
+       }
+ static struct arm64_ftr_reg arm64_ftr_regs[] = {
+       /* Op1 = 0, CRn = 0, CRm = 1 */
+       ARM64_FTR_REG(SYS_ID_PFR0_EL1, ftr_id_pfr0),
+       ARM64_FTR_REG(SYS_ID_PFR1_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_DFR0_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_MMFR0_EL1, ftr_id_mmfr0),
+       ARM64_FTR_REG(SYS_ID_MMFR1_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_MMFR2_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_MMFR3_EL1, ftr_generic_32bits),
+       /* Op1 = 0, CRn = 0, CRm = 2 */
+       ARM64_FTR_REG(SYS_ID_ISAR0_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_ISAR1_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_ISAR2_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_ISAR3_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_ISAR4_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_ID_ISAR5_EL1, ftr_id_isar5),
+       ARM64_FTR_REG(SYS_ID_MMFR4_EL1, ftr_id_mmfr4),
+       /* Op1 = 0, CRn = 0, CRm = 3 */
+       ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_MVFR2_EL1, ftr_mvfr2),
+       /* Op1 = 0, CRn = 0, CRm = 4 */
+       ARM64_FTR_REG(SYS_ID_AA64PFR0_EL1, ftr_id_aa64pfr0),
+       ARM64_FTR_REG(SYS_ID_AA64PFR1_EL1, ftr_aa64raz),
+       /* Op1 = 0, CRn = 0, CRm = 5 */
+       ARM64_FTR_REG(SYS_ID_AA64DFR0_EL1, ftr_id_aa64dfr0),
+       ARM64_FTR_REG(SYS_ID_AA64DFR1_EL1, ftr_generic),
+       /* Op1 = 0, CRn = 0, CRm = 6 */
+       ARM64_FTR_REG(SYS_ID_AA64ISAR0_EL1, ftr_id_aa64isar0),
+       ARM64_FTR_REG(SYS_ID_AA64ISAR1_EL1, ftr_aa64raz),
+       /* Op1 = 0, CRn = 0, CRm = 7 */
+       ARM64_FTR_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0),
+       ARM64_FTR_REG(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1),
+       /* Op1 = 3, CRn = 0, CRm = 0 */
+       ARM64_FTR_REG(SYS_CTR_EL0, ftr_ctr),
+       ARM64_FTR_REG(SYS_DCZID_EL0, ftr_dczid),
+       /* Op1 = 3, CRn = 14, CRm = 0 */
+       ARM64_FTR_REG(SYS_CNTFRQ_EL0, ftr_generic32),
+ };
+ static int search_cmp_ftr_reg(const void *id, const void *regp)
+ {
+       return (int)(unsigned long)id - (int)((const struct arm64_ftr_reg *)regp)->sys_id;
+ }
+ /*
+  * get_arm64_ftr_reg - Lookup a feature register entry using its
+  * sys_reg() encoding. With the array arm64_ftr_regs sorted in the
+  * ascending order of sys_id , we use binary search to find a matching
+  * entry.
+  *
+  * returns - Upon success,  matching ftr_reg entry for id.
+  *         - NULL on failure. It is upto the caller to decide
+  *         the impact of a failure.
+  */
+ static struct arm64_ftr_reg *get_arm64_ftr_reg(u32 sys_id)
+ {
+       return bsearch((const void *)(unsigned long)sys_id,
+                       arm64_ftr_regs,
+                       ARRAY_SIZE(arm64_ftr_regs),
+                       sizeof(arm64_ftr_regs[0]),
+                       search_cmp_ftr_reg);
+ }
+ static u64 arm64_ftr_set_value(struct arm64_ftr_bits *ftrp, s64 reg, s64 ftr_val)
+ {
+       u64 mask = arm64_ftr_mask(ftrp);
+       reg &= ~mask;
+       reg |= (ftr_val << ftrp->shift) & mask;
+       return reg;
+ }
+ static s64 arm64_ftr_safe_value(struct arm64_ftr_bits *ftrp, s64 new, s64 cur)
+ {
+       s64 ret = 0;
+       switch (ftrp->type) {
+       case FTR_EXACT:
+               ret = ftrp->safe_val;
+               break;
+       case FTR_LOWER_SAFE:
+               ret = new < cur ? new : cur;
+               break;
+       case FTR_HIGHER_SAFE:
+               ret = new > cur ? new : cur;
+               break;
+       default:
+               BUG();
+       }
+       return ret;
+ }
+ static int __init sort_cmp_ftr_regs(const void *a, const void *b)
+ {
+       return ((const struct arm64_ftr_reg *)a)->sys_id -
+                ((const struct arm64_ftr_reg *)b)->sys_id;
+ }
+ static void __init swap_ftr_regs(void *a, void *b, int size)
+ {
+       struct arm64_ftr_reg tmp = *(struct arm64_ftr_reg *)a;
+       *(struct arm64_ftr_reg *)a = *(struct arm64_ftr_reg *)b;
+       *(struct arm64_ftr_reg *)b = tmp;
+ }
+ static void __init sort_ftr_regs(void)
+ {
+       /* Keep the array sorted so that we can do the binary search */
+       sort(arm64_ftr_regs,
+               ARRAY_SIZE(arm64_ftr_regs),
+               sizeof(arm64_ftr_regs[0]),
+               sort_cmp_ftr_regs,
+               swap_ftr_regs);
+ }
+ /*
+  * Initialise the CPU feature register from Boot CPU values.
+  * Also initiliases the strict_mask for the register.
+  */
+ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
+ {
+       u64 val = 0;
+       u64 strict_mask = ~0x0ULL;
+       struct arm64_ftr_bits *ftrp;
+       struct arm64_ftr_reg *reg = get_arm64_ftr_reg(sys_reg);
+       BUG_ON(!reg);
+       for (ftrp  = reg->ftr_bits; ftrp->width; ftrp++) {
+               s64 ftr_new = arm64_ftr_value(ftrp, new);
+               val = arm64_ftr_set_value(ftrp, val, ftr_new);
+               if (!ftrp->strict)
+                       strict_mask &= ~arm64_ftr_mask(ftrp);
+       }
+       reg->sys_val = val;
+       reg->strict_mask = strict_mask;
+ }
+ void __init init_cpu_features(struct cpuinfo_arm64 *info)
+ {
+       /* Before we start using the tables, make sure it is sorted */
+       sort_ftr_regs();
+       init_cpu_ftr_reg(SYS_CTR_EL0, info->reg_ctr);
+       init_cpu_ftr_reg(SYS_DCZID_EL0, info->reg_dczid);
+       init_cpu_ftr_reg(SYS_CNTFRQ_EL0, info->reg_cntfrq);
+       init_cpu_ftr_reg(SYS_ID_AA64DFR0_EL1, info->reg_id_aa64dfr0);
+       init_cpu_ftr_reg(SYS_ID_AA64DFR1_EL1, info->reg_id_aa64dfr1);
+       init_cpu_ftr_reg(SYS_ID_AA64ISAR0_EL1, info->reg_id_aa64isar0);
+       init_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1);
+       init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0);
+       init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1);
+       init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0);
+       init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
+       init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
+       init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
+       init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
+       init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
+       init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
+       init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
+       init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
+       init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
+       init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
+       init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
+       init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
+       init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
+       init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
+       init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
+       init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
+       init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
+ }
+ static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
+ {
+       struct arm64_ftr_bits *ftrp;
+       for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) {
+               s64 ftr_cur = arm64_ftr_value(ftrp, reg->sys_val);
+               s64 ftr_new = arm64_ftr_value(ftrp, new);
+               if (ftr_cur == ftr_new)
+                       continue;
+               /* Find a safe value */
+               ftr_new = arm64_ftr_safe_value(ftrp, ftr_new, ftr_cur);
+               reg->sys_val = arm64_ftr_set_value(ftrp, reg->sys_val, ftr_new);
+       }
+ }
+ static int check_update_ftr_reg(u32 sys_id, int cpu, u64 val, u64 boot)
+ {
+       struct arm64_ftr_reg *regp = get_arm64_ftr_reg(sys_id);
+       BUG_ON(!regp);
+       update_cpu_ftr_reg(regp, val);
+       if ((boot & regp->strict_mask) == (val & regp->strict_mask))
+               return 0;
+       pr_warn("SANITY CHECK: Unexpected variation in %s. Boot CPU: %#016llx, CPU%d: %#016llx\n",
+                       regp->name, boot, cpu, val);
+       return 1;
+ }
+ /*
+  * Update system wide CPU feature registers with the values from a
+  * non-boot CPU. Also performs SANITY checks to make sure that there
+  * aren't any insane variations from that of the boot CPU.
+  */
+ void update_cpu_features(int cpu,
+                        struct cpuinfo_arm64 *info,
+                        struct cpuinfo_arm64 *boot)
+ {
+       int taint = 0;
+       /*
+        * The kernel can handle differing I-cache policies, but otherwise
+        * caches should look identical. Userspace JITs will make use of
+        * *minLine.
+        */
+       taint |= check_update_ftr_reg(SYS_CTR_EL0, cpu,
+                                     info->reg_ctr, boot->reg_ctr);
+       /*
+        * Userspace may perform DC ZVA instructions. Mismatched block sizes
+        * could result in too much or too little memory being zeroed if a
+        * process is preempted and migrated between CPUs.
+        */
+       taint |= check_update_ftr_reg(SYS_DCZID_EL0, cpu,
+                                     info->reg_dczid, boot->reg_dczid);
+       /* If different, timekeeping will be broken (especially with KVM) */
+       taint |= check_update_ftr_reg(SYS_CNTFRQ_EL0, cpu,
+                                     info->reg_cntfrq, boot->reg_cntfrq);
+       /*
+        * The kernel uses self-hosted debug features and expects CPUs to
+        * support identical debug features. We presently need CTX_CMPs, WRPs,
+        * and BRPs to be identical.
+        * ID_AA64DFR1 is currently RES0.
+        */
+       taint |= check_update_ftr_reg(SYS_ID_AA64DFR0_EL1, cpu,
+                                     info->reg_id_aa64dfr0, boot->reg_id_aa64dfr0);
+       taint |= check_update_ftr_reg(SYS_ID_AA64DFR1_EL1, cpu,
+                                     info->reg_id_aa64dfr1, boot->reg_id_aa64dfr1);
+       /*
+        * Even in big.LITTLE, processors should be identical instruction-set
+        * wise.
+        */
+       taint |= check_update_ftr_reg(SYS_ID_AA64ISAR0_EL1, cpu,
+                                     info->reg_id_aa64isar0, boot->reg_id_aa64isar0);
+       taint |= check_update_ftr_reg(SYS_ID_AA64ISAR1_EL1, cpu,
+                                     info->reg_id_aa64isar1, boot->reg_id_aa64isar1);
+       /*
+        * Differing PARange support is fine as long as all peripherals and
+        * memory are mapped within the minimum PARange of all CPUs.
+        * Linux should not care about secure memory.
+        */
+       taint |= check_update_ftr_reg(SYS_ID_AA64MMFR0_EL1, cpu,
+                                     info->reg_id_aa64mmfr0, boot->reg_id_aa64mmfr0);
+       taint |= check_update_ftr_reg(SYS_ID_AA64MMFR1_EL1, cpu,
+                                     info->reg_id_aa64mmfr1, boot->reg_id_aa64mmfr1);
+       /*
+        * EL3 is not our concern.
+        * ID_AA64PFR1 is currently RES0.
+        */
+       taint |= check_update_ftr_reg(SYS_ID_AA64PFR0_EL1, cpu,
+                                     info->reg_id_aa64pfr0, boot->reg_id_aa64pfr0);
+       taint |= check_update_ftr_reg(SYS_ID_AA64PFR1_EL1, cpu,
+                                     info->reg_id_aa64pfr1, boot->reg_id_aa64pfr1);
+       /*
+        * If we have AArch32, we care about 32-bit features for compat. These
+        * registers should be RES0 otherwise.
+        */
+       taint |= check_update_ftr_reg(SYS_ID_DFR0_EL1, cpu,
+                                       info->reg_id_dfr0, boot->reg_id_dfr0);
+       taint |= check_update_ftr_reg(SYS_ID_ISAR0_EL1, cpu,
+                                       info->reg_id_isar0, boot->reg_id_isar0);
+       taint |= check_update_ftr_reg(SYS_ID_ISAR1_EL1, cpu,
+                                       info->reg_id_isar1, boot->reg_id_isar1);
+       taint |= check_update_ftr_reg(SYS_ID_ISAR2_EL1, cpu,
+                                       info->reg_id_isar2, boot->reg_id_isar2);
+       taint |= check_update_ftr_reg(SYS_ID_ISAR3_EL1, cpu,
+                                       info->reg_id_isar3, boot->reg_id_isar3);
+       taint |= check_update_ftr_reg(SYS_ID_ISAR4_EL1, cpu,
+                                       info->reg_id_isar4, boot->reg_id_isar4);
+       taint |= check_update_ftr_reg(SYS_ID_ISAR5_EL1, cpu,
+                                       info->reg_id_isar5, boot->reg_id_isar5);
+       /*
+        * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and
+        * ACTLR formats could differ across CPUs and therefore would have to
+        * be trapped for virtualization anyway.
+        */
+       taint |= check_update_ftr_reg(SYS_ID_MMFR0_EL1, cpu,
+                                       info->reg_id_mmfr0, boot->reg_id_mmfr0);
+       taint |= check_update_ftr_reg(SYS_ID_MMFR1_EL1, cpu,
+                                       info->reg_id_mmfr1, boot->reg_id_mmfr1);
+       taint |= check_update_ftr_reg(SYS_ID_MMFR2_EL1, cpu,
+                                       info->reg_id_mmfr2, boot->reg_id_mmfr2);
+       taint |= check_update_ftr_reg(SYS_ID_MMFR3_EL1, cpu,
+                                       info->reg_id_mmfr3, boot->reg_id_mmfr3);
+       taint |= check_update_ftr_reg(SYS_ID_PFR0_EL1, cpu,
+                                       info->reg_id_pfr0, boot->reg_id_pfr0);
+       taint |= check_update_ftr_reg(SYS_ID_PFR1_EL1, cpu,
+                                       info->reg_id_pfr1, boot->reg_id_pfr1);
+       taint |= check_update_ftr_reg(SYS_MVFR0_EL1, cpu,
+                                       info->reg_mvfr0, boot->reg_mvfr0);
+       taint |= check_update_ftr_reg(SYS_MVFR1_EL1, cpu,
+                                       info->reg_mvfr1, boot->reg_mvfr1);
+       taint |= check_update_ftr_reg(SYS_MVFR2_EL1, cpu,
+                                       info->reg_mvfr2, boot->reg_mvfr2);
+       /*
+        * Mismatched CPU features are a recipe for disaster. Don't even
+        * pretend to support them.
+        */
+       WARN_TAINT_ONCE(taint, TAINT_CPU_OUT_OF_SPEC,
+                       "Unsupported CPU feature variation.\n");
+ }
+ u64 read_system_reg(u32 id)
+ {
+       struct arm64_ftr_reg *regp = get_arm64_ftr_reg(id);
+       /* We shouldn't get a request for an unsupported register */
+       BUG_ON(!regp);
+       return regp->sys_val;
+ }
  
 +#include <linux/irqchip/arm-gic-v3.h>
 +
  static bool
  feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry)
  {
        return val >= entry->min_field_value;
  }
  
- #define __ID_FEAT_CHK(reg)                                            \
- static bool __maybe_unused                                            \
- has_##reg##_feature(const struct arm64_cpu_capabilities *entry)               \
- {                                                                     \
-       u64 val;                                                        \
-                                                                       \
-       val = read_cpuid(reg##_el1);                                    \
-       return feature_matches(val, entry);                             \
- }
+ static bool
+ has_cpuid_feature(const struct arm64_cpu_capabilities *entry)
+ {
+       u64 val;
  
__ID_FEAT_CHK(id_aa64pfr0);
__ID_FEAT_CHK(id_aa64mmfr1);
- __ID_FEAT_CHK(id_aa64isar0);
      val = read_system_reg(entry->sys_reg);
      return feature_matches(val, entry);
+ }
  
-       if (!has_id_aa64pfr0_feature(entry))
 +static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry)
 +{
 +      bool has_sre;
 +
++      if (!has_cpuid_feature(entry))
 +              return false;
 +
 +      has_sre = gic_enable_sre();
 +      if (!has_sre)
 +              pr_warn_once("%s present but disabled by higher exception level\n",
 +                           entry->desc);
 +
 +      return has_sre;
 +}
 +
  static const struct arm64_cpu_capabilities arm64_features[] = {
        {
                .desc = "GIC system register CPU interface",
                .capability = ARM64_HAS_SYSREG_GIC_CPUIF,
 -              .matches = has_cpuid_feature,
 +              .matches = has_useable_gicv3_cpuif,
-               .field_pos = 24,
+               .sys_reg = SYS_ID_AA64PFR0_EL1,
+               .field_pos = ID_AA64PFR0_GIC_SHIFT,
                .min_field_value = 1,
        },
  #ifdef CONFIG_ARM64_PAN
Simple merge
index 61eb1d17586a859a1fcc1d0d0fd653028d736b11,a48d1f477b2e8c4e3852cd9677c766fcf243b7c2..de46b50f4cdf952087e77d473314e75728efeec0
@@@ -48,9 -48,17 +48,8 @@@ static struct mm_struct efi_mm = 
        .mmap_sem               = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
        .page_table_lock        = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
        .mmlist                 = LIST_HEAD_INIT(efi_mm.mmlist),
-       INIT_MM_CONTEXT(efi_mm)
  };
  
 -static int uefi_debug __initdata;
 -static int __init uefi_debug_setup(char *str)
 -{
 -      uefi_debug = 1;
 -
 -      return 0;
 -}
 -early_param("uefi_debug", uefi_debug_setup);
 -
  static int __init is_normal_ram(efi_memory_desc_t *md)
  {
        if (md->attribute & EFI_MEMORY_WB)
Simple merge
Simple merge
index 44ca4143b013227ebf9eb40eafd721454ab45074,3c5e4e6dcf687bc57f61c3212bbfd06aad637eb5..40f7b33a22dafce27c3491d181170760916aec04
@@@ -80,21 -80,17 +80,21 @@@ int cpu_suspend(unsigned long arg, int 
        if (ret == 0) {
                /*
                 * We are resuming from reset with TTBR0_EL1 set to the
 -               * idmap to enable the MMU; restore the active_mm mappings in
 -               * TTBR0_EL1 unless the active_mm == &init_mm, in which case
 -               * the thread entered cpu_suspend with TTBR0_EL1 set to
 -               * reserved TTBR0 page tables and should be restored as such.
 +               * idmap to enable the MMU; set the TTBR0 to the reserved
 +               * page tables to prevent speculative TLB allocations, flush
 +               * the local tlb and set the default tcr_el1.t0sz so that
 +               * the TTBR0 address space set-up is properly restored.
 +               * If the current active_mm != &init_mm we entered cpu_suspend
 +               * with mappings in TTBR0 that must be restored, so we switch
 +               * them back to complete the address space configuration
 +               * restoration before returning.
                 */
 -              if (mm == &init_mm)
 -                      cpu_set_reserved_ttbr0();
 -              else
 -                      cpu_switch_mm(mm->pgd, mm);
 -
 +              cpu_set_reserved_ttbr0();
-               flush_tlb_all();
+               local_flush_tlb_all();
 +              cpu_set_default_tcr_t0sz();
 +
 +              if (mm != &init_mm)
 +                      cpu_switch_mm(mm->pgd, mm);
  
                /*
                 * Restore per-cpu offset before any kernel
index ff5292c6277c4764734a1a1769af06347ccb8c4b,6a7d5cd772e6b73929fc33099d2c9193b1c0cb60..c9d1f34daab152028d8bcd795504ac4ed2919cc8
@@@ -34,9 -32,10 +35,11 @@@ config KV
        select KVM_VFIO
        select HAVE_KVM_EVENTFD
        select HAVE_KVM_IRQFD
 +      select KVM_ARM_VGIC_V3
        ---help---
          Support hosting virtualized guest machines.
+         We don't support KVM with 16K page tables yet, due to the multiple
+         levels of fake page tables.
  
          If unsure, say N.
  
Simple merge
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,816120ece6bcecfbcbc1c25be51324c5197b65cd..78dfbd34b6bffd2fa36312da89dc6ca43f036c3c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,68 +1,78 @@@
 -      if (*image_addr != (dram_base + TEXT_OFFSET)) {
+ /*
+  * Copyright (C) 2013, 2014 Linaro Ltd;  <roy.franz@linaro.org>
+  *
+  * This file implements the EFI boot stub for the arm64 kernel.
+  * Adapted from ARM version by Mark Salter <msalter@redhat.com>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  *
+  */
+ #include <linux/efi.h>
+ #include <asm/efi.h>
+ #include <asm/sections.h>
+ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
+                                       unsigned long *image_addr,
+                                       unsigned long *image_size,
+                                       unsigned long *reserve_addr,
+                                       unsigned long *reserve_size,
+                                       unsigned long dram_base,
+                                       efi_loaded_image_t *image)
+ {
+       efi_status_t status;
+       unsigned long kernel_size, kernel_memsize = 0;
+       unsigned long nr_pages;
+       void *old_image_addr = (void *)*image_addr;
++      unsigned long preferred_offset;
++
++      /*
++       * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
++       * a 2 MB aligned base, which itself may be lower than dram_base, as
++       * long as the resulting offset equals or exceeds it.
++       */
++      preferred_offset = round_down(dram_base, SZ_2M) + TEXT_OFFSET;
++      if (preferred_offset < dram_base)
++              preferred_offset += SZ_2M;
+       /* Relocate the image, if required. */
+       kernel_size = _edata - _text;
 -              *image_addr = *reserve_addr = dram_base + TEXT_OFFSET;
++      if (*image_addr != preferred_offset) {
+               kernel_memsize = kernel_size + (_end - _edata);
+               /*
+                * First, try a straight allocation at the preferred offset.
+                * This will work around the issue where, if dram_base == 0x0,
+                * efi_low_alloc() refuses to allocate at 0x0 (to prevent the
+                * address of the allocation to be mistaken for a FAIL return
+                * value or a NULL pointer). It will also ensure that, on
+                * platforms where the [dram_base, dram_base + TEXT_OFFSET)
+                * interval is partially occupied by the firmware (like on APM
+                * Mustang), we can still place the kernel at the address
+                * 'dram_base + TEXT_OFFSET'.
+                */
++              *image_addr = *reserve_addr = preferred_offset;
+               nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /
+                          EFI_PAGE_SIZE;
+               status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
+                                       EFI_LOADER_DATA, nr_pages,
+                                       (efi_physical_addr_t *)reserve_addr);
+               if (status != EFI_SUCCESS) {
+                       kernel_memsize += TEXT_OFFSET;
+                       status = efi_low_alloc(sys_table_arg, kernel_memsize,
+                                              SZ_2M, reserve_addr);
+                       if (status != EFI_SUCCESS) {
+                               pr_efi_err(sys_table_arg, "Failed to relocate kernel\n");
+                               return status;
+                       }
+                       *image_addr = *reserve_addr + TEXT_OFFSET;
+               }
+               memcpy((void *)*image_addr, old_image_addr, kernel_size);
+               *reserve_size = kernel_memsize;
+       }
+       return EFI_SUCCESS;
+ }