Merge branch 'spectre' of git://git.armlinux.org.uk/~rmk/linux-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 18 Nov 2018 18:45:09 +0000 (10:45 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 18 Nov 2018 18:45:09 +0000 (10:45 -0800)
Pull ARM spectre updates from Russell King:
 "These are the currently known final bits that resolve the Spectre
  issues. big.Little systems used to be sufficiently identical in that
  there were no differences between individual CPUs in the system that
  mattered to the kernel. With the advent of the Spectre problem, the
  CPUs now have differences in how the workaround is applied.

  As a result of previous Spectre patches, these systems ended up
  reporting quite a lot of:

     "CPUx: Spectre v2: incorrect context switching function, system vulnerable"

  messages due to the action of the big.Little switcher causing the CPUs
  to be re-initialised regularly. This series resolves that issue by
  making the CPU vtable unique to each CPU.

  However, since this is used very early, before per-cpu is setup,
  per-cpu can't be used. We also have a problem that two of the methods
  are not called from preempt-safe paths, but thankfully these remain
  identical between all CPUs in the system. To make sure, we validate
  that these are identical during boot"

* 'spectre' of git://git.armlinux.org.uk/~rmk/linux-arm:
  ARM: spectre-v2: per-CPU vtables to work around big.Little systems
  ARM: add PROC_VTABLE and PROC_TABLE macros
  ARM: clean up per-processor check_bugs method call
  ARM: split out processor lookup
  ARM: make lookup_processor_type() non-__init

1  2 
arch/arm/include/asm/cputype.h
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c

index 0d289240b6ca110ab961a280ddd20fc1c567f2a4,f6df4bb4e543f72cb9ce77ef14c5ac059701d603..775cac3c02bb0a31facb970e16feef83f86c6632
@@@ -2,6 -2,9 +2,6 @@@
  #ifndef __ASM_ARM_CPUTYPE_H
  #define __ASM_ARM_CPUTYPE_H
  
 -#include <linux/stringify.h>
 -#include <linux/kernel.h>
 -
  #define CPUID_ID      0
  #define CPUID_CACHETYPE       1
  #define CPUID_TCM     2
@@@ -59,7 -62,6 +59,7 @@@
        ((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK)
  
  #define ARM_CPU_IMP_ARM                       0x41
 +#define ARM_CPU_IMP_BRCM              0x42
  #define ARM_CPU_IMP_DEC                       0x44
  #define ARM_CPU_IMP_INTEL             0x69
  
@@@ -82,9 -84,8 +82,9 @@@
  #define ARM_CPU_PART_CORTEX_A75               0x4100d0a0
  #define ARM_CPU_PART_MASK             0xff00fff0
  
 -/* Broadcom cores */
 +/* Broadcom implemented processors */
  #define ARM_CPU_PART_BRAHMA_B15               0x420000f0
 +#define ARM_CPU_PART_BRAHMA_B53               0x42001000
  
  /* DEC implemented cores */
  #define ARM_CPU_PART_SA1100           0x4400a110
  /* Qualcomm implemented cores */
  #define ARM_CPU_PART_SCORPION         0x510002d0
  
 +#ifndef __ASSEMBLY__
 +
 +#include <linux/stringify.h>
 +#include <linux/kernel.h>
 +
  extern unsigned int processor_id;
+ struct proc_info_list *lookup_processor(u32 midr);
  
  #ifdef CONFIG_CPU_CP15
  #define read_cpuid(reg)                                                       \
@@@ -338,6 -335,4 +339,6 @@@ static inline int __attribute_const__ c
  #define cpuid_feature_extract(reg, field) \
        cpuid_feature_extract_field(read_cpuid_ext(reg), field)
  
 +#endif /* __ASSEMBLY__ */
 +
  #endif
diff --combined arch/arm/kernel/setup.c
index ac7e08886863cfa74855e5b91c4f436e85da1e0a,cd46a595422cf2ce37917c1b1933c14ae79dea9d..375b13f7e780663eddb3f04e632751064a6b5bfd
@@@ -16,6 -16,7 +16,6 @@@
  #include <linux/utsname.h>
  #include <linux/initrd.h>
  #include <linux/console.h>
 -#include <linux/bootmem.h>
  #include <linux/seq_file.h>
  #include <linux/screen_info.h>
  #include <linux/of_platform.h>
@@@ -114,6 -115,11 +114,11 @@@ EXPORT_SYMBOL(elf_hwcap2)
  
  #ifdef MULTI_CPU
  struct processor processor __ro_after_init;
+ #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+ struct processor *cpu_vtable[NR_CPUS] = {
+       [0] = &processor,
+ };
+ #endif
  #endif
  #ifdef MULTI_TLB
  struct cpu_tlb_fns cpu_tlb __ro_after_init;
@@@ -666,28 -672,33 +671,33 @@@ static void __init smp_build_mpidr_hash
  }
  #endif
  
- static void __init setup_processor(void)
+ /*
+  * locate processor in the list of supported processor types.  The linker
+  * builds this table for us from the entries in arch/arm/mm/proc-*.S
+  */
+ struct proc_info_list *lookup_processor(u32 midr)
  {
-       struct proc_info_list *list;
+       struct proc_info_list *list = lookup_processor_type(midr);
  
-       /*
-        * locate processor in the list of supported processor
-        * types.  The linker builds this table for us from the
-        * entries in arch/arm/mm/proc-*.S
-        */
-       list = lookup_processor_type(read_cpuid_id());
        if (!list) {
-               pr_err("CPU configuration botched (ID %08x), unable to continue.\n",
-                      read_cpuid_id());
-               while (1);
+               pr_err("CPU%u: configuration botched (ID %08x), CPU halted\n",
+                      smp_processor_id(), midr);
+               while (1)
+               /* can't use cpu_relax() here as it may require MMU setup */;
        }
  
+       return list;
+ }
+ static void __init setup_processor(void)
+ {
+       unsigned int midr = read_cpuid_id();
+       struct proc_info_list *list = lookup_processor(midr);
        cpu_name = list->cpu_name;
        __cpu_architecture = __get_cpu_architecture();
  
- #ifdef MULTI_CPU
-       processor = *list->proc;
- #endif
+       init_proc_vtable(list->proc);
  #ifdef MULTI_TLB
        cpu_tlb = *list->tlb;
  #endif
  #endif
  
        pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
-               cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
+               list->cpu_name, midr, midr & 15,
                proc_arch[cpu_architecture()], get_cr());
  
        snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
@@@ -753,7 -764,7 +763,7 @@@ int __init arm_add_memory(u64 start, u6
        else
                size -= aligned_start - start;
  
 -#ifndef CONFIG_ARCH_PHYS_ADDR_T_64BIT
 +#ifndef CONFIG_PHYS_ADDR_T_64BIT
        if (aligned_start > ULONG_MAX) {
                pr_crit("Ignoring memory at 0x%08llx outside 32-bit physical address space\n",
                        (long long)start);
@@@ -856,7 -867,7 +866,7 @@@ static void __init request_standard_res
                 */
                boot_alias_start = phys_to_idmap(start);
                if (arm_has_idmap_alias() && boot_alias_start != IDMAP_INVALID_ADDR) {
 -                      res = memblock_virt_alloc(sizeof(*res), 0);
 +                      res = memblock_alloc(sizeof(*res), SMP_CACHE_BYTES);
                        res->name = "System RAM (boot alias)";
                        res->start = boot_alias_start;
                        res->end = phys_to_idmap(end);
                        request_resource(&iomem_resource, res);
                }
  
 -              res = memblock_virt_alloc(sizeof(*res), 0);
 +              res = memblock_alloc(sizeof(*res), SMP_CACHE_BYTES);
                res->name  = "System RAM";
                res->start = start;
                res->end = end;
@@@ -1144,7 -1155,7 +1154,7 @@@ void __init setup_arch(char **cmdline_p
  
        reserve_crashkernel();
  
 -#ifdef CONFIG_MULTI_IRQ_HANDLER
 +#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
        handle_arch_irq = mdesc->handle_irq;
  #endif
  
diff --combined arch/arm/kernel/smp.c
index 0978282d5fc27a7c4a5e6b0e274da8bfc4c14c8d,82b879db32ee4ca8d07454da7c2a0f7d73e9de85..12a6172263c0b057a94f2041accf581088374fb0
@@@ -42,6 -42,7 +42,7 @@@
  #include <asm/mmu_context.h>
  #include <asm/pgtable.h>
  #include <asm/pgalloc.h>
+ #include <asm/procinfo.h>
  #include <asm/processor.h>
  #include <asm/sections.h>
  #include <asm/tlbflush.h>
@@@ -102,6 -103,30 +103,30 @@@ static unsigned long get_arch_pgd(pgd_
  #endif
  }
  
+ #if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+ static int secondary_biglittle_prepare(unsigned int cpu)
+ {
+       if (!cpu_vtable[cpu])
+               cpu_vtable[cpu] = kzalloc(sizeof(*cpu_vtable[cpu]), GFP_KERNEL);
+       return cpu_vtable[cpu] ? 0 : -ENOMEM;
+ }
+ static void secondary_biglittle_init(void)
+ {
+       init_proc_vtable(lookup_processor(read_cpuid_id())->proc);
+ }
+ #else
+ static int secondary_biglittle_prepare(unsigned int cpu)
+ {
+       return 0;
+ }
+ static void secondary_biglittle_init(void)
+ {
+ }
+ #endif
  int __cpu_up(unsigned int cpu, struct task_struct *idle)
  {
        int ret;
        if (!smp_ops.smp_boot_secondary)
                return -ENOSYS;
  
+       ret = secondary_biglittle_prepare(cpu);
+       if (ret)
+               return ret;
        /*
         * We need to tell the secondary core where to find
         * its stack and the page tables.
@@@ -237,6 -266,8 +266,6 @@@ int __cpu_disable(void
        flush_cache_louis();
        local_flush_tlb_all();
  
 -      clear_tasks_mm_cpumask(cpu);
 -
        return 0;
  }
  
@@@ -254,7 -285,6 +283,7 @@@ void __cpu_die(unsigned int cpu
        }
        pr_debug("CPU%u: shutdown\n", cpu);
  
 +      clear_tasks_mm_cpumask(cpu);
        /*
         * platform_cpu_kill() is generally expected to do the powering off
         * and/or cutting of clocks to the dying CPU.  Optionally, this may
@@@ -359,6 -389,8 +388,8 @@@ asmlinkage void secondary_start_kernel(
        struct mm_struct *mm = &init_mm;
        unsigned int cpu;
  
+       secondary_biglittle_init();
        /*
         * The identity mapping is uncached (strongly ordered), so
         * switch away from it before attempting any exclusive accesses.