diff options
author | Yazen Ghannam <yazen.ghannam@amd.com> | 2018-05-04 01:59:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2018-05-14 02:57:48 -0400 |
commit | a9c1e3e791409e35207277b7873efc756b6fb625 (patch) | |
tree | abd8d8e5e9ada0389af23f3fc8b60c8222436ca7 | |
parent | dc2d26e4b667c8005c58669e71de3efd17f4390f (diff) |
efi: Decode IA32/X64 Cache, TLB, and Bus Check structures
Print the common fields of the Cache, TLB, and Bus check structures.The
fields of these three check types are the same except for a few more
fields in the Bus check structure. The remaining Bus check structure
fields will be decoded in a following patch.
Based on UEFI 2.7,
Table 254. IA32/X64 Cache Check Structure
Table 255. IA32/X64 TLB Check Structure
Table 256. IA32/X64 Bus Check Structure
Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-efi@vger.kernel.org
Link: http://lkml.kernel.org/r/20180504060003.19618-8-ard.biesheuvel@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | drivers/firmware/efi/cper-x86.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c index 5438097b93ac..f70c46f7a4db 100644 --- a/drivers/firmware/efi/cper-x86.c +++ b/drivers/firmware/efi/cper-x86.c | |||
@@ -30,6 +30,25 @@ | |||
30 | #define INFO_VALID_RESPONDER_ID BIT_ULL(3) | 30 | #define INFO_VALID_RESPONDER_ID BIT_ULL(3) |
31 | #define INFO_VALID_IP BIT_ULL(4) | 31 | #define INFO_VALID_IP BIT_ULL(4) |
32 | 32 | ||
33 | #define CHECK_VALID_TRANS_TYPE BIT_ULL(0) | ||
34 | #define CHECK_VALID_OPERATION BIT_ULL(1) | ||
35 | #define CHECK_VALID_LEVEL BIT_ULL(2) | ||
36 | #define CHECK_VALID_PCC BIT_ULL(3) | ||
37 | #define CHECK_VALID_UNCORRECTED BIT_ULL(4) | ||
38 | #define CHECK_VALID_PRECISE_IP BIT_ULL(5) | ||
39 | #define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6) | ||
40 | #define CHECK_VALID_OVERFLOW BIT_ULL(7) | ||
41 | |||
42 | #define CHECK_VALID_BITS(check) (((check) & GENMASK_ULL(15, 0))) | ||
43 | #define CHECK_TRANS_TYPE(check) (((check) & GENMASK_ULL(17, 16)) >> 16) | ||
44 | #define CHECK_OPERATION(check) (((check) & GENMASK_ULL(21, 18)) >> 18) | ||
45 | #define CHECK_LEVEL(check) (((check) & GENMASK_ULL(24, 22)) >> 22) | ||
46 | #define CHECK_PCC BIT_ULL(25) | ||
47 | #define CHECK_UNCORRECTED BIT_ULL(26) | ||
48 | #define CHECK_PRECISE_IP BIT_ULL(27) | ||
49 | #define CHECK_RESTARTABLE_IP BIT_ULL(28) | ||
50 | #define CHECK_OVERFLOW BIT_ULL(29) | ||
51 | |||
33 | enum err_types { | 52 | enum err_types { |
34 | ERR_TYPE_CACHE = 0, | 53 | ERR_TYPE_CACHE = 0, |
35 | ERR_TYPE_TLB, | 54 | ERR_TYPE_TLB, |
@@ -52,11 +71,81 @@ static enum err_types cper_get_err_type(const guid_t *err_type) | |||
52 | return N_ERR_TYPES; | 71 | return N_ERR_TYPES; |
53 | } | 72 | } |
54 | 73 | ||
74 | static const char * const ia_check_trans_type_strs[] = { | ||
75 | "Instruction", | ||
76 | "Data Access", | ||
77 | "Generic", | ||
78 | }; | ||
79 | |||
80 | static const char * const ia_check_op_strs[] = { | ||
81 | "generic error", | ||
82 | "generic read", | ||
83 | "generic write", | ||
84 | "data read", | ||
85 | "data write", | ||
86 | "instruction fetch", | ||
87 | "prefetch", | ||
88 | "eviction", | ||
89 | "snoop", | ||
90 | }; | ||
91 | |||
92 | static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit) | ||
93 | { | ||
94 | printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false"); | ||
95 | } | ||
96 | |||
97 | static void print_err_info(const char *pfx, u8 err_type, u64 check) | ||
98 | { | ||
99 | u16 validation_bits = CHECK_VALID_BITS(check); | ||
100 | |||
101 | if (err_type == ERR_TYPE_MS) | ||
102 | return; | ||
103 | |||
104 | if (validation_bits & CHECK_VALID_TRANS_TYPE) { | ||
105 | u8 trans_type = CHECK_TRANS_TYPE(check); | ||
106 | |||
107 | printk("%sTransaction Type: %u, %s\n", pfx, trans_type, | ||
108 | trans_type < ARRAY_SIZE(ia_check_trans_type_strs) ? | ||
109 | ia_check_trans_type_strs[trans_type] : "unknown"); | ||
110 | } | ||
111 | |||
112 | if (validation_bits & CHECK_VALID_OPERATION) { | ||
113 | u8 op = CHECK_OPERATION(check); | ||
114 | |||
115 | /* | ||
116 | * CACHE has more operation types than TLB or BUS, though the | ||
117 | * name and the order are the same. | ||
118 | */ | ||
119 | u8 max_ops = (err_type == ERR_TYPE_CACHE) ? 9 : 7; | ||
120 | |||
121 | printk("%sOperation: %u, %s\n", pfx, op, | ||
122 | op < max_ops ? ia_check_op_strs[op] : "unknown"); | ||
123 | } | ||
124 | |||
125 | if (validation_bits & CHECK_VALID_LEVEL) | ||
126 | printk("%sLevel: %llu\n", pfx, CHECK_LEVEL(check)); | ||
127 | |||
128 | if (validation_bits & CHECK_VALID_PCC) | ||
129 | print_bool("Processor Context Corrupt", pfx, check, CHECK_PCC); | ||
130 | |||
131 | if (validation_bits & CHECK_VALID_UNCORRECTED) | ||
132 | print_bool("Uncorrected", pfx, check, CHECK_UNCORRECTED); | ||
133 | |||
134 | if (validation_bits & CHECK_VALID_PRECISE_IP) | ||
135 | print_bool("Precise IP", pfx, check, CHECK_PRECISE_IP); | ||
136 | |||
137 | if (validation_bits & CHECK_VALID_RESTARTABLE_IP) | ||
138 | print_bool("Restartable IP", pfx, check, CHECK_RESTARTABLE_IP); | ||
139 | |||
140 | if (validation_bits & CHECK_VALID_OVERFLOW) | ||
141 | print_bool("Overflow", pfx, check, CHECK_OVERFLOW); | ||
142 | } | ||
143 | |||
55 | void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc) | 144 | void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc) |
56 | { | 145 | { |
57 | int i; | 146 | int i; |
58 | struct cper_ia_err_info *err_info; | 147 | struct cper_ia_err_info *err_info; |
59 | char newpfx[64]; | 148 | char newpfx[64], infopfx[64]; |
60 | u8 err_type; | 149 | u8 err_type; |
61 | 150 | ||
62 | if (proc->validation_bits & VALID_LAPIC_ID) | 151 | if (proc->validation_bits & VALID_LAPIC_ID) |
@@ -87,6 +176,14 @@ void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc) | |||
87 | if (err_info->validation_bits & INFO_VALID_CHECK_INFO) { | 176 | if (err_info->validation_bits & INFO_VALID_CHECK_INFO) { |
88 | printk("%sCheck Information: 0x%016llx\n", newpfx, | 177 | printk("%sCheck Information: 0x%016llx\n", newpfx, |
89 | err_info->check_info); | 178 | err_info->check_info); |
179 | |||
180 | if (err_type < N_ERR_TYPES) { | ||
181 | snprintf(infopfx, sizeof(infopfx), "%s ", | ||
182 | newpfx); | ||
183 | |||
184 | print_err_info(infopfx, err_type, | ||
185 | err_info->check_info); | ||
186 | } | ||
90 | } | 187 | } |
91 | 188 | ||
92 | if (err_info->validation_bits & INFO_VALID_TARGET_ID) { | 189 | if (err_info->validation_bits & INFO_VALID_TARGET_ID) { |