cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cper-arm.c (11056B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * UEFI Common Platform Error Record (CPER) support
      4 *
      5 * Copyright (C) 2017, The Linux Foundation. All rights reserved.
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/module.h>
     10#include <linux/time.h>
     11#include <linux/cper.h>
     12#include <linux/dmi.h>
     13#include <linux/acpi.h>
     14#include <linux/pci.h>
     15#include <linux/aer.h>
     16#include <linux/printk.h>
     17#include <linux/bcd.h>
     18#include <acpi/ghes.h>
     19#include <ras/ras_event.h>
     20
     21static const char * const arm_reg_ctx_strs[] = {
     22	"AArch32 general purpose registers",
     23	"AArch32 EL1 context registers",
     24	"AArch32 EL2 context registers",
     25	"AArch32 secure context registers",
     26	"AArch64 general purpose registers",
     27	"AArch64 EL1 context registers",
     28	"AArch64 EL2 context registers",
     29	"AArch64 EL3 context registers",
     30	"Misc. system register structure",
     31};
     32
     33static const char * const arm_err_trans_type_strs[] = {
     34	"Instruction",
     35	"Data Access",
     36	"Generic",
     37};
     38
     39static const char * const arm_bus_err_op_strs[] = {
     40	"Generic error (type cannot be determined)",
     41	"Generic read (type of instruction or data request cannot be determined)",
     42	"Generic write (type of instruction of data request cannot be determined)",
     43	"Data read",
     44	"Data write",
     45	"Instruction fetch",
     46	"Prefetch",
     47};
     48
     49static const char * const arm_cache_err_op_strs[] = {
     50	"Generic error (type cannot be determined)",
     51	"Generic read (type of instruction or data request cannot be determined)",
     52	"Generic write (type of instruction of data request cannot be determined)",
     53	"Data read",
     54	"Data write",
     55	"Instruction fetch",
     56	"Prefetch",
     57	"Eviction",
     58	"Snooping (processor initiated a cache snoop that resulted in an error)",
     59	"Snooped (processor raised a cache error caused by another processor or device snooping its cache)",
     60	"Management",
     61};
     62
     63static const char * const arm_tlb_err_op_strs[] = {
     64	"Generic error (type cannot be determined)",
     65	"Generic read (type of instruction or data request cannot be determined)",
     66	"Generic write (type of instruction of data request cannot be determined)",
     67	"Data read",
     68	"Data write",
     69	"Instruction fetch",
     70	"Prefetch",
     71	"Local management operation (processor initiated a TLB management operation that resulted in an error)",
     72	"External management operation (processor raised a TLB error caused by another processor or device broadcasting TLB operations)",
     73};
     74
     75static const char * const arm_bus_err_part_type_strs[] = {
     76	"Local processor originated request",
     77	"Local processor responded to request",
     78	"Local processor observed",
     79	"Generic",
     80};
     81
     82static const char * const arm_bus_err_addr_space_strs[] = {
     83	"External Memory Access",
     84	"Internal Memory Access",
     85	"Unknown",
     86	"Device Memory Access",
     87};
     88
     89static void cper_print_arm_err_info(const char *pfx, u32 type,
     90				    u64 error_info)
     91{
     92	u8 trans_type, op_type, level, participation_type, address_space;
     93	u16 mem_attributes;
     94	bool proc_context_corrupt, corrected, precise_pc, restartable_pc;
     95	bool time_out, access_mode;
     96
     97	/* If the type is unknown, bail. */
     98	if (type > CPER_ARM_MAX_TYPE)
     99		return;
    100
    101	/*
    102	 * Vendor type errors have error information values that are vendor
    103	 * specific.
    104	 */
    105	if (type == CPER_ARM_VENDOR_ERROR)
    106		return;
    107
    108	if (error_info & CPER_ARM_ERR_VALID_TRANSACTION_TYPE) {
    109		trans_type = ((error_info >> CPER_ARM_ERR_TRANSACTION_SHIFT)
    110			      & CPER_ARM_ERR_TRANSACTION_MASK);
    111		if (trans_type < ARRAY_SIZE(arm_err_trans_type_strs)) {
    112			printk("%stransaction type: %s\n", pfx,
    113			       arm_err_trans_type_strs[trans_type]);
    114		}
    115	}
    116
    117	if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) {
    118		op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT)
    119			   & CPER_ARM_ERR_OPERATION_MASK);
    120		switch (type) {
    121		case CPER_ARM_CACHE_ERROR:
    122			if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) {
    123				printk("%soperation type: %s\n", pfx,
    124				       arm_cache_err_op_strs[op_type]);
    125			}
    126			break;
    127		case CPER_ARM_TLB_ERROR:
    128			if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) {
    129				printk("%soperation type: %s\n", pfx,
    130				       arm_tlb_err_op_strs[op_type]);
    131			}
    132			break;
    133		case CPER_ARM_BUS_ERROR:
    134			if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) {
    135				printk("%soperation type: %s\n", pfx,
    136				       arm_bus_err_op_strs[op_type]);
    137			}
    138			break;
    139		}
    140	}
    141
    142	if (error_info & CPER_ARM_ERR_VALID_LEVEL) {
    143		level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT)
    144			 & CPER_ARM_ERR_LEVEL_MASK);
    145		switch (type) {
    146		case CPER_ARM_CACHE_ERROR:
    147			printk("%scache level: %d\n", pfx, level);
    148			break;
    149		case CPER_ARM_TLB_ERROR:
    150			printk("%sTLB level: %d\n", pfx, level);
    151			break;
    152		case CPER_ARM_BUS_ERROR:
    153			printk("%saffinity level at which the bus error occurred: %d\n",
    154			       pfx, level);
    155			break;
    156		}
    157	}
    158
    159	if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) {
    160		proc_context_corrupt = ((error_info >> CPER_ARM_ERR_PC_CORRUPT_SHIFT)
    161					& CPER_ARM_ERR_PC_CORRUPT_MASK);
    162		if (proc_context_corrupt)
    163			printk("%sprocessor context corrupted\n", pfx);
    164		else
    165			printk("%sprocessor context not corrupted\n", pfx);
    166	}
    167
    168	if (error_info & CPER_ARM_ERR_VALID_CORRECTED) {
    169		corrected = ((error_info >> CPER_ARM_ERR_CORRECTED_SHIFT)
    170			     & CPER_ARM_ERR_CORRECTED_MASK);
    171		if (corrected)
    172			printk("%sthe error has been corrected\n", pfx);
    173		else
    174			printk("%sthe error has not been corrected\n", pfx);
    175	}
    176
    177	if (error_info & CPER_ARM_ERR_VALID_PRECISE_PC) {
    178		precise_pc = ((error_info >> CPER_ARM_ERR_PRECISE_PC_SHIFT)
    179			      & CPER_ARM_ERR_PRECISE_PC_MASK);
    180		if (precise_pc)
    181			printk("%sPC is precise\n", pfx);
    182		else
    183			printk("%sPC is imprecise\n", pfx);
    184	}
    185
    186	if (error_info & CPER_ARM_ERR_VALID_RESTARTABLE_PC) {
    187		restartable_pc = ((error_info >> CPER_ARM_ERR_RESTARTABLE_PC_SHIFT)
    188				  & CPER_ARM_ERR_RESTARTABLE_PC_MASK);
    189		if (restartable_pc)
    190			printk("%sProgram execution can be restarted reliably at the PC associated with the error.\n", pfx);
    191	}
    192
    193	/* The rest of the fields are specific to bus errors */
    194	if (type != CPER_ARM_BUS_ERROR)
    195		return;
    196
    197	if (error_info & CPER_ARM_ERR_VALID_PARTICIPATION_TYPE) {
    198		participation_type = ((error_info >> CPER_ARM_ERR_PARTICIPATION_TYPE_SHIFT)
    199				      & CPER_ARM_ERR_PARTICIPATION_TYPE_MASK);
    200		if (participation_type < ARRAY_SIZE(arm_bus_err_part_type_strs)) {
    201			printk("%sparticipation type: %s\n", pfx,
    202			       arm_bus_err_part_type_strs[participation_type]);
    203		}
    204	}
    205
    206	if (error_info & CPER_ARM_ERR_VALID_TIME_OUT) {
    207		time_out = ((error_info >> CPER_ARM_ERR_TIME_OUT_SHIFT)
    208			    & CPER_ARM_ERR_TIME_OUT_MASK);
    209		if (time_out)
    210			printk("%srequest timed out\n", pfx);
    211	}
    212
    213	if (error_info & CPER_ARM_ERR_VALID_ADDRESS_SPACE) {
    214		address_space = ((error_info >> CPER_ARM_ERR_ADDRESS_SPACE_SHIFT)
    215				 & CPER_ARM_ERR_ADDRESS_SPACE_MASK);
    216		if (address_space < ARRAY_SIZE(arm_bus_err_addr_space_strs)) {
    217			printk("%saddress space: %s\n", pfx,
    218			       arm_bus_err_addr_space_strs[address_space]);
    219		}
    220	}
    221
    222	if (error_info & CPER_ARM_ERR_VALID_MEM_ATTRIBUTES) {
    223		mem_attributes = ((error_info >> CPER_ARM_ERR_MEM_ATTRIBUTES_SHIFT)
    224				  & CPER_ARM_ERR_MEM_ATTRIBUTES_MASK);
    225		printk("%smemory access attributes:0x%x\n", pfx, mem_attributes);
    226	}
    227
    228	if (error_info & CPER_ARM_ERR_VALID_ACCESS_MODE) {
    229		access_mode = ((error_info >> CPER_ARM_ERR_ACCESS_MODE_SHIFT)
    230			       & CPER_ARM_ERR_ACCESS_MODE_MASK);
    231		if (access_mode)
    232			printk("%saccess mode: normal\n", pfx);
    233		else
    234			printk("%saccess mode: secure\n", pfx);
    235	}
    236}
    237
    238void cper_print_proc_arm(const char *pfx,
    239			 const struct cper_sec_proc_arm *proc)
    240{
    241	int i, len, max_ctx_type;
    242	struct cper_arm_err_info *err_info;
    243	struct cper_arm_ctx_info *ctx_info;
    244	char newpfx[64], infopfx[64];
    245
    246	printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
    247
    248	len = proc->section_length - (sizeof(*proc) +
    249		proc->err_info_num * (sizeof(*err_info)));
    250	if (len < 0) {
    251		printk("%ssection length: %d\n", pfx, proc->section_length);
    252		printk("%ssection length is too small\n", pfx);
    253		printk("%sfirmware-generated error record is incorrect\n", pfx);
    254		printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num);
    255		return;
    256	}
    257
    258	if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
    259		printk("%sMultiprocessor Affinity Register (MPIDR): 0x%016llx\n",
    260			pfx, proc->mpidr);
    261
    262	if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
    263		printk("%serror affinity level: %d\n", pfx,
    264			proc->affinity_level);
    265
    266	if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
    267		printk("%srunning state: 0x%x\n", pfx, proc->running_state);
    268		printk("%sPower State Coordination Interface state: %d\n",
    269			pfx, proc->psci_state);
    270	}
    271
    272	snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
    273
    274	err_info = (struct cper_arm_err_info *)(proc + 1);
    275	for (i = 0; i < proc->err_info_num; i++) {
    276		printk("%sError info structure %d:\n", pfx, i);
    277
    278		printk("%snum errors: %d\n", pfx, err_info->multiple_error + 1);
    279
    280		if (err_info->validation_bits & CPER_ARM_INFO_VALID_FLAGS) {
    281			if (err_info->flags & CPER_ARM_INFO_FLAGS_FIRST)
    282				printk("%sfirst error captured\n", newpfx);
    283			if (err_info->flags & CPER_ARM_INFO_FLAGS_LAST)
    284				printk("%slast error captured\n", newpfx);
    285			if (err_info->flags & CPER_ARM_INFO_FLAGS_PROPAGATED)
    286				printk("%spropagated error captured\n",
    287				       newpfx);
    288			if (err_info->flags & CPER_ARM_INFO_FLAGS_OVERFLOW)
    289				printk("%soverflow occurred, error info is incomplete\n",
    290				       newpfx);
    291		}
    292
    293		printk("%serror_type: %d, %s\n", newpfx, err_info->type,
    294			err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
    295			cper_proc_error_type_strs[err_info->type] : "unknown");
    296		if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
    297			printk("%serror_info: 0x%016llx\n", newpfx,
    298			       err_info->error_info);
    299			snprintf(infopfx, sizeof(infopfx), "%s ", newpfx);
    300			cper_print_arm_err_info(infopfx, err_info->type,
    301						err_info->error_info);
    302		}
    303		if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
    304			printk("%svirtual fault address: 0x%016llx\n",
    305				newpfx, err_info->virt_fault_addr);
    306		if (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
    307			printk("%sphysical fault address: 0x%016llx\n",
    308				newpfx, err_info->physical_fault_addr);
    309		err_info += 1;
    310	}
    311
    312	ctx_info = (struct cper_arm_ctx_info *)err_info;
    313	max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
    314	for (i = 0; i < proc->context_info_num; i++) {
    315		int size = sizeof(*ctx_info) + ctx_info->size;
    316
    317		printk("%sContext info structure %d:\n", pfx, i);
    318		if (len < size) {
    319			printk("%ssection length is too small\n", newpfx);
    320			printk("%sfirmware-generated error record is incorrect\n", pfx);
    321			return;
    322		}
    323		if (ctx_info->type > max_ctx_type) {
    324			printk("%sInvalid context type: %d (max: %d)\n",
    325				newpfx, ctx_info->type, max_ctx_type);
    326			return;
    327		}
    328		printk("%sregister context type: %s\n", newpfx,
    329			arm_reg_ctx_strs[ctx_info->type]);
    330		print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
    331				(ctx_info + 1), ctx_info->size, 0);
    332		len -= size;
    333		ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
    334	}
    335
    336	if (len > 0) {
    337		printk("%sVendor specific error info has %u bytes:\n", pfx,
    338		       len);
    339		print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
    340				len, true);
    341	}
    342}