blob: 39b27ec2931e94cc0a6abafa2fe9f48fc340d7a7 [file] [log] [blame]
Arthur Heymans5f6cf612023-07-14 22:37:03 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <bootstate.h>
4#include <stdint.h>
5#include <stdbool.h>
6#include <SilCommon.h>
7#include <Sil-api.h> // needed above ApobCmn.h
8#include <ApobCmn.h>
9#include <device/device.h>
10#include <xPRF-api.h>
11#include <cpu/amd/mtrr.h>
12#include <cbmem.h>
13#include <amdblocks/memmap.h>
14
15#include "opensil.h"
16
17static const char *hole_info_type(MEMORY_HOLE_TYPES type)
18{
19 const struct hole_type {
20 MEMORY_HOLE_TYPES type;
21 const char *string;
22 } types[] = {
23 {UMA, "UMA"},
24 {MMIO, "MMIO"},
25 {PrivilegedDRAM, "PrivilegedDRAM"},
26 {Reserved1TbRemap, "Reserved1TbRemap"},
27 {ReservedSLink, "ReservedSLink"},
28 {ReservedSLinkAlignment, "ReservedSLinkAlignment"},
29 {ReservedDrtm, "ReservedDrtm"},
30 {ReservedCvip, "ReservedCvip"},
31 {ReservedSmuFeatures, "ReservedSmuFeatures"},
32 {ReservedFwtpm, "ReservedFwtpm"},
33 {ReservedMpioC20, "ReservedMpioC20"},
34 {ReservedNbif, "ReservedNbif"},
35 {ReservedCxl, "ReservedCxl"},
36 {ReservedCxlAlignment, "ReservedCxlAlignment"},
37 {ReservedCpuTmr, "ReservedCpuTmr"},
38 {ReservedRasEinj, "ReservedRasEinj"},
39 {MaxMemoryHoleTypes, "MaxMemoryHoleTypes"},
40 };
41
42 int i;
43 for (i = 0; i < ARRAY_SIZE(types); i++)
44 if (type == types[i].type)
45 break;
46 if (i == ARRAY_SIZE(types))
47 return "Unknown type";
48 return types[i].string;
49}
50
51static uint64_t top_of_mem;
52static uint32_t n_holes;
53static MEMORY_HOLE_DESCRIPTOR *hole_info;
54
55static void get_hole_info(void)
56{
57 static bool done;
58 if (done)
59 return;
60 SIL_STATUS status = xPrfGetSystemMemoryMap(&n_holes, &top_of_mem, (void **)&hole_info);
61 SIL_STATUS_report("xPrfGetSystemMemoryMap", status);
62 // Make sure hole_info does not get initialized to something odd by xPRF on failure
63 if (status != SilPass)
64 hole_info = NULL;
65 done = true;
66}
67
68
69static void print_memory_holes(void *unused)
70{
71 get_hole_info();
72 if (hole_info == NULL)
73 return;
74
75 printk(BIOS_DEBUG, "APOB: top of memory 0x%016llx\n", top_of_mem);
76 printk(BIOS_DEBUG, "The following holes are reported in APOB\n");
77 for (int hole = 0; hole < n_holes; hole++) {
78 printk(BIOS_DEBUG, " Base: 0x%016llx, Size: 0x%016llx, Type: %02d:%s\n",
79 hole_info[hole].Base, hole_info[hole].Size, hole_info[hole].Type,
80 hole_info_type(hole_info[hole].Type));
81 }
82}
83
84BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, print_memory_holes, NULL);
85
86// This assumes holes are allocated
Felix Heldfbda3232024-01-30 15:33:34 +010087void add_opensil_memmap(struct device *dev, unsigned long *idx)
Arthur Heymans5f6cf612023-07-14 22:37:03 +020088{
Felix Heldfbda3232024-01-30 15:33:34 +010089 ram_from_to(dev, (*idx)++, 0, 0xa0000);
90 mmio_from_to(dev, (*idx)++, 0xa0000, 0xc0000); // legacy VGA
91 reserved_ram_from_to(dev, (*idx)++, 0xc0000, 1 * MiB); // Option ROM
Arthur Heymans5f6cf612023-07-14 22:37:03 +020092
93 uint32_t mem_usable = (uintptr_t)cbmem_top();
94 uintptr_t early_reserved_dram_start, early_reserved_dram_end;
95 const struct memmap_early_dram *e = memmap_get_early_dram_usage();
96
97 early_reserved_dram_start = e->base;
98 early_reserved_dram_end = e->base + e->size;
99
100 // 1MB - bottom of DRAM reserved for early coreboot usage
Felix Heldfbda3232024-01-30 15:33:34 +0100101 ram_from_to(dev, (*idx)++, 1 * MiB, early_reserved_dram_start);
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200102
103 // DRAM reserved for early coreboot usage
Felix Heldfbda3232024-01-30 15:33:34 +0100104 reserved_ram_from_to(dev, (*idx)++, early_reserved_dram_start,
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200105 early_reserved_dram_end);
106
107 // top of DRAM consumed early - low top usable RAM
108 // cbmem_top() accounts for low UMA and TSEG if they are used.
Felix Heldfbda3232024-01-30 15:33:34 +0100109 ram_from_to(dev, (*idx)++, early_reserved_dram_end,
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200110 mem_usable);
111
112 // Account for UMA and TSEG
113 const uint32_t top_mem = ALIGN_DOWN(rdmsr(TOP_MEM).lo, 1 * MiB);
114 if (mem_usable != top_mem)
Felix Heldfbda3232024-01-30 15:33:34 +0100115 reserved_ram_from_to(dev, (*idx)++, mem_usable, top_mem);
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200116
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200117 // Check if we're done
118 if (top_of_mem <= 0x100000000)
Felix Heldfbda3232024-01-30 15:33:34 +0100119 return;
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200120
121 // Holes in upper DRAM
122 // This assumes all the holes in upper DRAM are continuous
123 get_hole_info();
124 if (hole_info == NULL)
Felix Heldfbda3232024-01-30 15:33:34 +0100125 return;
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200126 uint64_t lowest_upper_hole_base = top_of_mem;
127 uint64_t highest_upper_hole_end = 0x100000000;
128 for (int hole = 0; hole < n_holes; hole++) {
129 if (hole_info[hole].Type == MMIO)
130 continue;
131 if (hole_info[hole].Base < 0x100000000)
132 continue;
133 lowest_upper_hole_base = MIN(lowest_upper_hole_base, hole_info[hole].Base);
134 highest_upper_hole_end = MAX(highest_upper_hole_end, hole_info[hole].Base + hole_info[hole].Size);
135 if (hole_info[hole].Type == UMA)
Felix Heldfbda3232024-01-30 15:33:34 +0100136 mmio_range(dev, (*idx)++, hole_info[hole].Base, hole_info[hole].Size);
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200137 else
Felix Heldfbda3232024-01-30 15:33:34 +0100138 reserved_ram_range(dev, (*idx)++, hole_info[hole].Base, hole_info[hole].Size);
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200139 }
140
Felix Heldfbda3232024-01-30 15:33:34 +0100141 ram_from_to(dev, (*idx)++, 0x100000000, lowest_upper_hole_base);
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200142
143 // Do we need this?
144 if (top_of_mem > highest_upper_hole_end)
Felix Heldfbda3232024-01-30 15:33:34 +0100145 ram_from_to(dev, (*idx)++, highest_upper_hole_end, top_of_mem);
Arthur Heymans5f6cf612023-07-14 22:37:03 +0200146}