]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'powerpc-5.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 Feb 2020 23:57:56 +0000 (15:57 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 Feb 2020 23:57:56 +0000 (15:57 -0800)
Pull powerpc fixes from Michael Ellerman:
 "Some more powerpc fixes for 5.6. This is two weeks worth as I was out
  sick last week:

   - Three fixes for the recently added VMAP_STACK on 32-bit.

   - Three fixes related to hugepages on 8xx (32-bit).

   - A fix for a bug in our transactional memory handling that could
     lead to a kernel crash if we saw a page fault during signal
     delivery.

   - A fix for a deadlock in our PCI EEH (Enhanced Error Handling) code.

   - A couple of other minor fixes.

  Thanks to: Christophe Leroy, Erhard F, Frederic Barrat, Gustavo Luiz
  Duarte, Larry Finger, Leonardo Bras, Oliver O'Halloran, Sam Bobroff"

* tag 'powerpc-5.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/entry: Fix an #if which should be an #ifdef in entry_32.S
  powerpc/xmon: Fix whitespace handling in getstring()
  powerpc/6xx: Fix power_save_ppc32_restore() with CONFIG_VMAP_STACK
  powerpc/chrp: Fix enter_rtas() with CONFIG_VMAP_STACK
  powerpc/32s: Fix DSI and ISI exceptions for CONFIG_VMAP_STACK
  powerpc/tm: Fix clearing MSR[TS] in current when reclaiming on signal delivery
  powerpc/8xx: Fix clearing of bits 20-23 in ITLB miss
  powerpc/hugetlb: Fix 8M hugepages on 8xx
  powerpc/hugetlb: Fix 512k hugepages on 8xx with 16k page size
  powerpc/eeh: Fix deadlock handling dead PHB

17 files changed:
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/head_32.h
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/idle_6xx.S
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/mm/book3s32/hash_low.S
arch/powerpc/mm/book3s32/mmu.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/kasan/kasan_init_32.c
arch/powerpc/xmon/xmon.c

index 86332080399a57d461c3a0efbd1ac2b3debeb9ab..080a0bf8e54bb9cd6267e38adacb2dc15150b401 100644 (file)
@@ -295,8 +295,13 @@ static inline bool pfn_valid(unsigned long pfn)
 /*
  * Some number of bits at the level of the page table that points to
  * a hugepte are used to encode the size.  This masks those bits.
+ * On 8xx, HW assistance requires 4k alignment for the hugepte.
  */
+#ifdef CONFIG_PPC_8xx
+#define HUGEPD_SHIFT_MASK     0xfff
+#else
 #define HUGEPD_SHIFT_MASK     0x3f
+#endif
 
 #ifndef __ASSEMBLY__
 
index 8387698bd5b629692fc676143e39202ed7b47f66..eedcbfb9a6ff38d874b027c2d639519b83ebba24 100644 (file)
@@ -168,6 +168,10 @@ struct thread_struct {
        unsigned long   srr1;
        unsigned long   dar;
        unsigned long   dsisr;
+#ifdef CONFIG_PPC_BOOK3S_32
+       unsigned long   r0, r3, r4, r5, r6, r8, r9, r11;
+       unsigned long   lr, ctr;
+#endif
 #endif
        /* Debug Registers */
        struct debug_reg debug;
index c25e562f1cd9d3f1d4fdf93b70bc2f698c2c4427..fcf24a365fc014b0490c957a16c8a9bfd55fc2fd 100644 (file)
@@ -132,6 +132,18 @@ int main(void)
        OFFSET(SRR1, thread_struct, srr1);
        OFFSET(DAR, thread_struct, dar);
        OFFSET(DSISR, thread_struct, dsisr);
+#ifdef CONFIG_PPC_BOOK3S_32
+       OFFSET(THR0, thread_struct, r0);
+       OFFSET(THR3, thread_struct, r3);
+       OFFSET(THR4, thread_struct, r4);
+       OFFSET(THR5, thread_struct, r5);
+       OFFSET(THR6, thread_struct, r6);
+       OFFSET(THR8, thread_struct, r8);
+       OFFSET(THR9, thread_struct, r9);
+       OFFSET(THR11, thread_struct, r11);
+       OFFSET(THLR, thread_struct, lr);
+       OFFSET(THCTR, thread_struct, ctr);
+#endif
 #endif
 #ifdef CONFIG_SPE
        OFFSET(THREAD_EVR0, thread_struct, evr[0]);
index a1eaffe868de4d76cbb8c401ddb175671e336ef4..7b048cee767c746fefe8a75cb991fb94fe757164 100644 (file)
@@ -1184,6 +1184,17 @@ void eeh_handle_special_event(void)
                        eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
                        eeh_handle_normal_event(pe);
                } else {
+                       eeh_for_each_pe(pe, tmp_pe)
+                               eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
+                                       edev->mode &= ~EEH_DEV_NO_HANDLER;
+
+                       /* Notify all devices to be down */
+                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
+                       eeh_set_channel_state(pe, pci_channel_io_perm_failure);
+                       eeh_pe_report(
+                               "error_detected(permanent failure)", pe,
+                               eeh_report_failure, NULL);
+
                        pci_lock_rescan_remove();
                        list_for_each_entry(hose, &hose_list, list_node) {
                                phb_pe = eeh_phb_pe_get(hose);
@@ -1192,16 +1203,6 @@ void eeh_handle_special_event(void)
                                    (phb_pe->state & EEH_PE_RECOVERING))
                                        continue;
 
-                               eeh_for_each_pe(pe, tmp_pe)
-                                       eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
-                                               edev->mode &= ~EEH_DEV_NO_HANDLER;
-
-                               /* Notify all devices to be down */
-                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
-                               eeh_set_channel_state(pe, pci_channel_io_perm_failure);
-                               eeh_pe_report(
-                                       "error_detected(permanent failure)", pe,
-                                       eeh_report_failure, NULL);
                                bus = eeh_pe_bus_get(phb_pe);
                                if (!bus) {
                                        pr_err("%s: Cannot find PCI bus for "
index 0713daa651d9e469b2acedfea00d15f12ce6be70..16af0d8d90a8641ae2d43b29cef9d691a08f06e2 100644 (file)
@@ -783,7 +783,7 @@ fast_exception_return:
 1:     lis     r3,exc_exit_restart_end@ha
        addi    r3,r3,exc_exit_restart_end@l
        cmplw   r12,r3
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
        bge     2b
 #else
        bge     3f
@@ -791,7 +791,7 @@ fast_exception_return:
        lis     r4,exc_exit_restart@ha
        addi    r4,r4,exc_exit_restart@l
        cmplw   r12,r4
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
        blt     2b
 #else
        blt     3f
@@ -1354,12 +1354,17 @@ _GLOBAL(enter_rtas)
        mtspr   SPRN_SRR0,r8
        mtspr   SPRN_SRR1,r9
        RFI
-1:     tophys(r9,r1)
+1:     tophys_novmstack r9, r1
+#ifdef CONFIG_VMAP_STACK
+       li      r0, MSR_KERNEL & ~MSR_IR        /* can take DTLB miss */
+       mtmsr   r0
+       isync
+#endif
        lwz     r8,INT_FRAME_SIZE+4(r9) /* get return address */
        lwz     r9,8(r9)        /* original msr value */
        addi    r1,r1,INT_FRAME_SIZE
        li      r0,0
-       tophys(r7, r2)
+       tophys_novmstack r7, r2
        stw     r0, THREAD + RTAS_SP(r7)
        mtspr   SPRN_SRR0,r8
        mtspr   SPRN_SRR1,r9
index 0493fcac6409508394932ea267e2f28c2f690f32..97c887950c3ca19d3156b8cc1e7aca6ceaef79f7 100644 (file)
@@ -290,17 +290,55 @@ MachineCheck:
 7:     EXCEPTION_PROLOG_2
        addi    r3,r1,STACK_FRAME_OVERHEAD
 #ifdef CONFIG_PPC_CHRP
-       bne     cr1,1f
+#ifdef CONFIG_VMAP_STACK
+       mfspr   r4, SPRN_SPRG_THREAD
+       tovirt(r4, r4)
+       lwz     r4, RTAS_SP(r4)
+       cmpwi   cr1, r4, 0
 #endif
-       EXC_XFER_STD(0x200, machine_check_exception)
-#ifdef CONFIG_PPC_CHRP
-1:     b       machine_check_in_rtas
+       beq     cr1, machine_check_tramp
+       b       machine_check_in_rtas
+#else
+       b       machine_check_tramp
 #endif
 
 /* Data access exception. */
        . = 0x300
        DO_KVM  0x300
 DataAccess:
+#ifdef CONFIG_VMAP_STACK
+       mtspr   SPRN_SPRG_SCRATCH0,r10
+       mfspr   r10, SPRN_SPRG_THREAD
+BEGIN_MMU_FTR_SECTION
+       stw     r11, THR11(r10)
+       mfspr   r10, SPRN_DSISR
+       mfcr    r11
+#ifdef CONFIG_PPC_KUAP
+       andis.  r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH | DSISR_PROTFAULT)@h
+#else
+       andis.  r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
+#endif
+       mfspr   r10, SPRN_SPRG_THREAD
+       beq     hash_page_dsi
+.Lhash_page_dsi_cont:
+       mtcr    r11
+       lwz     r11, THR11(r10)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+       mtspr   SPRN_SPRG_SCRATCH1,r11
+       mfspr   r11, SPRN_DAR
+       stw     r11, DAR(r10)
+       mfspr   r11, SPRN_DSISR
+       stw     r11, DSISR(r10)
+       mfspr   r11, SPRN_SRR0
+       stw     r11, SRR0(r10)
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+       stw     r11, SRR1(r10)
+       mfcr    r10
+       andi.   r11, r11, MSR_PR
+
+       EXCEPTION_PROLOG_1
+       b       handle_page_fault_tramp_1
+#else  /* CONFIG_VMAP_STACK */
        EXCEPTION_PROLOG handle_dar_dsisr=1
        get_and_save_dar_dsisr_on_stack r4, r5, r11
 BEGIN_MMU_FTR_SECTION
@@ -316,11 +354,32 @@ BEGIN_MMU_FTR_SECTION
 FTR_SECTION_ELSE
        b       handle_page_fault_tramp_2
 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
+#endif /* CONFIG_VMAP_STACK */
 
 /* Instruction access exception. */
        . = 0x400
        DO_KVM  0x400
 InstructionAccess:
+#ifdef CONFIG_VMAP_STACK
+       mtspr   SPRN_SPRG_SCRATCH0,r10
+       mtspr   SPRN_SPRG_SCRATCH1,r11
+       mfspr   r10, SPRN_SPRG_THREAD
+       mfspr   r11, SPRN_SRR0
+       stw     r11, SRR0(r10)
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+       stw     r11, SRR1(r10)
+       mfcr    r10
+BEGIN_MMU_FTR_SECTION
+       andis.  r11, r11, SRR1_ISI_NOPT@h       /* no pte found? */
+       bne     hash_page_isi
+.Lhash_page_isi_cont:
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+       andi.   r11, r11, MSR_PR
+
+       EXCEPTION_PROLOG_1
+       EXCEPTION_PROLOG_2
+#else  /* CONFIG_VMAP_STACK */
        EXCEPTION_PROLOG
        andis.  r0,r9,SRR1_ISI_NOPT@h   /* no pte found? */
        beq     1f                      /* if so, try to put a PTE */
@@ -329,6 +388,7 @@ InstructionAccess:
 BEGIN_MMU_FTR_SECTION
        bl      hash_page
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif /* CONFIG_VMAP_STACK */
 1:     mr      r4,r12
        andis.  r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
        stw     r4, _DAR(r11)
@@ -344,7 +404,7 @@ Alignment:
        EXCEPTION_PROLOG handle_dar_dsisr=1
        save_dar_dsisr_on_stack r4, r5, r11
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_STD(0x600, alignment_exception)
+       b       alignment_exception_tramp
 
 /* Program check exception */
        EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
@@ -645,15 +705,100 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
 
        . = 0x3000
 
+machine_check_tramp:
+       EXC_XFER_STD(0x200, machine_check_exception)
+
+alignment_exception_tramp:
+       EXC_XFER_STD(0x600, alignment_exception)
+
 handle_page_fault_tramp_1:
+#ifdef CONFIG_VMAP_STACK
+       EXCEPTION_PROLOG_2 handle_dar_dsisr=1
+#endif
        lwz     r4, _DAR(r11)
        lwz     r5, _DSISR(r11)
        /* fall through */
 handle_page_fault_tramp_2:
        EXC_XFER_LITE(0x300, handle_page_fault)
 
+#ifdef CONFIG_VMAP_STACK
+.macro save_regs_thread                thread
+       stw     r0, THR0(\thread)
+       stw     r3, THR3(\thread)
+       stw     r4, THR4(\thread)
+       stw     r5, THR5(\thread)
+       stw     r6, THR6(\thread)
+       stw     r8, THR8(\thread)
+       stw     r9, THR9(\thread)
+       mflr    r0
+       stw     r0, THLR(\thread)
+       mfctr   r0
+       stw     r0, THCTR(\thread)
+.endm
+
+.macro restore_regs_thread     thread
+       lwz     r0, THLR(\thread)
+       mtlr    r0
+       lwz     r0, THCTR(\thread)
+       mtctr   r0
+       lwz     r0, THR0(\thread)
+       lwz     r3, THR3(\thread)
+       lwz     r4, THR4(\thread)
+       lwz     r5, THR5(\thread)
+       lwz     r6, THR6(\thread)
+       lwz     r8, THR8(\thread)
+       lwz     r9, THR9(\thread)
+.endm
+
+hash_page_dsi:
+       save_regs_thread        r10
+       mfdsisr r3
+       mfdar   r4
+       mfsrr0  r5
+       mfsrr1  r9
+       rlwinm  r3, r3, 32 - 15, _PAGE_RW       /* DSISR_STORE -> _PAGE_RW */
+       bl      hash_page
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       b       .Lhash_page_dsi_cont
+
+hash_page_isi:
+       mr      r11, r10
+       mfspr   r10, SPRN_SPRG_THREAD
+       save_regs_thread        r10
+       li      r3, 0
+       lwz     r4, SRR0(r10)
+       lwz     r9, SRR1(r10)
+       bl      hash_page
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       mr      r10, r11
+       b       .Lhash_page_isi_cont
+
+       .globl fast_hash_page_return
+fast_hash_page_return:
+       andis.  r10, r9, SRR1_ISI_NOPT@h        /* Set on ISI, cleared on DSI */
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       bne     1f
+
+       /* DSI */
+       mtcr    r11
+       lwz     r11, THR11(r10)
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       SYNC
+       RFI
+
+1:     /* ISI */
+       mtcr    r11
+       mfspr   r11, SPRN_SPRG_SCRATCH1
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       SYNC
+       RFI
+
 stack_overflow:
        vmap_stack_overflow_exception
+#endif
 
 AltiVecUnavailable:
        EXCEPTION_PROLOG
index a6a5fbbf8504ae3cd5d5104076cec9358873dabb..9db162f79fe6e650fd61be32dd80bda9ea844f08 100644 (file)
 .endm
 
 .macro EXCEPTION_PROLOG_2 handle_dar_dsisr=0
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       mtcr    r10
+FTR_SECTION_ELSE
+       stw     r10, _CCR(r11)
+ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
+#else
        stw     r10,_CCR(r11)           /* save registers */
+#endif
+       mfspr   r10, SPRN_SPRG_SCRATCH0
        stw     r12,GPR12(r11)
        stw     r9,GPR9(r11)
-       mfspr   r10,SPRN_SPRG_SCRATCH0
        stw     r10,GPR10(r11)
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       mfcr    r10
+       stw     r10, _CCR(r11)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif
        mfspr   r12,SPRN_SPRG_SCRATCH1
        stw     r12,GPR11(r11)
        mflr    r10
        stw     r10, _DSISR(r11)
        .endif
        lwz     r9, SRR1(r12)
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       andi.   r10, r9, MSR_PR
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif
        lwz     r12, SRR0(r12)
 #else
        mfspr   r12,SPRN_SRR0
index 9922306ae51244f9dcd0ed1f2f3ffac4603aabee..073a651787df8ab65847aa428fa1d9216d57a231 100644 (file)
@@ -256,7 +256,7 @@ InstructionTLBMiss:
         * set.  All other Linux PTE bits control the behavior
         * of the MMU.
         */
-       rlwimi  r10, r10, 0, 0x0f00     /* Clear bits 20-23 */
+       rlwinm  r10, r10, 0, ~0x0f00    /* Clear bits 20-23 */
        rlwimi  r10, r10, 4, 0x0400     /* Copy _PAGE_EXEC into bit 21 */
        ori     r10, r10, RPN_PATTERN | 0x200 /* Set 22 and 24-27 */
        mtspr   SPRN_MI_RPN, r10        /* Update TLB entry */
index 0ffdd18b9f268b2b75f3c305505deb89fb6d09de..433d97bea1f3b8eb2e7554c317c9600a41d53b08 100644 (file)
@@ -166,7 +166,11 @@ BEGIN_FTR_SECTION
        mfspr   r9,SPRN_HID0
        andis.  r9,r9,HID0_NAP@h
        beq     1f
+#ifdef CONFIG_VMAP_STACK
+       addis   r9, r11, nap_save_msscr0@ha
+#else
        addis   r9,r11,(nap_save_msscr0-KERNELBASE)@ha
+#endif
        lwz     r9,nap_save_msscr0@l(r9)
        mtspr   SPRN_MSSCR0, r9
        sync
@@ -174,7 +178,11 @@ BEGIN_FTR_SECTION
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
 BEGIN_FTR_SECTION
+#ifdef CONFIG_VMAP_STACK
+       addis   r9, r11, nap_save_hid1@ha
+#else
        addis   r9,r11,(nap_save_hid1-KERNELBASE)@ha
+#endif
        lwz     r9,nap_save_hid1@l(r9)
        mtspr   SPRN_HID1, r9
 END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
index e6c30cee6abf1748e52fe5a4ae9a0fbc01c3274a..d215f95545537ababac1eb849baab01df0e1642a 100644 (file)
@@ -200,14 +200,27 @@ unsigned long get_tm_stackpointer(struct task_struct *tsk)
         * normal/non-checkpointed stack pointer.
         */
 
+       unsigned long ret = tsk->thread.regs->gpr[1];
+
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        BUG_ON(tsk != current);
 
        if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+               preempt_disable();
                tm_reclaim_current(TM_CAUSE_SIGNAL);
                if (MSR_TM_TRANSACTIONAL(tsk->thread.regs->msr))
-                       return tsk->thread.ckpt_regs.gpr[1];
+                       ret = tsk->thread.ckpt_regs.gpr[1];
+
+               /*
+                * If we treclaim, we must clear the current thread's TM bits
+                * before re-enabling preemption. Otherwise we might be
+                * preempted and have the live MSR[TS] changed behind our back
+                * (tm_recheckpoint_new_task() would recheckpoint). Besides, we
+                * enter the signal handler in non-transactional state.
+                */
+               tsk->thread.regs->msr &= ~MSR_TS_MASK;
+               preempt_enable();
        }
 #endif
-       return tsk->thread.regs->gpr[1];
+       return ret;
 }
index 98600b276f764d957fe5f8d91386c921a288cc90..1b090a76b4444729c4b8614b72277c1643539e92 100644 (file)
@@ -489,19 +489,11 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
  */
 static int save_tm_user_regs(struct pt_regs *regs,
                             struct mcontext __user *frame,
-                            struct mcontext __user *tm_frame, int sigret)
+                            struct mcontext __user *tm_frame, int sigret,
+                            unsigned long msr)
 {
-       unsigned long msr = regs->msr;
-
        WARN_ON(tm_suspend_disabled);
 
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state.  This also ensures
-        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-        */
-       regs->msr &= ~MSR_TS_MASK;
-
        /* Save both sets of general registers */
        if (save_general_regs(&current->thread.ckpt_regs, frame)
            || save_general_regs(regs, tm_frame))
@@ -912,6 +904,10 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
        int sigret;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -944,13 +940,13 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_frame = &rt_sf->uc_transact.uc_mcontext;
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                if (__put_user((unsigned long)&rt_sf->uc_transact,
                               &rt_sf->uc.uc_link) ||
                    __put_user((unsigned long)tm_frame,
                               &rt_sf->uc_transact.uc_regs))
                        goto badframe;
-               if (save_tm_user_regs(regs, frame, tm_frame, sigret))
+               if (save_tm_user_regs(regs, frame, tm_frame, sigret, msr))
                        goto badframe;
        }
        else
@@ -1369,6 +1365,10 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
        int sigret;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -1402,9 +1402,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_mctx = &frame->mctx_transact;
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact,
-                                     sigret))
+                                     sigret, msr))
                        goto badframe;
        }
        else
index 117515564ec7a6e2d13ecdeba37e3973934fba10..84ed2e77ef9c3f5e039cf8f65921b5124e0bb226 100644 (file)
@@ -192,7 +192,8 @@ static long setup_sigcontext(struct sigcontext __user *sc,
 static long setup_tm_sigcontexts(struct sigcontext __user *sc,
                                 struct sigcontext __user *tm_sc,
                                 struct task_struct *tsk,
-                                int signr, sigset_t *set, unsigned long handler)
+                                int signr, sigset_t *set, unsigned long handler,
+                                unsigned long msr)
 {
        /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the
         * process never used altivec yet (MSR_VEC is zero in pt_regs of
@@ -207,12 +208,11 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
        elf_vrreg_t __user *tm_v_regs = sigcontext_vmx_regs(tm_sc);
 #endif
        struct pt_regs *regs = tsk->thread.regs;
-       unsigned long msr = tsk->thread.regs->msr;
        long err = 0;
 
        BUG_ON(tsk != current);
 
-       BUG_ON(!MSR_TM_ACTIVE(regs->msr));
+       BUG_ON(!MSR_TM_ACTIVE(msr));
 
        WARN_ON(tm_suspend_disabled);
 
@@ -222,13 +222,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
         */
        msr |= tsk->thread.ckpt_regs.msr & (MSR_FP | MSR_VEC | MSR_VSX);
 
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state.  This also ensures
-        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-        */
-       regs->msr &= ~MSR_TS_MASK;
-
 #ifdef CONFIG_ALTIVEC
        err |= __put_user(v_regs, &sc->v_regs);
        err |= __put_user(tm_v_regs, &tm_sc->v_regs);
@@ -824,6 +817,10 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        unsigned long newsp = 0;
        long err = 0;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -841,7 +838,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        err |= __put_user(0, &frame->uc.uc_flags);
        err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]);
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                /* The ucontext_t passed to userland points to the second
                 * ucontext_t (for transactional state) with its uc_link ptr.
                 */
@@ -849,7 +846,8 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
                err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
                                            &frame->uc_transact.uc_mcontext,
                                            tsk, ksig->sig, NULL,
-                                           (unsigned long)ksig->ka.sa.sa_handler);
+                                           (unsigned long)ksig->ka.sa.sa_handler,
+                                           msr);
        } else
 #endif
        {
index c11b0a005196675271839c20a9a0c89cf2253f13..2015c4f962380940700d84bcc32af9d4961b80ea 100644 (file)
 #include <asm/feature-fixups.h>
 #include <asm/code-patching-asm.h>
 
-#ifdef CONFIG_VMAP_STACK
-#define ADDR_OFFSET    0
-#else
-#define ADDR_OFFSET    PAGE_OFFSET
-#endif
-
 #ifdef CONFIG_SMP
        .section .bss
        .align  2
@@ -53,8 +47,8 @@ mmu_hash_lock:
        .text
 _GLOBAL(hash_page)
 #ifdef CONFIG_SMP
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@h
-       ori     r8, r8, (mmu_hash_lock - ADDR_OFFSET)@l
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@h
+       ori     r8, r8, (mmu_hash_lock - PAGE_OFFSET)@l
        lis     r0,0x0fff
        b       10f
 11:    lwz     r6,0(r8)
@@ -72,12 +66,9 @@ _GLOBAL(hash_page)
        cmplw   0,r4,r0
        ori     r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
        mfspr   r5, SPRN_SPRG_PGDIR     /* phys page-table root */
-#ifdef CONFIG_VMAP_STACK
-       tovirt(r5, r5)
-#endif
        blt+    112f                    /* assume user more likely */
-       lis     r5, (swapper_pg_dir - ADDR_OFFSET)@ha   /* if kernel address, use */
-       addi    r5 ,r5 ,(swapper_pg_dir - ADDR_OFFSET)@l        /* kernel page table */
+       lis     r5, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
+       addi    r5 ,r5 ,(swapper_pg_dir - PAGE_OFFSET)@l        /* kernel page table */
        rlwimi  r3,r9,32-12,29,29       /* MSR_PR -> _PAGE_USER */
 112:
 #ifndef CONFIG_PTE_64BIT
@@ -89,9 +80,6 @@ _GLOBAL(hash_page)
        lwzx    r8,r8,r5                /* Get L1 entry */
        rlwinm. r8,r8,0,0,20            /* extract pt base address */
 #endif
-#ifdef CONFIG_VMAP_STACK
-       tovirt(r8, r8)
-#endif
 #ifdef CONFIG_SMP
        beq-    hash_page_out           /* return if no mapping */
 #else
@@ -143,30 +131,36 @@ retry:
        bne-    retry                   /* retry if someone got there first */
 
        mfsrin  r3,r4                   /* get segment reg for segment */
+#ifndef CONFIG_VMAP_STACK
        mfctr   r0
        stw     r0,_CTR(r11)
+#endif
        bl      create_hpte             /* add the hash table entry */
 
 #ifdef CONFIG_SMP
        eieio
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@ha
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@ha
        li      r0,0
-       stw     r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
+       stw     r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
 #endif
 
+#ifdef CONFIG_VMAP_STACK
+       b       fast_hash_page_return
+#else
        /* Return from the exception */
        lwz     r5,_CTR(r11)
        mtctr   r5
        lwz     r0,GPR0(r11)
        lwz     r8,GPR8(r11)
        b       fast_exception_return
+#endif
 
 #ifdef CONFIG_SMP
 hash_page_out:
        eieio
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@ha
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@ha
        li      r0,0
-       stw     r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
+       stw     r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
        blr
 #endif /* CONFIG_SMP */
 
@@ -341,7 +335,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        patch_site      1f, patch__hash_page_A1
        patch_site      2f, patch__hash_page_A2
        /* Get the address of the primary PTE group in the hash table (r3) */
-0:     lis     r0, (Hash_base - ADDR_OFFSET)@h /* base address of hash table */
+0:     lis     r0, (Hash_base - PAGE_OFFSET)@h /* base address of hash table */
 1:     rlwimi  r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
 2:     rlwinm  r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
        xor     r3,r3,r0                /* make primary hash */
@@ -355,10 +349,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        beq+    10f                     /* no PTE: go look for an empty slot */
        tlbie   r4
 
-       lis     r4, (htab_hash_searches - ADDR_OFFSET)@ha
-       lwz     r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
+       lis     r4, (htab_hash_searches - PAGE_OFFSET)@ha
+       lwz     r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
        addi    r6,r6,1                 /* count how many searches we do */
-       stw     r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
+       stw     r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
 
        /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
        mtctr   r0
@@ -390,10 +384,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        beq+    found_empty
 
        /* update counter of times that the primary PTEG is full */
-       lis     r4, (primary_pteg_full - ADDR_OFFSET)@ha
-       lwz     r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
+       lis     r4, (primary_pteg_full - PAGE_OFFSET)@ha
+       lwz     r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
        addi    r6,r6,1
-       stw     r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
+       stw     r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
 
        patch_site      0f, patch__hash_page_C
        /* Search the secondary PTEG for an empty slot */
@@ -427,8 +421,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
         * lockup here but that shouldn't happen
         */
 
-1:     lis     r4, (next_slot - ADDR_OFFSET)@ha        /* get next evict slot */
-       lwz     r6, (next_slot - ADDR_OFFSET)@l(r4)
+1:     lis     r4, (next_slot - PAGE_OFFSET)@ha        /* get next evict slot */
+       lwz     r6, (next_slot - PAGE_OFFSET)@l(r4)
        addi    r6,r6,HPTE_SIZE                 /* search for candidate */
        andi.   r6,r6,7*HPTE_SIZE
        stw     r6,next_slot@l(r4)
index 0a1c65a2c56553cf36836af6bc30ef2424489980..f888cbb109b9134daee3176b37988b250ef008f5 100644 (file)
@@ -413,7 +413,7 @@ void __init MMU_init_hw(void)
 void __init MMU_init_hw_patch(void)
 {
        unsigned int hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
-       unsigned int hash;
+       unsigned int hash = (unsigned int)Hash - PAGE_OFFSET;
 
        if (ppc_md.progress)
                ppc_md.progress("hash:patch", 0x345);
@@ -425,11 +425,6 @@ void __init MMU_init_hw_patch(void)
        /*
         * Patch up the instructions in hashtable.S:create_hpte
         */
-       if (IS_ENABLED(CONFIG_VMAP_STACK))
-               hash = (unsigned int)Hash;
-       else
-               hash = (unsigned int)Hash - PAGE_OFFSET;
-
        modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__hash_page_A1, 0x7c0, hash_mb << 6);
        modify_instruction_site(&patch__hash_page_A2, 0x7c0, hash_mb2 << 6);
@@ -439,8 +434,7 @@ void __init MMU_init_hw_patch(void)
        /*
         * Patch up the instructions in hashtable.S:flush_hash_page
         */
-       modify_instruction_site(&patch__flush_hash_A0, 0xffff,
-                               ((unsigned int)Hash - PAGE_OFFSET) >> 16);
+       modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__flush_hash_A1, 0x7c0, hash_mb << 6);
        modify_instruction_site(&patch__flush_hash_A2, 0x7c0, hash_mb2 << 6);
        modify_instruction_site(&patch__flush_hash_B, 0xffff, hmask);
index 73d4873fc7f85442eafc08399446bc176fd82b9a..33b3461d91e8db0e7b19f569a5c20d06a9a827be 100644 (file)
@@ -53,20 +53,24 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        if (pshift >= pdshift) {
                cachep = PGT_CACHE(PTE_T_ORDER);
                num_hugepd = 1 << (pshift - pdshift);
+               new = NULL;
        } else if (IS_ENABLED(CONFIG_PPC_8xx)) {
-               cachep = PGT_CACHE(PTE_INDEX_SIZE);
+               cachep = NULL;
                num_hugepd = 1;
+               new = pte_alloc_one(mm);
        } else {
                cachep = PGT_CACHE(pdshift - pshift);
                num_hugepd = 1;
+               new = NULL;
        }
 
-       if (!cachep) {
+       if (!cachep && !new) {
                WARN_ONCE(1, "No page table cache created for hugetlb tables");
                return -ENOMEM;
        }
 
-       new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
+       if (cachep)
+               new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
 
        BUG_ON(pshift > HUGEPD_SHIFT_MASK);
        BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -97,7 +101,10 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        if (i < num_hugepd) {
                for (i = i - 1 ; i >= 0; i--, hpdp--)
                        *hpdp = __hugepd(0);
-               kmem_cache_free(cachep, new);
+               if (cachep)
+                       kmem_cache_free(cachep, new);
+               else
+                       pte_free(mm, new);
        } else {
                kmemleak_ignore(new);
        }
@@ -324,8 +331,7 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
        if (shift >= pdshift)
                hugepd_free(tlb, hugepte);
        else if (IS_ENABLED(CONFIG_PPC_8xx))
-               pgtable_free_tlb(tlb, hugepte,
-                                get_hugepd_cache_index(PTE_INDEX_SIZE));
+               pgtable_free_tlb(tlb, hugepte, 0);
        else
                pgtable_free_tlb(tlb, hugepte,
                                 get_hugepd_cache_index(pdshift - shift));
@@ -639,12 +645,13 @@ static int __init hugetlbpage_init(void)
                 * if we have pdshift and shift value same, we don't
                 * use pgt cache for hugepd.
                 */
-               if (pdshift > shift && IS_ENABLED(CONFIG_PPC_8xx))
-                       pgtable_cache_add(PTE_INDEX_SIZE);
-               else if (pdshift > shift)
-                       pgtable_cache_add(pdshift - shift);
-               else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) || IS_ENABLED(CONFIG_PPC_8xx))
+               if (pdshift > shift) {
+                       if (!IS_ENABLED(CONFIG_PPC_8xx))
+                               pgtable_cache_add(pdshift - shift);
+               } else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) ||
+                          IS_ENABLED(CONFIG_PPC_8xx)) {
                        pgtable_cache_add(PTE_T_ORDER);
+               }
 
                configured = true;
        }
index 16dd95bd0749d851410fce5ae727a0e9edfdb563..db5664dde5ff9d9d6a461eb1ed25a2d0f11e3d8e 100644 (file)
@@ -185,8 +185,7 @@ u8 __initdata early_hash[256 << 10] __aligned(256 << 10) = {0};
 
 static void __init kasan_early_hash_table(void)
 {
-       unsigned int hash = IS_ENABLED(CONFIG_VMAP_STACK) ? (unsigned int)early_hash :
-                                                           __pa(early_hash);
+       unsigned int hash = __pa(early_hash);
 
        modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
index e8c84d265602bc57bf47b49243a2044d93f2336d..0ec9640335bb3544548bcf3c391b2dd946621f4b 100644 (file)
@@ -3435,6 +3435,11 @@ getstring(char *s, int size)
        int c;
 
        c = skipbl();
+       if (c == '\n') {
+               *s = 0;
+               return;
+       }
+
        do {
                if( size > 1 ){
                        *s++ = c;