coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
crashlog_lib.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <intelblocks/crashlog.h>
5 #include <string.h>
6 #include <soc/crashlog.h>
7 #include <arch/bert_storage.h>
8 #include <soc/iomap.h>
9 #include <soc/pci_devs.h>
10 
11 /* global crashLog info */
19 static pmc_ipc_discovery_buf_t discovery_buf;
20 static pmc_crashlog_desc_table_t descriptor_table;
21 static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap;
22 static cpu_crashlog_discovery_table_t cpu_cl_disc_tab;
23 
25 {
27 }
28 
29 bool pmc_cl_discovery(void)
30 {
31  u32 tmp_bar_addr = 0, desc_table_addr = 0;
32 
33  const struct pmc_ipc_buffer *req = { 0 };
34  struct pmc_ipc_buffer *res = NULL;
35  uint32_t cmd_reg;
36  int r;
37 
41  printk(BIOS_DEBUG, "cmd_reg from pmc_make_ipc_cmd %d\n", cmd_reg);
42 
43  r = pmc_send_ipc_cmd(cmd_reg, req, res);
44 
45  if (r < 0) {
46  printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
47  return false;
48  }
49  discovery_buf.val_64_bits = ((u64)res->buf[1] << 32) | res->buf[0];
50 
51 
52  if (discovery_buf.bits.supported != 1) {
53  printk(BIOS_DEBUG, "PCH crashlog feature not supported.\n");
54  m_pmc_crashLog_support = false;
55  return false;
56  }
58 
59  /* Program BAR 0 and enable command register memory space decoding */
60  tmp_bar_addr = SPI_BASE_ADDRESS;
63 
64  if (discovery_buf.bits.discov_mechanism == 1) {
65  /* discovery mode */
66  if (discovery_buf.bits.base_offset & BIT(31)) {
67  printk(BIOS_DEBUG, "PCH discovery to be used is disabled.\n");
68  m_pmc_crashLog_present = false;
70  return false;
71  }
72  desc_table_addr = tmp_bar_addr + discovery_buf.bits.desc_tabl_offset;
75  printk(BIOS_DEBUG, "PMC crashLog size in discovery mode : 0x%X\n",
77  } else {
78  /* legacy mode */
79  if (discovery_buf.bits.dis) {
80  printk(BIOS_DEBUG, "PCH crashlog is disabled in legacy mode.\n");
81  m_pmc_crashLog_present = false;
82  return false;
83  }
84  m_pmc_crashLog_size = (discovery_buf.bits.size != 0) ?
85  (discovery_buf.bits.size * sizeof(u32)) : 0xC00;
86  printk(BIOS_DEBUG, "PMC crashlog size in legacy mode = 0x%x\n",
88  }
90 
91  return true;
92 }
93 
95 {
96  u32 base_addr = 0;
97  if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
100  } else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
103  } else {
104  printk(BIOS_ERR, "Invalid TEL_CFG_BAR value %d:\n",
105  cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
106  }
107 
108  return base_addr;
109 }
110 
111 
113 {
114  return SPI_BASE_ADDRESS;
115 }
116 
118 {
119 
120  if (pci_read_config16(PCH_DEV_SRAM, PCI_VENDOR_ID) == 0xFFFF) {
121  printk(BIOS_ERR, "PMC SSRAM PCI device is disabled.\n");
122  return false;
123  }
124 
125  return true;
126 }
127 
128 static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t *cl_devsc_cap)
129 {
130  cl_devsc_cap->cap_data.data = pci_read_config32(SA_DEV_TMT,
132  if (cl_devsc_cap->cap_data.fields.pcie_cap_id != TELEMETRY_EXTENDED_CAP_ID) {
133  printk(BIOS_DEBUG, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
134  cl_devsc_cap->cap_data.fields.pcie_cap_id, TELEMETRY_EXTENDED_CAP_ID);
135  return false;
136  }
137 
138  /* walk through the entries until crashLog entry */
139  cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(SA_DEV_TMT, TEL_DVSEV_ID);
140  int new_offset = 0;
141  while (cl_devsc_cap->devsc_data.fields.devsc_id != CRASHLOG_DVSEC_ID) {
142  if (cl_devsc_cap->cap_data.fields.next_cap_offset == 0
143  || cl_devsc_cap->cap_data.fields.next_cap_offset == 0xFFFF) {
144  printk(BIOS_DEBUG, "Read invalid pcie_cap_id value: : 0x%x\n",
145  cl_devsc_cap->cap_data.fields.pcie_cap_id);
146  return false;
147  }
148  new_offset = cl_devsc_cap->cap_data.fields.next_cap_offset;
149  cl_devsc_cap->cap_data.data = pci_read_config32(SA_DEV_TMT,
150  new_offset + TEL_DVSEC_PCIE_CAP_ID);
151  cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(SA_DEV_TMT,
152  new_offset + TEL_DVSEV_ID);
153  }
154  cpu_crash_version = cl_devsc_cap->devsc_data.fields.devsc_ver;
155 
156  cl_devsc_cap->discovery_data.data = pci_read_config32(SA_DEV_TMT, new_offset
158 
159  return true;
160 }
161 
162 
163 static bool cpu_cl_gen_discovery_table(void)
164 {
165  u32 bar_addr = 0, disc_tab_addr = 0;
166  bar_addr = cl_get_cpu_bar_addr();
167  disc_tab_addr = bar_addr +
168  cpu_cl_devsc_cap.discovery_data.fields.discovery_table_offset;
169  memset(&cpu_cl_disc_tab, 0, sizeof(cpu_crashlog_discovery_table_t));
170 
171  cpu_cl_disc_tab.header.data = ((u64)read32((u32 *)disc_tab_addr) +
172  ((u64)read32((u32 *)(disc_tab_addr + 4)) << 32));
173 
174  cpu_cl_disc_tab.cmd_mailbox.data = read32((u32 *)(disc_tab_addr + 8));
175  cpu_cl_disc_tab.mailbox_data = read32((u32 *)(disc_tab_addr + 12));
176 
177  printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
178  cpu_cl_disc_tab.header.fields.count);
179 
180  if (cpu_cl_disc_tab.header.fields.guid != CPU_CRASHLOG_DISC_TAB_GUID_VALID) {
181  printk(BIOS_ERR, "Invalid CPU crashlog discovery table GUID, expected = 0x%X ,"
182  "actual = 0x%X\n", CPU_CRASHLOG_DISC_TAB_GUID_VALID,
183  cpu_cl_disc_tab.header.fields.guid);
184  return false;
185  }
186 
187  int cur_offset = 0;
188  for (int i = 0; i < cpu_cl_disc_tab.header.fields.count ; i++) {
189  cur_offset = 16 + 8*i;
190  cpu_cl_disc_tab.buffers[i].data = ((u64)read32((u32 *)(disc_tab_addr +
191  cur_offset)) + ((u64)read32((u32 *)
192  (disc_tab_addr + cur_offset + 4)) << 32));
193  printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer: 0x%x size:"
194  "0x%x offset: 0x%x\n", i, cpu_cl_disc_tab.buffers[i].fields.size,
195  cpu_cl_disc_tab.buffers[i].fields.offset);
196  m_cpu_crashLog_size += cpu_cl_disc_tab.buffers[i].fields.size * sizeof(u32);
197  }
198 
200 
201  return true;
202 }
203 
205 {
206  memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
207 
209  printk(BIOS_ERR, "CPU crashlog capability not found.\n");
210  m_cpu_crashLog_support = false;
211  return false;
212  }
213 
214  m_cpu_crashLog_support = true;
215 
216  /* Program BAR address and enable command register memory space decoding */
217  u32 tmp_bar_addr = PCH_PWRM_BASE_ADDRESS;
218  printk(BIOS_DEBUG, "tmp_bar_addr: 0x%X\n", tmp_bar_addr);
219 
220  if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
222  } else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
224  } else {
225  printk(BIOS_DEBUG, "invalid discovery data t_bir_q: 0x%x\n",
226  cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
227  return false;
228  }
230 
232  printk(BIOS_ERR, "CPU crashlog discovery table not valid.\n");
233  m_cpu_crashLog_present = false;
234  return false;
235  }
236  m_cpu_crashLog_present = true;
237 
238  return true;
239 }
240 
242 {
243  memset(&discovery_buf, 0, sizeof(pmc_ipc_discovery_buf_t));
244  memset(&descriptor_table, 0, sizeof(pmc_crashlog_desc_table_t));
245  memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
246 }
247 
248 
250 {
252 }
253 
254 
255 pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void)
256 {
257  return discovery_buf;
258 }
259 
260 
261 pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void)
262 {
263  return descriptor_table;
264 }
265 
266 
268 {
269  return m_pmc_crashLog_size;
270 }
271 
272 
274 {
275  return m_cpu_crashLog_size;
276 }
277 
278 
280 {
281  return m_cpu_crashLog_present;
282 }
283 
284 
286 {
287  return m_pmc_crashLog_present;
288 }
289 
290 
292 {
293  return m_cpu_crashLog_support;
294 }
295 
296 
298 {
299  return m_pmc_crashLog_support;
300 }
301 
302 
303 void update_new_pmc_crashlog_size(u32 *pmc_crash_size)
304 {
305  m_pmc_crashLog_size = *pmc_crash_size;
306 }
307 
308 
309 cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void)
310 {
311  return cpu_cl_disc_tab;
312 }
313 
314 
315 void update_new_cpu_crashlog_size(u32 *cpu_crash_size)
316 {
317  m_cpu_crashLog_size = *cpu_crash_size;
318 }
#define TEL_DVSEC_OFFSET
Definition: crashlog.h:10
#define TELEMETRY_EXTENDED_CAP_ID
Definition: crashlog.h:15
#define CRASHLOG_DVSEC_ID
Definition: crashlog.h:16
#define TEL_DVSEC_TBIR_BAR1
Definition: crashlog.h:18
#define TEL_DVSEV_DISCOVERY_TABLE_OFFSET
Definition: crashlog.h:14
#define TEL_DVSEC_PCIE_CAP_ID
Definition: crashlog.h:11
#define TEL_DVSEV_ID
Definition: crashlog.h:13
#define TEL_DVSEC_TBIR_BAR0
Definition: crashlog.h:17
#define CRASHLOG_MAILBOX_INTF_ADDRESS
Definition: crashlog.h:21
#define SPI_BASE_ADDRESS
Definition: iomap.h:8
static uint32_t read32(const void *addr)
Definition: mmio.h:22
void * memset(void *dstpp, int c, size_t len)
Definition: memset.c:12
int pmc_cl_gen_descriptor_table(u32 desc_table_addr, pmc_crashlog_desc_table_t *descriptor_table)
Definition: crashlog.c:138
#define PMC_IPC_CMD_CRASHLOG
Definition: crashlog.h:16
#define PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY
Definition: crashlog.h:17
#define CPU_CRASHLOG_DISC_TAB_GUID_VALID
Definition: crashlog.h:28
#define printk(level,...)
Definition: stdlib.h:16
static u32 cpu_crash_version
Definition: crashlog_lib.c:18
bool cl_pmc_sram_has_mmio_access(void)
Definition: crashlog_lib.c:117
static bool m_pmc_crashLog_support
Definition: crashlog_lib.c:12
bool cl_pmc_data_present(void)
Definition: crashlog_lib.c:285
int cl_get_total_data_size(void)
Definition: crashlog_lib.c:249
int cl_get_pmc_record_size(void)
Definition: crashlog_lib.c:267
static bool m_pmc_crashLog_present
Definition: crashlog_lib.c:13
cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void)
Definition: crashlog_lib.c:309
static u32 m_cpu_crashLog_size
Definition: crashlog_lib.c:17
static bool cpu_cl_gen_discovery_table(void)
Definition: crashlog_lib.c:163
static pmc_crashlog_desc_table_t descriptor_table
Definition: crashlog_lib.c:20
pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void)
Definition: crashlog_lib.c:255
int cl_get_cpu_record_size(void)
Definition: crashlog_lib.c:273
bool cl_cpu_data_present(void)
Definition: crashlog_lib.c:279
static u32 m_pmc_crashLog_size
Definition: crashlog_lib.c:16
static bool m_cpu_crashLog_present
Definition: crashlog_lib.c:15
static pmc_ipc_discovery_buf_t discovery_buf
Definition: crashlog_lib.c:19
static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap
Definition: crashlog_lib.c:21
bool pmc_crashlog_support(void)
Definition: crashlog_lib.c:297
void update_new_pmc_crashlog_size(u32 *pmc_crash_size)
Definition: crashlog_lib.c:303
u32 cl_get_cpu_bar_addr(void)
Definition: crashlog_lib.c:94
void update_new_cpu_crashlog_size(u32 *cpu_crash_size)
Definition: crashlog_lib.c:315
pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void)
Definition: crashlog_lib.c:261
static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t *cl_devsc_cap)
Definition: crashlog_lib.c:128
bool cpu_crashlog_support(void)
Definition: crashlog_lib.c:291
bool cpu_cl_discovery(void)
Definition: crashlog_lib.c:204
u32 cl_get_cpu_tmp_bar(void)
Definition: crashlog_lib.c:112
static cpu_crashlog_discovery_table_t cpu_cl_disc_tab
Definition: crashlog_lib.c:22
static bool m_cpu_crashLog_support
Definition: crashlog_lib.c:14
bool pmc_cl_discovery(void)
Definition: crashlog_lib.c:29
u32 __weak cl_get_cpu_mb_int_addr(void)
Definition: crashlog_lib.c:24
void reset_discovery_buffers(void)
Definition: crashlog_lib.c:241
#define BIT(nr)
Definition: ec_commands.h:45
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline void pci_or_config16(const struct device *dev, u16 reg, u16 ormask)
Definition: pci_ops.h:180
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
#define PCH_PWRM_BASE_ADDRESS
Definition: iomap.h:70
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define PCI_BASE_ADDRESS_MEM_ATTR_MASK
Definition: pci_def.h:77
#define PCI_COMMAND_MEMORY
Definition: pci_def.h:12
#define PCI_BASE_ADDRESS_0
Definition: pci_def.h:63
#define PCI_COMMAND
Definition: pci_def.h:10
#define PCI_VENDOR_ID
Definition: pci_def.h:8
#define PCI_BASE_ADDRESS_1
Definition: pci_def.h:64
enum cb_err pmc_send_ipc_cmd(uint32_t cmd, const struct pmc_ipc_buffer *wbuf, struct pmc_ipc_buffer *rbuf)
Definition: pmc_ipc.c:81
#define PMC_IPC_CMD_SIZE_SHIFT
Definition: pmc_ipc.h:16
static uint32_t pmc_make_ipc_cmd(uint32_t cmd, uint32_t subcmd, uint32_t size)
Definition: pmc_ipc.h:56
const struct smm_save_state_ops *legacy_ops __weak
Definition: save_state.c:8
#define SA_DEV_TMT
Definition: pci_devs.h:65
#define PCH_DEV_SRAM
Definition: pci_devs.h:130
#define NULL
Definition: stddef.h:19
uint64_t u64
Definition: stdint.h:54
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
uint32_t buf[PMC_IPC_BUF_COUNT]
Definition: pmc_ipc.h:69