2020-04-04 18:50:57 +02:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2019-04-22 22:55:16 +02:00
|
|
|
|
|
|
|
#define __SIMPLE_DEVICE__
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdint.h>
|
2020-06-11 01:37:23 +02:00
|
|
|
#include <cbmem.h>
|
2019-04-22 22:55:16 +02:00
|
|
|
#include <console/console.h>
|
2019-08-04 18:54:32 +02:00
|
|
|
#include <cpu/x86/smm.h>
|
2019-04-22 22:55:16 +02:00
|
|
|
#include <cpu/amd/msr.h>
|
2020-06-18 17:53:08 +02:00
|
|
|
#include <arch/bert_storage.h>
|
2020-01-21 07:05:31 +01:00
|
|
|
#include <memrange.h>
|
|
|
|
#include <fsp/util.h>
|
|
|
|
#include <FspGuids.h>
|
2020-06-11 01:37:23 +02:00
|
|
|
#include <soc/memmap.h>
|
2019-04-22 22:55:16 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* For data stored in TSEG, ensure TValid is clear so R/W access can reach
|
|
|
|
* the DRAM when not in SMM.
|
|
|
|
*/
|
|
|
|
static void clear_tvalid(void)
|
|
|
|
{
|
|
|
|
msr_t hwcr = rdmsr(HWCR_MSR);
|
|
|
|
msr_t mask = rdmsr(SMM_MASK_MSR);
|
|
|
|
int tvalid = !!(mask.lo & SMM_TSEG_VALID);
|
|
|
|
|
|
|
|
if (hwcr.lo & SMM_LOCK) {
|
|
|
|
if (!tvalid) /* not valid but locked means still accessible */
|
|
|
|
return;
|
|
|
|
|
|
|
|
printk(BIOS_ERR, "Error: can't clear TValid, already locked\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mask.lo &= ~SMM_TSEG_VALID;
|
|
|
|
wrmsr(SMM_MASK_MSR, mask);
|
|
|
|
}
|
|
|
|
|
2019-08-05 11:49:09 +02:00
|
|
|
void smm_region(uintptr_t *start, size_t *size)
|
2019-04-22 22:55:16 +02:00
|
|
|
{
|
2019-08-06 21:14:34 +02:00
|
|
|
static int once;
|
2020-01-21 07:05:31 +01:00
|
|
|
struct range_entry tseg;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
*start = 0;
|
|
|
|
*size = 0;
|
|
|
|
|
|
|
|
status = fsp_find_range_hob(&tseg, AMD_FSP_TSEG_HOB_GUID.b);
|
|
|
|
|
|
|
|
if (status < 0) {
|
|
|
|
printk(BIOS_ERR, "Error: unable to find TSEG HOB\n");
|
|
|
|
return;
|
|
|
|
}
|
2019-04-22 22:55:16 +02:00
|
|
|
|
2020-01-21 07:05:31 +01:00
|
|
|
*start = (uintptr_t)range_entry_base(&tseg);
|
|
|
|
*size = range_entry_size(&tseg);
|
2019-04-22 22:55:16 +02:00
|
|
|
|
2019-08-06 21:14:34 +02:00
|
|
|
if (!once) {
|
|
|
|
clear_tvalid();
|
|
|
|
once = 1;
|
|
|
|
}
|
2019-04-22 22:55:16 +02:00
|
|
|
}
|
2020-06-11 01:37:23 +02:00
|
|
|
|
2020-06-18 17:53:08 +02:00
|
|
|
void bert_reserved_region(void **start, size_t *size)
|
|
|
|
{
|
|
|
|
struct range_entry bert;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
*start = NULL;
|
|
|
|
*size = 0;
|
|
|
|
|
|
|
|
status = fsp_find_range_hob(&bert, AMD_FSP_BERT_HOB_GUID.b);
|
|
|
|
|
|
|
|
if (status < 0) {
|
|
|
|
printk(BIOS_ERR, "Error: unable to find BERT HOB\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*start = (void *)(uintptr_t)range_entry_base(&bert);
|
|
|
|
*size = range_entry_size(&bert);
|
|
|
|
}
|
|
|
|
|
2020-06-11 01:37:23 +02:00
|
|
|
void memmap_stash_early_dram_usage(void)
|
|
|
|
{
|
|
|
|
struct memmap_early_dram *e;
|
|
|
|
|
|
|
|
e = cbmem_add(CBMEM_ID_CB_EARLY_DRAM, sizeof(*e));
|
|
|
|
|
|
|
|
if (!e)
|
|
|
|
die("ERROR: Failed to stash early dram usage!\n");
|
|
|
|
|
|
|
|
e->base = (uint32_t)(uintptr_t)_early_reserved_dram;
|
|
|
|
e->size = REGION_SIZE(early_reserved_dram);
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct memmap_early_dram *memmap_get_early_dram_usage(void)
|
|
|
|
{
|
|
|
|
struct memmap_early_dram *e = cbmem_find(CBMEM_ID_CB_EARLY_DRAM);
|
|
|
|
|
|
|
|
if (!e)
|
|
|
|
die("ERROR: Failed to read early dram usage!\n");
|
|
|
|
|
|
|
|
return e;
|
|
|
|
}
|