Skip to content

Commit 98b90ed

Browse files
xen0nchenhuacai
authored andcommitted
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>
1 parent 5e3e784 commit 98b90ed

1 file changed

Lines changed: 75 additions & 7 deletions

File tree

arch/loongarch/kernel/traps.c

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,83 @@ static void print_ecfg(unsigned long x)
234234
pr_cont(" VS=%d)\n", (int) FIELD_GET(CSR_ECFG_VS, x));
235235
}
236236

237+
static const char *humanize_exc_name(unsigned int ecode, unsigned int esubcode)
238+
{
239+
/*
240+
* LoongArch users and developers are probably more familiar with
241+
* those names found in the ISA manual, so we are going to print out
242+
* the latter. This will require some mapping.
243+
*/
244+
switch (ecode) {
245+
case EXCCODE_RSV: return "INT";
246+
case EXCCODE_TLBL: return "PIL";
247+
case EXCCODE_TLBS: return "PIS";
248+
case EXCCODE_TLBI: return "PIF";
249+
case EXCCODE_TLBM: return "PME";
250+
case EXCCODE_TLBNR: return "PNR";
251+
case EXCCODE_TLBNX: return "PNX";
252+
case EXCCODE_TLBPE: return "PPI";
253+
case EXCCODE_ADE:
254+
switch (esubcode) {
255+
case EXSUBCODE_ADEF: return "ADEF";
256+
case EXSUBCODE_ADEM: return "ADEM";
257+
}
258+
break;
259+
case EXCCODE_ALE: return "ALE";
260+
case EXCCODE_BCE: return "BCE";
261+
case EXCCODE_SYS: return "SYS";
262+
case EXCCODE_BP: return "BRK";
263+
case EXCCODE_INE: return "INE";
264+
case EXCCODE_IPE: return "IPE";
265+
case EXCCODE_FPDIS: return "FPD";
266+
case EXCCODE_LSXDIS: return "SXD";
267+
case EXCCODE_LASXDIS: return "ASXD";
268+
case EXCCODE_FPE:
269+
switch (esubcode) {
270+
case EXCSUBCODE_FPE: return "FPE";
271+
case EXCSUBCODE_VFPE: return "VFPE";
272+
}
273+
break;
274+
case EXCCODE_WATCH:
275+
switch (esubcode) {
276+
case EXCSUBCODE_WPEF: return "WPEF";
277+
case EXCSUBCODE_WPEM: return "WPEM";
278+
}
279+
break;
280+
case EXCCODE_BTDIS: return "BTD";
281+
case EXCCODE_BTE: return "BTE";
282+
case EXCCODE_GSPR: return "GSPR";
283+
case EXCCODE_HVC: return "HVC";
284+
case EXCCODE_GCM:
285+
switch (esubcode) {
286+
case EXCSUBCODE_GCSC: return "GCSC";
287+
case EXCSUBCODE_GCHC: return "GCHC";
288+
}
289+
break;
290+
/*
291+
* The manual did not mention the EXCCODE_SE case, but print out it
292+
* nevertheless.
293+
*/
294+
case EXCCODE_SE: return "SE";
295+
}
296+
297+
return "???";
298+
}
299+
300+
static void print_estat(unsigned long x)
301+
{
302+
unsigned int ecode = FIELD_GET(CSR_ESTAT_EXC, x);
303+
unsigned int esubcode = FIELD_GET(CSR_ESTAT_ESUBCODE, x);
304+
305+
printk("ESTAT: %08lx [%s] (", x, humanize_exc_name(ecode, esubcode));
306+
print_intr_fragment("IS", FIELD_GET(CSR_ESTAT_IS, x));
307+
pr_cont(" ECode=%d EsubCode=%d)\n", (int) ecode, (int) esubcode);
308+
}
309+
237310
static void __show_regs(const struct pt_regs *regs)
238311
{
239312
const int field = 2 * sizeof(unsigned long);
240-
unsigned int excsubcode;
241-
unsigned int exccode;
313+
unsigned int exccode = FIELD_GET(CSR_ESTAT_EXC, regs->csr_estat);
242314

243315
show_regs_print_info(KERN_DEFAULT);
244316

@@ -279,11 +351,7 @@ static void __show_regs(const struct pt_regs *regs)
279351
print_prmd(regs->csr_prmd);
280352
print_euen(regs->csr_euen);
281353
print_ecfg(regs->csr_ecfg);
282-
printk("ESTAT: %08lx\n", regs->csr_estat);
283-
284-
exccode = ((regs->csr_estat) & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
285-
excsubcode = ((regs->csr_estat) & CSR_ESTAT_ESUBCODE) >> CSR_ESTAT_ESUBCODE_SHIFT;
286-
printk("ExcCode : %x (SubCode %x)\n", exccode, excsubcode);
354+
print_estat(regs->csr_estat);
287355

288356
if (exccode >= EXCCODE_TLBL && exccode <= EXCCODE_ALE)
289357
printk("BadVA : %0*lx\n", field, regs->csr_badvaddr);

0 commit comments

Comments
 (0)