Merge branch 'master' of gitee.com:src-openeuler/qemu into fix-usb

This commit is contained in:
lijiajie128 2020-08-26 09:30:12 +08:00 committed by Gitee
commit 27947f2b8c
23 changed files with 5226 additions and 2 deletions

View File

@ -1,6 +1,6 @@
Name: qemu Name: qemu
Version: 4.1.0 Version: 4.1.0
Release: 20 Release: 22
Epoch: 2 Epoch: 2
Summary: QEMU is a generic and open source machine emulator and virtualizer Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY License: GPLv2 and BSD and MIT and CC-BY
@ -204,7 +204,29 @@ Patch0191: test-tpm-pass-optional-machine-options-to-swtpm-test.patch
Patch0192: test-tpm-tis-Get-prepared-to-share-tests-between-ISA.patch Patch0192: test-tpm-tis-Get-prepared-to-share-tests-between-ISA.patch
Patch0193: test-tpm-tis-Add-Sysbus-TPM-TIS-device-test.patch Patch0193: test-tpm-tis-Add-Sysbus-TPM-TIS-device-test.patch
Patch0194: build-smt-processor-structure-to-support-smt-topolog.patch Patch0194: build-smt-processor-structure-to-support-smt-topolog.patch
Patch0195: hw-usb-core-fix-buffer-overflow.patch Patch0195: target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch
Patch0196: target-arm-Add-ID_AA64MMFR2_EL1.patch
Patch0197: target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch
Patch0198: target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch
Patch0199: target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch
Patch0200: target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch
Patch0201: target-arm-Stop-assuming-DBGDIDR-always-exists.patch
Patch0202: target-arm-Move-DBGDIDR-into-ARMISARegisters.patch
Patch0203: target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch
Patch0204: target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch
Patch0205: target-arm-Read-debug-related-ID-registers-from-KVM.patch
Patch0206: target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch
Patch0207: target-arm-monitor-query-cpu-model-expansion-crashed.patch
Patch0208: target-arm-convert-isar-regs-to-array.patch
Patch0209: target-arm-parse-cpu-feature-related-options.patch
Patch0210: target-arm-register-CPU-features-for-property.patch
Patch0211: target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch
Patch0212: target-arm-introduce-CPU-feature-dependency-mechanis.patch
Patch0213: target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch
Patch0214: target-arm-Add-CPU-features-to-query-cpu-model-expan.patch
Patch0215: target-arm-Update-ID-fields.patch
Patch0216: target-arm-Add-more-CPU-features.patch
Patch0217: hw-usb-core-fix-buffer-overflow.patch
BuildRequires: flex BuildRequires: flex
BuildRequires: bison BuildRequires: bison
@ -554,6 +576,32 @@ getent passwd qemu >/dev/null || \
* Fri Aug 21 2020 Huawei Technologies Co., Ltd <lijiajie11@huawei.com> * Fri Aug 21 2020 Huawei Technologies Co., Ltd <lijiajie11@huawei.com>
- hw/usb/core.c: fix buffer overflow in do_token_setup function - hw/usb/core.c: fix buffer overflow in do_token_setup function
* Wed Aug 19 2020 Huawei Technologies Co., Ltd <liangpeng10@huawei.com>
- target-arm-convert-isar-regs-to-array.patch
- target-arm-parse-cpu-feature-related-options.patch
- target-arm-register-CPU-features-for-property.patch
- target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch
- target-arm-introduce-CPU-feature-dependency-mechanis.patch
- target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch
- target-arm-Add-CPU-features-to-query-cpu-model-expan.patch
- target-arm-Update-ID-fields.patch
- target-arm-Add-more-CPU-features.patch
* Wed Aug 19 2020 Huawei Technologies Co., Ltd <liangpeng10@huawei.com>
- target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch
- target-arm-Add-ID_AA64MMFR2_EL1.patch
- target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch
- target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch
- target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch
- target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch
- target-arm-Stop-assuming-DBGDIDR-always-exists.patch
- target-arm-Move-DBGDIDR-into-ARMISARegisters.patch
- target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch
- target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch
- target-arm-Read-debug-related-ID-registers-from-KVM.patch
- target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch
- target-arm-monitor-query-cpu-model-expansion-crashed.patch
* Tue Aug 18 2020 Huawei Technologies Co., Ltd <fanhenglong@huawei.com> * Tue Aug 18 2020 Huawei Technologies Co., Ltd <fanhenglong@huawei.com>
- hw/acpi/aml-build.c: build smt processor structure to support smt topology - hw/acpi/aml-build.c: build smt processor structure to support smt topology

View File

@ -0,0 +1,89 @@
From 274d25bdb2df13a26ad6d2a8a06fcc281a22f642 Mon Sep 17 00:00:00 2001
From: Peng Liang <liangpeng10@huawei.com>
Date: Thu, 6 Aug 2020 16:14:58 +0800
Subject: [PATCH 7/9] target/arm: Add CPU features to query-cpu-model-expansion
Add CPU features to the result of query-cpu-model-expansion so that
other applications (such as libvirt) can know the supported CPU
features.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
target/arm/cpu.c | 27 +++++++++++++++++++++++++++
target/arm/cpu.h | 2 ++
target/arm/monitor.c | 2 ++
3 files changed, 31 insertions(+)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index db46afba..dcf9f49e 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -25,6 +25,8 @@
#include "qemu/module.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
+#include "qapi/qmp/qdict.h"
+#include "qom/qom-qobject.h"
#include "cpu.h"
#include "internals.h"
#include "exec/exec-all.h"
@@ -1403,6 +1405,31 @@ static const CPUFeatureDep feature_dependencies[] = {
},
};
+void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features)
+{
+ Object *obj = OBJECT(cpu);
+ const char *name;
+ ObjectProperty *prop;
+ bool is_32bit = !arm_feature(&cpu->env, ARM_FEATURE_AARCH64);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cpu_features); ++i) {
+ if (is_32bit != cpu_features[i].is_32bit) {
+ continue;
+ }
+
+ name = cpu_features[i].name;
+ prop = object_property_find(obj, name, NULL);
+ if (prop) {
+ QObject *value;
+
+ assert(prop->get);
+ value = object_property_get_qobject(obj, name, &error_abort);
+ qdict_put_obj(features, name, value);
+ }
+ }
+}
+
static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 7bb481fb..068c3fa2 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3692,4 +3692,6 @@ static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id)
#define cpu_isar_feature(name, cpu) \
({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
+void arm_cpu_features_to_dict(ARMCPU *cpu, QDict *features);
+
#endif
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index e2b1d117..7c2ff3c0 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -219,6 +219,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
}
}
+ arm_cpu_features_to_dict(ARM_CPU(obj), qdict_out);
+
if (!qdict_size(qdict_out)) {
qobject_unref(qdict_out);
} else {
--
2.25.1

View File

@ -0,0 +1,87 @@
From 3451fb922aa7b0fe532e508ca13d4ab4b3ec75bf Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
Date: Sat, 8 Feb 2020 12:58:13 +0000
Subject: [PATCH 02/13] target/arm: Add ID_AA64MMFR2_EL1
Add definitions for all of the fields, up to ARMv8.5.
Convert the existing RESERVED register to a full register.
Query KVM for the value of the register for the host.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200208125816.14954-18-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/cpu.h | 17 +++++++++++++++++
target/arm/helper.c | 4 ++--
target/arm/kvm64.c | 2 ++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index fe310828..3e65bc50 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -866,6 +866,7 @@ struct ARMCPU {
uint64_t id_aa64pfr1;
uint64_t id_aa64mmfr0;
uint64_t id_aa64mmfr1;
+ uint64_t id_aa64mmfr2;
} isar;
uint32_t midr;
uint32_t revidr;
@@ -1762,6 +1763,22 @@ FIELD(ID_AA64MMFR1, PAN, 20, 4)
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
FIELD(ID_AA64MMFR1, XNX, 28, 4)
+FIELD(ID_AA64MMFR2, CNP, 0, 4)
+FIELD(ID_AA64MMFR2, UAO, 4, 4)
+FIELD(ID_AA64MMFR2, LSM, 8, 4)
+FIELD(ID_AA64MMFR2, IESB, 12, 4)
+FIELD(ID_AA64MMFR2, VARANGE, 16, 4)
+FIELD(ID_AA64MMFR2, CCIDX, 20, 4)
+FIELD(ID_AA64MMFR2, NV, 24, 4)
+FIELD(ID_AA64MMFR2, ST, 28, 4)
+FIELD(ID_AA64MMFR2, AT, 32, 4)
+FIELD(ID_AA64MMFR2, IDS, 36, 4)
+FIELD(ID_AA64MMFR2, FWB, 40, 4)
+FIELD(ID_AA64MMFR2, TTL, 48, 4)
+FIELD(ID_AA64MMFR2, BBM, 52, 4)
+FIELD(ID_AA64MMFR2, EVT, 56, 4)
+FIELD(ID_AA64MMFR2, E0PD, 60, 4)
+
FIELD(ID_DFR0, COPDBG, 0, 4)
FIELD(ID_DFR0, COPSDBG, 4, 4)
FIELD(ID_DFR0, MMAPDBG, 8, 4)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b74c23a9..c50b1ba1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6182,10 +6182,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
.access = PL1_R, .type = ARM_CP_CONST,
.resetvalue = cpu->isar.id_aa64mmfr1 },
- { .name = "ID_AA64MMFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
+ { .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,
- .resetvalue = 0 },
+ .resetvalue = cpu->isar.id_aa64mmfr2 },
{ .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
.access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 4f0bf000..b794108a 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -541,6 +541,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ARM64_SYS_REG(3, 0, 0, 7, 0));
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
ARM64_SYS_REG(3, 0, 0, 7, 1));
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
+ ARM64_SYS_REG(3, 0, 0, 7, 2));
/*
* Note that if AArch32 support is not present in the host,
--
2.25.1

View File

@ -0,0 +1,166 @@
From 515975da851ca9567053bcf0487fde4447dfdc4f Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 14 Feb 2020 17:51:04 +0000
Subject: [PATCH 06/13] target/arm: Add _aa64_ and _any_ versions of pmu_8_1
isar checks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add the 64-bit version of the "is this a v8.1 PMUv3?"
ID register check function, and the _any_ version that
checks for either AArch32 or AArch64 support. We'll use
this in a later commit.
We don't (yet) do any isar_feature checks on ID_AA64DFR1_EL1,
but we move id_aa64dfr1 into the ARMISARegisters struct with
id_aa64dfr0, for consistency.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20200214175116.9164-10-peter.maydell@linaro.org
---
target/arm/cpu.c | 3 ++-
target/arm/cpu.h | 15 +++++++++++++--
target/arm/cpu64.c | 8 ++++----
target/arm/helper.c | 12 +++++++-----
4 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 7e9b85a2..bb2edf4e 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1522,7 +1522,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
cpu);
#endif
} else {
- cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
+ 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);
cpu->pmceid0 = 0;
cpu->pmceid1 = 0;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 2d8d27e8..230130be 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -868,6 +868,8 @@ struct ARMCPU {
uint64_t id_aa64mmfr0;
uint64_t id_aa64mmfr1;
uint64_t id_aa64mmfr2;
+ uint64_t id_aa64dfr0;
+ uint64_t id_aa64dfr1;
} isar;
uint32_t midr;
uint32_t revidr;
@@ -884,8 +886,6 @@ struct ARMCPU {
uint32_t id_mmfr2;
uint32_t id_mmfr3;
uint32_t id_mmfr4;
- uint64_t id_aa64dfr0;
- uint64_t id_aa64dfr1;
uint64_t id_aa64afr0;
uint64_t id_aa64afr1;
uint32_t dbgdidr;
@@ -3657,6 +3657,17 @@ static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
}
+static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 &&
+ FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
+}
+
+static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id)
+{
+ return isar_feature_aa64_pmu_8_1(id) || isar_feature_aa32_pmu_8_1(id);
+}
+
/*
* Forward to the above feature tests given an ARMCPU pointer.
*/
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index afdabbeb..aa96548f 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -137,7 +137,7 @@ static void aarch64_a57_initfn(Object *obj)
cpu->isar.id_isar5 = 0x00011121;
cpu->isar.id_isar6 = 0;
cpu->isar.id_aa64pfr0 = 0x00002222;
- cpu->id_aa64dfr0 = 0x10305106;
+ cpu->isar.id_aa64dfr0 = 0x10305106;
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001124;
cpu->dbgdidr = 0x3516d000;
@@ -191,7 +191,7 @@ static void aarch64_a53_initfn(Object *obj)
cpu->isar.id_isar5 = 0x00011121;
cpu->isar.id_isar6 = 0;
cpu->isar.id_aa64pfr0 = 0x00002222;
- cpu->id_aa64dfr0 = 0x10305106;
+ cpu->isar.id_aa64dfr0 = 0x10305106;
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
cpu->dbgdidr = 0x3516d000;
@@ -244,7 +244,7 @@ static void aarch64_a72_initfn(Object *obj)
cpu->isar.id_isar4 = 0x00011142;
cpu->isar.id_isar5 = 0x00011121;
cpu->isar.id_aa64pfr0 = 0x00002222;
- cpu->id_aa64dfr0 = 0x10305106;
+ cpu->isar.id_aa64dfr0 = 0x10305106;
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001124;
cpu->dbgdidr = 0x3516d000;
@@ -276,7 +276,7 @@ static void aarch64_kunpeng_920_initfn(Object *obj)
cpu->midr = 0x480fd010;
cpu->ctr = 0x84448004;
cpu->isar.id_aa64pfr0 = 0x11001111;
- cpu->id_aa64dfr0 = 0x110305408;
+ cpu->isar.id_aa64dfr0 = 0x110305408;
cpu->isar.id_aa64isar0 = 0x10211120;
cpu->isar.id_aa64mmfr0 = 0x101125;
}
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 3f06ca19..a71f4ef6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -23,6 +23,7 @@
#include "hw/semihosting/semihost.h"
#include "sysemu/cpus.h"
#include "sysemu/kvm.h"
+#include "sysemu/tcg.h"
#include "qemu/range.h"
#include "qapi/qapi-commands-machine-target.h"
#include "qapi/error.h"
@@ -5611,9 +5612,10 @@ static void define_debug_regs(ARMCPU *cpu)
* check that if they both exist then they agree.
*/
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) == ctx_cmps);
+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS)
+ == ctx_cmps);
}
define_one_arm_cp_reg(cpu, &dbgdidr);
@@ -6112,11 +6114,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
{ .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
.access = PL1_R, .type = ARM_CP_CONST,
- .resetvalue = cpu->id_aa64dfr0 },
+ .resetvalue = cpu->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,
- .resetvalue = cpu->id_aa64dfr1 },
+ .resetvalue = cpu->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,
--
2.25.1

View File

@ -0,0 +1,76 @@
From 4001f3040937094660eab44dbb49b86817317ea9 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 14 Feb 2020 17:51:01 +0000
Subject: [PATCH 03/13] target/arm: Add and use FIELD definitions for
ID_AA64DFR0_EL1
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add FIELD() definitions for the ID_AA64DFR0_EL1 and use them
where we currently have hard-coded bit values.
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20200214175116.9164-7-peter.maydell@linaro.org
---
target/arm/cpu.c | 2 +-
target/arm/cpu.h | 10 ++++++++++
target/arm/helper.c | 6 +++---
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 811e5c63..dbd05e01 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1522,7 +1522,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
cpu);
#endif
} else {
- cpu->id_aa64dfr0 &= ~0xf00;
+ cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
cpu->id_dfr0 &= ~(0xf << 24);
cpu->pmceid0 = 0;
cpu->pmceid1 = 0;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 3e65bc50..91cc02b4 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1779,6 +1779,16 @@ FIELD(ID_AA64MMFR2, BBM, 52, 4)
FIELD(ID_AA64MMFR2, EVT, 56, 4)
FIELD(ID_AA64MMFR2, E0PD, 60, 4)
+FIELD(ID_AA64DFR0, DEBUGVER, 0, 4)
+FIELD(ID_AA64DFR0, TRACEVER, 4, 4)
+FIELD(ID_AA64DFR0, PMUVER, 8, 4)
+FIELD(ID_AA64DFR0, BRPS, 12, 4)
+FIELD(ID_AA64DFR0, WRPS, 20, 4)
+FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
+FIELD(ID_AA64DFR0, PMSVER, 32, 4)
+FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
+FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
+
FIELD(ID_DFR0, COPDBG, 0, 4)
FIELD(ID_DFR0, COPSDBG, 4, 4)
FIELD(ID_DFR0, MMAPDBG, 8, 4)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c50b1ba1..419be640 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5611,9 +5611,9 @@ static void define_debug_regs(ARMCPU *cpu)
* check that if they both exist then they agree.
*/
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
- assert(extract32(cpu->id_aa64dfr0, 12, 4) == brps);
- assert(extract32(cpu->id_aa64dfr0, 20, 4) == wrps);
- assert(extract32(cpu->id_aa64dfr0, 28, 4) == ctx_cmps);
+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) == ctx_cmps);
}
define_one_arm_cp_reg(cpu, &dbgdidr);
--
2.25.1

View File

@ -0,0 +1,77 @@
From 6f18e959eabf9c752659eb3851f193bf343346c5 Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
Date: Sat, 8 Feb 2020 12:57:59 +0000
Subject: [PATCH 01/13] target/arm: Add isar_feature tests for PAN + ATS1E1
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Include definitions for all of the bits in ID_MMFR3.
We already have a definition for ID_AA64MMFR1.PAN.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200208125816.14954-4-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/cpu.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 86eb79cd..fe310828 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1680,6 +1680,15 @@ FIELD(ID_ISAR6, FHM, 8, 4)
FIELD(ID_ISAR6, SB, 12, 4)
FIELD(ID_ISAR6, SPECRES, 16, 4)
+FIELD(ID_MMFR3, CMAINTVA, 0, 4)
+FIELD(ID_MMFR3, CMAINTSW, 4, 4)
+FIELD(ID_MMFR3, BPMAINT, 8, 4)
+FIELD(ID_MMFR3, MAINTBCST, 12, 4)
+FIELD(ID_MMFR3, PAN, 16, 4)
+FIELD(ID_MMFR3, COHWALK, 20, 4)
+FIELD(ID_MMFR3, CMEMSZ, 24, 4)
+FIELD(ID_MMFR3, SUPERSEC, 28, 4)
+
FIELD(ID_MMFR4, SPECSEI, 0, 4)
FIELD(ID_MMFR4, AC2, 4, 4)
FIELD(ID_MMFR4, XNX, 8, 4)
@@ -3445,6 +3454,16 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
}
+static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0;
+}
+
+static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
+}
+
/*
* 64-bit feature tests via id registers.
*/
@@ -3589,6 +3608,16 @@ static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
}
+static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0;
+}
+
+static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
+}
+
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
--
2.25.1

View File

@ -0,0 +1,30 @@
From 3eee1e4ff1ca342e760f759c727abc41780d0afa Mon Sep 17 00:00:00 2001
From: Peng Liang <liangpeng10@huawei.com>
Date: Tue, 11 Aug 2020 10:28:10 +0800
Subject: [PATCH 9/9] target/arm: Add more CPU features
Add i8mm, bf16, and dgh CPU features for AArch64.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
target/arm/cpu.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index dcf9f49e..7ae2d3da 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1132,6 +1132,9 @@ static struct CPUFeatureInfo cpu_features[] = {
FIELD_INFO("fhm", ID_ISAR6, FHM, false, 1, 0, true),
FIELD_INFO("sb", ID_ISAR6, SB, false, 1, 0, true),
FIELD_INFO("specres", ID_ISAR6, SPECRES, false, 1, 0, true),
+ FIELD_INFO("i8mm", ID_AA64ISAR1, I8MM, false, 1, 0, false),
+ FIELD_INFO("bf16", ID_AA64ISAR1, BF16, false, 1, 0, false),
+ FIELD_INFO("dgh", ID_AA64ISAR1, DGH, false, 1, 0, false),
FIELD_INFO("cmaintva", ID_MMFR3, CMAINTVA, false, 1, 0, true),
FIELD_INFO("cmaintsw", ID_MMFR3, CMAINTSW, false, 1, 0, true),
--
2.25.1

View File

@ -0,0 +1,160 @@
From 79a60f0eeb56faf5d162ca566d1cd9988c3e4d60 Mon Sep 17 00:00:00 2001
From: Peng Liang <liangpeng10@huawei.com>
Date: Thu, 6 Aug 2020 16:14:40 +0800
Subject: [PATCH 4/9] target/arm: Allow ID registers to synchronize to KVM
There are 2 steps to synchronize the values of system registers from
CPU state to KVM:
1. write to the values of system registers from CPU state to
(index,value) list by write_cpustate_to_list;
2. write the values in (index,value) list to KVM by
write_list_to_kvmstate;
In step 1, the values of constant system registers are not allowed to
write to (index,value) list. However, a constant system register is
CONSTANT for guest but not for QEMU, which means, QEMU can set/modify
the value of constant system registers that is different from phsical
registers when startup. But if KVM is enabled, guest can not read the
values of the system registers which QEMU set unless they can be written
to (index,value) list. And why not try to write to KVM if kvm_sync is
true?
At the moment we call write_cpustate_to_list, all ID registers are
contant, including ID_PFR1_EL1 and ID_AA64PFR0_EL1 because GIC has been
initialized. Hence, let's give all ID registers a chance to write to
KVM. If the write is successful, then write to (index,value) list.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
target/arm/helper.c | 31 ++++++++++++++++++++-----------
target/arm/kvm.c | 38 ++++++++++++++++++++++++++++++++++++++
target/arm/kvm_arm.h | 3 +++
3 files changed, 61 insertions(+), 11 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 459af431..97b6b861 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -32,6 +32,7 @@
#include "arm_ldst.h"
#include "exec/cpu_ldst.h"
#endif
+#include "kvm_arm.h"
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
@@ -267,30 +268,38 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
ok = false;
continue;
}
- if (ri->type & ARM_CP_NO_RAW) {
+ /*
+ * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2),
+ * where 1<=crm<8, 0<=op2<8. Let's give ID registers a chance to
+ * synchronize to kvm.
+ */
+ if ((ri->type & ARM_CP_NO_RAW) && !(kvm_sync &&
+ ri->opc0 == 3 && ri->opc1 == 0 && ri->crn == 0 && ri->crm > 0)) {
continue;
}
newval = read_raw_cp_reg(&cpu->env, ri);
if (kvm_sync) {
- /*
- * Only sync if the previous list->cpustate sync succeeded.
- * Rather than tracking the success/failure state for every
- * item in the list, we just recheck "does the raw write we must
- * have made in write_list_to_cpustate() read back OK" here.
- */
- uint64_t oldval = cpu->cpreg_values[i];
+ /* Only sync if we can sync to KVM successfully. */
+ uint64_t oldval;
+ uint64_t kvmval;
+ if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &oldval)) {
+ continue;
+ }
if (oldval == newval) {
continue;
}
- write_raw_cp_reg(&cpu->env, ri, oldval);
- if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
+ if (kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &newval)) {
+ continue;
+ }
+ if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &kvmval) ||
+ kvmval != newval) {
continue;
}
- write_raw_cp_reg(&cpu->env, ri, newval);
+ kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval);
}
cpu->cpreg_values[i] = newval;
}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 4f131f68..229b17ce 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -457,6 +457,44 @@ out:
return ret;
}
+int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target)
+{
+ uint32_t v32;
+ int ret;
+
+ switch (regidx & KVM_REG_SIZE_MASK) {
+ case KVM_REG_SIZE_U32:
+ ret = kvm_get_one_reg(CPU(cpu), regidx, &v32);
+ if (ret == 0) {
+ *target = v32;
+ }
+ return ret;
+ case KVM_REG_SIZE_U64:
+ return kvm_get_one_reg(CPU(cpu), regidx, target);
+ default:
+ return -1;
+ }
+}
+
+int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source)
+{
+ uint32_t v32;
+
+ switch (regidx & KVM_REG_SIZE_MASK) {
+ case KVM_REG_SIZE_U32:
+ v32 = *source;
+ if (v32 != *source) {
+ error_report("the value of source is too large");
+ return -1;
+ }
+ return kvm_set_one_reg(CPU(cpu), regidx, &v32);
+ case KVM_REG_SIZE_U64:
+ return kvm_set_one_reg(CPU(cpu), regidx, source);
+ default:
+ return -1;
+ }
+}
+
bool write_kvmstate_to_list(ARMCPU *cpu)
{
CPUState *cs = CPU(cpu);
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 0de5f83e..9b7104d6 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -400,4 +400,7 @@ static inline const char *its_class_name(void)
}
}
+int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target);
+int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source);
+
#endif
--
2.25.1

View File

@ -0,0 +1,248 @@
From 2eded1a4deeb5dd8d28414e54948bcf773f6b540 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 14 Feb 2020 17:51:03 +0000
Subject: [PATCH 05/13] target/arm: Define an aa32_pmu_8_1 isar feature test
function
Instead of open-coding a check on the ID_DFR0 PerfMon ID register
field, create a standardly-named isar_feature for "does AArch32 have
a v8.1 PMUv3" and use it.
This entails moving the id_dfr0 field into the ARMISARegisters struct.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20200214175116.9164-9-peter.maydell@linaro.org
---
hw/intc/armv7m_nvic.c | 2 +-
target/arm/cpu.c | 26 +++++++++++++-------------
target/arm/cpu.h | 9 ++++++++-
target/arm/cpu64.c | 6 +++---
target/arm/helper.c | 5 ++---
5 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 9f8f0d3f..0741db7b 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1223,7 +1223,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
case 0xd44: /* PFR1. */
return cpu->id_pfr1;
case 0xd48: /* DFR0. */
- return cpu->id_dfr0;
+ return cpu->isar.id_dfr0;
case 0xd4c: /* AFR0. */
return cpu->id_afr0;
case 0xd50: /* MMFR0. */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 6ad211b1..7e9b85a2 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1523,7 +1523,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
#endif
} else {
cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
- cpu->id_dfr0 = FIELD_DP32(cpu->id_dfr0, ID_DFR0, PERFMON, 0);
+ cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0);
cpu->pmceid0 = 0;
cpu->pmceid1 = 0;
}
@@ -1761,7 +1761,7 @@ static void arm1136_r2_initfn(Object *obj)
cpu->reset_sctlr = 0x00050078;
cpu->id_pfr0 = 0x111;
cpu->id_pfr1 = 0x1;
- cpu->id_dfr0 = 0x2;
+ cpu->isar.id_dfr0 = 0x2;
cpu->id_afr0 = 0x3;
cpu->id_mmfr0 = 0x01130003;
cpu->id_mmfr1 = 0x10030302;
@@ -1793,7 +1793,7 @@ static void arm1136_initfn(Object *obj)
cpu->reset_sctlr = 0x00050078;
cpu->id_pfr0 = 0x111;
cpu->id_pfr1 = 0x1;
- cpu->id_dfr0 = 0x2;
+ cpu->isar.id_dfr0 = 0x2;
cpu->id_afr0 = 0x3;
cpu->id_mmfr0 = 0x01130003;
cpu->id_mmfr1 = 0x10030302;
@@ -1826,7 +1826,7 @@ static void arm1176_initfn(Object *obj)
cpu->reset_sctlr = 0x00050078;
cpu->id_pfr0 = 0x111;
cpu->id_pfr1 = 0x11;
- cpu->id_dfr0 = 0x33;
+ cpu->isar.id_dfr0 = 0x33;
cpu->id_afr0 = 0;
cpu->id_mmfr0 = 0x01130003;
cpu->id_mmfr1 = 0x10030302;
@@ -1856,7 +1856,7 @@ static void arm11mpcore_initfn(Object *obj)
cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */
cpu->id_pfr0 = 0x111;
cpu->id_pfr1 = 0x1;
- cpu->id_dfr0 = 0;
+ cpu->isar.id_dfr0 = 0;
cpu->id_afr0 = 0x2;
cpu->id_mmfr0 = 0x01100103;
cpu->id_mmfr1 = 0x10020302;
@@ -1888,7 +1888,7 @@ static void cortex_m3_initfn(Object *obj)
cpu->pmsav7_dregion = 8;
cpu->id_pfr0 = 0x00000030;
cpu->id_pfr1 = 0x00000200;
- cpu->id_dfr0 = 0x00100000;
+ cpu->isar.id_dfr0 = 0x00100000;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x00000030;
cpu->id_mmfr1 = 0x00000000;
@@ -1919,7 +1919,7 @@ static void cortex_m4_initfn(Object *obj)
cpu->isar.mvfr2 = 0x00000000;
cpu->id_pfr0 = 0x00000030;
cpu->id_pfr1 = 0x00000200;
- cpu->id_dfr0 = 0x00100000;
+ cpu->isar.id_dfr0 = 0x00100000;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x00000030;
cpu->id_mmfr1 = 0x00000000;
@@ -1952,7 +1952,7 @@ static void cortex_m33_initfn(Object *obj)
cpu->isar.mvfr2 = 0x00000040;
cpu->id_pfr0 = 0x00000030;
cpu->id_pfr1 = 0x00000210;
- cpu->id_dfr0 = 0x00200000;
+ cpu->isar.id_dfr0 = 0x00200000;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x00101F40;
cpu->id_mmfr1 = 0x00000000;
@@ -2003,7 +2003,7 @@ static void cortex_r5_initfn(Object *obj)
cpu->midr = 0x411fc153; /* r1p3 */
cpu->id_pfr0 = 0x0131;
cpu->id_pfr1 = 0x001;
- cpu->id_dfr0 = 0x010400;
+ cpu->isar.id_dfr0 = 0x010400;
cpu->id_afr0 = 0x0;
cpu->id_mmfr0 = 0x0210030;
cpu->id_mmfr1 = 0x00000000;
@@ -2058,7 +2058,7 @@ static void cortex_a8_initfn(Object *obj)
cpu->reset_sctlr = 0x00c50078;
cpu->id_pfr0 = 0x1031;
cpu->id_pfr1 = 0x11;
- cpu->id_dfr0 = 0x400;
+ cpu->isar.id_dfr0 = 0x400;
cpu->id_afr0 = 0;
cpu->id_mmfr0 = 0x31100003;
cpu->id_mmfr1 = 0x20000000;
@@ -2131,7 +2131,7 @@ static void cortex_a9_initfn(Object *obj)
cpu->reset_sctlr = 0x00c50078;
cpu->id_pfr0 = 0x1031;
cpu->id_pfr1 = 0x11;
- cpu->id_dfr0 = 0x000;
+ cpu->isar.id_dfr0 = 0x000;
cpu->id_afr0 = 0;
cpu->id_mmfr0 = 0x00100103;
cpu->id_mmfr1 = 0x20000000;
@@ -2196,7 +2196,7 @@ static void cortex_a7_initfn(Object *obj)
cpu->reset_sctlr = 0x00c50078;
cpu->id_pfr0 = 0x00001131;
cpu->id_pfr1 = 0x00011011;
- cpu->id_dfr0 = 0x02010555;
+ cpu->isar.id_dfr0 = 0x02010555;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x10101105;
cpu->id_mmfr1 = 0x40000000;
@@ -2242,7 +2242,7 @@ static void cortex_a15_initfn(Object *obj)
cpu->reset_sctlr = 0x00c50078;
cpu->id_pfr0 = 0x00001131;
cpu->id_pfr1 = 0x00011011;
- cpu->id_dfr0 = 0x02010555;
+ cpu->isar.id_dfr0 = 0x02010555;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x10201105;
cpu->id_mmfr1 = 0x20000000;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 91cc02b4..2d8d27e8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -860,6 +860,7 @@ struct ARMCPU {
uint32_t mvfr0;
uint32_t mvfr1;
uint32_t mvfr2;
+ uint32_t id_dfr0;
uint64_t id_aa64isar0;
uint64_t id_aa64isar1;
uint64_t id_aa64pfr0;
@@ -875,7 +876,6 @@ struct ARMCPU {
uint32_t reset_sctlr;
uint32_t id_pfr0;
uint32_t id_pfr1;
- uint32_t id_dfr0;
uint64_t pmceid0;
uint64_t pmceid1;
uint32_t id_afr0;
@@ -3491,6 +3491,13 @@ static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
}
+static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id)
+{
+ /* 0xf means "non-standard IMPDEF PMU" */
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 &&
+ FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
+}
+
/*
* 64-bit feature tests via id registers.
*/
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 15f4ee92..afdabbeb 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -123,7 +123,7 @@ static void aarch64_a57_initfn(Object *obj)
cpu->reset_sctlr = 0x00c50838;
cpu->id_pfr0 = 0x00000131;
cpu->id_pfr1 = 0x00011011;
- cpu->id_dfr0 = 0x03010066;
+ cpu->isar.id_dfr0 = 0x03010066;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x10101105;
cpu->id_mmfr1 = 0x40000000;
@@ -177,7 +177,7 @@ static void aarch64_a53_initfn(Object *obj)
cpu->reset_sctlr = 0x00c50838;
cpu->id_pfr0 = 0x00000131;
cpu->id_pfr1 = 0x00011011;
- cpu->id_dfr0 = 0x03010066;
+ cpu->isar.id_dfr0 = 0x03010066;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x10101105;
cpu->id_mmfr1 = 0x40000000;
@@ -231,7 +231,7 @@ static void aarch64_a72_initfn(Object *obj)
cpu->reset_sctlr = 0x00c50838;
cpu->id_pfr0 = 0x00000131;
cpu->id_pfr1 = 0x00011011;
- cpu->id_dfr0 = 0x03010066;
+ cpu->isar.id_dfr0 = 0x03010066;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x10201105;
cpu->id_mmfr1 = 0x40000000;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 419be640..3f06ca19 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5907,7 +5907,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
{ .name = "ID_DFR0", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2,
.access = PL1_R, .type = ARM_CP_CONST,
- .resetvalue = cpu->id_dfr0 },
+ .resetvalue = cpu->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,
@@ -6050,8 +6050,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
} else {
define_arm_cp_regs(cpu, not_v7_cp_reginfo);
}
- if (FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) >= 4 &&
- FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) != 0xf) {
+ if (cpu_isar_feature(aa32_pmu_8_1, cpu)) {
ARMCPRegInfo v81_pmu_regs[] = {
{ .name = "PMCEID2", .state = ARM_CP_STATE_AA32,
.cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 4,
--
2.25.1

View File

@ -0,0 +1,57 @@
From 69eedbfc873ded9bf35439b813e9f6a7431dc727 Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
Date: Sat, 8 Feb 2020 12:58:12 +0000
Subject: [PATCH 09/13] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max
This includes enablement of ARMv8.1-PAN.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200208125816.14954-17-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/cpu.c | 4 ++++
target/arm/cpu64.c | 5 +++++
2 files changed, 9 insertions(+)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index a23c71db..119bd275 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2484,6 +2484,10 @@ static void arm_max_initfn(Object *obj)
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
cpu->isar.mvfr2 = t;
+ t = cpu->id_mmfr3;
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
+ cpu->id_mmfr3 = t;
+
t = cpu->id_mmfr4;
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
cpu->id_mmfr4 = t;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 7ad8b5e2..a0d07fd7 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -362,6 +362,7 @@ static void aarch64_max_initfn(Object *obj)
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, PAN, 2); /* ATS1E1 */
cpu->isar.id_aa64mmfr1 = t;
/* Replicate the same data to the 32-bit id registers. */
@@ -382,6 +383,10 @@ static void aarch64_max_initfn(Object *obj)
u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
cpu->isar.id_isar6 = u;
+ u = cpu->id_mmfr3;
+ u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
+ cpu->id_mmfr3 = u;
+
/*
* FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
* so do not set MVFR1.FPHP. Strictly speaking this is not legal,
--
2.25.1

View File

@ -0,0 +1,158 @@
From df641941e6fd7fef78e5c77c9a809a7a8e148589 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 14 Feb 2020 17:51:06 +0000
Subject: [PATCH 08/13] target/arm: Move DBGDIDR into ARMISARegisters
We're going to want to read the DBGDIDR register from KVM in
a subsequent commit, which means it needs to be in the
ARMISARegisters sub-struct. Move it.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200214175116.9164-12-peter.maydell@linaro.org
---
target/arm/cpu.c | 8 ++++----
target/arm/cpu.h | 2 +-
target/arm/cpu64.c | 6 +++---
target/arm/helper.c | 2 +-
target/arm/internals.h | 6 +++---
5 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index bb2edf4e..a23c71db 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2070,7 +2070,7 @@ static void cortex_a8_initfn(Object *obj)
cpu->isar.id_isar2 = 0x21232031;
cpu->isar.id_isar3 = 0x11112131;
cpu->isar.id_isar4 = 0x00111142;
- cpu->dbgdidr = 0x15141000;
+ cpu->isar.dbgdidr = 0x15141000;
cpu->clidr = (1 << 27) | (2 << 24) | 3;
cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
@@ -2143,7 +2143,7 @@ static void cortex_a9_initfn(Object *obj)
cpu->isar.id_isar2 = 0x21232041;
cpu->isar.id_isar3 = 0x11112131;
cpu->isar.id_isar4 = 0x00111142;
- cpu->dbgdidr = 0x35141000;
+ cpu->isar.dbgdidr = 0x35141000;
cpu->clidr = (1 << 27) | (1 << 24) | 3;
cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
@@ -2211,7 +2211,7 @@ static void cortex_a7_initfn(Object *obj)
cpu->isar.id_isar2 = 0x21232041;
cpu->isar.id_isar3 = 0x11112131;
cpu->isar.id_isar4 = 0x10011142;
- cpu->dbgdidr = 0x3515f005;
+ cpu->isar.dbgdidr = 0x3515f005;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
@@ -2254,7 +2254,7 @@ static void cortex_a15_initfn(Object *obj)
cpu->isar.id_isar2 = 0x21232041;
cpu->isar.id_isar3 = 0x11112131;
cpu->isar.id_isar4 = 0x10011142;
- cpu->dbgdidr = 0x3515f021;
+ cpu->isar.dbgdidr = 0x3515f021;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 4b1ae32b..3040aa40 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -861,6 +861,7 @@ struct ARMCPU {
uint32_t mvfr1;
uint32_t mvfr2;
uint32_t id_dfr0;
+ uint32_t dbgdidr;
uint64_t id_aa64isar0;
uint64_t id_aa64isar1;
uint64_t id_aa64pfr0;
@@ -888,7 +889,6 @@ struct ARMCPU {
uint32_t id_mmfr4;
uint64_t id_aa64afr0;
uint64_t id_aa64afr1;
- uint32_t dbgdidr;
uint32_t clidr;
uint64_t mp_affinity; /* MP ID without feature bits */
/* The elements of this array are the CCSIDR values for each cache,
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index aa96548f..7ad8b5e2 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -140,7 +140,7 @@ static void aarch64_a57_initfn(Object *obj)
cpu->isar.id_aa64dfr0 = 0x10305106;
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001124;
- cpu->dbgdidr = 0x3516d000;
+ cpu->isar.dbgdidr = 0x3516d000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
@@ -194,7 +194,7 @@ static void aarch64_a53_initfn(Object *obj)
cpu->isar.id_aa64dfr0 = 0x10305106;
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
- cpu->dbgdidr = 0x3516d000;
+ cpu->isar.dbgdidr = 0x3516d000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */
@@ -247,7 +247,7 @@ static void aarch64_a72_initfn(Object *obj)
cpu->isar.id_aa64dfr0 = 0x10305106;
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001124;
- cpu->dbgdidr = 0x3516d000;
+ cpu->isar.dbgdidr = 0x3516d000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c1ff4b6b..60ff7c0f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5597,7 +5597,7 @@ static void define_debug_regs(ARMCPU *cpu)
ARMCPRegInfo dbgdidr = {
.name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL0_R, .accessfn = access_tda,
- .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr,
+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
};
/* Note that all these register fields hold "number of Xs minus 1". */
diff --git a/target/arm/internals.h b/target/arm/internals.h
index a72d0a6c..1d01ecc4 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -867,7 +867,7 @@ static inline int arm_num_brps(ARMCPU *cpu)
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1;
} else {
- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, BRPS) + 1;
+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1;
}
}
@@ -881,7 +881,7 @@ static inline int arm_num_wrps(ARMCPU *cpu)
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1;
} else {
- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, WRPS) + 1;
+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1;
}
}
@@ -895,7 +895,7 @@ static inline int arm_num_ctx_cmps(ARMCPU *cpu)
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1;
} else {
- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, CTX_CMPS) + 1;
+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1;
}
}
--
2.25.1

View File

@ -0,0 +1,131 @@
From 9cda8af5af9e95e7b0ff683d0fb661c1ffcba8d8 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 14 Feb 2020 17:51:07 +0000
Subject: [PATCH 11/13] target/arm: Read debug-related ID registers from KVM
Now we have isar_feature test functions that look at fields in the
ID_AA64DFR0_EL1 and ID_DFR0 ID registers, add the code that reads
these register values from KVM so that the checks behave correctly
when we're using KVM.
No isar_feature function tests ID_AA64DFR1_EL1 or DBGDIDR yet, but we
add it to maintain the invariant that every field in the
ARMISARegisters struct is populated for a KVM CPU and can be relied
on. This requirement isn't actually written down yet, so add a note
to the relevant comment.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200214175116.9164-13-peter.maydell@linaro.org
---
target/arm/cpu.h | 5 +++++
target/arm/kvm32.c | 8 ++++++++
target/arm/kvm64.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 49 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a78c30c3..56d8cd8c 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -848,6 +848,11 @@ struct ARMCPU {
* prefix means a constant register.
* Some of these registers are split out into a substructure that
* is shared with the translators to control the ISA.
+ *
+ * Note that if you add an ID register to the ARMISARegisters struct
+ * you need to also update the 32-bit and 64-bit versions of the
+ * kvm_arm_get_host_cpu_features() function to correctly populate the
+ * field by reading the value from the KVM vCPU.
*/
struct ARMISARegisters {
uint32_t id_isar0;
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index 2247148e..e984d52d 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -93,6 +93,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ahcf->isar.id_isar6 = 0;
}
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
+ ARM_CP15_REG32(0, 0, 1, 2));
+
err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
KVM_REG_ARM | KVM_REG_SIZE_U32 |
KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0);
@@ -121,6 +124,11 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ahcf->isar.id_mmfr4 = 0;
}
+ /*
+ * There is no way to read DBGDIDR, because currently 32-bit KVM
+ * doesn't implement debug at all. Leave it at zero.
+ */
+
kvm_arm_destroy_scratch_host_vcpu(fdarray);
if (err < 0) {
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 276d1466..2a88b8df 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -533,6 +533,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
} else {
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1,
ARM64_SYS_REG(3, 0, 0, 4, 1));
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0,
+ ARM64_SYS_REG(3, 0, 0, 5, 0));
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1,
+ ARM64_SYS_REG(3, 0, 0, 5, 1));
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0,
ARM64_SYS_REG(3, 0, 0, 6, 0));
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1,
@@ -551,6 +555,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
* than skipping the reads and leaving 0, as we must avoid
* considering the values in every case.
*/
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
+ ARM64_SYS_REG(3, 0, 0, 1, 2));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
ARM64_SYS_REG(3, 0, 0, 1, 4));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
@@ -582,6 +588,36 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ARM64_SYS_REG(3, 0, 0, 3, 1));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2,
ARM64_SYS_REG(3, 0, 0, 3, 2));
+
+ /*
+ * DBGDIDR is a bit complicated because the kernel doesn't
+ * provide an accessor for it in 64-bit mode, which is what this
+ * scratch VM is in, and there's no architected "64-bit sysreg
+ * which reads the same as the 32-bit register" the way there is
+ * for other ID registers. Instead we synthesize a value from the
+ * AArch64 ID_AA64DFR0, the same way the kernel code in
+ * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does.
+ * We only do this if the CPU supports AArch32 at EL1.
+ */
+ if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) {
+ int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS);
+ int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS);
+ int ctx_cmps =
+ FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS);
+ int version = 6; /* ARMv8 debug architecture */
+ bool has_el3 =
+ !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3);
+ uint32_t dbgdidr = 0;
+
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps);
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, BRPS, brps);
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, CTX_CMPS, ctx_cmps);
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, VERSION, version);
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3);
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3);
+ dbgdidr |= (1 << 15); /* RES1 bit */
+ ahcf->isar.dbgdidr = dbgdidr;
+ }
}
kvm_arm_destroy_scratch_host_vcpu(fdarray);
--
2.25.1

View File

@ -0,0 +1,186 @@
From 1d4d4cda9637ec09f8cf30785f68b58cd46815c8 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 14 Feb 2020 17:51:05 +0000
Subject: [PATCH 07/13] target/arm: Stop assuming DBGDIDR always exists
The AArch32 DBGDIDR defines properties like the number of
breakpoints, watchpoints and context-matching comparators. On an
AArch64 CPU, the register may not even exist if AArch32 is not
supported at EL1.
Currently we hard-code use of DBGDIDR to identify the number of
breakpoints etc; this works for all our TCG CPUs, but will break if
we ever add an AArch64-only CPU. We also have an assert() that the
AArch32 and AArch64 registers match, which currently works only by
luck for KVM because we don't populate either of these ID registers
from the KVM vCPU and so they are both zero.
Clean this up so we have functions for finding the number
of breakpoints, watchpoints and context comparators which look
in the appropriate ID register.
This allows us to drop the "check that AArch64 and AArch32 agree
on the number of breakpoints etc" asserts:
* we no longer look at the AArch32 versions unless that's the
right place to be looking
* it's valid to have a CPU (eg AArch64-only) where they don't match
* we shouldn't have been asserting the validity of ID registers
in a codepath used with KVM anyway
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200214175116.9164-11-peter.maydell@linaro.org
---
target/arm/cpu.h | 7 +++++++
target/arm/debug_helper.c | 6 +++---
target/arm/helper.c | 21 +++++---------------
target/arm/internals.h | 42 +++++++++++++++++++++++++++++++++++++++
4 files changed, 57 insertions(+), 19 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 230130be..4b1ae32b 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1798,6 +1798,13 @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
FIELD(ID_DFR0, PERFMON, 24, 4)
FIELD(ID_DFR0, TRACEFILT, 28, 4)
+FIELD(DBGDIDR, SE_IMP, 12, 1)
+FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
+FIELD(DBGDIDR, VERSION, 16, 4)
+FIELD(DBGDIDR, CTX_CMPS, 20, 4)
+FIELD(DBGDIDR, BRPS, 24, 4)
+FIELD(DBGDIDR, WRPS, 28, 4)
+
FIELD(MVFR0, SIMDREG, 0, 4)
FIELD(MVFR0, FPSP, 4, 4)
FIELD(MVFR0, FPDP, 8, 4)
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index dde80273..3f8f667d 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -16,8 +16,8 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
{
CPUARMState *env = &cpu->env;
uint64_t bcr = env->cp15.dbgbcr[lbn];
- int brps = extract32(cpu->dbgdidr, 24, 4);
- int ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
+ int brps = arm_num_brps(cpu);
+ int ctx_cmps = arm_num_ctx_cmps(cpu);
int bt;
uint32_t contextidr;
@@ -28,7 +28,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
* case DBGWCR<n>_EL1.LBN must indicate that breakpoint).
* We choose the former.
*/
- if (lbn > brps || lbn < (brps - ctx_cmps)) {
+ if (lbn >= brps || lbn < (brps - ctx_cmps)) {
return false;
}
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a71f4ef6..c1ff4b6b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5601,23 +5601,12 @@ static void define_debug_regs(ARMCPU *cpu)
};
/* Note that all these register fields hold "number of Xs minus 1". */
- brps = extract32(cpu->dbgdidr, 24, 4);
- wrps = extract32(cpu->dbgdidr, 28, 4);
- ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
+ brps = arm_num_brps(cpu);
+ wrps = arm_num_wrps(cpu);
+ ctx_cmps = arm_num_ctx_cmps(cpu);
assert(ctx_cmps <= brps);
- /* The DBGDIDR and ID_AA64DFR0_EL1 define various properties
- * of the debug registers such as number of breakpoints;
- * check that if they both exist then they agree.
- */
- if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS)
- == ctx_cmps);
- }
-
define_one_arm_cp_reg(cpu, &dbgdidr);
define_arm_cp_regs(cpu, debug_cp_reginfo);
@@ -5625,7 +5614,7 @@ static void define_debug_regs(ARMCPU *cpu)
define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
}
- for (i = 0; i < brps + 1; i++) {
+ for (i = 0; i < brps; i++) {
ARMCPRegInfo dbgregs[] = {
{ .name = "DBGBVR", .state = ARM_CP_STATE_BOTH,
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
@@ -5644,7 +5633,7 @@ static void define_debug_regs(ARMCPU *cpu)
define_arm_cp_regs(cpu, dbgregs);
}
- for (i = 0; i < wrps + 1; i++) {
+ for (i = 0; i < wrps; i++) {
ARMCPRegInfo dbgregs[] = {
{ .name = "DBGWVR", .state = ARM_CP_STATE_BOTH,
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 232d9638..a72d0a6c 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -857,6 +857,48 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
}
}
+/**
+ * arm_num_brps: Return number of implemented breakpoints.
+ * Note that the ID register BRPS field is "number of bps - 1",
+ * and we return the actual number of breakpoints.
+ */
+static inline int arm_num_brps(ARMCPU *cpu)
+{
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1;
+ } else {
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, BRPS) + 1;
+ }
+}
+
+/**
+ * arm_num_wrps: Return number of implemented watchpoints.
+ * Note that the ID register WRPS field is "number of wps - 1",
+ * and we return the actual number of watchpoints.
+ */
+static inline int arm_num_wrps(ARMCPU *cpu)
+{
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1;
+ } else {
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, WRPS) + 1;
+ }
+}
+
+/**
+ * arm_num_ctx_cmps: Return number of implemented context comparators.
+ * Note that the ID register CTX_CMPS field is "number of cmps - 1",
+ * and we return the actual number of comparators.
+ */
+static inline int arm_num_ctx_cmps(ARMCPU *cpu)
+{
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1;
+ } else {
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, CTX_CMPS) + 1;
+ }
+}
+
/* Note make_memop_idx reserves 4 bits for mmu_idx, and MO_BSWAP is bit 3.
* Thus a TCGMemOpIdx, without any MO_ALIGN bits, fits in 8 bits.
*/
--
2.25.1

View File

@ -0,0 +1,453 @@
From 2bc630dc858bd0c010b7c375ebf1e8f4b4e0e346 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 14 Feb 2020 17:51:13 +0000
Subject: [PATCH 10/13] target/arm: Test correct register in aa32_pan and
aa32_ats1e1 checks
The isar_feature_aa32_pan and isar_feature_aa32_ats1e1 functions
are supposed to be testing fields in ID_MMFR3; but a cut-and-paste
error meant we were looking at MVFR0 instead.
Fix the functions to look at the right register; this requires
us to move at least id_mmfr3 to the ARMISARegisters struct; we
choose to move all the ID_MMFRn registers for consistency.
Fixes: 3d6ad6bb466f
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200214175116.9164-19-peter.maydell@linaro.org
---
hw/intc/armv7m_nvic.c | 8 ++--
target/arm/cpu.c | 96 +++++++++++++++++++++----------------------
target/arm/cpu.h | 14 +++----
target/arm/cpu64.c | 28 ++++++-------
target/arm/helper.c | 12 +++---
target/arm/kvm32.c | 17 ++++++++
target/arm/kvm64.c | 10 +++++
7 files changed, 106 insertions(+), 79 deletions(-)
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 0741db7b..f7ef6ad1 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -1227,13 +1227,13 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
case 0xd4c: /* AFR0. */
return cpu->id_afr0;
case 0xd50: /* MMFR0. */
- return cpu->id_mmfr0;
+ return cpu->isar.id_mmfr0;
case 0xd54: /* MMFR1. */
- return cpu->id_mmfr1;
+ return cpu->isar.id_mmfr1;
case 0xd58: /* MMFR2. */
- return cpu->id_mmfr2;
+ return cpu->isar.id_mmfr2;
case 0xd5c: /* MMFR3. */
- return cpu->id_mmfr3;
+ return cpu->isar.id_mmfr3;
case 0xd60: /* ISAR0. */
return cpu->isar.id_isar0;
case 0xd64: /* ISAR1. */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 119bd275..c3728e3d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1764,9 +1764,9 @@ static void arm1136_r2_initfn(Object *obj)
cpu->id_pfr1 = 0x1;
cpu->isar.id_dfr0 = 0x2;
cpu->id_afr0 = 0x3;
- cpu->id_mmfr0 = 0x01130003;
- cpu->id_mmfr1 = 0x10030302;
- cpu->id_mmfr2 = 0x01222110;
+ cpu->isar.id_mmfr0 = 0x01130003;
+ cpu->isar.id_mmfr1 = 0x10030302;
+ cpu->isar.id_mmfr2 = 0x01222110;
cpu->isar.id_isar0 = 0x00140011;
cpu->isar.id_isar1 = 0x12002111;
cpu->isar.id_isar2 = 0x11231111;
@@ -1796,9 +1796,9 @@ static void arm1136_initfn(Object *obj)
cpu->id_pfr1 = 0x1;
cpu->isar.id_dfr0 = 0x2;
cpu->id_afr0 = 0x3;
- cpu->id_mmfr0 = 0x01130003;
- cpu->id_mmfr1 = 0x10030302;
- cpu->id_mmfr2 = 0x01222110;
+ cpu->isar.id_mmfr0 = 0x01130003;
+ cpu->isar.id_mmfr1 = 0x10030302;
+ cpu->isar.id_mmfr2 = 0x01222110;
cpu->isar.id_isar0 = 0x00140011;
cpu->isar.id_isar1 = 0x12002111;
cpu->isar.id_isar2 = 0x11231111;
@@ -1829,9 +1829,9 @@ static void arm1176_initfn(Object *obj)
cpu->id_pfr1 = 0x11;
cpu->isar.id_dfr0 = 0x33;
cpu->id_afr0 = 0;
- cpu->id_mmfr0 = 0x01130003;
- cpu->id_mmfr1 = 0x10030302;
- cpu->id_mmfr2 = 0x01222100;
+ cpu->isar.id_mmfr0 = 0x01130003;
+ cpu->isar.id_mmfr1 = 0x10030302;
+ cpu->isar.id_mmfr2 = 0x01222100;
cpu->isar.id_isar0 = 0x0140011;
cpu->isar.id_isar1 = 0x12002111;
cpu->isar.id_isar2 = 0x11231121;
@@ -1859,9 +1859,9 @@ static void arm11mpcore_initfn(Object *obj)
cpu->id_pfr1 = 0x1;
cpu->isar.id_dfr0 = 0;
cpu->id_afr0 = 0x2;
- cpu->id_mmfr0 = 0x01100103;
- cpu->id_mmfr1 = 0x10020302;
- cpu->id_mmfr2 = 0x01222000;
+ cpu->isar.id_mmfr0 = 0x01100103;
+ cpu->isar.id_mmfr1 = 0x10020302;
+ cpu->isar.id_mmfr2 = 0x01222000;
cpu->isar.id_isar0 = 0x00100011;
cpu->isar.id_isar1 = 0x12002111;
cpu->isar.id_isar2 = 0x11221011;
@@ -1891,10 +1891,10 @@ static void cortex_m3_initfn(Object *obj)
cpu->id_pfr1 = 0x00000200;
cpu->isar.id_dfr0 = 0x00100000;
cpu->id_afr0 = 0x00000000;
- cpu->id_mmfr0 = 0x00000030;
- cpu->id_mmfr1 = 0x00000000;
- cpu->id_mmfr2 = 0x00000000;
- cpu->id_mmfr3 = 0x00000000;
+ cpu->isar.id_mmfr0 = 0x00000030;
+ cpu->isar.id_mmfr1 = 0x00000000;
+ cpu->isar.id_mmfr2 = 0x00000000;
+ cpu->isar.id_mmfr3 = 0x00000000;
cpu->isar.id_isar0 = 0x01141110;
cpu->isar.id_isar1 = 0x02111000;
cpu->isar.id_isar2 = 0x21112231;
@@ -1922,10 +1922,10 @@ static void cortex_m4_initfn(Object *obj)
cpu->id_pfr1 = 0x00000200;
cpu->isar.id_dfr0 = 0x00100000;
cpu->id_afr0 = 0x00000000;
- cpu->id_mmfr0 = 0x00000030;
- cpu->id_mmfr1 = 0x00000000;
- cpu->id_mmfr2 = 0x00000000;
- cpu->id_mmfr3 = 0x00000000;
+ cpu->isar.id_mmfr0 = 0x00000030;
+ cpu->isar.id_mmfr1 = 0x00000000;
+ cpu->isar.id_mmfr2 = 0x00000000;
+ cpu->isar.id_mmfr3 = 0x00000000;
cpu->isar.id_isar0 = 0x01141110;
cpu->isar.id_isar1 = 0x02111000;
cpu->isar.id_isar2 = 0x21112231;
@@ -1955,10 +1955,10 @@ static void cortex_m33_initfn(Object *obj)
cpu->id_pfr1 = 0x00000210;
cpu->isar.id_dfr0 = 0x00200000;
cpu->id_afr0 = 0x00000000;
- cpu->id_mmfr0 = 0x00101F40;
- cpu->id_mmfr1 = 0x00000000;
- cpu->id_mmfr2 = 0x01000000;
- cpu->id_mmfr3 = 0x00000000;
+ cpu->isar.id_mmfr0 = 0x00101F40;
+ cpu->isar.id_mmfr1 = 0x00000000;
+ cpu->isar.id_mmfr2 = 0x01000000;
+ cpu->isar.id_mmfr3 = 0x00000000;
cpu->isar.id_isar0 = 0x01101110;
cpu->isar.id_isar1 = 0x02212000;
cpu->isar.id_isar2 = 0x20232232;
@@ -2006,10 +2006,10 @@ static void cortex_r5_initfn(Object *obj)
cpu->id_pfr1 = 0x001;
cpu->isar.id_dfr0 = 0x010400;
cpu->id_afr0 = 0x0;
- cpu->id_mmfr0 = 0x0210030;
- cpu->id_mmfr1 = 0x00000000;
- cpu->id_mmfr2 = 0x01200000;
- cpu->id_mmfr3 = 0x0211;
+ cpu->isar.id_mmfr0 = 0x0210030;
+ cpu->isar.id_mmfr1 = 0x00000000;
+ cpu->isar.id_mmfr2 = 0x01200000;
+ cpu->isar.id_mmfr3 = 0x0211;
cpu->isar.id_isar0 = 0x02101111;
cpu->isar.id_isar1 = 0x13112111;
cpu->isar.id_isar2 = 0x21232141;
@@ -2061,10 +2061,10 @@ static void cortex_a8_initfn(Object *obj)
cpu->id_pfr1 = 0x11;
cpu->isar.id_dfr0 = 0x400;
cpu->id_afr0 = 0;
- cpu->id_mmfr0 = 0x31100003;
- cpu->id_mmfr1 = 0x20000000;
- cpu->id_mmfr2 = 0x01202000;
- cpu->id_mmfr3 = 0x11;
+ cpu->isar.id_mmfr0 = 0x31100003;
+ cpu->isar.id_mmfr1 = 0x20000000;
+ cpu->isar.id_mmfr2 = 0x01202000;
+ cpu->isar.id_mmfr3 = 0x11;
cpu->isar.id_isar0 = 0x00101111;
cpu->isar.id_isar1 = 0x12112111;
cpu->isar.id_isar2 = 0x21232031;
@@ -2134,10 +2134,10 @@ static void cortex_a9_initfn(Object *obj)
cpu->id_pfr1 = 0x11;
cpu->isar.id_dfr0 = 0x000;
cpu->id_afr0 = 0;
- cpu->id_mmfr0 = 0x00100103;
- cpu->id_mmfr1 = 0x20000000;
- cpu->id_mmfr2 = 0x01230000;
- cpu->id_mmfr3 = 0x00002111;
+ cpu->isar.id_mmfr0 = 0x00100103;
+ cpu->isar.id_mmfr1 = 0x20000000;
+ cpu->isar.id_mmfr2 = 0x01230000;
+ cpu->isar.id_mmfr3 = 0x00002111;
cpu->isar.id_isar0 = 0x00101111;
cpu->isar.id_isar1 = 0x13112111;
cpu->isar.id_isar2 = 0x21232041;
@@ -2199,10 +2199,10 @@ static void cortex_a7_initfn(Object *obj)
cpu->id_pfr1 = 0x00011011;
cpu->isar.id_dfr0 = 0x02010555;
cpu->id_afr0 = 0x00000000;
- cpu->id_mmfr0 = 0x10101105;
- cpu->id_mmfr1 = 0x40000000;
- cpu->id_mmfr2 = 0x01240000;
- cpu->id_mmfr3 = 0x02102211;
+ cpu->isar.id_mmfr0 = 0x10101105;
+ cpu->isar.id_mmfr1 = 0x40000000;
+ cpu->isar.id_mmfr2 = 0x01240000;
+ cpu->isar.id_mmfr3 = 0x02102211;
/* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
* table 4-41 gives 0x02101110, which includes the arm div insns.
*/
@@ -2245,10 +2245,10 @@ static void cortex_a15_initfn(Object *obj)
cpu->id_pfr1 = 0x00011011;
cpu->isar.id_dfr0 = 0x02010555;
cpu->id_afr0 = 0x00000000;
- cpu->id_mmfr0 = 0x10201105;
- cpu->id_mmfr1 = 0x20000000;
- cpu->id_mmfr2 = 0x01240000;
- cpu->id_mmfr3 = 0x02102211;
+ cpu->isar.id_mmfr0 = 0x10201105;
+ cpu->isar.id_mmfr1 = 0x20000000;
+ cpu->isar.id_mmfr2 = 0x01240000;
+ cpu->isar.id_mmfr3 = 0x02102211;
cpu->isar.id_isar0 = 0x02101110;
cpu->isar.id_isar1 = 0x13112111;
cpu->isar.id_isar2 = 0x21232041;
@@ -2484,13 +2484,13 @@ static void arm_max_initfn(Object *obj)
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
cpu->isar.mvfr2 = t;
- t = cpu->id_mmfr3;
+ t = cpu->isar.id_mmfr3;
t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
- cpu->id_mmfr3 = t;
+ cpu->isar.id_mmfr3 = t;
- t = cpu->id_mmfr4;
+ t = cpu->isar.id_mmfr4;
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
- cpu->id_mmfr4 = t;
+ cpu->isar.id_mmfr4 = t;
}
#endif
}
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 3040aa40..a78c30c3 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -857,6 +857,11 @@ struct ARMCPU {
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 mvfr0;
uint32_t mvfr1;
uint32_t mvfr2;
@@ -882,11 +887,6 @@ struct ARMCPU {
uint64_t pmceid0;
uint64_t pmceid1;
uint32_t id_afr0;
- uint32_t id_mmfr0;
- uint32_t id_mmfr1;
- uint32_t id_mmfr2;
- uint32_t id_mmfr3;
- uint32_t id_mmfr4;
uint64_t id_aa64afr0;
uint64_t id_aa64afr1;
uint32_t clidr;
@@ -3490,12 +3490,12 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
{
- return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0;
+ return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0;
}
static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
{
- return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
+ return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2;
}
static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index a0d07fd7..d450b8c8 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -125,10 +125,10 @@ static void aarch64_a57_initfn(Object *obj)
cpu->id_pfr1 = 0x00011011;
cpu->isar.id_dfr0 = 0x03010066;
cpu->id_afr0 = 0x00000000;
- cpu->id_mmfr0 = 0x10101105;
- cpu->id_mmfr1 = 0x40000000;
- cpu->id_mmfr2 = 0x01260000;
- cpu->id_mmfr3 = 0x02102211;
+ 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;
@@ -179,10 +179,10 @@ static void aarch64_a53_initfn(Object *obj)
cpu->id_pfr1 = 0x00011011;
cpu->isar.id_dfr0 = 0x03010066;
cpu->id_afr0 = 0x00000000;
- cpu->id_mmfr0 = 0x10101105;
- cpu->id_mmfr1 = 0x40000000;
- cpu->id_mmfr2 = 0x01260000;
- cpu->id_mmfr3 = 0x02102211;
+ 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;
@@ -233,10 +233,10 @@ static void aarch64_a72_initfn(Object *obj)
cpu->id_pfr1 = 0x00011011;
cpu->isar.id_dfr0 = 0x03010066;
cpu->id_afr0 = 0x00000000;
- cpu->id_mmfr0 = 0x10201105;
- cpu->id_mmfr1 = 0x40000000;
- cpu->id_mmfr2 = 0x01260000;
- cpu->id_mmfr3 = 0x02102211;
+ cpu->isar.id_mmfr0 = 0x10201105;
+ 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;
@@ -383,9 +383,9 @@ static void aarch64_max_initfn(Object *obj)
u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
cpu->isar.id_isar6 = u;
- u = cpu->id_mmfr3;
+ u = cpu->isar.id_mmfr3;
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
- cpu->id_mmfr3 = u;
+ cpu->isar.id_mmfr3 = u;
/*
* FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 60ff7c0f..49cd7a7e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5906,19 +5906,19 @@ void register_cp_regs_for_features(ARMCPU *cpu)
{ .name = "ID_MMFR0", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4,
.access = PL1_R, .type = ARM_CP_CONST,
- .resetvalue = cpu->id_mmfr0 },
+ .resetvalue = cpu->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,
- .resetvalue = cpu->id_mmfr1 },
+ .resetvalue = cpu->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,
- .resetvalue = cpu->id_mmfr2 },
+ .resetvalue = cpu->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,
- .resetvalue = cpu->id_mmfr3 },
+ .resetvalue = cpu->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,
@@ -5946,7 +5946,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
{ .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,
- .resetvalue = cpu->id_mmfr4 },
+ .resetvalue = cpu->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,
@@ -6426,7 +6426,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
define_arm_cp_regs(cpu, vmsa_cp_reginfo);
/* TTCBR2 is introduced with ARMv8.2-A32HPD. */
- if (FIELD_EX32(cpu->id_mmfr4, ID_MMFR4, HPDS) != 0) {
+ if (FIELD_EX32(cpu->isar.id_mmfr4, ID_MMFR4, HPDS) != 0) {
define_one_arm_cp_reg(cpu, &ttbcr2_reginfo);
}
}
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index ee158830..2247148e 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -104,6 +104,23 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
* Fortunately there is not yet anything in there that affects migration.
*/
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
+ ARM_CP15_REG32(0, 0, 1, 4));
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
+ ARM_CP15_REG32(0, 0, 1, 5));
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
+ ARM_CP15_REG32(0, 0, 1, 6));
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
+ ARM_CP15_REG32(0, 0, 1, 7));
+ if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
+ ARM_CP15_REG32(0, 0, 2, 6))) {
+ /*
+ * Older kernels don't support reading ID_MMFR4 (a new in v8
+ * register); assume it's zero.
+ */
+ ahcf->isar.id_mmfr4 = 0;
+ }
+
kvm_arm_destroy_scratch_host_vcpu(fdarray);
if (err < 0) {
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index b794108a..276d1466 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -551,6 +551,14 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
* than skipping the reads and leaving 0, as we must avoid
* considering the values in every case.
*/
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
+ ARM64_SYS_REG(3, 0, 0, 1, 4));
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
+ ARM64_SYS_REG(3, 0, 0, 1, 5));
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
+ ARM64_SYS_REG(3, 0, 0, 1, 6));
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
+ ARM64_SYS_REG(3, 0, 0, 1, 7));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
ARM64_SYS_REG(3, 0, 0, 2, 0));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
@@ -563,6 +571,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ARM64_SYS_REG(3, 0, 0, 2, 4));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
ARM64_SYS_REG(3, 0, 0, 2, 5));
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
+ ARM64_SYS_REG(3, 0, 0, 2, 6));
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
ARM64_SYS_REG(3, 0, 0, 2, 7));
--
2.25.1

View File

@ -0,0 +1,84 @@
From 47c76d73a435884b66ce6417cb853893099be5eb Mon Sep 17 00:00:00 2001
From: Peng Liang <liangpeng10@huawei.com>
Date: Tue, 11 Aug 2020 10:18:57 +0800
Subject: [PATCH 8/9] target/arm: Update ID fields
Update definitions for ID fields, up to ARMv8.6.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
target/arm/cpu.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 068c3fa2..eb875e11 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1691,6 +1691,8 @@ FIELD(ID_ISAR6, DP, 4, 4)
FIELD(ID_ISAR6, FHM, 8, 4)
FIELD(ID_ISAR6, SB, 12, 4)
FIELD(ID_ISAR6, SPECRES, 16, 4)
+FIELD(ID_ISAR6, BF16, 20, 4)
+FIELD(ID_ISAR6, I8MM, 24, 4)
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
@@ -1736,6 +1738,9 @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
FIELD(ID_AA64ISAR1, SB, 36, 4)
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
FIELD(ID_AA64PFR0, EL0, 0, 4)
FIELD(ID_AA64PFR0, EL1, 4, 4)
@@ -1746,11 +1751,18 @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
FIELD(ID_AA64PFR0, GIC, 24, 4)
FIELD(ID_AA64PFR0, RAS, 28, 4)
FIELD(ID_AA64PFR0, SVE, 32, 4)
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
+FIELD(ID_AA64PFR0, AMU, 44, 4)
+FIELD(ID_AA64PFR0, DIT, 44, 4)
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
FIELD(ID_AA64PFR1, BT, 0, 4)
FIELD(ID_AA64PFR1, SBSS, 4, 4)
FIELD(ID_AA64PFR1, MTE, 8, 4)
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
@@ -1764,6 +1776,8 @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
FIELD(ID_AA64MMFR0, EXS, 44, 4)
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
@@ -1773,6 +1787,8 @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
FIELD(ID_AA64MMFR1, PAN, 20, 4)
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
FIELD(ID_AA64MMFR1, XNX, 28, 4)
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
FIELD(ID_AA64MMFR2, CNP, 0, 4)
FIELD(ID_AA64MMFR2, UAO, 4, 4)
@@ -1799,6 +1815,7 @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
+FIELD(ID_AA64DFR0, MUPMU, 48, 4)
FIELD(ID_DFR0, COPDBG, 0, 4)
FIELD(ID_DFR0, COPSDBG, 4, 4)
--
2.25.1

View File

@ -0,0 +1,36 @@
From f54cdca97bf86f5ca1df8471bc229b89797b287e Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 14 Feb 2020 17:51:02 +0000
Subject: [PATCH 04/13] target/arm: Use FIELD macros for clearing ID_DFR0
PERFMON field
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We already define FIELD macros for ID_DFR0, so use them in the
one place where we're doing direct bit value manipulation.
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20200214175116.9164-8-peter.maydell@linaro.org
---
target/arm/cpu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index dbd05e01..6ad211b1 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1523,7 +1523,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
#endif
} else {
cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
- cpu->id_dfr0 &= ~(0xf << 24);
+ cpu->id_dfr0 = FIELD_DP32(cpu->id_dfr0, ID_DFR0, PERFMON, 0);
cpu->pmceid0 = 0;
cpu->pmceid1 = 0;
}
--
2.25.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,184 @@
From da538bb9d1acc22543a2b7b07ae35a62386bf226 Mon Sep 17 00:00:00 2001
From: Peng Liang <liangpeng10@huawei.com>
Date: Thu, 6 Aug 2020 16:14:46 +0800
Subject: [PATCH 5/9] target/arm: introduce CPU feature dependency mechanism
Some CPU features are dependent on other CPU features. For example,
ID_AA64PFR0_EL1.FP field and ID_AA64PFR0_EL1.AdvSIMD must have the same
value, which means FP and ADVSIMD are dependent on each other, FPHP and
ADVSIMDHP are dependent on each other.
This commit introduces a mechanism for CPU feature dependency in
AArch64. We build a directed graph from the CPU feature dependency
relationship, each edge from->to means the `to` CPU feature is dependent
on the `from` CPU feature. And we will automatically enable/disable CPU
feature according to the directed graph.
For example, a, b, and c CPU features are in relationship a->b->c, which
means c is dependent on b and b is dependent on a. If c is enabled by
user, then a and b is enabled automatically. And if a is disabled by
user, then b and c is disabled automatically.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
target/arm/cpu.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 129 insertions(+)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 3f63312c..d5576538 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1306,6 +1306,103 @@ static struct CPUFeatureInfo cpu_features[] = {
},
};
+typedef struct CPUFeatureDep {
+ CPUFeatureInfo from, to;
+} CPUFeatureDep;
+
+static const CPUFeatureDep feature_dependencies[] = {
+ {
+ .from = FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false),
+ .to = FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false),
+ },
+ {
+ .from = FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false),
+ .to = FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false),
+ },
+ {
+ .from = {
+ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH,
+ .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1,
+ .ni_value = 0, .name = "fphp", .is_32bit = false,
+ },
+ .to = {
+ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH,
+ .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1,
+ .ni_value = 0, .name = "asimdhp", .is_32bit = false,
+ },
+ },
+ {
+ .from = {
+ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH,
+ .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1,
+ .ni_value = 0, .name = "asimdhp", .is_32bit = false,
+ },
+ .to = {
+ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH,
+ .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1,
+ .ni_value = 0, .name = "fphp", .is_32bit = false,
+ },
+ },
+ {
+
+ .from = FIELD_INFO("aes", ID_AA64ISAR0, AES, false, 1, 0, false),
+ .to = {
+ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH,
+ .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "pmull", .is_32bit = false,
+ },
+ },
+ {
+
+ .from = FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false),
+ .to = {
+ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
+ .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "sha512", .is_32bit = false,
+ },
+ },
+ {
+ .from = FIELD_INFO("lrcpc", ID_AA64ISAR1, LRCPC, false, 1, 0, false),
+ .to = {
+ .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH,
+ .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "ilrcpc", .is_32bit = false,
+ },
+ },
+ {
+ .from = FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false),
+ .to = FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false),
+ },
+ {
+ .from = FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false),
+ .to = FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false),
+ },
+ {
+ .from = FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false),
+ .to = FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false),
+ },
+ {
+ .from = FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false),
+ .to = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false),
+ },
+ {
+ .from = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false),
+ .to = {
+ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
+ .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "sha512", .is_32bit = false,
+ },
+ },
+ {
+ .from = {
+ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
+ .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "sha512", .is_32bit = false,
+ },
+ .to = FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false),
+ },
+};
+
static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -1342,13 +1439,45 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
}
if (value) {
+ if (object_property_get_bool(obj, feat->name, NULL)) {
+ return;
+ }
isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
feat->shift, feat->length,
feat->min_value);
+ /* Auto enable the features which current feature is dependent on. */
+ for (int i = 0; i < ARRAY_SIZE(feature_dependencies); ++i) {
+ const CPUFeatureDep *d = &feature_dependencies[i];
+ if (strcmp(d->to.name, feat->name) != 0) {
+ continue;
+ }
+
+ object_property_set_bool(obj, true, d->from.name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
} else {
+ if (!object_property_get_bool(obj, feat->name, NULL)) {
+ return;
+ }
isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
feat->shift, feat->length,
feat->ni_value);
+ /* Auto disable the features which are dependent on current feature. */
+ for (int i = 0; i < ARRAY_SIZE(feature_dependencies); ++i) {
+ const CPUFeatureDep *d = &feature_dependencies[i];
+ if (strcmp(d->from.name, feat->name) != 0) {
+ continue;
+ }
+
+ object_property_set_bool(obj, false, d->to.name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
}
}
--
2.25.1

View File

@ -0,0 +1,92 @@
From 7ed595242f52d0654982d41a9c2a63be2bc3378e Mon Sep 17 00:00:00 2001
From: Peng Liang <liangpeng10@huawei.com>
Date: Thu, 6 Aug 2020 16:14:55 +0800
Subject: [PATCH 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE
Introduce KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to set
CPU features in ARM.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
linux-headers/linux/kvm.h | 2 ++
target/arm/cpu.c | 5 +++++
target/arm/kvm64.c | 14 ++++++++++++++
target/arm/kvm_arm.h | 7 +++++++
4 files changed, 28 insertions(+)
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 744e888e..4844edc3 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -995,6 +995,8 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_ARM_PTRAUTH_ADDRESS 171
#define KVM_CAP_ARM_PTRAUTH_GENERIC 172
+#define KVM_CAP_ARM_CPU_FEATURE 555
+
#ifdef KVM_CAP_IRQ_ROUTING
struct kvm_irq_routing_irqchip {
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d5576538..db46afba 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1427,6 +1427,11 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
Error *local_err = NULL;
bool value;
+ if (!kvm_arm_cpu_feature_supported()) {
+ warn_report("KVM doesn't support to set CPU feature in arm. "
+ "Setting to `%s` is ignored.", name);
+ return;
+ }
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 06cf31e8..05345556 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -644,6 +644,20 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
return true;
}
+bool kvm_arm_cpu_feature_supported(void)
+{
+ static bool cpu_feature_initialized;
+ static bool cpu_feature_supported;
+
+ if (!cpu_feature_initialized) {
+ cpu_feature_supported = kvm_check_extension(kvm_state,
+ KVM_CAP_ARM_CPU_FEATURE);
+ cpu_feature_initialized = true;
+ }
+
+ return cpu_feature_supported;
+}
+
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
int kvm_arch_init_vcpu(CPUState *cs)
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 9b7104d6..49e80878 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -239,6 +239,13 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
*/
void kvm_arm_add_vcpu_properties(Object *obj);
+/**
+ * kvm_arm_cpu_feature_supported:
+ *
+ * Returns true if KVM can set CPU features and false otherwise.
+ */
+bool kvm_arm_cpu_feature_supported(void);
+
/**
* kvm_arm_get_max_vm_ipa_size:
* @ms: Machine state handle
--
2.25.1

View File

@ -0,0 +1,373 @@
From c527fa45dd0bb03c7f35b79ff53f127297f96314 Mon Sep 17 00:00:00 2001
From: Andrew Jones <drjones@redhat.com>
Date: Thu, 31 Oct 2019 15:27:26 +0100
Subject: [PATCH 12/13] target/arm/monitor: Introduce
qmp_query_cpu_model_expansion
Add support for the query-cpu-model-expansion QMP command to Arm. We
do this selectively, only exposing CPU properties which represent
optional CPU features which the user may want to enable/disable.
Additionally we restrict the list of queryable cpu models to 'max',
'host', or the current type when KVM is in use. And, finally, we only
implement expansion type 'full', as Arm does not yet have a "base"
CPU type. More details and example queries are described in a new
document (docs/arm-cpu-features.rst).
Note, certainly more features may be added to the list of advertised
features, e.g. 'vfp' and 'neon'. The only requirement is that we can
detect invalid configurations and emit failures at QMP query time.
For 'vfp' and 'neon' this will require some refactoring to share a
validation function between the QMP query and the CPU realize
functions.
Signed-off-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Beata Michalska <beata.michalska@linaro.org>
Message-id: 20191031142734.8590-2-drjones@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
docs/arm-cpu-features.rst | 137 +++++++++++++++++++++++++++++++++++
qapi/machine-target.json | 6 +-
target/arm/monitor.c | 145 ++++++++++++++++++++++++++++++++++++++
3 files changed, 285 insertions(+), 3 deletions(-)
create mode 100644 docs/arm-cpu-features.rst
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
new file mode 100644
index 00000000..c79dcffb
--- /dev/null
+++ b/docs/arm-cpu-features.rst
@@ -0,0 +1,137 @@
+================
+ARM CPU Features
+================
+
+Examples of probing and using ARM CPU features
+
+Introduction
+============
+
+CPU features are optional features that a CPU of supporting type may
+choose to implement or not. In QEMU, optional CPU features have
+corresponding boolean CPU proprieties that, when enabled, indicate
+that the feature is implemented, and, conversely, when disabled,
+indicate that it is not implemented. An example of an ARM CPU feature
+is the Performance Monitoring Unit (PMU). CPU types such as the
+Cortex-A15 and the Cortex-A57, which respectively implement ARM
+architecture reference manuals ARMv7-A and ARMv8-A, may both optionally
+implement PMUs. For example, if a user wants to use a Cortex-A15 without
+a PMU, then the `-cpu` parameter should contain `pmu=off` on the QEMU
+command line, i.e. `-cpu cortex-a15,pmu=off`.
+
+As not all CPU types support all optional CPU features, then whether or
+not a CPU property exists depends on the CPU type. For example, CPUs
+that implement the ARMv8-A architecture reference manual may optionally
+support the AArch32 CPU feature, which may be enabled by disabling the
+`aarch64` CPU property. A CPU type such as the Cortex-A15, which does
+not implement ARMv8-A, will not have the `aarch64` CPU property.
+
+QEMU's support may be limited for some CPU features, only partially
+supporting the feature or only supporting the feature under certain
+configurations. For example, the `aarch64` CPU feature, which, when
+disabled, enables the optional AArch32 CPU feature, is only supported
+when using the KVM accelerator and when running on a host CPU type that
+supports the feature.
+
+CPU Feature Probing
+===================
+
+Determining which CPU features are available and functional for a given
+CPU type is possible with the `query-cpu-model-expansion` QMP command.
+Below are some examples where `scripts/qmp/qmp-shell` (see the top comment
+block in the script for usage) is used to issue the QMP commands.
+
+(1) Determine which CPU features are available for the `max` CPU type
+ (Note, we started QEMU with qemu-system-aarch64, so `max` is
+ implementing the ARMv8-A reference manual in this case)::
+
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max"}
+ { "return": {
+ "model": { "name": "max", "props": {
+ "pmu": true, "aarch64": true
+ }}}}
+
+We see that the `max` CPU type has the `pmu` and `aarch64` CPU features.
+We also see that the CPU features are enabled, as they are all `true`.
+
+(2) Let's try to disable the PMU::
+
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"pmu":false}}
+ { "return": {
+ "model": { "name": "max", "props": {
+ "pmu": false, "aarch64": true
+ }}}}
+
+We see it worked, as `pmu` is now `false`.
+
+(3) Let's try to disable `aarch64`, which enables the AArch32 CPU feature::
+
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"aarch64":false}}
+ {"error": {
+ "class": "GenericError", "desc":
+ "'aarch64' feature cannot be disabled unless KVM is enabled and 32-bit EL1 is supported"
+ }}
+
+It looks like this feature is limited to a configuration we do not
+currently have.
+
+(4) Let's try probing CPU features for the Cortex-A15 CPU type::
+
+ (QEMU) query-cpu-model-expansion type=full model={"name":"cortex-a15"}
+ {"return": {"model": {"name": "cortex-a15", "props": {"pmu": true}}}}
+
+Only the `pmu` CPU feature is available.
+
+A note about CPU feature dependencies
+-------------------------------------
+
+It's possible for features to have dependencies on other features. I.e.
+it may be possible to change one feature at a time without error, but
+when attempting to change all features at once an error could occur
+depending on the order they are processed. It's also possible changing
+all at once doesn't generate an error, because a feature's dependencies
+are satisfied with other features, but the same feature cannot be changed
+independently without error. For these reasons callers should always
+attempt to make their desired changes all at once in order to ensure the
+collection is valid.
+
+A note about CPU models and KVM
+-------------------------------
+
+Named CPU models generally do not work with KVM. There are a few cases
+that do work, e.g. using the named CPU model `cortex-a57` with KVM on a
+seattle host, but mostly if KVM is enabled the `host` CPU type must be
+used. This means the guest is provided all the same CPU features as the
+host CPU type has. And, for this reason, the `host` CPU type should
+enable all CPU features that the host has by default. Indeed it's even
+a bit strange to allow disabling CPU features that the host has when using
+the `host` CPU type, but in the absence of CPU models it's the best we can
+do if we want to launch guests without all the host's CPU features enabled.
+
+Enabling KVM also affects the `query-cpu-model-expansion` QMP command. The
+affect is not only limited to specific features, as pointed out in example
+(3) of "CPU Feature Probing", but also to which CPU types may be expanded.
+When KVM is enabled, only the `max`, `host`, and current CPU type may be
+expanded. This restriction is necessary as it's not possible to know all
+CPU types that may work with KVM, but it does impose a small risk of users
+experiencing unexpected errors. For example on a seattle, as mentioned
+above, the `cortex-a57` CPU type is also valid when KVM is enabled.
+Therefore a user could use the `host` CPU type for the current type, but
+then attempt to query `cortex-a57`, however that query will fail with our
+restrictions. This shouldn't be an issue though as management layers and
+users have been preferring the `host` CPU type for use with KVM for quite
+some time. Additionally, if the KVM-enabled QEMU instance running on a
+seattle host is using the `cortex-a57` CPU type, then querying `cortex-a57`
+will work.
+
+Using CPU Features
+==================
+
+After determining which CPU features are available and supported for a
+given CPU type, then they may be selectively enabled or disabled on the
+QEMU command line with that CPU type::
+
+ $ qemu-system-aarch64 -M virt -cpu max,pmu=off
+
+The example above disables the PMU for the `max` CPU type.
+
diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index 55310a6a..04623224 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -212,7 +212,7 @@
##
{ 'struct': 'CpuModelExpansionInfo',
'data': { 'model': 'CpuModelInfo' },
- 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' }
##
# @query-cpu-model-expansion:
@@ -237,7 +237,7 @@
# query-cpu-model-expansion while using these is not advised.
#
# Some architectures may not support all expansion types. s390x supports
-# "full" and "static".
+# "full" and "static". Arm only supports "full".
#
# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
# not supported, if the model cannot be expanded, if the model contains
@@ -251,7 +251,7 @@
'data': { 'type': 'CpuModelExpansionType',
'model': 'CpuModelInfo' },
'returns': 'CpuModelExpansionInfo',
- 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' }
##
# @CpuDefinitionInfo:
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index 6ec6dd04..560970de 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -23,7 +23,14 @@
#include "qemu/osdep.h"
#include "hw/boards.h"
#include "kvm_arm.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qapi-commands-machine-target.h"
#include "qapi/qapi-commands-misc-target.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/qmp/qdict.h"
+#include "qom/qom-qobject.h"
static GICCapability *gic_cap_new(int version)
{
@@ -82,3 +89,141 @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
return head;
}
+
+/*
+ * These are cpu model features we want to advertise. The order here
+ * matters as this is the order in which qmp_query_cpu_model_expansion
+ * will attempt to set them. If there are dependencies between features,
+ * then the order that considers those dependencies must be used.
+ */
+static const char *cpu_model_advertised_features[] = {
+ "aarch64", "pmu",
+ NULL
+};
+
+CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
+ CpuModelInfo *model,
+ Error **errp)
+{
+ CpuModelExpansionInfo *expansion_info;
+ const QDict *qdict_in = NULL;
+ QDict *qdict_out;
+ ObjectClass *oc;
+ Object *obj;
+ const char *name;
+ int i;
+
+ if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
+ error_setg(errp, "The requested expansion type is not supported");
+ return NULL;
+ }
+
+ if (!kvm_enabled() && !strcmp(model->name, "host")) {
+ error_setg(errp, "The CPU type '%s' requires KVM", model->name);
+ return NULL;
+ }
+
+ oc = cpu_class_by_name(TYPE_ARM_CPU, model->name);
+ if (!oc) {
+ error_setg(errp, "The CPU type '%s' is not a recognized ARM CPU type",
+ model->name);
+ return NULL;
+ }
+
+ if (kvm_enabled()) {
+ const char *cpu_type = current_machine->cpu_type;
+ int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
+ bool supported = false;
+
+ if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
+ /* These are kvmarm's recommended cpu types */
+ supported = true;
+ } else if (strlen(model->name) == len &&
+ !strncmp(model->name, cpu_type, len)) {
+ /* KVM is enabled and we're using this type, so it works. */
+ supported = true;
+ }
+ if (!supported) {
+ error_setg(errp, "We cannot guarantee the CPU type '%s' works "
+ "with KVM on this host", model->name);
+ return NULL;
+ }
+ }
+
+ if (model->props) {
+ qdict_in = qobject_to(QDict, model->props);
+ if (!qdict_in) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
+ return NULL;
+ }
+ }
+
+ obj = object_new(object_class_get_name(oc));
+
+ if (qdict_in) {
+ Visitor *visitor;
+ Error *err = NULL;
+
+ visitor = qobject_input_visitor_new(model->props);
+ visit_start_struct(visitor, NULL, NULL, 0, &err);
+ if (err) {
+ visit_free(visitor);
+ object_unref(obj);
+ error_propagate(errp, err);
+ return NULL;
+ }
+
+ i = 0;
+ while ((name = cpu_model_advertised_features[i++]) != NULL) {
+ if (qdict_get(qdict_in, name)) {
+ object_property_set(obj, visitor, name, &err);
+ if (err) {
+ break;
+ }
+ }
+ }
+
+ if (!err) {
+ visit_check_struct(visitor, &err);
+ }
+ visit_end_struct(visitor, NULL);
+ visit_free(visitor);
+ if (err) {
+ object_unref(obj);
+ error_propagate(errp, err);
+ return NULL;
+ }
+ }
+
+ expansion_info = g_new0(CpuModelExpansionInfo, 1);
+ expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
+ expansion_info->model->name = g_strdup(model->name);
+
+ qdict_out = qdict_new();
+
+ i = 0;
+ while ((name = cpu_model_advertised_features[i++]) != NULL) {
+ ObjectProperty *prop = object_property_find(obj, name, NULL);
+ if (prop) {
+ Error *err = NULL;
+ QObject *value;
+
+ assert(prop->get);
+ value = object_property_get_qobject(obj, name, &err);
+ assert(!err);
+
+ qdict_put_obj(qdict_out, name, value);
+ }
+ }
+
+ if (!qdict_size(qdict_out)) {
+ qobject_unref(qdict_out);
+ } else {
+ expansion_info->model->props = QOBJECT(qdict_out);
+ expansion_info->model->has_props = true;
+ }
+
+ object_unref(obj);
+
+ return expansion_info;
+}
--
2.25.1

View File

@ -0,0 +1,59 @@
From 5d75b922480f3fbefe83b5bb5e241e56a16e1e3e Mon Sep 17 00:00:00 2001
From: Liang Yan <lyan@suse.com>
Date: Fri, 7 Feb 2020 14:04:21 +0000
Subject: [PATCH 13/13] target/arm/monitor: query-cpu-model-expansion crashed
qemu when using machine type none
Commit e19afd566781 mentioned that target-arm only supports queryable
cpu models 'max', 'host', and the current type when KVM is in use.
The logic works well until using machine type none.
For machine type none, cpu_type will be null if cpu option is not
set by command line, strlen(cpu_type) will terminate process.
So We add a check above it.
This won't affect i386 and s390x since they do not use current_cpu.
Signed-off-by: Liang Yan <lyan@suse.com>
Message-id: 20200203134251.12986-1-lyan@suse.com
Reviewed-by: Andrew Jones <drjones@redhat.com>
Tested-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/monitor.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index 560970de..e2b1d117 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -131,17 +131,20 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
}
if (kvm_enabled()) {
- const char *cpu_type = current_machine->cpu_type;
- int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
bool supported = false;
if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
/* These are kvmarm's recommended cpu types */
supported = true;
- } else if (strlen(model->name) == len &&
- !strncmp(model->name, cpu_type, len)) {
- /* KVM is enabled and we're using this type, so it works. */
- supported = true;
+ } else if (current_machine->cpu_type) {
+ const char *cpu_type = current_machine->cpu_type;
+ int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
+
+ if (strlen(model->name) == len &&
+ !strncmp(model->name, cpu_type, len)) {
+ /* KVM is enabled and we're using this type, so it works. */
+ supported = true;
+ }
}
if (!supported) {
error_setg(errp, "We cannot guarantee the CPU type '%s' works "
--
2.25.1

View File

@ -0,0 +1,124 @@
From dca1df05ce3d6b17d03203fc6fd94e23548216c7 Mon Sep 17 00:00:00 2001
From: Peng Liang <liangpeng10@huawei.com>
Date: Thu, 6 Aug 2020 16:14:35 +0800
Subject: [PATCH 2/9] target/arm: parse cpu feature related options
The implementation of CPUClass::parse_features only supports CPU
features in "feature=value" format. However, libvirt maybe send us a
CPU feature string in "+feature/-feature" format. Hence, we need to
override CPUClass::parse_features to support CPU feature string in both
"feature=value" and "+feature/-feature" format.
The logic of AArch64CPUClass::parse_features is similar to that of
X86CPUClass::parse_features.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
target/arm/cpu64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index fe648752..7de20848 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -506,6 +506,88 @@ static void arm_cpu_parse_featurestr(const char *typename, char *features,
}
}
+static void
+cpu_add_feat_as_prop(const char *typename, const char *name, const char *val)
+{
+ GlobalProperty *prop = g_new0(typeof(*prop), 1);
+ prop->driver = typename;
+ prop->property = g_strdup(name);
+ prop->value = g_strdup(val);
+ qdev_prop_register_global(prop);
+}
+
+static gint compare_string(gconstpointer a, gconstpointer b)
+{
+ return g_strcmp0(a, b);
+}
+
+static GList *plus_features, *minus_features;
+
+static void aarch64_cpu_parse_features(const char *typename, char *features,
+ Error **errp)
+{
+ GList *l;
+ char *featurestr; /* Single 'key=value" string being parsed */
+ static bool cpu_globals_initialized;
+
+ if (cpu_globals_initialized) {
+ return;
+ }
+ cpu_globals_initialized = true;
+
+ if (!features) {
+ return;
+ }
+ for (featurestr = strtok(features, ",");
+ featurestr;
+ featurestr = strtok(NULL, ",")) {
+ const char *name;
+ const char *val = NULL;
+ char *eq = NULL;
+
+ /* Compatibility syntax: */
+ if (featurestr[0] == '+') {
+ plus_features = g_list_append(plus_features,
+ g_strdup(featurestr + 1));
+ continue;
+ } else if (featurestr[0] == '-') {
+ minus_features = g_list_append(minus_features,
+ g_strdup(featurestr + 1));
+ continue;
+ }
+
+ eq = strchr(featurestr, '=');
+ name = featurestr;
+ if (eq) {
+ *eq++ = 0;
+ val = eq;
+ } else {
+ error_setg(errp, "Unsupported property format: %s", name);
+ return;
+ }
+
+ if (g_list_find_custom(plus_features, name, compare_string)) {
+ warn_report("Ambiguous CPU model string. "
+ "Don't mix both \"+%s\" and \"%s=%s\"",
+ name, name, val);
+ }
+ if (g_list_find_custom(minus_features, name, compare_string)) {
+ warn_report("Ambiguous CPU model string. "
+ "Don't mix both \"-%s\" and \"%s=%s\"",
+ name, name, val);
+ }
+ cpu_add_feat_as_prop(typename, name, val);
+ }
+
+ for (l = plus_features; l; l = l->next) {
+ cpu_add_feat_as_prop(typename, l->data, "on");
+ }
+
+ for (l = minus_features; l; l = l->next) {
+ cpu_add_feat_as_prop(typename, l->data, "off");
+ }
+}
+
static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
@@ -517,6 +599,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_num_core_regs = 34;
cc->gdb_core_xml_file = "aarch64-core.xml";
cc->gdb_arch_name = aarch64_gdb_arch_name;
+ cc->parse_features = aarch64_cpu_parse_features;
}
static void aarch64_cpu_instance_init(Object *obj)
--
2.25.1

View File

@ -0,0 +1,398 @@
From f169b1f76cad9f727c701df853b05ad5e8d7f927 Mon Sep 17 00:00:00 2001
From: Peng Liang <liangpeng10@huawei.com>
Date: Thu, 6 Aug 2020 16:14:37 +0800
Subject: [PATCH 3/9] target/arm: register CPU features for property
The Arm architecture specifies a number of ID registers that are
characterized as comprising a set of 4-bit ID fields. Each ID field
identifies the presence, and possibly the level of support for, a
particular feature in an implementation of the architecture. [1]
For most of the ID fields, there is a minimum presence value, equal to
or higher than which means the corresponding CPU feature is implemented.
Hence, we can use the minimum presence value to determine whether a CPU
feature is enabled and enable a CPU feature.
To disable a CPU feature, setting the corresponding ID field to 0x0/0xf
(for unsigned/signed field) seems as a good idea. However, it maybe
lead to some problems. For example, ID_AA64PFR0_EL1.FP is a signed ID
field. ID_AA64PFR0_EL1.FP == 0x0 represents the implementation of FP
(floating-point) and ID_AA64PFR0_EL1.FP == 0x1 represents the
implementation of FPHP (half-precision floating-point). If
ID_AA64PFR0_EL1.FP is set to 0xf when FPHP is disabled (which is also
disable FP), guest kernel maybe stuck. Hence, we add a ni_value (means
not-implemented value) to disable a CPU feature safely.
[1] D13.1.3 Principles of the ID scheme for fields in ID registers in
DDI.0487
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
---
target/arm/cpu.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 343 insertions(+)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5bcdad0c..3f63312c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1034,6 +1034,347 @@ static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name,
visit_type_uint32(v, name, &cpu->init_svtor, errp);
}
+/**
+ * CPUFeatureInfo:
+ * @reg: The ID register where the ID field is in.
+ * @name: The name of the CPU feature.
+ * @length: The bit length of the ID field.
+ * @shift: The bit shift of the ID field in the ID register.
+ * @min_value: The minimum value equal to or larger than which means the CPU
+ * feature is implemented.
+ * @ni_value: Not-implemented value. It will be set to the ID field when
+ * disabling the CPU feature. Usually, it's min_value - 1.
+ * @sign: Whether the ID field is signed.
+ * @is_32bit: Whether the CPU feature is for 32-bit.
+ *
+ * In ARM, a CPU feature is described by an ID field, which is a 4-bit field in
+ * an ID register.
+ */
+typedef struct CPUFeatureInfo {
+ CPUIDReg reg;
+ const char *name;
+ int length;
+ int shift;
+ int min_value;
+ int ni_value;
+ bool sign;
+ bool is_32bit;
+} CPUFeatureInfo;
+
+#define FIELD_INFO(feature_name, id_reg, field, s, min_val, ni_val, is32bit) { \
+ .reg = id_reg, \
+ .length = R_ ## id_reg ## _ ## field ## _LENGTH, \
+ .shift = R_ ## id_reg ## _ ## field ## _SHIFT, \
+ .sign = s, \
+ .min_value = min_val, \
+ .ni_value = ni_val, \
+ .name = feature_name, \
+ .is_32bit = is32bit, \
+}
+
+static struct CPUFeatureInfo cpu_features[] = {
+ FIELD_INFO("swap", ID_ISAR0, SWAP, false, 1, 0, true),
+ FIELD_INFO("bitcount", ID_ISAR0, BITCOUNT, false, 1, 0, true),
+ FIELD_INFO("bitfield", ID_ISAR0, BITFIELD, false, 1, 0, true),
+ FIELD_INFO("cmpbranch", ID_ISAR0, CMPBRANCH, false, 1, 0, true),
+ FIELD_INFO("coproc", ID_ISAR0, COPROC, false, 1, 0, true),
+ FIELD_INFO("debug", ID_ISAR0, DEBUG, false, 1, 0, true),
+ FIELD_INFO("device", ID_ISAR0, DIVIDE, false, 1, 0, true),
+
+ FIELD_INFO("endian", ID_ISAR1, ENDIAN, false, 1, 0, true),
+ FIELD_INFO("except", ID_ISAR1, EXCEPT, false, 1, 0, true),
+ FIELD_INFO("except_ar", ID_ISAR1, EXCEPT_AR, false, 1, 0, true),
+ FIELD_INFO("extend", ID_ISAR1, EXTEND, false, 1, 0, true),
+ FIELD_INFO("ifthen", ID_ISAR1, IFTHEN, false, 1, 0, true),
+ FIELD_INFO("immediate", ID_ISAR1, IMMEDIATE, false, 1, 0, true),
+ FIELD_INFO("interwork", ID_ISAR1, INTERWORK, false, 1, 0, true),
+ FIELD_INFO("jazelle", ID_ISAR1, JAZELLE, false, 1, 0, true),
+
+ FIELD_INFO("loadstore", ID_ISAR2, LOADSTORE, false, 1, 0, true),
+ FIELD_INFO("memhint", ID_ISAR2, MEMHINT, false, 1, 0, true),
+ FIELD_INFO("multiaccessint", ID_ISAR2, MULTIACCESSINT, false, 1, 0, true),
+ FIELD_INFO("mult", ID_ISAR2, MULT, false, 1, 0, true),
+ FIELD_INFO("mults", ID_ISAR2, MULTS, false, 1, 0, true),
+ FIELD_INFO("multu", ID_ISAR2, MULTU, false, 1, 0, true),
+ FIELD_INFO("psr_ar", ID_ISAR2, PSR_AR, false, 1, 0, true),
+ FIELD_INFO("reversal", ID_ISAR2, REVERSAL, false, 1, 0, true),
+
+ FIELD_INFO("saturate", ID_ISAR3, SATURATE, false, 1, 0, true),
+ FIELD_INFO("simd", ID_ISAR3, SIMD, false, 1, 0, true),
+ FIELD_INFO("svc", ID_ISAR3, SVC, false, 1, 0, true),
+ FIELD_INFO("synchprim", ID_ISAR3, SYNCHPRIM, false, 1, 0, true),
+ FIELD_INFO("tabbranch", ID_ISAR3, TABBRANCH, false, 1, 0, true),
+ FIELD_INFO("t32copy", ID_ISAR3, T32COPY, false, 1, 0, true),
+ FIELD_INFO("truenop", ID_ISAR3, TRUENOP, false, 1, 0, true),
+ FIELD_INFO("t32ee", ID_ISAR3, T32EE, false, 1, 0, true),
+
+ FIELD_INFO("unpriv", ID_ISAR4, UNPRIV, false, 1, 0, true),
+ FIELD_INFO("withshifts", ID_ISAR4, WITHSHIFTS, false, 1, 0, true),
+ FIELD_INFO("writeback", ID_ISAR4, WRITEBACK, false, 1, 0, true),
+ FIELD_INFO("smc", ID_ISAR4, SMC, false, 1, 0, true),
+ FIELD_INFO("barrier", ID_ISAR4, BARRIER, false, 1, 0, true),
+ FIELD_INFO("synchprim_frac", ID_ISAR4, SYNCHPRIM_FRAC, false, 1, 0, true),
+ FIELD_INFO("psr_m", ID_ISAR4, PSR_M, false, 1, 0, true),
+ FIELD_INFO("swp_frac", ID_ISAR4, SWP_FRAC, false, 1, 0, true),
+
+ FIELD_INFO("sevl", ID_ISAR5, SEVL, false, 1, 0, true),
+ FIELD_INFO("aes", ID_ISAR5, AES, false, 1, 0, true),
+ FIELD_INFO("sha1", ID_ISAR5, SHA1, false, 1, 0, true),
+ FIELD_INFO("sha2", ID_ISAR5, SHA2, false, 1, 0, true),
+ FIELD_INFO("crc32", ID_ISAR5, CRC32, false, 1, 0, true),
+ FIELD_INFO("rdm", ID_ISAR5, RDM, false, 1, 0, true),
+ FIELD_INFO("vcma", ID_ISAR5, VCMA, false, 1, 0, true),
+
+ FIELD_INFO("jscvt", ID_ISAR6, JSCVT, false, 1, 0, true),
+ FIELD_INFO("dp", ID_ISAR6, DP, false, 1, 0, true),
+ FIELD_INFO("fhm", ID_ISAR6, FHM, false, 1, 0, true),
+ FIELD_INFO("sb", ID_ISAR6, SB, false, 1, 0, true),
+ FIELD_INFO("specres", ID_ISAR6, SPECRES, false, 1, 0, true),
+
+ FIELD_INFO("cmaintva", ID_MMFR3, CMAINTVA, false, 1, 0, true),
+ FIELD_INFO("cmaintsw", ID_MMFR3, CMAINTSW, false, 1, 0, true),
+ FIELD_INFO("bpmaint", ID_MMFR3, BPMAINT, false, 1, 0, true),
+ FIELD_INFO("maintbcst", ID_MMFR3, MAINTBCST, false, 1, 0, true),
+ FIELD_INFO("pan", ID_MMFR3, PAN, false, 1, 0, true),
+ FIELD_INFO("cohwalk", ID_MMFR3, COHWALK, false, 1, 0, true),
+ FIELD_INFO("cmemsz", ID_MMFR3, CMEMSZ, false, 1, 0, true),
+ FIELD_INFO("supersec", ID_MMFR3, SUPERSEC, false, 1, 0, true),
+
+ FIELD_INFO("specsei", ID_MMFR4, SPECSEI, false, 1, 0, true),
+ FIELD_INFO("ac2", ID_MMFR4, AC2, false, 1, 0, true),
+ FIELD_INFO("xnx", ID_MMFR4, XNX, false, 1, 0, true),
+ FIELD_INFO("cnp", ID_MMFR4, CNP, false, 1, 0, true),
+ FIELD_INFO("hpds", ID_MMFR4, HPDS, false, 1, 0, true),
+ FIELD_INFO("lsm", ID_MMFR4, LSM, false, 1, 0, true),
+ FIELD_INFO("ccidx", ID_MMFR4, CCIDX, false, 1, 0, true),
+ FIELD_INFO("evt", ID_MMFR4, EVT, false, 1, 0, true),
+
+ FIELD_INFO("simdreg", MVFR0, SIMDREG, false, 1, 0, true),
+ FIELD_INFO("fpsp", MVFR0, FPSP, false, 1, 0, true),
+ FIELD_INFO("fpdp", MVFR0, FPDP, false, 1, 0, true),
+ FIELD_INFO("fptrap", MVFR0, FPTRAP, false, 1, 0, true),
+ FIELD_INFO("fpdivide", MVFR0, FPDIVIDE, false, 1, 0, true),
+ FIELD_INFO("fpsqrt", MVFR0, FPSQRT, false, 1, 0, true),
+ FIELD_INFO("fpshvec", MVFR0, FPSHVEC, false, 1, 0, true),
+ FIELD_INFO("fpround", MVFR0, FPROUND, false, 1, 0, true),
+
+ FIELD_INFO("fpftz", MVFR1, FPFTZ, false, 1, 0, true),
+ FIELD_INFO("fpdnan", MVFR1, FPDNAN, false, 1, 0, true),
+ FIELD_INFO("simdls", MVFR1, SIMDLS, false, 1, 0, true),
+ FIELD_INFO("simdint", MVFR1, SIMDINT, false, 1, 0, true),
+ FIELD_INFO("simdsp", MVFR1, SIMDSP, false, 1, 0, true),
+ FIELD_INFO("simdhp", MVFR1, SIMDHP, false, 1, 0, true),
+ FIELD_INFO("fphp", MVFR1, FPHP, false, 1, 0, true),
+ FIELD_INFO("simdfmac", MVFR1, SIMDFMAC, false, 1, 0, true),
+
+ FIELD_INFO("simdmisc", MVFR2, SIMDMISC, false, 1, 0, true),
+ FIELD_INFO("fpmisc", MVFR2, FPMISC, false, 1, 0, true),
+
+ FIELD_INFO("debugver", ID_AA64DFR0, DEBUGVER, false, 1, 0, false),
+ FIELD_INFO("tracever", ID_AA64DFR0, TRACEVER, false, 1, 0, false),
+ FIELD_INFO("pmuver", ID_AA64DFR0, PMUVER, false, 1, 0, false),
+ FIELD_INFO("brps", ID_AA64DFR0, BRPS, false, 1, 0, false),
+ FIELD_INFO("wrps", ID_AA64DFR0, WRPS, false, 1, 0, false),
+ FIELD_INFO("ctx_cmps", ID_AA64DFR0, CTX_CMPS, false, 1, 0, false),
+ FIELD_INFO("pmsver", ID_AA64DFR0, PMSVER, false, 1, 0, false),
+ FIELD_INFO("doublelock", ID_AA64DFR0, DOUBLELOCK, false, 1, 0, false),
+ FIELD_INFO("tracefilt", ID_AA64DFR0, TRACEFILT, false, 1, 0, false),
+
+ FIELD_INFO("aes", ID_AA64ISAR0, AES, false, 1, 0, false),
+ FIELD_INFO("sha1", ID_AA64ISAR0, SHA1, false, 1, 0, false),
+ FIELD_INFO("sha2", ID_AA64ISAR0, SHA2, false, 1, 0, false),
+ FIELD_INFO("crc32", ID_AA64ISAR0, CRC32, false, 1, 0, false),
+ FIELD_INFO("atomics", ID_AA64ISAR0, ATOMIC, false, 1, 0, false),
+ FIELD_INFO("asimdrdm", ID_AA64ISAR0, RDM, false, 1, 0, false),
+ FIELD_INFO("sha3", ID_AA64ISAR0, SHA3, false, 1, 0, false),
+ FIELD_INFO("sm3", ID_AA64ISAR0, SM3, false, 1, 0, false),
+ FIELD_INFO("sm4", ID_AA64ISAR0, SM4, false, 1, 0, false),
+ FIELD_INFO("asimddp", ID_AA64ISAR0, DP, false, 1, 0, false),
+ FIELD_INFO("asimdfhm", ID_AA64ISAR0, FHM, false, 1, 0, false),
+ FIELD_INFO("flagm", ID_AA64ISAR0, TS, false, 1, 0, false),
+ FIELD_INFO("tlb", ID_AA64ISAR0, TLB, false, 1, 0, false),
+ FIELD_INFO("rng", ID_AA64ISAR0, RNDR, false, 1, 0, false),
+
+ FIELD_INFO("dcpop", ID_AA64ISAR1, DPB, false, 1, 0, false),
+ FIELD_INFO("papa", ID_AA64ISAR1, APA, false, 1, 0, false),
+ FIELD_INFO("api", ID_AA64ISAR1, API, false, 1, 0, false),
+ FIELD_INFO("jscvt", ID_AA64ISAR1, JSCVT, false, 1, 0, false),
+ FIELD_INFO("fcma", ID_AA64ISAR1, FCMA, false, 1, 0, false),
+ FIELD_INFO("lrcpc", ID_AA64ISAR1, LRCPC, false, 1, 0, false),
+ FIELD_INFO("pacg", ID_AA64ISAR1, GPA, false, 1, 0, false),
+ FIELD_INFO("gpi", ID_AA64ISAR1, GPI, false, 1, 0, false),
+ FIELD_INFO("frint", ID_AA64ISAR1, FRINTTS, false, 1, 0, false),
+ FIELD_INFO("sb", ID_AA64ISAR1, SB, false, 1, 0, false),
+ FIELD_INFO("specres", ID_AA64ISAR1, SPECRES, false, 1, 0, false),
+
+ FIELD_INFO("el0", ID_AA64PFR0, EL0, false, 1, 0, false),
+ FIELD_INFO("el1", ID_AA64PFR0, EL1, false, 1, 0, false),
+ FIELD_INFO("el2", ID_AA64PFR0, EL2, false, 1, 0, false),
+ FIELD_INFO("el3", ID_AA64PFR0, EL3, false, 1, 0, false),
+ FIELD_INFO("fp", ID_AA64PFR0, FP, true, 0, 0xf, false),
+ FIELD_INFO("asimd", ID_AA64PFR0, ADVSIMD, true, 0, 0xf, false),
+ FIELD_INFO("gic", ID_AA64PFR0, GIC, false, 1, 0, false),
+ FIELD_INFO("ras", ID_AA64PFR0, RAS, false, 1, 0, false),
+ FIELD_INFO("sve", ID_AA64PFR0, SVE, false, 1, 0, false),
+
+ FIELD_INFO("bti", ID_AA64PFR1, BT, false, 1, 0, false),
+ FIELD_INFO("sbss", ID_AA64PFR1, SBSS, false, 1, 0, false),
+ FIELD_INFO("mte", ID_AA64PFR1, MTE, false, 1, 0, false),
+ FIELD_INFO("ras_frac", ID_AA64PFR1, RAS_FRAC, false, 1, 0, false),
+
+ FIELD_INFO("parange", ID_AA64MMFR0, PARANGE, false, 1, 0, false),
+ FIELD_INFO("asidbits", ID_AA64MMFR0, ASIDBITS, false, 1, 0, false),
+ FIELD_INFO("bigend", ID_AA64MMFR0, BIGEND, false, 1, 0, false),
+ FIELD_INFO("snsmem", ID_AA64MMFR0, SNSMEM, false, 1, 0, false),
+ FIELD_INFO("bigendel0", ID_AA64MMFR0, BIGENDEL0, false, 1, 0, false),
+ FIELD_INFO("tgran16", ID_AA64MMFR0, TGRAN16, false, 1, 0, false),
+ FIELD_INFO("tgran64", ID_AA64MMFR0, TGRAN64, false, 1, 0, false),
+ FIELD_INFO("tgran4", ID_AA64MMFR0, TGRAN4, false, 1, 0, false),
+ FIELD_INFO("tgran16_2", ID_AA64MMFR0, TGRAN16_2, false, 1, 0, false),
+ FIELD_INFO("tgran64_2", ID_AA64MMFR0, TGRAN64_2, false, 1, 0, false),
+ FIELD_INFO("tgran4_2", ID_AA64MMFR0, TGRAN4_2, false, 1, 0, false),
+ FIELD_INFO("exs", ID_AA64MMFR0, EXS, false, 1, 0, false),
+
+ FIELD_INFO("hafdbs", ID_AA64MMFR1, HAFDBS, false, 1, 0, false),
+ FIELD_INFO("vmidbits", ID_AA64MMFR1, VMIDBITS, false, 1, 0, false),
+ FIELD_INFO("vh", ID_AA64MMFR1, VH, false, 1, 0, false),
+ FIELD_INFO("hpds", ID_AA64MMFR1, HPDS, false, 1, 0, false),
+ FIELD_INFO("lo", ID_AA64MMFR1, LO, false, 1, 0, false),
+ FIELD_INFO("pan", ID_AA64MMFR1, PAN, false, 1, 0, false),
+ FIELD_INFO("specsei", ID_AA64MMFR1, SPECSEI, false, 1, 0, false),
+ FIELD_INFO("xnx", ID_AA64MMFR1, XNX, false, 1, 0, false),
+
+ FIELD_INFO("cnp", ID_AA64MMFR2, CNP, false, 1, 0, false),
+ FIELD_INFO("uao", ID_AA64MMFR2, UAO, false, 1, 0, false),
+ FIELD_INFO("lsm", ID_AA64MMFR2, LSM, false, 1, 0, false),
+ FIELD_INFO("iesb", ID_AA64MMFR2, IESB, false, 1, 0, false),
+ FIELD_INFO("varange", ID_AA64MMFR2, VARANGE, false, 1, 0, false),
+ FIELD_INFO("ccidx", ID_AA64MMFR2, CCIDX, false, 1, 0, false),
+ FIELD_INFO("nv", ID_AA64MMFR2, NV, false, 1, 0, false),
+ FIELD_INFO("st", ID_AA64MMFR2, ST, false, 1, 0, false),
+ FIELD_INFO("uscat", ID_AA64MMFR2, AT, false, 1, 0, false),
+ FIELD_INFO("ids", ID_AA64MMFR2, IDS, false, 1, 0, false),
+ FIELD_INFO("fwb", ID_AA64MMFR2, FWB, false, 1, 0, false),
+ FIELD_INFO("ttl", ID_AA64MMFR2, TTL, false, 1, 0, false),
+ FIELD_INFO("bbm", ID_AA64MMFR2, BBM, false, 1, 0, false),
+ FIELD_INFO("evt", ID_AA64MMFR2, EVT, false, 1, 0, false),
+ FIELD_INFO("e0pd", ID_AA64MMFR2, E0PD, false, 1, 0, false),
+
+ FIELD_INFO("copdbg", ID_DFR0, COPDBG, false, 1, 0, false),
+ FIELD_INFO("copsdbg", ID_DFR0, COPSDBG, false, 1, 0, false),
+ FIELD_INFO("mmapdbg", ID_DFR0, MMAPDBG, false, 1, 0, false),
+ FIELD_INFO("coptrc", ID_DFR0, COPTRC, false, 1, 0, false),
+ FIELD_INFO("mmaptrc", ID_DFR0, MMAPTRC, false, 1, 0, false),
+ FIELD_INFO("mprofdbg", ID_DFR0, MPROFDBG, false, 1, 0, false),
+ FIELD_INFO("perfmon", ID_DFR0, PERFMON, false, 1, 0, false),
+ FIELD_INFO("tracefilt", ID_DFR0, TRACEFILT, false, 1, 0, false),
+
+ {
+ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_FP_LENGTH,
+ .shift = R_ID_AA64PFR0_FP_SHIFT, .sign = true, .min_value = 1,
+ .ni_value = 0, .name = "fphp", .is_32bit = false,
+ },
+ {
+ .reg = ID_AA64PFR0, .length = R_ID_AA64PFR0_ADVSIMD_LENGTH,
+ .shift = R_ID_AA64PFR0_ADVSIMD_SHIFT, .sign = true, .min_value = 1,
+ .ni_value = 0, .name = "asimdhp", .is_32bit = false,
+ },
+ {
+ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_AES_LENGTH,
+ .shift = R_ID_AA64ISAR0_AES_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "pmull", .is_32bit = false,
+ },
+ {
+ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_SHA2_LENGTH,
+ .shift = R_ID_AA64ISAR0_SHA2_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "sha512", .is_32bit = false,
+ },
+ {
+ .reg = ID_AA64ISAR0, .length = R_ID_AA64ISAR0_TS_LENGTH,
+ .shift = R_ID_AA64ISAR0_TS_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "flagm2", .is_32bit = false,
+ },
+ {
+ .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_DPB_LENGTH,
+ .shift = R_ID_AA64ISAR1_DPB_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "dcpodp", .is_32bit = false,
+ },
+ {
+ .reg = ID_AA64ISAR1, .length = R_ID_AA64ISAR1_LRCPC_LENGTH,
+ .shift = R_ID_AA64ISAR1_LRCPC_SHIFT, .sign = false, .min_value = 2,
+ .ni_value = 1, .name = "ilrcpc", .is_32bit = false,
+ },
+};
+
+static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ CPUFeatureInfo *feat = opaque;
+ int field_value = feat->sign ? sextract64(cpu->isar.regs[feat->reg],
+ feat->shift, feat->length) :
+ extract64(cpu->isar.regs[feat->reg],
+ feat->shift, feat->length);
+ bool value = field_value >= feat->min_value;
+
+ visit_type_bool(v, name, &value, errp);
+}
+
+static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ ARMCPU *cpu = ARM_CPU(obj);
+ ARMISARegisters *isar = &cpu->isar;
+ CPUFeatureInfo *feat = opaque;
+ Error *local_err = NULL;
+ bool value;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ visit_type_bool(v, name, &value, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ if (value) {
+ isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
+ feat->shift, feat->length,
+ feat->min_value);
+ } else {
+ isar->regs[feat->reg] = deposit64(isar->regs[feat->reg],
+ feat->shift, feat->length,
+ feat->ni_value);
+ }
+}
+
+static void arm_cpu_register_feature_props(ARMCPU *cpu)
+{
+ int i;
+ int num = ARRAY_SIZE(cpu_features);
+ ObjectProperty *op;
+ CPUARMState *env = &cpu->env;
+
+ for (i = 0; i < num; i++) {
+ if ((arm_feature(env, ARM_FEATURE_AARCH64) && cpu_features[i].is_32bit)
+ || (!arm_feature(env, ARM_FEATURE_AARCH64) &&
+ cpu_features[i].is_32bit)) {
+ continue;
+ }
+ op = object_property_find(OBJECT(cpu), cpu_features[i].name, NULL);
+ if (!op) {
+ object_property_add(OBJECT(cpu), cpu_features[i].name, "bool",
+ arm_cpu_get_bit_prop,
+ arm_cpu_set_bit_prop,
+ NULL, &cpu_features[i], &error_abort);
+ }
+ }
+}
+
void arm_cpu_post_init(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -1150,6 +1491,8 @@ void arm_cpu_post_init(Object *obj)
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
&error_abort);
+
+ arm_cpu_register_feature_props(cpu);
}
static void arm_cpu_finalizefn(Object *obj)
--
2.25.1