1 /* SPDX-License-Identifier: GPL-2.0-only */
7 #include <Sil-api.h> // needed above ApobCmn.h
9 #include <device/device.h>
11 #include <cpu/amd/mtrr.h>
13 #include <amdblocks/memmap.h>
17 static const char *hole_info_type(MEMORY_HOLE_TYPES type
)
19 const struct hole_type
{
20 MEMORY_HOLE_TYPES type
;
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"},
43 for (i
= 0; i
< ARRAY_SIZE(types
); i
++)
44 if (type
== types
[i
].type
)
46 if (i
== ARRAY_SIZE(types
))
47 return "Unknown type";
48 return types
[i
].string
;
51 static uint64_t top_of_mem
;
52 static uint32_t n_holes
;
53 static MEMORY_HOLE_DESCRIPTOR
*hole_info
;
55 static void get_hole_info(void)
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
)
69 static void print_memory_holes(void *unused
)
72 if (hole_info
== NULL
)
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
));
84 BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES
, BS_ON_ENTRY
, print_memory_holes
, NULL
);
86 // This assumes holes are allocated
87 void add_opensil_memmap(struct device
*dev
, unsigned long *idx
)
89 // Account for UMA and TSEG
90 const uint32_t mem_usable
= cbmem_top();
91 const uint32_t top_mem
= ALIGN_DOWN(get_top_of_mem_below_4gb(), 1 * MiB
);
92 if (mem_usable
!= top_mem
)
93 reserved_ram_from_to(dev
, (*idx
)++, mem_usable
, top_mem
);
95 // Check if we're done
96 if (top_of_mem
<= 4ULL * GiB
)
99 // Holes in upper DRAM
100 // This assumes all the holes in upper DRAM are continuous
102 if (hole_info
== NULL
)
104 uint64_t lowest_upper_hole_base
= top_of_mem
;
105 uint64_t highest_upper_hole_end
= 4ULL * GiB
;
106 for (int hole
= 0; hole
< n_holes
; hole
++) {
107 if (hole_info
[hole
].Type
== MMIO
)
109 if (hole_info
[hole
].Base
< 4ULL * GiB
)
111 lowest_upper_hole_base
= MIN(lowest_upper_hole_base
, hole_info
[hole
].Base
);
112 highest_upper_hole_end
= MAX(highest_upper_hole_end
, hole_info
[hole
].Base
+ hole_info
[hole
].Size
);
113 if (hole_info
[hole
].Type
== UMA
)
114 mmio_range(dev
, (*idx
)++, hole_info
[hole
].Base
, hole_info
[hole
].Size
);
116 reserved_ram_range(dev
, (*idx
)++, hole_info
[hole
].Base
, hole_info
[hole
].Size
);
119 ram_from_to(dev
, (*idx
)++, 4ULL * GiB
, lowest_upper_hole_base
);
122 if (top_of_mem
> highest_upper_hole_end
)
123 ram_from_to(dev
, (*idx
)++, highest_upper_hole_end
, top_of_mem
);