diff options
author | WANG Xuerui <git@xen0n.name> | 2023-05-01 12:19:27 +0300 |
---|---|---|
committer | Huacai Chen <chenhuacai@loongson.cn> | 2023-05-01 12:19:27 +0300 |
commit | 98b90ede59472de5931b7e4d72c3ff948eaa19a4 (patch) | |
tree | c600622d80165cd026500e77625b798764408dd1 /arch | |
parent | 5e3e784d35c41ca21251f92c243780c791100b02 (diff) | |
download | linux-98b90ede59472de5931b7e4d72c3ff948eaa19a4.tar.xz |
LoongArch: Humanize the ESTAT line when showing registers
Example output looks like:
[ xx.xxxxxx] ESTAT: 00001000 [INT] (IS=12 ECode=0 EsubCode=0)
Signed-off-by: WANG Xuerui <git@xen0n.name>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/loongarch/kernel/traps.c | 82 |
1 files changed, 75 insertions, 7 deletions
diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c index 6376997f2ae9..748fe2f9aed0 100644 --- a/arch/loongarch/kernel/traps.c +++ b/arch/loongarch/kernel/traps.c @@ -234,11 +234,83 @@ static void print_ecfg(unsigned long x) pr_cont(" VS=%d)\n", (int) FIELD_GET(CSR_ECFG_VS, x)); } +static const char *humanize_exc_name(unsigned int ecode, unsigned int esubcode) +{ + /* + * LoongArch users and developers are probably more familiar with + * those names found in the ISA manual, so we are going to print out + * the latter. This will require some mapping. + */ + switch (ecode) { + case EXCCODE_RSV: return "INT"; + case EXCCODE_TLBL: return "PIL"; + case EXCCODE_TLBS: return "PIS"; + case EXCCODE_TLBI: return "PIF"; + case EXCCODE_TLBM: return "PME"; + case EXCCODE_TLBNR: return "PNR"; + case EXCCODE_TLBNX: return "PNX"; + case EXCCODE_TLBPE: return "PPI"; + case EXCCODE_ADE: + switch (esubcode) { + case EXSUBCODE_ADEF: return "ADEF"; + case EXSUBCODE_ADEM: return "ADEM"; + } + break; + case EXCCODE_ALE: return "ALE"; + case EXCCODE_BCE: return "BCE"; + case EXCCODE_SYS: return "SYS"; + case EXCCODE_BP: return "BRK"; + case EXCCODE_INE: return "INE"; + case EXCCODE_IPE: return "IPE"; + case EXCCODE_FPDIS: return "FPD"; + case EXCCODE_LSXDIS: return "SXD"; + case EXCCODE_LASXDIS: return "ASXD"; + case EXCCODE_FPE: + switch (esubcode) { + case EXCSUBCODE_FPE: return "FPE"; + case EXCSUBCODE_VFPE: return "VFPE"; + } + break; + case EXCCODE_WATCH: + switch (esubcode) { + case EXCSUBCODE_WPEF: return "WPEF"; + case EXCSUBCODE_WPEM: return "WPEM"; + } + break; + case EXCCODE_BTDIS: return "BTD"; + case EXCCODE_BTE: return "BTE"; + case EXCCODE_GSPR: return "GSPR"; + case EXCCODE_HVC: return "HVC"; + case EXCCODE_GCM: + switch (esubcode) { + case EXCSUBCODE_GCSC: return "GCSC"; + case EXCSUBCODE_GCHC: return "GCHC"; + } + break; + /* + * The manual did not mention the EXCCODE_SE case, but print out it + * nevertheless. + */ + case EXCCODE_SE: return "SE"; + } + + return "???"; +} + +static void print_estat(unsigned long x) +{ + unsigned int ecode = FIELD_GET(CSR_ESTAT_EXC, x); + unsigned int esubcode = FIELD_GET(CSR_ESTAT_ESUBCODE, x); + + printk("ESTAT: %08lx [%s] (", x, humanize_exc_name(ecode, esubcode)); + print_intr_fragment("IS", FIELD_GET(CSR_ESTAT_IS, x)); + pr_cont(" ECode=%d EsubCode=%d)\n", (int) ecode, (int) esubcode); +} + static void __show_regs(const struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); - unsigned int excsubcode; - unsigned int exccode; + unsigned int exccode = FIELD_GET(CSR_ESTAT_EXC, regs->csr_estat); show_regs_print_info(KERN_DEFAULT); @@ -279,11 +351,7 @@ static void __show_regs(const struct pt_regs *regs) print_prmd(regs->csr_prmd); print_euen(regs->csr_euen); print_ecfg(regs->csr_ecfg); - printk("ESTAT: %08lx\n", regs->csr_estat); - - exccode = ((regs->csr_estat) & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT; - excsubcode = ((regs->csr_estat) & CSR_ESTAT_ESUBCODE) >> CSR_ESTAT_ESUBCODE_SHIFT; - printk("ExcCode : %x (SubCode %x)\n", exccode, excsubcode); + print_estat(regs->csr_estat); if (exccode >= EXCCODE_TLBL && exccode <= EXCCODE_ALE) printk("BadVA : %0*lx\n", field, regs->csr_badvaddr); |