blob: 9eb54d95595cd6af9efff6a693b33965befd9443 [file] [log] [blame]
Rocky Phagurad4db36e2021-04-03 08:49:32 -07001/* 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
10static 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
26static 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
59static 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
72unsigned 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 */
Angel Pons5484a952021-11-24 11:34:40 +010078 void *mem = cbmem_add(CBMEM_ID_ACPI_HEST, CONFIG_ERROR_LOG_BUFFER_SIZE);
Rocky Phagurad4db36e2021-04-03 08:49:32 -070079 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
Elyes Haouasd6b6b222022-10-10 12:34:21 +020094 current = ALIGN_UP(current, 8);
Rocky Phagurad4db36e2021-04-03 08:49:32 -070095 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}