Skip to content

Commit

Permalink
powerpc/traps: Enhance readability for trap types
Browse files Browse the repository at this point in the history
Define macros to list ppc interrupt types in interttupt.h, replace the
reference of the trap hex values with these macros.

Referred the hex numbers in arch/powerpc/kernel/exceptions-64e.S,
arch/powerpc/kernel/exceptions-64s.S, arch/powerpc/kernel/head_*.S,
arch/powerpc/kernel/head_booke.h and arch/powerpc/include/asm/kvm_asm.h.

Signed-off-by: Xiongwei Song <sxwjean@gmail.com>
[mpe: Resolve conflicts in nmi_disables_ftrace(), fix 40x build]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/1618398033-13025-1-git-send-email-sxwjean@me.com
  • Loading branch information
xwsong authored and mpe committed Apr 17, 2021
1 parent 7de21e6 commit 7153d4b
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 30 deletions.
52 changes: 48 additions & 4 deletions arch/powerpc/include/asm/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,50 @@
#include <asm/kprobes.h>
#include <asm/runlatch.h>

/* BookE/4xx */
#define INTERRUPT_CRITICAL_INPUT 0x100

/* BookE */
#define INTERRUPT_DEBUG 0xd00
#ifdef CONFIG_BOOKE
#define INTERRUPT_PERFMON 0x260
#define INTERRUPT_DOORBELL 0x280
#endif

/* BookS/4xx/8xx */
#define INTERRUPT_MACHINE_CHECK 0x200

/* BookS/8xx */
#define INTERRUPT_SYSTEM_RESET 0x100

/* BookS */
#define INTERRUPT_DATA_SEGMENT 0x380
#define INTERRUPT_INST_SEGMENT 0x480
#define INTERRUPT_TRACE 0xd00
#define INTERRUPT_H_DATA_STORAGE 0xe00
#define INTERRUPT_H_FAC_UNAVAIL 0xf80
#ifdef CONFIG_PPC_BOOK3S
#define INTERRUPT_DOORBELL 0xa00
#define INTERRUPT_PERFMON 0xf00
#endif

/* BookE/BookS/4xx/8xx */
#define INTERRUPT_DATA_STORAGE 0x300
#define INTERRUPT_INST_STORAGE 0x400
#define INTERRUPT_ALIGNMENT 0x600
#define INTERRUPT_PROGRAM 0x700
#define INTERRUPT_SYSCALL 0xc00

/* BookE/BookS/44x */
#define INTERRUPT_FP_UNAVAIL 0x800

/* BookE/BookS/44x/8xx */
#define INTERRUPT_DECREMENTER 0x900

#ifndef INTERRUPT_PERFMON
#define INTERRUPT_PERFMON 0x0
#endif

static inline void nap_adjust_return(struct pt_regs *regs)
{
#ifdef CONFIG_PPC_970_NAP
Expand Down Expand Up @@ -65,7 +109,7 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup
* CT_WARN_ON comes here via program_check_exception,
* so avoid recursion.
*/
if (TRAP(regs) != 0x700)
if (TRAP(regs) != INTERRUPT_PROGRAM)
CT_WARN_ON(ct_state() != CONTEXT_KERNEL);
}
#endif
Expand Down Expand Up @@ -131,13 +175,13 @@ static inline bool nmi_disables_ftrace(struct pt_regs *regs)
{
/* Allow DEC and PMI to be traced when they are soft-NMI */
if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
if (TRAP(regs) == 0x900)
if (TRAP(regs) == INTERRUPT_DECREMENTER)
return false;
if (TRAP(regs) == 0xf00)
if (TRAP(regs) == INTERRUPT_PERFMON)
return false;
}
if (IS_ENABLED(CONFIG_PPC_BOOK3E)) {
if (TRAP(regs) == 0x260)
if (TRAP(regs) == INTERRUPT_PERFMON)
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/fadump.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ void crash_fadump(struct pt_regs *regs, const char *str)
* If we came in via system reset, wait a while for the secondary
* CPUs to enter.
*/
if (TRAP(&(fdh->regs)) == 0x100) {
if (TRAP(&(fdh->regs)) == INTERRUPT_SYSTEM_RESET) {
msecs = CRASH_TIMEOUT;
while ((atomic_read(&cpus_in_fadump) < ncpus) && (--msecs > 0))
mdelay(1);
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs, unsign
* CT_WARN_ON comes here via program_check_exception,
* so avoid recursion.
*/
if (TRAP(regs) != 0x700)
if (TRAP(regs) != INTERRUPT_PROGRAM)
CT_WARN_ON(ct_state() == CONTEXT_USER);

kuap = kuap_get_and_assert_locked();
Expand Down
4 changes: 3 additions & 1 deletion arch/powerpc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -1467,7 +1467,9 @@ static void __show_regs(struct pt_regs *regs)
trap = TRAP(regs);
if (!trap_is_syscall(regs) && cpu_has_feature(CPU_FTR_CFAR))
pr_cont("CFAR: "REG" ", regs->orig_gpr3);
if (trap == 0x200 || trap == 0x300 || trap == 0x600) {
if (trap == INTERRUPT_MACHINE_CHECK ||
trap == INTERRUPT_DATA_STORAGE ||
trap == INTERRUPT_ALIGNMENT) {
if (IS_ENABLED(CONFIG_4xx) || IS_ENABLED(CONFIG_BOOKE))
pr_cont("DEAR: "REG" ESR: "REG" ", regs->dar, regs->dsisr);
else
Expand Down
6 changes: 3 additions & 3 deletions arch/powerpc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ static void oops_end(unsigned long flags, struct pt_regs *regs,
/*
* system_reset_excption handles debugger, crash dump, panic, for 0x100
*/
if (TRAP(regs) == 0x100)
if (TRAP(regs) == INTERRUPT_SYSTEM_RESET)
return;

crash_fadump(regs, "die oops");
Expand Down Expand Up @@ -289,7 +289,7 @@ void die(const char *str, struct pt_regs *regs, long err)
/*
* system_reset_excption handles debugger, crash dump, panic, for 0x100
*/
if (TRAP(regs) != 0x100) {
if (TRAP(regs) != INTERRUPT_SYSTEM_RESET) {
if (debugger(regs))
return;
}
Expand Down Expand Up @@ -1691,7 +1691,7 @@ DEFINE_INTERRUPT_HANDLER(facility_unavailable_exception)
u8 status;
bool hv;

hv = (TRAP(regs) == 0xf80);
hv = (TRAP(regs) == INTERRUPT_H_FAC_UNAVAIL);
if (hv)
value = mfspr(SPRN_HFSCR);
else
Expand Down
3 changes: 2 additions & 1 deletion arch/powerpc/kexec/crash.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <asm/smp.h>
#include <asm/setjmp.h>
#include <asm/debug.h>
#include <asm/interrupt.h>

/*
* The primary CPU waits a while for all secondary CPUs to enter. This is to
Expand Down Expand Up @@ -336,7 +337,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
* If we came in via system reset, wait a while for the secondary
* CPUs to enter.
*/
if (TRAP(regs) == 0x100)
if (TRAP(regs) == INTERRUPT_SYSTEM_RESET)
mdelay(PRIMARY_TIMEOUT);

crash_kexec_prepare_cpus(crashing_cpu);
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/mm/book3s64/hash_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)

/* page is dirty */
if (!test_bit(PG_dcache_clean, &page->flags) && !PageReserved(page)) {
if (trap == 0x400) {
if (trap == INTERRUPT_INST_STORAGE) {
flush_dcache_icache_page(page);
set_bit(PG_dcache_clean, &page->flags);
} else
Expand Down Expand Up @@ -1556,7 +1556,7 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault)
if (user_mode(regs) || (region_id == USER_REGION_ID))
access &= ~_PAGE_PRIVILEGED;

if (TRAP(regs) == 0x400)
if (TRAP(regs) == INTERRUPT_INST_STORAGE)
access |= _PAGE_EXEC;

err = hash_page_mm(mm, ea, access, TRAP(regs), flags);
Expand Down
16 changes: 8 additions & 8 deletions arch/powerpc/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr,
static bool bad_kernel_fault(struct pt_regs *regs, unsigned long error_code,
unsigned long address, bool is_write)
{
int is_exec = TRAP(regs) == 0x400;
int is_exec = TRAP(regs) == INTERRUPT_INST_STORAGE;

/* NX faults set DSISR_PROTFAULT on the 8xx, DSISR_NOEXEC_OR_G on others */
if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT |
Expand Down Expand Up @@ -391,7 +391,7 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address,
struct vm_area_struct * vma;
struct mm_struct *mm = current->mm;
unsigned int flags = FAULT_FLAG_DEFAULT;
int is_exec = TRAP(regs) == 0x400;
int is_exec = TRAP(regs) == INTERRUPT_INST_STORAGE;
int is_user = user_mode(regs);
int is_write = page_fault_is_write(error_code);
vm_fault_t fault, major = 0;
Expand Down Expand Up @@ -574,20 +574,20 @@ static void __bad_page_fault(struct pt_regs *regs, int sig)
/* kernel has accessed a bad area */

switch (TRAP(regs)) {
case 0x300:
case 0x380:
case 0xe00:
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",
is_write ? "write" : "read", regs->dar);
break;
case 0x400:
case 0x480:
case INTERRUPT_INST_STORAGE:
case INTERRUPT_INST_SEGMENT:
pr_alert("BUG: Unable to handle kernel instruction fetch%s",
regs->nip < PAGE_SIZE ? " (NULL pointer?)\n" : "\n");
break;
case 0x600:
case INTERRUPT_ALIGNMENT:
pr_alert("BUG: Unable to handle kernel unaligned access at 0x%08lx\n",
regs->dar);
break;
Expand Down
5 changes: 3 additions & 2 deletions arch/powerpc/perf/core-book3s.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <asm/firmware.h>
#include <asm/ptrace.h>
#include <asm/code-patching.h>
#include <asm/interrupt.h>

#ifdef CONFIG_PPC64
#include "internal.h"
Expand Down Expand Up @@ -168,7 +169,7 @@ static bool regs_use_siar(struct pt_regs *regs)
* they have not been setup using perf_read_regs() and so regs->result
* is something random.
*/
return ((TRAP(regs) == 0xf00) && regs->result);
return ((TRAP(regs) == INTERRUPT_PERFMON) && regs->result);
}

/*
Expand Down Expand Up @@ -347,7 +348,7 @@ static inline void perf_read_regs(struct pt_regs *regs)
* hypervisor samples as well as samples in the kernel with
* interrupts off hence the userspace check.
*/
if (TRAP(regs) != 0xf00)
if (TRAP(regs) != INTERRUPT_PERFMON)
use_siar = 0;
else if ((ppmu->flags & PPMU_NO_SIAR))
use_siar = 0;
Expand Down
20 changes: 13 additions & 7 deletions arch/powerpc/xmon/xmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include <asm/code-patching.h>
#include <asm/sections.h>
#include <asm/inst.h>
#include <asm/interrupt.h>

#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
Expand Down Expand Up @@ -605,7 +606,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
* debugger break (IPI). This is similar to
* crash_kexec_secondary().
*/
if (TRAP(regs) != 0x100 || !wait_for_other_cpus(ncpus))
if (TRAP(regs) != INTERRUPT_SYSTEM_RESET || !wait_for_other_cpus(ncpus))
smp_send_debugger_break();

wait_for_other_cpus(ncpus);
Expand All @@ -615,7 +616,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)

if (!locked_down) {
/* for breakpoint or single step, print curr insn */
if (bp || TRAP(regs) == 0xd00)
if (bp || TRAP(regs) == INTERRUPT_TRACE)
ppc_inst_dump(regs->nip, 1, 0);
printf("enter ? for help\n");
}
Expand Down Expand Up @@ -684,7 +685,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
disable_surveillance();
if (!locked_down) {
/* for breakpoint or single step, print current insn */
if (bp || TRAP(regs) == 0xd00)
if (bp || TRAP(regs) == INTERRUPT_TRACE)
ppc_inst_dump(regs->nip, 1, 0);
printf("enter ? for help\n");
}
Expand Down Expand Up @@ -1769,9 +1770,12 @@ static void excprint(struct pt_regs *fp)
printf(" sp: %lx\n", fp->gpr[1]);
printf(" msr: %lx\n", fp->msr);

if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
if (trap == INTERRUPT_DATA_STORAGE ||
trap == INTERRUPT_DATA_SEGMENT ||
trap == INTERRUPT_ALIGNMENT ||
trap == INTERRUPT_MACHINE_CHECK) {
printf(" dar: %lx\n", fp->dar);
if (trap != 0x380)
if (trap != INTERRUPT_DATA_SEGMENT)
printf(" dsisr: %lx\n", fp->dsisr);
}

Expand All @@ -1785,7 +1789,7 @@ static void excprint(struct pt_regs *fp)
current->pid, current->comm);
}

if (trap == 0x700)
if (trap == INTERRUPT_PROGRAM)
print_bug_trap(fp);

printf(linux_banner);
Expand Down Expand Up @@ -1837,7 +1841,9 @@ static void prregs(struct pt_regs *fp)
printf("ctr = "REG" xer = "REG" trap = %4lx\n",
fp->ctr, fp->xer, fp->trap);
trap = TRAP(fp);
if (trap == 0x300 || trap == 0x380 || trap == 0x600)
if (trap == INTERRUPT_DATA_STORAGE ||
trap == INTERRUPT_DATA_SEGMENT ||
trap == INTERRUPT_ALIGNMENT)
printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
}

Expand Down

0 comments on commit 7153d4b

Please sign in to comment.