Merge tag 'powerpc-cve-2020-4788' into fixes
authorMichael Ellerman <mpe@ellerman.id.au>
Mon, 23 Nov 2020 10:16:27 +0000 (21:16 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 23 Nov 2020 10:16:27 +0000 (21:16 +1100)
From Daniel's cover letter:

IBM Power9 processors can speculatively operate on data in the L1 cache
before it has been completely validated, via a way-prediction mechanism. It
is not possible for an attacker to determine the contents of impermissible
memory using this method, since these systems implement a combination of
hardware and software security measures to prevent scenarios where
protected data could be leaked.

However these measures don't address the scenario where an attacker induces
the operating system to speculatively execute instructions using data that
the attacker controls. This can be used for example to speculatively bypass
"kernel user access prevention" techniques, as discovered by Anthony
Steinhauser of Google's Safeside Project. This is not an attack by itself,
but there is a possibility it could be used in conjunction with
side-channels or other weaknesses in the privileged code to construct an
attack.

This issue can be mitigated by flushing the L1 cache between privilege
boundaries of concern.

This patch series flushes the L1 cache on kernel entry (patch 2) and after the
kernel performs any user accesses (patch 3). It also adds a self-test and
performs some related cleanups.

13 files changed:
arch/powerpc/Makefile
arch/powerpc/include/asm/nohash/32/kup-8xx.h
arch/powerpc/include/asm/nohash/32/mmu-8xx.h
arch/powerpc/include/asm/nohash/32/pte-8xx.h
arch/powerpc/include/asm/topology.h
arch/powerpc/include/asm/uaccess.h
arch/powerpc/kernel/eeh_cache.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/head_40x.S
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/head_book3s_32.S
arch/powerpc/kernel/smp.c
arch/powerpc/kvm/book3s_xive_native.c

index a4d56f0..16b8336 100644 (file)
@@ -248,7 +248,6 @@ KBUILD_CFLAGS               += $(call cc-option,-mno-string)
 cpu-as-$(CONFIG_40x)           += -Wa,-m405
 cpu-as-$(CONFIG_44x)           += -Wa,-m440
 cpu-as-$(CONFIG_ALTIVEC)       += $(call as-option,-Wa$(comma)-maltivec)
-cpu-as-$(CONFIG_E200)          += -Wa,-me200
 cpu-as-$(CONFIG_E500)          += -Wa,-me500
 
 # When using '-many -mpower4' gas will first try and find a matching power4
index 85ed239..567cdc5 100644 (file)
@@ -63,7 +63,7 @@ static inline void restore_user_access(unsigned long flags)
 static inline bool
 bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
 {
-       return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xf0000000),
+       return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000),
                    "Bug: fault blocked by AP register !");
 }
 
index 1d9ac0f..0bd1b14 100644 (file)
  * respectively NA for All or X for Supervisor and no access for User.
  * Then we use the APG to say whether accesses are according to Page rules or
  * "all Supervisor" rules (Access to all)
- * Therefore, we define 2 APG groups. lsb is _PMD_USER
- * 0 => Kernel => 01 (all accesses performed according to page definition)
- * 1 => User => 00 (all accesses performed as supervisor iaw page definition)
- * 2-15 => Not Used
- */
-#define MI_APG_INIT    0x40000000
-
-/*
- * 0 => Kernel => 01 (all accesses performed according to page definition)
- * 1 => User => 10 (all accesses performed according to swaped page definition)
- * 2-15 => Not Used
- */
-#define MI_APG_KUEP    0x60000000
+ * _PAGE_ACCESSED is also managed via APG. When _PAGE_ACCESSED is not set, say
+ * "all User" rules, that will lead to NA for all.
+ * Therefore, we define 4 APG groups. lsb is _PAGE_ACCESSED
+ * 0 => Kernel => 11 (all accesses performed according as user iaw page definition)
+ * 1 => Kernel+Accessed => 01 (all accesses performed according to page definition)
+ * 2 => User => 11 (all accesses performed according as user iaw page definition)
+ * 3 => User+Accessed => 00 (all accesses performed as supervisor iaw page definition) for INIT
+ *                    => 10 (all accesses performed according to swaped page definition) for KUEP
+ * 4-15 => Not Used
+ */
+#define MI_APG_INIT    0xdc000000
+#define MI_APG_KUEP    0xde000000
 
 /* The effective page number register.  When read, contains the information
  * about the last instruction TLB miss.  When MI_RPN is written, bits in
 #define MD_Ks          0x80000000      /* Should not be set */
 #define MD_Kp          0x40000000      /* Should always be set */
 
-/*
- * All pages' PP data bits are set to either 000 or 011 or 001, which means
- * respectively RW for Supervisor and no access for User, or RO for
- * Supervisor and no access for user and NA for ALL.
- * Then we use the APG to say whether accesses are according to Page rules or
- * "all Supervisor" rules (Access to all)
- * Therefore, we define 2 APG groups. lsb is _PMD_USER
- * 0 => Kernel => 01 (all accesses performed according to page definition)
- * 1 => User => 00 (all accesses performed as supervisor iaw page definition)
- * 2-15 => Not Used
- */
-#define MD_APG_INIT    0x40000000
-
-/*
- * 0 => No user => 01 (all accesses performed according to page definition)
- * 1 => User => 10 (all accesses performed according to swaped page definition)
- * 2-15 => Not Used
- */
-#define MD_APG_KUAP    0x60000000
+/* See explanation above at the definition of MI_APG_INIT */
+#define MD_APG_INIT    0xdc000000
+#define MD_APG_KUAP    0xde000000
 
 /* The effective page number register.  When read, contains the information
  * about the last instruction TLB miss.  When MD_RPN is written, bits in
index 66f403a..1581204 100644 (file)
@@ -39,9 +39,9 @@
  * into the TLB.
  */
 #define _PAGE_GUARDED  0x0010  /* Copied to L1 G entry in DTLB */
-#define _PAGE_SPECIAL  0x0020  /* SW entry */
+#define _PAGE_ACCESSED 0x0020  /* Copied to L1 APG 1 entry in I/DTLB */
 #define _PAGE_EXEC     0x0040  /* Copied to PP (bit 21) in ITLB */
-#define _PAGE_ACCESSED 0x0080  /* software: page referenced */
+#define _PAGE_SPECIAL  0x0080  /* SW entry */
 
 #define _PAGE_NA       0x0200  /* Supervisor NA, User no access */
 #define _PAGE_RO       0x0600  /* Supervisor RO, User no access */
 
 #define _PMD_PRESENT   0x0001
 #define _PMD_PRESENT_MASK      _PMD_PRESENT
-#define _PMD_BAD       0x0fd0
+#define _PMD_BAD       0x0f90
 #define _PMD_PAGE_MASK 0x000c
 #define _PMD_PAGE_8M   0x000c
 #define _PMD_PAGE_512K 0x0004
-#define _PMD_USER      0x0020  /* APG 1 */
+#define _PMD_ACCESSED  0x0020  /* APG 1 */
+#define _PMD_USER      0x0040  /* APG 2 */
 
 #define _PTE_NONE_MASK 0
 
index 8728590..3beeb03 100644 (file)
@@ -6,6 +6,7 @@
 
 struct device;
 struct device_node;
+struct drmem_lmb;
 
 #ifdef CONFIG_NUMA
 
@@ -61,6 +62,9 @@ static inline int early_cpu_to_node(int cpu)
         */
        return (nid < 0) ? 0 : nid;
 }
+
+int of_drconf_to_nid_single(struct drmem_lmb *lmb);
+
 #else
 
 static inline int early_cpu_to_node(int cpu) { return 0; }
@@ -84,10 +88,12 @@ static inline int cpu_distance(__be32 *cpu1_assoc, __be32 *cpu2_assoc)
        return 0;
 }
 
-#endif /* CONFIG_NUMA */
+static inline int of_drconf_to_nid_single(struct drmem_lmb *lmb)
+{
+       return first_online_node;
+}
 
-struct drmem_lmb;
-int of_drconf_to_nid_single(struct drmem_lmb *lmb);
+#endif /* CONFIG_NUMA */
 
 #if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR)
 extern int find_and_online_cpu_nid(int cpu);
index ef5bbb7..501c9a7 100644 (file)
@@ -178,7 +178,7 @@ do {                                                                \
  * are no aliasing issues.
  */
 #define __put_user_asm_goto(x, addr, label, op)                        \
-       asm volatile goto(                                      \
+       asm_volatile_goto(                                      \
                "1:     " op "%U1%X1 %0,%1      # put_user\n"   \
                EX_TABLE(1b, %l2)                               \
                :                                               \
@@ -191,7 +191,7 @@ do {                                                                \
        __put_user_asm_goto(x, ptr, label, "std")
 #else /* __powerpc64__ */
 #define __put_user_asm2_goto(x, addr, label)                   \
-       asm volatile goto(                                      \
+       asm_volatile_goto(                                      \
                "1:     stw%X1 %0, %1\n"                        \
                "2:     stw%X1 %L0, %L1\n"                      \
                EX_TABLE(1b, %l2)                               \
index 6b50bf1..bf32704 100644 (file)
@@ -264,8 +264,9 @@ static int eeh_addr_cache_show(struct seq_file *s, void *v)
 {
        struct pci_io_addr_range *piar;
        struct rb_node *n;
+       unsigned long flags;
 
-       spin_lock(&pci_io_addr_cache_root.piar_lock);
+       spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
        for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n)) {
                piar = rb_entry(n, struct pci_io_addr_range, rb_node);
 
@@ -273,7 +274,7 @@ static int eeh_addr_cache_show(struct seq_file *s, void *v)
                       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem",
                       &piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
        }
-       spin_unlock(&pci_io_addr_cache_root.piar_lock);
+       spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
 
        return 0;
 }
index f63a3d3..4d01f09 100644 (file)
@@ -1000,8 +1000,6 @@ TRAMP_REAL_BEGIN(system_reset_idle_wake)
  * Vectors for the FWNMI option.  Share common code.
  */
 TRAMP_REAL_BEGIN(system_reset_fwnmi)
-       /* XXX: fwnmi guest could run a nested/PR guest, so why no test?  */
-       __IKVM_REAL(system_reset)=0
        GEN_INT_ENTRY system_reset, virt=0
 
 #endif /* CONFIG_PPC_PSERIES */
@@ -1412,6 +1410,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
  *   If none is found, do a Linux page fault. Linux page faults can happen in
  *   kernel mode due to user copy operations of course.
  *
+ *   KVM: The KVM HDSI handler may perform a load with MSR[DR]=1 in guest
+ *   MMU context, which may cause a DSI in the host, which must go to the
+ *   KVM handler. MSR[IR] is not enabled, so the real-mode handler will
+ *   always be used regardless of AIL setting.
+ *
  * - Radix MMU
  *   The hardware loads from the Linux page table directly, so a fault goes
  *   immediately to Linux page fault.
@@ -1422,10 +1425,8 @@ INT_DEFINE_BEGIN(data_access)
        IVEC=0x300
        IDAR=1
        IDSISR=1
-#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        IKVM_SKIP=1
        IKVM_REAL=1
-#endif
 INT_DEFINE_END(data_access)
 
 EXC_REAL_BEGIN(data_access, 0x300, 0x80)
@@ -1464,6 +1465,8 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
  *   ppc64_bolted_size (first segment). The kernel handler must avoid stomping
  *   on user-handler data structures.
  *
+ *   KVM: Same as 0x300, DSLB must test for KVM guest.
+ *
  * A dedicated save area EXSLB is used (XXX: but it actually need not be
  * these days, we could use EXGEN).
  */
@@ -1472,10 +1475,8 @@ INT_DEFINE_BEGIN(data_access_slb)
        IAREA=PACA_EXSLB
        IRECONCILE=0
        IDAR=1
-#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        IKVM_SKIP=1
        IKVM_REAL=1
-#endif
 INT_DEFINE_END(data_access_slb)
 
 EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
index 44c9018..a1ae006 100644 (file)
@@ -284,11 +284,7 @@ _ENTRY(saved_ksp_limit)
 
        rlwimi  r11, r10, 22, 20, 29    /* Compute PTE address */
        lwz     r11, 0(r11)             /* Get Linux PTE */
-#ifdef CONFIG_SWAP
        li      r9, _PAGE_PRESENT | _PAGE_ACCESSED
-#else
-       li      r9, _PAGE_PRESENT
-#endif
        andc.   r9, r9, r11             /* Check permission */
        bne     5f
 
@@ -369,11 +365,7 @@ _ENTRY(saved_ksp_limit)
 
        rlwimi  r11, r10, 22, 20, 29    /* Compute PTE address */
        lwz     r11, 0(r11)             /* Get Linux PTE */
-#ifdef CONFIG_SWAP
        li      r9, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
-#else
-       li      r9, _PAGE_PRESENT | _PAGE_EXEC
-#endif
        andc.   r9, r9, r11             /* Check permission */
        bne     5f
 
index 9f359d3..ee0bfeb 100644 (file)
@@ -202,9 +202,7 @@ SystemCall:
 
 InstructionTLBMiss:
        mtspr   SPRN_SPRG_SCRATCH0, r10
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP) || defined(CONFIG_HUGETLBFS)
        mtspr   SPRN_SPRG_SCRATCH1, r11
-#endif
 
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
@@ -224,25 +222,13 @@ InstructionTLBMiss:
 3:
        mtcr    r11
 #endif
-#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
        lwz     r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10)        /* Get level 1 entry */
        mtspr   SPRN_MD_TWC, r11
-#else
-       lwz     r10, (swapper_pg_dir-PAGE_OFFSET)@l(r10)        /* Get level 1 entry */
-       mtspr   SPRN_MI_TWC, r10        /* Set segment attributes */
-       mtspr   SPRN_MD_TWC, r10
-#endif
        mfspr   r10, SPRN_MD_TWC
        lwz     r10, 0(r10)     /* Get the pte */
-#if defined(CONFIG_HUGETLBFS) || !defined(CONFIG_PIN_TLB_TEXT)
+       rlwimi  r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
        rlwimi  r11, r10, 32 - 9, _PMD_PAGE_512K
        mtspr   SPRN_MI_TWC, r11
-#endif
-#ifdef CONFIG_SWAP
-       rlwinm  r11, r10, 32-5, _PAGE_PRESENT
-       and     r11, r11, r10
-       rlwimi  r10, r11, 0, _PAGE_PRESENT
-#endif
        /* The Linux PTE won't go exactly into the MMU TLB.
         * Software indicator bits 20 and 23 must be clear.
         * Software indicator bits 22, 24, 25, 26, and 27 must be
@@ -256,9 +242,7 @@ InstructionTLBMiss:
 
        /* Restore registers */
 0:     mfspr   r10, SPRN_SPRG_SCRATCH0
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP) || defined(CONFIG_HUGETLBFS)
        mfspr   r11, SPRN_SPRG_SCRATCH1
-#endif
        rfi
        patch_site      0b, patch__itlbmiss_exit_1
 
@@ -268,9 +252,7 @@ InstructionTLBMiss:
        addi    r10, r10, 1
        stw     r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
        mfspr   r10, SPRN_SPRG_SCRATCH0
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP)
        mfspr   r11, SPRN_SPRG_SCRATCH1
-#endif
        rfi
 #endif
 
@@ -297,30 +279,16 @@ DataStoreTLBMiss:
        mfspr   r10, SPRN_MD_TWC
        lwz     r10, 0(r10)     /* Get the pte */
 
-       /* Insert the Guarded flag into the TWC from the Linux PTE.
+       /* Insert Guarded and Accessed flags into the TWC from the Linux PTE.
         * It is bit 27 of both the Linux PTE and the TWC (at least
         * I got that right :-).  It will be better when we can put
         * this into the Linux pgd/pmd and load it in the operation
         * above.
         */
-       rlwimi  r11, r10, 0, _PAGE_GUARDED
+       rlwimi  r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
        rlwimi  r11, r10, 32 - 9, _PMD_PAGE_512K
        mtspr   SPRN_MD_TWC, r11
 
-       /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
-        * We also need to know if the insn is a load/store, so:
-        * Clear _PAGE_PRESENT and load that which will
-        * trap into DTLB Error with store bit set accordinly.
-        */
-       /* PRESENT=0x1, ACCESSED=0x20
-        * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
-        * r10 = (r10 & ~PRESENT) | r11;
-        */
-#ifdef CONFIG_SWAP
-       rlwinm  r11, r10, 32-5, _PAGE_PRESENT
-       and     r11, r11, r10
-       rlwimi  r10, r11, 0, _PAGE_PRESENT
-#endif
        /* The Linux PTE won't go exactly into the MMU TLB.
         * Software indicator bits 24, 25, 26, and 27 must be
         * set.  All other Linux PTE bits control the behavior
@@ -711,7 +679,7 @@ initial_mmu:
        li      r9, 4                           /* up to 4 pages of 8M */
        mtctr   r9
        lis     r9, KERNELBASE@h                /* Create vaddr for TLB */
-       li      r10, MI_PS8MEG | MI_SVALID      /* Set 8M byte page */
+       li      r10, MI_PS8MEG | _PMD_ACCESSED | MI_SVALID
        li      r11, MI_BOOTINIT                /* Create RPN for address 0 */
 1:
        mtspr   SPRN_MI_CTR, r8 /* Set instruction MMU control */
@@ -775,7 +743,7 @@ _GLOBAL(mmu_pin_tlb)
 #ifdef CONFIG_PIN_TLB_TEXT
        LOAD_REG_IMMEDIATE(r5, 28 << 8)
        LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
-       LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG)
+       LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
        LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
        LOAD_REG_ADDR(r9, _sinittext)
        li      r0, 4
@@ -797,7 +765,7 @@ _GLOBAL(mmu_pin_tlb)
        LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
 #ifdef CONFIG_PIN_TLB_DATA
        LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
-       LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG)
+       LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
 #ifdef CONFIG_PIN_TLB_IMMR
        li      r0, 3
 #else
@@ -834,7 +802,7 @@ _GLOBAL(mmu_pin_tlb)
 #endif
 #ifdef CONFIG_PIN_TLB_IMMR
        LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
-       LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED)
+       LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED | _PMD_ACCESSED)
        mfspr   r8, SPRN_IMMR
        rlwinm  r8, r8, 0, 0xfff80000
        ori     r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
index 5eb9eed..a0dda2a 100644 (file)
@@ -156,6 +156,7 @@ __after_mmu_off:
        bl      initial_bats
        bl      load_segment_registers
 BEGIN_MMU_FTR_SECTION
+       bl      reloc_offset
        bl      early_hash_table
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
 #if defined(CONFIG_BOOTX_TEXT)
@@ -457,11 +458,7 @@ InstructionTLBMiss:
        cmplw   0,r1,r3
 #endif
        mfspr   r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
        li      r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
-#else
-       li      r1,_PAGE_PRESENT | _PAGE_EXEC
-#endif
 #if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
        bgt-    112f
        lis     r2, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
@@ -523,11 +520,7 @@ DataLoadTLBMiss:
        lis     r1, TASK_SIZE@h         /* check if kernel address */
        cmplw   0,r1,r3
        mfspr   r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
        li      r1, _PAGE_PRESENT | _PAGE_ACCESSED
-#else
-       li      r1, _PAGE_PRESENT
-#endif
        bgt-    112f
        lis     r2, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
        addi    r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l        /* kernel page table */
@@ -603,11 +596,7 @@ DataStoreTLBMiss:
        lis     r1, TASK_SIZE@h         /* check if kernel address */
        cmplw   0,r1,r3
        mfspr   r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
        li      r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
-#else
-       li      r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT
-#endif
        bgt-    112f
        lis     r2, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
        addi    r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l        /* kernel page table */
@@ -932,7 +921,7 @@ early_hash_table:
        ori     r6, r6, 3       /* 256kB table */
        mtspr   SPRN_SDR1, r6
        lis     r6, early_hash@h
-       lis     r3, Hash@ha
+       addis   r3, r3, Hash@ha
        stw     r6, Hash@l(r3)
        blr
 
index 3c6b982..8c2857c 100644 (file)
@@ -1393,13 +1393,14 @@ static void add_cpu_to_masks(int cpu)
 /* Activate a secondary processor. */
 void start_secondary(void *unused)
 {
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu = raw_smp_processor_id();
 
        mmgrab(&init_mm);
        current->active_mm = &init_mm;
 
        smp_store_cpu_info(cpu);
        set_dec(tb_ticks_per_jiffy);
+       rcu_cpu_starting(cpu);
        preempt_disable();
        cpu_callin_map[cpu] = 1;
 
index d0c2db0..a59a94f 100644 (file)
@@ -251,6 +251,13 @@ static vm_fault_t xive_native_esb_fault(struct vm_fault *vmf)
        }
 
        state = &sb->irq_state[src];
+
+       /* Some sanity checking */
+       if (!state->valid) {
+               pr_devel("%s: source %lx invalid !\n", __func__, irq);
+               return VM_FAULT_SIGBUS;
+       }
+
        kvmppc_xive_select_irq(state, &hw_num, &xd);
 
        arch_spin_lock(&sb->lock);