Patch "powerpc/64s: Don't use DSISR for SLB faults" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    powerpc/64s: Don't use DSISR for SLB faults

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     powerpc-64s-don-t-use-dsisr-for-slb-faults.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit c570ad34483618428cb4592a6b0e8015c1177b56
Author: Michael Ellerman <mpe@xxxxxxxxxxxxxx>
Date:   Tue Feb 22 22:34:49 2022 +1100

    powerpc/64s: Don't use DSISR for SLB faults
    
    [ Upstream commit d4679ac8ea2e5078704aa1c026db36580cc1bf9a ]
    
    Since commit 46ddcb3950a2 ("powerpc/mm: Show if a bad page fault on data
    is read or write.") we use page_fault_is_write(regs->dsisr) in
    __bad_page_fault() to determine if the fault is for a read or write, and
    change the message printed accordingly.
    
    But SLB faults, aka Data Segment Interrupts, don't set DSISR (Data
    Storage Interrupt Status Register) to a useful value. All ISA versions
    from v2.03 through v3.1 specify that the Data Segment Interrupt sets
    DSISR "to an undefined value". As far as I can see there's no mention of
    SLB faults setting DSISR in any BookIV content either.
    
    This manifests as accesses that should be a read being incorrectly
    reported as writes, for example, using the xmon "dump" command:
    
      0:mon> d 0x5deadbeef0000000
      5deadbeef0000000
      [359526.415354][    C6] BUG: Unable to handle kernel data access on write at 0x5deadbeef0000000
      [359526.415611][    C6] Faulting instruction address: 0xc00000000010a300
      cpu 0x6: Vector: 380 (Data SLB Access) at [c00000000ffbf400]
          pc: c00000000010a300: mread+0x90/0x190
    
    If we disassemble the PC, we see a load instruction:
    
      0:mon> di c00000000010a300
      c00000000010a300 89490000      lbz     r10,0(r9)
    
    We can also see in exceptions-64s.S that the data_access_slb block
    doesn't set IDSISR=1, which means it doesn't load DSISR into pt_regs. So
    the value we're using to determine if the fault is a read/write is some
    stale value in pt_regs from a previous page fault.
    
    Rework the printing logic to separate the SLB fault case out, and only
    print read/write in the cases where we can determine it.
    
    The result looks like eg:
    
      0:mon> d 0x5deadbeef0000000
      5deadbeef0000000
      [  721.779525][    C6] BUG: Unable to handle kernel data access at 0x5deadbeef0000000
      [  721.779697][    C6] Faulting instruction address: 0xc00000000014cbe0
      cpu 0x6: Vector: 380 (Data SLB Access) at [c00000000ffbf390]
    
      0:mon> d 0
      0000000000000000
      [  742.793242][    C6] BUG: Kernel NULL pointer dereference at 0x00000000
      [  742.793316][    C6] Faulting instruction address: 0xc00000000014cbe0
      cpu 0x6: Vector: 380 (Data SLB Access) at [c00000000ffbf390]
    
    Fixes: 46ddcb3950a2 ("powerpc/mm: Show if a bad page fault on data is read or write.")
    Reported-by: Nageswara R Sastry <rnsastry@xxxxxxxxxxxxx>
    Signed-off-by: Michael Ellerman <mpe@xxxxxxxxxxxxxx>
    Reviewed-by: Nicholas Piggin <npiggin@xxxxxxxxx>
    Link: https://lore.kernel.org/r/20220222113449.319193-1-mpe@xxxxxxxxxxxxxx
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index a8d0ce85d39a..4a15172dfef2 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -568,18 +568,24 @@ NOKPROBE_SYMBOL(hash__do_page_fault);
 static void __bad_page_fault(struct pt_regs *regs, int sig)
 {
 	int is_write = page_fault_is_write(regs->dsisr);
+	const char *msg;
 
 	/* kernel has accessed a bad area */
 
+	if (regs->dar < PAGE_SIZE)
+		msg = "Kernel NULL pointer dereference";
+	else
+		msg = "Unable to handle kernel data access";
+
 	switch (TRAP(regs)) {
 	case INTERRUPT_DATA_STORAGE:
-	case INTERRUPT_DATA_SEGMENT:
 	case INTERRUPT_H_DATA_STORAGE:
-		pr_alert("BUG: %s on %s at 0x%08lx\n",
-			 regs->dar < PAGE_SIZE ? "Kernel NULL pointer dereference" :
-			 "Unable to handle kernel data access",
+		pr_alert("BUG: %s on %s at 0x%08lx\n", msg,
 			 is_write ? "write" : "read", regs->dar);
 		break;
+	case INTERRUPT_DATA_SEGMENT:
+		pr_alert("BUG: %s at 0x%08lx\n", msg, regs->dar);
+		break;
 	case INTERRUPT_INST_STORAGE:
 	case INTERRUPT_INST_SEGMENT:
 		pr_alert("BUG: Unable to handle kernel instruction fetch%s",



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux