xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/basecode/ramtop/ramtop.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <commonlib/bsd/ipchksum.h>
4 #include <console/console.h>
5 #include <cpu/cpu.h>
6 #include <cpu/x86/mtrr.h>
7 #include <intelbasecode/ramtop.h>
8 #include <pc80/mc146818rtc.h>
9 #include <stdint.h>
10 
11 /* We need a region in CMOS to store the RAMTOP address */
12 
13 #define RAMTOP_SIGNATURE   0x52544F50 /* 'RTOP' */
14 
15 /*
16  * Address of the ramtop byte in CMOS. Should be reserved
17  * in mainboards' cmos.layout and not covered by checksum.
18  */
19 
20 #if CONFIG(USE_OPTION_TABLE)
21 #include "option_table.h"
22 
23 #ifndef CMOS_VSTART_ramtop
24 #error "The `ramtop` CMOS entry is missing, please add it to your cmos.layout."
25 #endif
26 
27 #if CMOS_VSTART_ramtop % 8 != 0
28 #error "The `ramtop` CMOS entry needs to be byte aligned, check your cmos.layout."
29 #endif	// CMOS_VSTART_ramtop % 8 != 0
30 
31 #if CMOS_VLEN_ramtop != (10 * 8)
32 #error "The `ramtop` CMOS entry needs to be 10 bytes long, check your cmos.layout."
33 #endif	// CMOS_VLEN_ramtop != (10 * 8)
34 
35 #else
36 #define CMOS_VSTART_ramtop 800
37 #endif	// CONFIG(USE_OPTION_TABLE)
38 
39 struct ramtop_table {
40 	uint32_t signature;
41 	uint32_t addr;
42 	uint16_t checksum;
43 } __packed;
44 
45 /* Read and validate ramtop_table structure from CMOS */
ramtop_cmos_read(struct ramtop_table * ramtop)46 static int ramtop_cmos_read(struct ramtop_table *ramtop)
47 {
48 	u8 i, *p;
49 	u16 csum;
50 
51 	for (p = (u8 *)ramtop, i = 0; i < sizeof(*ramtop); i++, p++)
52 		*p = cmos_read((CMOS_VSTART_ramtop / 8) + i);
53 
54 	/* Verify signature */
55 	if (ramtop->signature != RAMTOP_SIGNATURE) {
56 		printk(BIOS_DEBUG, "ramtop_table invalid signature\n");
57 		return -1;
58 	}
59 
60 	/* Verify checksum over signature and counter only */
61 	csum = ipchksum(ramtop, offsetof(struct ramtop_table, checksum));
62 
63 	if (csum != ramtop->checksum) {
64 		printk(BIOS_DEBUG, "ramtop_table checksum mismatch\n");
65 		return -1;
66 	}
67 
68 	return 0;
69 }
70 
71 /* Write ramtop_table structure to CMOS */
ramtop_cmos_write(struct ramtop_table * ramtop)72 static void ramtop_cmos_write(struct ramtop_table *ramtop)
73 {
74 	u8 i, *p;
75 
76 	/* Checksum over signature and counter only */
77 	ramtop->checksum = ipchksum(ramtop, offsetof(struct ramtop_table, checksum));
78 
79 	for (p = (u8 *)ramtop, i = 0; i < sizeof(*ramtop); i++, p++)
80 		cmos_write(*p, (CMOS_VSTART_ramtop / 8) + i);
81 }
82 
83 /* Update the RAMTOP if required based on the input top_of_ram address */
update_ramtop(uint32_t addr)84 void update_ramtop(uint32_t addr)
85 {
86 	struct ramtop_table ramtop;
87 
88 	/* Read and update ramtop (if required) */
89 	if (ramtop_cmos_read(&ramtop) < 0) {
90 		/* Structure invalid, re-initialize */
91 		ramtop.signature = RAMTOP_SIGNATURE;
92 		ramtop.addr = 0;
93 	}
94 
95 	/* Update ramtop if required */
96 	if (ramtop.addr == addr)
97 		return;
98 
99 	ramtop.addr = addr;
100 
101 	/* Write the new top_of_ram address to CMOS */
102 	ramtop_cmos_write(&ramtop);
103 
104 	printk(BIOS_DEBUG, "Updated the RAMTOP address into CMOS 0x%x\n", ramtop.addr);
105 }
106 
get_ramtop_addr(void)107 uint32_t get_ramtop_addr(void)
108 {
109 	struct ramtop_table ramtop;
110 
111 	if (ramtop_cmos_read(&ramtop) < 0)
112 		return 0;
113 
114 	return ramtop.addr;
115 }
116 
117 /* Early caching of top_of_ram region */
early_ramtop_enable_cache_range(void)118 void early_ramtop_enable_cache_range(void)
119 {
120 	uint32_t ramtop = get_ramtop_addr();
121 	if (!ramtop)
122 		return;
123 
124 	int mtrr = get_free_var_mtrr();
125 	if (mtrr == -1) {
126 		printk(BIOS_WARNING, "ramtop_table update failure due to no free MTRR available!\n");
127 		return;
128 	}
129 
130 	/*
131 	 * Background: Some SoCs have a critical bug inside the NEM logic which is responsible
132 	 *             for mapping cached memory to physical memory during tear down and
133 	 *             eventually malfunctions if the number of cache sets is not a power of two.
134 	 *             This can lead to runtime hangs.
135 	 *
136 	 * Workaround: To mitigate this issue on affected SoCs, we force the MTRR type to
137 	 *             WC (Write Combining) unless the cache set count is a power of two.
138 	 *             This change alters caching behavior but prevents the runtime failures.
139 	 */
140 	unsigned int mtrr_type = MTRR_TYPE_WRCOMB;
141 	/*
142 	 * We need to make sure late romstage (including FSP-M post mem) will be run
143 	 * cached. Caching 16MB below ramtop is a safe to cover late romstage.
144 	 */
145 	if (is_cache_sets_power_of_two())
146 		mtrr_type = MTRR_TYPE_WRBACK;
147 
148 	set_var_mtrr(mtrr, ramtop - 16 * MiB, 16 * MiB, mtrr_type);
149 }
150