mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-03 22:17:03 +00:00
Signature of RTCT ACPI table maybe "PTCT"(v1) or "RTCT"(v2). and the MAGIC number in CRL header is also changed from "PTCM" to "RTCM". This patch refine the code to detect RTCT table for both v1 and v2. Tracked-On: #6020 Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
210 lines
6.6 KiB
C
210 lines
6.6 KiB
C
/*
|
|
* Copyright (C) 2020 Intel Corporation. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
#include <types.h>
|
|
#include <asm/lib/bits.h>
|
|
#include <rtl.h>
|
|
#include <util.h>
|
|
#include <logmsg.h>
|
|
#include <misc_cfg.h>
|
|
#include <asm/mmu.h>
|
|
#include <asm/cpu_caps.h>
|
|
#include <asm/rtcm.h>
|
|
|
|
|
|
static uint64_t ssram_bottom_hpa;
|
|
static uint64_t ssram_top_hpa;
|
|
|
|
/* is_sw_sram_initialized is used to tell whether Software SRAM is successfully initialized for all cores */
|
|
static volatile bool is_sw_sram_initialized = false;
|
|
|
|
#ifdef CONFIG_SSRAM_ENABLED
|
|
|
|
#define foreach_rtct_entry(rtct, e) \
|
|
for (e = (void *)rtct + sizeof(struct acpi_table_header); \
|
|
((uint64_t)e - (uint64_t)rtct) < rtct->length; \
|
|
e = (struct rtct_entry *)((uint64_t)e + e->size))
|
|
|
|
#define RTCT_V1 1U
|
|
#define RTCT_V2 2U
|
|
static uint32_t rtct_version = RTCT_V1;
|
|
|
|
static struct rtct_entry_data_rtcm_binary *rtcm_binary = NULL;
|
|
|
|
static struct acpi_table_header *acpi_rtct_tbl = NULL;
|
|
|
|
static inline void *get_rtct_entry_base()
|
|
{
|
|
return (void *)acpi_rtct_tbl + sizeof(*acpi_rtct_tbl);
|
|
}
|
|
|
|
void set_rtct_tbl(void *rtct_tbl_addr)
|
|
{
|
|
acpi_rtct_tbl = rtct_tbl_addr;
|
|
}
|
|
|
|
/*
|
|
*@desc This function parses native RTCT ACPI talbe to figure out the entry to CRL binary
|
|
* and SSRAM range. All SSRAM regions shall be continuous and L3 cache be inclusive.
|
|
*
|
|
*@pre the SSRAM region is separate and never mixed with normal DRAM
|
|
*@pre acpi_rtct_tbl != NULL
|
|
*/
|
|
static void parse_rtct(void)
|
|
{
|
|
uint64_t bottom_hpa = ULONG_MAX;
|
|
struct rtct_entry *entry;
|
|
struct rtct_entry_data_ssram *ssram;
|
|
struct rtct_entry_data_ssram_v2 *ssram_v2;
|
|
struct rtct_entry_data_compatibility *compat;
|
|
|
|
/* Check RTCT format */
|
|
foreach_rtct_entry(acpi_rtct_tbl, entry) {
|
|
if (entry->type == RTCT_V2_COMPATIBILITY) {
|
|
compat = (struct rtct_entry_data_compatibility *)entry->data;
|
|
rtct_version = compat->rtct_ver_major;
|
|
break;
|
|
}
|
|
}
|
|
pr_info("RTCT Version: V%d.\n", rtct_version);
|
|
|
|
if (rtct_version == RTCT_V1) {
|
|
foreach_rtct_entry(acpi_rtct_tbl, entry) {
|
|
if (entry->type == RTCT_ENTRY_TYPE_SOFTWARE_SRAM) {
|
|
ssram = (struct rtct_entry_data_ssram *)entry->data;
|
|
|
|
ssram_top_hpa = max(ssram_top_hpa, ssram->base + ssram->size);
|
|
bottom_hpa = min(bottom_hpa, ssram->base);
|
|
pr_info("found L%d Software SRAM, at HPA %llx, size %x",
|
|
ssram->cache_level, ssram->base, ssram->size);
|
|
} else if (entry->type == RTCT_ENTRY_TYPE_RTCM_BINARY) {
|
|
rtcm_binary = (struct rtct_entry_data_rtcm_binary *)entry->data;
|
|
ASSERT((rtcm_binary->address != 0UL && rtcm_binary->size != 0U),
|
|
"Invalid PTCM binary.");
|
|
}
|
|
}
|
|
} else if (rtct_version == RTCT_V2) {
|
|
foreach_rtct_entry(acpi_rtct_tbl, entry) {
|
|
if (entry->type == RTCT_V2_SSRAM) {
|
|
ssram_v2 = (struct rtct_entry_data_ssram_v2 *)entry->data;
|
|
|
|
ssram_top_hpa = max(ssram_top_hpa, ssram_v2->base + ssram_v2->size);
|
|
bottom_hpa = min(bottom_hpa, ssram_v2->base);
|
|
pr_info("found L%d Software SRAM, at HPA %llx, size %x",
|
|
ssram_v2->cache_level, ssram_v2->base, ssram_v2->size);
|
|
} else if (entry->type == RTCT_V2_CRL_BINARY) {
|
|
rtcm_binary = (struct rtct_entry_data_rtcm_binary *)entry->data;
|
|
ASSERT((rtcm_binary->address != 0UL && rtcm_binary->size != 0U),
|
|
"Invalid PTCM binary.");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bottom_hpa != ULONG_MAX) {
|
|
/* Software SRAM regions are detected. */
|
|
ssram_bottom_hpa = bottom_hpa;
|
|
ssram_top_hpa = round_page_up(ssram_top_hpa);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Function to initialize Software SRAM. Both BSP and APs shall call this function to
|
|
* make sure Software SRAM is initialized, which is required by RTCM.
|
|
* BSP:
|
|
* To parse RTCT and find the entry of RTCM command function
|
|
* AP:
|
|
* Wait until BSP has done the parsing work, then call the RTCM ABI.
|
|
*
|
|
* Synchronization of AP and BSP is ensured, both inside and outside RTCM.
|
|
* BSP shall be the last to finish the call.
|
|
*/
|
|
bool init_software_sram(bool is_bsp)
|
|
{
|
|
bool ret = true;
|
|
int32_t rtcm_ret_code;
|
|
struct rtcm_header *header;
|
|
rtcm_abi_func rtcm_command_func = NULL;
|
|
static uint64_t init_sw_sram_cpus_mask = (1UL << BSP_CPU_ID);
|
|
|
|
/*
|
|
* When we shut down an RTVM, its pCPUs will be re-initialized
|
|
* we must ensure init_software_sram() will only be executed at the first time when a pcpu is booted
|
|
* That's why we add "!is_sw_sram_initialized" as an condition.
|
|
*/
|
|
if (!is_sw_sram_initialized && (acpi_rtct_tbl != NULL)) {
|
|
/* TODO: We may use SMP call to flush TLB and do Software SRAM initialization on APs */
|
|
if (is_bsp) {
|
|
parse_rtct();
|
|
if (rtcm_binary != NULL) {
|
|
/* Clear the NX bit of PTCM area */
|
|
set_paging_x((uint64_t)hpa2hva(rtcm_binary->address), rtcm_binary->size);
|
|
}
|
|
bitmap_clear_lock(get_pcpu_id(), &init_sw_sram_cpus_mask);
|
|
}
|
|
|
|
wait_sync_change(&init_sw_sram_cpus_mask, 0UL);
|
|
if (rtcm_binary != NULL) {
|
|
header = hpa2hva(rtcm_binary->address);
|
|
pr_info("rtcm_bin_address:%llx, rtcm magic:%x, rtcm version:%x",
|
|
rtcm_binary->address, header->magic, header->version);
|
|
ASSERT(((header->magic == RTCM_MAGIC_PTCM) || (header->magic == RTCM_MAGIC_RTCM)),
|
|
"Wrong RTCM magic value!");
|
|
|
|
/* Flush the TLB, so that BSP/AP can execute the RTCM ABI */
|
|
flush_tlb_range((uint64_t)hpa2hva(rtcm_binary->address), rtcm_binary->size);
|
|
rtcm_command_func = (rtcm_abi_func)(hpa2hva(rtcm_binary->address) + header->command_offset);
|
|
pr_info("rtcm command function is found at %llx", rtcm_command_func);
|
|
rtcm_ret_code = rtcm_command_func(RTCM_CMD_INIT_SOFTWARE_SRAM, get_rtct_entry_base());
|
|
pr_info("rtcm initialization return %d", rtcm_ret_code);
|
|
/* return 0 for success, -1 for failure */
|
|
ASSERT(rtcm_ret_code == 0);
|
|
|
|
if (is_bsp) {
|
|
/* Restore the NX bit of RTCM area in page table */
|
|
set_paging_nx((uint64_t)hpa2hva(rtcm_binary->address), rtcm_binary->size);
|
|
}
|
|
|
|
bitmap_set_lock(get_pcpu_id(), &init_sw_sram_cpus_mask);
|
|
wait_sync_change(&init_sw_sram_cpus_mask, ALL_CPUS_MASK);
|
|
/* Flush the TLB on BSP and all APs to restore the NX for Software SRAM area */
|
|
flush_tlb_range((uint64_t)hpa2hva(rtcm_binary->address), rtcm_binary->size);
|
|
|
|
if (is_bsp) {
|
|
is_sw_sram_initialized = true;
|
|
pr_info("BSP Software SRAM has been initialized, base_hpa:0x%lx, top_hpa:0x%lx.\n",
|
|
ssram_bottom_hpa, ssram_top_hpa);
|
|
}
|
|
ret = disable_host_monitor_wait();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
#else
|
|
void set_rtct_tbl(__unused void *rtct_tbl_addr)
|
|
{
|
|
}
|
|
|
|
bool init_software_sram(__unused bool is_bsp)
|
|
{
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
/* @pre called after 'init_software_sram()' done. */
|
|
bool is_software_sram_enabled(void)
|
|
{
|
|
return is_sw_sram_initialized;
|
|
}
|
|
|
|
uint64_t get_software_sram_base(void)
|
|
{
|
|
return ssram_bottom_hpa;
|
|
}
|
|
|
|
uint64_t get_software_sram_size(void)
|
|
{
|
|
return (ssram_top_hpa - ssram_bottom_hpa);
|
|
}
|