362 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2018, Advanced Micro Devices, Inc.3 4#include <linux/cper.h>5#include <linux/acpi.h>6 7/*8 * We don't need a "CPER_IA" prefix since these are all locally defined.9 * This will save us a lot of line space.10 */11#define VALID_LAPIC_ID BIT_ULL(0)12#define VALID_CPUID_INFO BIT_ULL(1)13#define VALID_PROC_ERR_INFO_NUM(bits) (((bits) & GENMASK_ULL(7, 2)) >> 2)14#define VALID_PROC_CXT_INFO_NUM(bits) (((bits) & GENMASK_ULL(13, 8)) >> 8)15 16#define INFO_ERR_STRUCT_TYPE_CACHE \17 GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B, \18 0x57, 0x3F, 0xAD, 0x2C)19#define INFO_ERR_STRUCT_TYPE_TLB \20 GUID_INIT(0xFC06B535, 0x5E1F, 0x4562, 0x9F, 0x25, 0x0A, 0x3B, \21 0x9A, 0xDB, 0x63, 0xC3)22#define INFO_ERR_STRUCT_TYPE_BUS \23 GUID_INIT(0x1CF3F8B3, 0xC5B1, 0x49a2, 0xAA, 0x59, 0x5E, 0xEF, \24 0x92, 0xFF, 0xA6, 0x3C)25#define INFO_ERR_STRUCT_TYPE_MS \26 GUID_INIT(0x48AB7F57, 0xDC34, 0x4f6c, 0xA7, 0xD3, 0xB0, 0xB5, \27 0xB0, 0xA7, 0x43, 0x14)28 29#define INFO_VALID_CHECK_INFO BIT_ULL(0)30#define INFO_VALID_TARGET_ID BIT_ULL(1)31#define INFO_VALID_REQUESTOR_ID BIT_ULL(2)32#define INFO_VALID_RESPONDER_ID BIT_ULL(3)33#define INFO_VALID_IP BIT_ULL(4)34 35#define CHECK_VALID_TRANS_TYPE BIT_ULL(0)36#define CHECK_VALID_OPERATION BIT_ULL(1)37#define CHECK_VALID_LEVEL BIT_ULL(2)38#define CHECK_VALID_PCC BIT_ULL(3)39#define CHECK_VALID_UNCORRECTED BIT_ULL(4)40#define CHECK_VALID_PRECISE_IP BIT_ULL(5)41#define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6)42#define CHECK_VALID_OVERFLOW BIT_ULL(7)43 44#define CHECK_VALID_BUS_PART_TYPE BIT_ULL(8)45#define CHECK_VALID_BUS_TIME_OUT BIT_ULL(9)46#define CHECK_VALID_BUS_ADDR_SPACE BIT_ULL(10)47 48#define CHECK_VALID_BITS(check) (((check) & GENMASK_ULL(15, 0)))49#define CHECK_TRANS_TYPE(check) (((check) & GENMASK_ULL(17, 16)) >> 16)50#define CHECK_OPERATION(check) (((check) & GENMASK_ULL(21, 18)) >> 18)51#define CHECK_LEVEL(check) (((check) & GENMASK_ULL(24, 22)) >> 22)52#define CHECK_PCC BIT_ULL(25)53#define CHECK_UNCORRECTED BIT_ULL(26)54#define CHECK_PRECISE_IP BIT_ULL(27)55#define CHECK_RESTARTABLE_IP BIT_ULL(28)56#define CHECK_OVERFLOW BIT_ULL(29)57 58#define CHECK_BUS_PART_TYPE(check) (((check) & GENMASK_ULL(31, 30)) >> 30)59#define CHECK_BUS_TIME_OUT BIT_ULL(32)60#define CHECK_BUS_ADDR_SPACE(check) (((check) & GENMASK_ULL(34, 33)) >> 33)61 62#define CHECK_VALID_MS_ERR_TYPE BIT_ULL(0)63#define CHECK_VALID_MS_PCC BIT_ULL(1)64#define CHECK_VALID_MS_UNCORRECTED BIT_ULL(2)65#define CHECK_VALID_MS_PRECISE_IP BIT_ULL(3)66#define CHECK_VALID_MS_RESTARTABLE_IP BIT_ULL(4)67#define CHECK_VALID_MS_OVERFLOW BIT_ULL(5)68 69#define CHECK_MS_ERR_TYPE(check) (((check) & GENMASK_ULL(18, 16)) >> 16)70#define CHECK_MS_PCC BIT_ULL(19)71#define CHECK_MS_UNCORRECTED BIT_ULL(20)72#define CHECK_MS_PRECISE_IP BIT_ULL(21)73#define CHECK_MS_RESTARTABLE_IP BIT_ULL(22)74#define CHECK_MS_OVERFLOW BIT_ULL(23)75 76#define CTX_TYPE_MSR 177#define CTX_TYPE_MMREG 778 79enum err_types {80 ERR_TYPE_CACHE = 0,81 ERR_TYPE_TLB,82 ERR_TYPE_BUS,83 ERR_TYPE_MS,84 N_ERR_TYPES85};86 87static enum err_types cper_get_err_type(const guid_t *err_type)88{89 if (guid_equal(err_type, &INFO_ERR_STRUCT_TYPE_CACHE))90 return ERR_TYPE_CACHE;91 else if (guid_equal(err_type, &INFO_ERR_STRUCT_TYPE_TLB))92 return ERR_TYPE_TLB;93 else if (guid_equal(err_type, &INFO_ERR_STRUCT_TYPE_BUS))94 return ERR_TYPE_BUS;95 else if (guid_equal(err_type, &INFO_ERR_STRUCT_TYPE_MS))96 return ERR_TYPE_MS;97 else98 return N_ERR_TYPES;99}100 101static const char * const ia_check_trans_type_strs[] = {102 "Instruction",103 "Data Access",104 "Generic",105};106 107static const char * const ia_check_op_strs[] = {108 "generic error",109 "generic read",110 "generic write",111 "data read",112 "data write",113 "instruction fetch",114 "prefetch",115 "eviction",116 "snoop",117};118 119static const char * const ia_check_bus_part_type_strs[] = {120 "Local Processor originated request",121 "Local Processor responded to request",122 "Local Processor observed",123 "Generic",124};125 126static const char * const ia_check_bus_addr_space_strs[] = {127 "Memory Access",128 "Reserved",129 "I/O",130 "Other Transaction",131};132 133static const char * const ia_check_ms_error_type_strs[] = {134 "No Error",135 "Unclassified",136 "Microcode ROM Parity Error",137 "External Error",138 "FRC Error",139 "Internal Unclassified",140};141 142static const char * const ia_reg_ctx_strs[] = {143 "Unclassified Data",144 "MSR Registers (Machine Check and other MSRs)",145 "32-bit Mode Execution Context",146 "64-bit Mode Execution Context",147 "FXSAVE Context",148 "32-bit Mode Debug Registers (DR0-DR7)",149 "64-bit Mode Debug Registers (DR0-DR7)",150 "Memory Mapped Registers",151};152 153static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)154{155 printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");156}157 158static void print_err_info_ms(const char *pfx, u16 validation_bits, u64 check)159{160 if (validation_bits & CHECK_VALID_MS_ERR_TYPE) {161 u8 err_type = CHECK_MS_ERR_TYPE(check);162 163 printk("%sError Type: %u, %s\n", pfx, err_type,164 err_type < ARRAY_SIZE(ia_check_ms_error_type_strs) ?165 ia_check_ms_error_type_strs[err_type] : "unknown");166 }167 168 if (validation_bits & CHECK_VALID_MS_PCC)169 print_bool("Processor Context Corrupt", pfx, check, CHECK_MS_PCC);170 171 if (validation_bits & CHECK_VALID_MS_UNCORRECTED)172 print_bool("Uncorrected", pfx, check, CHECK_MS_UNCORRECTED);173 174 if (validation_bits & CHECK_VALID_MS_PRECISE_IP)175 print_bool("Precise IP", pfx, check, CHECK_MS_PRECISE_IP);176 177 if (validation_bits & CHECK_VALID_MS_RESTARTABLE_IP)178 print_bool("Restartable IP", pfx, check, CHECK_MS_RESTARTABLE_IP);179 180 if (validation_bits & CHECK_VALID_MS_OVERFLOW)181 print_bool("Overflow", pfx, check, CHECK_MS_OVERFLOW);182}183 184static void print_err_info(const char *pfx, u8 err_type, u64 check)185{186 u16 validation_bits = CHECK_VALID_BITS(check);187 188 /*189 * The MS Check structure varies a lot from the others, so use a190 * separate function for decoding.191 */192 if (err_type == ERR_TYPE_MS)193 return print_err_info_ms(pfx, validation_bits, check);194 195 if (validation_bits & CHECK_VALID_TRANS_TYPE) {196 u8 trans_type = CHECK_TRANS_TYPE(check);197 198 printk("%sTransaction Type: %u, %s\n", pfx, trans_type,199 trans_type < ARRAY_SIZE(ia_check_trans_type_strs) ?200 ia_check_trans_type_strs[trans_type] : "unknown");201 }202 203 if (validation_bits & CHECK_VALID_OPERATION) {204 u8 op = CHECK_OPERATION(check);205 206 /*207 * CACHE has more operation types than TLB or BUS, though the208 * name and the order are the same.209 */210 u8 max_ops = (err_type == ERR_TYPE_CACHE) ? 9 : 7;211 212 printk("%sOperation: %u, %s\n", pfx, op,213 op < max_ops ? ia_check_op_strs[op] : "unknown");214 }215 216 if (validation_bits & CHECK_VALID_LEVEL)217 printk("%sLevel: %llu\n", pfx, CHECK_LEVEL(check));218 219 if (validation_bits & CHECK_VALID_PCC)220 print_bool("Processor Context Corrupt", pfx, check, CHECK_PCC);221 222 if (validation_bits & CHECK_VALID_UNCORRECTED)223 print_bool("Uncorrected", pfx, check, CHECK_UNCORRECTED);224 225 if (validation_bits & CHECK_VALID_PRECISE_IP)226 print_bool("Precise IP", pfx, check, CHECK_PRECISE_IP);227 228 if (validation_bits & CHECK_VALID_RESTARTABLE_IP)229 print_bool("Restartable IP", pfx, check, CHECK_RESTARTABLE_IP);230 231 if (validation_bits & CHECK_VALID_OVERFLOW)232 print_bool("Overflow", pfx, check, CHECK_OVERFLOW);233 234 if (err_type != ERR_TYPE_BUS)235 return;236 237 if (validation_bits & CHECK_VALID_BUS_PART_TYPE) {238 u8 part_type = CHECK_BUS_PART_TYPE(check);239 240 printk("%sParticipation Type: %u, %s\n", pfx, part_type,241 part_type < ARRAY_SIZE(ia_check_bus_part_type_strs) ?242 ia_check_bus_part_type_strs[part_type] : "unknown");243 }244 245 if (validation_bits & CHECK_VALID_BUS_TIME_OUT)246 print_bool("Time Out", pfx, check, CHECK_BUS_TIME_OUT);247 248 if (validation_bits & CHECK_VALID_BUS_ADDR_SPACE) {249 u8 addr_space = CHECK_BUS_ADDR_SPACE(check);250 251 printk("%sAddress Space: %u, %s\n", pfx, addr_space,252 addr_space < ARRAY_SIZE(ia_check_bus_addr_space_strs) ?253 ia_check_bus_addr_space_strs[addr_space] : "unknown");254 }255}256 257void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)258{259 int i;260 struct cper_ia_err_info *err_info;261 struct cper_ia_proc_ctx *ctx_info;262 char newpfx[64], infopfx[64];263 u8 err_type;264 265 if (proc->validation_bits & VALID_LAPIC_ID)266 printk("%sLocal APIC_ID: 0x%llx\n", pfx, proc->lapic_id);267 268 if (proc->validation_bits & VALID_CPUID_INFO) {269 printk("%sCPUID Info:\n", pfx);270 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, proc->cpuid,271 sizeof(proc->cpuid), 0);272 }273 274 snprintf(newpfx, sizeof(newpfx), "%s ", pfx);275 276 err_info = (struct cper_ia_err_info *)(proc + 1);277 for (i = 0; i < VALID_PROC_ERR_INFO_NUM(proc->validation_bits); i++) {278 printk("%sError Information Structure %d:\n", pfx, i);279 280 err_type = cper_get_err_type(&err_info->err_type);281 printk("%sError Structure Type: %s\n", newpfx,282 err_type < ARRAY_SIZE(cper_proc_error_type_strs) ?283 cper_proc_error_type_strs[err_type] : "unknown");284 285 if (err_type >= N_ERR_TYPES) {286 printk("%sError Structure Type: %pUl\n", newpfx,287 &err_info->err_type);288 }289 290 if (err_info->validation_bits & INFO_VALID_CHECK_INFO) {291 printk("%sCheck Information: 0x%016llx\n", newpfx,292 err_info->check_info);293 294 if (err_type < N_ERR_TYPES) {295 snprintf(infopfx, sizeof(infopfx), "%s ",296 newpfx);297 298 print_err_info(infopfx, err_type,299 err_info->check_info);300 }301 }302 303 if (err_info->validation_bits & INFO_VALID_TARGET_ID) {304 printk("%sTarget Identifier: 0x%016llx\n",305 newpfx, err_info->target_id);306 }307 308 if (err_info->validation_bits & INFO_VALID_REQUESTOR_ID) {309 printk("%sRequestor Identifier: 0x%016llx\n",310 newpfx, err_info->requestor_id);311 }312 313 if (err_info->validation_bits & INFO_VALID_RESPONDER_ID) {314 printk("%sResponder Identifier: 0x%016llx\n",315 newpfx, err_info->responder_id);316 }317 318 if (err_info->validation_bits & INFO_VALID_IP) {319 printk("%sInstruction Pointer: 0x%016llx\n",320 newpfx, err_info->ip);321 }322 323 err_info++;324 }325 326 ctx_info = (struct cper_ia_proc_ctx *)err_info;327 for (i = 0; i < VALID_PROC_CXT_INFO_NUM(proc->validation_bits); i++) {328 int size = sizeof(*ctx_info) + ctx_info->reg_arr_size;329 int groupsize = 4;330 331 printk("%sContext Information Structure %d:\n", pfx, i);332 333 printk("%sRegister Context Type: %s\n", newpfx,334 ctx_info->reg_ctx_type < ARRAY_SIZE(ia_reg_ctx_strs) ?335 ia_reg_ctx_strs[ctx_info->reg_ctx_type] : "unknown");336 337 printk("%sRegister Array Size: 0x%04x\n", newpfx,338 ctx_info->reg_arr_size);339 340 if (ctx_info->reg_ctx_type == CTX_TYPE_MSR) {341 groupsize = 8; /* MSRs are 8 bytes wide. */342 printk("%sMSR Address: 0x%08x\n", newpfx,343 ctx_info->msr_addr);344 }345 346 if (ctx_info->reg_ctx_type == CTX_TYPE_MMREG) {347 printk("%sMM Register Address: 0x%016llx\n", newpfx,348 ctx_info->mm_reg_addr);349 }350 351 if (ctx_info->reg_ctx_type != CTX_TYPE_MSR ||352 arch_apei_report_x86_error(ctx_info, proc->lapic_id)) {353 printk("%sRegister Array:\n", newpfx);354 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16,355 groupsize, (ctx_info + 1),356 ctx_info->reg_arr_size, 0);357 }358 359 ctx_info = (struct cper_ia_proc_ctx *)((long)ctx_info + size);360 }361}362