1 // SPDX-License-Identifier: GPL-2.0-only
3 * UEFI Common Platform Error Record (CPER) support for CXL Section.
5 * Copyright (C) 2022 Advanced Micro Devices, Inc.
10 #include <linux/cper.h>
13 #define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0)
14 #define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1)
15 #define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2)
16 #define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3)
17 #define PROT_ERR_VALID_CAPABILITY BIT_ULL(4)
18 #define PROT_ERR_VALID_DVSEC BIT_ULL(5)
19 #define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6)
21 /* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */
22 struct cxl_ras_capability_regs {
32 static const char * const prot_err_agent_type_strs[] = {
33 "Restricted CXL Device",
34 "Restricted CXL Host Downstream Port",
37 "CXL Fabric Manager managed Logical Device",
39 "CXL Downstream Switch Port",
40 "CXL Upstream Switch Port",
44 * The layout of the enumeration and the values matches CXL Agent Type
45 * field in the UEFI 2.10 Section N.2.13,
48 RCD, /* Restricted CXL Device */
49 RCH_DP, /* Restricted CXL Host Downstream Port */
50 DEVICE, /* CXL Device */
51 LD, /* CXL Logical Device */
52 FMLD, /* CXL Fabric Manager managed Logical Device */
53 RP, /* CXL Root Port */
54 DSP, /* CXL Downstream Switch Port */
55 USP, /* CXL Upstream Switch Port */
58 void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err)
60 if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_TYPE)
61 pr_info("%s agent_type: %d, %s\n", pfx, prot_err->agent_type,
62 prot_err->agent_type < ARRAY_SIZE(prot_err_agent_type_strs)
63 ? prot_err_agent_type_strs[prot_err->agent_type]
66 if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_ADDRESS) {
67 switch (prot_err->agent_type) {
69 * According to UEFI 2.10 Section N.2.13, the term CXL Device
70 * is used to refer to Restricted CXL Device, CXL Device, CXL
71 * Logical Device or a CXL Fabric Manager Managed Logical
81 pr_info("%s agent_address: %04x:%02x:%02x.%x\n",
82 pfx, prot_err->agent_addr.segment,
83 prot_err->agent_addr.bus,
84 prot_err->agent_addr.device,
85 prot_err->agent_addr.function);
88 pr_info("%s rcrb_base_address: 0x%016llx\n", pfx,
89 prot_err->agent_addr.rcrb_base_addr);
96 if (prot_err->valid_bits & PROT_ERR_VALID_DEVICE_ID) {
97 const __u8 *class_code;
99 switch (prot_err->agent_type) {
107 pr_info("%s slot: %d\n", pfx,
108 prot_err->device_id.slot >> CPER_PCIE_SLOT_SHIFT);
109 pr_info("%s vendor_id: 0x%04x, device_id: 0x%04x\n",
110 pfx, prot_err->device_id.vendor_id,
111 prot_err->device_id.device_id);
112 pr_info("%s sub_vendor_id: 0x%04x, sub_device_id: 0x%04x\n",
113 pfx, prot_err->device_id.subsystem_vendor_id,
114 prot_err->device_id.subsystem_id);
115 class_code = prot_err->device_id.class_code;
116 pr_info("%s class_code: %02x%02x\n", pfx,
117 class_code[1], class_code[0]);
124 if (prot_err->valid_bits & PROT_ERR_VALID_SERIAL_NUMBER) {
125 switch (prot_err->agent_type) {
130 pr_info("%s lower_dw: 0x%08x, upper_dw: 0x%08x\n", pfx,
131 prot_err->dev_serial_num.lower_dw,
132 prot_err->dev_serial_num.upper_dw);
139 if (prot_err->valid_bits & PROT_ERR_VALID_CAPABILITY) {
140 switch (prot_err->agent_type) {
148 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4,
149 prot_err->capability,
150 sizeof(prot_err->capability), 0);
157 if (prot_err->valid_bits & PROT_ERR_VALID_DVSEC) {
158 pr_info("%s DVSEC length: 0x%04x\n", pfx, prot_err->dvsec_len);
160 pr_info("%s CXL DVSEC:\n", pfx);
161 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, (prot_err + 1),
162 prot_err->dvsec_len, 0);
165 if (prot_err->valid_bits & PROT_ERR_VALID_ERROR_LOG) {
166 size_t size = sizeof(*prot_err) + prot_err->dvsec_len;
167 struct cxl_ras_capability_regs *cxl_ras;
169 pr_info("%s Error log length: 0x%04x\n", pfx, prot_err->err_len);
171 pr_info("%s CXL Error Log:\n", pfx);
172 cxl_ras = (struct cxl_ras_capability_regs *)((long)prot_err + size);
173 pr_info("%s cxl_ras_uncor_status: 0x%08x", pfx,
174 cxl_ras->uncor_status);
175 pr_info("%s cxl_ras_uncor_mask: 0x%08x\n", pfx,
176 cxl_ras->uncor_mask);
177 pr_info("%s cxl_ras_uncor_severity: 0x%08x\n", pfx,
178 cxl_ras->uncor_severity);
179 pr_info("%s cxl_ras_cor_status: 0x%08x", pfx,
180 cxl_ras->cor_status);
181 pr_info("%s cxl_ras_cor_mask: 0x%08x\n", pfx,
183 pr_info("%s cap_control: 0x%08x\n", pfx,
184 cxl_ras->cap_control);
185 pr_info("%s Header Log Registers:\n", pfx);
186 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, cxl_ras->header_log,
187 sizeof(cxl_ras->header_log), 0);