1 /*
2 * Copyright (C) 2020-2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #include <types.h>
7 #include <asm/lib/bits.h>
8 #include <rtl.h>
9 #include <util.h>
10 #include <logmsg.h>
11 #include <misc_cfg.h>
12 #include <asm/mmu.h>
13 #include <asm/cpu_caps.h>
14 #include <asm/rtcm.h>
15
16
17 static uint64_t ssram_bottom_hpa;
18 static uint64_t ssram_top_hpa;
19
20 /* is_sw_sram_initialized is used to tell whether Software SRAM is successfully initialized for all cores */
21 static volatile bool is_sw_sram_initialized = false;
22
23 #ifdef CONFIG_SSRAM_ENABLED
24
25 #define foreach_rtct_entry(rtct, e) \
26 for (e = (void *)rtct + sizeof(struct acpi_table_header); \
27 ((uint64_t)e - (uint64_t)rtct) < rtct->length; \
28 e = (struct rtct_entry *)((uint64_t)e + e->size))
29
30 #define RTCT_V1 1U
31 #define RTCT_V2 2U
32 static uint32_t rtct_version = RTCT_V1;
33
34 static struct rtct_entry_data_rtcm_binary *rtcm_binary = NULL;
35
36 static struct acpi_table_header *acpi_rtct_tbl = NULL;
37
get_rtct_entry_base()38 static inline void *get_rtct_entry_base()
39 {
40 return (void *)acpi_rtct_tbl + sizeof(*acpi_rtct_tbl);
41 }
42
set_rtct_tbl(void * rtct_tbl_addr)43 void set_rtct_tbl(void *rtct_tbl_addr)
44 {
45 acpi_rtct_tbl = rtct_tbl_addr;
46 }
47
48 /*
49 *@desc This function parses native RTCT ACPI talbe to figure out the entry to CRL binary
50 * and SSRAM range. All SSRAM regions shall be continuous and L3 cache be inclusive.
51 *
52 *@pre the SSRAM region is separate and never mixed with normal DRAM
53 *@pre acpi_rtct_tbl != NULL
54 */
parse_rtct(void)55 static void parse_rtct(void)
56 {
57 uint64_t bottom_hpa = ULONG_MAX;
58 struct rtct_entry *entry;
59 struct rtct_entry_data_ssram *ssram;
60 struct rtct_entry_data_ssram_v2 *ssram_v2;
61 struct rtct_entry_data_compatibility *compat;
62
63 /* Check RTCT format */
64 foreach_rtct_entry(acpi_rtct_tbl, entry) {
65 if (entry->type == RTCT_V2_COMPATIBILITY) {
66 compat = (struct rtct_entry_data_compatibility *)entry->data;
67 rtct_version = compat->rtct_ver_major;
68 break;
69 }
70 }
71 pr_info("RTCT Version: V%d.\n", rtct_version);
72
73 if (rtct_version == RTCT_V1) {
74 foreach_rtct_entry(acpi_rtct_tbl, entry) {
75 if (entry->type == RTCT_ENTRY_TYPE_SOFTWARE_SRAM) {
76 ssram = (struct rtct_entry_data_ssram *)entry->data;
77
78 ssram_top_hpa = max(ssram_top_hpa, ssram->base + ssram->size);
79 bottom_hpa = min(bottom_hpa, ssram->base);
80 pr_info("found L%d Software SRAM, at HPA %llx, size %x",
81 ssram->cache_level, ssram->base, ssram->size);
82 } else if (entry->type == RTCT_ENTRY_TYPE_RTCM_BINARY) {
83 rtcm_binary = (struct rtct_entry_data_rtcm_binary *)entry->data;
84 ASSERT((rtcm_binary->address != 0UL && rtcm_binary->size != 0U),
85 "Invalid PTCM binary.");
86 }
87 }
88 } else if (rtct_version == RTCT_V2) {
89 foreach_rtct_entry(acpi_rtct_tbl, entry) {
90 if (entry->type == RTCT_V2_SSRAM) {
91 ssram_v2 = (struct rtct_entry_data_ssram_v2 *)entry->data;
92
93 ssram_top_hpa = max(ssram_top_hpa, ssram_v2->base + ssram_v2->size);
94 bottom_hpa = min(bottom_hpa, ssram_v2->base);
95 pr_info("found L%d Software SRAM, at HPA %llx, size %x",
96 ssram_v2->cache_level, ssram_v2->base, ssram_v2->size);
97 } else if (entry->type == RTCT_V2_CRL_BINARY) {
98 rtcm_binary = (struct rtct_entry_data_rtcm_binary *)entry->data;
99 ASSERT((rtcm_binary->address != 0UL && rtcm_binary->size != 0U),
100 "Invalid PTCM binary.");
101 }
102 }
103 }
104
105 if (bottom_hpa != ULONG_MAX) {
106 /* Software SRAM regions are detected. */
107 ssram_bottom_hpa = bottom_hpa;
108 ssram_top_hpa = round_page_up(ssram_top_hpa);
109 }
110 }
111
112 /*
113 * Function to initialize Software SRAM. Both BSP and APs shall call this function to
114 * make sure Software SRAM is initialized, which is required by RTCM.
115 * BSP:
116 * To parse RTCT and find the entry of RTCM command function
117 * AP:
118 * Wait until BSP has done the parsing work, then call the RTCM ABI.
119 *
120 * Synchronization of AP and BSP is ensured, both inside and outside RTCM.
121 * BSP shall be the last to finish the call.
122 */
init_software_sram(bool is_bsp)123 bool init_software_sram(bool is_bsp)
124 {
125 bool ret = true;
126 int32_t rtcm_ret_code;
127 struct rtcm_header *header;
128 rtcm_abi_func rtcm_command_func = NULL;
129 static uint64_t init_sw_sram_cpus_mask = (1UL << BSP_CPU_ID);
130
131 /*
132 * When we shut down an RTVM, its pCPUs will be re-initialized
133 * we must ensure init_software_sram() will only be executed at the first time when a pcpu is booted
134 * That's why we add "!is_sw_sram_initialized" as an condition.
135 */
136 if (!is_sw_sram_initialized && (acpi_rtct_tbl != NULL)) {
137 /* TODO: We may use SMP call to flush TLB and do Software SRAM initialization on APs */
138 if (is_bsp) {
139 parse_rtct();
140 if (rtcm_binary != NULL) {
141 /* Clear the NX bit of PTCM area */
142 set_paging_x((uint64_t)hpa2hva(rtcm_binary->address), rtcm_binary->size);
143 }
144 bitmap_clear_lock(get_pcpu_id(), &init_sw_sram_cpus_mask);
145 }
146
147 wait_sync_change(&init_sw_sram_cpus_mask, 0UL);
148 if (rtcm_binary != NULL) {
149 header = hpa2hva(rtcm_binary->address);
150 pr_info("rtcm_bin_address:%llx, rtcm magic:%x, rtcm version:%x",
151 rtcm_binary->address, header->magic, header->version);
152 ASSERT(((header->magic == RTCM_MAGIC_PTCM) || (header->magic == RTCM_MAGIC_RTCM)),
153 "Wrong RTCM magic value!");
154
155 /* Flush the TLB, so that BSP/AP can execute the RTCM ABI */
156 flush_tlb_range((uint64_t)hpa2hva(rtcm_binary->address), rtcm_binary->size);
157 rtcm_command_func = (rtcm_abi_func)(hpa2hva(rtcm_binary->address) + header->command_offset);
158 pr_info("rtcm command function is found at %llx", rtcm_command_func);
159 rtcm_ret_code = rtcm_command_func(RTCM_CMD_INIT_SOFTWARE_SRAM, get_rtct_entry_base());
160 pr_info("rtcm initialization return %d", rtcm_ret_code);
161 /* return 0 for success, -1 for failure */
162 ASSERT(rtcm_ret_code == 0);
163
164 if (is_bsp) {
165 /* Restore the NX bit of RTCM area in page table */
166 set_paging_nx((uint64_t)hpa2hva(rtcm_binary->address), rtcm_binary->size);
167 }
168
169 bitmap_set_lock(get_pcpu_id(), &init_sw_sram_cpus_mask);
170 wait_sync_change(&init_sw_sram_cpus_mask, ALL_CPUS_MASK);
171 /* Flush the TLB on BSP and all APs to restore the NX for Software SRAM area */
172 flush_tlb_range((uint64_t)hpa2hva(rtcm_binary->address), rtcm_binary->size);
173
174 if (is_bsp) {
175 is_sw_sram_initialized = true;
176 pr_info("BSP Software SRAM has been initialized, base_hpa:0x%lx, top_hpa:0x%lx.\n",
177 ssram_bottom_hpa, ssram_top_hpa);
178 }
179 ret = disable_host_monitor_wait();
180 }
181 }
182 return ret;
183 }
184 #else
set_rtct_tbl(__unused void * rtct_tbl_addr)185 void set_rtct_tbl(__unused void *rtct_tbl_addr)
186 {
187 }
188
init_software_sram(__unused bool is_bsp)189 bool init_software_sram(__unused bool is_bsp)
190 {
191 return true;
192 }
193 #endif
194
195 /* @pre called after 'init_software_sram()' done. */
is_software_sram_enabled(void)196 bool is_software_sram_enabled(void)
197 {
198 return is_sw_sram_initialized;
199 }
200
get_software_sram_base(void)201 uint64_t get_software_sram_base(void)
202 {
203 return ssram_bottom_hpa;
204 }
205
get_software_sram_size(void)206 uint64_t get_software_sram_size(void)
207 {
208 return (ssram_top_hpa - ssram_bottom_hpa);
209 }
210