xref: /aosp_15_r20/external/coreboot/src/soc/intel/xeon_sp/ras/hest.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <soc/acpi.h>
4 #include <acpi/acpi_gnvs.h>
5 #include <cbmem.h>
6 #include <console/console.h>
7 #include <soc/hest.h>
8 #include <intelblocks/nvs.h>
9 
hest_get_elog_addr(void)10 static u64 hest_get_elog_addr(void)
11 {
12 	/* The elog address comes from reserved memory */
13 	struct global_nvs *gnvs;
14 	gnvs = acpi_get_gnvs();
15 	if (!gnvs) {
16 		printk(BIOS_ERR, "Unable to get gnvs\n");
17 		return 0;
18 	}
19 
20 	/* Runtime logging address */
21 	printk(BIOS_DEBUG, "\t status blk start addr = %llx\n", gnvs->hest_log_addr);
22 	printk(BIOS_DEBUG, "\t size = %x\n", CONFIG_ERROR_LOG_BUFFER_SIZE);
23 	return gnvs->hest_log_addr;
24 }
25 
acpi_hest_add_ghes(void * current)26 static u32 acpi_hest_add_ghes(void *current)
27 {
28 	ghes_record_t *rec = (ghes_record_t *)current;
29 	u32 size = sizeof(ghes_record_t);
30 
31 	/* Fill GHES error source descriptor  */
32 	memset(rec, 0, size);
33 	rec->esd.type = HEST_GHES_DESC_TYPE;
34 	rec->esd.source_id = 0; /* 0 for MCE check exception source */
35 	rec->esd.enabled = 1;
36 	rec->esd.related_src_id = 0xffff;
37 	rec->esd.prealloc_erecords = 1;
38 	rec->esd.max_section_per_record = 0xf;
39 	rec->max_raw_data_length = GHES_MAX_RAW_DATA_LENGTH;
40 
41 	/* Add error_status_address */
42 	rec->sts_addr.space_id = 0;
43 	rec->sts_addr.bit_width = 0x40;
44 	rec->sts_addr.bit_offset = 0;
45 	rec->sts_addr.access_size = QWORD_ACCESS;
46 
47 	/* Add notification structure */
48 	rec->notify.type = NOTIFY_TYPE_SCI;
49 	rec->notify.length = sizeof(acpi_hest_hen_t);
50 	rec->err_sts_blk_len = GHEST_ERROR_STATUS_BLOCK_LENGTH;
51 
52 	/* error status block entries start address */
53 	if (CONFIG(SOC_ACPI_HEST))
54 		rec->sts_addr.addr = hest_get_elog_addr();
55 
56 	return size;
57 }
58 
acpi_fill_hest(acpi_hest_t * hest)59 static unsigned long acpi_fill_hest(acpi_hest_t *hest)
60 {
61 	acpi_header_t *header = &(hest->header);
62 	void *current;
63 	current = (void *)(hest);
64 	void *next = current;
65 	next = hest + 1;
66 	next += acpi_hest_add_ghes(next);
67 	hest->error_source_count += 1;
68 	header->length = next - current;
69 	return header->length;
70 }
71 
hest_create(unsigned long current,struct acpi_rsdp * rsdp)72 unsigned long hest_create(unsigned long current, struct acpi_rsdp *rsdp)
73 {
74 	struct global_nvs *gnvs;
75 	acpi_hest_t *hest;
76 
77 	/* Reserve memory for Enhanced error logging */
78 	void *mem = cbmem_add(CBMEM_ID_ACPI_HEST, CONFIG_ERROR_LOG_BUFFER_SIZE);
79 	if (!mem) {
80 		printk(BIOS_ERR, "Unable to allocate HEST memory\n");
81 		return current;
82 	}
83 
84 	printk(BIOS_DEBUG, "HEST memory created: %p\n", mem);
85 	gnvs = acpi_get_gnvs();
86 	if (!gnvs) {
87 		printk(BIOS_ERR, "Unable to get gnvs\n");
88 		return current;
89 	}
90 	gnvs->hest_log_addr = (uintptr_t)mem;
91 	printk(BIOS_DEBUG, "elog_addr: %llx, size:%x\n", gnvs->hest_log_addr,
92 		CONFIG_ERROR_LOG_BUFFER_SIZE);
93 
94 	current = ALIGN_UP(current, 8);
95 	hest = (acpi_hest_t *)current;
96 	acpi_write_hest(hest, acpi_fill_hest);
97 	acpi_add_table(rsdp, (void *)current);
98 	current += hest->header.length;
99 	return current;
100 }
101