From 84b0f39ed6f83374e0345b8fdf402746adda4995 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Sat, 8 Feb 2020 12:57:59 +0000 Subject: [PATCH 01/28] 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 Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20200208125816.14954-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell (cherry-picked from commit 3d6ad6bb466f487bcc861f99e2c9054230df1076) Signed-off-by: Peng Liang --- ...dd-isar_feature-tests-for-PAN-ATS1E1.patch | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch diff --git a/target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch b/target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch new file mode 100644 index 00000000..920a36b5 --- /dev/null +++ b/target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch @@ -0,0 +1,79 @@ +From ee8de09f5b23c067f991f55d4f4ae6a6dc6de11c Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 8 Feb 2020 12:57:59 +0000 +Subject: [PATCH] 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 +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200208125816.14954-4-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +(cherry-picked from commit 3d6ad6bb466f487bcc861f99e2c9054230df1076) +Signed-off-by: Peng Liang +--- + target/arm/cpu.h | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 86eb79cd02..fe3108281a 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.23.0 + -- Gitee From b963c46486770824d068a305e18f87d55869cf69 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Sat, 8 Feb 2020 12:58:13 +0000 Subject: [PATCH 02/28] 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 Signed-off-by: Richard Henderson Message-id: 20200208125816.14954-18-richard.henderson@linaro.org Signed-off-by: Peter Maydell (cherry-picked from commit 64761e10af2742a916c08271828890274137b9e8) Signed-off-by: Peng Liang --- target-arm-Add-ID_AA64MMFR2_EL1.patch | 89 +++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 target-arm-Add-ID_AA64MMFR2_EL1.patch diff --git a/target-arm-Add-ID_AA64MMFR2_EL1.patch b/target-arm-Add-ID_AA64MMFR2_EL1.patch new file mode 100644 index 00000000..f424d7b3 --- /dev/null +++ b/target-arm-Add-ID_AA64MMFR2_EL1.patch @@ -0,0 +1,89 @@ +From 07dae4b3fdc5ad7c4b24d0e6aa5d3f4025212b3f Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 8 Feb 2020 12:58:13 +0000 +Subject: [PATCH] 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 +Signed-off-by: Richard Henderson +Message-id: 20200208125816.14954-18-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +(cherry-picked from commit 64761e10af2742a916c08271828890274137b9e8) +Signed-off-by: Peng Liang +--- + 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 fe3108281a..3e65bc50a4 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 b74c23a9bc..c50b1ba1c9 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 4f0bf00070..b794108a06 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.23.0 + -- Gitee From 0aa9d98ac57dfe688d956e8dcdb162aba0635c81 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 14 Feb 2020 17:51:01 +0000 Subject: [PATCH 03/28] 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é Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20200214175116.9164-7-peter.maydell@linaro.org (cherry-picked from commit ceb2744b47a1ef4184dca56a158eb3156b6eba36) Signed-off-by: Peng Liang --- ...nd-use-FIELD-definitions-for-ID_AA64.patch | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch diff --git a/target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch b/target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch new file mode 100644 index 00000000..b2144082 --- /dev/null +++ b/target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch @@ -0,0 +1,77 @@ +From 21d5d53e9114c3b4d3d8c888b1c5fdec1667ecc7 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 14 Feb 2020 17:51:01 +0000 +Subject: [PATCH] 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é +Reviewed-by: Richard Henderson +Signed-off-by: Peter Maydell +Message-id: 20200214175116.9164-7-peter.maydell@linaro.org +(cherry-picked from commit ceb2744b47a1ef4184dca56a158eb3156b6eba36) +Signed-off-by: Peng Liang +--- + 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 811e5c6365..dbd05e0113 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 3e65bc50a4..91cc02b43f 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 c50b1ba1c9..419be64037 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.23.0 + -- Gitee From 3333d474e124b1637bb555957d99f3d83df674b3 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 14 Feb 2020 17:51:02 +0000 Subject: [PATCH 04/28] 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é Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20200214175116.9164-8-peter.maydell@linaro.org (cherry-picked from commit d52c061e541982a3663ad5c65bd3b518dbe85b87) Signed-off-by: Peng Liang --- ...IELD-macros-for-clearing-ID_DFR0-PER.patch | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch diff --git a/target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch b/target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch new file mode 100644 index 00000000..149191a6 --- /dev/null +++ b/target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch @@ -0,0 +1,38 @@ +From 47338f4586001deb0e8cb04016e091ee7b2a24da Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 14 Feb 2020 17:51:02 +0000 +Subject: [PATCH] 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é +Reviewed-by: Richard Henderson +Signed-off-by: Peter Maydell +Message-id: 20200214175116.9164-8-peter.maydell@linaro.org +(cherry-picked from commit d52c061e541982a3663ad5c65bd3b518dbe85b87) +Signed-off-by: Peng Liang +--- + 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 dbd05e0113..6ad211b138 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.23.0 + -- Gitee From 4f98db71878edbf4c2d24ae8b2e539ee48552f28 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 14 Feb 2020 17:51:03 +0000 Subject: [PATCH 05/28] 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 Signed-off-by: Peter Maydell Message-id: 20200214175116.9164-9-peter.maydell@linaro.org (cherry-picked from commit a617953855b65a602d36364b9643f7e5bc31288e) Signed-off-by: Peng Liang --- ...e-an-aa32_pmu_8_1-isar-feature-test-.patch | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch diff --git a/target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch b/target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch new file mode 100644 index 00000000..7ba53999 --- /dev/null +++ b/target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch @@ -0,0 +1,249 @@ +From 3c44da3e72185d52af1412516156a180ecb8079e Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 14 Feb 2020 17:51:03 +0000 +Subject: [PATCH] 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 +Signed-off-by: Peter Maydell +Message-id: 20200214175116.9164-9-peter.maydell@linaro.org +(cherry-picked from commit a617953855b65a602d36364b9643f7e5bc31288e) +Signed-off-by: Peng Liang +--- + 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 9f8f0d3ff5..0741db7b0b 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 6ad211b138..7e9b85a289 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 91cc02b43f..2d8d27e80a 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 15f4ee9215..afdabbebbf 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 419be64037..3f06ca1964 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.23.0 + -- Gitee From 37878d12c4148038bd84f748a7c2b996b658ce98 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 14 Feb 2020 17:51:04 +0000 Subject: [PATCH 06/28] 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 Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell Message-id: 20200214175116.9164-10-peter.maydell@linaro.org (cherry-picked from commit 2a609df87d9b886fd38a190a754dbc241ff707e8) Signed-off-by: Peng Liang --- ...aa64_-and-_any_-versions-of-pmu_8_1-.patch | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch diff --git a/target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch b/target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch new file mode 100644 index 00000000..2dbcde80 --- /dev/null +++ b/target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch @@ -0,0 +1,168 @@ +From 3602361df4f43e4e5d5dc56e9e767ee93b8176bd Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 14 Feb 2020 17:51:04 +0000 +Subject: [PATCH] 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 +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Peter Maydell +Message-id: 20200214175116.9164-10-peter.maydell@linaro.org +(cherry-picked from commit 2a609df87d9b886fd38a190a754dbc241ff707e8) +Signed-off-by: Peng Liang +--- + 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 7e9b85a289..bb2edf4e18 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 2d8d27e80a..230130be81 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 afdabbebbf..aa96548f10 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 3f06ca1964..a71f4ef62d 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.23.0 + -- Gitee From 659f2bd0b41a919594a3e43bad13a96cfdfb753c Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 14 Feb 2020 17:51:05 +0000 Subject: [PATCH 07/28] 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 Reviewed-by: Richard Henderson Message-id: 20200214175116.9164-11-peter.maydell@linaro.org (cherry-picked from commit 88ce6c6ee85d902f59dc65afc3ca86b34f02b9ed) Signed-off-by: Peng Liang --- ...-Stop-assuming-DBGDIDR-always-exists.patch | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 target-arm-Stop-assuming-DBGDIDR-always-exists.patch diff --git a/target-arm-Stop-assuming-DBGDIDR-always-exists.patch b/target-arm-Stop-assuming-DBGDIDR-always-exists.patch new file mode 100644 index 00000000..14efa830 --- /dev/null +++ b/target-arm-Stop-assuming-DBGDIDR-always-exists.patch @@ -0,0 +1,188 @@ +From 1c7e6ebd21275e25e74445521d44d6242e40ff39 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 14 Feb 2020 17:51:05 +0000 +Subject: [PATCH] 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 +Reviewed-by: Richard Henderson +Message-id: 20200214175116.9164-11-peter.maydell@linaro.org +(cherry-picked from commit 88ce6c6ee85d902f59dc65afc3ca86b34f02b9ed) +Signed-off-by: Peng Liang +--- + 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 230130be81..4b1ae32bd2 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 dde80273ff..3f8f667df7 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_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 a71f4ef62d..c1ff4b6bd0 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 232d963875..a72d0a6cd1 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.23.0 + -- Gitee From ade77d7741b322a3c4d9af860f829f769a01f1c4 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 14 Feb 2020 17:51:06 +0000 Subject: [PATCH 08/28] 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 Reviewed-by: Richard Henderson Message-id: 20200214175116.9164-12-peter.maydell@linaro.org (cherry-picked from commit 4426d3617d64922d97b74ed22e67e33b6fb7de0a) Signed-off-by: Peng Liang --- ...rm-Move-DBGDIDR-into-ARMISARegisters.patch | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 target-arm-Move-DBGDIDR-into-ARMISARegisters.patch diff --git a/target-arm-Move-DBGDIDR-into-ARMISARegisters.patch b/target-arm-Move-DBGDIDR-into-ARMISARegisters.patch new file mode 100644 index 00000000..f742b984 --- /dev/null +++ b/target-arm-Move-DBGDIDR-into-ARMISARegisters.patch @@ -0,0 +1,160 @@ +From d90d85c86d98a35a6a51e0ef6edb95ca7f6de6ba Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 14 Feb 2020 17:51:06 +0000 +Subject: [PATCH] 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 +Reviewed-by: Richard Henderson +Message-id: 20200214175116.9164-12-peter.maydell@linaro.org +(cherry-picked from commit 4426d3617d64922d97b74ed22e67e33b6fb7de0a) +Signed-off-by: Peng Liang +--- + 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 bb2edf4e18..a23c71dbf7 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 4b1ae32bd2..3040aa4027 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 aa96548f10..7ad8b5e237 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 c1ff4b6bd0..60ff7c0fa1 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 a72d0a6cd1..1d01ecc413 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.23.0 + -- Gitee From f69b207970701e8b1c08edb8358844a8dbccc044 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Sat, 8 Feb 2020 12:58:12 +0000 Subject: [PATCH 09/28] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max This includes enablement of ARMv8.1-PAN. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20200208125816.14954-17-richard.henderson@linaro.org Signed-off-by: Peter Maydell (cherry-picked from commit e0fe7309a7c21ef2386de50d37c86aea0d671c08) Signed-off-by: Peng Liang --- ...arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch diff --git a/target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch b/target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch new file mode 100644 index 00000000..020c7ea8 --- /dev/null +++ b/target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch @@ -0,0 +1,59 @@ +From af3515aafaeea4744ffdd0e6816306db050f1606 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Sat, 8 Feb 2020 12:58:12 +0000 +Subject: [PATCH] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max + +This includes enablement of ARMv8.1-PAN. + +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20200208125816.14954-17-richard.henderson@linaro.org +Signed-off-by: Peter Maydell +(cherry-picked from commit e0fe7309a7c21ef2386de50d37c86aea0d671c08) +Signed-off-by: Peng Liang +--- + 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 a23c71dbf7..119bd27558 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 7ad8b5e237..a0d07fd78e 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.23.0 + -- Gitee From d03485e959753b2eac7dba84593069b4f839d4c3 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 14 Feb 2020 17:51:13 +0000 Subject: [PATCH 10/28] 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 Reviewed-by: Richard Henderson Message-id: 20200214175116.9164-19-peter.maydell@linaro.org (cherry-picked from commit 10054016eda1b13bdd8340d100fd029cc8b58f36) Signed-off-by: Peng Liang --- ...correct-register-in-aa32_pan-and-aa3.patch | 455 ++++++++++++++++++ 1 file changed, 455 insertions(+) create mode 100644 target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch diff --git a/target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch b/target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch new file mode 100644 index 00000000..276ddb69 --- /dev/null +++ b/target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch @@ -0,0 +1,455 @@ +From bb4c4e28a538076f384f9735c1d250ab39aacd07 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 14 Feb 2020 17:51:13 +0000 +Subject: [PATCH] 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 +Reviewed-by: Richard Henderson +Message-id: 20200214175116.9164-19-peter.maydell@linaro.org +(cherry-picked from commit 10054016eda1b13bdd8340d100fd029cc8b58f36) +Signed-off-by: Peng Liang +--- + 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 0741db7b0b..f7ef6ad141 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 119bd27558..c3728e3d95 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 3040aa4027..a78c30c355 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 a0d07fd78e..d450b8c8d7 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 60ff7c0fa1..49cd7a7ee4 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 ee1588305d..2247148e25 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 b794108a06..276d146600 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.23.0 + -- Gitee From b520ac7fc1727b0b7fa79d1e0cb9c8b2ba3e0282 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 14 Feb 2020 17:51:07 +0000 Subject: [PATCH 11/28] 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 Reviewed-by: Richard Henderson Message-id: 20200214175116.9164-13-peter.maydell@linaro.org (cherry-picked from commit 1548a7b2ad621a31b4216ed703b6d658a2ecf0d0) Signed-off-by: Peng Liang --- ...-debug-related-ID-registers-from-KVM.patch | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 target-arm-Read-debug-related-ID-registers-from-KVM.patch diff --git a/target-arm-Read-debug-related-ID-registers-from-KVM.patch b/target-arm-Read-debug-related-ID-registers-from-KVM.patch new file mode 100644 index 00000000..ec1706a4 --- /dev/null +++ b/target-arm-Read-debug-related-ID-registers-from-KVM.patch @@ -0,0 +1,133 @@ +From 58cd6440c5a50d5ef9cc85c0566486683a8bf0f4 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 14 Feb 2020 17:51:07 +0000 +Subject: [PATCH] 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 +Reviewed-by: Richard Henderson +Message-id: 20200214175116.9164-13-peter.maydell@linaro.org +(cherry-picked from commit 1548a7b2ad621a31b4216ed703b6d658a2ecf0d0) +Signed-off-by: Peng Liang +--- + 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 a78c30c355..56d8cd8ce6 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 2247148e25..e984d52dd2 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 276d146600..2a88b8df37 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.23.0 + -- Gitee From 2741867e2f8b88e9cc3370224b195ceefae179c7 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 31 Oct 2019 15:27:26 +0100 Subject: [PATCH 12/28] 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 Reviewed-by: Richard Henderson Reviewed-by: Eric Auger Reviewed-by: Beata Michalska Message-id: 20191031142734.8590-2-drjones@redhat.com Signed-off-by: Peter Maydell (cherry-picked from commit e19afd5667819d74ab25d1a1171efe7b5002c6ee) Signed-off-by: Peng Liang --- ...or-Introduce-qmp_query_cpu_model_exp.patch | 374 ++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch diff --git a/target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch b/target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch new file mode 100644 index 00000000..987391c3 --- /dev/null +++ b/target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch @@ -0,0 +1,374 @@ +From b98d65859769aa68deb34cb590aba35d8854ec07 Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Thu, 31 Oct 2019 15:27:26 +0100 +Subject: [PATCH] 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 +Reviewed-by: Richard Henderson +Reviewed-by: Eric Auger +Reviewed-by: Beata Michalska +Message-id: 20191031142734.8590-2-drjones@redhat.com +Signed-off-by: Peter Maydell +(cherry-picked from commit e19afd5667819d74ab25d1a1171efe7b5002c6ee) +Signed-off-by: Peng Liang +--- + 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 0000000000..c79dcffb55 +--- /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 55310a6aa2..0462322472 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 6ec6dd04ac..560970de7f 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.23.0 + -- Gitee From a21c429af421ef6abcc3befa65b5ec352904c405 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Fri, 7 Feb 2020 14:04:21 +0000 Subject: [PATCH 13/28] 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 Message-id: 20200203134251.12986-1-lyan@suse.com Reviewed-by: Andrew Jones Tested-by: Andrew Jones Signed-off-by: Peter Maydell (cherry-picked from commit 0999a4ba8718aa96105b978d3567fc7e90244c7e) Signed-off-by: Peng Liang --- ...or-query-cpu-model-expansion-crashed.patch | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 target-arm-monitor-query-cpu-model-expansion-crashed.patch diff --git a/target-arm-monitor-query-cpu-model-expansion-crashed.patch b/target-arm-monitor-query-cpu-model-expansion-crashed.patch new file mode 100644 index 00000000..52711901 --- /dev/null +++ b/target-arm-monitor-query-cpu-model-expansion-crashed.patch @@ -0,0 +1,61 @@ +From ea20aeab55e8ec61cb9500d5a44d82a9f95e41b3 Mon Sep 17 00:00:00 2001 +From: Liang Yan +Date: Fri, 7 Feb 2020 14:04:21 +0000 +Subject: [PATCH] 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 +Message-id: 20200203134251.12986-1-lyan@suse.com +Reviewed-by: Andrew Jones +Tested-by: Andrew Jones +Signed-off-by: Peter Maydell +(cherry-picked from commit 0999a4ba8718aa96105b978d3567fc7e90244c7e) +Signed-off-by: Peng Liang +--- + 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 560970de7f..e2b1d117a4 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.23.0 + -- Gitee From e407eb26e77c30f3cd9505b374b0017cda3cf447 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 6 Aug 2020 16:14:25 +0800 Subject: [PATCH 14/28] target/arm: convert isar regs to array The isar in ARMCPU is a struct, each field of which represents an ID register. It's not convenient for us to support CPU feature in AArch64. So let's change it to an array first and add an enum as the index of the array for convenience. Since we will never access high 32-bits of ID registers in AArch32, it's harmless to change the ID registers in AArch32 to 64-bits. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang (cherry-picked from commit 5b5976d6d99a55bdaf0f1596c8b0706366d0df92) --- target-arm-convert-isar-regs-to-array.patch | 1909 +++++++++++++++++++ 1 file changed, 1909 insertions(+) create mode 100644 target-arm-convert-isar-regs-to-array.patch diff --git a/target-arm-convert-isar-regs-to-array.patch b/target-arm-convert-isar-regs-to-array.patch new file mode 100644 index 00000000..d696e9ba --- /dev/null +++ b/target-arm-convert-isar-regs-to-array.patch @@ -0,0 +1,1909 @@ +From 94bca008d78e1b493657c3947449401ea9e5f12e Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:25 +0800 +Subject: [PATCH] target/arm: convert isar regs to array + +The isar in ARMCPU is a struct, each field of which represents an ID +register. It's not convenient for us to support CPU feature in AArch64. +So let's change it to an array first and add an enum as the index of the +array for convenience. Since we will never access high 32-bits of ID +registers in AArch32, it's harmless to change the ID registers in +AArch32 to 64-bits. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +(cherry-picked from commit 5b5976d6d99a55bdaf0f1596c8b0706366d0df92) +--- + hw/intc/armv7m_nvic.c | 28 +-- + target/arm/cpu.c | 440 +++++++++++++++++++++-------------------- + target/arm/cpu.h | 178 +++++++++-------- + target/arm/cpu64.c | 158 +++++++-------- + target/arm/helper.c | 54 ++--- + target/arm/internals.h | 15 +- + target/arm/kvm64.c | 68 +++---- + 7 files changed, 478 insertions(+), 463 deletions(-) + +diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c +index f7ef6ad141..5013ec978c 100644 +--- a/hw/intc/armv7m_nvic.c ++++ b/hw/intc/armv7m_nvic.c +@@ -1223,29 +1223,29 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + case 0xd44: /* PFR1. */ + return cpu->id_pfr1; + case 0xd48: /* DFR0. */ +- return cpu->isar.id_dfr0; ++ return cpu->isar.regs[ID_DFR0]; + case 0xd4c: /* AFR0. */ + return cpu->id_afr0; + case 0xd50: /* MMFR0. */ +- return cpu->isar.id_mmfr0; ++ return cpu->isar.regs[ID_MMFR0]; + case 0xd54: /* MMFR1. */ +- return cpu->isar.id_mmfr1; ++ return cpu->isar.regs[ID_MMFR1]; + case 0xd58: /* MMFR2. */ +- return cpu->isar.id_mmfr2; ++ return cpu->isar.regs[ID_MMFR2]; + case 0xd5c: /* MMFR3. */ +- return cpu->isar.id_mmfr3; ++ return cpu->isar.regs[ID_MMFR3]; + case 0xd60: /* ISAR0. */ +- return cpu->isar.id_isar0; ++ return cpu->isar.regs[ID_ISAR0]; + case 0xd64: /* ISAR1. */ +- return cpu->isar.id_isar1; ++ return cpu->isar.regs[ID_ISAR1]; + case 0xd68: /* ISAR2. */ +- return cpu->isar.id_isar2; ++ return cpu->isar.regs[ID_ISAR2]; + case 0xd6c: /* ISAR3. */ +- return cpu->isar.id_isar3; ++ return cpu->isar.regs[ID_ISAR3]; + case 0xd70: /* ISAR4. */ +- return cpu->isar.id_isar4; ++ return cpu->isar.regs[ID_ISAR4]; + case 0xd74: /* ISAR5. */ +- return cpu->isar.id_isar5; ++ return cpu->isar.regs[ID_ISAR5]; + case 0xd78: /* CLIDR */ + return cpu->clidr; + case 0xd7c: /* CTR */ +@@ -1450,11 +1450,11 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + } + return cpu->env.v7m.fpdscr[attrs.secure]; + case 0xf40: /* MVFR0 */ +- return cpu->isar.mvfr0; ++ return cpu->isar.regs[MVFR0]; + case 0xf44: /* MVFR1 */ +- return cpu->isar.mvfr1; ++ return cpu->isar.regs[MVFR1]; + case 0xf48: /* MVFR2 */ +- return cpu->isar.mvfr2; ++ return cpu->isar.regs[MVFR2]; + default: + bad_offset: + qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset); +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index c3728e3d95..5bcdad0c5e 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -170,9 +170,9 @@ static void arm_cpu_reset(CPUState *s) + g_hash_table_foreach(cpu->cp_regs, cp_reg_check_reset, cpu); + + env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid; +- env->vfp.xregs[ARM_VFP_MVFR0] = cpu->isar.mvfr0; +- env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.mvfr1; +- env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.mvfr2; ++ env->vfp.xregs[ARM_VFP_MVFR0] = cpu->isar.regs[MVFR0]; ++ env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.regs[MVFR1]; ++ env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.regs[MVFR2]; + + cpu->power_state = cpu->start_powered_off ? PSCI_OFF : PSCI_ON; + s->halted = cpu->start_powered_off; +@@ -1251,19 +1251,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + unset_feature(env, ARM_FEATURE_VFP3); + unset_feature(env, ARM_FEATURE_VFP4); + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, FP, 0xf); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; + +- u = cpu->isar.id_isar6; ++ u = cpu->isar.regs[ID_ISAR6]; + u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0); +- cpu->isar.id_isar6 = u; ++ cpu->isar.regs[ID_ISAR6] = u; + +- u = cpu->isar.mvfr0; ++ u = cpu->isar.regs[MVFR0]; + u = FIELD_DP32(u, MVFR0, FPSP, 0); + u = FIELD_DP32(u, MVFR0, FPDP, 0); + u = FIELD_DP32(u, MVFR0, FPTRAP, 0); +@@ -1271,17 +1271,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + u = FIELD_DP32(u, MVFR0, FPSQRT, 0); + u = FIELD_DP32(u, MVFR0, FPSHVEC, 0); + u = FIELD_DP32(u, MVFR0, FPROUND, 0); +- cpu->isar.mvfr0 = u; ++ cpu->isar.regs[MVFR0] = u; + +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, FPFTZ, 0); + u = FIELD_DP32(u, MVFR1, FPDNAN, 0); + u = FIELD_DP32(u, MVFR1, FPHP, 0); +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; + +- u = cpu->isar.mvfr2; ++ u = cpu->isar.regs[MVFR2]; + u = FIELD_DP32(u, MVFR2, FPMISC, 0); +- cpu->isar.mvfr2 = u; ++ cpu->isar.regs[MVFR2] = u; + } + + if (!cpu->has_neon) { +@@ -1290,56 +1290,56 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + + unset_feature(env, ARM_FEATURE_NEON); + +- t = cpu->isar.id_aa64isar0; ++ t = cpu->isar.regs[ID_AA64ISAR0]; + t = FIELD_DP64(t, ID_AA64ISAR0, DP, 0); +- cpu->isar.id_aa64isar0 = t; ++ cpu->isar.regs[ID_AA64ISAR0] = t; + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 0xf); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; + +- u = cpu->isar.id_isar5; ++ u = cpu->isar.regs[ID_ISAR5]; + u = FIELD_DP32(u, ID_ISAR5, RDM, 0); + u = FIELD_DP32(u, ID_ISAR5, VCMA, 0); +- cpu->isar.id_isar5 = u; ++ cpu->isar.regs[ID_ISAR5] = u; + +- u = cpu->isar.id_isar6; ++ u = cpu->isar.regs[ID_ISAR6]; + u = FIELD_DP32(u, ID_ISAR6, DP, 0); + u = FIELD_DP32(u, ID_ISAR6, FHM, 0); +- cpu->isar.id_isar6 = u; ++ cpu->isar.regs[ID_ISAR6] = u; + +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, SIMDLS, 0); + u = FIELD_DP32(u, MVFR1, SIMDINT, 0); + u = FIELD_DP32(u, MVFR1, SIMDSP, 0); + u = FIELD_DP32(u, MVFR1, SIMDHP, 0); + u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0); +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; + +- u = cpu->isar.mvfr2; ++ u = cpu->isar.regs[MVFR2]; + u = FIELD_DP32(u, MVFR2, SIMDMISC, 0); +- cpu->isar.mvfr2 = u; ++ cpu->isar.regs[MVFR2] = u; + } + + if (!cpu->has_neon && !cpu->has_vfp) { + uint64_t t; + uint32_t u; + +- t = cpu->isar.id_aa64isar0; ++ t = cpu->isar.regs[ID_AA64ISAR0]; + t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 0); +- cpu->isar.id_aa64isar0 = t; ++ cpu->isar.regs[ID_AA64ISAR0] = t; + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 0); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- u = cpu->isar.mvfr0; ++ u = cpu->isar.regs[MVFR0]; + u = FIELD_DP32(u, MVFR0, SIMDREG, 0); +- cpu->isar.mvfr0 = u; ++ cpu->isar.regs[MVFR0] = u; + } + + if (arm_feature(env, ARM_FEATURE_M) && !cpu->has_dsp) { +@@ -1347,19 +1347,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + + unset_feature(env, ARM_FEATURE_THUMB_DSP); + +- u = cpu->isar.id_isar1; ++ u = cpu->isar.regs[ID_ISAR1]; + u = FIELD_DP32(u, ID_ISAR1, EXTEND, 1); +- cpu->isar.id_isar1 = u; ++ cpu->isar.regs[ID_ISAR1] = u; + +- u = cpu->isar.id_isar2; ++ u = cpu->isar.regs[ID_ISAR2]; + u = FIELD_DP32(u, ID_ISAR2, MULTU, 1); + u = FIELD_DP32(u, ID_ISAR2, MULTS, 1); +- cpu->isar.id_isar2 = u; ++ cpu->isar.regs[ID_ISAR2] = u; + +- u = cpu->isar.id_isar3; ++ u = cpu->isar.regs[ID_ISAR3]; + u = FIELD_DP32(u, ID_ISAR3, SIMD, 1); + u = FIELD_DP32(u, ID_ISAR3, SATURATE, 0); +- cpu->isar.id_isar3 = u; ++ cpu->isar.regs[ID_ISAR3] = u; + } + + /* Some features automatically imply others: */ +@@ -1499,7 +1499,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12]. + */ + cpu->id_pfr1 &= ~0xf0; +- cpu->isar.id_aa64pfr0 &= ~0xf000; ++ cpu->isar.regs[ID_AA64PFR0] &= ~0xf000; + } + + if (!cpu->has_el2) { +@@ -1522,9 +1522,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + cpu); + #endif + } else { +- cpu->isar.id_aa64dfr0 = +- FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); +- cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0); ++ cpu->isar.regs[ID_AA64DFR0] = ++ FIELD_DP64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER, 0); ++ cpu->isar.regs[ID_DFR0] = FIELD_DP32(cpu->isar.regs[ID_DFR0], ID_DFR0, ++ PERFMON, 0); + cpu->pmceid0 = 0; + cpu->pmceid1 = 0; + } +@@ -1534,7 +1535,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * registers if we don't have EL2. These are id_pfr1[15:12] and + * id_aa64pfr0_el1[11:8]. + */ +- cpu->isar.id_aa64pfr0 &= ~0xf00; ++ cpu->isar.regs[ID_AA64PFR0] &= ~0xf00; + cpu->id_pfr1 &= ~0xf000; + } + +@@ -1675,13 +1676,15 @@ static void arm926_initfn(Object *obj) + * ARMv5 does not have the ID_ISAR registers, but we can still + * set the field to indicate Jazelle support within QEMU. + */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], ID_ISAR1, ++ JAZELLE, 1); + /* + * Similarly, we need to set MVFR0 fields to enable double precision + * and short vector support even though ARMv5 doesn't have this register. + */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, ++ FPSHVEC, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); + } + + static void arm946_initfn(Object *obj) +@@ -1717,13 +1720,15 @@ static void arm1026_initfn(Object *obj) + * ARMv5 does not have the ID_ISAR registers, but we can still + * set the field to indicate Jazelle support within QEMU. + */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], ID_ISAR1, ++ JAZELLE, 1); + /* + * Similarly, we need to set MVFR0 fields to enable double precision + * and short vector support even though ARMv5 doesn't have this register. + */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, ++ FPSHVEC, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); + + { + /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ +@@ -1756,22 +1761,22 @@ static void arm1136_r2_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); + cpu->midr = 0x4107b362; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; + cpu->id_pfr0 = 0x111; + cpu->id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0x2; ++ cpu->isar.regs[ID_DFR0] = 0x2; + cpu->id_afr0 = 0x3; +- 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; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222110; ++ cpu->isar.regs[ID_ISAR0] = 0x00140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231111; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 7; + } + +@@ -1788,22 +1793,22 @@ static void arm1136_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); + cpu->midr = 0x4117b363; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; + cpu->id_pfr0 = 0x111; + cpu->id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0x2; ++ cpu->isar.regs[ID_DFR0] = 0x2; + cpu->id_afr0 = 0x3; +- 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; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222110; ++ cpu->isar.regs[ID_ISAR0] = 0x00140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231111; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 7; + } + +@@ -1821,22 +1826,22 @@ static void arm1176_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_EL3); + cpu->midr = 0x410fb767; + cpu->reset_fpsid = 0x410120b5; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; + cpu->id_pfr0 = 0x111; + cpu->id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x33; ++ cpu->isar.regs[ID_DFR0] = 0x33; + cpu->id_afr0 = 0; +- 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; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x01141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222100; ++ cpu->isar.regs[ID_ISAR0] = 0x0140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231121; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x01141; + cpu->reset_auxcr = 7; + } + +@@ -1852,21 +1857,21 @@ static void arm11mpcore_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + cpu->midr = 0x410fb022; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ + cpu->id_pfr0 = 0x111; + cpu->id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0; ++ cpu->isar.regs[ID_DFR0] = 0; + cpu->id_afr0 = 0x2; +- 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; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01100103; ++ cpu->isar.regs[ID_MMFR1] = 0x10020302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222000; ++ cpu->isar.regs[ID_ISAR0] = 0x00100011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11221011; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 1; + } + +@@ -1889,19 +1894,19 @@ static void cortex_m3_initfn(Object *obj) + cpu->pmsav7_dregion = 8; + cpu->id_pfr0 = 0x00000030; + cpu->id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 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; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00000030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x00000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01141110; ++ cpu->isar.regs[ID_ISAR1] = 0x02111000; ++ cpu->isar.regs[ID_ISAR2] = 0x21112231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111110; ++ cpu->isar.regs[ID_ISAR4] = 0x01310102; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m4_initfn(Object *obj) +@@ -1915,24 +1920,24 @@ static void cortex_m4_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_VFP4); + cpu->midr = 0x410fc240; /* r0p0 */ + cpu->pmsav7_dregion = 8; +- cpu->isar.mvfr0 = 0x10110021; +- cpu->isar.mvfr1 = 0x11000011; +- cpu->isar.mvfr2 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x10110021; ++ cpu->isar.regs[MVFR1] = 0x11000011; ++ cpu->isar.regs[MVFR2] = 0x00000000; + cpu->id_pfr0 = 0x00000030; + cpu->id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 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; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00000030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x00000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01141110; ++ cpu->isar.regs[ID_ISAR1] = 0x02111000; ++ cpu->isar.regs[ID_ISAR2] = 0x21112231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111110; ++ cpu->isar.regs[ID_ISAR4] = 0x01310102; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m33_initfn(Object *obj) +@@ -1948,24 +1953,24 @@ static void cortex_m33_initfn(Object *obj) + cpu->midr = 0x410fd213; /* r0p3 */ + cpu->pmsav7_dregion = 16; + cpu->sau_sregion = 8; +- cpu->isar.mvfr0 = 0x10110021; +- cpu->isar.mvfr1 = 0x11000011; +- cpu->isar.mvfr2 = 0x00000040; ++ cpu->isar.regs[MVFR0] = 0x10110021; ++ cpu->isar.regs[MVFR1] = 0x11000011; ++ cpu->isar.regs[MVFR2] = 0x00000040; + cpu->id_pfr0 = 0x00000030; + cpu->id_pfr1 = 0x00000210; +- cpu->isar.id_dfr0 = 0x00200000; ++ cpu->isar.regs[ID_DFR0] = 0x00200000; + cpu->id_afr0 = 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; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00101F40; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01101110; ++ cpu->isar.regs[ID_ISAR1] = 0x02212000; ++ cpu->isar.regs[ID_ISAR2] = 0x20232232; ++ cpu->isar.regs[ID_ISAR3] = 0x01111131; ++ cpu->isar.regs[ID_ISAR4] = 0x01310132; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + cpu->clidr = 0x00000000; + cpu->ctr = 0x8000c000; + } +@@ -2004,19 +2009,19 @@ static void cortex_r5_initfn(Object *obj) + cpu->midr = 0x411fc153; /* r1p3 */ + cpu->id_pfr0 = 0x0131; + cpu->id_pfr1 = 0x001; +- cpu->isar.id_dfr0 = 0x010400; ++ cpu->isar.regs[ID_DFR0] = 0x010400; + cpu->id_afr0 = 0x0; +- 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; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x0010142; +- cpu->isar.id_isar5 = 0x0; +- cpu->isar.id_isar6 = 0x0; ++ cpu->isar.regs[ID_MMFR0] = 0x0210030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01200000; ++ cpu->isar.regs[ID_MMFR3] = 0x0211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101111; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232141; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x0010142; ++ cpu->isar.regs[ID_ISAR5] = 0x0; ++ cpu->isar.regs[ID_ISAR6] = 0x0; + cpu->mp_is_up = true; + cpu->pmsav7_dregion = 16; + define_arm_cp_regs(cpu, cortexr5_cp_reginfo); +@@ -2028,8 +2033,8 @@ static void cortex_r5f_initfn(Object *obj) + + cortex_r5_initfn(obj); + set_feature(&cpu->env, ARM_FEATURE_VFP3); +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x00000011; ++ cpu->isar.regs[MVFR0] = 0x10110221; ++ cpu->isar.regs[MVFR1] = 0x00000011; + } + + static const ARMCPRegInfo cortexa8_cp_reginfo[] = { +@@ -2053,24 +2058,24 @@ static void cortex_a8_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_EL3); + cpu->midr = 0x410fc080; + cpu->reset_fpsid = 0x410330c0; +- cpu->isar.mvfr0 = 0x11110222; +- cpu->isar.mvfr1 = 0x00011111; ++ cpu->isar.regs[MVFR0] = 0x11110222; ++ cpu->isar.regs[MVFR1] = 0x00011111; + cpu->ctr = 0x82048004; + cpu->reset_sctlr = 0x00c50078; + cpu->id_pfr0 = 0x1031; + cpu->id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x400; ++ cpu->isar.regs[ID_DFR0] = 0x400; + cpu->id_afr0 = 0; +- 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; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x00111142; +- cpu->isar.dbgdidr = 0x15141000; ++ cpu->isar.regs[ID_MMFR0] = 0x31100003; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01202000; ++ cpu->isar.regs[ID_MMFR3] = 0x11; ++ cpu->isar.regs[ID_ISAR0] = 0x00101111; ++ cpu->isar.regs[ID_ISAR1] = 0x12112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232031; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00111142; ++ cpu->isar.regs[DBGDIDR] = 0x15141000; + cpu->clidr = (1 << 27) | (2 << 24) | 3; + cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ + cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */ +@@ -2126,24 +2131,24 @@ static void cortex_a9_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CBAR); + cpu->midr = 0x410fc090; + cpu->reset_fpsid = 0x41033090; +- cpu->isar.mvfr0 = 0x11110222; +- cpu->isar.mvfr1 = 0x01111111; ++ cpu->isar.regs[MVFR0] = 0x11110222; ++ cpu->isar.regs[MVFR1] = 0x01111111; + cpu->ctr = 0x80038003; + cpu->reset_sctlr = 0x00c50078; + cpu->id_pfr0 = 0x1031; + cpu->id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x000; ++ cpu->isar.regs[ID_DFR0] = 0x000; + cpu->id_afr0 = 0; +- 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; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x00111142; +- cpu->isar.dbgdidr = 0x35141000; ++ cpu->isar.regs[ID_MMFR0] = 0x00100103; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01230000; ++ cpu->isar.regs[ID_MMFR3] = 0x00002111; ++ cpu->isar.regs[ID_ISAR0] = 0x00101111; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00111142; ++ cpu->isar.regs[DBGDIDR] = 0x35141000; + cpu->clidr = (1 << 27) | (1 << 24) | 3; + cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */ + cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */ +@@ -2191,27 +2196,27 @@ static void cortex_a7_initfn(Object *obj) + cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7; + cpu->midr = 0x410fc075; + cpu->reset_fpsid = 0x41023075; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x11111111; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x11111111; + cpu->ctr = 0x84448003; + cpu->reset_sctlr = 0x00c50078; + cpu->id_pfr0 = 0x00001131; + cpu->id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x02010555; ++ cpu->isar.regs[ID_DFR0] = 0x02010555; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01240000; +- cpu->isar.id_mmfr3 = 0x02102211; ++ cpu->isar.regs[ID_MMFR0] = 0x10101105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01240000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; + /* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but + * table 4-41 gives 0x02101110, which includes the arm div insns. + */ +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x10011142; +- cpu->isar.dbgdidr = 0x3515f005; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x10011142; ++ cpu->isar.regs[DBGDIDR] = 0x3515f005; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ +@@ -2237,24 +2242,24 @@ static void cortex_a15_initfn(Object *obj) + cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15; + cpu->midr = 0x412fc0f1; + cpu->reset_fpsid = 0x410430f0; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x11111111; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x11111111; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50078; + cpu->id_pfr0 = 0x00001131; + cpu->id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x02010555; ++ cpu->isar.regs[ID_DFR0] = 0x02010555; + cpu->id_afr0 = 0x00000000; +- 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; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x10011142; +- cpu->isar.dbgdidr = 0x3515f021; ++ cpu->isar.regs[ID_MMFR0] = 0x10201105; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01240000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x10011142; ++ cpu->isar.regs[DBGDIDR] = 0x3515f021; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ +@@ -2447,7 +2452,8 @@ static void arm_max_initfn(Object *obj) + cortex_a15_initfn(obj); + + /* old-style VFP short-vector support */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, ++ FPSHVEC, 1); + + #ifdef CONFIG_USER_ONLY + /* We don't set these in system emulation mode for the moment, +@@ -2458,39 +2464,39 @@ static void arm_max_initfn(Object *obj) + { + uint32_t t; + +- t = cpu->isar.id_isar5; ++ t = cpu->isar.regs[ID_ISAR5]; + t = FIELD_DP32(t, ID_ISAR5, AES, 2); + t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); + t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); + t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); + t = FIELD_DP32(t, ID_ISAR5, RDM, 1); + t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); +- cpu->isar.id_isar5 = t; ++ cpu->isar.regs[ID_ISAR5] = t; + +- t = cpu->isar.id_isar6; ++ t = cpu->isar.regs[ID_ISAR6]; + t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); + t = FIELD_DP32(t, ID_ISAR6, DP, 1); + t = FIELD_DP32(t, ID_ISAR6, FHM, 1); + t = FIELD_DP32(t, ID_ISAR6, SB, 1); + t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); +- cpu->isar.id_isar6 = t; ++ cpu->isar.regs[ID_ISAR6] = t; + +- t = cpu->isar.mvfr1; ++ t = cpu->isar.regs[MVFR1]; + t = FIELD_DP32(t, MVFR1, FPHP, 2); /* v8.0 FP support */ +- cpu->isar.mvfr1 = t; ++ cpu->isar.regs[MVFR1] = t; + +- t = cpu->isar.mvfr2; ++ t = cpu->isar.regs[MVFR2]; + t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ + t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ +- cpu->isar.mvfr2 = t; ++ cpu->isar.regs[MVFR2] = t; + +- t = cpu->isar.id_mmfr3; ++ t = cpu->isar.regs[ID_MMFR3]; + t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ +- cpu->isar.id_mmfr3 = t; ++ cpu->isar.regs[ID_MMFR3] = t; + +- t = cpu->isar.id_mmfr4; ++ t = cpu->isar.regs[ID_MMFR4]; + t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ +- cpu->isar.id_mmfr4 = t; ++ cpu->isar.regs[ID_MMFR4] = t; + } + #endif + } +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 56d8cd8ce6..7bb481fb4d 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -63,6 +63,37 @@ + #define ARMV7M_EXCP_PENDSV 14 + #define ARMV7M_EXCP_SYSTICK 15 + ++typedef enum CPUIDReg { ++ MIDR_EL1, ++ ID_ISAR0, ++ ID_ISAR1, ++ ID_ISAR2, ++ ID_ISAR3, ++ ID_ISAR4, ++ ID_ISAR5, ++ ID_ISAR6, ++ ID_MMFR0, ++ ID_MMFR1, ++ ID_MMFR2, ++ ID_MMFR3, ++ ID_MMFR4, ++ ID_AA64ISAR0, ++ ID_AA64ISAR1, ++ ID_AA64PFR0, ++ ID_AA64PFR1, ++ ID_AA64MMFR0, ++ ID_AA64MMFR1, ++ ID_AA64MMFR2, ++ ID_AA64DFR0, ++ ID_AA64DFR1, ++ ID_DFR0, ++ MVFR0, ++ MVFR1, ++ MVFR2, ++ DBGDIDR, ++ ID_MAX, ++} CPUIDReg; ++ + /* For M profile, some registers are banked secure vs non-secure; + * these are represented as a 2-element array where the first element + * is the non-secure copy and the second is the secure copy. +@@ -855,32 +886,7 @@ struct ARMCPU { + * field by reading the value from the KVM vCPU. + */ + struct ARMISARegisters { +- uint32_t id_isar0; +- uint32_t id_isar1; +- uint32_t id_isar2; +- uint32_t id_isar3; +- uint32_t id_isar4; +- uint32_t id_isar5; +- uint32_t id_isar6; +- uint32_t id_mmfr0; +- uint32_t id_mmfr1; +- uint32_t id_mmfr2; +- uint32_t id_mmfr3; +- uint32_t id_mmfr4; +- uint32_t mvfr0; +- 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; +- uint64_t id_aa64pfr1; +- uint64_t id_aa64mmfr0; +- uint64_t id_aa64mmfr1; +- uint64_t id_aa64mmfr2; +- uint64_t id_aa64dfr0; +- uint64_t id_aa64dfr1; ++ uint64_t regs[ID_MAX]; + } isar; + uint32_t midr; + uint32_t revidr; +@@ -3358,77 +3364,77 @@ extern const uint64_t pred_esz_masks[4]; + */ + static inline bool isar_feature_thumb_div(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) != 0; + } + + static inline bool isar_feature_arm_div(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; ++ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) > 1; + } + + static inline bool isar_feature_jazelle(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR1], ID_ISAR1, JAZELLE) != 0; + } + + static inline bool isar_feature_aa32_aes(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, AES) != 0; + } + + static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, AES) > 1; + } + + static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, SHA1) != 0; + } + + static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, SHA2) != 0; + } + + static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, CRC32) != 0; + } + + static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, RDM) != 0; + } + + static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, VCMA) != 0; + } + + static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, JSCVT) != 0; + } + + static inline bool isar_feature_aa32_dp(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, DP) != 0; + } + + static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, FHM) != 0; + } + + static inline bool isar_feature_aa32_sb(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, SB) != 0; + } + + static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, SPECRES) != 0; + } + + static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) +@@ -3438,24 +3444,24 @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) + * the ARMv8.2-FP16 extension is implemented for aa32 mode. + * At which point we can properly set and check MVFR1.FPHP. + */ +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) == 1; + } + + static inline bool isar_feature_aa32_fp_d32(const ARMISARegisters *id) + { + /* Return true if D16-D31 are implemented */ +- return FIELD_EX64(id->mvfr0, MVFR0, SIMDREG) >= 2; ++ return FIELD_EX64(id->regs[MVFR0], MVFR0, SIMDREG) >= 2; + } + + static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id) + { +- return FIELD_EX64(id->mvfr0, MVFR0, FPSHVEC) > 0; ++ return FIELD_EX64(id->regs[MVFR0], MVFR0, FPSHVEC) > 0; + } + + static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id) + { + /* Return true if CPU supports double precision floating point */ +- return FIELD_EX64(id->mvfr0, MVFR0, FPDP) > 0; ++ return FIELD_EX64(id->regs[MVFR0], MVFR0, FPDP) > 0; + } + + /* +@@ -3465,49 +3471,49 @@ static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id) + */ + static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id) + { +- return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 0; ++ return FIELD_EX64(id->regs[MVFR1], MVFR1, FPHP) > 0; + } + + static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) + { +- return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 1; ++ return FIELD_EX64(id->regs[MVFR1], MVFR1, FPHP) > 1; + } + + static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id) + { +- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 1; ++ return FIELD_EX64(id->regs[MVFR2], MVFR2, FPMISC) >= 1; + } + + static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id) + { +- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 2; ++ return FIELD_EX64(id->regs[MVFR2], MVFR2, FPMISC) >= 2; + } + + static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id) + { +- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 3; ++ return FIELD_EX64(id->regs[MVFR2], MVFR2, FPMISC) >= 3; + } + + static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4; ++ return FIELD_EX64(id->regs[MVFR2], MVFR2, FPMISC) >= 4; + } + + static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR3], ID_MMFR3, PAN) != 0; + } + + static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2; ++ return FIELD_EX32(id->regs[ID_MMFR3], 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; ++ return FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) >= 4 && ++ FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) != 0xf; + } + + /* +@@ -3515,92 +3521,92 @@ static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id) + */ + static inline bool isar_feature_aa64_aes(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, AES) != 0; + } + + static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) > 1; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, AES) > 1; + } + + static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA1) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SHA1) != 0; + } + + static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SHA2) != 0; + } + + static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) > 1; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SHA2) > 1; + } + + static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, CRC32) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, CRC32) != 0; + } + + static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, ATOMIC) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, ATOMIC) != 0; + } + + static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RDM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, RDM) != 0; + } + + static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA3) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SHA3) != 0; + } + + static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM3) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SM3) != 0; + } + + static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM4) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, SM4) != 0; + } + + static inline bool isar_feature_aa64_dp(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, DP) != 0; + } + + static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, FHM) != 0; + } + + static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TS) != 0; + } + + static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TS) >= 2; + } + + static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, RNDR) != 0; + } + + static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, JSCVT) != 0; + } + + static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FCMA) != 0; + } + + static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) +@@ -3611,7 +3617,7 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) + * defined algorithms, and thus API+GPI, and this predicate controls + * migration of the 128-bit keys. + */ +- return (id->id_aa64isar1 & ++ return (id->regs[ID_AA64ISAR1] & + (FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) | + FIELD_DP64(0, ID_AA64ISAR1, API, 0xf) | + FIELD_DP64(0, ID_AA64ISAR1, GPA, 0xf) | +@@ -3620,59 +3626,59 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) + + static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, SB) != 0; + } + + static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, SPECRES) != 0; + } + + static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FRINTTS) != 0; + } + + static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id) + { + /* We always set the AdvSIMD and FP fields identically wrt FP16. */ +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) == 1; + } + + static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, EL0) >= 2; + } + + static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, SVE) != 0; + } + + static inline bool isar_feature_aa64_lor(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0; ++ return FIELD_EX64(id->regs[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; ++ return FIELD_EX64(id->regs[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; ++ return FIELD_EX64(id->regs[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; ++ return FIELD_EX64(id->regs[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; ++ return FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 4 && ++ FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf; + } + + static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id) +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index d450b8c8d7..fe64875216 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -116,31 +116,31 @@ static void aarch64_a57_initfn(Object *obj) + cpu->midr = 0x411fd070; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034070; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; + cpu->id_pfr0 = 0x00000131; + cpu->id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001124; +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10101105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_ISAR6] = 0; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ +@@ -170,31 +170,31 @@ static void aarch64_a53_initfn(Object *obj) + cpu->midr = 0x410fd034; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034070; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x84448004; /* L1Ip = VIPT */ + cpu->reset_sctlr = 0x00c50838; + cpu->id_pfr0 = 0x00000131; + cpu->id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10101105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_ISAR6] = 0; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001122; /* 40 bit physical addr */ ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ +@@ -224,30 +224,30 @@ static void aarch64_a72_initfn(Object *obj) + cpu->midr = 0x410fd083; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034080; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; + cpu->id_pfr0 = 0x00000131; + cpu->id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- 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; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001124; +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10201105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ +@@ -275,10 +275,10 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + + cpu->midr = 0x480fd010; + cpu->ctr = 0x84448004; +- cpu->isar.id_aa64pfr0 = 0x11001111; +- cpu->isar.id_aa64dfr0 = 0x110305408; +- cpu->isar.id_aa64isar0 = 0x10211120; +- cpu->isar.id_aa64mmfr0 = 0x101125; ++ cpu->isar.regs[ID_AA64PFR0] = 0x11001111; ++ cpu->isar.regs[ID_AA64DFR0] = 0x110305408; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x10211120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x101125; + } + + static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name, +@@ -321,7 +321,7 @@ static void aarch64_max_initfn(Object *obj) + uint32_t u; + aarch64_a57_initfn(obj); + +- t = cpu->isar.id_aa64isar0; ++ t = cpu->isar.regs[ID_AA64ISAR0]; + t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* AES + PMULL */ + t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); + t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* SHA512 */ +@@ -335,9 +335,9 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1); + t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */ + t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); +- cpu->isar.id_aa64isar0 = t; ++ cpu->isar.regs[ID_AA64ISAR0] = t; + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); + t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); + t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */ +@@ -347,45 +347,45 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1); + t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1); + t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); + t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); + t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; + +- t = cpu->isar.id_aa64pfr1; ++ t = cpu->isar.regs[ID_AA64PFR1]; + t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); +- cpu->isar.id_aa64pfr1 = t; ++ cpu->isar.regs[ID_AA64PFR1] = t; + +- t = cpu->isar.id_aa64mmfr1; ++ t = cpu->isar.regs[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; ++ cpu->isar.regs[ID_AA64MMFR1] = t; + + /* Replicate the same data to the 32-bit id registers. */ +- u = cpu->isar.id_isar5; ++ u = cpu->isar.regs[ID_ISAR5]; + u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */ + u = FIELD_DP32(u, ID_ISAR5, SHA1, 1); + u = FIELD_DP32(u, ID_ISAR5, SHA2, 1); + u = FIELD_DP32(u, ID_ISAR5, CRC32, 1); + u = FIELD_DP32(u, ID_ISAR5, RDM, 1); + u = FIELD_DP32(u, ID_ISAR5, VCMA, 1); +- cpu->isar.id_isar5 = u; ++ cpu->isar.regs[ID_ISAR5] = u; + +- u = cpu->isar.id_isar6; ++ u = cpu->isar.regs[ID_ISAR6]; + u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1); + u = FIELD_DP32(u, ID_ISAR6, DP, 1); + u = FIELD_DP32(u, ID_ISAR6, FHM, 1); + u = FIELD_DP32(u, ID_ISAR6, SB, 1); + u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1); +- cpu->isar.id_isar6 = u; ++ cpu->isar.regs[ID_ISAR6] = u; + +- u = cpu->isar.id_mmfr3; ++ u = cpu->isar.regs[ID_MMFR3]; + u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */ +- cpu->isar.id_mmfr3 = u; ++ cpu->isar.regs[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 49cd7a7ee4..459af43101 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->isar.dbgdidr, ++ .type = ARM_CP_CONST, .resetvalue = cpu->isar.regs[DBGDIDR], + }; + + /* Note that all these register fields hold "number of Xs minus 1". */ +@@ -5672,7 +5672,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) + { + ARMCPU *cpu = env_archcpu(env); +- uint64_t pfr0 = cpu->isar.id_aa64pfr0; ++ uint64_t pfr0 = cpu->isar.regs[ID_AA64PFR0]; + + if (env->gicv3state) { + pfr0 |= 1 << 24; +@@ -5898,7 +5898,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->isar.id_dfr0 }, ++ .resetvalue = cpu->isar.regs[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, +@@ -5906,51 +5906,51 @@ 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->isar.id_mmfr0 }, ++ .resetvalue = cpu->isar.regs[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->isar.id_mmfr1 }, ++ .resetvalue = cpu->isar.regs[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->isar.id_mmfr2 }, ++ .resetvalue = cpu->isar.regs[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->isar.id_mmfr3 }, ++ .resetvalue = cpu->isar.regs[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, +- .resetvalue = cpu->isar.id_isar0 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR0] }, + { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_isar1 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR1] }, + { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_isar2 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR2] }, + { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_isar3 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR3] }, + { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_isar4 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR4] }, + { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_isar5 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR5] }, + { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_mmfr4 }, ++ .resetvalue = cpu->isar.regs[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, +- .resetvalue = cpu->isar.id_isar6 }, ++ .resetvalue = cpu->isar.regs[ID_ISAR6] }, + REGINFO_SENTINEL + }; + define_arm_cp_regs(cpu, v6_idregs); +@@ -6074,7 +6074,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + { .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64pfr1}, ++ .resetvalue = cpu->isar.regs[ID_AA64PFR1]}, + { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -6103,11 +6103,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->isar.id_aa64dfr0 }, ++ .resetvalue = cpu->isar.regs[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->isar.id_aa64dfr1 }, ++ .resetvalue = cpu->isar.regs[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, +@@ -6135,11 +6135,11 @@ void register_cp_regs_for_features(ARMCPU *cpu) + { .name = "ID_AA64ISAR0_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64isar0 }, ++ .resetvalue = cpu->isar.regs[ID_AA64ISAR0] }, + { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64isar1 }, ++ .resetvalue = cpu->isar.regs[ID_AA64ISAR1] }, + { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -6167,15 +6167,15 @@ void register_cp_regs_for_features(ARMCPU *cpu) + { .name = "ID_AA64MMFR0_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64mmfr0 }, ++ .resetvalue = cpu->isar.regs[ID_AA64MMFR0] }, + { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64mmfr1 }, ++ .resetvalue = cpu->isar.regs[ID_AA64MMFR1] }, + { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64mmfr2 }, ++ .resetvalue = cpu->isar.regs[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, +@@ -6199,15 +6199,15 @@ void register_cp_regs_for_features(ARMCPU *cpu) + { .name = "MVFR0_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.mvfr0 }, ++ .resetvalue = cpu->isar.regs[MVFR0] }, + { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.mvfr1 }, ++ .resetvalue = cpu->isar.regs[MVFR1] }, + { .name = "MVFR2_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.mvfr2 }, ++ .resetvalue = cpu->isar.regs[MVFR2] }, + { .name = "MVFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 3, + .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->isar.id_mmfr4, ID_MMFR4, HPDS) != 0) { ++ if (FIELD_EX32(cpu->isar.regs[ID_MMFR4], ID_MMFR4, HPDS) != 0) { + define_one_arm_cp_reg(cpu, &ttbcr2_reginfo); + } + } +diff --git a/target/arm/internals.h b/target/arm/internals.h +index 1d01ecc413..2da13ba807 100644 +--- a/target/arm/internals.h ++++ b/target/arm/internals.h +@@ -237,7 +237,7 @@ static inline unsigned int arm_pamax(ARMCPU *cpu) + [5] = 48, + }; + unsigned int parange = +- FIELD_EX64(cpu->isar.id_aa64mmfr0, ID_AA64MMFR0, PARANGE); ++ FIELD_EX64(cpu->isar.regs[ID_AA64MMFR0], ID_AA64MMFR0, PARANGE); + + /* id_aa64mmfr0 is a read-only register so values outside of the + * supported mappings can be considered an implementation error. */ +@@ -865,9 +865,9 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) + 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; ++ return FIELD_EX64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, BRPS) + 1; + } else { +- return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1; ++ return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, BRPS) + 1; + } + } + +@@ -879,9 +879,9 @@ static inline int arm_num_brps(ARMCPU *cpu) + 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; ++ return FIELD_EX64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, WRPS) + 1; + } else { +- return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1; ++ return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, WRPS) + 1; + } + } + +@@ -893,9 +893,10 @@ static inline int arm_num_wrps(ARMCPU *cpu) + 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; ++ return FIELD_EX64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, ++ CTX_CMPS) + 1; + } else { +- return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1; ++ return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, CTX_CMPS) + 1; + } + } + +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index 2a88b8df37..06cf31e809 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -455,7 +455,7 @@ static inline void unset_feature(uint64_t *features, int feature) + *features &= ~(1ULL << feature); + } + +-static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) ++static int read_sys_reg32(int fd, uint64_t *pret, uint64_t id) + { + uint64_t ret; + struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)&ret }; +@@ -509,7 +509,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + ahcf->target = init.target; + ahcf->dtb_compatible = "arm,arm-v8"; + +- err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, ++ err = read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64PFR0], + ARM64_SYS_REG(3, 0, 0, 4, 0)); + if (unlikely(err < 0)) { + /* +@@ -528,24 +528,24 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * ??? Either of these sounds like too much effort just + * to work around running a modern host kernel. + */ +- ahcf->isar.id_aa64pfr0 = 0x00000011; /* EL1&0, AArch64 only */ ++ ahcf->isar.regs[ID_AA64PFR0] = 0x00000011; /* EL1&0, AArch64 only */ + err = 0; + } else { +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64PFR1], + ARM64_SYS_REG(3, 0, 0, 4, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64DFR0], + ARM64_SYS_REG(3, 0, 0, 5, 0)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64DFR1], + ARM64_SYS_REG(3, 0, 0, 5, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ISAR0], + ARM64_SYS_REG(3, 0, 0, 6, 0)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ISAR1], + ARM64_SYS_REG(3, 0, 0, 6, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR0], + ARM64_SYS_REG(3, 0, 0, 7, 0)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR1], + ARM64_SYS_REG(3, 0, 0, 7, 1)); +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64MMFR2], + ARM64_SYS_REG(3, 0, 0, 7, 2)); + + /* +@@ -555,38 +555,38 @@ 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, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_DFR0], + ARM64_SYS_REG(3, 0, 0, 1, 2)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR0], + ARM64_SYS_REG(3, 0, 0, 1, 4)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR1], + ARM64_SYS_REG(3, 0, 0, 1, 5)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR2], + ARM64_SYS_REG(3, 0, 0, 1, 6)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR3], + ARM64_SYS_REG(3, 0, 0, 1, 7)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR0], + ARM64_SYS_REG(3, 0, 0, 2, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR1], + ARM64_SYS_REG(3, 0, 0, 2, 1)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR2], + ARM64_SYS_REG(3, 0, 0, 2, 2)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR3], + ARM64_SYS_REG(3, 0, 0, 2, 3)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR4], + ARM64_SYS_REG(3, 0, 0, 2, 4)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR5], + ARM64_SYS_REG(3, 0, 0, 2, 5)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_MMFR4], + ARM64_SYS_REG(3, 0, 0, 2, 6)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_ISAR6], + ARM64_SYS_REG(3, 0, 0, 2, 7)); + +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR0], + ARM64_SYS_REG(3, 0, 0, 3, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR1], + ARM64_SYS_REG(3, 0, 0, 3, 1)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[MVFR2], + ARM64_SYS_REG(3, 0, 0, 3, 2)); + + /* +@@ -599,14 +599,16 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * 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); ++ if (FIELD_EX32(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL1) >= 2) { ++ int wrps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ++ ID_AA64DFR0, WRPS); ++ int brps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ++ ID_AA64DFR0, BRPS); + int ctx_cmps = +- FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); ++ FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, CTX_CMPS); + int version = 6; /* ARMv8 debug architecture */ + bool has_el3 = +- !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); ++ !!FIELD_EX32(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL3); + uint32_t dbgdidr = 0; + + dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); +@@ -616,7 +618,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + 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; ++ ahcf->isar.regs[DBGDIDR] = dbgdidr; + } + } + +-- +2.23.0 + -- Gitee From 3d21dabc5a1a1cc35329ce35305e0cde72cece9b Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 6 Aug 2020 16:14:35 +0800 Subject: [PATCH 15/28] 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 Signed-off-by: Peng Liang (cherry-picked from commit d7d6c711c44f18d34c7d5e730dd66da3664e02d5) --- ...rm-parse-cpu-feature-related-options.patch | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 target-arm-parse-cpu-feature-related-options.patch diff --git a/target-arm-parse-cpu-feature-related-options.patch b/target-arm-parse-cpu-feature-related-options.patch new file mode 100644 index 00000000..b215a9c7 --- /dev/null +++ b/target-arm-parse-cpu-feature-related-options.patch @@ -0,0 +1,125 @@ +From 01dc5cdc6f8664601577c48d8d8b90775e2bb6d5 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:35 +0800 +Subject: [PATCH] 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 +Signed-off-by: Peng Liang +(cherry-picked from commit d7d6c711c44f18d34c7d5e730dd66da3664e02d5) +--- + target/arm/cpu64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 83 insertions(+) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index fe64875216..7de208488c 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.23.0 + -- Gitee From e3be4ea4ade84a207cb20f3b486c5b66772af3d1 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 6 Aug 2020 16:14:37 +0800 Subject: [PATCH 16/28] 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 Signed-off-by: Peng Liang (cherry-picked from commit 234f15e02b3b6e7195cc2cba0de3b7053dc9da09) --- ...m-register-CPU-features-for-property.patch | 399 ++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 target-arm-register-CPU-features-for-property.patch diff --git a/target-arm-register-CPU-features-for-property.patch b/target-arm-register-CPU-features-for-property.patch new file mode 100644 index 00000000..ab214198 --- /dev/null +++ b/target-arm-register-CPU-features-for-property.patch @@ -0,0 +1,399 @@ +From eea75b5ba8bcfe97521306c6183708cd9596270b Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:37 +0800 +Subject: [PATCH] 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 +Signed-off-by: Peng Liang +(cherry-picked from commit 234f15e02b3b6e7195cc2cba0de3b7053dc9da09) +--- + target/arm/cpu.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 343 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 5bcdad0c5e..3f63312c85 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.23.0 + -- Gitee From bd1a51d1dd6b97e9544b58c3161da8aaf67b5ec4 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 6 Aug 2020 16:14:40 +0800 Subject: [PATCH 17/28] 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 Signed-off-by: Peng Liang (cherry-picked from commit f4e592d1235bbb1290b8bc3684cb57c4304d63dc) --- ...w-ID-registers-to-synchronize-to-KVM.patch | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch diff --git a/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch b/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch new file mode 100644 index 00000000..37a2daab --- /dev/null +++ b/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch @@ -0,0 +1,161 @@ +From ad9e15e9ea89f29cece5c9f96517ec3c055178d0 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:40 +0800 +Subject: [PATCH] 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 +Signed-off-by: Peng Liang +(cherry-picked from commit f4e592d1235bbb1290b8bc3684cb57c4304d63dc) +--- + 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 459af43101..97b6b86197 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 4f131f687d..229b17cea0 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 0de5f83ee8..9b7104d622 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.23.0 + -- Gitee From f35baabcce856f073c4ef35b975d13c28e9356bb Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 6 Aug 2020 16:14:46 +0800 Subject: [PATCH 18/28] 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 Signed-off-by: Peng Liang (cherry-picked from commit 9a16d2b2389664aa50e63c33af0ea94afb45185b) --- ...duce-CPU-feature-dependency-mechanis.patch | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 target-arm-introduce-CPU-feature-dependency-mechanis.patch diff --git a/target-arm-introduce-CPU-feature-dependency-mechanis.patch b/target-arm-introduce-CPU-feature-dependency-mechanis.patch new file mode 100644 index 00000000..3b4752a6 --- /dev/null +++ b/target-arm-introduce-CPU-feature-dependency-mechanis.patch @@ -0,0 +1,185 @@ +From f52bdbd22a9c0ab7e0cd602988fb2e0780e74766 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:46 +0800 +Subject: [PATCH] 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 +Signed-off-by: Peng Liang +(cherry-picked from commit 9a16d2b2389664aa50e63c33af0ea94afb45185b) +--- + target/arm/cpu.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 129 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 3f63312c85..d55765386b 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.23.0 + -- Gitee From 411ca8c85ebe75db4313ba8b02b3fc7e3cb7aa20 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 6 Aug 2020 16:14:55 +0800 Subject: [PATCH 19/28] 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 Signed-off-by: Peng Liang (cherry-picked from commit e55671b1d033f8815316407e0274fd85f48bc4df) --- ...rm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch diff --git a/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch b/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch new file mode 100644 index 00000000..17f6e1fe --- /dev/null +++ b/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch @@ -0,0 +1,93 @@ +From b1fc3b2b4e4d846f00fa4baa1e298323d173821c Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:55 +0800 +Subject: [PATCH] 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 +Signed-off-by: Peng Liang +(cherry-picked from commit e55671b1d033f8815316407e0274fd85f48bc4df) +--- + 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 744e888e68..4844edc3a3 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 d55765386b..db46afba7b 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 06cf31e809..05345556dd 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 9b7104d622..49e80878f4 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.23.0 + -- Gitee From e75eba82c94537ffe63c6de6d794d2f4af9b7fd2 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 6 Aug 2020 16:14:58 +0800 Subject: [PATCH 20/28] 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 Signed-off-by: Peng Liang (cherry-picked from commit e39f3e8e4d945a87a936388204b3125041da4032) --- ...PU-features-to-query-cpu-model-expan.patch | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 target-arm-Add-CPU-features-to-query-cpu-model-expan.patch diff --git a/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch b/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch new file mode 100644 index 00000000..34958f1e --- /dev/null +++ b/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch @@ -0,0 +1,90 @@ +From 5d9d03aee0407e27f38ec3e4996c9312d8a81f57 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Thu, 6 Aug 2020 16:14:58 +0800 +Subject: [PATCH] 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 +Signed-off-by: Peng Liang +(cherry-picked from commit e39f3e8e4d945a87a936388204b3125041da4032) +--- + 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 db46afba7b..dcf9f49ed3 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 7bb481fb4d..068c3fa2ad 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 e2b1d117a4..7c2ff3c06e 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.23.0 + -- Gitee From 53269940a0e6e1b7bf783a03a1c096a88a2923f8 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Tue, 11 Aug 2020 10:18:57 +0800 Subject: [PATCH 21/28] target/arm: Update ID fields Update definitions for ID fields, up to ARMv8.6. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang (cherry-picked from commit f87ed4385cdadf4af38b76385d2aa581b7ade6c9) --- target-arm-Update-ID-fields.patch | 85 +++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 target-arm-Update-ID-fields.patch diff --git a/target-arm-Update-ID-fields.patch b/target-arm-Update-ID-fields.patch new file mode 100644 index 00000000..233034aa --- /dev/null +++ b/target-arm-Update-ID-fields.patch @@ -0,0 +1,85 @@ +From e6c94219b9f6a201853b19c8db0b02ef8ee4a9d5 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Tue, 11 Aug 2020 10:18:57 +0800 +Subject: [PATCH] target/arm: Update ID fields + +Update definitions for ID fields, up to ARMv8.6. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +(cherry-picked from commit f87ed4385cdadf4af38b76385d2aa581b7ade6c9) +--- + target/arm/cpu.h | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 068c3fa2ad..eb875e112a 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.23.0 + -- Gitee From 6e86afded672fcba85ec68114eb0bfd49b025dce Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Tue, 11 Aug 2020 10:28:10 +0800 Subject: [PATCH 22/28] target/arm: Add more CPU features Add i8mm, bf16, and dgh CPU features for AArch64. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang (cherry-picked from commit 8acf8dd1a20c53453d028a7b86f593019329d8c1) --- target-arm-Add-more-CPU-features.patch | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 target-arm-Add-more-CPU-features.patch diff --git a/target-arm-Add-more-CPU-features.patch b/target-arm-Add-more-CPU-features.patch new file mode 100644 index 00000000..550c52cc --- /dev/null +++ b/target-arm-Add-more-CPU-features.patch @@ -0,0 +1,31 @@ +From f4948980bd6ede3255643982afe01f56c93fec71 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Tue, 11 Aug 2020 10:28:10 +0800 +Subject: [PATCH] target/arm: Add more CPU features + +Add i8mm, bf16, and dgh CPU features for AArch64. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +(cherry-picked from commit 8acf8dd1a20c53453d028a7b86f593019329d8c1) +--- + target/arm/cpu.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index dcf9f49ed3..7ae2d3da56 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.23.0 + -- Gitee From 3ba8d2311e57c6b166cc6e22add64e03e1f4de0e Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Mon, 7 Sep 2020 14:07:07 +0800 Subject: [PATCH 23/28] target/arm: ignore evtstrm and cpuid CPU features evtstrm and cpuid cann't be controlled by VMM: 1. evtstrm: The generic timer is configured to generate events at a frequency of approximately 100KHz. It's controlled by the linux kernel config CONFIG_ARM_ARCH_TIMER_EVTSTREAM. 2. cpuid: EL0 access to certain ID registers is available. It's always set by linux kernel after 77c97b4ee2129 ("arm64: cpufeature: Expose CPUID registers by emulation"). However, they are exposed by getauxval() and /proc/cpuinfo. Hence, let's report and ignore the CPU features if someone set them. Signed-off-by: Peng Liang (cherry-picked from commit 02f8ee8f420e62aff233748c7e848a1c1197b741) --- ...gnore-evtstrm-and-cpuid-CPU-features.patch | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch diff --git a/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch b/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch new file mode 100644 index 00000000..060d511a --- /dev/null +++ b/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch @@ -0,0 +1,67 @@ +From 5cd3062c5aed4b15d0df1af4e606b4e5ddbc78f7 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Mon, 7 Sep 2020 14:07:07 +0800 +Subject: [PATCH] target/arm: ignore evtstrm and cpuid CPU features + +evtstrm and cpuid cann't be controlled by VMM: +1. evtstrm: The generic timer is configured to generate events at a + frequency of approximately 100KHz. It's controlled by the linux + kernel config CONFIG_ARM_ARCH_TIMER_EVTSTREAM. +2. cpuid: EL0 access to certain ID registers is available. It's always + set by linux kernel after 77c97b4ee2129 ("arm64: cpufeature: Expose + CPUID registers by emulation"). +However, they are exposed by getauxval() and /proc/cpuinfo. Hence, +let's report and ignore the CPU features if someone set them. + +Signed-off-by: Peng Liang +(cherry-picked from commit 02f8ee8f420e62aff233748c7e848a1c1197b741) +--- + target/arm/cpu64.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 7de208488c..726d123d8e 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -506,10 +506,37 @@ static void arm_cpu_parse_featurestr(const char *typename, char *features, + } + } + ++static const char *unconfigurable_feats[] = { ++ "evtstrm", ++ "cpuid", ++ NULL ++}; ++ ++static bool is_configurable_feat(const char *name) ++{ ++ int i; ++ ++ for (i = 0; unconfigurable_feats[i]; ++i) { ++ if (g_strcmp0(unconfigurable_feats[i], name) == 0) { ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static void + cpu_add_feat_as_prop(const char *typename, const char *name, const char *val) + { +- GlobalProperty *prop = g_new0(typeof(*prop), 1); ++ GlobalProperty *prop; ++ ++ if (!is_configurable_feat(name)) { ++ info_report("CPU feature '%s' is not configurable by QEMU. Ignore it.", ++ name); ++ return; ++ } ++ ++ prop = g_new0(typeof(*prop), 1); + prop->driver = typename; + prop->property = g_strdup(name); + prop->value = g_strdup(val); +-- +2.23.0 + -- Gitee From 1850ba2b9e89c0d2b129ae239249ba556fcb2ef4 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Sat, 19 Sep 2020 09:04:45 +0800 Subject: [PATCH 24/28] target/arm: Update the ID registers of Kunpeng-920 The values of some ID registers in Kunpeng-920 are not exactly correct. Let's update them. The values are read from Kunpeng-920 by calling read_sysreg_s. Signed-off-by: Peng Liang (cherry-picked from commit b54ca94f19a9b22537712638ae05d2095258eb80) --- ...date-the-ID-registers-of-Kunpeng-920.patch | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 target-arm-Update-the-ID-registers-of-Kunpeng-920.patch diff --git a/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch b/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch new file mode 100644 index 00000000..a86bf0bf --- /dev/null +++ b/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch @@ -0,0 +1,58 @@ +From 8e19c7e6d89bb4da69a46934469c7bb74e088524 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Sat, 19 Sep 2020 09:04:45 +0800 +Subject: [PATCH] target/arm: Update the ID registers of Kunpeng-920 + +The values of some ID registers in Kunpeng-920 are not exactly correct. +Let's update them. The values are read from Kunpeng-920 by calling +read_sysreg_s. + +Signed-off-by: Peng Liang +(cherry-picked from commit b54ca94f19a9b22537712638ae05d2095258eb80) +--- + target/arm/cpu64.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 726d123d8e..a1649f8844 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -275,10 +275,33 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + + cpu->midr = 0x480fd010; + cpu->ctr = 0x84448004; +- cpu->isar.regs[ID_AA64PFR0] = 0x11001111; ++ cpu->isar.regs[ID_ISAR0] = 0; ++ cpu->isar.regs[ID_ISAR1] = 0; ++ cpu->isar.regs[ID_ISAR2] = 0; ++ cpu->isar.regs[ID_ISAR3] = 0; ++ cpu->isar.regs[ID_ISAR4] = 0; ++ cpu->isar.regs[ID_ISAR5] = 0; ++ cpu->isar.regs[ID_MMFR0] = 0; ++ cpu->isar.regs[ID_MMFR1] = 0; ++ cpu->isar.regs[ID_MMFR2] = 0; ++ cpu->isar.regs[ID_MMFR3] = 0; ++ cpu->isar.regs[ID_MMFR4] = 0; ++ cpu->isar.regs[MVFR0] = 0; ++ cpu->isar.regs[MVFR1] = 0; ++ cpu->isar.regs[MVFR2] = 0; ++ cpu->isar.regs[ID_DFR0] = 0; ++ cpu->isar.regs[MVFR2] = 0; ++ cpu->isar.regs[MVFR2] = 0; ++ cpu->isar.regs[MVFR2] = 0; ++ cpu->id_pfr0 = 0; ++ cpu->id_pfr1 = 0; ++ cpu->isar.regs[ID_AA64PFR0] = 0x0000010011111111; + cpu->isar.regs[ID_AA64DFR0] = 0x110305408; +- cpu->isar.regs[ID_AA64ISAR0] = 0x10211120; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x0001100010211120; ++ cpu->isar.regs[ID_AA64ISAR1] = 0x00011001; + cpu->isar.regs[ID_AA64MMFR0] = 0x101125; ++ cpu->isar.regs[ID_AA64MMFR1] = 0x10211122; ++ cpu->isar.regs[ID_AA64MMFR2] = 0x00001011; + } + + static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name, +-- +2.23.0 + -- Gitee From a257e205fd1d973d676195e00bd703a0c039fcef Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Wed, 16 Sep 2020 19:40:28 +0800 Subject: [PATCH 25/28] target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest Some AArch64 CPU doesn't support AArch32 mode, and the values of AArch32 registers are all 0. Hence, We'd better not to modify AArch32 registers in AArch64 mode. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang (cherry-picked from commit 88e3146118230de8b99280db219a6a6c47bebce1) --- ...set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch diff --git a/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch b/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch new file mode 100644 index 00000000..18ae1702 --- /dev/null +++ b/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch @@ -0,0 +1,32 @@ +From 3f12c87017c6e052fc769a1b49278ca6bcce7a96 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Wed, 16 Sep 2020 19:40:28 +0800 +Subject: [PATCH] target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest + +Some AArch64 CPU doesn't support AArch32 mode, and the values of AArch32 +registers are all 0. Hence, We'd better not to modify AArch32 registers +in AArch64 mode. + +Signed-off-by: zhanghailiang +Signed-off-by: Peng Liang +(cherry-picked from commit 88e3146118230de8b99280db219a6a6c47bebce1) +--- + target/arm/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 97b6b86197..b262f5d6c5 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -5672,7 +5672,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + ARMCPU *cpu = env_archcpu(env); + uint64_t pfr1 = cpu->id_pfr1; + +- if (env->gicv3state) { ++ if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && env->gicv3state) { + pfr1 |= 1 << 28; + } + return pfr1; +-- +2.23.0 + -- Gitee From 4196932ecfc99e74d17f12fcf07d8cf29bcfcbae Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Mon, 21 Sep 2020 22:14:20 +0800 Subject: [PATCH 26/28] target/arm: clear EL2 and EL3 only when kvm is not enabled When has_el2 and has_el3 are disabled, which is the default value for virt machine, QEMU will clear the corresponding field in ID_PFR1_EL1 and ID_AA64PFR0_EL1 to not expose EL3 and EL2 to guest. Because KVM doesn't support to emulate ID registers in AArch64 before, it will not take effect. Hence, clear EL2 and EL3 only when kvm is not enabled for backwards compatibility. Signed-off-by: Peng Liang (cherry-picked from commit ad6ce039cab07b6a99ccaa36fbb0043ae85a74c9) --- ...-EL2-and-EL3-only-when-kvm-is-not-en.patch | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch diff --git a/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch b/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch new file mode 100644 index 00000000..a323a3f9 --- /dev/null +++ b/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch @@ -0,0 +1,43 @@ +From 0004cdfd44cd1aafd7b2142385e67acdd632ad30 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Mon, 21 Sep 2020 22:14:20 +0800 +Subject: [PATCH] target/arm: clear EL2 and EL3 only when kvm is not enabled + +When has_el2 and has_el3 are disabled, which is the default value for +virt machine, QEMU will clear the corresponding field in ID_PFR1_EL1 and +ID_AA64PFR0_EL1 to not expose EL3 and EL2 to guest. Because KVM doesn't +support to emulate ID registers in AArch64 before, it will not take +effect. Hence, clear EL2 and EL3 only when kvm is not enabled for +backwards compatibility. + +Signed-off-by: Peng Liang +(cherry-picked from commit ad6ce039cab07b6a99ccaa36fbb0043ae85a74c9) +--- + target/arm/cpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 7ae2d3da56..3f62336acf 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1996,7 +1996,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + } + } + +- if (!cpu->has_el3) { ++ if (!cpu->has_el3 && !kvm_enabled()) { + /* If the has_el3 CPU property is disabled then we need to disable the + * feature. + */ +@@ -2037,7 +2037,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + cpu->pmceid1 = 0; + } + +- if (!arm_feature(env, ARM_FEATURE_EL2)) { ++ if (!arm_feature(env, ARM_FEATURE_EL2) && !kvm_enabled()) { + /* Disable the hypervisor feature bits in the processor feature + * registers if we don't have EL2. These are id_pfr1[15:12] and + * id_aa64pfr0_el1[11:8]. +-- +2.23.0 + -- Gitee From 618d721818d993c6df5340446a2e05501c7d2e60 Mon Sep 17 00:00:00 2001 From: Euler Robot Date: Mon, 2 Nov 2020 21:28:15 +0800 Subject: [PATCH 27/28] spec: Update patch and changelog with !29 target/arm: Add isar_feature tests for PAN + ATS1E1 target/arm: Add ID_AA64MMFR2_EL1 target/arm: Add and use FIELD definitions for ID_AA64DFR0_EL1 target/arm: Use FIELD macros for clearing ID_DFR0 PERFMON field target/arm: Define an aa32_pmu_8_1 isar feature test function target/arm: Add _aa64_ and _any_ versions of pmu_8_1 isar checks target/arm: Stop assuming DBGDIDR always exists target/arm: Move DBGDIDR into ARMISARegisters target/arm: Enable ARMv8.2-ATS1E1 in -cpu max target/arm: Test correct register in aa32_pan and aa32_ats1e1 checks target/arm: Read debug-related ID registers from KVM target/arm/monitor: Introduce qmp_query_cpu_model_expansion target/arm/monitor: query-cpu-model-expansion crashed qemu when using machine type none target/arm: convert isar regs to array target/arm: parse cpu feature related options target/arm: register CPU features for property target/arm: Allow ID registers to synchronize to KVM target/arm: introduce CPU feature dependency mechanism target/arm: introduce KVM_CAP_ARM_CPU_FEATURE target/arm: Add CPU features to query-cpu-model-expansion target/arm: Update ID fields target/arm: Add more CPU features target/arm: ignore evtstrm and cpuid CPU features target/arm: Update the ID registers of Kunpeng-920 target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest target/arm: clear EL2 and EL3 only when kvm is not enabled Signed-off-by: Andrew Jones Signed-off-by: Liang Yan Signed-off-by: Peng Liang Signed-off-by: Peter Maydell Signed-off-by: Richard Henderson Signed-off-by: zhanghailiang --- qemu.spec | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/qemu.spec b/qemu.spec index 18aff9b4..3fce264c 100644 --- a/qemu.spec +++ b/qemu.spec @@ -196,6 +196,32 @@ Patch0183: sm501-Clean-up-local-variables-in-sm501_2d_operation.patch Patch0184: sm501-Replace-hand-written-implementation-with-pixma.patch Patch0185: pci-check-bus-pointer-before-dereference.patch Patch0186: hw-ide-check-null-block-before-_cancel_dma_sync.patch +Patch0187: target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch +Patch0188: target-arm-Add-ID_AA64MMFR2_EL1.patch +Patch0189: target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch +Patch0190: target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch +Patch0191: target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch +Patch0192: target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch +Patch0193: target-arm-Stop-assuming-DBGDIDR-always-exists.patch +Patch0194: target-arm-Move-DBGDIDR-into-ARMISARegisters.patch +Patch0195: target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch +Patch0196: target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch +Patch0197: target-arm-Read-debug-related-ID-registers-from-KVM.patch +Patch0198: target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch +Patch0199: target-arm-monitor-query-cpu-model-expansion-crashed.patch +Patch0200: target-arm-convert-isar-regs-to-array.patch +Patch0201: target-arm-parse-cpu-feature-related-options.patch +Patch0202: target-arm-register-CPU-features-for-property.patch +Patch0203: target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch +Patch0204: target-arm-introduce-CPU-feature-dependency-mechanis.patch +Patch0205: target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch +Patch0206: target-arm-Add-CPU-features-to-query-cpu-model-expan.patch +Patch0207: target-arm-Update-ID-fields.patch +Patch0208: target-arm-Add-more-CPU-features.patch +Patch0209: target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch +Patch0210: target-arm-Update-the-ID-registers-of-Kunpeng-920.patch +Patch0211: target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch +Patch0212: target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch BuildRequires: flex BuildRequires: bison @@ -541,6 +567,34 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Mon Sep 21 2020 Huawei Technologies Co., Ltd +- target/arm: Add isar_feature tests for PAN + ATS1E1 +- target/arm: Add ID_AA64MMFR2_EL1 +- target/arm: Add and use FIELD definitions for ID_AA64DFR0_EL1 +- target/arm: Use FIELD macros for clearing ID_DFR0 PERFMON field +- target/arm: Define an aa32_pmu_8_1 isar feature test function +- target/arm: Add _aa64_ and _any_ versions of pmu_8_1 isar checks +- target/arm: Stop assuming DBGDIDR always exists +- target/arm: Move DBGDIDR into ARMISARegisters +- target/arm: Enable ARMv8.2-ATS1E1 in -cpu max +- target/arm: Test correct register in aa32_pan and aa32_ats1e1 checks +- target/arm: Read debug-related ID registers from KVM +- target/arm/monitor: Introduce qmp_query_cpu_model_expansion +- target/arm/monitor: query-cpu-model-expansion crashed qemu when using machine type none +- target/arm: convert isar regs to array +- target/arm: parse cpu feature related options +- target/arm: register CPU features for property +- target/arm: Allow ID registers to synchronize to KVM +- target/arm: introduce CPU feature dependency mechanism +- target/arm: introduce KVM_CAP_ARM_CPU_FEATURE +- target/arm: Add CPU features to query-cpu-model-expansion +- target/arm: Update ID fields +- target/arm: Add more CPU features +- target/arm: ignore evtstrm and cpuid CPU features +- target/arm: Update the ID registers of Kunpeng-920 +- target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest +- target/arm: clear EL2 and EL3 only when kvm is not enabled + * Wed Oct 14 2020 Prasad J Pandit - pci: check bus pointer before dereference - hw/ide: check null block before _cancel_dma_sync -- Gitee From 2eaac8df60a71793ae639384f7702fb5775eee43 Mon Sep 17 00:00:00 2001 From: Euler Robot Date: Mon, 2 Nov 2020 21:28:16 +0800 Subject: [PATCH 28/28] spec: Update release version with !29 increase release verison by one Signed-off-by: Euler Robot --- qemu.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu.spec b/qemu.spec index 3fce264c..699a553b 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 4.1.0 -Release: 23 +Release: 24 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY -- Gitee