mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-target-arm-20250701-1' of https://gitlab.com/pm215/qemu into staging
target-arm queue: * MAINTAINERS update for arm hvf * target/arm: Make RETA[AB] UNDEF when pauth is not implemented * target/arm: Refactoring of ID register value storage * target/arm: Various refactoring/cleanup patches * virt: Don't show an ITS in ACPI tables when no ITS is present * tests/functional: test device passthrough on aarch64 * tests/functional: Expand Aarch64 SMMU tests to run on HVF accelerator # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmhkE/IZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3vNeD/9ZcHiqTxLyuurYntf63VLP # 55NRozF0By7f83dOja5r+NWeGSPqhDBO05PpBVArt+giE2dkkVCoJ5stNrls5ACl # oi5glXQL/bW+A3nN+WmcD+s2RMVHn5jZ6f5ChRsFo2bWYl0rtrR1raC/wl415ag/ # MMRjbXj6sabEITY7794KBN4M5RDVS+Zcu7dzPZecsttbxLIGLBvvJ0bFSmh91tH4 # Tyy889v2GHou1BxSWVcSWNCTQ9jLYV7a+VHHs4uTlsBc3Pw7LXS4DcPhEdfZ3+gy # RaZUu1Eq213qd3r75FqFgR4mrY/nIm/CXd+mWjC5LsLOX0BYQKlAFiDH599AeZV3 # f1Wa0+POJDSKLDux+hPu3/2eeggI4d5XKAW9dgCYKicCtfhFEKXmTtaJtZyW+vTR # Vpl8SDVoljDd3q/045CXzOdM5N+5xj2WNNNKYYW4stHJrAIxa88pBeK2bqzT372x # V8FENVzK+7owTibi63XEshgdVlBcCB9Xpp+9p4TEbMZcd8EEUVDFC5F6iF9hNUYT # s1cqphTVscWDXxkTSok6POHOIvotRdT7EcIVQ9VfJxVREGrtWkioDii1O+olMhyF # uoeoxkFE1Jih4LQz937pqCCgP0PPd9DMtXdX/WeiAcZSDEHlO8gbRiIIyf11qL2i # aiMIF0rHY9PvxIisnukkLQ== # =x5Ur # -----END PGP SIGNATURE----- # gpg: Signature made Tue 01 Jul 2025 12:59:30 EDT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20250701-1' of https://gitlab.com/pm215/qemu: (43 commits) tests/functional: test device passthrough on aarch64 tests/functional: Expand Aarch64 SMMU tests to run on HVF accelerator tests/functional: Add hvf_available() helper tests/functional: Require TCG to run Aarch64 imx8mp-evk test tests/functional: Restrict nested Aarch64 Xen test to TCG tests/functional: Set sbsa-ref machine type in each test function hw/arm/sbsa-ref: Tidy up use of RAMLIMIT_GB definition hw/arm/virt: Rename cpu_post_init() -> post_cpus_gic_realized() hw/arm/virt: Make EL2 accelerator check an accept-list hw/arm/virt: Make EL3-guest accel check an accept-list target/arm: Restrict system register properties to system binary target/arm/hvf: Pass @target_el argument to hvf_raise_exception() target/arm: Correct KVM & HVF dtb_compatible value target/arm/hvf: Log $pc in hvf_unknown_hvc() trace event accel/hvf: Trace VM memory mapping target/arm/hvf: Trace hv_vcpu_run() failures target/arm/hvf: Directly re-lock BQL after hv_vcpu_run() target/arm: Unify gen_exception_internal() target/arm: Reduce arm_cpu_post_init() declaration scope target/arm: Remove arm_handle_psci_call() stub ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -511,6 +511,7 @@ F: system/cpus.c
|
||||
|
||||
Apple Silicon HVF CPUs
|
||||
M: Alexander Graf <agraf@csgraf.de>
|
||||
R: Mads Ynddal <mads@ynddal.dk>
|
||||
S: Maintained
|
||||
F: target/arm/hvf/
|
||||
F: target/arm/hvf-stub.c
|
||||
@@ -527,6 +528,7 @@ HVF
|
||||
M: Cameron Esfahani <dirty@apple.com>
|
||||
M: Roman Bolshakov <rbolshakov@ddn.com>
|
||||
R: Phil Dennis-Jordan <phil@philjordan.eu>
|
||||
R: Mads Ynddal <mads@ynddal.dk>
|
||||
W: https://wiki.qemu.org/Features/HVF
|
||||
S: Maintained
|
||||
F: accel/hvf/
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "system/hvf_int.h"
|
||||
#include "system/runstate.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "trace.h"
|
||||
|
||||
HVFState *hvf_state;
|
||||
|
||||
@@ -97,6 +98,7 @@ static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags)
|
||||
if (macslot->present) {
|
||||
if (macslot->size != slot->size) {
|
||||
macslot->present = 0;
|
||||
trace_hvf_vm_unmap(macslot->gpa_start, macslot->size);
|
||||
ret = hv_vm_unmap(macslot->gpa_start, macslot->size);
|
||||
assert_hvf_ok(ret);
|
||||
}
|
||||
@@ -109,6 +111,10 @@ static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags)
|
||||
macslot->present = 1;
|
||||
macslot->gpa_start = slot->start;
|
||||
macslot->size = slot->size;
|
||||
trace_hvf_vm_map(slot->start, slot->size, slot->mem, flags,
|
||||
flags & HV_MEMORY_READ ? 'R' : '-',
|
||||
flags & HV_MEMORY_WRITE ? 'W' : '-',
|
||||
flags & HV_MEMORY_EXEC ? 'E' : '-');
|
||||
ret = hv_vm_map(slot->mem, slot->start, slot->size, flags);
|
||||
assert_hvf_ok(ret);
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# See docs/devel/tracing.rst for syntax documentation.
|
||||
|
||||
# hvf-accel-ops.c
|
||||
hvf_vm_map(uint64_t paddr, uint64_t size, void *vaddr, uint8_t flags, const char r, const char w, const char e) "paddr:0x%016"PRIx64" size:0x%08"PRIx64" vaddr:%p flags:0x%02x/%c%c%c"
|
||||
hvf_vm_unmap(uint64_t paddr, uint64_t size) "paddr:0x%016"PRIx64" size:0x%08"PRIx64
|
||||
@@ -0,0 +1,2 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#include "trace/trace-accel_hvf.h"
|
||||
+5
-3
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/datadir.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -53,8 +54,7 @@
|
||||
#include "target/arm/cpu-qom.h"
|
||||
#include "target/arm/gtimer.h"
|
||||
|
||||
#define RAMLIMIT_GB 8192
|
||||
#define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB)
|
||||
#define RAMLIMIT_BYTES (8 * TiB)
|
||||
|
||||
#define NUM_IRQS 256
|
||||
#define NUM_SMMU_IRQS 4
|
||||
@@ -756,7 +756,9 @@ static void sbsa_ref_init(MachineState *machine)
|
||||
sms->smp_cpus = smp_cpus;
|
||||
|
||||
if (machine->ram_size > sbsa_ref_memmap[SBSA_MEM].size) {
|
||||
error_report("sbsa-ref: cannot model more than %dGB RAM", RAMLIMIT_GB);
|
||||
char *size_str = size_to_str(RAMLIMIT_BYTES);
|
||||
|
||||
error_report("sbsa-ref: cannot model more than %s of RAM", size_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
+124
-62
@@ -266,6 +266,43 @@ static int iort_idmap_compare(gconstpointer a, gconstpointer b)
|
||||
return idmap_a->input_base - idmap_b->input_base;
|
||||
}
|
||||
|
||||
/* Compute ID ranges (RIDs) from RC that are directed to the ITS Group node */
|
||||
static void create_rc_its_idmaps(GArray *its_idmaps, GArray *smmu_idmaps)
|
||||
{
|
||||
AcpiIortIdMapping *idmap;
|
||||
AcpiIortIdMapping next_range = {0};
|
||||
|
||||
/*
|
||||
* Based on the RID ranges that are directed to the SMMU, determine the
|
||||
* bypassed RID ranges, i.e., the ones that are directed to the ITS Group
|
||||
* node and do not pass through the SMMU, by subtracting the SMMU-bound
|
||||
* ranges from the full RID range (0x0000–0xFFFF).
|
||||
*/
|
||||
for (int i = 0; i < smmu_idmaps->len; i++) {
|
||||
idmap = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i);
|
||||
|
||||
if (next_range.input_base < idmap->input_base) {
|
||||
next_range.id_count = idmap->input_base - next_range.input_base;
|
||||
g_array_append_val(its_idmaps, next_range);
|
||||
}
|
||||
|
||||
next_range.input_base = idmap->input_base + idmap->id_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append the last RC -> ITS ID mapping.
|
||||
*
|
||||
* RIDs are 16-bit, according to the PCI Express 2.0 Base Specification, rev
|
||||
* 0.9, section 2.2.6.2, "Transaction Descriptor - Transaction ID Field",
|
||||
* hence the end of the range is 0x10000.
|
||||
*/
|
||||
if (next_range.input_base < 0x10000) {
|
||||
next_range.id_count = 0x10000 - next_range.input_base;
|
||||
g_array_append_val(its_idmaps, next_range);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Input Output Remapping Table (IORT)
|
||||
* Conforms to "IO Remapping Table System Software on ARM Platforms",
|
||||
@@ -276,10 +313,9 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
{
|
||||
int i, nb_nodes, rc_mapping_count;
|
||||
size_t node_size, smmu_offset = 0;
|
||||
AcpiIortIdMapping *idmap;
|
||||
uint32_t id = 0;
|
||||
GArray *smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
|
||||
GArray *its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
|
||||
GArray *rc_smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
|
||||
GArray *rc_its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping));
|
||||
|
||||
AcpiTable table = { .sig = "IORT", .rev = 3, .oem_id = vms->oem_id,
|
||||
.oem_table_id = vms->oem_table_id };
|
||||
@@ -287,40 +323,39 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
acpi_table_begin(&table, table_data);
|
||||
|
||||
if (vms->iommu == VIRT_IOMMU_SMMUV3) {
|
||||
AcpiIortIdMapping next_range = {0};
|
||||
|
||||
object_child_foreach_recursive(object_get_root(),
|
||||
iort_host_bridges, smmu_idmaps);
|
||||
iort_host_bridges, rc_smmu_idmaps);
|
||||
|
||||
/* Sort the smmu idmap by input_base */
|
||||
g_array_sort(smmu_idmaps, iort_idmap_compare);
|
||||
g_array_sort(rc_smmu_idmaps, iort_idmap_compare);
|
||||
|
||||
/*
|
||||
* Split the whole RIDs by mapping from RC to SMMU,
|
||||
* build the ID mapping from RC to ITS directly.
|
||||
* Knowing the ID ranges from the RC to the SMMU, it's possible to
|
||||
* determine the ID ranges from RC that are directed to the ITS.
|
||||
*/
|
||||
for (i = 0; i < smmu_idmaps->len; i++) {
|
||||
idmap = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i);
|
||||
create_rc_its_idmaps(rc_its_idmaps, rc_smmu_idmaps);
|
||||
|
||||
if (next_range.input_base < idmap->input_base) {
|
||||
next_range.id_count = idmap->input_base - next_range.input_base;
|
||||
g_array_append_val(its_idmaps, next_range);
|
||||
}
|
||||
nb_nodes = 2; /* RC and SMMUv3 */
|
||||
rc_mapping_count = rc_smmu_idmaps->len;
|
||||
|
||||
next_range.input_base = idmap->input_base + idmap->id_count;
|
||||
if (vms->its) {
|
||||
/*
|
||||
* Knowing the ID ranges from the RC to the SMMU, it's possible to
|
||||
* determine the ID ranges from RC that go directly to ITS.
|
||||
*/
|
||||
create_rc_its_idmaps(rc_its_idmaps, rc_smmu_idmaps);
|
||||
|
||||
nb_nodes++; /* ITS */
|
||||
rc_mapping_count += rc_its_idmaps->len;
|
||||
}
|
||||
|
||||
/* Append the last RC -> ITS ID mapping */
|
||||
if (next_range.input_base < 0x10000) {
|
||||
next_range.id_count = 0x10000 - next_range.input_base;
|
||||
g_array_append_val(its_idmaps, next_range);
|
||||
}
|
||||
|
||||
nb_nodes = 3; /* RC, ITS, SMMUv3 */
|
||||
rc_mapping_count = smmu_idmaps->len + its_idmaps->len;
|
||||
} else {
|
||||
nb_nodes = 2; /* RC, ITS */
|
||||
rc_mapping_count = 1;
|
||||
if (vms->its) {
|
||||
nb_nodes = 2; /* RC and ITS */
|
||||
rc_mapping_count = 1; /* Direct map to ITS */
|
||||
} else {
|
||||
nb_nodes = 1; /* RC only */
|
||||
rc_mapping_count = 0; /* No output mapping */
|
||||
}
|
||||
}
|
||||
/* Number of IORT Nodes */
|
||||
build_append_int_noprefix(table_data, nb_nodes, 4);
|
||||
@@ -329,31 +364,43 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
build_append_int_noprefix(table_data, IORT_NODE_OFFSET, 4);
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
|
||||
|
||||
/* Table 12 ITS Group Format */
|
||||
build_append_int_noprefix(table_data, 0 /* ITS Group */, 1); /* Type */
|
||||
node_size = 20 /* fixed header size */ + 4 /* 1 GIC ITS Identifier */;
|
||||
build_append_int_noprefix(table_data, node_size, 2); /* Length */
|
||||
build_append_int_noprefix(table_data, 1, 1); /* Revision */
|
||||
build_append_int_noprefix(table_data, id++, 4); /* Identifier */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Number of ID mappings */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Reference to ID Array */
|
||||
build_append_int_noprefix(table_data, 1, 4); /* Number of ITSs */
|
||||
/* GIC ITS Identifier Array */
|
||||
build_append_int_noprefix(table_data, 0 /* MADT translation_id */, 4);
|
||||
if (vms->its) {
|
||||
/* Table 12 ITS Group Format */
|
||||
build_append_int_noprefix(table_data, 0 /* ITS Group */, 1); /* Type */
|
||||
node_size = 20 /* fixed header size */ + 4 /* 1 GIC ITS Identifier */;
|
||||
build_append_int_noprefix(table_data, node_size, 2); /* Length */
|
||||
build_append_int_noprefix(table_data, 1, 1); /* Revision */
|
||||
build_append_int_noprefix(table_data, id++, 4); /* Identifier */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Number of ID mappings */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Reference to ID Array */
|
||||
build_append_int_noprefix(table_data, 1, 4); /* Number of ITSs */
|
||||
/* GIC ITS Identifier Array */
|
||||
build_append_int_noprefix(table_data, 0 /* MADT translation_id */, 4);
|
||||
}
|
||||
|
||||
if (vms->iommu == VIRT_IOMMU_SMMUV3) {
|
||||
int irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
|
||||
int smmu_mapping_count, offset_to_id_array;
|
||||
|
||||
if (vms->its) {
|
||||
smmu_mapping_count = 1; /* ITS Group node */
|
||||
offset_to_id_array = SMMU_V3_ENTRY_SIZE; /* Just after the header */
|
||||
} else {
|
||||
smmu_mapping_count = 0; /* No ID mappings */
|
||||
offset_to_id_array = 0; /* No ID mappings array */
|
||||
}
|
||||
smmu_offset = table_data->len - table.table_offset;
|
||||
/* Table 9 SMMUv3 Format */
|
||||
build_append_int_noprefix(table_data, 4 /* SMMUv3 */, 1); /* Type */
|
||||
node_size = SMMU_V3_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE;
|
||||
node_size = SMMU_V3_ENTRY_SIZE +
|
||||
(ID_MAPPING_ENTRY_SIZE * smmu_mapping_count);
|
||||
build_append_int_noprefix(table_data, node_size, 2); /* Length */
|
||||
build_append_int_noprefix(table_data, 4, 1); /* Revision */
|
||||
build_append_int_noprefix(table_data, id++, 4); /* Identifier */
|
||||
build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */
|
||||
/* Number of ID mappings */
|
||||
build_append_int_noprefix(table_data, smmu_mapping_count, 4);
|
||||
/* Reference to ID Array */
|
||||
build_append_int_noprefix(table_data, SMMU_V3_ENTRY_SIZE, 4);
|
||||
build_append_int_noprefix(table_data, offset_to_id_array, 4);
|
||||
/* Base address */
|
||||
build_append_int_noprefix(table_data, vms->memmap[VIRT_SMMU].base, 8);
|
||||
/* Flags */
|
||||
@@ -369,9 +416,11 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Proximity domain */
|
||||
/* DeviceID mapping index (ignored since interrupts are GSIV based) */
|
||||
build_append_int_noprefix(table_data, 0, 4);
|
||||
|
||||
/* output IORT node is the ITS group node (the first node) */
|
||||
build_iort_id_mapping(table_data, 0, 0x10000, IORT_NODE_OFFSET);
|
||||
/* Array of ID mappings */
|
||||
if (smmu_mapping_count) {
|
||||
/* Output IORT node is the ITS Group node (the first node). */
|
||||
build_iort_id_mapping(table_data, 0, 0x10000, IORT_NODE_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
/* Table 17 Root Complex Node */
|
||||
@@ -407,29 +456,44 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
if (vms->iommu == VIRT_IOMMU_SMMUV3) {
|
||||
AcpiIortIdMapping *range;
|
||||
|
||||
/* translated RIDs connect to SMMUv3 node: RC -> SMMUv3 -> ITS */
|
||||
for (i = 0; i < smmu_idmaps->len; i++) {
|
||||
range = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i);
|
||||
/* output IORT node is the smmuv3 node */
|
||||
/*
|
||||
* Map RIDs (input) from RC to SMMUv3 nodes: RC -> SMMUv3.
|
||||
*
|
||||
* N.B.: The mapping from SMMUv3 to ITS Group node (SMMUv3 -> ITS) is
|
||||
* defined in the SMMUv3 table, where all SMMUv3 IDs are mapped to the
|
||||
* ITS Group node, if ITS is available.
|
||||
*/
|
||||
for (i = 0; i < rc_smmu_idmaps->len; i++) {
|
||||
range = &g_array_index(rc_smmu_idmaps, AcpiIortIdMapping, i);
|
||||
/* Output IORT node is the SMMUv3 node. */
|
||||
build_iort_id_mapping(table_data, range->input_base,
|
||||
range->id_count, smmu_offset);
|
||||
}
|
||||
|
||||
/* bypassed RIDs connect to ITS group node directly: RC -> ITS */
|
||||
for (i = 0; i < its_idmaps->len; i++) {
|
||||
range = &g_array_index(its_idmaps, AcpiIortIdMapping, i);
|
||||
/* output IORT node is the ITS group node (the first node) */
|
||||
build_iort_id_mapping(table_data, range->input_base,
|
||||
range->id_count, IORT_NODE_OFFSET);
|
||||
if (vms->its) {
|
||||
/*
|
||||
* Map bypassed (don't go through the SMMU) RIDs (input) to
|
||||
* ITS Group node directly: RC -> ITS.
|
||||
*/
|
||||
for (i = 0; i < rc_its_idmaps->len; i++) {
|
||||
range = &g_array_index(rc_its_idmaps, AcpiIortIdMapping, i);
|
||||
/* Output IORT node is the ITS Group node (the first node). */
|
||||
build_iort_id_mapping(table_data, range->input_base,
|
||||
range->id_count, IORT_NODE_OFFSET);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* output IORT node is the ITS group node (the first node) */
|
||||
/*
|
||||
* Map all RIDs (input) to ITS Group node directly, since there is no
|
||||
* SMMU: RC -> ITS.
|
||||
* Output IORT node is the ITS Group node (the first node).
|
||||
*/
|
||||
build_iort_id_mapping(table_data, 0, 0x10000, IORT_NODE_OFFSET);
|
||||
}
|
||||
|
||||
acpi_table_end(linker, &table);
|
||||
g_array_free(smmu_idmaps, true);
|
||||
g_array_free(its_idmaps, true);
|
||||
g_array_free(rc_smmu_idmaps, true);
|
||||
g_array_free(rc_its_idmaps, true);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -737,7 +801,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
memmap[VIRT_HIGH_GIC_REDIST2].size);
|
||||
}
|
||||
|
||||
if (its_class_name()) {
|
||||
if (vms->its) {
|
||||
/*
|
||||
* ACPI spec, Revision 6.0 Errata A
|
||||
* (original 6.0 definition has invalid Length)
|
||||
@@ -969,10 +1033,8 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
||||
vms->oem_table_id);
|
||||
}
|
||||
|
||||
if (its_class_name()) {
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_iort(tables_blob, tables->linker, vms);
|
||||
}
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_iort(tables_blob, tables->linker, vms);
|
||||
|
||||
#ifdef CONFIG_TPM
|
||||
if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) {
|
||||
|
||||
+16
-22
@@ -705,21 +705,18 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
||||
|
||||
static void create_its(VirtMachineState *vms)
|
||||
{
|
||||
const char *itsclass = its_class_name();
|
||||
DeviceState *dev;
|
||||
|
||||
if (!strcmp(itsclass, "arm-gicv3-its")) {
|
||||
if (!vms->tcg_its) {
|
||||
itsclass = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!itsclass) {
|
||||
/* Do nothing if not supported */
|
||||
assert(vms->its);
|
||||
if (!kvm_irqchip_in_kernel() && !vms->tcg_its) {
|
||||
/*
|
||||
* Do nothing if ITS is neither supported by the host nor emulated by
|
||||
* the machine.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
dev = qdev_new(itsclass);
|
||||
dev = qdev_new(its_class_name());
|
||||
|
||||
object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(vms->gic),
|
||||
&error_abort);
|
||||
@@ -2029,10 +2026,11 @@ static void finalize_gic_version(VirtMachineState *vms)
|
||||
}
|
||||
|
||||
/*
|
||||
* virt_cpu_post_init() must be called after the CPUs have
|
||||
* been realized and the GIC has been created.
|
||||
* virt_post_cpus_gic_realized() must be called after the CPUs and
|
||||
* the GIC have both been realized.
|
||||
*/
|
||||
static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
|
||||
static void virt_post_cpus_gic_realized(VirtMachineState *vms,
|
||||
MemoryRegion *sysmem)
|
||||
{
|
||||
int max_cpus = MACHINE(vms)->smp.max_cpus;
|
||||
bool aarch64, pmu, steal_time;
|
||||
@@ -2203,14 +2201,14 @@ static void machvirt_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (vms->secure && (kvm_enabled() || hvf_enabled())) {
|
||||
if (vms->secure && !tcg_enabled() && !qtest_enabled()) {
|
||||
error_report("mach-virt: %s does not support providing "
|
||||
"Security extensions (TrustZone) to the guest CPU",
|
||||
current_accel_name());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
|
||||
if (vms->virt && !tcg_enabled() && !qtest_enabled()) {
|
||||
error_report("mach-virt: %s does not support providing "
|
||||
"Virtualization extensions to the guest CPU",
|
||||
current_accel_name());
|
||||
@@ -2349,7 +2347,7 @@ static void machvirt_init(MachineState *machine)
|
||||
|
||||
create_gic(vms, sysmem);
|
||||
|
||||
virt_cpu_post_init(vms, sysmem);
|
||||
virt_post_cpus_gic_realized(vms, sysmem);
|
||||
|
||||
fdt_add_pmu_nodes(vms);
|
||||
|
||||
@@ -3342,12 +3340,8 @@ static void virt_instance_init(Object *obj)
|
||||
|
||||
/* Default allows ITS instantiation */
|
||||
vms->its = true;
|
||||
|
||||
if (vmc->no_tcg_its) {
|
||||
vms->tcg_its = false;
|
||||
} else {
|
||||
vms->tcg_its = true;
|
||||
}
|
||||
/* Allow ITS emulation if the machine version supports it */
|
||||
vms->tcg_its = !vmc->no_tcg_its;
|
||||
|
||||
/* Default disallows iommu instantiation */
|
||||
vms->iommu = VIRT_IOMMU_NONE;
|
||||
|
||||
+14
-13
@@ -988,6 +988,7 @@ static void nvic_nmi_trigger(void *opaque, int n, int level)
|
||||
static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
|
||||
{
|
||||
ARMCPU *cpu = s->cpu;
|
||||
ARMISARegisters *isar = &cpu->isar;
|
||||
uint32_t val;
|
||||
|
||||
switch (offset) {
|
||||
@@ -1263,17 +1264,17 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_pfr0;
|
||||
return GET_IDREG(isar, ID_PFR0);
|
||||
case 0xd44: /* PFR1. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_pfr1;
|
||||
return GET_IDREG(isar, ID_PFR1);
|
||||
case 0xd48: /* DFR0. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_dfr0;
|
||||
return GET_IDREG(isar, ID_DFR0);
|
||||
case 0xd4c: /* AFR0. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
@@ -1283,52 +1284,52 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_mmfr0;
|
||||
return GET_IDREG(isar, ID_MMFR0);
|
||||
case 0xd54: /* MMFR1. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_mmfr1;
|
||||
return GET_IDREG(isar, ID_MMFR1);
|
||||
case 0xd58: /* MMFR2. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_mmfr2;
|
||||
return GET_IDREG(isar, ID_MMFR2);
|
||||
case 0xd5c: /* MMFR3. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_mmfr3;
|
||||
return GET_IDREG(isar, ID_MMFR3);
|
||||
case 0xd60: /* ISAR0. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_isar0;
|
||||
return GET_IDREG(&cpu->isar, ID_ISAR0);
|
||||
case 0xd64: /* ISAR1. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_isar1;
|
||||
return GET_IDREG(&cpu->isar, ID_ISAR1);
|
||||
case 0xd68: /* ISAR2. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_isar2;
|
||||
return GET_IDREG(&cpu->isar, ID_ISAR2);
|
||||
case 0xd6c: /* ISAR3. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_isar3;
|
||||
return GET_IDREG(&cpu->isar, ID_ISAR3);
|
||||
case 0xd70: /* ISAR4. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_isar4;
|
||||
return GET_IDREG(&cpu->isar, ID_ISAR4);
|
||||
case 0xd74: /* ISAR5. */
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
return cpu->isar.id_isar5;
|
||||
return GET_IDREG(&cpu->isar, ID_ISAR5);
|
||||
case 0xd78: /* CLIDR */
|
||||
return cpu->clidr;
|
||||
case 0xd7c: /* CTR */
|
||||
|
||||
@@ -128,7 +128,7 @@ struct GICv3ITSCommonClass {
|
||||
* Return the ITS class name to use depending on whether KVM acceleration
|
||||
* and KVM CAP_SIGNAL_MSI are supported
|
||||
*
|
||||
* Returns: class name to use or NULL
|
||||
* Returns: class name to use
|
||||
*/
|
||||
const char *its_class_name(void);
|
||||
|
||||
|
||||
@@ -3630,6 +3630,7 @@ if have_block
|
||||
endif
|
||||
if have_system
|
||||
trace_events_subdirs += [
|
||||
'accel/hvf',
|
||||
'accel/kvm',
|
||||
'audio',
|
||||
'backends',
|
||||
|
||||
@@ -23,13 +23,19 @@ import textwrap
|
||||
from typing import Optional
|
||||
|
||||
# pylint: disable=import-error
|
||||
from .accel import kvm_available, list_accel, tcg_available
|
||||
from .accel import (
|
||||
hvf_available,
|
||||
kvm_available,
|
||||
list_accel,
|
||||
tcg_available,
|
||||
)
|
||||
|
||||
|
||||
__all__ = (
|
||||
'VerboseProcessError',
|
||||
'add_visual_margin',
|
||||
'get_info_usernet_hostfwd_port',
|
||||
'hvf_available',
|
||||
'kvm_available',
|
||||
'list_accel',
|
||||
'tcg_available',
|
||||
|
||||
@@ -82,3 +82,12 @@ def tcg_available(qemu_bin: str) -> bool:
|
||||
@param qemu_bin (str): path to the QEMU binary
|
||||
"""
|
||||
return 'tcg' in list_accel(qemu_bin)
|
||||
|
||||
|
||||
def hvf_available(qemu_bin: str) -> bool:
|
||||
"""
|
||||
Check if HVF is available.
|
||||
|
||||
@param qemu_bin (str): path to the QEMU binary
|
||||
"""
|
||||
return 'hvf' in list_accel(qemu_bin)
|
||||
|
||||
+159
-158
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Definitions for Arm ID system registers
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef ARM_CPU_SYSREGS_H
|
||||
#define ARM_CPU_SYSREGS_H
|
||||
|
||||
/*
|
||||
* Following is similar to the coprocessor regs encodings, but with an argument
|
||||
* ordering that matches the ARM ARM. We also reuse the various CP_REG_ defines
|
||||
* that actually are the same as the equivalent KVM_REG_ values.
|
||||
*/
|
||||
#define ENCODE_ID_REG(op0, op1, crn, crm, op2) \
|
||||
(((op0) << CP_REG_ARM64_SYSREG_OP0_SHIFT) | \
|
||||
((op1) << CP_REG_ARM64_SYSREG_OP1_SHIFT) | \
|
||||
((crn) << CP_REG_ARM64_SYSREG_CRN_SHIFT) | \
|
||||
((crm) << CP_REG_ARM64_SYSREG_CRM_SHIFT) | \
|
||||
((op2) << CP_REG_ARM64_SYSREG_OP2_SHIFT))
|
||||
|
||||
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) NAME##_IDX,
|
||||
|
||||
typedef enum ARMIDRegisterIdx {
|
||||
#include "cpu-sysregs.h.inc"
|
||||
NUM_ID_IDX,
|
||||
} ARMIDRegisterIdx;
|
||||
|
||||
#undef DEF
|
||||
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \
|
||||
SYS_##NAME = ENCODE_ID_REG(OP0, OP1, CRN, CRM, OP2),
|
||||
|
||||
typedef enum ARMSysRegs {
|
||||
#include "cpu-sysregs.h.inc"
|
||||
} ARMSysRegs;
|
||||
|
||||
#undef DEF
|
||||
|
||||
extern const uint32_t id_register_sysreg[NUM_ID_IDX];
|
||||
|
||||
int get_sysreg_idx(ARMSysRegs sysreg);
|
||||
|
||||
#endif /* ARM_CPU_SYSREGS_H */
|
||||
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
DEF(ID_AA64PFR0_EL1, 3, 0, 0, 4, 0)
|
||||
DEF(ID_AA64PFR1_EL1, 3, 0, 0, 4, 1)
|
||||
DEF(ID_AA64SMFR0_EL1, 3, 0, 0, 4, 5)
|
||||
DEF(ID_AA64DFR0_EL1, 3, 0, 0, 5, 0)
|
||||
DEF(ID_AA64DFR1_EL1, 3, 0, 0, 5, 1)
|
||||
DEF(ID_AA64ISAR0_EL1, 3, 0, 0, 6, 0)
|
||||
DEF(ID_AA64ISAR1_EL1, 3, 0, 0, 6, 1)
|
||||
DEF(ID_AA64ISAR2_EL1, 3, 0, 0, 6, 2)
|
||||
DEF(ID_AA64MMFR0_EL1, 3, 0, 0, 7, 0)
|
||||
DEF(ID_AA64MMFR1_EL1, 3, 0, 0, 7, 1)
|
||||
DEF(ID_AA64MMFR2_EL1, 3, 0, 0, 7, 2)
|
||||
DEF(ID_AA64MMFR3_EL1, 3, 0, 0, 7, 3)
|
||||
DEF(ID_PFR0_EL1, 3, 0, 0, 1, 0)
|
||||
DEF(ID_PFR1_EL1, 3, 0, 0, 1, 1)
|
||||
DEF(ID_DFR0_EL1, 3, 0, 0, 1, 2)
|
||||
DEF(ID_MMFR0_EL1, 3, 0, 0, 1, 4)
|
||||
DEF(ID_MMFR1_EL1, 3, 0, 0, 1, 5)
|
||||
DEF(ID_MMFR2_EL1, 3, 0, 0, 1, 6)
|
||||
DEF(ID_MMFR3_EL1, 3, 0, 0, 1, 7)
|
||||
DEF(ID_ISAR0_EL1, 3, 0, 0, 2, 0)
|
||||
DEF(ID_ISAR1_EL1, 3, 0, 0, 2, 1)
|
||||
DEF(ID_ISAR2_EL1, 3, 0, 0, 2, 2)
|
||||
DEF(ID_ISAR3_EL1, 3, 0, 0, 2, 3)
|
||||
DEF(ID_ISAR4_EL1, 3, 0, 0, 2, 4)
|
||||
DEF(ID_ISAR5_EL1, 3, 0, 0, 2, 5)
|
||||
DEF(ID_MMFR4_EL1, 3, 0, 0, 2, 6)
|
||||
DEF(ID_ISAR6_EL1, 3, 0, 0, 2, 7)
|
||||
DEF(MVFR0_EL1, 3, 0, 0, 3, 0)
|
||||
DEF(MVFR1_EL1, 3, 0, 0, 3, 1)
|
||||
DEF(MVFR2_EL1, 3, 0, 0, 3, 2)
|
||||
DEF(ID_PFR2_EL1, 3, 0, 0, 3, 4)
|
||||
DEF(ID_DFR1_EL1, 3, 0, 0, 3, 5)
|
||||
DEF(ID_MMFR5_EL1, 3, 0, 0, 3, 6)
|
||||
DEF(ID_AA64ZFR0_EL1, 3, 0, 0, 4, 4)
|
||||
DEF(CTR_EL0, 3, 3, 0, 0, 1)
|
||||
+48
-76
@@ -1500,6 +1500,7 @@ static void arm_cpu_initfn(Object *obj)
|
||||
* 0 means "unset, use the default value". That default might vary depending
|
||||
* on the CPU type, and is set in the realize fn.
|
||||
*/
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static const Property arm_cpu_gt_cntfrq_property =
|
||||
DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz, 0);
|
||||
|
||||
@@ -1509,7 +1510,6 @@ static const Property arm_cpu_reset_cbar_property =
|
||||
static const Property arm_cpu_reset_hivecs_property =
|
||||
DEFINE_PROP_BOOL("reset-hivecs", ARMCPU, reset_hivecs, false);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static const Property arm_cpu_has_el2_property =
|
||||
DEFINE_PROP_BOOL("has_el2", ARMCPU, has_el2, true);
|
||||
|
||||
@@ -1532,6 +1532,7 @@ static const Property arm_cpu_has_neon_property =
|
||||
static const Property arm_cpu_has_dsp_property =
|
||||
DEFINE_PROP_BOOL("dsp", ARMCPU, has_dsp, true);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static const Property arm_cpu_has_mpu_property =
|
||||
DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
|
||||
|
||||
@@ -1544,6 +1545,7 @@ static const Property arm_cpu_pmsav7_dregion_property =
|
||||
DEFINE_PROP_UNSIGNED_NODEFAULT("pmsav7-dregion", ARMCPU,
|
||||
pmsav7_dregion,
|
||||
qdev_prop_uint32, uint32_t);
|
||||
#endif
|
||||
|
||||
static bool arm_get_pmu(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -1713,7 +1715,7 @@ static void arm_cpu_propagate_feature_implications(ARMCPU *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
void arm_cpu_post_init(Object *obj)
|
||||
static void arm_cpu_post_init(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
|
||||
@@ -1731,6 +1733,7 @@ void arm_cpu_post_init(Object *obj)
|
||||
"Set on/off to enable/disable aarch64 "
|
||||
"execution state ");
|
||||
}
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
|
||||
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
|
||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_cbar_property);
|
||||
@@ -1746,7 +1749,6 @@ void arm_cpu_post_init(Object *obj)
|
||||
OBJ_PROP_FLAG_READWRITE);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
|
||||
/* Add the has_el3 state CPU property only if EL3 is allowed. This will
|
||||
* prevent "has_el3" from existing on CPUs which cannot support EL3.
|
||||
@@ -1818,6 +1820,7 @@ void arm_cpu_post_init(Object *obj)
|
||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_dsp_property);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_PMSA)) {
|
||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_mpu_property);
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_V7)) {
|
||||
@@ -1854,8 +1857,6 @@ void arm_cpu_post_init(Object *obj)
|
||||
&cpu->psci_conduit,
|
||||
OBJ_PROP_FLAG_READWRITE);
|
||||
|
||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property);
|
||||
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) {
|
||||
qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property);
|
||||
}
|
||||
@@ -1864,7 +1865,6 @@ void arm_cpu_post_init(Object *obj)
|
||||
kvm_arm_add_vcpu_properties(cpu);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) &&
|
||||
cpu_isar_feature(aa64_mte, cpu)) {
|
||||
object_property_add_link(obj, "tag-memory",
|
||||
@@ -1882,6 +1882,7 @@ void arm_cpu_post_init(Object *obj)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property);
|
||||
}
|
||||
|
||||
static void arm_cpu_finalizefn(Object *obj)
|
||||
@@ -1962,6 +1963,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
ARMCPU *cpu = ARM_CPU(dev);
|
||||
ARMISARegisters *isar = &cpu->isar;
|
||||
ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev);
|
||||
CPUARMState *env = &cpu->env;
|
||||
Error *local_err = NULL;
|
||||
@@ -2119,21 +2121,16 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
if (!cpu->has_vfp) {
|
||||
uint64_t t;
|
||||
uint32_t u;
|
||||
|
||||
t = cpu->isar.id_aa64isar1;
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0);
|
||||
cpu->isar.id_aa64isar1 = t;
|
||||
FIELD_DP64_IDREG(isar, ID_AA64ISAR1, JSCVT, 0);
|
||||
|
||||
t = cpu->isar.id_aa64pfr0;
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf);
|
||||
cpu->isar.id_aa64pfr0 = t;
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR0, FP, 0xf);
|
||||
|
||||
u = cpu->isar.id_isar6;
|
||||
u = GET_IDREG(isar, ID_ISAR6);
|
||||
u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR6, BF16, 0);
|
||||
cpu->isar.id_isar6 = u;
|
||||
SET_IDREG(isar, ID_ISAR6, u);
|
||||
|
||||
u = cpu->isar.mvfr0;
|
||||
u = FIELD_DP32(u, MVFR0, FPSP, 0);
|
||||
@@ -2167,7 +2164,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
|
||||
unset_feature(env, ARM_FEATURE_NEON);
|
||||
|
||||
t = cpu->isar.id_aa64isar0;
|
||||
t = GET_IDREG(isar, ID_AA64ISAR0);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, AES, 0);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 0);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 0);
|
||||
@@ -2175,32 +2172,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 0);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 0);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0);
|
||||
cpu->isar.id_aa64isar0 = t;
|
||||
SET_IDREG(isar, ID_AA64ISAR0, t);
|
||||
|
||||
t = cpu->isar.id_aa64isar1;
|
||||
t = GET_IDREG(isar, ID_AA64ISAR1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 0);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0);
|
||||
cpu->isar.id_aa64isar1 = t;
|
||||
SET_IDREG(isar, ID_AA64ISAR1, t);
|
||||
|
||||
t = cpu->isar.id_aa64pfr0;
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf);
|
||||
cpu->isar.id_aa64pfr0 = t;
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR0, ADVSIMD, 0xf);
|
||||
|
||||
u = cpu->isar.id_isar5;
|
||||
u = GET_IDREG(isar, ID_ISAR5);
|
||||
u = FIELD_DP32(u, ID_ISAR5, AES, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR5, SHA1, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR5, SHA2, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR5, RDM, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR5, VCMA, 0);
|
||||
cpu->isar.id_isar5 = u;
|
||||
SET_IDREG(isar, ID_ISAR5, u);
|
||||
|
||||
u = cpu->isar.id_isar6;
|
||||
u = GET_IDREG(isar, ID_ISAR6);
|
||||
u = FIELD_DP32(u, ID_ISAR6, DP, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR6, BF16, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR6, I8MM, 0);
|
||||
cpu->isar.id_isar6 = u;
|
||||
SET_IDREG(isar, ID_ISAR6, u);
|
||||
|
||||
if (!arm_feature(env, ARM_FEATURE_M)) {
|
||||
u = cpu->isar.mvfr1;
|
||||
@@ -2217,16 +2212,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
if (!cpu->has_neon && !cpu->has_vfp) {
|
||||
uint64_t t;
|
||||
uint32_t u;
|
||||
|
||||
t = cpu->isar.id_aa64isar0;
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0);
|
||||
cpu->isar.id_aa64isar0 = t;
|
||||
FIELD_DP64_IDREG(isar, ID_AA64ISAR0, FHM, 0);
|
||||
|
||||
t = cpu->isar.id_aa64isar1;
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0);
|
||||
cpu->isar.id_aa64isar1 = t;
|
||||
FIELD_DP64_IDREG(isar, ID_AA64ISAR1, FRINTTS, 0);
|
||||
|
||||
u = cpu->isar.mvfr0;
|
||||
u = FIELD_DP32(u, MVFR0, SIMDREG, 0);
|
||||
@@ -2243,19 +2233,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
|
||||
unset_feature(env, ARM_FEATURE_THUMB_DSP);
|
||||
|
||||
u = cpu->isar.id_isar1;
|
||||
u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1);
|
||||
cpu->isar.id_isar1 = u;
|
||||
FIELD_DP32_IDREG(isar, ID_ISAR1, EXTEND, 1);
|
||||
|
||||
u = cpu->isar.id_isar2;
|
||||
u = GET_IDREG(isar, ID_ISAR2);
|
||||
u = FIELD_DP32(u, ID_ISAR2, MULTU, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR2, MULTS, 1);
|
||||
cpu->isar.id_isar2 = u;
|
||||
SET_IDREG(isar, ID_ISAR2, u);
|
||||
|
||||
u = cpu->isar.id_isar3;
|
||||
u = GET_IDREG(isar, ID_ISAR3);
|
||||
u = FIELD_DP32(u, ID_ISAR3, SIMD, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0);
|
||||
cpu->isar.id_isar3 = u;
|
||||
SET_IDREG(isar, ID_ISAR3, u);
|
||||
}
|
||||
|
||||
|
||||
@@ -2330,14 +2318,12 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
* Disable the security extension feature bits in the processor
|
||||
* feature registers as well.
|
||||
*/
|
||||
cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1, ID_PFR1, SECURITY, 0);
|
||||
cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPSDBG, 0);
|
||||
cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
|
||||
ID_AA64PFR0, EL3, 0);
|
||||
FIELD_DP32_IDREG(isar, ID_PFR1, SECURITY, 0);
|
||||
FIELD_DP32_IDREG(isar, ID_DFR0, COPSDBG, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL3, 0);
|
||||
|
||||
/* Disable the realm management extension, which requires EL3. */
|
||||
cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
|
||||
ID_AA64PFR0, RME, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR0, RME, 0);
|
||||
}
|
||||
|
||||
if (!cpu->has_el2) {
|
||||
@@ -2360,9 +2346,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
cpu);
|
||||
#endif
|
||||
} else {
|
||||
cpu->isar.id_aa64dfr0 =
|
||||
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
|
||||
cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64DFR0, PMUVER, 0);
|
||||
FIELD_DP32_IDREG(isar, ID_DFR0, PERFMON, 0);
|
||||
cpu->pmceid0 = 0;
|
||||
cpu->pmceid1 = 0;
|
||||
}
|
||||
@@ -2372,10 +2357,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
* Disable the hypervisor feature bits in the processor feature
|
||||
* registers if we don't have EL2.
|
||||
*/
|
||||
cpu->isar.id_aa64pfr0 = FIELD_DP64(cpu->isar.id_aa64pfr0,
|
||||
ID_AA64PFR0, EL2, 0);
|
||||
cpu->isar.id_pfr1 = FIELD_DP32(cpu->isar.id_pfr1,
|
||||
ID_PFR1, VIRTUALIZATION, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR0, EL2, 0);
|
||||
FIELD_DP32_IDREG(isar, ID_PFR1, VIRTUALIZATION, 0);
|
||||
}
|
||||
|
||||
if (cpu_isar_feature(aa64_mte, cpu)) {
|
||||
@@ -2394,8 +2377,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
* This matches Cortex-A710 BROADCASTMTE input being LOW.
|
||||
*/
|
||||
if (tcg_enabled() && cpu->tag_memory == NULL) {
|
||||
cpu->isar.id_aa64pfr1 =
|
||||
FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 1);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR1, MTE, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2403,7 +2385,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
* enabled on the guest (i.e mte=off), clear guest's MTE bits."
|
||||
*/
|
||||
if (kvm_enabled() && !cpu->kvm_mte) {
|
||||
FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR1, MTE, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -2423,32 +2405,22 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
* try to access the non-existent system registers for them.
|
||||
*/
|
||||
/* FEAT_SPE (Statistical Profiling Extension) */
|
||||
cpu->isar.id_aa64dfr0 =
|
||||
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMSVER, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64DFR0, PMSVER, 0);
|
||||
/* FEAT_TRBE (Trace Buffer Extension) */
|
||||
cpu->isar.id_aa64dfr0 =
|
||||
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEBUFFER, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEBUFFER, 0);
|
||||
/* FEAT_TRF (Self-hosted Trace Extension) */
|
||||
cpu->isar.id_aa64dfr0 =
|
||||
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEFILT, 0);
|
||||
cpu->isar.id_dfr0 =
|
||||
FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, TRACEFILT, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEFILT, 0);
|
||||
FIELD_DP32_IDREG(isar, ID_DFR0, TRACEFILT, 0);
|
||||
/* Trace Macrocell system register access */
|
||||
cpu->isar.id_aa64dfr0 =
|
||||
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEVER, 0);
|
||||
cpu->isar.id_dfr0 =
|
||||
FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, COPTRC, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64DFR0, TRACEVER, 0);
|
||||
FIELD_DP32_IDREG(isar, ID_DFR0, COPTRC, 0);
|
||||
/* Memory mapped trace */
|
||||
cpu->isar.id_dfr0 =
|
||||
FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, MMAPTRC, 0);
|
||||
FIELD_DP32_IDREG(isar, ID_DFR0, MMAPTRC, 0);
|
||||
/* FEAT_AMU (Activity Monitors Extension) */
|
||||
cpu->isar.id_aa64pfr0 =
|
||||
FIELD_DP64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, AMU, 0);
|
||||
cpu->isar.id_pfr0 =
|
||||
FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, AMU, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR0, AMU, 0);
|
||||
FIELD_DP32_IDREG(isar, ID_PFR0, AMU, 0);
|
||||
/* FEAT_MPAM (Memory Partitioning and Monitoring Extension) */
|
||||
cpu->isar.id_aa64pfr0 =
|
||||
FIELD_DP64(cpu->isar.id_aa64pfr0, ID_AA64PFR0, MPAM, 0);
|
||||
FIELD_DP64_IDREG(isar, ID_AA64PFR0, MPAM, 0);
|
||||
}
|
||||
|
||||
/* MPU can be configured out of a PMSA CPU either by setting has-mpu
|
||||
|
||||
+49
-33
@@ -32,6 +32,7 @@
|
||||
#include "qapi/qapi-types-common.h"
|
||||
#include "target/arm/multiprocessing.h"
|
||||
#include "target/arm/gtimer.h"
|
||||
#include "target/arm/cpu-sysregs.h"
|
||||
|
||||
#define EXCP_UDEF 1 /* undefined instruction */
|
||||
#define EXCP_SWI 2 /* software interrupt */
|
||||
@@ -834,6 +835,53 @@ typedef struct {
|
||||
uint32_t map, init, supported;
|
||||
} ARMVQMap;
|
||||
|
||||
/* REG is ID_XXX */
|
||||
#define FIELD_DP64_IDREG(ISAR, REG, FIELD, VALUE) \
|
||||
({ \
|
||||
ARMISARegisters *i_ = (ISAR); \
|
||||
uint64_t regval = i_->idregs[REG ## _EL1_IDX]; \
|
||||
regval = FIELD_DP64(regval, REG, FIELD, VALUE); \
|
||||
i_->idregs[REG ## _EL1_IDX] = regval; \
|
||||
})
|
||||
|
||||
#define FIELD_DP32_IDREG(ISAR, REG, FIELD, VALUE) \
|
||||
({ \
|
||||
ARMISARegisters *i_ = (ISAR); \
|
||||
uint64_t regval = i_->idregs[REG ## _EL1_IDX]; \
|
||||
regval = FIELD_DP32(regval, REG, FIELD, VALUE); \
|
||||
i_->idregs[REG ## _EL1_IDX] = regval; \
|
||||
})
|
||||
|
||||
#define FIELD_EX64_IDREG(ISAR, REG, FIELD) \
|
||||
({ \
|
||||
const ARMISARegisters *i_ = (ISAR); \
|
||||
FIELD_EX64(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \
|
||||
})
|
||||
|
||||
#define FIELD_EX32_IDREG(ISAR, REG, FIELD) \
|
||||
({ \
|
||||
const ARMISARegisters *i_ = (ISAR); \
|
||||
FIELD_EX32(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \
|
||||
})
|
||||
|
||||
#define FIELD_SEX64_IDREG(ISAR, REG, FIELD) \
|
||||
({ \
|
||||
const ARMISARegisters *i_ = (ISAR); \
|
||||
FIELD_SEX64(i_->idregs[REG ## _EL1_IDX], REG, FIELD); \
|
||||
})
|
||||
|
||||
#define SET_IDREG(ISAR, REG, VALUE) \
|
||||
({ \
|
||||
ARMISARegisters *i_ = (ISAR); \
|
||||
i_->idregs[REG ## _EL1_IDX] = VALUE; \
|
||||
})
|
||||
|
||||
#define GET_IDREG(ISAR, REG) \
|
||||
({ \
|
||||
const ARMISARegisters *i_ = (ISAR); \
|
||||
i_->idregs[REG ## _EL1_IDX]; \
|
||||
})
|
||||
|
||||
/**
|
||||
* ARMCPU:
|
||||
* @env: #CPUARMState
|
||||
@@ -1002,44 +1050,14 @@ struct ArchCPU {
|
||||
* field by reading the value from the KVM vCPU.
|
||||
*/
|
||||
struct ARMISARegisters {
|
||||
uint32_t id_isar0;
|
||||
uint32_t id_isar1;
|
||||
uint32_t id_isar2;
|
||||
uint32_t id_isar3;
|
||||
uint32_t id_isar4;
|
||||
uint32_t id_isar5;
|
||||
uint32_t id_isar6;
|
||||
uint32_t id_mmfr0;
|
||||
uint32_t id_mmfr1;
|
||||
uint32_t id_mmfr2;
|
||||
uint32_t id_mmfr3;
|
||||
uint32_t id_mmfr4;
|
||||
uint32_t id_mmfr5;
|
||||
uint32_t id_pfr0;
|
||||
uint32_t id_pfr1;
|
||||
uint32_t id_pfr2;
|
||||
uint32_t mvfr0;
|
||||
uint32_t mvfr1;
|
||||
uint32_t mvfr2;
|
||||
uint32_t id_dfr0;
|
||||
uint32_t id_dfr1;
|
||||
uint32_t dbgdidr;
|
||||
uint32_t dbgdevid;
|
||||
uint32_t dbgdevid1;
|
||||
uint64_t id_aa64isar0;
|
||||
uint64_t id_aa64isar1;
|
||||
uint64_t id_aa64isar2;
|
||||
uint64_t id_aa64pfr0;
|
||||
uint64_t id_aa64pfr1;
|
||||
uint64_t id_aa64mmfr0;
|
||||
uint64_t id_aa64mmfr1;
|
||||
uint64_t id_aa64mmfr2;
|
||||
uint64_t id_aa64mmfr3;
|
||||
uint64_t id_aa64dfr0;
|
||||
uint64_t id_aa64dfr1;
|
||||
uint64_t id_aa64zfr0;
|
||||
uint64_t id_aa64smfr0;
|
||||
uint64_t reset_pmcr_el0;
|
||||
uint64_t idregs[NUM_ID_IDX];
|
||||
} isar;
|
||||
uint64_t midr;
|
||||
uint32_t revidr;
|
||||
@@ -1150,8 +1168,6 @@ void arm_gt_sel2vtimer_cb(void *opaque);
|
||||
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
|
||||
void gt_rme_post_el_change(ARMCPU *cpu, void *opaque);
|
||||
|
||||
void arm_cpu_post_init(Object *obj);
|
||||
|
||||
#define ARM_AFF0_SHIFT 0
|
||||
#define ARM_AFF0_MASK (0xFFULL << ARM_AFF0_SHIFT)
|
||||
#define ARM_AFF1_SHIFT 8
|
||||
|
||||
+72
-56
@@ -36,6 +36,28 @@
|
||||
#include "cpu-features.h"
|
||||
#include "cpregs.h"
|
||||
|
||||
/* convert between <register>_IDX and SYS_<register> */
|
||||
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \
|
||||
[NAME##_IDX] = SYS_##NAME,
|
||||
|
||||
const uint32_t id_register_sysreg[NUM_ID_IDX] = {
|
||||
#include "cpu-sysregs.h.inc"
|
||||
};
|
||||
|
||||
#undef DEF
|
||||
#define DEF(NAME, OP0, OP1, CRN, CRM, OP2) \
|
||||
case SYS_##NAME: return NAME##_IDX;
|
||||
|
||||
int get_sysreg_idx(ARMSysRegs sysreg)
|
||||
{
|
||||
switch (sysreg) {
|
||||
#include "cpu-sysregs.h.inc"
|
||||
}
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
#undef DEF
|
||||
|
||||
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
|
||||
{
|
||||
/*
|
||||
@@ -114,7 +136,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
|
||||
* SVE is disabled and so are all vector lengths. Good.
|
||||
* Disable all SVE extensions as well.
|
||||
*/
|
||||
cpu->isar.id_aa64zfr0 = 0;
|
||||
SET_IDREG(&cpu->isar, ID_AA64ZFR0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -288,16 +310,13 @@ static bool cpu_arm_get_sve(Object *obj, Error **errp)
|
||||
static void cpu_arm_set_sve(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
uint64_t t;
|
||||
|
||||
if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
|
||||
error_setg(errp, "'sve' feature not supported by KVM on this host");
|
||||
return;
|
||||
}
|
||||
|
||||
t = cpu->isar.id_aa64pfr0;
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
|
||||
cpu->isar.id_aa64pfr0 = t;
|
||||
FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, SVE, value);
|
||||
}
|
||||
|
||||
void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp)
|
||||
@@ -309,7 +328,7 @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp)
|
||||
|
||||
if (vq_map == 0) {
|
||||
if (!cpu_isar_feature(aa64_sme, cpu)) {
|
||||
cpu->isar.id_aa64smfr0 = 0;
|
||||
SET_IDREG(&cpu->isar, ID_AA64SMFR0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -348,11 +367,8 @@ static bool cpu_arm_get_sme(Object *obj, Error **errp)
|
||||
static void cpu_arm_set_sme(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
uint64_t t;
|
||||
|
||||
t = cpu->isar.id_aa64pfr1;
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, SME, value);
|
||||
cpu->isar.id_aa64pfr1 = t;
|
||||
FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR1, SME, value);
|
||||
}
|
||||
|
||||
static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp)
|
||||
@@ -365,11 +381,8 @@ static bool cpu_arm_get_sme_fa64(Object *obj, Error **errp)
|
||||
static void cpu_arm_set_sme_fa64(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
uint64_t t;
|
||||
|
||||
t = cpu->isar.id_aa64smfr0;
|
||||
t = FIELD_DP64(t, ID_AA64SMFR0, FA64, value);
|
||||
cpu->isar.id_aa64smfr0 = t;
|
||||
FIELD_DP64_IDREG(&cpu->isar, ID_AA64SMFR0, FA64, value);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
@@ -480,6 +493,7 @@ void aarch64_add_sme_properties(Object *obj)
|
||||
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
|
||||
{
|
||||
ARMPauthFeature features = cpu_isar_feature(pauth_feature, cpu);
|
||||
ARMISARegisters *isar = &cpu->isar;
|
||||
uint64_t isar1, isar2;
|
||||
|
||||
/*
|
||||
@@ -490,13 +504,13 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
|
||||
*
|
||||
* Begin by disabling all fields.
|
||||
*/
|
||||
isar1 = cpu->isar.id_aa64isar1;
|
||||
isar1 = GET_IDREG(isar, ID_AA64ISAR1);
|
||||
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, APA, 0);
|
||||
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPA, 0);
|
||||
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, API, 0);
|
||||
isar1 = FIELD_DP64(isar1, ID_AA64ISAR1, GPI, 0);
|
||||
|
||||
isar2 = cpu->isar.id_aa64isar2;
|
||||
isar2 = GET_IDREG(isar, ID_AA64ISAR2);
|
||||
isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, APA3, 0);
|
||||
isar2 = FIELD_DP64(isar2, ID_AA64ISAR2, GPA3, 0);
|
||||
|
||||
@@ -558,8 +572,8 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
cpu->isar.id_aa64isar1 = isar1;
|
||||
cpu->isar.id_aa64isar2 = isar2;
|
||||
SET_IDREG(isar, ID_AA64ISAR1, isar1);
|
||||
SET_IDREG(isar, ID_AA64ISAR2, isar2);
|
||||
}
|
||||
|
||||
static const Property arm_cpu_pauth_property =
|
||||
@@ -606,17 +620,18 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
t = cpu->isar.id_aa64mmfr0;
|
||||
t = GET_IDREG(&cpu->isar, ID_AA64MMFR0);
|
||||
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2); /* 16k pages w/ LPA2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1); /* 4k pages w/ LPA2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3); /* 4k stage2 w/ LPA2 */
|
||||
cpu->isar.id_aa64mmfr0 = t;
|
||||
SET_IDREG(&cpu->isar, ID_AA64MMFR0, t);
|
||||
}
|
||||
|
||||
static void aarch64_a57_initfn(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
ARMISARegisters *isar = &cpu->isar;
|
||||
|
||||
cpu->dtb_compatible = "arm,cortex-a57";
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
@@ -637,25 +652,25 @@ static void aarch64_a57_initfn(Object *obj)
|
||||
cpu->isar.mvfr2 = 0x00000043;
|
||||
cpu->ctr = 0x8444c004;
|
||||
cpu->reset_sctlr = 0x00c50838;
|
||||
cpu->isar.id_pfr0 = 0x00000131;
|
||||
cpu->isar.id_pfr1 = 0x00011011;
|
||||
cpu->isar.id_dfr0 = 0x03010066;
|
||||
SET_IDREG(isar, ID_PFR0, 0x00000131);
|
||||
SET_IDREG(isar, ID_PFR1, 0x00011011);
|
||||
SET_IDREG(isar, ID_DFR0, 0x03010066);
|
||||
cpu->id_afr0 = 0x00000000;
|
||||
cpu->isar.id_mmfr0 = 0x10101105;
|
||||
cpu->isar.id_mmfr1 = 0x40000000;
|
||||
cpu->isar.id_mmfr2 = 0x01260000;
|
||||
cpu->isar.id_mmfr3 = 0x02102211;
|
||||
cpu->isar.id_isar0 = 0x02101110;
|
||||
cpu->isar.id_isar1 = 0x13112111;
|
||||
cpu->isar.id_isar2 = 0x21232042;
|
||||
cpu->isar.id_isar3 = 0x01112131;
|
||||
cpu->isar.id_isar4 = 0x00011142;
|
||||
cpu->isar.id_isar5 = 0x00011121;
|
||||
cpu->isar.id_isar6 = 0;
|
||||
cpu->isar.id_aa64pfr0 = 0x00002222;
|
||||
cpu->isar.id_aa64dfr0 = 0x10305106;
|
||||
cpu->isar.id_aa64isar0 = 0x00011120;
|
||||
cpu->isar.id_aa64mmfr0 = 0x00001124;
|
||||
SET_IDREG(isar, ID_MMFR0, 0x10101105);
|
||||
SET_IDREG(isar, ID_MMFR1, 0x40000000);
|
||||
SET_IDREG(isar, ID_MMFR2, 0x01260000);
|
||||
SET_IDREG(isar, ID_MMFR3, 0x02102211);
|
||||
SET_IDREG(isar, ID_ISAR0, 0x02101110);
|
||||
SET_IDREG(isar, ID_ISAR1, 0x13112111);
|
||||
SET_IDREG(isar, ID_ISAR2, 0x21232042);
|
||||
SET_IDREG(isar, ID_ISAR3, 0x01112131);
|
||||
SET_IDREG(isar, ID_ISAR4, 0x00011142);
|
||||
SET_IDREG(isar, ID_ISAR5, 0x00011121);
|
||||
SET_IDREG(isar, ID_ISAR6, 0);
|
||||
SET_IDREG(isar, ID_AA64PFR0, 0x00002222);
|
||||
SET_IDREG(isar, ID_AA64DFR0, 0x10305106);
|
||||
SET_IDREG(isar, ID_AA64ISAR0, 0x00011120);
|
||||
SET_IDREG(isar, ID_AA64MMFR0, 0x00001124);
|
||||
cpu->isar.dbgdidr = 0x3516d000;
|
||||
cpu->isar.dbgdevid = 0x01110f13;
|
||||
cpu->isar.dbgdevid1 = 0x2;
|
||||
@@ -678,6 +693,7 @@ static void aarch64_a57_initfn(Object *obj)
|
||||
static void aarch64_a53_initfn(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
ARMISARegisters *isar = &cpu->isar;
|
||||
|
||||
cpu->dtb_compatible = "arm,cortex-a53";
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
@@ -698,25 +714,25 @@ static void aarch64_a53_initfn(Object *obj)
|
||||
cpu->isar.mvfr2 = 0x00000043;
|
||||
cpu->ctr = 0x84448004; /* L1Ip = VIPT */
|
||||
cpu->reset_sctlr = 0x00c50838;
|
||||
cpu->isar.id_pfr0 = 0x00000131;
|
||||
cpu->isar.id_pfr1 = 0x00011011;
|
||||
cpu->isar.id_dfr0 = 0x03010066;
|
||||
SET_IDREG(isar, ID_PFR0, 0x00000131);
|
||||
SET_IDREG(isar, ID_PFR1, 0x00011011);
|
||||
SET_IDREG(isar, ID_DFR0, 0x03010066);
|
||||
cpu->id_afr0 = 0x00000000;
|
||||
cpu->isar.id_mmfr0 = 0x10101105;
|
||||
cpu->isar.id_mmfr1 = 0x40000000;
|
||||
cpu->isar.id_mmfr2 = 0x01260000;
|
||||
cpu->isar.id_mmfr3 = 0x02102211;
|
||||
cpu->isar.id_isar0 = 0x02101110;
|
||||
cpu->isar.id_isar1 = 0x13112111;
|
||||
cpu->isar.id_isar2 = 0x21232042;
|
||||
cpu->isar.id_isar3 = 0x01112131;
|
||||
cpu->isar.id_isar4 = 0x00011142;
|
||||
cpu->isar.id_isar5 = 0x00011121;
|
||||
cpu->isar.id_isar6 = 0;
|
||||
cpu->isar.id_aa64pfr0 = 0x00002222;
|
||||
cpu->isar.id_aa64dfr0 = 0x10305106;
|
||||
cpu->isar.id_aa64isar0 = 0x00011120;
|
||||
cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
|
||||
SET_IDREG(isar, ID_MMFR0, 0x10101105);
|
||||
SET_IDREG(isar, ID_MMFR1, 0x40000000);
|
||||
SET_IDREG(isar, ID_MMFR2, 0x01260000);
|
||||
SET_IDREG(isar, ID_MMFR3, 0x02102211);
|
||||
SET_IDREG(isar, ID_ISAR0, 0x02101110);
|
||||
SET_IDREG(isar, ID_ISAR1, 0x13112111);
|
||||
SET_IDREG(isar, ID_ISAR2, 0x21232042);
|
||||
SET_IDREG(isar, ID_ISAR3, 0x01112131);
|
||||
SET_IDREG(isar, ID_ISAR4, 0x00011142);
|
||||
SET_IDREG(isar, ID_ISAR5, 0x00011121);
|
||||
SET_IDREG(isar, ID_ISAR6, 0);
|
||||
SET_IDREG(isar, ID_AA64PFR0, 0x00002222);
|
||||
SET_IDREG(isar, ID_AA64DFR0, 0x10305106);
|
||||
SET_IDREG(isar, ID_AA64ISAR0, 0x00011120);
|
||||
SET_IDREG(isar, ID_AA64MMFR0, 0x00001122); /* 40 bit physical addr */
|
||||
cpu->isar.dbgdidr = 0x3516d000;
|
||||
cpu->isar.dbgdevid = 0x00110f13;
|
||||
cpu->isar.dbgdevid1 = 0x1;
|
||||
|
||||
+35
-33
@@ -6932,7 +6932,7 @@ static void define_pmu_regs(ARMCPU *cpu)
|
||||
static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
uint64_t pfr1 = cpu->isar.id_pfr1;
|
||||
uint64_t pfr1 = GET_IDREG(&cpu->isar, ID_PFR1);
|
||||
|
||||
if (env->gicv3state) {
|
||||
pfr1 |= 1 << 28;
|
||||
@@ -6943,7 +6943,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
uint64_t pfr0 = cpu->isar.id_aa64pfr0;
|
||||
uint64_t pfr0 = GET_IDREG(&cpu->isar, ID_AA64PFR0);
|
||||
|
||||
if (env->gicv3state) {
|
||||
pfr0 |= 1 << 24;
|
||||
@@ -7750,6 +7750,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
{
|
||||
/* Register all the coprocessor registers based on feature bits */
|
||||
CPUARMState *env = &cpu->env;
|
||||
ARMISARegisters *isar = &cpu->isar;
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
/* M profile has no coprocessor registers */
|
||||
return;
|
||||
@@ -7775,7 +7777,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_pfr0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_PFR0)},
|
||||
/*
|
||||
* ID_PFR1 is not a plain ARM_CP_CONST because we don't know
|
||||
* the value of the GIC field until after we define these regs.
|
||||
@@ -7786,7 +7788,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.accessfn = access_aa32_tid3,
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
.type = ARM_CP_CONST,
|
||||
.resetvalue = cpu->isar.id_pfr1,
|
||||
.resetvalue = GET_IDREG(isar, ID_PFR1),
|
||||
#else
|
||||
.type = ARM_CP_NO_RAW,
|
||||
.accessfn = access_aa32_tid3,
|
||||
@@ -7798,7 +7800,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_dfr0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_DFR0)},
|
||||
{ .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@@ -7808,62 +7810,62 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_mmfr0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_MMFR0)},
|
||||
{ .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_mmfr1 },
|
||||
.resetvalue = GET_IDREG(isar, ID_MMFR1)},
|
||||
{ .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_mmfr2 },
|
||||
.resetvalue = GET_IDREG(isar, ID_MMFR2)},
|
||||
{ .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_mmfr3 },
|
||||
.resetvalue = GET_IDREG(isar, ID_MMFR3)},
|
||||
{ .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_isar0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_ISAR0)},
|
||||
{ .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_isar1 },
|
||||
.resetvalue = GET_IDREG(isar, ID_ISAR1)},
|
||||
{ .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_isar2 },
|
||||
.resetvalue = GET_IDREG(isar, ID_ISAR2)},
|
||||
{ .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_isar3 },
|
||||
.resetvalue = GET_IDREG(isar, ID_ISAR3) },
|
||||
{ .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_isar4 },
|
||||
.resetvalue = GET_IDREG(isar, ID_ISAR4) },
|
||||
{ .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_isar5 },
|
||||
.resetvalue = GET_IDREG(isar, ID_ISAR5) },
|
||||
{ .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_mmfr4 },
|
||||
.resetvalue = GET_IDREG(isar, ID_MMFR4)},
|
||||
{ .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa32_tid3,
|
||||
.resetvalue = cpu->isar.id_isar6 },
|
||||
.resetvalue = GET_IDREG(isar, ID_ISAR6) },
|
||||
};
|
||||
define_arm_cp_regs(cpu, v6_idregs);
|
||||
define_arm_cp_regs(cpu, v6_cp_reginfo);
|
||||
@@ -7914,7 +7916,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.access = PL1_R,
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
.type = ARM_CP_CONST,
|
||||
.resetvalue = cpu->isar.id_aa64pfr0
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64PFR0)
|
||||
#else
|
||||
.type = ARM_CP_NO_RAW,
|
||||
.accessfn = access_aa64_tid3,
|
||||
@@ -7926,7 +7928,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64pfr1},
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64PFR1)},
|
||||
{ .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@@ -7941,12 +7943,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64zfr0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64ZFR0)},
|
||||
{ .name = "ID_AA64SMFR0_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64smfr0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64SMFR0)},
|
||||
{ .name = "ID_AA64PFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 6,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@@ -7961,12 +7963,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64dfr0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64DFR0) },
|
||||
{ .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64dfr1 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64DFR1) },
|
||||
{ .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@@ -8001,17 +8003,17 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64isar0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64ISAR0)},
|
||||
{ .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64isar1 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64ISAR1)},
|
||||
{ .name = "ID_AA64ISAR2_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64isar2 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64ISAR2)},
|
||||
{ .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@@ -8041,22 +8043,22 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64mmfr0 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64MMFR0)},
|
||||
{ .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64mmfr1 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64MMFR1) },
|
||||
{ .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64mmfr2 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64MMFR2) },
|
||||
{ .name = "ID_AA64MMFR3_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_aa64mmfr3 },
|
||||
.resetvalue = GET_IDREG(isar, ID_AA64MMFR3) },
|
||||
{ .name = "ID_AA64MMFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 4,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@@ -8128,17 +8130,17 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_pfr2 },
|
||||
.resetvalue = GET_IDREG(isar, ID_PFR2)},
|
||||
{ .name = "ID_DFR1", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_dfr1 },
|
||||
.resetvalue = GET_IDREG(isar, ID_DFR1)},
|
||||
{ .name = "ID_MMFR5", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
.resetvalue = cpu->isar.id_mmfr5 },
|
||||
.resetvalue = GET_IDREG(isar, ID_MMFR5)},
|
||||
{ .name = "RES_0_C0_C3_7", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 7,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
|
||||
+43
-29
@@ -19,6 +19,7 @@
|
||||
#include "system/hw_accel.h"
|
||||
#include "hvf_arm.h"
|
||||
#include "cpregs.h"
|
||||
#include "cpu-sysregs.h"
|
||||
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
@@ -845,14 +846,17 @@ static uint64_t hvf_get_reg(CPUState *cpu, int rt)
|
||||
return val;
|
||||
}
|
||||
|
||||
static void clamp_id_aa64mmfr0_parange_to_ipa_size(uint64_t *id_aa64mmfr0)
|
||||
static void clamp_id_aa64mmfr0_parange_to_ipa_size(ARMISARegisters *isar)
|
||||
{
|
||||
uint32_t ipa_size = chosen_ipa_bit_size ?
|
||||
chosen_ipa_bit_size : hvf_arm_get_max_ipa_bit_size();
|
||||
uint64_t id_aa64mmfr0;
|
||||
|
||||
/* Clamp down the PARange to the IPA size the kernel supports. */
|
||||
uint8_t index = round_down_to_parange_index(ipa_size);
|
||||
*id_aa64mmfr0 = (*id_aa64mmfr0 & ~R_ID_AA64MMFR0_PARANGE_MASK) | index;
|
||||
id_aa64mmfr0 = GET_IDREG(isar, ID_AA64MMFR0);
|
||||
id_aa64mmfr0 = (id_aa64mmfr0 & ~R_ID_AA64MMFR0_PARANGE_MASK) | index;
|
||||
SET_IDREG(isar, ID_AA64MMFR0, id_aa64mmfr0);
|
||||
}
|
||||
|
||||
static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
||||
@@ -862,16 +866,16 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
||||
int reg;
|
||||
uint64_t *val;
|
||||
} regs[] = {
|
||||
{ HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 },
|
||||
{ HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 },
|
||||
{ HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 },
|
||||
{ HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 },
|
||||
{ HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 },
|
||||
{ HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 },
|
||||
{ HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.idregs[ID_AA64PFR0_EL1_IDX] },
|
||||
{ HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.idregs[ID_AA64PFR1_EL1_IDX] },
|
||||
{ HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.idregs[ID_AA64DFR0_EL1_IDX] },
|
||||
{ HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.idregs[ID_AA64DFR1_EL1_IDX] },
|
||||
{ HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.idregs[ID_AA64ISAR0_EL1_IDX] },
|
||||
{ HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.idregs[ID_AA64ISAR1_EL1_IDX] },
|
||||
/* Add ID_AA64ISAR2_EL1 here when HVF supports it */
|
||||
{ HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 },
|
||||
{ HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 },
|
||||
{ HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 },
|
||||
{ HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.idregs[ID_AA64MMFR0_EL1_IDX] },
|
||||
{ HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.idregs[ID_AA64MMFR1_EL1_IDX] },
|
||||
{ HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.idregs[ID_AA64MMFR2_EL1_IDX] },
|
||||
/* Add ID_AA64MMFR3_EL1 here when HVF supports it */
|
||||
};
|
||||
hv_vcpu_t fd;
|
||||
@@ -879,7 +883,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
||||
hv_vcpu_exit_t *exit;
|
||||
int i;
|
||||
|
||||
ahcf->dtb_compatible = "arm,arm-v8";
|
||||
ahcf->dtb_compatible = "arm,armv8";
|
||||
ahcf->features = (1ULL << ARM_FEATURE_V8) |
|
||||
(1ULL << ARM_FEATURE_NEON) |
|
||||
(1ULL << ARM_FEATURE_AARCH64) |
|
||||
@@ -898,7 +902,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
||||
r |= hv_vcpu_get_sys_reg(fd, HV_SYS_REG_MIDR_EL1, &ahcf->midr);
|
||||
r |= hv_vcpu_destroy(fd);
|
||||
|
||||
clamp_id_aa64mmfr0_parange_to_ipa_size(&host_isar.id_aa64mmfr0);
|
||||
clamp_id_aa64mmfr0_parange_to_ipa_size(&host_isar);
|
||||
|
||||
/*
|
||||
* Disable SME, which is not properly handled by QEMU hvf yet.
|
||||
@@ -910,7 +914,8 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
||||
* - fix any assumptions we made that SME implies SVE (since
|
||||
* on the M4 there is SME but not SVE)
|
||||
*/
|
||||
host_isar.id_aa64pfr1 &= ~R_ID_AA64PFR1_SME_MASK;
|
||||
SET_IDREG(&host_isar, ID_AA64PFR1,
|
||||
GET_IDREG(&host_isar, ID_AA64PFR1) & ~R_ID_AA64PFR1_SME_MASK);
|
||||
|
||||
ahcf->isar = host_isar;
|
||||
|
||||
@@ -927,7 +932,7 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
||||
ahcf->reset_sctlr |= 0x00800000;
|
||||
|
||||
/* Make sure we don't advertise AArch32 support for EL0/EL1 */
|
||||
if ((host_isar.id_aa64pfr0 & 0xff) != 0x11) {
|
||||
if ((GET_IDREG(&host_isar, ID_AA64PFR0) & 0xff) != 0x11) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1065,12 +1070,12 @@ int hvf_arch_init_vcpu(CPUState *cpu)
|
||||
|
||||
/* We're limited to underlying hardware caps, override internal versions */
|
||||
ret = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_ID_AA64MMFR0_EL1,
|
||||
&arm_cpu->isar.id_aa64mmfr0);
|
||||
&arm_cpu->isar.idregs[ID_AA64MMFR0_EL1_IDX]);
|
||||
assert_hvf_ok(ret);
|
||||
|
||||
clamp_id_aa64mmfr0_parange_to_ipa_size(&arm_cpu->isar.id_aa64mmfr0);
|
||||
clamp_id_aa64mmfr0_parange_to_ipa_size(&arm_cpu->isar);
|
||||
ret = hv_vcpu_set_sys_reg(cpu->accel->fd, HV_SYS_REG_ID_AA64MMFR0_EL1,
|
||||
arm_cpu->isar.id_aa64mmfr0);
|
||||
arm_cpu->isar.idregs[ID_AA64MMFR0_EL1_IDX]);
|
||||
assert_hvf_ok(ret);
|
||||
|
||||
return 0;
|
||||
@@ -1083,13 +1088,13 @@ void hvf_kick_vcpu_thread(CPUState *cpu)
|
||||
}
|
||||
|
||||
static void hvf_raise_exception(CPUState *cpu, uint32_t excp,
|
||||
uint32_t syndrome)
|
||||
uint32_t syndrome, int target_el)
|
||||
{
|
||||
ARMCPU *arm_cpu = ARM_CPU(cpu);
|
||||
CPUARMState *env = &arm_cpu->env;
|
||||
|
||||
cpu->exception_index = excp;
|
||||
env->exception.target_el = 1;
|
||||
env->exception.target_el = target_el;
|
||||
env->exception.syndrome = syndrome;
|
||||
|
||||
arm_cpu_do_interrupt(cpu);
|
||||
@@ -1449,7 +1454,7 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint64_t *val)
|
||||
SYSREG_CRN(reg),
|
||||
SYSREG_CRM(reg),
|
||||
SYSREG_OP2(reg));
|
||||
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
|
||||
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized(), 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1759,7 +1764,7 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
|
||||
SYSREG_CRN(reg),
|
||||
SYSREG_CRM(reg),
|
||||
SYSREG_OP2(reg));
|
||||
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
|
||||
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized(), 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1910,7 +1915,17 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||
flush_cpu_state(cpu);
|
||||
|
||||
bql_unlock();
|
||||
assert_hvf_ok(hv_vcpu_run(cpu->accel->fd));
|
||||
r = hv_vcpu_run(cpu->accel->fd);
|
||||
bql_lock();
|
||||
switch (r) {
|
||||
case HV_SUCCESS:
|
||||
break;
|
||||
case HV_ILLEGAL_GUEST_STATE:
|
||||
trace_hvf_illegal_guest_state();
|
||||
/* fall through */
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
/* handle VMEXIT */
|
||||
uint64_t exit_reason = hvf_exit->reason;
|
||||
@@ -1918,7 +1933,6 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||
uint32_t ec = syn_get_ec(syndrome);
|
||||
|
||||
ret = 0;
|
||||
bql_lock();
|
||||
switch (exit_reason) {
|
||||
case HV_EXIT_REASON_EXCEPTION:
|
||||
/* This is the main one, handle below. */
|
||||
@@ -1953,7 +1967,7 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||
if (!hvf_find_sw_breakpoint(cpu, env->pc)) {
|
||||
/* Re-inject into the guest */
|
||||
ret = 0;
|
||||
hvf_raise_exception(cpu, EXCP_BKPT, syn_aa64_bkpt(0));
|
||||
hvf_raise_exception(cpu, EXCP_BKPT, syn_aa64_bkpt(0), 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2058,13 +2072,13 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||
cpu_synchronize_state(cpu);
|
||||
if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_HVC) {
|
||||
if (!hvf_handle_psci_call(cpu)) {
|
||||
trace_hvf_unknown_hvc(env->xregs[0]);
|
||||
trace_hvf_unknown_hvc(env->pc, env->xregs[0]);
|
||||
/* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */
|
||||
env->xregs[0] = -1;
|
||||
}
|
||||
} else {
|
||||
trace_hvf_unknown_hvc(env->xregs[0]);
|
||||
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
|
||||
trace_hvf_unknown_hvc(env->pc, env->xregs[0]);
|
||||
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized(), 1);
|
||||
}
|
||||
break;
|
||||
case EC_AA64_SMC:
|
||||
@@ -2079,7 +2093,7 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||
}
|
||||
} else {
|
||||
trace_hvf_unknown_smc(env->xregs[0]);
|
||||
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
|
||||
hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized(), 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user