From 8fc54636e96f1093e944bd29b578b84b08e6182f Mon Sep 17 00:00:00 2001 From: Yonghua Huang Date: Thu, 27 May 2021 09:14:33 +0800 Subject: [PATCH] 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 Acked-by: Yu Wang --- devicemodel/hw/platform/acpi/acpi.c | 22 +++- devicemodel/hw/platform/acpi/rtct.c | 185 +++++++++++++++++++++++++--- devicemodel/include/rtct.h | 27 ++++ 3 files changed, 212 insertions(+), 22 deletions(-) diff --git a/devicemodel/hw/platform/acpi/acpi.c b/devicemodel/hw/platform/acpi/acpi.c index ad61e9afd..6f145df0e 100644 --- a/devicemodel/hw/platform/acpi/acpi.c +++ b/devicemodel/hw/platform/acpi/acpi.c @@ -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, @@ -1178,12 +1181,16 @@ int create_and_inject_vrtct(struct vmctx *ctx) 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 +1203,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 +1214,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(); diff --git a/devicemodel/hw/platform/acpi/rtct.c b/devicemodel/hw/platform/acpi/rtct.c index 5a3db5e38..14f5f7eeb 100644 --- a/devicemodel/hw/platform/acpi/rtct.c +++ b/devicemodel/hw/platform/acpi/rtct.c @@ -22,10 +22,16 @@ #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) +#define RTCT_COMPAT_SIZE (RTCT_ENTRY_HEADER_SIZE + 16) +#define RTCT_SSRAM_V2_SIZE (RTCT_ENTRY_HEADER_SIZE + 24) + #define BITMASK(nr) (1U << nr) #define foreach_rtct_entry(rtct, e) \ @@ -34,6 +40,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 +69,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 +157,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 +209,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 +244,31 @@ static bool is_pcpu_assigned_to_guest(uint32_t lapicid) return false; } +/** + * @brief Check if a given pCPU is assigned to current guest. + * + * @param cache_id Physical cache ID. + * @param cache_level Cache Level, 2 or 3. + * + * @return true if given pCPU is assigned 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 +278,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 +319,76 @@ 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 = 0; + 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; + } + } + 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 +494,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 diff --git a/devicemodel/include/rtct.h b/devicemodel/include/rtct.h index 4ca7c2122..c0269d35a 100644 --- a/devicemodel/include/rtct.h +++ b/devicemodel/include/rtct.h @@ -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;