mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-target-arm-20220509' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue: * MAINTAINERS/.mailmap: update email for Leif Lindholm * hw/arm: add version information to sbsa-ref machine DT * Enable new features for -cpu max: FEAT_Debugv8p2, FEAT_Debugv8p4, FEAT_RAS (minimal version only), FEAT_IESB, FEAT_CSV2, FEAT_CSV2_2, FEAT_CSV3, FEAT_DGH * Emulate Cortex-A76 * Emulate Neoverse-N1 * Fix the virt board default NUMA topology # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmJ5AbsZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3vyFEACZZ6tRVJYB6YpIzI7rho9x # hVQIMTc4D5lmVetJnbLdLazifIy60oIOtSKV3Y3oj5DLMcsf6NITrPaFPWNRX3Nm # mcbTCT5FGj8i7b1CkpEylLwvRQbIaoz2GnJPckdYelxxAq1uJNog3fmoG8nVtJ1F # HfXVCVkZGQyiyr6Y2/zn3vpdp9n6/4RymN8ugizkcgIRII87DKV+DNDalw613JG4 # 5xxBOGkYzo5DZM8TgL8Ylmb5Jy9XY0EN1xpkyHFOg6gi0B3UZTxHq5SvK6NFoZLJ # ogyhmMh6IjEfhUIDCtWG9VCoPyWpOXAFoh7D7akFVB4g2SIvBvcuGzFxCAsh5q3K # s+9CgNX1SZpJQkT1jLjQlNzoUhh8lNc7QvhPWVrbAj3scc+1xVnS5MJsokEV21Cx # /bp3mFwCL+Q4gjsMKx1nKSvxLv8xlxRtIilmlfj+wvpkenIfIwHYjbvItJTlAy1L # +arx8fqImNQorxO6oMjOuAlSbNnDKup5qvwGghyu/qz/YEnGQVzN6gI324Km081L # 1u31H/B3C2rj3qMsYMp5yOqgprXi1D5c6wfYIpLD/C4UfHgIlRiprawZPDM7fAhX # vxhUhhj3e9OgkbC9yqd6SUR2Uk3YaQlp319LyoZa3VKSvjBTciFsMXXnIV1UitYp # BGtz8+FypPVkYH7zQB9c7Q== # =ey1m # -----END PGP SIGNATURE----- # gpg: Signature made Mon 09 May 2022 04:57:47 AM PDT # 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] * tag 'pull-target-arm-20220509' of https://git.linaro.org/people/pmaydell/qemu-arm: (32 commits) hw/acpi/aml-build: Use existing CPU topology to build PPTT table hw/arm/virt: Fix CPU's default NUMA node ID qtest/numa-test: Correct CPU and NUMA association in aarch64_numa_cpu() hw/arm/virt: Consider SMP configuration in CPU topology qtest/numa-test: Specify CPU topology in aarch64_numa_cpu() qapi/machine.json: Add cluster-id hw/arm: add versioning to sbsa-ref machine DT target/arm: Define neoverse-n1 target/arm: Define cortex-a76 target/arm: Enable FEAT_DGH for -cpu max target/arm: Enable FEAT_CSV3 for -cpu max target/arm: Enable FEAT_CSV2_2 for -cpu max target/arm: Enable FEAT_CSV2 for -cpu max target/arm: Enable FEAT_IESB for -cpu max target/arm: Enable FEAT_RAS for -cpu max target/arm: Implement ESB instruction target/arm: Implement virtual SError exceptions target/arm: Enable SCR and HCR bits for RAS target/arm: Add minimal RAS registers target/arm: Enable FEAT_Debugv8p4 for -cpu max ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -62,7 +62,8 @@ Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
|
||||
Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
|
||||
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
|
||||
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
|
||||
Leif Lindholm <leif@nuviainc.com> <leif.lindholm@linaro.org>
|
||||
Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
|
||||
Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
|
||||
Radoslaw Biernacki <rad@semihalf.com> <radoslaw.biernacki@linaro.org>
|
||||
Paul Burton <paulburton@kernel.org> <paul.burton@mips.com>
|
||||
Paul Burton <paulburton@kernel.org> <paul.burton@imgtec.com>
|
||||
|
||||
+1
-1
@@ -886,7 +886,7 @@ F: include/hw/ssi/imx_spi.h
|
||||
SBSA-REF
|
||||
M: Radoslaw Biernacki <rad@semihalf.com>
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
R: Leif Lindholm <leif@nuviainc.com>
|
||||
R: Leif Lindholm <quic_llindhol@quicinc.com>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/sbsa-ref.c
|
||||
|
||||
@@ -12,8 +12,16 @@ the following architecture extensions:
|
||||
- FEAT_BBM at level 2 (Translation table break-before-make levels)
|
||||
- FEAT_BF16 (AArch64 BFloat16 instructions)
|
||||
- FEAT_BTI (Branch Target Identification)
|
||||
- FEAT_CSV2 (Cache speculation variant 2)
|
||||
- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
|
||||
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
|
||||
- FEAT_CSV2_2 (Cache speculation variant 2, version 2)
|
||||
- FEAT_CSV3 (Cache speculation variant 3)
|
||||
- FEAT_DGH (Data gathering hint)
|
||||
- FEAT_DIT (Data Independent Timing instructions)
|
||||
- FEAT_DPB (DC CVAP instruction)
|
||||
- FEAT_Debugv8p2 (Debug changes for v8.2)
|
||||
- FEAT_Debugv8p4 (Debug changes for v8.4)
|
||||
- FEAT_DotProd (Advanced SIMD dot product instructions)
|
||||
- FEAT_FCMA (Floating-point complex number instructions)
|
||||
- FEAT_FHM (Floating-point half-precision multiplication instructions)
|
||||
@@ -23,6 +31,7 @@ the following architecture extensions:
|
||||
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
|
||||
- FEAT_HPDS (Hierarchical permission disables)
|
||||
- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
|
||||
- FEAT_IESB (Implicit error synchronization event)
|
||||
- FEAT_JSCVT (JavaScript conversion instructions)
|
||||
- FEAT_LOR (Limited ordering regions)
|
||||
- FEAT_LPA (Large Physical Address space)
|
||||
@@ -40,6 +49,7 @@ the following architecture extensions:
|
||||
- FEAT_PMULL (PMULL, PMULL2 instructions)
|
||||
- FEAT_PMUv3p1 (PMU Extensions v3.1)
|
||||
- FEAT_PMUv3p4 (PMU Extensions v3.4)
|
||||
- FEAT_RAS (Reliability, availability, and serviceability)
|
||||
- FEAT_RDM (Advanced SIMD rounding double multiply accumulate instructions)
|
||||
- FEAT_RNG (Random number generator)
|
||||
- FEAT_SB (Speculation Barrier)
|
||||
|
||||
@@ -55,8 +55,10 @@ Supported guest CPU types:
|
||||
- ``cortex-a53`` (64-bit)
|
||||
- ``cortex-a57`` (64-bit)
|
||||
- ``cortex-a72`` (64-bit)
|
||||
- ``cortex-a76`` (64-bit)
|
||||
- ``a64fx`` (64-bit)
|
||||
- ``host`` (with KVM only)
|
||||
- ``neoverse-n1`` (64-bit)
|
||||
- ``max`` (same as ``host`` for KVM; best possible emulation with TCG)
|
||||
|
||||
Note that the default is ``cortex-a15``, so for an AArch64 guest you must
|
||||
|
||||
+48
-63
@@ -2002,86 +2002,71 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
GQueue *list = g_queue_new();
|
||||
guint pptt_start = table_data->len;
|
||||
guint parent_offset;
|
||||
guint length, i;
|
||||
int uid = 0;
|
||||
int socket;
|
||||
CPUArchIdList *cpus = ms->possible_cpus;
|
||||
int64_t socket_id = -1, cluster_id = -1, core_id = -1;
|
||||
uint32_t socket_offset = 0, cluster_offset = 0, core_offset = 0;
|
||||
uint32_t pptt_start = table_data->len;
|
||||
int n;
|
||||
AcpiTable table = { .sig = "PPTT", .rev = 2,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
|
||||
for (socket = 0; socket < ms->smp.sockets; socket++) {
|
||||
g_queue_push_tail(list,
|
||||
GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
build_processor_hierarchy_node(
|
||||
table_data,
|
||||
/*
|
||||
* Physical package - represents the boundary
|
||||
* of a physical package
|
||||
*/
|
||||
(1 << 0),
|
||||
0, socket, NULL, 0);
|
||||
}
|
||||
|
||||
if (mc->smp_props.clusters_supported) {
|
||||
length = g_queue_get_length(list);
|
||||
for (i = 0; i < length; i++) {
|
||||
int cluster;
|
||||
|
||||
parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
for (cluster = 0; cluster < ms->smp.clusters; cluster++) {
|
||||
g_queue_push_tail(list,
|
||||
GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
build_processor_hierarchy_node(
|
||||
table_data,
|
||||
(0 << 0), /* not a physical package */
|
||||
parent_offset, cluster, NULL, 0);
|
||||
}
|
||||
/*
|
||||
* This works with the assumption that cpus[n].props.*_id has been
|
||||
* sorted from top to down levels in mc->possible_cpu_arch_ids().
|
||||
* Otherwise, the unexpected and duplicated containers will be
|
||||
* created.
|
||||
*/
|
||||
for (n = 0; n < cpus->len; n++) {
|
||||
if (cpus->cpus[n].props.socket_id != socket_id) {
|
||||
assert(cpus->cpus[n].props.socket_id > socket_id);
|
||||
socket_id = cpus->cpus[n].props.socket_id;
|
||||
cluster_id = -1;
|
||||
core_id = -1;
|
||||
socket_offset = table_data->len - pptt_start;
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(1 << 0), /* Physical package */
|
||||
0, socket_id, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
length = g_queue_get_length(list);
|
||||
for (i = 0; i < length; i++) {
|
||||
int core;
|
||||
|
||||
parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
for (core = 0; core < ms->smp.cores; core++) {
|
||||
if (ms->smp.threads > 1) {
|
||||
g_queue_push_tail(list,
|
||||
GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
build_processor_hierarchy_node(
|
||||
table_data,
|
||||
(0 << 0), /* not a physical package */
|
||||
parent_offset, core, NULL, 0);
|
||||
} else {
|
||||
build_processor_hierarchy_node(
|
||||
table_data,
|
||||
(1 << 1) | /* ACPI Processor ID valid */
|
||||
(1 << 3), /* Node is a Leaf */
|
||||
parent_offset, uid++, NULL, 0);
|
||||
if (mc->smp_props.clusters_supported) {
|
||||
if (cpus->cpus[n].props.cluster_id != cluster_id) {
|
||||
assert(cpus->cpus[n].props.cluster_id > cluster_id);
|
||||
cluster_id = cpus->cpus[n].props.cluster_id;
|
||||
core_id = -1;
|
||||
cluster_offset = table_data->len - pptt_start;
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(0 << 0), /* Not a physical package */
|
||||
socket_offset, cluster_id, NULL, 0);
|
||||
}
|
||||
} else {
|
||||
cluster_offset = socket_offset;
|
||||
}
|
||||
}
|
||||
|
||||
length = g_queue_get_length(list);
|
||||
for (i = 0; i < length; i++) {
|
||||
int thread;
|
||||
if (ms->smp.threads == 1) {
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(1 << 1) | /* ACPI Processor ID valid */
|
||||
(1 << 3), /* Node is a Leaf */
|
||||
cluster_offset, n, NULL, 0);
|
||||
} else {
|
||||
if (cpus->cpus[n].props.core_id != core_id) {
|
||||
assert(cpus->cpus[n].props.core_id > core_id);
|
||||
core_id = cpus->cpus[n].props.core_id;
|
||||
core_offset = table_data->len - pptt_start;
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(0 << 0), /* Not a physical package */
|
||||
cluster_offset, core_id, NULL, 0);
|
||||
}
|
||||
|
||||
parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
for (thread = 0; thread < ms->smp.threads; thread++) {
|
||||
build_processor_hierarchy_node(
|
||||
table_data,
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(1 << 1) | /* ACPI Processor ID valid */
|
||||
(1 << 2) | /* Processor is a Thread */
|
||||
(1 << 3), /* Node is a Leaf */
|
||||
parent_offset, uid++, NULL, 0);
|
||||
core_offset, n, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
g_queue_free(list);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,6 +145,8 @@ static const int sbsa_ref_irqmap[] = {
|
||||
static const char * const valid_cpus[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-a57"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a72"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a76"),
|
||||
ARM_CPU_TYPE_NAME("neoverse-n1"),
|
||||
ARM_CPU_TYPE_NAME("max"),
|
||||
};
|
||||
|
||||
@@ -190,6 +192,20 @@ static void create_fdt(SBSAMachineState *sms)
|
||||
qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
|
||||
qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
|
||||
|
||||
/*
|
||||
* This versioning scheme is for informing platform fw only. It is neither:
|
||||
* - A QEMU versioned machine type; a given version of QEMU will emulate
|
||||
* a given version of the platform.
|
||||
* - A reflection of level of SBSA (now SystemReady SR) support provided.
|
||||
*
|
||||
* machine-version-major: updated when changes breaking fw compatibility
|
||||
* are introduced.
|
||||
* machine-version-minor: updated when features are added that don't break
|
||||
* fw compatibility.
|
||||
*/
|
||||
qemu_fdt_setprop_cell(fdt, "/", "machine-version-major", 0);
|
||||
qemu_fdt_setprop_cell(fdt, "/", "machine-version-minor", 0);
|
||||
|
||||
if (ms->numa_state->have_numa_distance) {
|
||||
int size = nb_numa_nodes * nb_numa_nodes * 3 * sizeof(uint32_t);
|
||||
uint32_t *matrix = g_malloc0(size);
|
||||
|
||||
+19
-2
@@ -202,7 +202,9 @@ static const char *valid_cpus[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-a53"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a57"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a72"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a76"),
|
||||
ARM_CPU_TYPE_NAME("a64fx"),
|
||||
ARM_CPU_TYPE_NAME("neoverse-n1"),
|
||||
ARM_CPU_TYPE_NAME("host"),
|
||||
ARM_CPU_TYPE_NAME("max"),
|
||||
};
|
||||
@@ -2552,7 +2554,9 @@ virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
|
||||
|
||||
static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||
{
|
||||
return idx % ms->numa_state->num_nodes;
|
||||
int64_t socket_id = ms->possible_cpus->cpus[idx].props.socket_id;
|
||||
|
||||
return socket_id % ms->numa_state->num_nodes;
|
||||
}
|
||||
|
||||
static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
||||
@@ -2560,6 +2564,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
||||
int n;
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
VirtMachineState *vms = VIRT_MACHINE(ms);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(vms);
|
||||
|
||||
if (ms->possible_cpus) {
|
||||
assert(ms->possible_cpus->len == max_cpus);
|
||||
@@ -2573,8 +2578,20 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
||||
ms->possible_cpus->cpus[n].type = ms->cpu_type;
|
||||
ms->possible_cpus->cpus[n].arch_id =
|
||||
virt_cpu_mp_affinity(vms, n);
|
||||
|
||||
assert(!mc->smp_props.dies_supported);
|
||||
ms->possible_cpus->cpus[n].props.has_socket_id = true;
|
||||
ms->possible_cpus->cpus[n].props.socket_id =
|
||||
n / (ms->smp.clusters * ms->smp.cores * ms->smp.threads);
|
||||
ms->possible_cpus->cpus[n].props.has_cluster_id = true;
|
||||
ms->possible_cpus->cpus[n].props.cluster_id =
|
||||
(n / (ms->smp.cores * ms->smp.threads)) % ms->smp.clusters;
|
||||
ms->possible_cpus->cpus[n].props.has_core_id = true;
|
||||
ms->possible_cpus->cpus[n].props.core_id =
|
||||
(n / ms->smp.threads) % ms->smp.cores;
|
||||
ms->possible_cpus->cpus[n].props.has_thread_id = true;
|
||||
ms->possible_cpus->cpus[n].props.thread_id = n;
|
||||
ms->possible_cpus->cpus[n].props.thread_id =
|
||||
n % ms->smp.threads;
|
||||
}
|
||||
return ms->possible_cpus;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,10 @@ void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict)
|
||||
if (c->has_die_id) {
|
||||
monitor_printf(mon, " die-id: \"%" PRIu64 "\"\n", c->die_id);
|
||||
}
|
||||
if (c->has_cluster_id) {
|
||||
monitor_printf(mon, " cluster-id: \"%" PRIu64 "\"\n",
|
||||
c->cluster_id);
|
||||
}
|
||||
if (c->has_core_id) {
|
||||
monitor_printf(mon, " core-id: \"%" PRIu64 "\"\n", c->core_id);
|
||||
}
|
||||
|
||||
@@ -682,6 +682,11 @@ void machine_set_cpu_numa_node(MachineState *machine,
|
||||
return;
|
||||
}
|
||||
|
||||
if (props->has_cluster_id && !slot->props.has_cluster_id) {
|
||||
error_setg(errp, "cluster-id is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
if (props->has_socket_id && !slot->props.has_socket_id) {
|
||||
error_setg(errp, "socket-id is not supported");
|
||||
return;
|
||||
@@ -701,6 +706,11 @@ void machine_set_cpu_numa_node(MachineState *machine,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (props->has_cluster_id &&
|
||||
props->cluster_id != slot->props.cluster_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (props->has_die_id && props->die_id != slot->props.die_id) {
|
||||
continue;
|
||||
}
|
||||
@@ -995,6 +1005,12 @@ static char *cpu_slot_to_string(const CPUArchId *cpu)
|
||||
}
|
||||
g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id);
|
||||
}
|
||||
if (cpu->props.has_cluster_id) {
|
||||
if (s->len) {
|
||||
g_string_append_printf(s, ", ");
|
||||
}
|
||||
g_string_append_printf(s, "cluster-id: %"PRId64, cpu->props.cluster_id);
|
||||
}
|
||||
if (cpu->props.has_core_id) {
|
||||
if (s->len) {
|
||||
g_string_append_printf(s, ", ");
|
||||
|
||||
+4
-2
@@ -868,10 +868,11 @@
|
||||
# @node-id: NUMA node ID the CPU belongs to
|
||||
# @socket-id: socket number within node/board the CPU belongs to
|
||||
# @die-id: die number within socket the CPU belongs to (since 4.1)
|
||||
# @core-id: core number within die the CPU belongs to
|
||||
# @cluster-id: cluster number within die the CPU belongs to (since 7.1)
|
||||
# @core-id: core number within cluster the CPU belongs to
|
||||
# @thread-id: thread number within core the CPU belongs to
|
||||
#
|
||||
# Note: currently there are 5 properties that could be present
|
||||
# Note: currently there are 6 properties that could be present
|
||||
# but management should be prepared to pass through other
|
||||
# properties with device_add command to allow for future
|
||||
# interface extension. This also requires the filed names to be kept in
|
||||
@@ -883,6 +884,7 @@
|
||||
'data': { '*node-id': 'int',
|
||||
'*socket-id': 'int',
|
||||
'*die-id': 'int',
|
||||
'*cluster-id': 'int',
|
||||
'*core-id': 'int',
|
||||
'*thread-id': 'int'
|
||||
}
|
||||
|
||||
+10
-6
@@ -187,13 +187,17 @@ SMULTT .... 0001 0110 .... 0000 .... 1110 .... @rd0mn
|
||||
|
||||
{
|
||||
{
|
||||
YIELD ---- 0011 0010 0000 1111 ---- 0000 0001
|
||||
WFE ---- 0011 0010 0000 1111 ---- 0000 0010
|
||||
WFI ---- 0011 0010 0000 1111 ---- 0000 0011
|
||||
[
|
||||
YIELD ---- 0011 0010 0000 1111 ---- 0000 0001
|
||||
WFE ---- 0011 0010 0000 1111 ---- 0000 0010
|
||||
WFI ---- 0011 0010 0000 1111 ---- 0000 0011
|
||||
|
||||
# TODO: Implement SEV, SEVL; may help SMP performance.
|
||||
# SEV ---- 0011 0010 0000 1111 ---- 0000 0100
|
||||
# SEVL ---- 0011 0010 0000 1111 ---- 0000 0101
|
||||
# TODO: Implement SEV, SEVL; may help SMP performance.
|
||||
# SEV ---- 0011 0010 0000 1111 ---- 0000 0100
|
||||
# SEVL ---- 0011 0010 0000 1111 ---- 0000 0101
|
||||
|
||||
ESB ---- 0011 0010 0000 1111 ---- 0001 0000
|
||||
]
|
||||
|
||||
# The canonical nop ends in 00000000, but the whole of the
|
||||
# rest of the space executes as nop if otherwise unsupported.
|
||||
|
||||
@@ -102,6 +102,17 @@ enum {
|
||||
ARM_CP_SVE = 1 << 14,
|
||||
/* Flag: Do not expose in gdb sysreg xml. */
|
||||
ARM_CP_NO_GDB = 1 << 15,
|
||||
/*
|
||||
* Flags: If EL3 but not EL2...
|
||||
* - UNDEF: discard the cpreg,
|
||||
* - KEEP: retain the cpreg as is,
|
||||
* - C_NZ: set const on the cpreg, but retain resetvalue,
|
||||
* - else: set const on the cpreg, zero resetvalue, aka RES0.
|
||||
* See rule RJFFP in section D1.1.3 of DDI0487H.a.
|
||||
*/
|
||||
ARM_CP_EL3_NO_EL2_UNDEF = 1 << 16,
|
||||
ARM_CP_EL3_NO_EL2_KEEP = 1 << 17,
|
||||
ARM_CP_EL3_NO_EL2_C_NZ = 1 << 18,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+56
-10
@@ -85,7 +85,7 @@ static bool arm_cpu_has_work(CPUState *cs)
|
||||
return (cpu->power_state != PSCI_OFF)
|
||||
&& cs->interrupt_request &
|
||||
(CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD
|
||||
| CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ
|
||||
| CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ | CPU_INTERRUPT_VSERR
|
||||
| CPU_INTERRUPT_EXITTB);
|
||||
}
|
||||
|
||||
@@ -230,6 +230,11 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||
*/
|
||||
env->cp15.gcr_el1 = 0x1ffff;
|
||||
}
|
||||
/*
|
||||
* Disable access to SCXTNUM_EL0 from CSV2_1p2.
|
||||
* This is not yet exposed from the Linux kernel in any way.
|
||||
*/
|
||||
env->cp15.sctlr_el[1] |= SCTLR_TSCXT;
|
||||
#else
|
||||
/* Reset into the highest available EL */
|
||||
if (arm_feature(env, ARM_FEATURE_EL3)) {
|
||||
@@ -511,6 +516,12 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
|
||||
return false;
|
||||
}
|
||||
return !(env->daif & PSTATE_I);
|
||||
case EXCP_VSERR:
|
||||
if (!(hcr_el2 & HCR_AMO) || (hcr_el2 & HCR_TGE)) {
|
||||
/* VIRQs are only taken when hypervized. */
|
||||
return false;
|
||||
}
|
||||
return !(env->daif & PSTATE_A);
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
@@ -632,6 +643,17 @@ static bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
if (interrupt_request & CPU_INTERRUPT_VSERR) {
|
||||
excp_idx = EXCP_VSERR;
|
||||
target_el = 1;
|
||||
if (arm_excp_unmasked(cs, excp_idx, target_el,
|
||||
cur_el, secure, hcr_el2)) {
|
||||
/* Taking a virtual abort clears HCR_EL2.VSE */
|
||||
env->cp15.hcr_el2 &= ~HCR_VSE;
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_VSERR);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
found:
|
||||
@@ -684,6 +706,25 @@ void arm_cpu_update_vfiq(ARMCPU *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
void arm_cpu_update_vserr(ARMCPU *cpu)
|
||||
{
|
||||
/*
|
||||
* Update the interrupt level for VSERR, which is the HCR_EL2.VSE bit.
|
||||
*/
|
||||
CPUARMState *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
bool new_state = env->cp15.hcr_el2 & HCR_VSE;
|
||||
|
||||
if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VSERR) != 0)) {
|
||||
if (new_state) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_VSERR);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_VSERR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static void arm_cpu_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
@@ -1793,11 +1834,14 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
*/
|
||||
unset_feature(env, ARM_FEATURE_EL3);
|
||||
|
||||
/* Disable the security extension feature bits in the processor feature
|
||||
* registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12].
|
||||
/*
|
||||
* Disable the security extension feature bits in the processor
|
||||
* feature registers as well.
|
||||
*/
|
||||
cpu->isar.id_pfr1 &= ~0xf0;
|
||||
cpu->isar.id_aa64pfr0 &= ~0xf000;
|
||||
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);
|
||||
}
|
||||
|
||||
if (!cpu->has_el2) {
|
||||
@@ -1828,12 +1872,14 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
if (!arm_feature(env, ARM_FEATURE_EL2)) {
|
||||
/* Disable the hypervisor feature bits in the processor feature
|
||||
* registers if we don't have EL2. These are id_pfr1[15:12] and
|
||||
* id_aa64pfr0_el1[11:8].
|
||||
/*
|
||||
* Disable the hypervisor feature bits in the processor feature
|
||||
* registers if we don't have EL2.
|
||||
*/
|
||||
cpu->isar.id_aa64pfr0 &= ~0xf00;
|
||||
cpu->isar.id_pfr1 &= ~0xf000;
|
||||
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);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#define EXCP_LSERR 21 /* v8M LSERR SecureFault */
|
||||
#define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
|
||||
#define EXCP_DIVBYZERO 23 /* v7M DIVBYZERO UsageFault */
|
||||
#define EXCP_VSERR 24
|
||||
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
|
||||
|
||||
#define ARMV7M_EXCP_RESET 1
|
||||
@@ -89,6 +90,7 @@ enum {
|
||||
#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
|
||||
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_EXT_2
|
||||
#define CPU_INTERRUPT_VFIQ CPU_INTERRUPT_TGT_EXT_3
|
||||
#define CPU_INTERRUPT_VSERR CPU_INTERRUPT_TGT_INT_0
|
||||
|
||||
/* The usual mapping for an AArch64 system register to its AArch32
|
||||
* counterpart is for the 32 bit world to have access to the lower
|
||||
@@ -525,6 +527,11 @@ typedef struct CPUArchState {
|
||||
uint64_t tfsr_el[4]; /* tfsre0_el1 is index 0. */
|
||||
uint64_t gcr_el1;
|
||||
uint64_t rgsr_el1;
|
||||
|
||||
/* Minimal RAS registers */
|
||||
uint64_t disr_el1;
|
||||
uint64_t vdisr_el2;
|
||||
uint64_t vsesr_el2;
|
||||
} cp15;
|
||||
|
||||
struct {
|
||||
@@ -681,6 +688,8 @@ typedef struct CPUArchState {
|
||||
ARMPACKey apdb;
|
||||
ARMPACKey apga;
|
||||
} keys;
|
||||
|
||||
uint64_t scxtnum_el[4];
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
@@ -1204,6 +1213,7 @@ void pmu_init(ARMCPU *cpu);
|
||||
#define SCTLR_WXN (1U << 19)
|
||||
#define SCTLR_ST (1U << 20) /* up to ??, RAZ in v6 */
|
||||
#define SCTLR_UWXN (1U << 20) /* v7 onward, AArch32 only */
|
||||
#define SCTLR_TSCXT (1U << 20) /* FEAT_CSV2_1p2, AArch64 only */
|
||||
#define SCTLR_FI (1U << 21) /* up to v7, v8 RES0 */
|
||||
#define SCTLR_IESB (1U << 21) /* v8.2-IESB, AArch64 only */
|
||||
#define SCTLR_U (1U << 22) /* up to v6, RAO in v7 */
|
||||
@@ -4015,6 +4025,19 @@ static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id)
|
||||
{
|
||||
int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2);
|
||||
if (key >= 2) {
|
||||
return true; /* FEAT_CSV2_2 */
|
||||
}
|
||||
if (key == 1) {
|
||||
key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC);
|
||||
return key >= 2; /* FEAT_CSV2_1p2 */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
|
||||
|
||||
+195
-158
@@ -34,65 +34,9 @@
|
||||
#include "hvf_arm.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "cpregs.h"
|
||||
#include "internals.h"
|
||||
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static uint64_t a57_a53_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
/* Number of cores is in [25:24]; otherwise we RAZ */
|
||||
return (cpu->core_count - 1) << 24;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
{ .name = "L2CTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 2,
|
||||
.access = PL1_RW, .readfn = a57_a53_l2ctlr_read,
|
||||
.writefn = arm_cp_write_ignore },
|
||||
{ .name = "L2CTLR",
|
||||
.cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 2,
|
||||
.access = PL1_RW, .readfn = a57_a53_l2ctlr_read,
|
||||
.writefn = arm_cp_write_ignore },
|
||||
#endif
|
||||
{ .name = "L2ECTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 3,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "L2ECTLR",
|
||||
.cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 3,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "L2ACTLR", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 0, .opc2 = 0,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 0,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "CPUACTLR",
|
||||
.cp = 15, .opc1 = 0, .crm = 15,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||
{ .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 1,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "CPUECTLR",
|
||||
.cp = 15, .opc1 = 1, .crm = 15,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||
{ .name = "CPUMERRSR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 2,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "CPUMERRSR",
|
||||
.cp = 15, .opc1 = 2, .crm = 15,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||
{ .name = "L2MERRSR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 3,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "L2MERRSR",
|
||||
.cp = 15, .opc1 = 3, .crm = 15,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||
};
|
||||
|
||||
static void aarch64_a57_initfn(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
@@ -143,7 +87,7 @@ static void aarch64_a57_initfn(Object *obj)
|
||||
cpu->gic_num_lrs = 4;
|
||||
cpu->gic_vpribits = 5;
|
||||
cpu->gic_vprebits = 5;
|
||||
define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
|
||||
define_cortex_a72_a57_a53_cp_reginfo(cpu);
|
||||
}
|
||||
|
||||
static void aarch64_a53_initfn(Object *obj)
|
||||
@@ -196,7 +140,7 @@ static void aarch64_a53_initfn(Object *obj)
|
||||
cpu->gic_num_lrs = 4;
|
||||
cpu->gic_vpribits = 5;
|
||||
cpu->gic_vprebits = 5;
|
||||
define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
|
||||
define_cortex_a72_a57_a53_cp_reginfo(cpu);
|
||||
}
|
||||
|
||||
static void aarch64_a72_initfn(Object *obj)
|
||||
@@ -247,7 +191,137 @@ static void aarch64_a72_initfn(Object *obj)
|
||||
cpu->gic_num_lrs = 4;
|
||||
cpu->gic_vpribits = 5;
|
||||
cpu->gic_vprebits = 5;
|
||||
define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
|
||||
define_cortex_a72_a57_a53_cp_reginfo(cpu);
|
||||
}
|
||||
|
||||
static void aarch64_a76_initfn(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
|
||||
cpu->dtb_compatible = "arm,cortex-a76";
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
set_feature(&cpu->env, ARM_FEATURE_PMU);
|
||||
|
||||
/* Ordered by B2.4 AArch64 registers by functional group */
|
||||
cpu->clidr = 0x82000023;
|
||||
cpu->ctr = 0x8444C004;
|
||||
cpu->dcz_blocksize = 4;
|
||||
cpu->isar.id_aa64dfr0 = 0x0000000010305408ull;
|
||||
cpu->isar.id_aa64isar0 = 0x0000100010211120ull;
|
||||
cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
|
||||
cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull;
|
||||
cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
|
||||
cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
|
||||
cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */
|
||||
cpu->isar.id_aa64pfr1 = 0x0000000000000010ull;
|
||||
cpu->id_afr0 = 0x00000000;
|
||||
cpu->isar.id_dfr0 = 0x04010088;
|
||||
cpu->isar.id_isar0 = 0x02101110;
|
||||
cpu->isar.id_isar1 = 0x13112111;
|
||||
cpu->isar.id_isar2 = 0x21232042;
|
||||
cpu->isar.id_isar3 = 0x01112131;
|
||||
cpu->isar.id_isar4 = 0x00010142;
|
||||
cpu->isar.id_isar5 = 0x01011121;
|
||||
cpu->isar.id_isar6 = 0x00000010;
|
||||
cpu->isar.id_mmfr0 = 0x10201105;
|
||||
cpu->isar.id_mmfr1 = 0x40000000;
|
||||
cpu->isar.id_mmfr2 = 0x01260000;
|
||||
cpu->isar.id_mmfr3 = 0x02122211;
|
||||
cpu->isar.id_mmfr4 = 0x00021110;
|
||||
cpu->isar.id_pfr0 = 0x10010131;
|
||||
cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */
|
||||
cpu->isar.id_pfr2 = 0x00000011;
|
||||
cpu->midr = 0x414fd0b1; /* r4p1 */
|
||||
cpu->revidr = 0;
|
||||
|
||||
/* From B2.18 CCSIDR_EL1 */
|
||||
cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */
|
||||
cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */
|
||||
cpu->ccsidr[2] = 0x707fe03a; /* 512KB L2 cache */
|
||||
|
||||
/* From B2.93 SCTLR_EL3 */
|
||||
cpu->reset_sctlr = 0x30c50838;
|
||||
|
||||
/* From B4.23 ICH_VTR_EL2 */
|
||||
cpu->gic_num_lrs = 4;
|
||||
cpu->gic_vpribits = 5;
|
||||
cpu->gic_vprebits = 5;
|
||||
|
||||
/* From B5.1 AdvSIMD AArch64 register summary */
|
||||
cpu->isar.mvfr0 = 0x10110222;
|
||||
cpu->isar.mvfr1 = 0x13211111;
|
||||
cpu->isar.mvfr2 = 0x00000043;
|
||||
}
|
||||
|
||||
static void aarch64_neoverse_n1_initfn(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
|
||||
cpu->dtb_compatible = "arm,neoverse-n1";
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
set_feature(&cpu->env, ARM_FEATURE_PMU);
|
||||
|
||||
/* Ordered by B2.4 AArch64 registers by functional group */
|
||||
cpu->clidr = 0x82000023;
|
||||
cpu->ctr = 0x8444c004;
|
||||
cpu->dcz_blocksize = 4;
|
||||
cpu->isar.id_aa64dfr0 = 0x0000000110305408ull;
|
||||
cpu->isar.id_aa64isar0 = 0x0000100010211120ull;
|
||||
cpu->isar.id_aa64isar1 = 0x0000000000100001ull;
|
||||
cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull;
|
||||
cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
|
||||
cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull;
|
||||
cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */
|
||||
cpu->isar.id_aa64pfr1 = 0x0000000000000020ull;
|
||||
cpu->id_afr0 = 0x00000000;
|
||||
cpu->isar.id_dfr0 = 0x04010088;
|
||||
cpu->isar.id_isar0 = 0x02101110;
|
||||
cpu->isar.id_isar1 = 0x13112111;
|
||||
cpu->isar.id_isar2 = 0x21232042;
|
||||
cpu->isar.id_isar3 = 0x01112131;
|
||||
cpu->isar.id_isar4 = 0x00010142;
|
||||
cpu->isar.id_isar5 = 0x01011121;
|
||||
cpu->isar.id_isar6 = 0x00000010;
|
||||
cpu->isar.id_mmfr0 = 0x10201105;
|
||||
cpu->isar.id_mmfr1 = 0x40000000;
|
||||
cpu->isar.id_mmfr2 = 0x01260000;
|
||||
cpu->isar.id_mmfr3 = 0x02122211;
|
||||
cpu->isar.id_mmfr4 = 0x00021110;
|
||||
cpu->isar.id_pfr0 = 0x10010131;
|
||||
cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */
|
||||
cpu->isar.id_pfr2 = 0x00000011;
|
||||
cpu->midr = 0x414fd0c1; /* r4p1 */
|
||||
cpu->revidr = 0;
|
||||
|
||||
/* From B2.23 CCSIDR_EL1 */
|
||||
cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */
|
||||
cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */
|
||||
cpu->ccsidr[2] = 0x70ffe03a; /* 1MB L2 cache */
|
||||
|
||||
/* From B2.98 SCTLR_EL3 */
|
||||
cpu->reset_sctlr = 0x30c50838;
|
||||
|
||||
/* From B4.23 ICH_VTR_EL2 */
|
||||
cpu->gic_num_lrs = 4;
|
||||
cpu->gic_vpribits = 5;
|
||||
cpu->gic_vprebits = 5;
|
||||
|
||||
/* From B5.1 AdvSIMD AArch64 register summary */
|
||||
cpu->isar.mvfr0 = 0x10110222;
|
||||
cpu->isar.mvfr1 = 0x13211111;
|
||||
cpu->isar.mvfr2 = 0x00000043;
|
||||
}
|
||||
|
||||
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
|
||||
@@ -738,7 +812,6 @@ static void aarch64_max_initfn(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
uint64_t t;
|
||||
uint32_t u;
|
||||
|
||||
if (kvm_enabled() || hvf_enabled()) {
|
||||
/* With KVM or HVF, '-cpu max' is identical to '-cpu host' */
|
||||
@@ -770,51 +843,56 @@ static void aarch64_max_initfn(Object *obj)
|
||||
cpu->midr = t;
|
||||
|
||||
t = cpu->isar.id_aa64isar0;
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* AES + PMULL */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* SHA512 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* FEAT_PMULL */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); /* FEAT_SHA1 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* FEAT_SHA512 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, CRC32, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 2);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, RDM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SHA3, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 2); /* FEAT_LSE */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, RDM, 1); /* FEAT_RDM */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SHA3, 1); /* FEAT_SHA3 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1); /* FEAT_SM3 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1); /* FEAT_SM4 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1); /* FEAT_DotProd */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1); /* FEAT_FHM */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* FEAT_FlagM2 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); /* FEAT_RNG */
|
||||
cpu->isar.id_aa64isar0 = t;
|
||||
|
||||
t = cpu->isar.id_aa64isar1;
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); /* FEAT_DPB2 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); /* FEAT_JSCVT */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); /* FEAT_FCMA */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* FEAT_LRCPC2 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1); /* FEAT_FRINTTS */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1); /* FEAT_SB */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1); /* FEAT_SPECRES */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 1); /* FEAT_BF16 */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, DGH, 1); /* FEAT_DGH */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); /* FEAT_I8MM */
|
||||
cpu->isar.id_aa64isar1 = t;
|
||||
|
||||
t = cpu->isar.id_aa64pfr0;
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, RAS, 1); /* FEAT_RAS */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, FP, 1);
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1);
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1);
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1); /* FEAT_CSV3 */
|
||||
cpu->isar.id_aa64pfr0 = t;
|
||||
|
||||
t = cpu->isar.id_aa64pfr1;
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2);
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); /* FEAT_BTI */
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); /* FEAT_SSBS2 */
|
||||
/*
|
||||
* Begin with full support for MTE. This will be downgraded to MTE=0
|
||||
* during realize if the board provides no tag memory, much like
|
||||
* we do for EL2 with the virtualization=on property.
|
||||
*/
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3);
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
|
||||
cpu->isar.id_aa64pfr1 = t;
|
||||
|
||||
t = cpu->isar.id_aa64mmfr0;
|
||||
@@ -826,86 +904,43 @@ static void aarch64_max_initfn(Object *obj)
|
||||
cpu->isar.id_aa64mmfr0 = t;
|
||||
|
||||
t = cpu->isar.id_aa64mmfr1;
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* FEAT_PAN2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
|
||||
cpu->isar.id_aa64mmfr1 = t;
|
||||
|
||||
t = cpu->isar.id_aa64mmfr2;
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* FEAT_TTCNP */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); /* FEAT_UAO */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, IESB, 1); /* FEAT_IESB */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1); /* FEAT_LVA */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* FEAT_TTST */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1); /* FEAT_TTL */
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, BBM, 2); /* FEAT_BBM at level 2 */
|
||||
cpu->isar.id_aa64mmfr2 = t;
|
||||
|
||||
t = cpu->isar.id_aa64zfr0;
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* PMULL */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, BFLOAT16, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SHA3, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SM4, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* FEAT_SVE_PMULL128 */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); /* FEAT_SVE_BitPerm */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, BFLOAT16, 1); /* FEAT_BF16 */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SHA3, 1); /* FEAT_SVE_SHA3 */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SM4, 1); /* FEAT_SVE_SM4 */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); /* FEAT_I8MM */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); /* FEAT_F32MM */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); /* FEAT_F64MM */
|
||||
cpu->isar.id_aa64zfr0 = t;
|
||||
|
||||
/* Replicate the same data to the 32-bit id registers. */
|
||||
u = cpu->isar.id_isar5;
|
||||
u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */
|
||||
u = FIELD_DP32(u, ID_ISAR5, SHA1, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR5, SHA2, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR5, CRC32, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR5, RDM, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR5, VCMA, 1);
|
||||
cpu->isar.id_isar5 = u;
|
||||
|
||||
u = cpu->isar.id_isar6;
|
||||
u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, SB, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, BF16, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, I8MM, 1);
|
||||
cpu->isar.id_isar6 = u;
|
||||
|
||||
u = cpu->isar.id_pfr0;
|
||||
u = FIELD_DP32(u, ID_PFR0, DIT, 1);
|
||||
cpu->isar.id_pfr0 = u;
|
||||
|
||||
u = cpu->isar.id_pfr2;
|
||||
u = FIELD_DP32(u, ID_PFR2, SSBS, 1);
|
||||
cpu->isar.id_pfr2 = u;
|
||||
|
||||
u = cpu->isar.id_mmfr3;
|
||||
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
|
||||
cpu->isar.id_mmfr3 = u;
|
||||
|
||||
u = cpu->isar.id_mmfr4;
|
||||
u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */
|
||||
u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
|
||||
u = FIELD_DP32(u, ID_MMFR4, CNP, 1); /* TTCNP */
|
||||
u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */
|
||||
cpu->isar.id_mmfr4 = u;
|
||||
|
||||
t = cpu->isar.id_aa64dfr0;
|
||||
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
|
||||
t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 9); /* FEAT_Debugv8p4 */
|
||||
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* FEAT_PMUv3p4 */
|
||||
cpu->isar.id_aa64dfr0 = t;
|
||||
|
||||
u = cpu->isar.id_dfr0;
|
||||
u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
|
||||
cpu->isar.id_dfr0 = u;
|
||||
|
||||
u = cpu->isar.mvfr1;
|
||||
u = FIELD_DP32(u, MVFR1, FPHP, 3); /* v8.2-FP16 */
|
||||
u = FIELD_DP32(u, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
|
||||
cpu->isar.mvfr1 = u;
|
||||
/* Replicate the same data to the 32-bit id registers. */
|
||||
aa32_max_features(cpu);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/*
|
||||
@@ -976,7 +1011,9 @@ static const ARMCPUInfo aarch64_cpus[] = {
|
||||
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
|
||||
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
|
||||
{ .name = "cortex-a72", .initfn = aarch64_a72_initfn },
|
||||
{ .name = "cortex-a76", .initfn = aarch64_a76_initfn },
|
||||
{ .name = "a64fx", .initfn = aarch64_a64fx_initfn },
|
||||
{ .name = "neoverse-n1", .initfn = aarch64_neoverse_n1_initfn },
|
||||
{ .name = "max", .initfn = aarch64_max_initfn },
|
||||
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
|
||||
{ .name = "host", .initfn = aarch64_host_initfn },
|
||||
|
||||
+168
-59
@@ -20,6 +20,130 @@
|
||||
#endif
|
||||
#include "cpregs.h"
|
||||
|
||||
|
||||
/* Share AArch32 -cpu max features with AArch64. */
|
||||
void aa32_max_features(ARMCPU *cpu)
|
||||
{
|
||||
uint32_t t;
|
||||
|
||||
/* Add additional features supported by QEMU */
|
||||
t = cpu->isar.id_isar5;
|
||||
t = FIELD_DP32(t, ID_ISAR5, AES, 2); /* FEAT_PMULL */
|
||||
t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); /* FEAT_SHA1 */
|
||||
t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); /* FEAT_SHA256 */
|
||||
t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR5, RDM, 1); /* FEAT_RDM */
|
||||
t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); /* FEAT_FCMA */
|
||||
cpu->isar.id_isar5 = t;
|
||||
|
||||
t = cpu->isar.id_isar6;
|
||||
t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); /* FEAT_JSCVT */
|
||||
t = FIELD_DP32(t, ID_ISAR6, DP, 1); /* Feat_DotProd */
|
||||
t = FIELD_DP32(t, ID_ISAR6, FHM, 1); /* FEAT_FHM */
|
||||
t = FIELD_DP32(t, ID_ISAR6, SB, 1); /* FEAT_SB */
|
||||
t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); /* FEAT_SPECRES */
|
||||
t = FIELD_DP32(t, ID_ISAR6, BF16, 1); /* FEAT_AA32BF16 */
|
||||
t = FIELD_DP32(t, ID_ISAR6, I8MM, 1); /* FEAT_AA32I8MM */
|
||||
cpu->isar.id_isar6 = t;
|
||||
|
||||
t = cpu->isar.mvfr1;
|
||||
t = FIELD_DP32(t, MVFR1, FPHP, 3); /* FEAT_FP16 */
|
||||
t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* FEAT_FP16 */
|
||||
cpu->isar.mvfr1 = t;
|
||||
|
||||
t = cpu->isar.mvfr2;
|
||||
t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
|
||||
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
|
||||
cpu->isar.mvfr2 = t;
|
||||
|
||||
t = cpu->isar.id_mmfr3;
|
||||
t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* FEAT_PAN2 */
|
||||
cpu->isar.id_mmfr3 = t;
|
||||
|
||||
t = cpu->isar.id_mmfr4;
|
||||
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* FEAT_AA32HPD */
|
||||
t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
|
||||
t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* FEAT_TTCNP */
|
||||
t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX*/
|
||||
cpu->isar.id_mmfr4 = t;
|
||||
|
||||
t = cpu->isar.id_pfr0;
|
||||
t = FIELD_DP32(t, ID_PFR0, CSV2, 2); /* FEAT_CVS2 */
|
||||
t = FIELD_DP32(t, ID_PFR0, DIT, 1); /* FEAT_DIT */
|
||||
t = FIELD_DP32(t, ID_PFR0, RAS, 1); /* FEAT_RAS */
|
||||
cpu->isar.id_pfr0 = t;
|
||||
|
||||
t = cpu->isar.id_pfr2;
|
||||
t = FIELD_DP32(t, ID_PFR2, CSV3, 1); /* FEAT_CSV3 */
|
||||
t = FIELD_DP32(t, ID_PFR2, SSBS, 1); /* FEAT_SSBS */
|
||||
cpu->isar.id_pfr2 = t;
|
||||
|
||||
t = cpu->isar.id_dfr0;
|
||||
t = FIELD_DP32(t, ID_DFR0, COPDBG, 9); /* FEAT_Debugv8p4 */
|
||||
t = FIELD_DP32(t, ID_DFR0, COPSDBG, 9); /* FEAT_Debugv8p4 */
|
||||
t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* FEAT_PMUv3p4 */
|
||||
cpu->isar.id_dfr0 = t;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static uint64_t l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
/* Number of cores is in [25:24]; otherwise we RAZ */
|
||||
return (cpu->core_count - 1) << 24;
|
||||
}
|
||||
|
||||
static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
|
||||
{ .name = "L2CTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 2,
|
||||
.access = PL1_RW, .readfn = l2ctlr_read,
|
||||
.writefn = arm_cp_write_ignore },
|
||||
{ .name = "L2CTLR",
|
||||
.cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 2,
|
||||
.access = PL1_RW, .readfn = l2ctlr_read,
|
||||
.writefn = arm_cp_write_ignore },
|
||||
{ .name = "L2ECTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 11, .crm = 0, .opc2 = 3,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "L2ECTLR",
|
||||
.cp = 15, .opc1 = 1, .crn = 9, .crm = 0, .opc2 = 3,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "L2ACTLR", .state = ARM_CP_STATE_BOTH,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 0, .opc2 = 0,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 0,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "CPUACTLR",
|
||||
.cp = 15, .opc1 = 0, .crm = 15,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||
{ .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 1,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "CPUECTLR",
|
||||
.cp = 15, .opc1 = 1, .crm = 15,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||
{ .name = "CPUMERRSR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 2,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "CPUMERRSR",
|
||||
.cp = 15, .opc1 = 2, .crm = 15,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||
{ .name = "L2MERRSR_EL1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 2, .opc2 = 3,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "L2MERRSR",
|
||||
.cp = 15, .opc1 = 3, .crm = 15,
|
||||
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
|
||||
};
|
||||
|
||||
void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu)
|
||||
{
|
||||
define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
/* CPU models. These are not needed for the AArch64 linux-user build. */
|
||||
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
|
||||
|
||||
@@ -936,70 +1060,55 @@ static void arm_max_initfn(Object *obj)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(obj);
|
||||
|
||||
cortex_a15_initfn(obj);
|
||||
/* aarch64_a57_initfn, advertising none of the aarch64 features */
|
||||
cpu->dtb_compatible = "arm,cortex-a57";
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL2);
|
||||
set_feature(&cpu->env, ARM_FEATURE_EL3);
|
||||
set_feature(&cpu->env, ARM_FEATURE_PMU);
|
||||
cpu->midr = 0x411fd070;
|
||||
cpu->revidr = 0x00000000;
|
||||
cpu->reset_fpsid = 0x41034070;
|
||||
cpu->isar.mvfr0 = 0x10110222;
|
||||
cpu->isar.mvfr1 = 0x12111111;
|
||||
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;
|
||||
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.dbgdidr = 0x3516d000;
|
||||
cpu->clidr = 0x0a200023;
|
||||
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
|
||||
cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
|
||||
cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */
|
||||
define_cortex_a72_a57_a53_cp_reginfo(cpu);
|
||||
|
||||
/* old-style VFP short-vector support */
|
||||
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
|
||||
aa32_max_features(cpu);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/*
|
||||
* We don't set these in system emulation mode for the moment,
|
||||
* since we don't correctly set (all of) the ID registers to
|
||||
* advertise them.
|
||||
* Break with true ARMv8 and add back old-style VFP short-vector support.
|
||||
* Only do this for user-mode, where -cpu max is the default, so that
|
||||
* older v6 and v7 programs are more likely to work without adjustment.
|
||||
*/
|
||||
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||
{
|
||||
uint32_t t;
|
||||
|
||||
t = cpu->isar.id_isar5;
|
||||
t = FIELD_DP32(t, ID_ISAR5, AES, 2);
|
||||
t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
|
||||
cpu->isar.id_isar5 = t;
|
||||
|
||||
t = cpu->isar.id_isar6;
|
||||
t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, SB, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, BF16, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);
|
||||
cpu->isar.id_isar6 = t;
|
||||
|
||||
t = cpu->isar.mvfr1;
|
||||
t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
|
||||
t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
|
||||
cpu->isar.mvfr1 = t;
|
||||
|
||||
t = cpu->isar.mvfr2;
|
||||
t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
|
||||
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
|
||||
cpu->isar.mvfr2 = t;
|
||||
|
||||
t = cpu->isar.id_mmfr3;
|
||||
t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
|
||||
cpu->isar.id_mmfr3 = t;
|
||||
|
||||
t = cpu->isar.id_mmfr4;
|
||||
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
|
||||
t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
|
||||
t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
|
||||
t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
|
||||
cpu->isar.id_mmfr4 = t;
|
||||
|
||||
t = cpu->isar.id_pfr0;
|
||||
t = FIELD_DP32(t, ID_PFR0, DIT, 1);
|
||||
cpu->isar.id_pfr0 = t;
|
||||
|
||||
t = cpu->isar.id_pfr2;
|
||||
t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
|
||||
cpu->isar.id_pfr2 = t;
|
||||
}
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
|
||||
#endif
|
||||
}
|
||||
#endif /* !TARGET_AARCH64 */
|
||||
|
||||
|
||||
+355
-245
File diff suppressed because it is too large
Load Diff
@@ -54,6 +54,7 @@ DEF_HELPER_1(wfe, void, env)
|
||||
DEF_HELPER_1(yield, void, env)
|
||||
DEF_HELPER_1(pre_hvc, void, env)
|
||||
DEF_HELPER_2(pre_smc, void, env, i32)
|
||||
DEF_HELPER_1(vesb, void, env)
|
||||
|
||||
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
|
||||
DEF_HELPER_2(cpsr_write_eret, void, env, i32)
|
||||
|
||||
@@ -947,6 +947,14 @@ void arm_cpu_update_virq(ARMCPU *cpu);
|
||||
*/
|
||||
void arm_cpu_update_vfiq(ARMCPU *cpu);
|
||||
|
||||
/**
|
||||
* arm_cpu_update_vserr: Update CPU_INTERRUPT_VSERR bit
|
||||
*
|
||||
* Update the CPU_INTERRUPT_VSERR bit in cs->interrupt_request,
|
||||
* following a change to the HCR_EL2.VSE bit.
|
||||
*/
|
||||
void arm_cpu_update_vserr(ARMCPU *cpu);
|
||||
|
||||
/**
|
||||
* arm_mmu_idx_el:
|
||||
* @env: The cpu environment
|
||||
@@ -1307,4 +1315,12 @@ int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
|
||||
int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
|
||||
#else
|
||||
void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
|
||||
#endif
|
||||
|
||||
void aa32_max_features(ARMCPU *cpu);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -960,3 +960,46 @@ void HELPER(probe_access)(CPUARMState *env, target_ulong ptr,
|
||||
access_type, mmu_idx, ra);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function corresponds to AArch64.vESBOperation().
|
||||
* Note that the AArch32 version is not functionally different.
|
||||
*/
|
||||
void HELPER(vesb)(CPUARMState *env)
|
||||
{
|
||||
/*
|
||||
* The EL2Enabled() check is done inside arm_hcr_el2_eff,
|
||||
* and will return HCR_EL2.VSE == 0, so nothing happens.
|
||||
*/
|
||||
uint64_t hcr = arm_hcr_el2_eff(env);
|
||||
bool enabled = !(hcr & HCR_TGE) && (hcr & HCR_AMO);
|
||||
bool pending = enabled && (hcr & HCR_VSE);
|
||||
bool masked = (env->daif & PSTATE_A);
|
||||
|
||||
/* If VSE pending and masked, defer the exception. */
|
||||
if (pending && masked) {
|
||||
uint32_t syndrome;
|
||||
|
||||
if (arm_el_is_aa64(env, 1)) {
|
||||
/* Copy across IDS and ISS from VSESR. */
|
||||
syndrome = env->cp15.vsesr_el2 & 0x1ffffff;
|
||||
} else {
|
||||
ARMMMUFaultInfo fi = { .type = ARMFault_AsyncExternal };
|
||||
|
||||
if (extended_addresses_enabled(env)) {
|
||||
syndrome = arm_fi_to_lfsc(&fi);
|
||||
} else {
|
||||
syndrome = arm_fi_to_sfsc(&fi);
|
||||
}
|
||||
/* Copy across AET and ExT from VSESR. */
|
||||
syndrome |= env->cp15.vsesr_el2 & 0xd000;
|
||||
}
|
||||
|
||||
/* Set VDISR_EL2.A along with the syndrome. */
|
||||
env->cp15.vdisr_el2 = syndrome | (1u << 31);
|
||||
|
||||
/* Clear pending virtual SError */
|
||||
env->cp15.hcr_el2 &= ~HCR_VSE;
|
||||
cpu_reset_interrupt(env_cpu(env), CPU_INTERRUPT_VSERR);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user