dm: add RTCT v2 support for guest

The latest version of RTCT specification is version 2.

 This patch is to add RTCT v2 support for virtual RTCT
 of guest.

Tracked-On: #6020
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Yonghua Huang 2021-05-27 09:14:33 +08:00 committed by wenlingz
parent 69808297b1
commit d0426fd249
3 changed files with 211 additions and 22 deletions

View File

@ -1161,12 +1161,15 @@ static struct {
int create_and_inject_vrtct(struct vmctx *ctx)
{
#define RTCT_NATIVE_FILE_PATH_IN_SOS "/sys/firmware/acpi/tables/PTCT"
#define RTCT_V2_NATIVE_FILE_PATH_IN_SOS "/sys/firmware/acpi/tables/RTCT"
#define RTCT_BUF_LEN 0x200 /* Otherwise, need to modify DSDT_OFFSET corresponding */
int native_rtct_fd;
int rc;
size_t native_rtct_len;
size_t vrtct_len;
uint8_t buf[RTCT_BUF_LEN] = {0};
uint8_t *buf;
uint8_t *vrtct;
struct vm_memmap memmap = {
.type = VM_MMIO,
@ -1176,14 +1179,19 @@ int create_and_inject_vrtct(struct vmctx *ctx)
.prot = PROT_ALL
};
/* Name of native RTCT table is "PTCT"(v1) or "RTCT"(v2) */
native_rtct_fd = open(RTCT_NATIVE_FILE_PATH_IN_SOS, O_RDONLY);
if (native_rtct_fd < 0) {
pr_err("failed to open /sys/firmware/acpi/tables/PTCT !!!!! errno:%d\n", errno);
return -1;
native_rtct_fd = open(RTCT_V2_NATIVE_FILE_PATH_IN_SOS, O_RDONLY);
if (native_rtct_fd < 0) {
pr_err("RTCT file is NOT detected.\n");
return -1;
}
}
native_rtct_len = lseek(native_rtct_fd, 0, SEEK_END);
if (native_rtct_len > RTCT_BUF_LEN) {
pr_err("%s native_rtct_len = %d large than RTCT_BUF_LEN\n", __func__, native_rtct_len);
buf = malloc(native_rtct_len);
if (buf == NULL) {
pr_err("%s failed to allocate buffer, native_rtct_len = %d\n", __func__, native_rtct_len);
return -1;
}
@ -1196,8 +1204,10 @@ int create_and_inject_vrtct(struct vmctx *ctx)
close(native_rtct_fd);
vrtct = build_vrtct(ctx, (void *)buf);
if (vrtct == NULL)
if (vrtct == NULL) {
free(buf);
return -1;
}
vrtct_len = ((struct acpi_table_hdr *)vrtct)->length;
if (vrtct_len > RTCT_BUF_LEN) {
@ -1205,6 +1215,7 @@ int create_and_inject_vrtct(struct vmctx *ctx)
}
memcpy(vm_map_gpa(ctx, ACPI_BASE + RTCT_OFFSET, vrtct_len), vrtct, vrtct_len);
free(vrtct);
free(buf);
memmap.hpa = get_software_sram_base_hpa();
memmap.gpa = get_software_sram_base_gpa();

View File

@ -22,6 +22,9 @@
#include "log.h"
#include "rtct.h"
#define RTCT_V1 1
#define RTCT_V2 2
#define RTCT_ENTRY_HEADER_SIZE 8
#define RTCT_SSRAM_HEADER_SIZE (RTCT_ENTRY_HEADER_SIZE + 20)
#define RTCT_MEM_HI_HEADER_SIZE (RTCT_ENTRY_HEADER_SIZE + 8)
@ -34,6 +37,8 @@
e = (struct rtct_entry *)((uint64_t)e + e->size))
static uint16_t guest_vcpu_num;
static uint32_t guest_l2_cat_shift;
static uint32_t guest_l3_cat_shift;
static uint32_t guest_lapicid_tbl[MAX_PLATFORM_LAPIC_IDS];
static uint64_t software_sram_base_hpa;
@ -61,6 +66,25 @@ static inline void add_rtct_entry(struct acpi_table_hdr *rtct, struct rtct_entry
rtct->length += e->size;
}
/**
* @brief Pass-through a native entry to virtual RTCT.
*
* @param vrtct Pointer to virtual RTCT.
* @param entry Pointer to native RTCT entry.
*
* @return 0 on success and non-zero on fail.
*/
static int vrtct_passthru_native_entry(struct acpi_table_hdr *vrtct, struct rtct_entry *entry)
{
struct rtct_entry *rtct_entry;
rtct_entry = get_free_rtct_entry(vrtct);
memcpy((void *)rtct_entry, (void *)entry, entry->size);
add_rtct_entry(vrtct, rtct_entry);
return 0;
}
/**
* @brief Add a new Software SRAM region entry to virtual RTCT.
*
@ -130,32 +154,50 @@ static int vrtct_add_mem_hierarchy_entry(struct acpi_table_hdr *vrtct, uint32_t
return 0;
}
/**
* @brief Update the base address of Software SRAM regions in vRTCT from
* host physical address(HPA) to guest physical address(GPA).
*
* @param vrtct Pointer to virtual RTCT.
* @param rtct_ver version of virtual RTCT.
*
* @return void
*/
static void remap_software_sram_regions(struct acpi_table_hdr *vrtct)
static void remap_software_sram_regions(struct acpi_table_hdr *vrtct, int rtct_ver)
{
struct rtct_entry *entry;
struct rtct_entry_data_ssram *sw_sram_region;
struct rtct_entry_data_ssram *ssram;
struct rtct_entry_data_ssram_v2 *ssram_v2;
uint64_t hpa_bottom, hpa_top;
hpa_bottom = (uint64_t)-1;
hpa_top = 0;
foreach_rtct_entry(vrtct, entry) {
if (entry->type == RTCT_ENTRY_TYPE_SSRAM) {
sw_sram_region = (struct rtct_entry_data_ssram *)entry->data;
if (hpa_bottom > sw_sram_region->base) {
hpa_bottom = sw_sram_region->base;
}
if (rtct_ver == RTCT_V1) {
foreach_rtct_entry(vrtct, entry) {
if (entry->type == RTCT_ENTRY_TYPE_SSRAM) {
ssram = (struct rtct_entry_data_ssram *)entry->data;
if (hpa_bottom > ssram->base) {
hpa_bottom = ssram->base;
}
if (hpa_top < sw_sram_region->base + sw_sram_region->size) {
hpa_top = sw_sram_region->base + sw_sram_region->size;
if (hpa_top < ssram->base + ssram->size) {
hpa_top = ssram->base + ssram->size;
}
}
}
} else if (rtct_ver == RTCT_V2) {
foreach_rtct_entry(vrtct, entry) {
if (entry->type == RTCT_V2_SSRAM) {
ssram_v2 = (struct rtct_entry_data_ssram_v2 *)entry->data;
if (hpa_bottom > ssram_v2->base) {
hpa_bottom = ssram_v2->base;
}
if (hpa_top < ssram_v2->base + ssram_v2->size) {
hpa_top = ssram_v2->base + ssram_v2->size;
}
}
}
}
@ -164,10 +206,19 @@ static void remap_software_sram_regions(struct acpi_table_hdr *vrtct)
software_sram_base_hpa = hpa_bottom;
software_sram_size = hpa_top - hpa_bottom;
foreach_rtct_entry(vrtct, entry) {
if (entry->type == RTCT_ENTRY_TYPE_SSRAM) {
sw_sram_region = (struct rtct_entry_data_ssram *)entry->data;
sw_sram_region->base = software_sram_base_gpa + (sw_sram_region->base - hpa_bottom);
if (rtct_ver == RTCT_V1) {
foreach_rtct_entry(vrtct, entry) {
if (entry->type == RTCT_ENTRY_TYPE_SSRAM) {
ssram = (struct rtct_entry_data_ssram *)entry->data;
ssram->base = software_sram_base_gpa + (ssram->base - hpa_bottom);
}
}
} else if (rtct_ver == RTCT_V2) {
foreach_rtct_entry(vrtct, entry) {
if (entry->type == RTCT_V2_SSRAM) {
ssram_v2 = (struct rtct_entry_data_ssram_v2 *)entry->data;
ssram_v2->base = software_sram_base_gpa + (ssram_v2->base - hpa_bottom);
}
}
}
}
@ -190,6 +241,31 @@ static bool is_pcpu_assigned_to_guest(uint32_t lapicid)
return false;
}
/**
* @brief Check if a given cache is accessible to current guest.
*
* @param cache_id Physical cache ID.
* @param cache_level Cache Level, 2 or 3.
*
* @return true if given cache is accessible to current guest, else false.
*/
static bool is_cache_accessible_to_guest(uint32_t cache_id, uint32_t cache_level)
{
int i;
uint32_t shift[2];
if ((cache_level != 2) && (cache_level != 3))
return false;
shift[0] = guest_l2_cat_shift;
shift[1] = guest_l3_cat_shift;
for (i = 0; i < guest_vcpu_num; i++) {
if ((guest_lapicid_tbl[i] >> shift[cache_level - 2]) == cache_id)
return true;
}
return false;
}
/**
* @brief Initialize Software SRAM and memory hierarchy entries in virtual RTCT,
* configurations of these entries are from native RTCT.
@ -199,7 +275,7 @@ static bool is_pcpu_assigned_to_guest(uint32_t lapicid)
*
* @return 0 on success and non-zero on fail.
*/
static int passthru_rtct_to_guest(struct acpi_table_hdr *vrtct, struct acpi_table_hdr *native_rtct)
static int init_vrtct_v1(struct acpi_table_hdr *vrtct, struct acpi_table_hdr *native_rtct)
{
int i, plapic_num, vlapic_num, rc = 0;
struct rtct_entry *entry;
@ -240,7 +316,77 @@ static int passthru_rtct_to_guest(struct acpi_table_hdr *vrtct, struct acpi_tabl
return -1;
}
remap_software_sram_regions(vrtct);
return 0;
}
/**
* @brief Initialize Software SRAM and memory hierarchy entries in virtual RTCT,
* configurations of these entries are from native RTCT.
*
* @param vrtct Pointer to virtual RTCT.
* @param native_rtct Pointer to native RTCT.
*
* @return 0 on success and non-zero on fail.
*/
static int init_vrtct_v2(struct acpi_table_hdr *vrtct, struct acpi_table_hdr *native_rtct)
{
int rc = 0;
struct rtct_entry *entry;
struct rtct_entry_data_ssram_v2 *ssram_v2;
foreach_rtct_entry(native_rtct, entry) {
if ((entry->type == RTCT_V2_COMPATIBILITY) ||
(entry->type == RTCT_V2_MEMORY_HIERARCHY_LATENCY)) {
rc = vrtct_passthru_native_entry(vrtct, entry);
} else if (entry->type == RTCT_V2_SSRAM) {
ssram_v2 = (struct rtct_entry_data_ssram_v2 *)entry->data;
if (is_cache_accessible_to_guest(ssram_v2->cache_id, ssram_v2->cache_level)) {
rc = vrtct_passthru_native_entry(vrtct, entry);
}
}
if (rc)
return -1;
}
return 0;
}
/**
* @brief Initialize Software SRAM and memory hierarchy entries in virtual RTCT,
* configurations of these entries are from native RTCT.
*
* @param vrtct Pointer to virtual RTCT.
* @param native_rtct Pointer to native RTCT.
*
* @return 0 on success and non-zero on fail.
*/
static int passthru_rtct_to_guest(struct acpi_table_hdr *vrtct, struct acpi_table_hdr *native_rtct)
{
int rtct_ver = RTCT_V1, rc = -1;
struct rtct_entry *entry;
struct rtct_entry_data_compatibility *compat;
/* get native RTCT version. */
foreach_rtct_entry(native_rtct, entry) {
if (entry->type == RTCT_V2_COMPATIBILITY) {
compat = (struct rtct_entry_data_compatibility *)entry->data;
rtct_ver = compat->RTCT_Ver_Major;
break;
}
}
printf("%s, Native RTCT version:%d.\n", __func__, rtct_ver);
if (rtct_ver == RTCT_V1) {
rc = init_vrtct_v1(vrtct, native_rtct);
} else if (rtct_ver == RTCT_V2) {
rc = init_vrtct_v2(vrtct, native_rtct);
}
if (rc)
return -1;
remap_software_sram_regions(vrtct, rtct_ver);
vrtct->checksum = vrtct_checksum((uint8_t *)vrtct, vrtct->length);
return 0;
}
@ -346,12 +492,17 @@ uint8_t *build_vrtct(struct vmctx *ctx, void *cfg)
__func__, dm_cpu_bitmask, hv_cpu_bitmask, guest_pcpu_bitmask);
guest_vcpu_num = bitmap_weight(guest_pcpu_bitmask);
guest_l2_cat_shift = platform_info.l2_cat_shift;
guest_l3_cat_shift = platform_info.l3_cat_shift;
if (init_guest_lapicid_tbl(&platform_info, guest_pcpu_bitmask) < 0) {
pr_err("%s,init guest lapicid table fail.\n", __func__);
goto error;
}
printf("%s, vcpu_num:%d, l2_shift:%d, l3_shift:%d.\n", __func__,
guest_vcpu_num, guest_l2_cat_shift, guest_l3_cat_shift);
gpu_rsvmem_base_gpa = get_gpu_rsvmem_base_gpa();
software_sram_size = SOFTWARE_SRAM_MAX_SIZE;
/* TODO: It is better to put one boundary between GPU region and SW SRAM

View File

@ -17,6 +17,18 @@
#define RTCT_ENTRY_TYPE_RT_IOMMU 8U
#define RTCT_ENTRY_TYPE_MEM_HIERARCHY_LATENCY 9U
/*Entry IDs for RTCT version 2*/
#define RTCT_V2_COMPATIBILITY 0U
#define RTCT_V2_RTCD_LIMIT 1U
#define RTCT_V2_CRL_BINARY 2U
#define RTCT_V2_IA_WAYMASK 3U
#define RTCT_V2_WRC_WAYMASK 4U
#define RTCT_V2_GT_WAYMASK 5U
#define RTCT_V2_SSRAM_WAYMASK 6U
#define RTCT_V2_SSRAM 7U
#define RTCT_V2_MEMORY_HIERARCHY_LATENCY 8U
#define RTCT_V2_ERROR_LOG_ADDRESS 9U
struct rtct_entry {
uint16_t size;
uint16_t format_version;
@ -24,6 +36,13 @@ struct rtct_entry {
uint32_t data[64];
} __packed;
struct rtct_entry_data_compatibility {
uint32_t RTCT_Ver_Major;
uint32_t RTCT_Ver_Minor;
uint32_t RTCD_Ver_Major;
uint32_t RTCD_Ver_Minor;
} __packed;
struct rtct_entry_data_ssram {
uint32_t cache_level;
uint64_t base;
@ -32,6 +51,14 @@ struct rtct_entry_data_ssram {
uint32_t apic_id_tbl[64];
} __packed;
struct rtct_entry_data_ssram_v2 {
uint32_t cache_level;
uint32_t cache_id;
uint64_t base;
uint32_t size;
uint32_t shared;
} __packed;
struct rtct_entry_data_mem_hi_latency {
uint32_t hierarchy;
uint32_t clock_cycles;