blob: 470b51785e2aa654a7c965f2ec09e1bd06156917 [file] [log] [blame]
Raul E Rangel899be1b2021-02-05 15:50:20 -07001/* SPDX-License-Identifier: GPL-2.0-only */
2
Felix Held6e2f5f22021-02-08 18:16:07 +01003#include <amdblocks/memmap.h>
Raul E Rangel899be1b2021-02-05 15:50:20 -07004#include <console/console.h>
5#include <cbmem.h>
Felix Held6e2f5f22021-02-08 18:16:07 +01006#include <cpu/amd/msr.h>
7#include <cpu/x86/smm.h>
8#include <fsp/util.h>
9#include <FspGuids.h>
10#include <memrange.h>
11#include <stdint.h>
Raul E Rangel899be1b2021-02-05 15:50:20 -070012
13void memmap_stash_early_dram_usage(void)
14{
15 struct memmap_early_dram *e;
16
17 e = cbmem_add(CBMEM_ID_CB_EARLY_DRAM, sizeof(*e));
18
19 if (!e)
20 die("ERROR: Failed to stash early dram usage!\n");
21
22 e->base = (uint32_t)(uintptr_t)_early_reserved_dram;
23 e->size = REGION_SIZE(early_reserved_dram);
24}
25
26const struct memmap_early_dram *memmap_get_early_dram_usage(void)
27{
28 struct memmap_early_dram *e = cbmem_find(CBMEM_ID_CB_EARLY_DRAM);
29
30 if (!e)
31 die("ERROR: Failed to read early dram usage!\n");
32
33 return e;
34}
Felix Held6e2f5f22021-02-08 18:16:07 +010035
36/*
37 * For data stored in TSEG, ensure TValid is clear so R/W access can reach
38 * the DRAM when not in SMM.
39 */
40static void clear_tvalid(void)
41{
42 msr_t hwcr = rdmsr(HWCR_MSR);
43 msr_t mask = rdmsr(SMM_MASK_MSR);
44 int tvalid = !!(mask.lo & SMM_TSEG_VALID);
45
46 if (hwcr.lo & SMM_LOCK) {
47 if (!tvalid) /* not valid but locked means still accessible */
48 return;
49
50 printk(BIOS_ERR, "Error: can't clear TValid, already locked\n");
51 return;
52 }
53
54 mask.lo &= ~SMM_TSEG_VALID;
55 wrmsr(SMM_MASK_MSR, mask);
56}
57
58void smm_region(uintptr_t *start, size_t *size)
59{
60 static int once;
61 struct range_entry tseg;
62 int status;
63
64 *start = 0;
65 *size = 0;
66
67 status = fsp_find_range_hob(&tseg, AMD_FSP_TSEG_HOB_GUID.b);
68
69 if (status < 0) {
70 printk(BIOS_ERR, "Error: unable to find TSEG HOB\n");
71 return;
72 }
73
74 *start = (uintptr_t)range_entry_base(&tseg);
75 *size = range_entry_size(&tseg);
76
77 if (!once) {
78 clear_tvalid();
79 once = 1;
80 }
81}