/* SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include #include #include static u64 hest_get_elog_addr(void) { /* The elog address comes from reserved memory */ struct global_nvs *gnvs; gnvs = acpi_get_gnvs(); if (!gnvs) { printk(BIOS_ERR, "Unable to get gnvs\n"); return 0; } /* Runtime logging address */ printk(BIOS_DEBUG, "\t status blk start addr = %llx\n", gnvs->hest_log_addr); printk(BIOS_DEBUG, "\t size = %x\n", CONFIG_ERROR_LOG_BUFFER_SIZE); return gnvs->hest_log_addr; } static u32 acpi_hest_add_ghes(void *current) { ghes_record_t *rec = (ghes_record_t *)current; u32 size = sizeof(ghes_record_t); /* Fill GHES error source descriptor */ memset(rec, 0, size); rec->esd.type = HEST_GHES_DESC_TYPE; rec->esd.source_id = 0; /* 0 for MCE check exception source */ rec->esd.enabled = 1; rec->esd.related_src_id = 0xffff; rec->esd.prealloc_erecords = 1; rec->esd.max_section_per_record = 0xf; rec->max_raw_data_length = GHES_MAX_RAW_DATA_LENGTH; /* Add error_status_address */ rec->sts_addr.space_id = 0; rec->sts_addr.bit_width = 0x40; rec->sts_addr.bit_offset = 0; rec->sts_addr.access_size = QWORD_ACCESS; /* Add notification structure */ rec->notify.type = NOTIFY_TYPE_SCI; rec->notify.length = sizeof(acpi_hest_hen_t); rec->err_sts_blk_len = GHEST_ERROR_STATUS_BLOCK_LENGTH; /* error status block entries start address */ if (CONFIG(SOC_ACPI_HEST)) rec->sts_addr.addr = hest_get_elog_addr(); return size; } static unsigned long acpi_fill_hest(acpi_hest_t *hest) { acpi_header_t *header = &(hest->header); void *current; current = (void *)(hest); void *next = current; next = hest + 1; next += acpi_hest_add_ghes(next); hest->error_source_count += 1; header->length += next - current; return header->length; } unsigned long hest_create(unsigned long current, struct acpi_rsdp *rsdp) { struct global_nvs *gnvs; acpi_hest_t *hest; /* Reserve memory for Enhanced error logging */ void *mem = cbmem_add(CMBMEM_ID_ACPI_HEST, CONFIG_ERROR_LOG_BUFFER_SIZE); if (!mem) { printk(BIOS_ERR, "Unable to allocate HEST memory\n"); return current; } printk(BIOS_DEBUG, "HEST memory created: %p\n", mem); gnvs = acpi_get_gnvs(); if (!gnvs) { printk(BIOS_ERR, "Unable to get gnvs\n"); return current; } gnvs->hest_log_addr = (uintptr_t)mem; printk(BIOS_DEBUG, "elog_addr: %llx, size:%x\n", gnvs->hest_log_addr, CONFIG_ERROR_LOG_BUFFER_SIZE); current = ALIGN(current, 8); hest = (acpi_hest_t *)current; acpi_write_hest(hest, acpi_fill_hest); acpi_add_table(rsdp, (void *)current); current += hest->header.length; return current; }