From 5979f50fa9fdbb3fb49e2b498f84faa7503c8ed1 Mon Sep 17 00:00:00 2001 From: Xiaoyao Li Date: Tue, 13 May 2025 23:16:51 -0400 Subject: [PATCH 01/35] i386/tcg: Make CPUID_HT and CPUID_EXT3_CMP_LEG supported Since commit c6bd2dd63420 ("i386/cpu: Set up CPUID_HT in x86_cpu_expand_features() instead of cpu_x86_cpuid()") and commit 99a637a86f55 ("i386/cpu: Set and track CPUID_EXT3_CMP_LEG in env->features[FEAT_8000_0001_ECX]"), it gets warnings when booting the VM with vcpus >= 2 and with tcg: qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:EDX.ht [bit 28] qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.80000001H:ECX.cmp-legacy [bit 1] This is because, after the two commits, CPUID_HT and CPUID_EXT3_CMP_LEG are set in env->features[] when vcpus >=2 (in x86_cpu_expand_features()) later in x86_cpu_filter_features() it will check against the TCG supported bits. However, current TCG doesn't mark the two bits as supported, hence the warnings. Fix it by adding the two bits to the supported bits of TCG since multiple vcpus are supported by TCG. Fixes: c6bd2dd63420 ("i386/cpu: Set up CPUID_HT in x86_cpu_expand_features() instead of cpu_x86_cpuid()") Fixes: 99a637a86f55 ("i386/cpu: Set and track CPUID_EXT3_CMP_LEG in env->features[FEAT_8000_0001_ECX]") Reported-by: Ewan Hai Signed-off-by: Xiaoyao Li Link: https://lore.kernel.org/r/20250514031652.838763-2-xiaoyao.li@intel.com Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index ec908d7d36..9689f6374e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -776,11 +776,12 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \ CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \ CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \ - CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS | CPUID_DE) + CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS | CPUID_DE | \ + CPUID_HT) /* partly implemented: CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64) */ /* missing: - CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */ + CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_TM, CPUID_PBE */ /* * Kernel-only features that can be shown to usermode programs even if @@ -848,7 +849,8 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \ CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | \ - CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_KERNEL_FEATURES) + CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_KERNEL_FEATURES | \ + CPUID_EXT3_CMP_LEG) #define TCG_EXT4_FEATURES 0 From 7a48612306768833f8cc87418a5a53e712f26ac1 Mon Sep 17 00:00:00 2001 From: Xiaoyao Li Date: Tue, 13 May 2025 23:16:52 -0400 Subject: [PATCH 02/35] i386/hvf: Make CPUID_HT supported Since Commit c6bd2dd63420 ("i386/cpu: Set up CPUID_HT in x86_cpu_expand_features() instead of cpu_x86_cpuid()"), CPUID_HT will be set in env->features[] in x86_cpu_expand_features() when vcpus >= 2. Later in x86_cpu_filter_features() it will check against the HVF supported bits. It will trigger the warning like qemu-system-x86_64: warning: host doesn't support requested feature: CPUID.01H:EDX.ht [bit 28] Add CPUID_HT to HVF supported CPUID bits to fix it. Signed-off-by: Xiaoyao Li Link: https://lore.kernel.org/r/20250514031652.838763-3-xiaoyao.li@intel.com Signed-off-by: Paolo Bonzini --- target/i386/hvf/x86_cpuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c index fa131b18c6..0798a0cbaf 100644 --- a/target/i386/hvf/x86_cpuid.c +++ b/target/i386/hvf/x86_cpuid.c @@ -73,7 +73,7 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX | - CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS; + CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS | CPUID_HT; ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 | CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID | CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE | From e5894fd6f411c113e2b5f62811e96eeb5b084381 Mon Sep 17 00:00:00 2001 From: Rakesh Jeyasingh Date: Tue, 29 Apr 2025 22:33:53 +0530 Subject: [PATCH 03/35] hw/pci-host/gt64120: Fix endianness handling The GT-64120 PCI controller requires special handling where: 1. Host bridge(bus 0 ,device 0) must never be byte-swapped 2. Other devices follow MByteSwap bit in GT_PCI0_CMD The previous implementation incorrectly swapped all accesses, breaking host bridge detection (lspci -d 11ab:4620). Changes made: 1. Removed gt64120_update_pci_cfgdata_mapping() and moved data_mem initialization to gt64120_realize() for cleaner setup 2. Implemented custom read/write handlers that: - Preserve host bridge accesses (extract32(config_reg,11,13)==0) - apply swapping only for non-bridge devices in big-endian mode Fixes: 145e2198 ("hw/mips/gt64xxx_pci: Endian-swap using PCI_HOST_BRIDGE MemoryRegionOps") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2826 Signed-off-by: Rakesh Jeyasingh Tested-by: Thomas Huth Link: https://lore.kernel.org/r/20250429170354.150581-2-rakeshjb010@gmail.com Signed-off-by: Paolo Bonzini --- hw/pci-host/gt64120.c | 82 +++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/hw/pci-host/gt64120.c b/hw/pci-host/gt64120.c index 56a6ef93b7..b12a25696c 100644 --- a/hw/pci-host/gt64120.c +++ b/hw/pci-host/gt64120.c @@ -320,38 +320,6 @@ static void gt64120_isd_mapping(GT64120State *s) memory_region_transaction_commit(); } -static void gt64120_update_pci_cfgdata_mapping(GT64120State *s) -{ - /* Indexed on MByteSwap bit, see Table 158: PCI_0 Command, Offset: 0xc00 */ - static const MemoryRegionOps *pci_host_data_ops[] = { - &pci_host_data_be_ops, &pci_host_data_le_ops - }; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - - memory_region_transaction_begin(); - - /* - * The setting of the MByteSwap bit and MWordSwap bit in the PCI Internal - * Command Register determines how data transactions from the CPU to/from - * PCI are handled along with the setting of the Endianness bit in the CPU - * Configuration Register. See: - * - Table 16: 32-bit PCI Transaction Endianness - * - Table 158: PCI_0 Command, Offset: 0xc00 - */ - - if (memory_region_is_mapped(&phb->data_mem)) { - memory_region_del_subregion(&s->ISD_mem, &phb->data_mem); - object_unparent(OBJECT(&phb->data_mem)); - } - memory_region_init_io(&phb->data_mem, OBJECT(phb), - pci_host_data_ops[s->regs[GT_PCI0_CMD] & 1], - s, "pci-conf-data", 4); - memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGDATA << 2, - &phb->data_mem, 1); - - memory_region_transaction_commit(); -} - static void gt64120_pci_mapping(GT64120State *s) { memory_region_transaction_begin(); @@ -645,7 +613,6 @@ static void gt64120_writel(void *opaque, hwaddr addr, case GT_PCI0_CMD: case GT_PCI1_CMD: s->regs[saddr] = val & 0x0401fc0f; - gt64120_update_pci_cfgdata_mapping(s); break; case GT_PCI0_TOR: case GT_PCI0_BS_SCS10: @@ -1024,6 +991,48 @@ static const MemoryRegionOps isd_mem_ops = { }, }; +static bool bswap(const GT64120State *s) +{ + PCIHostState *phb = PCI_HOST_BRIDGE(s); + /*check for bus == 0 && device == 0, Bits 11:15 = Device , Bits 16:23 = Bus*/ + bool is_phb_dev0 = extract32(phb->config_reg, 11, 13) == 0; + bool le_mode = FIELD_EX32(s->regs[GT_PCI0_CMD], GT_PCI0_CMD, MByteSwap); + /* Only swap for non-bridge devices in big-endian mode */ + return !le_mode && !is_phb_dev0; +} + +static uint64_t gt64120_pci_data_read(void *opaque, hwaddr addr, unsigned size) +{ + GT64120State *s = opaque; + uint32_t val = pci_host_data_le_ops.read(opaque, addr, size); + + if (bswap(s)) { + val = bswap32(val); + } + return val; +} + +static void gt64120_pci_data_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + GT64120State *s = opaque; + + if (bswap(s)) { + val = bswap32(val); + } + pci_host_data_le_ops.write(opaque, addr, val, size); +} + +static const MemoryRegionOps gt64120_pci_data_ops = { + .read = gt64120_pci_data_read, + .write = gt64120_pci_data_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static void gt64120_reset(DeviceState *dev) { GT64120State *s = GT64120_PCI_HOST_BRIDGE(dev); @@ -1178,7 +1187,6 @@ static void gt64120_reset(DeviceState *dev) gt64120_isd_mapping(s); gt64120_pci_mapping(s); - gt64120_update_pci_cfgdata_mapping(s); } static void gt64120_realize(DeviceState *dev, Error **errp) @@ -1202,6 +1210,12 @@ static void gt64120_realize(DeviceState *dev, Error **errp) memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGADDR << 2, &phb->conf_mem, 1); + memory_region_init_io(&phb->data_mem, OBJECT(phb), + >64120_pci_data_ops, + s, "pci-conf-data", 4); + memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGDATA << 2, + &phb->data_mem, 1); + /* * The whole address space decoded by the GT-64120A doesn't generate From 560375cff3ccedabf1fe5ca1bc7a31b13fdc68e5 Mon Sep 17 00:00:00 2001 From: Rakesh Jeyasingh Date: Tue, 29 Apr 2025 22:33:54 +0530 Subject: [PATCH 04/35] hw/pci-host: Remove unused pci_host_data_be_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_host_data_be_ops became unused after endianness fixes Suggested-by: Paolo Bonzini Signed-off-by: Rakesh Jeyasingh Reviewed-by: Philippe Mathieu-Daudé Tested-by: Thomas Huth Link: https://lore.kernel.org/r/20250429170354.150581-3-rakeshjb010@gmail.com Signed-off-by: Paolo Bonzini --- hw/pci/pci_host.c | 6 ------ include/hw/pci-host/dino.h | 4 ---- include/hw/pci/pci_host.h | 1 - 3 files changed, 11 deletions(-) diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index abe83bbab8..7179d99178 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -217,12 +217,6 @@ const MemoryRegionOps pci_host_data_le_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -const MemoryRegionOps pci_host_data_be_ops = { - .read = pci_host_data_read, - .write = pci_host_data_write, - .endianness = DEVICE_BIG_ENDIAN, -}; - static bool pci_host_needed(void *opaque) { PCIHostState *s = opaque; diff --git a/include/hw/pci-host/dino.h b/include/hw/pci-host/dino.h index fd7975c798..5dc8cdf610 100644 --- a/include/hw/pci-host/dino.h +++ b/include/hw/pci-host/dino.h @@ -109,10 +109,6 @@ static const uint32_t reg800_keep_bits[DINO800_REGS] = { struct DinoState { PCIHostState parent_obj; - /* - * PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops, - * so that we can map PCI_CONFIG_DATA to pci_host_data_be_ops. - */ uint32_t config_reg_dino; /* keep original copy, including 2 lowest bits */ uint32_t iar0; diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h index e52d8ec2cd..954dd446fa 100644 --- a/include/hw/pci/pci_host.h +++ b/include/hw/pci/pci_host.h @@ -68,6 +68,5 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, unsigned len); extern const MemoryRegionOps pci_host_conf_le_ops; extern const MemoryRegionOps pci_host_conf_be_ops; extern const MemoryRegionOps pci_host_data_le_ops; -extern const MemoryRegionOps pci_host_data_be_ops; #endif /* PCI_HOST_H */ From a1b3e82773c4b9f438c2d77f9101fca760b347e6 Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Fri, 16 May 2025 17:11:29 +0800 Subject: [PATCH 05/35] qapi/misc-target: Rename SGXEPCSection to SgxEpcSection QAPI requires strict PascalCase naming style, i.e., only the first letter of a single word is allowed to be uppercase, which could help with readability. Rename SGXEPCSection to SgxEpcSection. Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20250516091130.2374221-2-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- hw/i386/sgx.c | 18 +++++++++--------- qapi/misc-target.json | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c index 5685c4fb80..3c601689eb 100644 --- a/hw/i386/sgx.c +++ b/hw/i386/sgx.c @@ -84,10 +84,10 @@ static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high) ((high & MAKE_64BIT_MASK(0, 20)) << 32); } -static SGXEPCSectionList *sgx_calc_host_epc_sections(void) +static SgxEpcSectionList *sgx_calc_host_epc_sections(void) { - SGXEPCSectionList *head = NULL, **tail = &head; - SGXEPCSection *section; + SgxEpcSectionList *head = NULL, **tail = &head; + SgxEpcSection *section; uint32_t i, type; uint32_t eax, ebx, ecx, edx; uint32_t j = 0; @@ -104,7 +104,7 @@ static SGXEPCSectionList *sgx_calc_host_epc_sections(void) break; } - section = g_new0(SGXEPCSection, 1); + section = g_new0(SgxEpcSection, 1); section->node = j++; section->size = sgx_calc_section_metric(ecx, edx); QAPI_LIST_APPEND(tail, section); @@ -183,17 +183,17 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp) return info; } -static SGXEPCSectionList *sgx_get_epc_sections_list(void) +static SgxEpcSectionList *sgx_get_epc_sections_list(void) { GSList *device_list = sgx_epc_get_device_list(); - SGXEPCSectionList *head = NULL, **tail = &head; - SGXEPCSection *section; + SgxEpcSectionList *head = NULL, **tail = &head; + SgxEpcSection *section; for (; device_list; device_list = device_list->next) { DeviceState *dev = device_list->data; Object *obj = OBJECT(dev); - section = g_new0(SGXEPCSection, 1); + section = g_new0(SgxEpcSection, 1); section->node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP, &error_abort); section->size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP, @@ -237,7 +237,7 @@ SGXInfo *qmp_query_sgx(Error **errp) void hmp_info_sgx(Monitor *mon, const QDict *qdict) { Error *err = NULL; - SGXEPCSectionList *section_list, *section; + SgxEpcSectionList *section_list, *section; g_autoptr(SGXInfo) info = qmp_query_sgx(&err); uint64_t size = 0; diff --git a/qapi/misc-target.json b/qapi/misc-target.json index 42e4a7417d..a1275d3873 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -319,7 +319,7 @@ 'if': 'TARGET_ARM' } ## -# @SGXEPCSection: +# @SgxEpcSection: # # Information about intel SGX EPC section info # @@ -329,7 +329,7 @@ # # Since: 7.0 ## -{ 'struct': 'SGXEPCSection', +{ 'struct': 'SgxEpcSection', 'data': { 'node': 'int', 'size': 'uint64'}} @@ -355,7 +355,7 @@ 'sgx1': 'bool', 'sgx2': 'bool', 'flc': 'bool', - 'sections': ['SGXEPCSection']}, + 'sections': ['SgxEpcSection']}, 'if': 'TARGET_I386' } ## From 88aea26d1880f105b00c352485d3bf1f21d55012 Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Fri, 16 May 2025 17:11:30 +0800 Subject: [PATCH 06/35] qapi/misc-target: Rename SGXInfo to SgxInfo QAPI requires strict PascalCase naming style, i.e., only the first letter of a single word is allowed to be uppercase, which could help with readability. Rename SGXInfo to SgxInfo. Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20250516091130.2374221-3-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- hw/i386/sgx-stub.c | 4 ++-- hw/i386/sgx.c | 14 +++++++------- qapi/misc-target.json | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c index 38ff75e9f3..ccb21a975d 100644 --- a/hw/i386/sgx-stub.c +++ b/hw/i386/sgx-stub.c @@ -10,13 +10,13 @@ void sgx_epc_build_srat(GArray *table_data) { } -SGXInfo *qmp_query_sgx(Error **errp) +SgxInfo *qmp_query_sgx(Error **errp) { error_setg(errp, "SGX support is not compiled in"); return NULL; } -SGXInfo *qmp_query_sgx_capabilities(Error **errp) +SgxInfo *qmp_query_sgx_capabilities(Error **errp) { error_setg(errp, "SGX support is not compiled in"); return NULL; diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c index 3c601689eb..c80203b438 100644 --- a/hw/i386/sgx.c +++ b/hw/i386/sgx.c @@ -153,9 +153,9 @@ static void sgx_epc_reset(void *opaque) } } -SGXInfo *qmp_query_sgx_capabilities(Error **errp) +SgxInfo *qmp_query_sgx_capabilities(Error **errp) { - SGXInfo *info = NULL; + SgxInfo *info = NULL; uint32_t eax, ebx, ecx, edx; Error *local_err = NULL; @@ -166,7 +166,7 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp) return NULL; } - info = g_new0(SGXInfo, 1); + info = g_new0(SgxInfo, 1); host_cpuid(0x7, 0, &eax, &ebx, &ecx, &edx); info->sgx = ebx & (1U << 2) ? true : false; @@ -205,9 +205,9 @@ static SgxEpcSectionList *sgx_get_epc_sections_list(void) return head; } -SGXInfo *qmp_query_sgx(Error **errp) +SgxInfo *qmp_query_sgx(Error **errp) { - SGXInfo *info = NULL; + SgxInfo *info = NULL; X86MachineState *x86ms; PCMachineState *pcms = (PCMachineState *)object_dynamic_cast(qdev_get_machine(), @@ -223,7 +223,7 @@ SGXInfo *qmp_query_sgx(Error **errp) return NULL; } - info = g_new0(SGXInfo, 1); + info = g_new0(SgxInfo, 1); info->sgx = true; info->sgx1 = true; @@ -238,7 +238,7 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict) { Error *err = NULL; SgxEpcSectionList *section_list, *section; - g_autoptr(SGXInfo) info = qmp_query_sgx(&err); + g_autoptr(SgxInfo) info = qmp_query_sgx(&err); uint64_t size = 0; if (err) { diff --git a/qapi/misc-target.json b/qapi/misc-target.json index a1275d3873..6b3c9d8bd5 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -334,7 +334,7 @@ 'size': 'uint64'}} ## -# @SGXInfo: +# @SgxInfo: # # Information about intel Safe Guard eXtension (SGX) support # @@ -350,7 +350,7 @@ # # Since: 6.2 ## -{ 'struct': 'SGXInfo', +{ 'struct': 'SgxInfo', 'data': { 'sgx': 'bool', 'sgx1': 'bool', 'sgx2': 'bool', @@ -363,7 +363,7 @@ # # Returns information about SGX # -# Returns: @SGXInfo +# Returns: @SgxInfo # # Since: 6.2 # @@ -375,14 +375,14 @@ # "sections": [{"node": 0, "size": 67108864}, # {"node": 1, "size": 29360128}]} } ## -{ 'command': 'query-sgx', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } +{ 'command': 'query-sgx', 'returns': 'SgxInfo', 'if': 'TARGET_I386' } ## # @query-sgx-capabilities: # # Returns information from host SGX capabilities # -# Returns: @SGXInfo +# Returns: @SgxInfo # # Since: 6.2 # @@ -394,7 +394,7 @@ # "section" : [{"node": 0, "size": 67108864}, # {"node": 1, "size": 29360128}]} } ## -{ 'command': 'query-sgx-capabilities', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } +{ 'command': 'query-sgx-capabilities', 'returns': 'SgxInfo', 'if': 'TARGET_I386' } ## From c6b8fb0fb1599cffdfe6603f93bba937c1ecb0b1 Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Tue, 13 May 2025 22:31:30 +0800 Subject: [PATCH 07/35] qapi/misc-target: Fix the doc related SGXEPCSection The "sections" field of SGXInfo is used to gather EPC section information for both the guest and the host. Therefore, delete the "for guest" limitation. Additionally, avoid the abbreviation "info" and use "information" instead. And for SGXEPCSection, delete the redundant word "info". Reported-by: Markus Armbruster Signed-off-by: Zhao Liu Acked-by: Markus Armbruster Link: https://lore.kernel.org/r/20250513143131.2008078-2-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- qapi/misc-target.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qapi/misc-target.json b/qapi/misc-target.json index 6b3c9d8bd5..6814708972 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -321,7 +321,7 @@ ## # @SgxEpcSection: # -# Information about intel SGX EPC section info +# Information about intel SGX EPC section # # @node: the numa node # @@ -346,7 +346,7 @@ # # @flc: true if FLC is supported # -# @sections: The EPC sections info for guest (Since: 7.0) +# @sections: The EPC sections information (Since: 7.0) # # Since: 6.2 ## From 7f2131c35c1781ca41c62dc26fd93282e1351323 Mon Sep 17 00:00:00 2001 From: Zhao Liu Date: Tue, 13 May 2025 22:31:31 +0800 Subject: [PATCH 08/35] qapi/misc-target: Fix the doc to distinguish query-sgx and query-sgx-capabilities There're 2 QMP commands: query-sgx and query-sgx-capabilities, but their outputs are very similar and the documentation lacks clear differentiation. From the codes, query-sgx is used to gather guest's SGX capabilities (including SGX related CPUIDs and EPC sections' size, in SGXInfo), and if guest doesn't have SGX, then QEMU will report the error message. On the other hand, query-sgx-capabilities is used to gather host's SGX capabilities (descripted by SGXInfo as well). And if host doesn't support SGX, then QEMU will also report the error message. Considering that SGXInfo is already documented and both these 2 commands have enough error messages (for the exception case in their codes). Therefore the QAPI documentation for these two commands only needs to emphasize that one of them applies to the guest and the other to the host. Fix their documentation to reflect this difference. Reported-by: Markus Armbruster Suggested-by: Paolo Bonzini Signed-off-by: Zhao Liu Acked-by: Markus Armbruster Link: https://lore.kernel.org/r/20250513143131.2008078-3-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- qapi/misc-target.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qapi/misc-target.json b/qapi/misc-target.json index 6814708972..f7ec695caa 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -361,7 +361,7 @@ ## # @query-sgx: # -# Returns information about SGX +# Returns information about configured SGX capabilities of guest # # Returns: @SgxInfo # @@ -380,7 +380,7 @@ ## # @query-sgx-capabilities: # -# Returns information from host SGX capabilities +# Returns information about SGX capabilities of host # # Returns: @SgxInfo # From 82c81c07e83670befc61333e0bdf3d810e581219 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 12:00:14 +0100 Subject: [PATCH 09/35] hw/riscv: acpi: only create RHCT MMU entry for supported types Do not create the RHCT MMU type entry for RV32 CPUs, since it only has definitions for SV39/SV48/SV57. Likewise, check that satp_mode_max_from_map() will actually return a valid value, skipping the MMU type entry if all MMU types were disabled on the command line. Acked-by: Alistair Francis Signed-off-by: Paolo Bonzini --- hw/riscv/virt-acpi-build.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index 1eef2fb4eb..e693d529e1 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -288,6 +288,7 @@ static void build_rhct(GArray *table_data, RISCVCPU *cpu = &s->soc[0].harts[0]; uint32_t mmu_offset = 0; uint8_t satp_mode_max; + bool rv32 = riscv_cpu_is_32bit(cpu); g_autofree char *isa = NULL; AcpiTable table = { .sig = "RHCT", .rev = 1, .oem_id = s->oem_id, @@ -307,7 +308,8 @@ static void build_rhct(GArray *table_data, num_rhct_nodes++; } - if (cpu->cfg.satp_mode.supported != 0) { + if (!rv32 && cpu->cfg.satp_mode.supported != 0 && + (cpu->cfg.satp_mode.map & ~(1 << VM_1_10_MBARE))) { num_rhct_nodes++; } @@ -367,7 +369,8 @@ static void build_rhct(GArray *table_data, } /* MMU node structure */ - if (cpu->cfg.satp_mode.supported != 0) { + if (!rv32 && cpu->cfg.satp_mode.supported != 0 && + (cpu->cfg.satp_mode.map & ~(1 << VM_1_10_MBARE))) { satp_mode_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); mmu_offset = table_data->len - table.table_offset; build_append_int_noprefix(table_data, 2, 2); /* Type */ @@ -382,7 +385,7 @@ static void build_rhct(GArray *table_data, } else if (satp_mode_max == VM_1_10_SV39) { build_append_int_noprefix(table_data, 0, 1); /* Sv39 */ } else { - assert(1); + g_assert_not_reached(); } } From b22cfa0f44e360d09595705cea8c97be692e2080 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 13:04:22 +0100 Subject: [PATCH 10/35] target/riscv: assert argument to set_satp_mode_max_supported is valid Check that the argument to set_satp_mode_max_supported is valid for the MXL value of the CPU. It would be a bug in the CPU definition if it weren't. In fact, there is such a bug in riscv_bare_cpu_init(): not just SV64 is not a valid VM mode for 32-bit CPUs, SV64 is not a valid VM mode at all, not yet at least. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d92874baa0..0f7ce5305b 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -444,6 +444,8 @@ static void set_satp_mode_max_supported(RISCVCPU *cpu, cpu->cfg.satp_mode.supported |= (1 << i); } } + + assert(cpu->cfg.satp_mode.supported & (1 << satp_mode)); } /* Set the satp mode to the max supported */ @@ -1497,7 +1499,9 @@ static void riscv_bare_cpu_init(Object *obj) * satp_mode manually (see set_satp_mode_default()). */ #ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_SV64); + set_satp_mode_max_supported(RISCV_CPU(obj), + riscv_cpu_mxl(&RISCV_CPU(obj)->env) == MXL_RV32 ? + VM_1_10_SV32 : VM_1_10_SV57); #endif } From 357ce8171a9c7581ba02475874c8c28ed5220d9e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 10:52:09 +0100 Subject: [PATCH 11/35] target/riscv: cpu: store max SATP mode as a single integer The maximum available SATP mode implies all the shorter virtual address sizes. Store it in RISCVCPUConfig and avoid recomputing it via satp_mode_max_from_map. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 11 +++++------ target/riscv/cpu_cfg.h | 1 + target/riscv/tcg/tcg-cpu.c | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 0f7ce5305b..32c283a662 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -446,6 +446,7 @@ static void set_satp_mode_max_supported(RISCVCPU *cpu, } assert(cpu->cfg.satp_mode.supported & (1 << satp_mode)); + cpu->cfg.max_satp_mode = satp_mode; } /* Set the satp mode to the max supported */ @@ -1172,16 +1173,13 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) { bool rv32 = riscv_cpu_is_32bit(cpu); - uint8_t satp_mode_map_max, satp_mode_supported_max; + uint8_t satp_mode_map_max; /* The CPU wants the OS to decide which satp mode to use */ if (cpu->cfg.satp_mode.supported == 0) { return; } - satp_mode_supported_max = - satp_mode_max_from_map(cpu->cfg.satp_mode.supported); - if (cpu->cfg.satp_mode.map == 0) { if (cpu->cfg.satp_mode.init == 0) { /* If unset by the user, we fallback to the default satp mode. */ @@ -1210,10 +1208,10 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) satp_mode_map_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); /* Make sure the user asked for a supported configuration (HW and qemu) */ - if (satp_mode_map_max > satp_mode_supported_max) { + if (satp_mode_map_max > cpu->cfg.max_satp_mode) { error_setg(errp, "satp_mode %s is higher than hw max capability %s", satp_mode_str(satp_mode_map_max, rv32), - satp_mode_str(satp_mode_supported_max, rv32)); + satp_mode_str(cpu->cfg.max_satp_mode, rv32)); return; } @@ -1473,6 +1471,7 @@ static void riscv_cpu_init(Object *obj) cpu->cfg.cbop_blocksize = 64; cpu->cfg.cboz_blocksize = 64; cpu->env.vext_ver = VEXT_VERSION_1_00_0; + cpu->cfg.max_satp_mode = -1; } static void riscv_bare_cpu_init(Object *obj) diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index cfe371b829..c8ea5cdc87 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -196,6 +196,7 @@ struct RISCVCPUConfig { bool short_isa_string; + int8_t max_satp_mode; RISCVSATPMap satp_mode; }; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 55e00972b7..ab8659f304 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -816,8 +816,9 @@ static bool riscv_cpu_validate_profile_satp(RISCVCPU *cpu, RISCVCPUProfile *profile, bool send_warn) { - int satp_max = satp_mode_max_from_map(cpu->cfg.satp_mode.supported); + int satp_max = cpu->cfg.max_satp_mode; + assert(satp_max >= 0); if (profile->satp_mode > satp_max) { if (send_warn) { bool is_32bit = riscv_cpu_is_32bit(cpu); From 211c7f9bb817ca7bb7855535da4db5ca80a8aa1d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 11:09:15 +0100 Subject: [PATCH 12/35] target/riscv: update max_satp_mode based on QOM properties Almost all users of cpu->cfg.satp_mode care about the "max" value satp_mode_max_from_map(cpu->cfg.satp_mode.map). Convert the QOM properties back into it. For TCG, deduce the bitmap of supported modes from valid_vm[]. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- hw/riscv/virt-acpi-build.c | 14 +++++--------- hw/riscv/virt.c | 5 ++--- target/riscv/cpu.c | 27 ++++++++++----------------- target/riscv/cpu.h | 1 - target/riscv/csr.c | 9 +++++++-- 5 files changed, 24 insertions(+), 32 deletions(-) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index e693d529e1..8b5683dbde 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -287,7 +287,6 @@ static void build_rhct(GArray *table_data, uint32_t isa_offset, num_rhct_nodes, cmo_offset = 0; RISCVCPU *cpu = &s->soc[0].harts[0]; uint32_t mmu_offset = 0; - uint8_t satp_mode_max; bool rv32 = riscv_cpu_is_32bit(cpu); g_autofree char *isa = NULL; @@ -308,8 +307,7 @@ static void build_rhct(GArray *table_data, num_rhct_nodes++; } - if (!rv32 && cpu->cfg.satp_mode.supported != 0 && - (cpu->cfg.satp_mode.map & ~(1 << VM_1_10_MBARE))) { + if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) { num_rhct_nodes++; } @@ -369,20 +367,18 @@ static void build_rhct(GArray *table_data, } /* MMU node structure */ - if (!rv32 && cpu->cfg.satp_mode.supported != 0 && - (cpu->cfg.satp_mode.map & ~(1 << VM_1_10_MBARE))) { - satp_mode_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); + if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) { mmu_offset = table_data->len - table.table_offset; build_append_int_noprefix(table_data, 2, 2); /* Type */ build_append_int_noprefix(table_data, 8, 2); /* Length */ build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ build_append_int_noprefix(table_data, 0, 1); /* Reserved */ /* MMU Type */ - if (satp_mode_max == VM_1_10_SV57) { + if (cpu->cfg.max_satp_mode == VM_1_10_SV57) { build_append_int_noprefix(table_data, 2, 1); /* Sv57 */ - } else if (satp_mode_max == VM_1_10_SV48) { + } else if (cpu->cfg.max_satp_mode == VM_1_10_SV48) { build_append_int_noprefix(table_data, 1, 1); /* Sv48 */ - } else if (satp_mode_max == VM_1_10_SV39) { + } else if (cpu->cfg.max_satp_mode == VM_1_10_SV39) { build_append_int_noprefix(table_data, 0, 1); /* Sv39 */ } else { g_assert_not_reached(); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 0dcced1b49..cf280a92e5 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -237,10 +237,10 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket, uint32_t cpu_phandle; MachineState *ms = MACHINE(s); bool is_32_bit = riscv_is_32bit(&s->soc[0]); - uint8_t satp_mode_max; for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) { RISCVCPU *cpu_ptr = &s->soc[socket].harts[cpu]; + int8_t satp_mode_max = cpu_ptr->cfg.max_satp_mode; g_autofree char *cpu_name = NULL; g_autofree char *core_name = NULL; g_autofree char *intc_name = NULL; @@ -252,8 +252,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket, s->soc[socket].hartid_base + cpu); qemu_fdt_add_subnode(ms->fdt, cpu_name); - if (cpu_ptr->cfg.satp_mode.supported != 0) { - satp_mode_max = satp_mode_max_from_map(cpu_ptr->cfg.satp_mode.map); + if (satp_mode_max != -1) { sv_name = g_strdup_printf("riscv,%s", satp_mode_str(satp_mode_max, is_32_bit)); qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type", sv_name); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 32c283a662..48576bff92 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -389,7 +389,7 @@ static uint8_t satp_mode_from_str(const char *satp_mode_str) g_assert_not_reached(); } -uint8_t satp_mode_max_from_map(uint32_t map) +static uint8_t satp_mode_max_from_map(uint32_t map) { /* * 'map = 0' will make us return (31 - 32), which C will @@ -455,15 +455,13 @@ static void set_satp_mode_default_map(RISCVCPU *cpu) /* * Bare CPUs do not default to the max available. * Users must set a valid satp_mode in the command - * line. + * line. Otherwise, leave the existing max_satp_mode + * in place. */ if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_BARE_CPU) != NULL) { warn_report("No satp mode set. Defaulting to 'bare'"); - cpu->cfg.satp_mode.map = (1 << VM_1_10_MBARE); - return; + cpu->cfg.max_satp_mode = VM_1_10_MBARE; } - - cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported; } #endif @@ -1175,8 +1173,8 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) bool rv32 = riscv_cpu_is_32bit(cpu); uint8_t satp_mode_map_max; - /* The CPU wants the OS to decide which satp mode to use */ - if (cpu->cfg.satp_mode.supported == 0) { + if (cpu->cfg.max_satp_mode == -1) { + /* The CPU wants the hypervisor to decide which satp mode to allow */ return; } @@ -1195,14 +1193,14 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) (cpu->cfg.satp_mode.supported & (1 << i))) { for (int j = i - 1; j >= 0; --j) { if (cpu->cfg.satp_mode.supported & (1 << j)) { - cpu->cfg.satp_mode.map |= (1 << j); - break; + cpu->cfg.max_satp_mode = j; + return; } } - break; } } } + return; } satp_mode_map_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); @@ -1232,12 +1230,7 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) } } - /* Finally expand the map so that all valid modes are set */ - for (int i = satp_mode_map_max - 1; i >= 0; --i) { - if (cpu->cfg.satp_mode.supported & (1 << i)) { - cpu->cfg.satp_mode.map |= (1 << i); - } - } + cpu->cfg.max_satp_mode = satp_mode_map_max; } #endif diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index b56d3afa69..3d89a4a83b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -930,7 +930,6 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs); target_ulong riscv_new_csr_seed(target_ulong new_value, target_ulong write_mask); -uint8_t satp_mode_max_from_map(uint32_t map); const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit); /* Implemented in th_csr.c */ diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 288edeedea..9843fd2191 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1912,8 +1912,13 @@ static RISCVException read_mstatus(CPURISCVState *env, int csrno, static bool validate_vm(CPURISCVState *env, target_ulong vm) { - uint64_t mode_supported = riscv_cpu_cfg(env)->satp_mode.map; - return get_field(mode_supported, (1 << vm)); + bool rv32 = riscv_cpu_mxl(env) == MXL_RV32; + RISCVCPU *cpu = env_archcpu(env); + int satp_mode_supported_max = cpu->cfg.max_satp_mode; + const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64; + + assert(satp_mode_supported_max >= 0); + return vm <= satp_mode_supported_max && valid_vm[vm]; } static target_ulong legalize_xatp(CPURISCVState *env, target_ulong old_xatp, From dabb54c160b84d648f375d8f7688fb1099ba32ab Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 11:09:15 +0100 Subject: [PATCH 13/35] target/riscv: remove supported from RISCVSATPMap "supported" can be computed on the fly based on the max_satp_mode. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 34 ++++++++++++++++++++++++---------- target/riscv/cpu_cfg.h | 4 +--- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 48576bff92..0326cd8e56 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -439,14 +439,27 @@ static void set_satp_mode_max_supported(RISCVCPU *cpu, bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32; const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64; - for (int i = 0; i <= satp_mode; ++i) { - if (valid_vm[i]) { - cpu->cfg.satp_mode.supported |= (1 << i); - } + assert(valid_vm[satp_mode]); + cpu->cfg.max_satp_mode = satp_mode; +} + +static bool get_satp_mode_supported(RISCVCPU *cpu, uint16_t *supported) +{ + bool rv32 = riscv_cpu_is_32bit(cpu); + const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64; + int satp_mode = cpu->cfg.max_satp_mode; + + if (satp_mode == -1) { + return false; } - assert(cpu->cfg.satp_mode.supported & (1 << satp_mode)); - cpu->cfg.max_satp_mode = satp_mode; + *supported = 0; + for (int i = 0; i <= satp_mode; ++i) { + if (valid_vm[i]) { + *supported |= (1 << i); + } + } + return true; } /* Set the satp mode to the max supported */ @@ -1171,9 +1184,10 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) { bool rv32 = riscv_cpu_is_32bit(cpu); + uint16_t supported; uint8_t satp_mode_map_max; - if (cpu->cfg.max_satp_mode == -1) { + if (!get_satp_mode_supported(cpu, &supported)) { /* The CPU wants the hypervisor to decide which satp mode to allow */ return; } @@ -1190,9 +1204,9 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) */ for (int i = 1; i < 16; ++i) { if ((cpu->cfg.satp_mode.init & (1 << i)) && - (cpu->cfg.satp_mode.supported & (1 << i))) { + supported & (1 << i)) { for (int j = i - 1; j >= 0; --j) { - if (cpu->cfg.satp_mode.supported & (1 << j)) { + if (supported & (1 << j)) { cpu->cfg.max_satp_mode = j; return; } @@ -1221,7 +1235,7 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) for (int i = satp_mode_map_max - 1; i >= 0; --i) { if (!(cpu->cfg.satp_mode.map & (1 << i)) && (cpu->cfg.satp_mode.init & (1 << i)) && - (cpu->cfg.satp_mode.supported & (1 << i))) { + (supported & (1 << i))) { error_setg(errp, "cannot disable %s satp mode if %s " "is enabled", satp_mode_str(i, false), satp_mode_str(satp_mode_map_max, false)); diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index c8ea5cdc87..8b80e03c9a 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -29,11 +29,9 @@ * * init is a 16-bit bitmap used to make sure the user selected a correct * configuration as per the specification. - * - * supported is a 16-bit bitmap used to reflect the hw capabilities. */ typedef struct { - uint16_t map, init, supported; + uint16_t map, init; } RISCVSATPMap; struct RISCVCPUConfig { From 80b22be3820f1076d9de1b1f1646ae6b352d7675 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 11:27:12 +0100 Subject: [PATCH 14/35] target/riscv: move satp_mode.{map,init} out of CPUConfig They are used to provide the nice QOM properties for svNN, but the canonical source of the CPU configuration is now cpu->cfg.max_satp_mode. Store them in the ArchCPU struct. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 32 ++++++++++++++++---------------- target/riscv/cpu.h | 14 ++++++++++++++ target/riscv/cpu_cfg.h | 14 -------------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 0326cd8e56..54a996c292 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1192,8 +1192,8 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) return; } - if (cpu->cfg.satp_mode.map == 0) { - if (cpu->cfg.satp_mode.init == 0) { + if (cpu->satp_modes.map == 0) { + if (cpu->satp_modes.init == 0) { /* If unset by the user, we fallback to the default satp mode. */ set_satp_mode_default_map(cpu); } else { @@ -1203,7 +1203,7 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) * valid_vm_1_10_32/64. */ for (int i = 1; i < 16; ++i) { - if ((cpu->cfg.satp_mode.init & (1 << i)) && + if ((cpu->satp_modes.init & (1 << i)) && supported & (1 << i)) { for (int j = i - 1; j >= 0; --j) { if (supported & (1 << j)) { @@ -1217,7 +1217,7 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) return; } - satp_mode_map_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); + satp_mode_map_max = satp_mode_max_from_map(cpu->satp_modes.map); /* Make sure the user asked for a supported configuration (HW and qemu) */ if (satp_mode_map_max > cpu->cfg.max_satp_mode) { @@ -1233,8 +1233,8 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) */ if (!rv32) { for (int i = satp_mode_map_max - 1; i >= 0; --i) { - if (!(cpu->cfg.satp_mode.map & (1 << i)) && - (cpu->cfg.satp_mode.init & (1 << i)) && + if (!(cpu->satp_modes.map & (1 << i)) && + (cpu->satp_modes.init & (1 << i)) && (supported & (1 << i))) { error_setg(errp, "cannot disable %s satp mode if %s " "is enabled", satp_mode_str(i, false), @@ -1322,11 +1322,11 @@ bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu) static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - RISCVSATPMap *satp_map = opaque; + RISCVSATPModes *satp_modes = opaque; uint8_t satp = satp_mode_from_str(name); bool value; - value = satp_map->map & (1 << satp); + value = satp_modes->map & (1 << satp); visit_type_bool(v, name, &value, errp); } @@ -1334,7 +1334,7 @@ static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name, static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - RISCVSATPMap *satp_map = opaque; + RISCVSATPModes *satp_modes = opaque; uint8_t satp = satp_mode_from_str(name); bool value; @@ -1342,8 +1342,8 @@ static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name, return; } - satp_map->map = deposit32(satp_map->map, satp, 1, value); - satp_map->init |= 1 << satp; + satp_modes->map = deposit32(satp_modes->map, satp, 1, value); + satp_modes->init |= 1 << satp; } void riscv_add_satp_mode_properties(Object *obj) @@ -1352,16 +1352,16 @@ void riscv_add_satp_mode_properties(Object *obj) if (cpu->env.misa_mxl == MXL_RV32) { object_property_add(obj, "sv32", "bool", cpu_riscv_get_satp, - cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode); + cpu_riscv_set_satp, NULL, &cpu->satp_modes); } else { object_property_add(obj, "sv39", "bool", cpu_riscv_get_satp, - cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode); + cpu_riscv_set_satp, NULL, &cpu->satp_modes); object_property_add(obj, "sv48", "bool", cpu_riscv_get_satp, - cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode); + cpu_riscv_set_satp, NULL, &cpu->satp_modes); object_property_add(obj, "sv57", "bool", cpu_riscv_get_satp, - cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode); + cpu_riscv_set_satp, NULL, &cpu->satp_modes); object_property_add(obj, "sv64", "bool", cpu_riscv_get_satp, - cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode); + cpu_riscv_set_satp, NULL, &cpu->satp_modes); } } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 3d89a4a83b..731ea2540c 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -499,6 +499,19 @@ struct CPUArchState { uint64_t rnmi_excpvec; }; +/* + * map is a 16-bit bitmap: the most significant set bit in map is the maximum + * satp mode that is supported. It may be chosen by the user and must respect + * what qemu implements (valid_1_10_32/64) and what the hw is capable of + * (supported bitmap below). + * + * init is a 16-bit bitmap used to make sure the user selected a correct + * configuration as per the specification. + */ +typedef struct { + uint16_t map, init; +} RISCVSATPModes; + /* * RISCVCPU: * @env: #CPURISCVState @@ -515,6 +528,7 @@ struct ArchCPU { /* Configuration Settings */ RISCVCPUConfig cfg; + RISCVSATPModes satp_modes; QEMUTimer *pmu_timer; /* A bitmask of Available programmable counters */ diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 8b80e03c9a..8fa73c8a07 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -21,19 +21,6 @@ #ifndef RISCV_CPU_CFG_H #define RISCV_CPU_CFG_H -/* - * map is a 16-bit bitmap: the most significant set bit in map is the maximum - * satp mode that is supported. It may be chosen by the user and must respect - * what qemu implements (valid_1_10_32/64) and what the hw is capable of - * (supported bitmap below). - * - * init is a 16-bit bitmap used to make sure the user selected a correct - * configuration as per the specification. - */ -typedef struct { - uint16_t map, init; -} RISCVSATPMap; - struct RISCVCPUConfig { bool ext_zba; bool ext_zbb; @@ -195,7 +182,6 @@ struct RISCVCPUConfig { bool short_isa_string; int8_t max_satp_mode; - RISCVSATPMap satp_mode; }; typedef struct RISCVCPUConfig RISCVCPUConfig; From 71fb3aa5ebba5ba822371f864a12dbcded08147d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 13:12:09 +0100 Subject: [PATCH 15/35] target/riscv: introduce RISCVCPUDef Start putting all the CPU definitions in a struct. Later this will replace instance_init functions with declarative code, for now just remove the ugly cast of class_data. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 27 ++++++++++++++++++--------- target/riscv/cpu.h | 4 ++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 54a996c292..6e92fbb992 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3073,8 +3073,9 @@ static void riscv_cpu_common_class_init(ObjectClass *c, const void *data) static void riscv_cpu_class_init(ObjectClass *c, const void *data) { RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); + const RISCVCPUDef *def = data; - mcc->misa_mxl_max = (RISCVMXL)GPOINTER_TO_UINT(data); + mcc->misa_mxl_max = def->misa_mxl_max; riscv_cpu_validate_misa_mxl(mcc); } @@ -3170,40 +3171,48 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) } #endif -#define DEFINE_DYNAMIC_CPU(type_name, misa_mxl_max, initfn) \ +#define DEFINE_DYNAMIC_CPU(type_name, misa_mxl_max_, initfn) \ { \ .name = (type_name), \ .parent = TYPE_RISCV_DYNAMIC_CPU, \ .instance_init = (initfn), \ .class_init = riscv_cpu_class_init, \ - .class_data = GUINT_TO_POINTER(misa_mxl_max) \ + .class_data = &(const RISCVCPUDef) { \ + .misa_mxl_max = (misa_mxl_max_), \ + }, \ } -#define DEFINE_VENDOR_CPU(type_name, misa_mxl_max, initfn) \ +#define DEFINE_VENDOR_CPU(type_name, misa_mxl_max_, initfn) \ { \ .name = (type_name), \ .parent = TYPE_RISCV_VENDOR_CPU, \ .instance_init = (initfn), \ .class_init = riscv_cpu_class_init, \ - .class_data = GUINT_TO_POINTER(misa_mxl_max) \ + .class_data = &(const RISCVCPUDef) { \ + .misa_mxl_max = (misa_mxl_max_), \ + }, \ } -#define DEFINE_BARE_CPU(type_name, misa_mxl_max, initfn) \ +#define DEFINE_BARE_CPU(type_name, misa_mxl_max_, initfn) \ { \ .name = (type_name), \ .parent = TYPE_RISCV_BARE_CPU, \ .instance_init = (initfn), \ .class_init = riscv_cpu_class_init, \ - .class_data = GUINT_TO_POINTER(misa_mxl_max) \ + .class_data = &(const RISCVCPUDef) { \ + .misa_mxl_max = (misa_mxl_max_), \ + }, \ } -#define DEFINE_PROFILE_CPU(type_name, misa_mxl_max, initfn) \ +#define DEFINE_PROFILE_CPU(type_name, misa_mxl_max_, initfn) \ { \ .name = (type_name), \ .parent = TYPE_RISCV_BARE_CPU, \ .instance_init = (initfn), \ .class_init = riscv_cpu_class_init, \ - .class_data = GUINT_TO_POINTER(misa_mxl_max) \ + .class_data = &(const RISCVCPUDef) { \ + .misa_mxl_max = (misa_mxl_max_), \ + }, \ } static const TypeInfo riscv_cpu_type_infos[] = { diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 731ea2540c..9de3f716ea 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -538,6 +538,10 @@ struct ArchCPU { const GPtrArray *decoders; }; +typedef struct RISCVCPUDef { + RISCVMXL misa_mxl_max; /* max mxl for this cpu */ +} RISCVCPUDef; + /** * RISCVCPUClass: * @parent_realize: The parent class' realize handler. From 5fd23f20e12a56e7ac2dabbe9570fb2f10d7c5b4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 13:13:23 +0100 Subject: [PATCH 16/35] target/riscv: store RISCVCPUDef struct directly in the class Prepare for adding more fields to RISCVCPUDef and reading them in riscv_cpu_init: instead of storing the misa_mxl_max field in RISCVCPUClass, ensure that there's always a valid RISCVCPUDef struct and go through it. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- hw/riscv/boot.c | 2 +- target/riscv/cpu.c | 23 ++++++++++++++++++----- target/riscv/cpu.h | 2 +- target/riscv/gdbstub.c | 6 +++--- target/riscv/kvm/kvm-cpu.c | 21 +++++++++------------ target/riscv/machine.c | 2 +- target/riscv/tcg/tcg-cpu.c | 10 +++++----- target/riscv/translate.c | 2 +- 8 files changed, 39 insertions(+), 29 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 765b9e2b1a..828a867be3 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -37,7 +37,7 @@ bool riscv_is_32bit(RISCVHartArrayState *harts) { RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(&harts->harts[0]); - return mcc->misa_mxl_max == MXL_RV32; + return mcc->def->misa_mxl_max == MXL_RV32; } /* diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6e92fbb992..22e3a2211e 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -356,7 +356,7 @@ void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext) int riscv_cpu_max_xlen(RISCVCPUClass *mcc) { - return 16 << mcc->misa_mxl_max; + return 16 << mcc->def->misa_mxl_max; } #ifndef CONFIG_USER_ONLY @@ -1047,7 +1047,7 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) mcc->parent_phases.hold(obj, type); } #ifndef CONFIG_USER_ONLY - env->misa_mxl = mcc->misa_mxl_max; + env->misa_mxl = mcc->def->misa_mxl_max; env->priv = PRV_M; env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV); if (env->misa_mxl > MXL_RV32) { @@ -1449,7 +1449,7 @@ static void riscv_cpu_init(Object *obj) RISCVCPU *cpu = RISCV_CPU(obj); CPURISCVState *env = &cpu->env; - env->misa_mxl = mcc->misa_mxl_max; + env->misa_mxl = mcc->def->misa_mxl_max; #ifndef CONFIG_USER_ONLY qdev_init_gpio_in(DEVICE(obj), riscv_cpu_set_irq, @@ -1543,7 +1543,7 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc) CPUClass *cc = CPU_CLASS(mcc); /* Validate that MISA_MXL is set properly. */ - switch (mcc->misa_mxl_max) { + switch (mcc->def->misa_mxl_max) { #ifdef TARGET_RISCV64 case MXL_RV64: case MXL_RV128: @@ -3070,12 +3070,24 @@ static void riscv_cpu_common_class_init(ObjectClass *c, const void *data) device_class_set_props(dc, riscv_cpu_properties); } +static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) +{ + RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); + RISCVCPUClass *pcc = RISCV_CPU_CLASS(object_class_get_parent(c)); + + if (pcc->def) { + mcc->def = g_memdup2(pcc->def, sizeof(*pcc->def)); + } else { + mcc->def = g_new0(RISCVCPUDef, 1); + } +} + static void riscv_cpu_class_init(ObjectClass *c, const void *data) { RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); const RISCVCPUDef *def = data; - mcc->misa_mxl_max = def->misa_mxl_max; + mcc->def->misa_mxl_max = def->misa_mxl_max; riscv_cpu_validate_misa_mxl(mcc); } @@ -3226,6 +3238,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { .abstract = true, .class_size = sizeof(RISCVCPUClass), .class_init = riscv_cpu_common_class_init, + .class_base_init = riscv_cpu_class_base_init, }, { .name = TYPE_RISCV_DYNAMIC_CPU, diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 9de3f716ea..d2d4db95c1 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -554,7 +554,7 @@ struct RISCVCPUClass { DeviceRealize parent_realize; ResettablePhases parent_phases; - RISCVMXL misa_mxl_max; /* max mxl for this cpu */ + RISCVCPUDef *def; }; static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 18e88f416a..1934f919c0 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -62,7 +62,7 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) return 0; } - switch (mcc->misa_mxl_max) { + switch (mcc->def->misa_mxl_max) { case MXL_RV32: return gdb_get_reg32(mem_buf, tmp); case MXL_RV64: @@ -82,7 +82,7 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) int length = 0; target_ulong tmp; - switch (mcc->misa_mxl_max) { + switch (mcc->def->misa_mxl_max) { case MXL_RV32: tmp = (int32_t)ldl_p(mem_buf); length = 4; @@ -359,7 +359,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs), 0); } - switch (mcc->misa_mxl_max) { + switch (mcc->def->misa_mxl_max) { case MXL_RV32: gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 82f9728636..e77f612af3 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -2086,22 +2086,19 @@ static void kvm_cpu_accel_register_types(void) } type_init(kvm_cpu_accel_register_types); -static void riscv_host_cpu_class_init(ObjectClass *c, const void *data) -{ - RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); - -#if defined(TARGET_RISCV32) - mcc->misa_mxl_max = MXL_RV32; -#elif defined(TARGET_RISCV64) - mcc->misa_mxl_max = MXL_RV64; -#endif -} - static const TypeInfo riscv_kvm_cpu_type_infos[] = { { .name = TYPE_RISCV_CPU_HOST, .parent = TYPE_RISCV_CPU, - .class_init = riscv_host_cpu_class_init, +#if defined(TARGET_RISCV32) + .class_data = &(const RISCVCPUDef) { + .misa_mxl_max = MXL_RV32, + }, +#elif defined(TARGET_RISCV64) + .class_data = &(const RISCVCPUDef) { + .misa_mxl_max = MXL_RV64, + }, +#endif } }; diff --git a/target/riscv/machine.c b/target/riscv/machine.c index a1f70cc955..c97e9ce9df 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -170,7 +170,7 @@ static bool rv128_needed(void *opaque) { RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(opaque); - return mcc->misa_mxl_max == MXL_RV128; + return mcc->def->misa_mxl_max == MXL_RV128; } static const VMStateDescription vmstate_rv128 = { diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index ab8659f304..305912b8dd 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -691,7 +691,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } - if (mcc->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) { + if (mcc->def->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) { error_setg(errp, "Zcf extension is only relevant to RV32"); return; } @@ -788,7 +788,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } - if (mcc->misa_mxl_max == MXL_RV32 && cpu->cfg.ext_svukte) { + if (mcc->def->misa_mxl_max == MXL_RV32 && cpu->cfg.ext_svukte) { error_setg(errp, "svukte is not supported for RV32"); return; } @@ -1026,7 +1026,7 @@ static void cpu_enable_zc_implied_rules(RISCVCPU *cpu) cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true); cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true); - if (riscv_has_ext(env, RVF) && mcc->misa_mxl_max == MXL_RV32) { + if (riscv_has_ext(env, RVF) && mcc->def->misa_mxl_max == MXL_RV32) { cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true); } } @@ -1035,7 +1035,7 @@ static void cpu_enable_zc_implied_rules(RISCVCPU *cpu) if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) { cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true); - if (riscv_has_ext(env, RVF) && mcc->misa_mxl_max == MXL_RV32) { + if (riscv_has_ext(env, RVF) && mcc->def->misa_mxl_max == MXL_RV32) { cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true); } @@ -1161,7 +1161,7 @@ static bool riscv_tcg_cpu_realize(CPUState *cs, Error **errp) #ifndef CONFIG_USER_ONLY RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); - if (mcc->misa_mxl_max >= MXL_RV128 && qemu_tcg_mttcg_enabled()) { + if (mcc->def->misa_mxl_max >= MXL_RV128 && qemu_tcg_mttcg_enabled()) { /* Missing 128-bit aligned atomics */ error_setg(errp, "128-bit RISC-V currently does not work with Multi " diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 0d4f7d601c..d7a6de02df 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1276,7 +1276,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s; ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO); ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); - ctx->misa_mxl_max = mcc->misa_mxl_max; + ctx->misa_mxl_max = mcc->def->misa_mxl_max; ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL); ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL); ctx->cs = cs; From 7f9e15d82d21714a2c82aff8869b8ef9aa191c98 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 13:41:49 +0100 Subject: [PATCH 17/35] target/riscv: merge riscv_cpu_class_init with the class_base function Since all TYPE_RISCV_CPU subclasses support a class_data of type RISCVCPUDef, process it even before calling the .class_init function for the subclasses. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 22e3a2211e..334791eebd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3080,15 +3080,18 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) } else { mcc->def = g_new0(RISCVCPUDef, 1); } -} -static void riscv_cpu_class_init(ObjectClass *c, const void *data) -{ - RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); - const RISCVCPUDef *def = data; + if (data) { + const RISCVCPUDef *def = data; + if (def->misa_mxl_max) { + assert(def->misa_mxl_max <= MXL_RV128); + mcc->def->misa_mxl_max = def->misa_mxl_max; + } + } - mcc->def->misa_mxl_max = def->misa_mxl_max; - riscv_cpu_validate_misa_mxl(mcc); + if (!object_class_is_abstract(c)) { + riscv_cpu_validate_misa_mxl(mcc); + } } static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, @@ -3188,7 +3191,6 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) .name = (type_name), \ .parent = TYPE_RISCV_DYNAMIC_CPU, \ .instance_init = (initfn), \ - .class_init = riscv_cpu_class_init, \ .class_data = &(const RISCVCPUDef) { \ .misa_mxl_max = (misa_mxl_max_), \ }, \ @@ -3199,7 +3201,6 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) .name = (type_name), \ .parent = TYPE_RISCV_VENDOR_CPU, \ .instance_init = (initfn), \ - .class_init = riscv_cpu_class_init, \ .class_data = &(const RISCVCPUDef) { \ .misa_mxl_max = (misa_mxl_max_), \ }, \ @@ -3210,7 +3211,6 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) .name = (type_name), \ .parent = TYPE_RISCV_BARE_CPU, \ .instance_init = (initfn), \ - .class_init = riscv_cpu_class_init, \ .class_data = &(const RISCVCPUDef) { \ .misa_mxl_max = (misa_mxl_max_), \ }, \ @@ -3221,7 +3221,6 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) .name = (type_name), \ .parent = TYPE_RISCV_BARE_CPU, \ .instance_init = (initfn), \ - .class_init = riscv_cpu_class_init, \ .class_data = &(const RISCVCPUDef) { \ .misa_mxl_max = (misa_mxl_max_), \ }, \ From 12877e739b3afff2b6ff7b80d6a6b22e451671c2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 11:28:23 +0100 Subject: [PATCH 18/35] target/riscv: move RISCVCPUConfig fields to a header file To support merging a subclass's RISCVCPUDef into the superclass, a list of all the CPU features is needed. Put them into a header file that can be included multiple times, expanding the macros BOOL_FIELD and TYPE_FIELD to different operations. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu_cfg.h | 163 +--------------------------- target/riscv/cpu_cfg_fields.h.inc | 170 ++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 160 deletions(-) create mode 100644 target/riscv/cpu_cfg_fields.h.inc diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 8fa73c8a07..e9bf75730a 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -22,166 +22,9 @@ #define RISCV_CPU_CFG_H struct RISCVCPUConfig { - bool ext_zba; - bool ext_zbb; - bool ext_zbc; - bool ext_zbkb; - bool ext_zbkc; - bool ext_zbkx; - bool ext_zbs; - bool ext_zca; - bool ext_zcb; - bool ext_zcd; - bool ext_zce; - bool ext_zcf; - bool ext_zcmp; - bool ext_zcmt; - bool ext_zk; - bool ext_zkn; - bool ext_zknd; - bool ext_zkne; - bool ext_zknh; - bool ext_zkr; - bool ext_zks; - bool ext_zksed; - bool ext_zksh; - bool ext_zkt; - bool ext_zifencei; - bool ext_zicntr; - bool ext_zicsr; - bool ext_zicbom; - bool ext_zicbop; - bool ext_zicboz; - bool ext_zicfilp; - bool ext_zicfiss; - bool ext_zicond; - bool ext_zihintntl; - bool ext_zihintpause; - bool ext_zihpm; - bool ext_zimop; - bool ext_zcmop; - bool ext_ztso; - bool ext_smstateen; - bool ext_sstc; - bool ext_smcdeleg; - bool ext_ssccfg; - bool ext_smcntrpmf; - bool ext_smcsrind; - bool ext_sscsrind; - bool ext_ssdbltrp; - bool ext_smdbltrp; - bool ext_svadu; - bool ext_svinval; - bool ext_svnapot; - bool ext_svpbmt; - bool ext_svvptc; - bool ext_svukte; - bool ext_zdinx; - bool ext_zaamo; - bool ext_zacas; - bool ext_zama16b; - bool ext_zabha; - bool ext_zalrsc; - bool ext_zawrs; - bool ext_zfa; - bool ext_zfbfmin; - bool ext_zfh; - bool ext_zfhmin; - bool ext_zfinx; - bool ext_zhinx; - bool ext_zhinxmin; - bool ext_zve32f; - bool ext_zve32x; - bool ext_zve64f; - bool ext_zve64d; - bool ext_zve64x; - bool ext_zvbb; - bool ext_zvbc; - bool ext_zvkb; - bool ext_zvkg; - bool ext_zvkned; - bool ext_zvknha; - bool ext_zvknhb; - bool ext_zvksed; - bool ext_zvksh; - bool ext_zvkt; - bool ext_zvkn; - bool ext_zvknc; - bool ext_zvkng; - bool ext_zvks; - bool ext_zvksc; - bool ext_zvksg; - bool ext_zmmul; - bool ext_zvfbfmin; - bool ext_zvfbfwma; - bool ext_zvfh; - bool ext_zvfhmin; - bool ext_smaia; - bool ext_ssaia; - bool ext_smctr; - bool ext_ssctr; - bool ext_sscofpmf; - bool ext_smepmp; - bool ext_smrnmi; - bool ext_ssnpm; - bool ext_smnpm; - bool ext_smmpm; - bool ext_sspm; - bool ext_supm; - bool rvv_ta_all_1s; - bool rvv_ma_all_1s; - bool rvv_vl_half_avl; - - uint32_t mvendorid; - uint64_t marchid; - uint64_t mimpid; - - /* Named features */ - bool ext_svade; - bool ext_zic64b; - bool ext_ssstateen; - bool ext_sha; - - /* - * Always 'true' booleans for named features - * TCG always implement/can't be user disabled, - * based on spec version. - */ - bool has_priv_1_13; - bool has_priv_1_12; - bool has_priv_1_11; - - /* Always enabled for TCG if has_priv_1_11 */ - bool ext_ziccrse; - - /* Vendor-specific custom extensions */ - bool ext_xtheadba; - bool ext_xtheadbb; - bool ext_xtheadbs; - bool ext_xtheadcmo; - bool ext_xtheadcondmov; - bool ext_xtheadfmemidx; - bool ext_xtheadfmv; - bool ext_xtheadmac; - bool ext_xtheadmemidx; - bool ext_xtheadmempair; - bool ext_xtheadsync; - bool ext_XVentanaCondOps; - - uint32_t pmu_mask; - uint16_t vlenb; - uint16_t elen; - uint16_t cbom_blocksize; - uint16_t cbop_blocksize; - uint16_t cboz_blocksize; - bool mmu; - bool pmp; - bool debug; - bool misa_w; - - bool short_isa_string; - - int8_t max_satp_mode; +#define BOOL_FIELD(x) bool x; +#define TYPED_FIELD(type, x) type x; +#include "cpu_cfg_fields.h.inc" }; typedef struct RISCVCPUConfig RISCVCPUConfig; diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc new file mode 100644 index 0000000000..cb86bfc5dc --- /dev/null +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -0,0 +1,170 @@ +/* + * Required definitions before including this file: + * + * #define BOOL_FIELD(x) + * #define TYPED_FIELD(type, x) + */ + +BOOL_FIELD(ext_zba) +BOOL_FIELD(ext_zbb) +BOOL_FIELD(ext_zbc) +BOOL_FIELD(ext_zbkb) +BOOL_FIELD(ext_zbkc) +BOOL_FIELD(ext_zbkx) +BOOL_FIELD(ext_zbs) +BOOL_FIELD(ext_zca) +BOOL_FIELD(ext_zcb) +BOOL_FIELD(ext_zcd) +BOOL_FIELD(ext_zce) +BOOL_FIELD(ext_zcf) +BOOL_FIELD(ext_zcmp) +BOOL_FIELD(ext_zcmt) +BOOL_FIELD(ext_zk) +BOOL_FIELD(ext_zkn) +BOOL_FIELD(ext_zknd) +BOOL_FIELD(ext_zkne) +BOOL_FIELD(ext_zknh) +BOOL_FIELD(ext_zkr) +BOOL_FIELD(ext_zks) +BOOL_FIELD(ext_zksed) +BOOL_FIELD(ext_zksh) +BOOL_FIELD(ext_zkt) +BOOL_FIELD(ext_zifencei) +BOOL_FIELD(ext_zicntr) +BOOL_FIELD(ext_zicsr) +BOOL_FIELD(ext_zicbom) +BOOL_FIELD(ext_zicbop) +BOOL_FIELD(ext_zicboz) +BOOL_FIELD(ext_zicfilp) +BOOL_FIELD(ext_zicfiss) +BOOL_FIELD(ext_zicond) +BOOL_FIELD(ext_zihintntl) +BOOL_FIELD(ext_zihintpause) +BOOL_FIELD(ext_zihpm) +BOOL_FIELD(ext_zimop) +BOOL_FIELD(ext_zcmop) +BOOL_FIELD(ext_ztso) +BOOL_FIELD(ext_smstateen) +BOOL_FIELD(ext_sstc) +BOOL_FIELD(ext_smcdeleg) +BOOL_FIELD(ext_ssccfg) +BOOL_FIELD(ext_smcntrpmf) +BOOL_FIELD(ext_smcsrind) +BOOL_FIELD(ext_sscsrind) +BOOL_FIELD(ext_ssdbltrp) +BOOL_FIELD(ext_smdbltrp) +BOOL_FIELD(ext_svadu) +BOOL_FIELD(ext_svinval) +BOOL_FIELD(ext_svnapot) +BOOL_FIELD(ext_svpbmt) +BOOL_FIELD(ext_svvptc) +BOOL_FIELD(ext_svukte) +BOOL_FIELD(ext_zdinx) +BOOL_FIELD(ext_zaamo) +BOOL_FIELD(ext_zacas) +BOOL_FIELD(ext_zama16b) +BOOL_FIELD(ext_zabha) +BOOL_FIELD(ext_zalrsc) +BOOL_FIELD(ext_zawrs) +BOOL_FIELD(ext_zfa) +BOOL_FIELD(ext_zfbfmin) +BOOL_FIELD(ext_zfh) +BOOL_FIELD(ext_zfhmin) +BOOL_FIELD(ext_zfinx) +BOOL_FIELD(ext_zhinx) +BOOL_FIELD(ext_zhinxmin) +BOOL_FIELD(ext_zve32f) +BOOL_FIELD(ext_zve32x) +BOOL_FIELD(ext_zve64f) +BOOL_FIELD(ext_zve64d) +BOOL_FIELD(ext_zve64x) +BOOL_FIELD(ext_zvbb) +BOOL_FIELD(ext_zvbc) +BOOL_FIELD(ext_zvkb) +BOOL_FIELD(ext_zvkg) +BOOL_FIELD(ext_zvkned) +BOOL_FIELD(ext_zvknha) +BOOL_FIELD(ext_zvknhb) +BOOL_FIELD(ext_zvksed) +BOOL_FIELD(ext_zvksh) +BOOL_FIELD(ext_zvkt) +BOOL_FIELD(ext_zvkn) +BOOL_FIELD(ext_zvknc) +BOOL_FIELD(ext_zvkng) +BOOL_FIELD(ext_zvks) +BOOL_FIELD(ext_zvksc) +BOOL_FIELD(ext_zvksg) +BOOL_FIELD(ext_zmmul) +BOOL_FIELD(ext_zvfbfmin) +BOOL_FIELD(ext_zvfbfwma) +BOOL_FIELD(ext_zvfh) +BOOL_FIELD(ext_zvfhmin) +BOOL_FIELD(ext_smaia) +BOOL_FIELD(ext_ssaia) +BOOL_FIELD(ext_smctr) +BOOL_FIELD(ext_ssctr) +BOOL_FIELD(ext_sscofpmf) +BOOL_FIELD(ext_smepmp) +BOOL_FIELD(ext_smrnmi) +BOOL_FIELD(ext_ssnpm) +BOOL_FIELD(ext_smnpm) +BOOL_FIELD(ext_smmpm) +BOOL_FIELD(ext_sspm) +BOOL_FIELD(ext_supm) +BOOL_FIELD(rvv_ta_all_1s) +BOOL_FIELD(rvv_ma_all_1s) +BOOL_FIELD(rvv_vl_half_avl) +/* Named features */ +BOOL_FIELD(ext_svade) +BOOL_FIELD(ext_zic64b) +BOOL_FIELD(ext_ssstateen) +BOOL_FIELD(ext_sha) + +/* + * Always 'true' booleans for named features + * TCG always implement/can't be user disabled, + * based on spec version. + */ +BOOL_FIELD(has_priv_1_13) +BOOL_FIELD(has_priv_1_12) +BOOL_FIELD(has_priv_1_11) + +/* Always enabled for TCG if has_priv_1_11 */ +BOOL_FIELD(ext_ziccrse) + +/* Vendor-specific custom extensions */ +BOOL_FIELD(ext_xtheadba) +BOOL_FIELD(ext_xtheadbb) +BOOL_FIELD(ext_xtheadbs) +BOOL_FIELD(ext_xtheadcmo) +BOOL_FIELD(ext_xtheadcondmov) +BOOL_FIELD(ext_xtheadfmemidx) +BOOL_FIELD(ext_xtheadfmv) +BOOL_FIELD(ext_xtheadmac) +BOOL_FIELD(ext_xtheadmemidx) +BOOL_FIELD(ext_xtheadmempair) +BOOL_FIELD(ext_xtheadsync) +BOOL_FIELD(ext_XVentanaCondOps) + +BOOL_FIELD(mmu) +BOOL_FIELD(pmp) +BOOL_FIELD(debug) +BOOL_FIELD(misa_w) + +BOOL_FIELD(short_isa_string) + +TYPED_FIELD(uint32_t, mvendorid) +TYPED_FIELD(uint64_t, marchid) +TYPED_FIELD(uint64_t, mimpid) + +TYPED_FIELD(uint32_t, pmu_mask) +TYPED_FIELD(uint16_t, vlenb) +TYPED_FIELD(uint16_t, elen) +TYPED_FIELD(uint16_t, cbom_blocksize) +TYPED_FIELD(uint16_t, cbop_blocksize) +TYPED_FIELD(uint16_t, cboz_blocksize) + +TYPED_FIELD(int8_t, max_satp_mode) + +#undef BOOL_FIELD +#undef TYPED_FIELD From 407254031edd649e6acde736e3f7e95bb0fdf299 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Mar 2025 13:22:48 +0100 Subject: [PATCH 19/35] target/riscv: include default value in cpu_cfg_fields.h.inc In preparation for adding a function to merge two RISCVCPUConfigs (pulling values from the parent if they are not overridden) annotate cpu_cfg_fields.h.inc with the default value of the fields. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu_cfg.h | 2 +- target/riscv/cpu_cfg_fields.h.inc | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index e9bf75730a..aa28dc8d7e 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -23,7 +23,7 @@ struct RISCVCPUConfig { #define BOOL_FIELD(x) bool x; -#define TYPED_FIELD(type, x) type x; +#define TYPED_FIELD(type, x, default) type x; #include "cpu_cfg_fields.h.inc" }; diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc index cb86bfc5dc..59f134a419 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -2,7 +2,7 @@ * Required definitions before including this file: * * #define BOOL_FIELD(x) - * #define TYPED_FIELD(type, x) + * #define TYPED_FIELD(type, x, default) */ BOOL_FIELD(ext_zba) @@ -153,18 +153,18 @@ BOOL_FIELD(misa_w) BOOL_FIELD(short_isa_string) -TYPED_FIELD(uint32_t, mvendorid) -TYPED_FIELD(uint64_t, marchid) -TYPED_FIELD(uint64_t, mimpid) +TYPED_FIELD(uint32_t, mvendorid, 0) +TYPED_FIELD(uint64_t, marchid, 0) +TYPED_FIELD(uint64_t, mimpid, 0) -TYPED_FIELD(uint32_t, pmu_mask) -TYPED_FIELD(uint16_t, vlenb) -TYPED_FIELD(uint16_t, elen) -TYPED_FIELD(uint16_t, cbom_blocksize) -TYPED_FIELD(uint16_t, cbop_blocksize) -TYPED_FIELD(uint16_t, cboz_blocksize) +TYPED_FIELD(uint32_t, pmu_mask, 0) +TYPED_FIELD(uint16_t, vlenb, 0) +TYPED_FIELD(uint16_t, elen, 0) +TYPED_FIELD(uint16_t, cbom_blocksize, 0) +TYPED_FIELD(uint16_t, cbop_blocksize, 0) +TYPED_FIELD(uint16_t, cboz_blocksize, 0) -TYPED_FIELD(int8_t, max_satp_mode) +TYPED_FIELD(int8_t, max_satp_mode, -1) #undef BOOL_FIELD #undef TYPED_FIELD From a6ba81424a7e751fbcee40dc1f5826ba29fddd30 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 11:31:30 +0100 Subject: [PATCH 20/35] target/riscv: add more RISCVCPUDef fields Allow using RISCVCPUDef to replicate all the logic of custom .instance_init functions. To simulate inheritance, merge the child's RISCVCPUDef with the parent and then finally move it to the CPUState at the end of TYPE_RISCV_CPU's own instance_init function. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 42 +++++++++++++++++++++++++++++++++++++- target/riscv/cpu.h | 4 ++++ target/riscv/kvm/kvm-cpu.c | 6 ++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 334791eebd..634216870e 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -73,6 +73,13 @@ bool riscv_cpu_option_set(const char *optname) return g_hash_table_contains(general_user_opts, optname); } +static void riscv_cpu_cfg_merge(RISCVCPUConfig *dest, const RISCVCPUConfig *src) +{ +#define BOOL_FIELD(x) dest->x |= src->x; +#define TYPED_FIELD(type, x, default_) if (src->x != default_) dest->x = src->x; +#include "cpu_cfg_fields.h.inc" +} + #define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ {#_name, _min_ver, CPU_CFG_OFFSET(_prop)} @@ -434,7 +441,7 @@ const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit) } static void set_satp_mode_max_supported(RISCVCPU *cpu, - uint8_t satp_mode) + int satp_mode) { bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32; const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64; @@ -1479,6 +1486,16 @@ static void riscv_cpu_init(Object *obj) cpu->cfg.cboz_blocksize = 64; cpu->env.vext_ver = VEXT_VERSION_1_00_0; cpu->cfg.max_satp_mode = -1; + + env->misa_ext_mask = env->misa_ext = mcc->def->misa_ext; + riscv_cpu_cfg_merge(&cpu->cfg, &mcc->def->cfg); + + if (mcc->def->priv_spec != RISCV_PROFILE_ATTR_UNUSED) { + cpu->env.priv_ver = mcc->def->priv_spec; + } + if (mcc->def->vext_spec != RISCV_PROFILE_ATTR_UNUSED) { + cpu->env.vext_ver = mcc->def->vext_spec; + } } static void riscv_bare_cpu_init(Object *obj) @@ -3087,6 +3104,17 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) assert(def->misa_mxl_max <= MXL_RV128); mcc->def->misa_mxl_max = def->misa_mxl_max; } + if (def->priv_spec != RISCV_PROFILE_ATTR_UNUSED) { + assert(def->priv_spec <= PRIV_VERSION_LATEST); + mcc->def->priv_spec = def->priv_spec; + } + if (def->vext_spec != RISCV_PROFILE_ATTR_UNUSED) { + assert(def->vext_spec != 0); + mcc->def->vext_spec = def->vext_spec; + } + mcc->def->misa_ext |= def->misa_ext; + + riscv_cpu_cfg_merge(&mcc->def->cfg, &def->cfg); } if (!object_class_is_abstract(c)) { @@ -3193,6 +3221,9 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) .instance_init = (initfn), \ .class_data = &(const RISCVCPUDef) { \ .misa_mxl_max = (misa_mxl_max_), \ + .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .cfg.max_satp_mode = -1, \ }, \ } @@ -3203,6 +3234,9 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) .instance_init = (initfn), \ .class_data = &(const RISCVCPUDef) { \ .misa_mxl_max = (misa_mxl_max_), \ + .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .cfg.max_satp_mode = -1, \ }, \ } @@ -3213,6 +3247,9 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) .instance_init = (initfn), \ .class_data = &(const RISCVCPUDef) { \ .misa_mxl_max = (misa_mxl_max_), \ + .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .cfg.max_satp_mode = -1, \ }, \ } @@ -3223,6 +3260,9 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) .instance_init = (initfn), \ .class_data = &(const RISCVCPUDef) { \ .misa_mxl_max = (misa_mxl_max_), \ + .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .cfg.max_satp_mode = -1, \ }, \ } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index d2d4db95c1..29b01e9aa8 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -540,6 +540,10 @@ struct ArchCPU { typedef struct RISCVCPUDef { RISCVMXL misa_mxl_max; /* max mxl for this cpu */ + uint32_t misa_ext; + int priv_spec; + int32_t vext_spec; + RISCVCPUConfig cfg; } RISCVCPUDef; /** diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index e77f612af3..efb41fac53 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -2093,10 +2093,16 @@ static const TypeInfo riscv_kvm_cpu_type_infos[] = { #if defined(TARGET_RISCV32) .class_data = &(const RISCVCPUDef) { .misa_mxl_max = MXL_RV32, + .priv_spec = RISCV_PROFILE_ATTR_UNUSED, + .vext_spec = RISCV_PROFILE_ATTR_UNUSED, + .cfg.max_satp_mode = -1, }, #elif defined(TARGET_RISCV64) .class_data = &(const RISCVCPUDef) { .misa_mxl_max = MXL_RV64, + .priv_spec = RISCV_PROFILE_ATTR_UNUSED, + .vext_spec = RISCV_PROFILE_ATTR_UNUSED, + .cfg.max_satp_mode = -1, }, #endif } From 4e012d36c8654e7fa12762002150334bf591628a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 17:03:01 +0100 Subject: [PATCH 21/35] target/riscv: convert abstract CPU classes to RISCVCPUDef Start from the top of the hierarchy: dynamic and vendor CPUs are just markers, whereas bare CPUs can have their instance_init function replaced by RISCVCPUDef. The only difference is that the maximum supported SATP mode has to be specified separately for 32-bit and 64-bit modes. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 93 ++++++++++++++++++++++------------------------ target/riscv/cpu.h | 1 + 2 files changed, 46 insertions(+), 48 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 634216870e..7dcaf72fc1 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1474,8 +1474,8 @@ static void riscv_cpu_init(Object *obj) * for all CPUs. Each accelerator will decide what to do when * users disable them. */ - RISCV_CPU(obj)->cfg.ext_zicntr = true; - RISCV_CPU(obj)->cfg.ext_zihpm = true; + RISCV_CPU(obj)->cfg.ext_zicntr = !mcc->def->bare; + RISCV_CPU(obj)->cfg.ext_zihpm = !mcc->def->bare; /* Default values for non-bool cpu properties */ cpu->cfg.pmu_mask = MAKE_64BIT_MASK(3, 16); @@ -1498,36 +1498,6 @@ static void riscv_cpu_init(Object *obj) } } -static void riscv_bare_cpu_init(Object *obj) -{ - RISCVCPU *cpu = RISCV_CPU(obj); - - /* - * Bare CPUs do not inherit the timer and performance - * counters from the parent class (see riscv_cpu_init() - * for info on why the parent enables them). - * - * Users have to explicitly enable these counters for - * bare CPUs. - */ - cpu->cfg.ext_zicntr = false; - cpu->cfg.ext_zihpm = false; - - /* Set to QEMU's first supported priv version */ - cpu->env.priv_ver = PRIV_VERSION_1_10_0; - - /* - * Support all available satp_mode settings. The default - * value will be set to MBARE if the user doesn't set - * satp_mode manually (see set_satp_mode_default()). - */ -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(RISCV_CPU(obj), - riscv_cpu_mxl(&RISCV_CPU(obj)->env) == MXL_RV32 ? - VM_1_10_SV32 : VM_1_10_SV57); -#endif -} - typedef struct misa_ext_info { const char *name; const char *description; @@ -3100,6 +3070,7 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) if (data) { const RISCVCPUDef *def = data; + mcc->def->bare |= def->bare; if (def->misa_mxl_max) { assert(def->misa_mxl_max <= MXL_RV128); mcc->def->misa_mxl_max = def->misa_mxl_max; @@ -3253,6 +3224,19 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) }, \ } +#define DEFINE_ABSTRACT_RISCV_CPU(type_name, parent_type_name, ...) \ + { \ + .name = (type_name), \ + .parent = (parent_type_name), \ + .abstract = true, \ + .class_data = &(const RISCVCPUDef) { \ + .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ + .cfg.max_satp_mode = -1, \ + __VA_ARGS__ \ + }, \ + } + #define DEFINE_PROFILE_CPU(type_name, misa_mxl_max_, initfn) \ { \ .name = (type_name), \ @@ -3279,22 +3263,35 @@ static const TypeInfo riscv_cpu_type_infos[] = { .class_init = riscv_cpu_common_class_init, .class_base_init = riscv_cpu_class_base_init, }, - { - .name = TYPE_RISCV_DYNAMIC_CPU, - .parent = TYPE_RISCV_CPU, - .abstract = true, - }, - { - .name = TYPE_RISCV_VENDOR_CPU, - .parent = TYPE_RISCV_CPU, - .abstract = true, - }, - { - .name = TYPE_RISCV_BARE_CPU, - .parent = TYPE_RISCV_CPU, - .instance_init = riscv_bare_cpu_init, - .abstract = true, - }, + + DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_DYNAMIC_CPU, TYPE_RISCV_CPU), + DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_VENDOR_CPU, TYPE_RISCV_CPU), + DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_BARE_CPU, TYPE_RISCV_CPU, + /* + * Bare CPUs do not inherit the timer and performance + * counters from the parent class (see riscv_cpu_init() + * for info on why the parent enables them). + * + * Users have to explicitly enable these counters for + * bare CPUs. + */ + .bare = true, + + /* Set to QEMU's first supported priv version */ + .priv_spec = PRIV_VERSION_1_10_0, + + /* + * Support all available satp_mode settings. By default + * only MBARE will be available if the user doesn't enable + * a mode manually (see riscv_cpu_satp_mode_finalize()). + */ +#ifdef TARGET_RISCV32 + .cfg.max_satp_mode = VM_1_10_SV32, +#else + .cfg.max_satp_mode = VM_1_10_SV57, +#endif + ), + #if defined(TARGET_RISCV32) DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, MXL_RV32, riscv_max_cpu_init), #elif defined(TARGET_RISCV64) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 29b01e9aa8..f3d70afb86 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -544,6 +544,7 @@ typedef struct RISCVCPUDef { int priv_spec; int32_t vext_spec; RISCVCPUConfig cfg; + bool bare; } RISCVCPUDef; /** From 198265df8a71e6743d42d5003c29a060fea7d019 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 27 Feb 2025 14:56:30 +0100 Subject: [PATCH 22/35] target/riscv: convert profile CPU models to RISCVCPUDef Profile CPUs reuse the instance_init function for bare CPUs; make them proper subclasses instead. Enabling a profile is now done based on the RISCVCPUDef struct: even though there is room for only one in RISCVCPUDef, subclasses check that the parent class's profile is enabled through the parent profile mechanism. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 85 +++++++++++++++++++++++++--------------------- target/riscv/cpu.h | 1 + 2 files changed, 48 insertions(+), 38 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 7dcaf72fc1..54fce76765 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1487,6 +1487,10 @@ static void riscv_cpu_init(Object *obj) cpu->env.vext_ver = VEXT_VERSION_1_00_0; cpu->cfg.max_satp_mode = -1; + if (mcc->def->profile) { + mcc->def->profile->enabled = true; + } + env->misa_ext_mask = env->misa_ext = mcc->def->misa_ext; riscv_cpu_cfg_merge(&cpu->cfg, &mcc->def->cfg); @@ -2959,36 +2963,6 @@ static const Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("x-misa-w", RISCVCPU, cfg.misa_w, false), }; -#if defined(TARGET_RISCV64) -static void rva22u64_profile_cpu_init(Object *obj) -{ - rv64i_bare_cpu_init(obj); - - RVA22U64.enabled = true; -} - -static void rva22s64_profile_cpu_init(Object *obj) -{ - rv64i_bare_cpu_init(obj); - - RVA22S64.enabled = true; -} - -static void rva23u64_profile_cpu_init(Object *obj) -{ - rv64i_bare_cpu_init(obj); - - RVA23U64.enabled = true; -} - -static void rva23s64_profile_cpu_init(Object *obj) -{ - rv64i_bare_cpu_init(obj); - - RVA23S64.enabled = true; -} -#endif - static const gchar *riscv_gdb_arch_name(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); @@ -3057,6 +3031,32 @@ static void riscv_cpu_common_class_init(ObjectClass *c, const void *data) device_class_set_props(dc, riscv_cpu_properties); } +static bool profile_extends(RISCVCPUProfile *trial, RISCVCPUProfile *parent) +{ + RISCVCPUProfile *curr; + if (!parent) { + return true; + } + + curr = trial; + while (curr) { + if (curr == parent) { + return true; + } + curr = curr->u_parent; + } + + curr = trial; + while (curr) { + if (curr == parent) { + return true; + } + curr = curr->s_parent; + } + + return false; +} + static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) { RISCVCPUClass *mcc = RISCV_CPU_CLASS(c); @@ -3071,6 +3071,11 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) if (data) { const RISCVCPUDef *def = data; mcc->def->bare |= def->bare; + if (def->profile) { + assert(profile_extends(def->profile, mcc->def->profile)); + assert(mcc->def->bare); + mcc->def->profile = def->profile; + } if (def->misa_mxl_max) { assert(def->misa_mxl_max <= MXL_RV128); mcc->def->misa_mxl_max = def->misa_mxl_max; @@ -3237,19 +3242,22 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) }, \ } -#define DEFINE_PROFILE_CPU(type_name, misa_mxl_max_, initfn) \ +#define DEFINE_RISCV_CPU(type_name, parent_type_name, ...) \ { \ .name = (type_name), \ - .parent = TYPE_RISCV_BARE_CPU, \ - .instance_init = (initfn), \ + .parent = (parent_type_name), \ .class_data = &(const RISCVCPUDef) { \ - .misa_mxl_max = (misa_mxl_max_), \ .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ .cfg.max_satp_mode = -1, \ + __VA_ARGS__ \ }, \ } +#define DEFINE_PROFILE_CPU(type_name, parent_type_name, profile_) \ + DEFINE_RISCV_CPU(type_name, parent_type_name, \ + .profile = &(profile_)) + static const TypeInfo riscv_cpu_type_infos[] = { { .name = TYPE_RISCV_CPU, @@ -3328,10 +3336,11 @@ static const TypeInfo riscv_cpu_type_infos[] = { #endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, MXL_RV64, rv64i_bare_cpu_init), DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64E, MXL_RV64, rv64e_bare_cpu_init), - DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22U64, MXL_RV64, rva22u64_profile_cpu_init), - DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22S64, MXL_RV64, rva22s64_profile_cpu_init), - DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA23U64, MXL_RV64, rva23u64_profile_cpu_init), - DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA23S64, MXL_RV64, rva23s64_profile_cpu_init), + + DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22U64, TYPE_RISCV_CPU_RV64I, RVA22U64), + DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22S64, TYPE_RISCV_CPU_RV64I, RVA22S64), + DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA23U64, TYPE_RISCV_CPU_RV64I, RVA23U64), + DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA23S64, TYPE_RISCV_CPU_RV64I, RVA23S64), #endif /* TARGET_RISCV64 */ }; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index f3d70afb86..ed88adef45 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -540,6 +540,7 @@ struct ArchCPU { typedef struct RISCVCPUDef { RISCVMXL misa_mxl_max; /* max mxl for this cpu */ + RISCVCPUProfile *profile; uint32_t misa_ext; int priv_spec; int32_t vext_spec; From 37815d80be11f98636a4ed76fe6b1ecc7aefcaf3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 17:10:46 +0100 Subject: [PATCH 23/35] target/riscv: convert bare CPU models to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 58 ++++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 41 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 54fce76765..8b82a1b7b3 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -732,18 +732,6 @@ static void rv128_base_cpu_init(Object *obj) } #endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ -static void rv64i_bare_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - riscv_cpu_set_misa_ext(env, RVI); -} - -static void rv64e_bare_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - riscv_cpu_set_misa_ext(env, RVE); -} - #endif /* !TARGET_RISCV64 */ #if defined(TARGET_RISCV32) || \ @@ -836,18 +824,6 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj) cpu->cfg.ext_zicsr = true; cpu->cfg.pmp = true; } - -static void rv32i_bare_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - riscv_cpu_set_misa_ext(env, RVI); -} - -static void rv32e_bare_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - riscv_cpu_set_misa_ext(env, RVE); -} #endif static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) @@ -3216,19 +3192,6 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) }, \ } -#define DEFINE_BARE_CPU(type_name, misa_mxl_max_, initfn) \ - { \ - .name = (type_name), \ - .parent = TYPE_RISCV_BARE_CPU, \ - .instance_init = (initfn), \ - .class_data = &(const RISCVCPUDef) { \ - .misa_mxl_max = (misa_mxl_max_), \ - .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ - .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ - .cfg.max_satp_mode = -1, \ - }, \ - } - #define DEFINE_ABSTRACT_RISCV_CPU(type_name, parent_type_name, ...) \ { \ .name = (type_name), \ @@ -3313,8 +3276,15 @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32, rv32_sifive_e_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E34, MXL_RV32, rv32_imafcu_nommu_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32, rv32_sifive_u_cpu_init), - DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32I, MXL_RV32, rv32i_bare_cpu_init), - DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E, MXL_RV32, rv32e_bare_cpu_init), + + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV32I, TYPE_RISCV_BARE_CPU, + .misa_mxl_max = MXL_RV32, + .misa_ext = RVI + ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV32E, TYPE_RISCV_BARE_CPU, + .misa_mxl_max = MXL_RV32, + .misa_ext = RVE + ), #endif #if (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY)) @@ -3334,8 +3304,14 @@ static const TypeInfo riscv_cpu_type_infos[] = { #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, MXL_RV128, rv128_base_cpu_init), #endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ - DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, MXL_RV64, rv64i_bare_cpu_init), - DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64E, MXL_RV64, rv64e_bare_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV64I, TYPE_RISCV_BARE_CPU, + .misa_mxl_max = MXL_RV64, + .misa_ext = RVI + ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV64E, TYPE_RISCV_BARE_CPU, + .misa_mxl_max = MXL_RV64, + .misa_ext = RVE + ), DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22U64, TYPE_RISCV_CPU_RV64I, RVA22U64), DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22S64, TYPE_RISCV_CPU_RV64I, RVA22S64), From 0edc2465ba76c0d2bbeb475b6d2491c92dccd27b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 14:59:05 +0100 Subject: [PATCH 24/35] target/riscv: convert dynamic CPU models to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 113 +++++++++++++-------------------------------- 1 file changed, 31 insertions(+), 82 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8b82a1b7b3..2b26f23bd0 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -485,38 +485,7 @@ static void set_satp_mode_default_map(RISCVCPU *cpu) } #endif -static void riscv_max_cpu_init(Object *obj) -{ - RISCVCPU *cpu = RISCV_CPU(obj); - CPURISCVState *env = &cpu->env; - - cpu->cfg.mmu = true; - cpu->cfg.pmp = true; - - env->priv_ver = PRIV_VERSION_LATEST; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(RISCV_CPU(obj), - riscv_cpu_mxl(&RISCV_CPU(obj)->env) == MXL_RV32 ? - VM_1_10_SV32 : VM_1_10_SV57); -#endif -} - #if defined(TARGET_RISCV64) -static void rv64_base_cpu_init(Object *obj) -{ - RISCVCPU *cpu = RISCV_CPU(obj); - CPURISCVState *env = &cpu->env; - - cpu->cfg.mmu = true; - cpu->cfg.pmp = true; - - /* Set latest version of privileged specification */ - env->priv_ver = PRIV_VERSION_LATEST; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); -#endif -} - static void rv64_sifive_u_cpu_init(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); @@ -717,41 +686,11 @@ static void rv64_xiangshan_nanhu_cpu_init(Object *obj) #endif } -#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) -static void rv128_base_cpu_init(Object *obj) -{ - RISCVCPU *cpu = RISCV_CPU(obj); - CPURISCVState *env = &cpu->env; - - cpu->cfg.mmu = true; - cpu->cfg.pmp = true; - - /* Set latest version of privileged specification */ - env->priv_ver = PRIV_VERSION_LATEST; - set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); -} -#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ - #endif /* !TARGET_RISCV64 */ #if defined(TARGET_RISCV32) || \ (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY)) -static void rv32_base_cpu_init(Object *obj) -{ - RISCVCPU *cpu = RISCV_CPU(obj); - CPURISCVState *env = &cpu->env; - - cpu->cfg.mmu = true; - cpu->cfg.pmp = true; - - /* Set latest version of privileged specification */ - env->priv_ver = PRIV_VERSION_LATEST; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32); -#endif -} - static void rv32_sifive_u_cpu_init(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); @@ -3166,19 +3105,6 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) } #endif -#define DEFINE_DYNAMIC_CPU(type_name, misa_mxl_max_, initfn) \ - { \ - .name = (type_name), \ - .parent = TYPE_RISCV_DYNAMIC_CPU, \ - .instance_init = (initfn), \ - .class_data = &(const RISCVCPUDef) { \ - .misa_mxl_max = (misa_mxl_max_), \ - .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ - .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ - .cfg.max_satp_mode = -1, \ - }, \ - } - #define DEFINE_VENDOR_CPU(type_name, misa_mxl_max_, initfn) \ { \ .name = (type_name), \ @@ -3235,7 +3161,12 @@ static const TypeInfo riscv_cpu_type_infos[] = { .class_base_init = riscv_cpu_class_base_init, }, - DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_DYNAMIC_CPU, TYPE_RISCV_CPU), + DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_DYNAMIC_CPU, TYPE_RISCV_CPU, + .cfg.mmu = true, + .cfg.pmp = true, + .priv_spec = PRIV_VERSION_LATEST, + ), + DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_VENDOR_CPU, TYPE_RISCV_CPU), DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_BARE_CPU, TYPE_RISCV_CPU, /* @@ -3263,15 +3194,23 @@ static const TypeInfo riscv_cpu_type_infos[] = { #endif ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_MAX, TYPE_RISCV_DYNAMIC_CPU, #if defined(TARGET_RISCV32) - DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, MXL_RV32, riscv_max_cpu_init), + .misa_mxl_max = MXL_RV32, + .cfg.max_satp_mode = VM_1_10_SV32, #elif defined(TARGET_RISCV64) - DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, MXL_RV64, riscv_max_cpu_init), + .misa_mxl_max = MXL_RV64, + .cfg.max_satp_mode = VM_1_10_SV57, #endif + ), #if defined(TARGET_RISCV32) || \ (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY)) - DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32, MXL_RV32, rv32_base_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE32, TYPE_RISCV_DYNAMIC_CPU, + .cfg.max_satp_mode = VM_1_10_SV32, + .misa_mxl_max = MXL_RV32, + ), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX, MXL_RV32, rv32_ibex_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32, rv32_sifive_e_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E34, MXL_RV32, rv32_imafcu_nommu_cpu_init), @@ -3288,11 +3227,18 @@ static const TypeInfo riscv_cpu_type_infos[] = { #endif #if (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY)) - DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX32, MXL_RV32, riscv_max_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_MAX32, TYPE_RISCV_DYNAMIC_CPU, + .cfg.max_satp_mode = VM_1_10_SV32, + .misa_mxl_max = MXL_RV32, + ), #endif #if defined(TARGET_RISCV64) - DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64, MXL_RV64, rv64_base_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE64, TYPE_RISCV_DYNAMIC_CPU, + .cfg.max_satp_mode = VM_1_10_SV57, + .misa_mxl_max = MXL_RV64, + ), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64, rv64_sifive_e_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64, rv64_sifive_u_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SHAKTI_C, MXL_RV64, rv64_sifive_u_cpu_init), @@ -3302,8 +3248,11 @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_XIANGSHAN_NANHU, MXL_RV64, rv64_xiangshan_nanhu_cpu_init), #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) - DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, MXL_RV128, rv128_base_cpu_init), -#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */ + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE128, TYPE_RISCV_DYNAMIC_CPU, + .cfg.max_satp_mode = VM_1_10_SV57, + .misa_mxl_max = MXL_RV128, + ), +#endif /* CONFIG_TCG */ DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV64I, TYPE_RISCV_BARE_CPU, .misa_mxl_max = MXL_RV64, .misa_ext = RVI From e89d4931d0a15ff0481e9a6e7cbb9f7a28e91434 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 15:32:52 +0100 Subject: [PATCH 25/35] target/riscv: convert SiFive E CPU models to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 74 ++++++++++++------------------------------ 2 files changed, 21 insertions(+), 54 deletions(-) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 4cfdb74891..0f9be15e47 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -44,6 +44,7 @@ #define TYPE_RISCV_CPU_RVA23S64 RISCV_CPU_TYPE_NAME("rva23s64") #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") +#define TYPE_RISCV_CPU_SIFIVE_E RISCV_CPU_TYPE_NAME("sifive-e") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") #define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34") #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 2b26f23bd0..17ad8b2ca1 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -503,23 +503,6 @@ static void rv64_sifive_u_cpu_init(Object *obj) cpu->cfg.pmp = true; } -static void rv64_sifive_e_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - RISCVCPU *cpu = RISCV_CPU(obj); - - riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVC | RVU); - env->priv_ver = PRIV_VERSION_1_10_0; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_MBARE); -#endif - - /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_zicsr = true; - cpu->cfg.pmp = true; -} - static void rv64_thead_c906_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; @@ -708,23 +691,6 @@ static void rv32_sifive_u_cpu_init(Object *obj) cpu->cfg.pmp = true; } -static void rv32_sifive_e_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - RISCVCPU *cpu = RISCV_CPU(obj); - - riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVC | RVU); - env->priv_ver = PRIV_VERSION_1_10_0; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_MBARE); -#endif - - /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_zicsr = true; - cpu->cfg.pmp = true; -} - static void rv32_ibex_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; @@ -746,23 +712,6 @@ static void rv32_ibex_cpu_init(Object *obj) cpu->cfg.ext_zbc = true; cpu->cfg.ext_zbs = true; } - -static void rv32_imafcu_nommu_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - RISCVCPU *cpu = RISCV_CPU(obj); - - riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVC | RVU); - env->priv_ver = PRIV_VERSION_1_10_0; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_MBARE); -#endif - - /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_zicsr = true; - cpu->cfg.pmp = true; -} #endif static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) @@ -3204,6 +3153,15 @@ static const TypeInfo riscv_cpu_type_infos[] = { #endif ), + DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E, TYPE_RISCV_VENDOR_CPU, + .misa_ext = RVI | RVM | RVA | RVC | RVU, + .priv_spec = PRIV_VERSION_1_10_0, + .cfg.max_satp_mode = VM_1_10_MBARE, + .cfg.ext_zifencei = true, + .cfg.ext_zicsr = true, + .cfg.pmp = true + ), + #if defined(TARGET_RISCV32) || \ (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY)) DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE32, TYPE_RISCV_DYNAMIC_CPU, @@ -3212,8 +3170,14 @@ static const TypeInfo riscv_cpu_type_infos[] = { ), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX, MXL_RV32, rv32_ibex_cpu_init), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32, rv32_sifive_e_cpu_init), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E34, MXL_RV32, rv32_imafcu_nommu_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E31, TYPE_RISCV_CPU_SIFIVE_E, + .misa_mxl_max = MXL_RV32 + ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E34, TYPE_RISCV_CPU_SIFIVE_E, + .misa_mxl_max = MXL_RV32, + .misa_ext = RVF, /* IMAFCU */ + ), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32, rv32_sifive_u_cpu_init), DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV32I, TYPE_RISCV_BARE_CPU, @@ -3239,7 +3203,9 @@ static const TypeInfo riscv_cpu_type_infos[] = { .misa_mxl_max = MXL_RV64, ), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64, rv64_sifive_e_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E51, TYPE_RISCV_CPU_SIFIVE_E, + .misa_mxl_max = MXL_RV64 + ), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64, rv64_sifive_u_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SHAKTI_C, MXL_RV64, rv64_sifive_u_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906, MXL_RV64, rv64_thead_c906_cpu_init), From 5106b8ee9ac78505f872a956c931c1f965ad073e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 17:27:16 +0100 Subject: [PATCH 26/35] target/riscv: convert ibex CPU models to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 17ad8b2ca1..689c33916e 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -690,28 +690,6 @@ static void rv32_sifive_u_cpu_init(Object *obj) cpu->cfg.mmu = true; cpu->cfg.pmp = true; } - -static void rv32_ibex_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - RISCVCPU *cpu = RISCV_CPU(obj); - - riscv_cpu_set_misa_ext(env, RVI | RVM | RVC | RVU); - env->priv_ver = PRIV_VERSION_1_12_0; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_MBARE); -#endif - /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_zicsr = true; - cpu->cfg.pmp = true; - cpu->cfg.ext_smepmp = true; - - cpu->cfg.ext_zba = true; - cpu->cfg.ext_zbb = true; - cpu->cfg.ext_zbc = true; - cpu->cfg.ext_zbs = true; -} #endif static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) @@ -3169,7 +3147,22 @@ static const TypeInfo riscv_cpu_type_infos[] = { .misa_mxl_max = MXL_RV32, ), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX, MXL_RV32, rv32_ibex_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_IBEX, TYPE_RISCV_VENDOR_CPU, + .misa_mxl_max = MXL_RV32, + .misa_ext = RVI | RVM | RVC | RVU, + .priv_spec = PRIV_VERSION_1_12_0, + .cfg.max_satp_mode = VM_1_10_MBARE, + .cfg.ext_zifencei = true, + .cfg.ext_zicsr = true, + .cfg.pmp = true, + .cfg.ext_smepmp = true, + + .cfg.ext_zba = true, + .cfg.ext_zbb = true, + .cfg.ext_zbc = true, + .cfg.ext_zbs = true + ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E31, TYPE_RISCV_CPU_SIFIVE_E, .misa_mxl_max = MXL_RV32 ), From 5a62948c91a910de4f9c7332cf8803152c099eac Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 18 Feb 2025 13:05:25 +0100 Subject: [PATCH 27/35] target/riscv: convert SiFive U models to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 79 +++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 0f9be15e47..1ee05eb393 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -48,6 +48,7 @@ #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") #define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34") #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") +#define TYPE_RISCV_CPU_SIFIVE_U RISCV_CPU_TYPE_NAME("sifive-u") #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") #define TYPE_RISCV_CPU_THEAD_C906 RISCV_CPU_TYPE_NAME("thead-c906") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 689c33916e..01b028653a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -440,8 +440,8 @@ const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit) g_assert_not_reached(); } -static void set_satp_mode_max_supported(RISCVCPU *cpu, - int satp_mode) +static void __attribute__((unused)) +set_satp_mode_max_supported(RISCVCPU *cpu, int satp_mode) { bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32; const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64; @@ -486,23 +486,6 @@ static void set_satp_mode_default_map(RISCVCPU *cpu) #endif #if defined(TARGET_RISCV64) -static void rv64_sifive_u_cpu_init(Object *obj) -{ - RISCVCPU *cpu = RISCV_CPU(obj); - CPURISCVState *env = &cpu->env; - riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); - env->priv_ver = PRIV_VERSION_1_10_0; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39); -#endif - - /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_zicsr = true; - cpu->cfg.mmu = true; - cpu->cfg.pmp = true; -} - static void rv64_thead_c906_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; @@ -671,27 +654,6 @@ static void rv64_xiangshan_nanhu_cpu_init(Object *obj) #endif /* !TARGET_RISCV64 */ -#if defined(TARGET_RISCV32) || \ - (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY)) - -static void rv32_sifive_u_cpu_init(Object *obj) -{ - RISCVCPU *cpu = RISCV_CPU(obj); - CPURISCVState *env = &cpu->env; - riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); - env->priv_ver = PRIV_VERSION_1_10_0; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32); -#endif - - /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_zicsr = true; - cpu->cfg.mmu = true; - cpu->cfg.pmp = true; -} -#endif - static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; @@ -2921,6 +2883,17 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) if (def->misa_mxl_max) { assert(def->misa_mxl_max <= MXL_RV128); mcc->def->misa_mxl_max = def->misa_mxl_max; + +#ifndef CONFIG_USER_ONLY + /* + * Hack to simplify CPU class hierarchies that include both 32- and + * 64-bit models: reduce SV39/48/57/64 to SV32 for 32-bit models. + */ + if (mcc->def->misa_mxl_max == MXL_RV32 && + !valid_vm_1_10_32[mcc->def->cfg.max_satp_mode]) { + mcc->def->cfg.max_satp_mode = VM_1_10_SV32; + } +#endif } if (def->priv_spec != RISCV_PROFILE_ATTR_UNUSED) { assert(def->priv_spec <= PRIV_VERSION_LATEST); @@ -3140,6 +3113,17 @@ static const TypeInfo riscv_cpu_type_infos[] = { .cfg.pmp = true ), + DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_U, TYPE_RISCV_VENDOR_CPU, + .misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU, + .priv_spec = PRIV_VERSION_1_10_0, + + .cfg.max_satp_mode = VM_1_10_SV39, + .cfg.ext_zifencei = true, + .cfg.ext_zicsr = true, + .cfg.mmu = true, + .cfg.pmp = true + ), + #if defined(TARGET_RISCV32) || \ (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY)) DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE32, TYPE_RISCV_DYNAMIC_CPU, @@ -3171,7 +3155,9 @@ static const TypeInfo riscv_cpu_type_infos[] = { .misa_ext = RVF, /* IMAFCU */ ), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32, rv32_sifive_u_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_U34, TYPE_RISCV_CPU_SIFIVE_U, + .misa_mxl_max = MXL_RV32, + ), DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RV32I, TYPE_RISCV_BARE_CPU, .misa_mxl_max = MXL_RV32, @@ -3199,8 +3185,15 @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E51, TYPE_RISCV_CPU_SIFIVE_E, .misa_mxl_max = MXL_RV64 ), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64, rv64_sifive_u_cpu_init), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SHAKTI_C, MXL_RV64, rv64_sifive_u_cpu_init), + + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_U54, TYPE_RISCV_CPU_SIFIVE_U, + .misa_mxl_max = MXL_RV64, + ), + + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SHAKTI_C, TYPE_RISCV_CPU_SIFIVE_U, + .misa_mxl_max = MXL_RV64, + ), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906, MXL_RV64, rv64_thead_c906_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_TT_ASCALON, MXL_RV64, rv64_tt_ascalon_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, MXL_RV64, rv64_veyron_v1_cpu_init), From 1d84c2401c48617b8695d292602e2e777e0d1178 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 17:39:49 +0100 Subject: [PATCH 28/35] target/riscv: th: make CSR insertion test a bit more intuitive In preparation for generalizing the custom CSR functionality, make the test return bool instead of int. Make the insertion_test optional, too. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/th_csr.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/target/riscv/th_csr.c b/target/riscv/th_csr.c index 6c970d4e81..969a9fe3c8 100644 --- a/target/riscv/th_csr.c +++ b/target/riscv/th_csr.c @@ -29,7 +29,7 @@ typedef struct { int csrno; - int (*insertion_test)(RISCVCPU *cpu); + bool (*insertion_test)(RISCVCPU *cpu); riscv_csr_operations csr_ops; } riscv_csr; @@ -42,13 +42,9 @@ static RISCVException smode(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } -static int test_thead_mvendorid(RISCVCPU *cpu) +static bool test_thead_mvendorid(RISCVCPU *cpu) { - if (cpu->cfg.mvendorid != THEAD_VENDOR_ID) { - return -1; - } - - return 0; + return cpu->cfg.mvendorid == THEAD_VENDOR_ID; } static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno, @@ -66,13 +62,12 @@ static riscv_csr th_csr_list[] = { .csr_ops = { "th.sxstatus", smode, read_th_sxstatus } } }; - void th_register_custom_csrs(RISCVCPU *cpu) { for (size_t i = 0; i < ARRAY_SIZE(th_csr_list); i++) { int csrno = th_csr_list[i].csrno; riscv_csr_operations *csr_ops = &th_csr_list[i].csr_ops; - if (!th_csr_list[i].insertion_test(cpu)) { + if (!th_csr_list[i].insertion_test || th_csr_list[i].insertion_test(cpu)) { riscv_set_csr_ops(csrno, csr_ops); } } From 1016b0364f981e7aa9304866d7d756813e8dc6c2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 27 Feb 2025 15:09:49 +0100 Subject: [PATCH 29/35] target/riscv: generalize custom CSR functionality While at it, constify it so that the RISCVCSR array in RISCVCPUDef can also be const. Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 25 ++++++++++++++++++++++++- target/riscv/cpu.h | 15 ++++++++++++--- target/riscv/csr.c | 2 +- target/riscv/th_csr.c | 21 +++------------------ 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 01b028653a..12f4bc4151 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -485,6 +485,19 @@ static void set_satp_mode_default_map(RISCVCPU *cpu) } #endif +#ifndef CONFIG_USER_ONLY +static void riscv_register_custom_csrs(RISCVCPU *cpu, const RISCVCSR *csr_list) +{ + for (size_t i = 0; csr_list[i].csr_ops.name; i++) { + int csrno = csr_list[i].csrno; + const riscv_csr_operations *csr_ops = &csr_list[i].csr_ops; + if (!csr_list[i].insertion_test || csr_list[i].insertion_test(cpu)) { + riscv_set_csr_ops(csrno, csr_ops); + } + } +} +#endif + #if defined(TARGET_RISCV64) static void rv64_thead_c906_cpu_init(Object *obj) { @@ -511,7 +524,7 @@ static void rv64_thead_c906_cpu_init(Object *obj) cpu->cfg.mvendorid = THEAD_VENDOR_ID; #ifndef CONFIG_USER_ONLY set_satp_mode_max_supported(cpu, VM_1_10_SV39); - th_register_custom_csrs(cpu); + riscv_register_custom_csrs(cpu, th_csr_list); #endif /* inherited from parent obj via riscv_cpu_init() */ @@ -1304,6 +1317,11 @@ static void riscv_cpu_init(Object *obj) if (mcc->def->vext_spec != RISCV_PROFILE_ATTR_UNUSED) { cpu->env.vext_ver = mcc->def->vext_spec; } +#ifndef CONFIG_USER_ONLY + if (mcc->def->custom_csrs) { + riscv_register_custom_csrs(cpu, mcc->def->custom_csrs); + } +#endif } typedef struct misa_ext_info { @@ -2906,6 +2924,11 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) mcc->def->misa_ext |= def->misa_ext; riscv_cpu_cfg_merge(&mcc->def->cfg, &def->cfg); + + if (def->custom_csrs) { + assert(!mcc->def->custom_csrs); + mcc->def->custom_csrs = def->custom_csrs; + } } if (!object_class_is_abstract(c)) { diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index ed88adef45..229ade9ed9 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -538,6 +538,8 @@ struct ArchCPU { const GPtrArray *decoders; }; +typedef struct RISCVCSR RISCVCSR; + typedef struct RISCVCPUDef { RISCVMXL misa_mxl_max; /* max mxl for this cpu */ RISCVCPUProfile *profile; @@ -546,6 +548,7 @@ typedef struct RISCVCPUDef { int32_t vext_spec; RISCVCPUConfig cfg; bool bare; + const RISCVCSR *custom_csrs; } RISCVCPUDef; /** @@ -893,6 +896,12 @@ typedef struct { uint32_t min_priv_ver; } riscv_csr_operations; +struct RISCVCSR { + int csrno; + bool (*insertion_test)(RISCVCPU *cpu); + riscv_csr_operations csr_ops; +}; + /* CSR function table constants */ enum { CSR_TABLE_SIZE = 0x1000 @@ -947,7 +956,7 @@ extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[]; void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops); -void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops); +void riscv_set_csr_ops(int csrno, const riscv_csr_operations *ops); void riscv_cpu_register_gdb_regs_for_features(CPUState *cs); @@ -956,8 +965,8 @@ target_ulong riscv_new_csr_seed(target_ulong new_value, const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit); -/* Implemented in th_csr.c */ -void th_register_custom_csrs(RISCVCPU *cpu); +/* In th_csr.c */ +extern const RISCVCSR th_csr_list[]; const char *priv_spec_to_str(int priv_version); #endif /* RISCV_CPU_H */ diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9843fd2191..fb14972169 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -40,7 +40,7 @@ void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops) *ops = csr_ops[csrno & (CSR_TABLE_SIZE - 1)]; } -void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops) +void riscv_set_csr_ops(int csrno, const riscv_csr_operations *ops) { csr_ops[csrno & (CSR_TABLE_SIZE - 1)] = *ops; } diff --git a/target/riscv/th_csr.c b/target/riscv/th_csr.c index 969a9fe3c8..49eb7bbab5 100644 --- a/target/riscv/th_csr.c +++ b/target/riscv/th_csr.c @@ -27,12 +27,6 @@ #define TH_SXSTATUS_MAEE BIT(21) #define TH_SXSTATUS_THEADISAEE BIT(22) -typedef struct { - int csrno; - bool (*insertion_test)(RISCVCPU *cpu); - riscv_csr_operations csr_ops; -} riscv_csr; - static RISCVException smode(CPURISCVState *env, int csrno) { if (riscv_has_ext(env, RVS)) { @@ -55,20 +49,11 @@ static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static riscv_csr th_csr_list[] = { +const RISCVCSR th_csr_list[] = { { .csrno = CSR_TH_SXSTATUS, .insertion_test = test_thead_mvendorid, .csr_ops = { "th.sxstatus", smode, read_th_sxstatus } - } + }, + { } }; -void th_register_custom_csrs(RISCVCPU *cpu) -{ - for (size_t i = 0; i < ARRAY_SIZE(th_csr_list); i++) { - int csrno = th_csr_list[i].csrno; - riscv_csr_operations *csr_ops = &th_csr_list[i].csr_ops; - if (!th_csr_list[i].insertion_test || th_csr_list[i].insertion_test(cpu)) { - riscv_set_csr_ops(csrno, csr_ops); - } - } -} From 5f687d77ff93ae3dd2fb48600e4e6ae32eb7350e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 15:48:47 +0100 Subject: [PATCH 30/35] target/riscv: convert THead C906 to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 61 +++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 12f4bc4151..5d2ccf647d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -499,38 +499,6 @@ static void riscv_register_custom_csrs(RISCVCPU *cpu, const RISCVCSR *csr_list) #endif #if defined(TARGET_RISCV64) -static void rv64_thead_c906_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - RISCVCPU *cpu = RISCV_CPU(obj); - - riscv_cpu_set_misa_ext(env, RVG | RVC | RVS | RVU); - env->priv_ver = PRIV_VERSION_1_11_0; - - cpu->cfg.ext_zfa = true; - cpu->cfg.ext_zfh = true; - cpu->cfg.mmu = true; - cpu->cfg.ext_xtheadba = true; - cpu->cfg.ext_xtheadbb = true; - cpu->cfg.ext_xtheadbs = true; - cpu->cfg.ext_xtheadcmo = true; - cpu->cfg.ext_xtheadcondmov = true; - cpu->cfg.ext_xtheadfmemidx = true; - cpu->cfg.ext_xtheadmac = true; - cpu->cfg.ext_xtheadmemidx = true; - cpu->cfg.ext_xtheadmempair = true; - cpu->cfg.ext_xtheadsync = true; - - cpu->cfg.mvendorid = THEAD_VENDOR_ID; -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_SV39); - riscv_register_custom_csrs(cpu, th_csr_list); -#endif - - /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.pmp = true; -} - static void rv64_veyron_v1_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; @@ -3217,7 +3185,34 @@ static const TypeInfo riscv_cpu_type_infos[] = { .misa_mxl_max = MXL_RV64, ), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906, MXL_RV64, rv64_thead_c906_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_THEAD_C906, TYPE_RISCV_VENDOR_CPU, + .misa_mxl_max = MXL_RV64, + .misa_ext = RVG | RVC | RVS | RVU, + .priv_spec = PRIV_VERSION_1_11_0, + + .cfg.ext_zfa = true, + .cfg.ext_zfh = true, + .cfg.mmu = true, + .cfg.ext_xtheadba = true, + .cfg.ext_xtheadbb = true, + .cfg.ext_xtheadbs = true, + .cfg.ext_xtheadcmo = true, + .cfg.ext_xtheadcondmov = true, + .cfg.ext_xtheadfmemidx = true, + .cfg.ext_xtheadmac = true, + .cfg.ext_xtheadmemidx = true, + .cfg.ext_xtheadmempair = true, + .cfg.ext_xtheadsync = true, + .cfg.pmp = true, + + .cfg.mvendorid = THEAD_VENDOR_ID, + + .cfg.max_satp_mode = VM_1_10_SV39, +#ifndef CONFIG_USER_ONLY + .custom_csrs = th_csr_list, +#endif + ), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_TT_ASCALON, MXL_RV64, rv64_tt_ascalon_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, MXL_RV64, rv64_veyron_v1_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_XIANGSHAN_NANHU, From 09ef7d97454a64e00d8dc9fd3a188d6c06003cc1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 15:53:28 +0100 Subject: [PATCH 31/35] target/riscv: convert TT Ascalon to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 127 +++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 67 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 5d2ccf647d..48939adaaf 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -539,72 +539,6 @@ static void rv64_veyron_v1_cpu_init(Object *obj) #endif } -/* Tenstorrent Ascalon */ -static void rv64_tt_ascalon_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - RISCVCPU *cpu = RISCV_CPU(obj); - - riscv_cpu_set_misa_ext(env, RVG | RVC | RVS | RVU | RVH | RVV); - env->priv_ver = PRIV_VERSION_1_13_0; - - /* Enable ISA extensions */ - cpu->cfg.mmu = true; - cpu->cfg.vlenb = 256 >> 3; - cpu->cfg.elen = 64; - cpu->env.vext_ver = VEXT_VERSION_1_00_0; - cpu->cfg.rvv_ma_all_1s = true; - cpu->cfg.rvv_ta_all_1s = true; - cpu->cfg.misa_w = true; - cpu->cfg.pmp = true; - cpu->cfg.cbom_blocksize = 64; - cpu->cfg.cbop_blocksize = 64; - cpu->cfg.cboz_blocksize = 64; - cpu->cfg.ext_zic64b = true; - cpu->cfg.ext_zicbom = true; - cpu->cfg.ext_zicbop = true; - cpu->cfg.ext_zicboz = true; - cpu->cfg.ext_zicntr = true; - cpu->cfg.ext_zicond = true; - cpu->cfg.ext_zicsr = true; - cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_zihintntl = true; - cpu->cfg.ext_zihintpause = true; - cpu->cfg.ext_zihpm = true; - cpu->cfg.ext_zimop = true; - cpu->cfg.ext_zawrs = true; - cpu->cfg.ext_zfa = true; - cpu->cfg.ext_zfbfmin = true; - cpu->cfg.ext_zfh = true; - cpu->cfg.ext_zfhmin = true; - cpu->cfg.ext_zcb = true; - cpu->cfg.ext_zcmop = true; - cpu->cfg.ext_zba = true; - cpu->cfg.ext_zbb = true; - cpu->cfg.ext_zbs = true; - cpu->cfg.ext_zkt = true; - cpu->cfg.ext_zvbb = true; - cpu->cfg.ext_zvbc = true; - cpu->cfg.ext_zvfbfmin = true; - cpu->cfg.ext_zvfbfwma = true; - cpu->cfg.ext_zvfh = true; - cpu->cfg.ext_zvfhmin = true; - cpu->cfg.ext_zvkng = true; - cpu->cfg.ext_smaia = true; - cpu->cfg.ext_smstateen = true; - cpu->cfg.ext_ssaia = true; - cpu->cfg.ext_sscofpmf = true; - cpu->cfg.ext_sstc = true; - cpu->cfg.ext_svade = true; - cpu->cfg.ext_svinval = true; - cpu->cfg.ext_svnapot = true; - cpu->cfg.ext_svpbmt = true; - -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_SV57); -#endif -} - static void rv64_xiangshan_nanhu_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; @@ -3213,7 +3147,66 @@ static const TypeInfo riscv_cpu_type_infos[] = { #endif ), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_TT_ASCALON, MXL_RV64, rv64_tt_ascalon_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_TT_ASCALON, TYPE_RISCV_VENDOR_CPU, + .misa_mxl_max = MXL_RV64, + .misa_ext = RVG | RVC | RVS | RVU | RVH | RVV, + .priv_spec = PRIV_VERSION_1_13_0, + .vext_spec = VEXT_VERSION_1_00_0, + + /* ISA extensions */ + .cfg.mmu = true, + .cfg.vlenb = 256 >> 3, + .cfg.elen = 64, + .cfg.rvv_ma_all_1s = true, + .cfg.rvv_ta_all_1s = true, + .cfg.misa_w = true, + .cfg.pmp = true, + .cfg.cbom_blocksize = 64, + .cfg.cbop_blocksize = 64, + .cfg.cboz_blocksize = 64, + .cfg.ext_zic64b = true, + .cfg.ext_zicbom = true, + .cfg.ext_zicbop = true, + .cfg.ext_zicboz = true, + .cfg.ext_zicntr = true, + .cfg.ext_zicond = true, + .cfg.ext_zicsr = true, + .cfg.ext_zifencei = true, + .cfg.ext_zihintntl = true, + .cfg.ext_zihintpause = true, + .cfg.ext_zihpm = true, + .cfg.ext_zimop = true, + .cfg.ext_zawrs = true, + .cfg.ext_zfa = true, + .cfg.ext_zfbfmin = true, + .cfg.ext_zfh = true, + .cfg.ext_zfhmin = true, + .cfg.ext_zcb = true, + .cfg.ext_zcmop = true, + .cfg.ext_zba = true, + .cfg.ext_zbb = true, + .cfg.ext_zbs = true, + .cfg.ext_zkt = true, + .cfg.ext_zvbb = true, + .cfg.ext_zvbc = true, + .cfg.ext_zvfbfmin = true, + .cfg.ext_zvfbfwma = true, + .cfg.ext_zvfh = true, + .cfg.ext_zvfhmin = true, + .cfg.ext_zvkng = true, + .cfg.ext_smaia = true, + .cfg.ext_smstateen = true, + .cfg.ext_ssaia = true, + .cfg.ext_sscofpmf = true, + .cfg.ext_sstc = true, + .cfg.ext_svade = true, + .cfg.ext_svinval = true, + .cfg.ext_svnapot = true, + .cfg.ext_svpbmt = true, + + .cfg.max_satp_mode = VM_1_10_SV57, + ), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, MXL_RV64, rv64_veyron_v1_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_XIANGSHAN_NANHU, MXL_RV64, rv64_xiangshan_nanhu_cpu_init), From 0927f7d55cd5a214eb2ef9671ddd271a3fb2a15c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 15:53:28 +0100 Subject: [PATCH 32/35] target/riscv: convert Ventana V1 to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 75 ++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 48939adaaf..000fcc6a1d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -499,45 +499,6 @@ static void riscv_register_custom_csrs(RISCVCPU *cpu, const RISCVCSR *csr_list) #endif #if defined(TARGET_RISCV64) -static void rv64_veyron_v1_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - RISCVCPU *cpu = RISCV_CPU(obj); - - riscv_cpu_set_misa_ext(env, RVG | RVC | RVS | RVU | RVH); - env->priv_ver = PRIV_VERSION_1_12_0; - - /* Enable ISA extensions */ - cpu->cfg.mmu = true; - cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_zicsr = true; - cpu->cfg.pmp = true; - cpu->cfg.ext_zicbom = true; - cpu->cfg.cbom_blocksize = 64; - cpu->cfg.cboz_blocksize = 64; - cpu->cfg.ext_zicboz = true; - cpu->cfg.ext_smaia = true; - cpu->cfg.ext_ssaia = true; - cpu->cfg.ext_sscofpmf = true; - cpu->cfg.ext_sstc = true; - cpu->cfg.ext_svinval = true; - cpu->cfg.ext_svnapot = true; - cpu->cfg.ext_svpbmt = true; - cpu->cfg.ext_smstateen = true; - cpu->cfg.ext_zba = true; - cpu->cfg.ext_zbb = true; - cpu->cfg.ext_zbc = true; - cpu->cfg.ext_zbs = true; - cpu->cfg.ext_XVentanaCondOps = true; - - cpu->cfg.mvendorid = VEYRON_V1_MVENDORID; - cpu->cfg.marchid = VEYRON_V1_MARCHID; - cpu->cfg.mimpid = VEYRON_V1_MIMPID; - -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_SV48); -#endif -} static void rv64_xiangshan_nanhu_cpu_init(Object *obj) { @@ -3207,7 +3168,41 @@ static const TypeInfo riscv_cpu_type_infos[] = { .cfg.max_satp_mode = VM_1_10_SV57, ), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, MXL_RV64, rv64_veyron_v1_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_VEYRON_V1, TYPE_RISCV_VENDOR_CPU, + .misa_mxl_max = MXL_RV64, + .misa_ext = RVG | RVC | RVS | RVU | RVH, + .priv_spec = PRIV_VERSION_1_12_0, + + /* ISA extensions */ + .cfg.mmu = true, + .cfg.ext_zifencei = true, + .cfg.ext_zicsr = true, + .cfg.pmp = true, + .cfg.ext_zicbom = true, + .cfg.cbom_blocksize = 64, + .cfg.cboz_blocksize = 64, + .cfg.ext_zicboz = true, + .cfg.ext_smaia = true, + .cfg.ext_ssaia = true, + .cfg.ext_sscofpmf = true, + .cfg.ext_sstc = true, + .cfg.ext_svinval = true, + .cfg.ext_svnapot = true, + .cfg.ext_svpbmt = true, + .cfg.ext_smstateen = true, + .cfg.ext_zba = true, + .cfg.ext_zbb = true, + .cfg.ext_zbc = true, + .cfg.ext_zbs = true, + .cfg.ext_XVentanaCondOps = true, + + .cfg.mvendorid = VEYRON_V1_MVENDORID, + .cfg.marchid = VEYRON_V1_MARCHID, + .cfg.mimpid = VEYRON_V1_MIMPID, + + .cfg.max_satp_mode = VM_1_10_SV48, + ), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_XIANGSHAN_NANHU, MXL_RV64, rv64_xiangshan_nanhu_cpu_init), #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) From 70f48d7fb19a88bca3cd4c388646d4cb9ee730f0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 17:36:06 +0100 Subject: [PATCH 33/35] target/riscv: convert Xiangshan Nanhu to RISCVCPUDef Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 80 +++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 57 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 000fcc6a1d..640aa958fd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -440,16 +440,6 @@ const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit) g_assert_not_reached(); } -static void __attribute__((unused)) -set_satp_mode_max_supported(RISCVCPU *cpu, int satp_mode) -{ - bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32; - const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64; - - assert(valid_vm[satp_mode]); - cpu->cfg.max_satp_mode = satp_mode; -} - static bool get_satp_mode_supported(RISCVCPU *cpu, uint16_t *supported) { bool rv32 = riscv_cpu_is_32bit(cpu); @@ -498,38 +488,6 @@ static void riscv_register_custom_csrs(RISCVCPU *cpu, const RISCVCSR *csr_list) } #endif -#if defined(TARGET_RISCV64) - -static void rv64_xiangshan_nanhu_cpu_init(Object *obj) -{ - CPURISCVState *env = &RISCV_CPU(obj)->env; - RISCVCPU *cpu = RISCV_CPU(obj); - - riscv_cpu_set_misa_ext(env, RVG | RVC | RVB | RVS | RVU); - env->priv_ver = PRIV_VERSION_1_12_0; - - /* Enable ISA extensions */ - cpu->cfg.ext_zbc = true; - cpu->cfg.ext_zbkb = true; - cpu->cfg.ext_zbkc = true; - cpu->cfg.ext_zbkx = true; - cpu->cfg.ext_zknd = true; - cpu->cfg.ext_zkne = true; - cpu->cfg.ext_zknh = true; - cpu->cfg.ext_zksed = true; - cpu->cfg.ext_zksh = true; - cpu->cfg.ext_svinval = true; - - cpu->cfg.mmu = true; - cpu->cfg.pmp = true; - -#ifndef CONFIG_USER_ONLY - set_satp_mode_max_supported(cpu, VM_1_10_SV39); -#endif -} - -#endif /* !TARGET_RISCV64 */ - static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; @@ -2891,19 +2849,6 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename) } #endif -#define DEFINE_VENDOR_CPU(type_name, misa_mxl_max_, initfn) \ - { \ - .name = (type_name), \ - .parent = TYPE_RISCV_VENDOR_CPU, \ - .instance_init = (initfn), \ - .class_data = &(const RISCVCPUDef) { \ - .misa_mxl_max = (misa_mxl_max_), \ - .priv_spec = RISCV_PROFILE_ATTR_UNUSED, \ - .vext_spec = RISCV_PROFILE_ATTR_UNUSED, \ - .cfg.max_satp_mode = -1, \ - }, \ - } - #define DEFINE_ABSTRACT_RISCV_CPU(type_name, parent_type_name, ...) \ { \ .name = (type_name), \ @@ -3203,8 +3148,29 @@ static const TypeInfo riscv_cpu_type_infos[] = { .cfg.max_satp_mode = VM_1_10_SV48, ), - DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_XIANGSHAN_NANHU, - MXL_RV64, rv64_xiangshan_nanhu_cpu_init), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_XIANGSHAN_NANHU, TYPE_RISCV_VENDOR_CPU, + .misa_mxl_max = MXL_RV64, + .misa_ext = RVG | RVC | RVB | RVS | RVU, + .priv_spec = PRIV_VERSION_1_12_0, + + /* ISA extensions */ + .cfg.ext_zbc = true, + .cfg.ext_zbkb = true, + .cfg.ext_zbkc = true, + .cfg.ext_zbkx = true, + .cfg.ext_zknd = true, + .cfg.ext_zkne = true, + .cfg.ext_zknh = true, + .cfg.ext_zksed = true, + .cfg.ext_zksh = true, + .cfg.ext_svinval = true, + + .cfg.mmu = true, + .cfg.pmp = true, + + .cfg.max_satp_mode = VM_1_10_SV39, + ), + #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE128, TYPE_RISCV_DYNAMIC_CPU, .cfg.max_satp_mode = VM_1_10_SV57, From 42bc8af14033b9eeeb535449f243767c015f027e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 6 Feb 2025 12:57:12 +0100 Subject: [PATCH 34/35] target/riscv: remove .instance_post_init Unlike other uses of .instance_post_init, accel_cpu_instance_init() *registers* properties, and therefore must be run before device_post_init() which sets them to their values from -global. In order to move all registration of properties to .instance_init, call accel_cpu_instance_init() at the end of riscv_cpu_init(). Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- target/riscv/cpu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 640aa958fd..629ac37501 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1083,11 +1083,6 @@ static bool riscv_cpu_is_dynamic(Object *cpu_obj) return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL; } -static void riscv_cpu_post_init(Object *obj) -{ - accel_cpu_instance_init(CPU(obj)); -} - static void riscv_cpu_init(Object *obj) { RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(obj); @@ -1143,6 +1138,8 @@ static void riscv_cpu_init(Object *obj) riscv_register_custom_csrs(cpu, mcc->def->custom_csrs); } #endif + + accel_cpu_instance_init(CPU(obj)); } typedef struct misa_ext_info { @@ -2885,7 +2882,6 @@ static const TypeInfo riscv_cpu_type_infos[] = { .instance_size = sizeof(RISCVCPU), .instance_align = __alignof(RISCVCPU), .instance_init = riscv_cpu_init, - .instance_post_init = riscv_cpu_post_init, .abstract = true, .class_size = sizeof(RISCVCPUClass), .class_init = riscv_cpu_common_class_init, From 220c739903cec99df032219ac94c45b5269a0ab5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 3 Feb 2025 12:35:39 +0100 Subject: [PATCH 35/35] qom: reverse order of instance_post_init calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the instance_post_init calls are performed from the leaf class and all the way up to Object. This is incorrect because the leaf class cannot observe property values applied by the superclasses; for example, a compat property will be set on a device *after* the class's post_init callback has run. In particular this makes it impossible for implementations of accel_cpu_instance_init() to operate based on the actual values of the properties, though it seems that cxl_dsp_instance_post_init and rp_instance_post_init might have similar issues. Follow instead the same order as instance_init, starting with Object and running the child class's instance_post_init after the parent. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Signed-off-by: Paolo Bonzini --- include/qom/object.h | 3 ++- qom/object.c | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/qom/object.h b/include/qom/object.h index 1d5b033724..26df6137b9 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -445,7 +445,8 @@ struct Object * class will have already been initialized so the type is only responsible * for initializing its own members. * @instance_post_init: This function is called to finish initialization of - * an object, after all @instance_init functions were called. + * an object, after all @instance_init functions were called, as well as + * @instance_post_init functions for the parent classes. * @instance_finalize: This function is called during object destruction. This * is called before the parent @instance_finalize function has been called. * An object should only free the members that are unique to its type in this diff --git a/qom/object.c b/qom/object.c index 7b013f40a0..1856bb36c7 100644 --- a/qom/object.c +++ b/qom/object.c @@ -431,13 +431,13 @@ static void object_init_with_type(Object *obj, TypeImpl *ti) static void object_post_init_with_type(Object *obj, TypeImpl *ti) { - if (ti->instance_post_init) { - ti->instance_post_init(obj); - } - if (type_has_parent(ti)) { object_post_init_with_type(obj, type_get_parent(ti)); } + + if (ti->instance_post_init) { + ti->instance_post_init(obj); + } } bool object_apply_global_props(Object *obj, const GPtrArray *props,