[PATCH] x86/fault: Make show_error_code() more extensible and tweak its formatting

From: Sean Christopherson
Date: Thu Dec 06 2018 - 10:25:13 EST


- Initialize each bit individually in the error_code_chars array. This
allows for non-contiguous bits and is self-documenting. Define a
macro to make the initialization code somewhatmore readable.

- Reverse the decode order so it's consistent with the raw display.

- Use ARRAY_SIZE instead of hardcoding '6' in multiple locations.

- Use '!' for the negative case to better contrast against '+'.

- Display four digits (was two) when printing the raw error code.

- Remove @regs from show_error_code().

Signed-off-by: Sean Christopherson <sean.j.christopherson@xxxxxxxxx>
---
arch/x86/mm/fault.c | 47 ++++++++++++++++++++++++---------------------
1 file changed, 25 insertions(+), 22 deletions(-)

diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 23dc7163f6ac..cd28d058ed39 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -605,45 +605,48 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)

/*
* This maps the somewhat obscure error_code number to symbolic text:
- *
- * P = protection fault (X86_PF_PROT)
- * W = write access (X86_PF_WRITE)
- * U = user-mode access (X86_PF_USER)
- * S = supervisor mode (X86_PF_RSVD)
- * I = instruction fault (X86_PF_INSTR)
- * K = keys fault (X86_PF_PK)
*/
-static const char error_code_chars[] = "PWUSIK";
+#define EC(x) ilog2(X86_PF_##x)
+static const char error_code_chars[] = {
+ [EC(PROT)] = 'P',
+ [EC(WRITE)] = 'W',
+ [EC(USER)] = 'U',
+ [EC(RSVD)] = 'S',
+ [EC(INSTR)] = 'I',
+ [EC(PK)] = 'K',
+};

/*
- * This helper function transforms the #PF error_code bits into " +P -W +U -R -I -K"
+ * This helper function transforms the #PF error_code bits into " +P !W +U !R !I !K"
* type of descriptive, almost human-readable error strings:
*/
-static void show_error_code(struct pt_regs *regs, unsigned long error_code)
+static void show_error_code(unsigned long error_code)
{
- unsigned int bit, mask;
- char err_txt[6*3+1]; /* Fixed length of 6 bits decoded plus zero at the end */
+ char err_txt[ARRAY_SIZE(error_code_chars)*3+1]; /* 3 chars per bit plus zero at the end */
+ unsigned offset = 0;
+ unsigned long mask;
+ int i;

- /* We go from the X86_PF_PROT bit to the X86_PF_PK bit: */
-
- for (bit = 0; bit < 6; bit++) {
- unsigned int offset = bit*3;
+ for (i = ARRAY_SIZE(error_code_chars) - 1; i >= 0; i--) {
+ if (!error_code_chars[i])
+ continue;

err_txt[offset+0] = ' ';

- mask = 1 << bit;
+ mask = 1 << i;
if (error_code & mask)
err_txt[offset+1] = '+';
else
- err_txt[offset+1] = '-';
+ err_txt[offset+1] = '!';

- err_txt[offset+2] = error_code_chars[bit];
+ err_txt[offset+2] = error_code_chars[i];
+ offset += 3;
}

/* Close the string: */
- err_txt[sizeof(err_txt)-1] = 0;
+ err_txt[offset] = 0;

- pr_alert("#PF error code: %s (%02lx)\n", err_txt, error_code);
+ pr_alert("#PF error code(%04lx): %s\n", error_code, err_txt);
}

static void
@@ -676,7 +679,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, unsigned long ad
address < PAGE_SIZE ? "NULL pointer dereference" : "paging request",
(void *)address);

- show_error_code(regs, error_code);
+ show_error_code(error_code);

if (!(error_code & X86_PF_USER) && user_mode(regs)) {
struct desc_ptr idt, gdt;
--
2.19.2