Support disable/enable CPU features for AArch64
QEMU does not support disable/enable CPU features in AArch64 for now. This patch series add support for CPU features in AArch64. Firstly, we change the isar struct in ARMCPU to an array for convenience. Secondly, we add support to configure CPU feautres in AArch64 and make sure that the ID registers can be synchronized to KVM so that guest can read the value we configure. Thirdly, we add a mechanism to solve the dependency relationship of some CPU features. Last, we add a KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to set CPU features in AArch64. Also export CPU features to the result of qmp query-cpu-model-expansion so that libvirt can get the supported CPU features. Update the ID fields to ARMv8.6 and add some CPU features according to the new ID fields. With related KVM patch set[1], we can disable/enable CPU features in AArch64. [1] https://patchwork.kernel.org/cover/11711693/ Signed-off-by: Peng Liang <liangpeng10@huawei.com>
This commit is contained in:
parent
0c39e725b0
commit
29b03965de
22
qemu.spec
22
qemu.spec
@ -1,6 +1,6 @@
|
||||
Name: qemu
|
||||
Version: 4.1.0
|
||||
Release: 20
|
||||
Release: 21
|
||||
Epoch: 2
|
||||
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
||||
License: GPLv2 and BSD and MIT and CC-BY
|
||||
@ -217,6 +217,15 @@ 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
|
||||
|
||||
BuildRequires: flex
|
||||
BuildRequires: bison
|
||||
@ -563,6 +572,17 @@ getent passwd qemu >/dev/null || \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* 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
|
||||
|
||||
89
target-arm-Add-CPU-features-to-query-cpu-model-expan.patch
Normal file
89
target-arm-Add-CPU-features-to-query-cpu-model-expan.patch
Normal 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
|
||||
|
||||
30
target-arm-Add-more-CPU-features.patch
Normal file
30
target-arm-Add-more-CPU-features.patch
Normal 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
|
||||
|
||||
160
target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch
Normal file
160
target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch
Normal 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
|
||||
|
||||
84
target-arm-Update-ID-fields.patch
Normal file
84
target-arm-Update-ID-fields.patch
Normal 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
|
||||
|
||||
1908
target-arm-convert-isar-regs-to-array.patch
Normal file
1908
target-arm-convert-isar-regs-to-array.patch
Normal file
File diff suppressed because it is too large
Load Diff
184
target-arm-introduce-CPU-feature-dependency-mechanis.patch
Normal file
184
target-arm-introduce-CPU-feature-dependency-mechanis.patch
Normal 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
|
||||
|
||||
92
target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch
Normal file
92
target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch
Normal 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
|
||||
|
||||
124
target-arm-parse-cpu-feature-related-options.patch
Normal file
124
target-arm-parse-cpu-feature-related-options.patch
Normal 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
|
||||
|
||||
398
target-arm-register-CPU-features-for-property.patch
Normal file
398
target-arm-register-CPU-features-for-property.patch
Normal 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user