// SPDX-License-Identifier: GPL-2.0 /* * UEFI Common Platform Error Record (CPER) support * * Copyright (C) 2017, The Linux Foundation. All rights reserved.
*/
staticconstchar * const arm_bus_err_op_strs[] = { "Generic error (type cannot be determined)", "Generic read (type of instruction or data request cannot be determined)", "Generic write (type of instruction of data request cannot be determined)", "Data read", "Data write", "Instruction fetch", "Prefetch",
};
staticconstchar * const arm_cache_err_op_strs[] = { "Generic error (type cannot be determined)", "Generic read (type of instruction or data request cannot be determined)", "Generic write (type of instruction of data request cannot be determined)", "Data read", "Data write", "Instruction fetch", "Prefetch", "Eviction", "Snooping (processor initiated a cache snoop that resulted in an error)", "Snooped (processor raised a cache error caused by another processor or device snooping its cache)", "Management",
};
staticconstchar * const arm_tlb_err_op_strs[] = { "Generic error (type cannot be determined)", "Generic read (type of instruction or data request cannot be determined)", "Generic write (type of instruction of data request cannot be determined)", "Data read", "Data write", "Instruction fetch", "Prefetch", "Local management operation (processor initiated a TLB management operation that resulted in an error)", "External management operation (processor raised a TLB error caused by another processor or device broadcasting TLB operations)",
};
if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) {
op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT)
& CPER_ARM_ERR_OPERATION_MASK); switch (type) { case CPER_ARM_CACHE_ERROR: if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) {
printk("%soperation type: %s\n", pfx,
arm_cache_err_op_strs[op_type]);
} break; case CPER_ARM_TLB_ERROR: if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) {
printk("%soperation type: %s\n", pfx,
arm_tlb_err_op_strs[op_type]);
} break; case CPER_ARM_BUS_ERROR: if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) {
printk("%soperation type: %s\n", pfx,
arm_bus_err_op_strs[op_type]);
} break;
}
}
if (error_info & CPER_ARM_ERR_VALID_LEVEL) {
level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT)
& CPER_ARM_ERR_LEVEL_MASK); switch (type) { case CPER_ARM_CACHE_ERROR:
printk("%scache level: %d\n", pfx, level); break; case CPER_ARM_TLB_ERROR:
printk("%sTLB level: %d\n", pfx, level); break; case CPER_ARM_BUS_ERROR:
printk("%saffinity level at which the bus error occurred: %d\n",
pfx, level); break;
}
}
if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) {
proc_context_corrupt = ((error_info >> CPER_ARM_ERR_PC_CORRUPT_SHIFT)
& CPER_ARM_ERR_PC_CORRUPT_MASK); if (proc_context_corrupt)
printk("%sprocessor context corrupted\n", pfx); else
printk("%sprocessor context not corrupted\n", pfx);
}
if (error_info & CPER_ARM_ERR_VALID_CORRECTED) {
corrected = ((error_info >> CPER_ARM_ERR_CORRECTED_SHIFT)
& CPER_ARM_ERR_CORRECTED_MASK); if (corrected)
printk("%sthe error has been corrected\n", pfx); else
printk("%sthe error has not been corrected\n", pfx);
}
if (error_info & CPER_ARM_ERR_VALID_PRECISE_PC) {
precise_pc = ((error_info >> CPER_ARM_ERR_PRECISE_PC_SHIFT)
& CPER_ARM_ERR_PRECISE_PC_MASK); if (precise_pc)
printk("%sPC is precise\n", pfx); else
printk("%sPC is imprecise\n", pfx);
}
if (error_info & CPER_ARM_ERR_VALID_RESTARTABLE_PC) {
restartable_pc = ((error_info >> CPER_ARM_ERR_RESTARTABLE_PC_SHIFT)
& CPER_ARM_ERR_RESTARTABLE_PC_MASK); if (restartable_pc)
printk("%sProgram execution can be restarted reliably at the PC associated with the error.\n", pfx);
}
/* The rest of the fields are specific to bus errors */ if (type != CPER_ARM_BUS_ERROR) return;
ctx_info = (struct cper_arm_ctx_info *)err_info;
max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1; for (i = 0; i < proc->context_info_num; i++) { int size = ALIGN(sizeof(*ctx_info) + ctx_info->size, 16);
printk("%sContext info structure %d:\n", pfx, i); if (len < size) {
printk("%ssection length is too small\n", newpfx);
printk("%sfirmware-generated error record is incorrect\n", pfx); return;
} if (ctx_info->type > max_ctx_type) {
printk("%sInvalid context type: %d (max: %d)\n",
newpfx, ctx_info->type, max_ctx_type); return;
}
printk("%sregister context type: %s\n", newpfx,
arm_reg_ctx_strs[ctx_info->type]);
print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
(ctx_info + 1), ctx_info->size, 0);
len -= size;
ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
}
if (len > 0) {
printk("%sVendor specific error info has %u bytes:\n", pfx,
len);
print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
len, true);
}
}
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.