From 3bcc53980b05dbcdc9bc70fc7ec3bc37320edcbd Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Sep 2023 19:54:52 +0100 Subject: [PATCH 01/41] target/arm: Correct minor errors in Cortex-A710 definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct a couple of minor errors in the Cortex-A710 definition: * ID_AA64DFR0_EL1.DebugVer is 9 (indicating Armv8.4 debug architecture) * ID_AA64ISAR1_EL1.APA is 5 (indicating more PAuth support) * there is an IMPDEF CPUCFR_EL1, like that on the Neoverse-N1 Fixes: e3d45c0a89576 ("target/arm: Implement cortex-a710") Signed-off-by: Peter Maydell Tested-by: Marcin Juszkiewicz Reviewed-by: Alex Bennée Message-id: 20230915185453.1871167-2-peter.maydell@linaro.org --- target/arm/tcg/cpu64.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index d978aa5f7a..e2bcac4854 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -840,6 +840,13 @@ static const ARMCPRegInfo cortex_a710_cp_reginfo[] = { { .name = "CPUPFR_EL3", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 6, .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + /* + * Report CPUCFR_EL1.SCU as 1, as we do not implement the DSU + * (and in particular its system registers). + */ + { .name = "CPUCFR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 0, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 4 }, /* * Stub RAMINDEX, as we don't actually implement caches, BTB, @@ -909,12 +916,12 @@ static void aarch64_a710_initfn(Object *obj) cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */ cpu->isar.id_aa64pfr1 = 0x0000000000000221ull; cpu->isar.id_aa64zfr0 = 0x0000110100110021ull; /* with Crypto */ - cpu->isar.id_aa64dfr0 = 0x000011f010305611ull; + cpu->isar.id_aa64dfr0 = 0x000011f010305619ull; cpu->isar.id_aa64dfr1 = 0; cpu->id_aa64afr0 = 0; cpu->id_aa64afr1 = 0; cpu->isar.id_aa64isar0 = 0x0221111110212120ull; /* with Crypto */ - cpu->isar.id_aa64isar1 = 0x0010111101211032ull; + cpu->isar.id_aa64isar1 = 0x0010111101211052ull; cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull; cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; cpu->isar.id_aa64mmfr2 = 0x1221011110101011ull; From dfff1000fef24f6686e0be5e6472613985a363dc Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 15 Sep 2023 19:54:53 +0100 Subject: [PATCH 02/41] target/arm: Implement Neoverse N2 CPU model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement a model of the Neoverse N2 CPU. This is an Armv9.0-A processor very similar to the Cortex-A710. The differences are: * no FEAT_EVT * FEAT_DGH (data gathering hint) * FEAT_NV (not yet implemented in QEMU) * Statistical Profiling Extension (not implemented in QEMU) * 48 bit physical address range, not 40 * CTR_EL0.DIC = 1 (no explicit icache cleaning needed) * PMCR_EL0.N = 6 (always 6 PMU counters, not 20) Because it has 48-bit physical address support, we can use this CPU in the sbsa-ref board as well as the virt board. Signed-off-by: Peter Maydell Tested-by: Marcin Juszkiewicz Reviewed-by: Alex Bennée Message-id: 20230915185453.1871167-3-peter.maydell@linaro.org --- docs/system/arm/virt.rst | 1 + hw/arm/sbsa-ref.c | 1 + hw/arm/virt.c | 1 + target/arm/tcg/cpu64.c | 103 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+) diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index e1697ac8f4..7c4c80180c 100644 --- a/docs/system/arm/virt.rst +++ b/docs/system/arm/virt.rst @@ -63,6 +63,7 @@ Supported guest CPU types: - ``host`` (with KVM only) - ``neoverse-n1`` (64-bit) - ``neoverse-v1`` (64-bit) +- ``neoverse-n2`` (64-bit) - ``max`` (same as ``host`` for KVM; best possible emulation with TCG) Note that the default is ``cortex-a15``, so for an AArch64 guest you must diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index e8a82618f0..bce44690e5 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -149,6 +149,7 @@ static const char * const valid_cpus[] = { ARM_CPU_TYPE_NAME("cortex-a72"), ARM_CPU_TYPE_NAME("neoverse-n1"), ARM_CPU_TYPE_NAME("neoverse-v1"), + ARM_CPU_TYPE_NAME("neoverse-n2"), ARM_CPU_TYPE_NAME("max"), }; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 529f1c089c..92085d2d8f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -215,6 +215,7 @@ static const char *valid_cpus[] = { ARM_CPU_TYPE_NAME("a64fx"), ARM_CPU_TYPE_NAME("neoverse-n1"), ARM_CPU_TYPE_NAME("neoverse-v1"), + ARM_CPU_TYPE_NAME("neoverse-n2"), #endif ARM_CPU_TYPE_NAME("cortex-a53"), ARM_CPU_TYPE_NAME("cortex-a57"), diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index e2bcac4854..a9a8c0a059 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -963,6 +963,108 @@ static void aarch64_a710_initfn(Object *obj) aarch64_add_sve_properties(obj); } +/* Extra IMPDEF regs in the N2 beyond those in the A710 */ +static const ARMCPRegInfo neoverse_n2_cp_reginfo[] = { + { .name = "CPURNDBR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 3, .opc2 = 0, + .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "CPURNDPEID_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 3, .opc2 = 1, + .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, +}; + +static void aarch64_neoverse_n2_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + cpu->dtb_compatible = "arm,neoverse-n2"; + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); + set_feature(&cpu->env, ARM_FEATURE_EL2); + set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); + + /* Ordered by Section B.5: AArch64 ID registers */ + cpu->midr = 0x410FD493; /* r0p3 */ + cpu->revidr = 0; + cpu->isar.id_pfr0 = 0x21110131; + cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ + cpu->isar.id_dfr0 = 0x16011099; + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; + cpu->isar.id_isar0 = 0x02101110; + cpu->isar.id_isar1 = 0x13112111; + cpu->isar.id_isar2 = 0x21232042; + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00010142; + cpu->isar.id_isar5 = 0x11011121; /* with Crypto */ + cpu->isar.id_mmfr4 = 0x01021110; + cpu->isar.id_isar6 = 0x01111111; + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; + cpu->isar.id_pfr2 = 0x00000011; + cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */ + cpu->isar.id_aa64pfr1 = 0x0000000000000221ull; + cpu->isar.id_aa64zfr0 = 0x0000110100110021ull; /* with Crypto */ + cpu->isar.id_aa64dfr0 = 0x000011f210305619ull; + cpu->isar.id_aa64dfr1 = 0; + cpu->id_aa64afr0 = 0; + cpu->id_aa64afr1 = 0; + cpu->isar.id_aa64isar0 = 0x0221111110212120ull; /* with Crypto */ + cpu->isar.id_aa64isar1 = 0x0011111101211052ull; + cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x1221011112101011ull; + cpu->clidr = 0x0000001482000023ull; + cpu->gm_blocksize = 4; + cpu->ctr = 0x00000004b444c004ull; + cpu->dcz_blocksize = 4; + /* TODO FEAT_MPAM: mpamidr_el1 = 0x0000_0001_001e_01ff */ + + /* Section B.7.2: PMCR_EL0 */ + cpu->isar.reset_pmcr_el0 = 0x3000; /* with 6 counters */ + + /* Section B.8.9: ICH_VTR_EL2 */ + cpu->gic_num_lrs = 4; + cpu->gic_vpribits = 5; + cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; + + /* Section 14: Scalable Vector Extensions support */ + cpu->sve_vq.supported = 1 << 0; /* 128bit */ + + /* + * The Neoverse N2 TRM does not list CCSIDR values. The layout of + * the caches are in text in Table 7-1, Table 8-1, and Table 9-1. + * + * L1: 4-way set associative 64-byte line size, total 64K. + * L2: 8-way set associative 64 byte line size, total either 512K or 1024K. + */ + cpu->ccsidr[0] = make_ccsidr64(4, 64, 64 * KiB); /* L1 dcache */ + cpu->ccsidr[1] = cpu->ccsidr[0]; /* L1 icache */ + cpu->ccsidr[2] = make_ccsidr64(8, 64, 512 * KiB); /* L2 cache */ + + /* FIXME: Not documented -- copied from neoverse-v1 */ + cpu->reset_sctlr = 0x30c50838; + + /* + * The Neoverse N2 has all of the Cortex-A710 IMPDEF registers, + * and a few more RNG related ones. + */ + define_arm_cp_regs(cpu, cortex_a710_cp_reginfo); + define_arm_cp_regs(cpu, neoverse_n2_cp_reginfo); + + aarch64_add_pauth_properties(obj); + aarch64_add_sve_properties(obj); +} + /* * -cpu max: a CPU with as many features enabled as our emulation supports. * The version of '-cpu max' for qemu-system-arm is defined in cpu32.c; @@ -1165,6 +1267,7 @@ static const ARMCPUInfo aarch64_cpus[] = { { .name = "a64fx", .initfn = aarch64_a64fx_initfn }, { .name = "neoverse-n1", .initfn = aarch64_neoverse_n1_initfn }, { .name = "neoverse-v1", .initfn = aarch64_neoverse_v1_initfn }, + { .name = "neoverse-n2", .initfn = aarch64_neoverse_n2_initfn }, }; static void aarch64_cpu_register_types(void) From 5a534314a85b735f766aa64b35697ed1d59f7068 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Oct 2023 17:35:05 +0100 Subject: [PATCH 03/41] target/arm: Move feature test functions to their own header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The feature test functions isar_feature_*() now take up nearly a thousand lines in target/arm/cpu.h. This header file is included by a lot of source files, most of which don't need these functions. Move the feature test functions to their own header file. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231024163510.2972081-2-peter.maydell@linaro.org --- bsd-user/arm/target_arch.h | 1 + hw/arm/armv7m.c | 1 + hw/intc/armv7m_nvic.c | 1 + linux-user/aarch64/cpu_loop.c | 1 + linux-user/aarch64/signal.c | 1 + linux-user/aarch64/target_prctl.h | 2 + linux-user/arm/signal.c | 1 + linux-user/elfload.c | 4 + linux-user/mmap.c | 4 + target/arm/arch_dump.c | 1 + target/arm/cpu-features.h | 994 ++++++++++++++++++++++++++++++ target/arm/cpu.c | 1 + target/arm/cpu.h | 971 ----------------------------- target/arm/cpu64.c | 1 + target/arm/debug_helper.c | 1 + target/arm/gdbstub.c | 1 + target/arm/helper.c | 1 + target/arm/internals.h | 1 + target/arm/kvm64.c | 1 + target/arm/machine.c | 1 + target/arm/ptw.c | 1 + target/arm/tcg/cpu64.c | 1 + target/arm/tcg/hflags.c | 1 + target/arm/tcg/m_helper.c | 1 + target/arm/tcg/op_helper.c | 1 + target/arm/tcg/pauth_helper.c | 1 + target/arm/tcg/tlb_helper.c | 1 + target/arm/tcg/translate.h | 2 +- target/arm/vfp_helper.c | 1 + 29 files changed, 1028 insertions(+), 972 deletions(-) create mode 100644 target/arm/cpu-features.h diff --git a/bsd-user/arm/target_arch.h b/bsd-user/arm/target_arch.h index 561934bbd2..d80cb85c64 100644 --- a/bsd-user/arm/target_arch.h +++ b/bsd-user/arm/target_arch.h @@ -21,6 +21,7 @@ #define TARGET_ARCH_H #include "qemu.h" +#include "target/arm/cpu-features.h" void target_cpu_set_tls(CPUARMState *env, target_ulong newtls); target_ulong target_cpu_get_tls(CPUARMState *env); diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 1f78e18872..d10abb36a8 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -21,6 +21,7 @@ #include "qemu/module.h" #include "qemu/log.h" #include "target/arm/idau.h" +#include "target/arm/cpu-features.h" #include "migration/vmstate.h" /* Bitbanded IO. Each word corresponds to a single bit. */ diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 03b6b8c986..942be7bd11 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -21,6 +21,7 @@ #include "sysemu/tcg.h" #include "sysemu/runstate.h" #include "target/arm/cpu.h" +#include "target/arm/cpu-features.h" #include "exec/exec-all.h" #include "exec/memop.h" #include "qemu/log.h" diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c index 2e2f7cf218..8c20dc8a39 100644 --- a/linux-user/aarch64/cpu_loop.c +++ b/linux-user/aarch64/cpu_loop.c @@ -25,6 +25,7 @@ #include "qemu/guest-random.h" #include "semihosting/common-semi.h" #include "target/arm/syndrome.h" +#include "target/arm/cpu-features.h" #define get_user_code_u32(x, gaddr, env) \ ({ abi_long __r = get_user_u32((x), (gaddr)); \ diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index b265cfd470..a1e22d526d 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -21,6 +21,7 @@ #include "user-internals.h" #include "signal-common.h" #include "linux-user/trace.h" +#include "target/arm/cpu-features.h" struct target_sigcontext { uint64_t fault_address; diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h index 907c314146..5067e7d731 100644 --- a/linux-user/aarch64/target_prctl.h +++ b/linux-user/aarch64/target_prctl.h @@ -6,6 +6,8 @@ #ifndef AARCH64_TARGET_PRCTL_H #define AARCH64_TARGET_PRCTL_H +#include "target/arm/cpu-features.h" + static abi_long do_prctl_sve_get_vl(CPUArchState *env) { ARMCPU *cpu = env_archcpu(env); diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c index cf99fd7b8a..4020601c54 100644 --- a/linux-user/arm/signal.c +++ b/linux-user/arm/signal.c @@ -21,6 +21,7 @@ #include "user-internals.h" #include "signal-common.h" #include "linux-user/trace.h" +#include "target/arm/cpu-features.h" struct target_sigcontext { abi_ulong trap_no; diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 2e3809f03c..baa69e5535 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -23,6 +23,10 @@ #include "target_signal.h" #include "accel/tcg/debuginfo.h" +#ifdef TARGET_ARM +#include "target/arm/cpu-features.h" +#endif + #ifdef _ARCH_PPC64 #undef ARCH_DLINFO #undef ELF_PLATFORM diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 7b44b9ff49..96c9433e27 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -26,6 +26,10 @@ #include "target_mman.h" #include "qemu/interval-tree.h" +#ifdef TARGET_ARM +#include "target/arm/cpu-features.h" +#endif + static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; static __thread int mmap_lock_count; diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c index 2d8e41ab8a..06cdf4ba28 100644 --- a/target/arm/arch_dump.c +++ b/target/arm/arch_dump.c @@ -22,6 +22,7 @@ #include "cpu.h" #include "elf.h" #include "sysemu/dump.h" +#include "cpu-features.h" /* struct user_pt_regs from arch/arm64/include/uapi/asm/ptrace.h */ struct aarch64_user_regs { diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h new file mode 100644 index 0000000000..bfc9bfafe7 --- /dev/null +++ b/target/arm/cpu-features.h @@ -0,0 +1,994 @@ +/* + * QEMU Arm CPU -- feature test functions + * + * Copyright (c) 2023 Linaro Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef TARGET_ARM_FEATURES_H +#define TARGET_ARM_FEATURES_H + +/* + * Naming convention for isar_feature functions: + * Functions which test 32-bit ID registers should have _aa32_ in + * their name. Functions which test 64-bit ID registers should have + * _aa64_ in their name. These must only be used in code where we + * know for certain that the CPU has AArch32 or AArch64 respectively + * or where the correct answer for a CPU which doesn't implement that + * CPU state is "false" (eg when generating A32 or A64 code, if adding + * system registers that are specific to that CPU state, for "should + * we let this system register bit be set" tests where the 32-bit + * flavour of the register doesn't have the bit, and so on). + * Functions which simply ask "does this feature exist at all" have + * _any_ in their name, and always return the logical OR of the _aa64_ + * and the _aa32_ function. + */ + +/* + * 32-bit feature tests via id registers. + */ +static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; +} + +static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; +} + +static inline bool isar_feature_aa32_lob(const ARMISARegisters *id) +{ + /* (M-profile) low-overhead loops and branch future */ + return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3; +} + +static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id) +{ + return FIELD_EX32(id->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; +} + +static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) +{ + return FIELD_EX32(id->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; +} + +static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) +{ + return FIELD_EX32(id->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; +} + +static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) +{ + return FIELD_EX32(id->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; +} + +static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) +{ + return FIELD_EX32(id->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; +} + +static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) +{ + return FIELD_EX32(id->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; +} + +static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; +} + +static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0; +} + +static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0; +} + +static inline bool isar_feature_aa32_ras(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0; +} + +static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; +} + +static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) +{ + /* + * Return true if M-profile state handling insns + * (VSCCLRM, CLRM, FPCTX access insns) are implemented + */ + return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3; +} + +static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) +{ + /* Sadly this is encoded differently for A-profile and M-profile */ + if (isar_feature_aa32_mprofile(id)) { + return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0; + } else { + return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; + } +} + +static inline bool isar_feature_aa32_mve(const ARMISARegisters *id) +{ + /* + * Return true if MVE is supported (either integer or floating point). + * We must check for M-profile as the MVFR1 field means something + * else for A-profile. + */ + return isar_feature_aa32_mprofile(id) && + FIELD_EX32(id->mvfr1, MVFR1, MVE) > 0; +} + +static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) +{ + /* + * Return true if MVE is supported (either integer or floating point). + * We must check for M-profile as the MVFR1 field means something + * else for A-profile. + */ + return isar_feature_aa32_mprofile(id) && + FIELD_EX32(id->mvfr1, MVFR1, MVE) >= 2; +} + +static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) +{ + /* + * Return true if either VFP or SIMD is implemented. + * In this case, a minimum of VFP w/ D0-D15. + */ + return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0; +} + +static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id) +{ + /* Return true if D16-D31 are implemented */ + return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2; +} + +static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0; +} + +static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id) +{ + /* Return true if CPU supports single precision floating point, VFPv2 */ + return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0; +} + +static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id) +{ + /* Return true if CPU supports single precision floating point, VFPv3 */ + return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2; +} + +static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id) +{ + /* Return true if CPU supports double precision floating point, VFPv2 */ + return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0; +} + +static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id) +{ + /* Return true if CPU supports double precision floating point, VFPv3 */ + return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2; +} + +static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) +{ + return isar_feature_aa32_fpsp_v2(id) || isar_feature_aa32_fpdp_v2(id); +} + +/* + * We always set the FP and SIMD FP16 fields to indicate identical + * levels of support (assuming SIMD is implemented at all), so + * we only need one set of accessors. + */ +static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0; +} + +static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1; +} + +/* + * Note that this ID register field covers both VFP and Neon FMAC, + * so should usually be tested in combination with some other + * check that confirms the presence of whichever of VFP or Neon is + * relevant, to avoid accidentally enabling a Neon feature on + * a VFP-no-Neon core or vice-versa. + */ +static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0; +} + +static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1; +} + +static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2; +} + +static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3; +} + +static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) +{ + return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4; +} + +static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; +} + +static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) +{ + return FIELD_EX32(id->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; +} + +static inline bool isar_feature_aa32_pmuv3p1(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; +} + +static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id) +{ + /* 0xf means "non-standard IMPDEF PMU" */ + return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && + FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; +} + +static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id) +{ + /* 0xf means "non-standard IMPDEF PMU" */ + return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 6 && + FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; +} + +static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0; +} + +static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0; +} + +static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0; +} + +static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0; +} + +static inline bool isar_feature_aa32_half_evt(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 1; +} + +static inline bool isar_feature_aa32_evt(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 2; +} + +static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0; +} + +static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0; +} + +static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5; +} + +static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id) +{ + return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8; +} + +static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id) +{ + return FIELD_EX32(id->dbgdevid, DBGDEVID, DOUBLELOCK) > 0; +} + +/* + * 64-bit feature tests via id registers. + */ +static inline bool isar_feature_aa64_aes(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +/* + * These are the values from APA/API/APA3. + * In general these must be compared '>=', per the normal Arm ARM + * treatment of fields in ID registers. + */ +typedef enum { + PauthFeat_None = 0, + PauthFeat_1 = 1, + PauthFeat_EPAC = 2, + PauthFeat_2 = 3, + PauthFeat_FPAC = 4, + PauthFeat_FPACCOMBINED = 5, +} ARMPauthFeature; + +static inline ARMPauthFeature +isar_feature_pauth_feature(const ARMISARegisters *id) +{ + /* + * Architecturally, only one of {APA,API,APA3} may be active (non-zero) + * and the other two must be zero. Thus we may avoid conditionals. + */ + return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) | + FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, API) | + FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3)); +} + +static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) +{ + /* + * Return true if any form of pauth is enabled, as this + * predicate controls migration of the 128-bit keys. + */ + return isar_feature_pauth_feature(id) != PauthFeat_None; +} + +static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id) +{ + /* + * Return true if pauth is enabled with the architected QARMA5 algorithm. + * QEMU will always enable or disable both APA and GPA. + */ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0; +} + +static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id) +{ + /* + * Return true if pauth is enabled with the architected QARMA3 algorithm. + * QEMU will always enable or disable both APA3 and GPA3. + */ + return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0; +} + +static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; +} + +static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; +} + +static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) +{ + return FIELD_EX64(id->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; +} + +static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; +} + +static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0; +} + +static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2; +} + +static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0; +} + +static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) +{ + /* We always set the AdvSIMD and FP fields identically. */ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf; +} + +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; +} + +static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; +} + +static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; +} + +static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2; +} + +static inline bool isar_feature_aa64_ras(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0; +} + +static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) >= 2; +} + +static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; +} + +static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0; +} + +static inline bool isar_feature_aa64_rme(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0; +} + +static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; +} + +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_pan3(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3; +} + +static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0; +} + +static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0; +} + +static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; +} + +static inline bool isar_feature_aa64_st(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0; +} + +static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0; +} + +static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0; +} + +static inline bool isar_feature_aa64_ids(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, IDS) != 0; +} + +static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 1; +} + +static inline bool isar_feature_aa64_evt(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 2; +} + +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_mte_insn_reg(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; +} + +static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; +} + +static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0; +} + +static inline bool isar_feature_aa64_pmuv3p1(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_aa64_pmuv3p4(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && + FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; +} + +static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 6 && + FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; +} + +static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; +} + +static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; +} + +static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; +} + +static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; +} + +static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; +} + +static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); + return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id)); +} + +static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2; +} + +static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); + return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); +} + +static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0; +} + +static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1; +} + +static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0; +} + +static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id)); +} + +static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id)); +} + +static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id)); +} + +static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0; +} + +static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; +} + +static inline bool isar_feature_aa64_lva(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0; +} + +static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0; +} + +static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0; +} + +static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2; +} + +static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; +} + +static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; +} + +static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) +{ + int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2); + if (key >= 2) { + return true; /* FEAT_CSV2_2 */ + } + if (key == 1) { + key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC); + return key >= 2; /* FEAT_CSV2_1p2 */ + } + return false; +} + +static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; +} + +static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8; +} + +static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; +} + +static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0; +} + +static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2; +} + +static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0; +} + +static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0; +} + +static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0; +} + +static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0; +} + +static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0; +} + +static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0; +} + +static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0; +} + +static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, F64F64); +} + +static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, I16I64) == 0xf; +} + +static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64); +} + +static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; +} + +static inline bool isar_feature_aa64_mops(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS); +} + +/* + * Feature tests for "does this exist in either 32-bit or 64-bit?" + */ +static inline bool isar_feature_any_fp16(const ARMISARegisters *id) +{ + return isar_feature_aa64_fp16(id) || isar_feature_aa32_fp16_arith(id); +} + +static inline bool isar_feature_any_predinv(const ARMISARegisters *id) +{ + return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id); +} + +static inline bool isar_feature_any_pmuv3p1(const ARMISARegisters *id) +{ + return isar_feature_aa64_pmuv3p1(id) || isar_feature_aa32_pmuv3p1(id); +} + +static inline bool isar_feature_any_pmuv3p4(const ARMISARegisters *id) +{ + return isar_feature_aa64_pmuv3p4(id) || isar_feature_aa32_pmuv3p4(id); +} + +static inline bool isar_feature_any_pmuv3p5(const ARMISARegisters *id) +{ + return isar_feature_aa64_pmuv3p5(id) || isar_feature_aa32_pmuv3p5(id); +} + +static inline bool isar_feature_any_ccidx(const ARMISARegisters *id) +{ + return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id); +} + +static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id) +{ + return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id); +} + +static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id) +{ + return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id); +} + +static inline bool isar_feature_any_ras(const ARMISARegisters *id) +{ + return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id); +} + +static inline bool isar_feature_any_half_evt(const ARMISARegisters *id) +{ + return isar_feature_aa64_half_evt(id) || isar_feature_aa32_half_evt(id); +} + +static inline bool isar_feature_any_evt(const ARMISARegisters *id) +{ + return isar_feature_aa64_evt(id) || isar_feature_aa32_evt(id); +} + +/* + * Forward to the above feature tests given an ARMCPU pointer. + */ +#define cpu_isar_feature(name, cpu) \ + ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); }) + +#endif diff --git a/target/arm/cpu.c b/target/arm/cpu.c index aa4e006f21..954328d72a 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -31,6 +31,7 @@ #include "hw/core/tcg-cpu-ops.h" #endif /* CONFIG_TCG */ #include "internals.h" +#include "cpu-features.h" #include "exec/exec-all.h" #include "hw/qdev-properties.h" #if !defined(CONFIG_USER_ONLY) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 76d4cef9e3..d51dfe48db 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3402,975 +3402,4 @@ static inline target_ulong cpu_untagged_addr(CPUState *cs, target_ulong x) } #endif -/* - * Naming convention for isar_feature functions: - * Functions which test 32-bit ID registers should have _aa32_ in - * their name. Functions which test 64-bit ID registers should have - * _aa64_ in their name. These must only be used in code where we - * know for certain that the CPU has AArch32 or AArch64 respectively - * or where the correct answer for a CPU which doesn't implement that - * CPU state is "false" (eg when generating A32 or A64 code, if adding - * system registers that are specific to that CPU state, for "should - * we let this system register bit be set" tests where the 32-bit - * flavour of the register doesn't have the bit, and so on). - * Functions which simply ask "does this feature exist at all" have - * _any_ in their name, and always return the logical OR of the _aa64_ - * and the _aa32_ function. - */ - -/* - * 32-bit feature tests via id registers. - */ -static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; -} - -static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; -} - -static inline bool isar_feature_aa32_lob(const ARMISARegisters *id) -{ - /* (M-profile) low-overhead loops and branch future */ - return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3; -} - -static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id) -{ - return FIELD_EX32(id->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; -} - -static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) -{ - return FIELD_EX32(id->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; -} - -static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) -{ - return FIELD_EX32(id->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; -} - -static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) -{ - return FIELD_EX32(id->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; -} - -static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) -{ - return FIELD_EX32(id->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; -} - -static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) -{ - return FIELD_EX32(id->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; -} - -static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; -} - -static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0; -} - -static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0; -} - -static inline bool isar_feature_aa32_ras(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0; -} - -static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; -} - -static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) -{ - /* - * Return true if M-profile state handling insns - * (VSCCLRM, CLRM, FPCTX access insns) are implemented - */ - return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3; -} - -static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) -{ - /* Sadly this is encoded differently for A-profile and M-profile */ - if (isar_feature_aa32_mprofile(id)) { - return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0; - } else { - return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; - } -} - -static inline bool isar_feature_aa32_mve(const ARMISARegisters *id) -{ - /* - * Return true if MVE is supported (either integer or floating point). - * We must check for M-profile as the MVFR1 field means something - * else for A-profile. - */ - return isar_feature_aa32_mprofile(id) && - FIELD_EX32(id->mvfr1, MVFR1, MVE) > 0; -} - -static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) -{ - /* - * Return true if MVE is supported (either integer or floating point). - * We must check for M-profile as the MVFR1 field means something - * else for A-profile. - */ - return isar_feature_aa32_mprofile(id) && - FIELD_EX32(id->mvfr1, MVFR1, MVE) >= 2; -} - -static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) -{ - /* - * Return true if either VFP or SIMD is implemented. - * In this case, a minimum of VFP w/ D0-D15. - */ - return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0; -} - -static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id) -{ - /* Return true if D16-D31 are implemented */ - return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2; -} - -static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id) -{ - return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0; -} - -static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id) -{ - /* Return true if CPU supports single precision floating point, VFPv2 */ - return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0; -} - -static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id) -{ - /* Return true if CPU supports single precision floating point, VFPv3 */ - return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2; -} - -static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id) -{ - /* Return true if CPU supports double precision floating point, VFPv2 */ - return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0; -} - -static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id) -{ - /* Return true if CPU supports double precision floating point, VFPv3 */ - return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2; -} - -static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) -{ - return isar_feature_aa32_fpsp_v2(id) || isar_feature_aa32_fpdp_v2(id); -} - -/* - * We always set the FP and SIMD FP16 fields to indicate identical - * levels of support (assuming SIMD is implemented at all), so - * we only need one set of accessors. - */ -static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id) -{ - return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0; -} - -static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) -{ - return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1; -} - -/* - * Note that this ID register field covers both VFP and Neon FMAC, - * so should usually be tested in combination with some other - * check that confirms the presence of whichever of VFP or Neon is - * relevant, to avoid accidentally enabling a Neon feature on - * a VFP-no-Neon core or vice-versa. - */ -static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id) -{ - return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0; -} - -static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id) -{ - return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1; -} - -static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id) -{ - return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2; -} - -static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id) -{ - return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3; -} - -static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) -{ - return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4; -} - -static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; -} - -static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) -{ - return FIELD_EX32(id->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; -} - -static inline bool isar_feature_aa32_pmuv3p1(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; -} - -static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id) -{ - /* 0xf means "non-standard IMPDEF PMU" */ - return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && - FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; -} - -static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id) -{ - /* 0xf means "non-standard IMPDEF PMU" */ - return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 6 && - FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; -} - -static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0; -} - -static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0; -} - -static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0; -} - -static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0; -} - -static inline bool isar_feature_aa32_half_evt(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 1; -} - -static inline bool isar_feature_aa32_evt(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 2; -} - -static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0; -} - -static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0; -} - -static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5; -} - -static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id) -{ - return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8; -} - -static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id) -{ - return FIELD_EX32(id->dbgdevid, DBGDEVID, DOUBLELOCK) > 0; -} - -/* - * 64-bit feature tests via id registers. - */ -static inline bool isar_feature_aa64_aes(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -/* - * These are the values from APA/API/APA3. - * In general these must be compared '>=', per the normal Arm ARM - * treatment of fields in ID registers. - */ -typedef enum { - PauthFeat_None = 0, - PauthFeat_1 = 1, - PauthFeat_EPAC = 2, - PauthFeat_2 = 3, - PauthFeat_FPAC = 4, - PauthFeat_FPACCOMBINED = 5, -} ARMPauthFeature; - -static inline ARMPauthFeature -isar_feature_pauth_feature(const ARMISARegisters *id) -{ - /* - * Architecturally, only one of {APA,API,APA3} may be active (non-zero) - * and the other two must be zero. Thus we may avoid conditionals. - */ - return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) | - FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, API) | - FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3)); -} - -static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) -{ - /* - * Return true if any form of pauth is enabled, as this - * predicate controls migration of the 128-bit keys. - */ - return isar_feature_pauth_feature(id) != PauthFeat_None; -} - -static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id) -{ - /* - * Return true if pauth is enabled with the architected QARMA5 algorithm. - * QEMU will always enable or disable both APA and GPA. - */ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0; -} - -static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id) -{ - /* - * Return true if pauth is enabled with the architected QARMA3 algorithm. - * QEMU will always enable or disable both APA3 and GPA3. - */ - return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0; -} - -static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; -} - -static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; -} - -static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) -{ - return FIELD_EX64(id->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; -} - -static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; -} - -static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0; -} - -static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2; -} - -static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0; -} - -static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) -{ - /* We always set the AdvSIMD and FP fields identically. */ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf; -} - -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; -} - -static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; -} - -static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; -} - -static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2; -} - -static inline bool isar_feature_aa64_ras(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0; -} - -static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) >= 2; -} - -static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; -} - -static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0; -} - -static inline bool isar_feature_aa64_rme(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0; -} - -static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; -} - -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_pan3(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3; -} - -static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0; -} - -static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0; -} - -static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; -} - -static inline bool isar_feature_aa64_st(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0; -} - -static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0; -} - -static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0; -} - -static inline bool isar_feature_aa64_ids(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, IDS) != 0; -} - -static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 1; -} - -static inline bool isar_feature_aa64_evt(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 2; -} - -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_mte_insn_reg(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; -} - -static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; -} - -static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0; -} - -static inline bool isar_feature_aa64_pmuv3p1(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_aa64_pmuv3p4(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && - FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; -} - -static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 6 && - FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; -} - -static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; -} - -static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; -} - -static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; -} - -static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; -} - -static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) -{ - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; -} - -static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); - return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id)); -} - -static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2; -} - -static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); - return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); -} - -static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id) -{ - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0; -} - -static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1; -} - -static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id) -{ - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0; -} - -static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); - return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id)); -} - -static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); - return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id)); -} - -static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2); - return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id)); -} - -static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0; -} - -static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; -} - -static inline bool isar_feature_aa64_lva(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0; -} - -static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0; -} - -static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0; -} - -static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2; -} - -static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; -} - -static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; -} - -static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) -{ - int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2); - if (key >= 2) { - return true; /* FEAT_CSV2_2 */ - } - if (key == 1) { - key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC); - return key >= 2; /* FEAT_CSV2_1p2 */ - } - return false; -} - -static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; -} - -static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8; -} - -static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; -} - -static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0; -} - -static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2; -} - -static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0; -} - -static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0; -} - -static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0; -} - -static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0; -} - -static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0; -} - -static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0; -} - -static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0; -} - -static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, F64F64); -} - -static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, I16I64) == 0xf; -} - -static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64); -} - -static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) -{ - return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; -} - -static inline bool isar_feature_aa64_mops(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS); -} - -/* - * Feature tests for "does this exist in either 32-bit or 64-bit?" - */ -static inline bool isar_feature_any_fp16(const ARMISARegisters *id) -{ - return isar_feature_aa64_fp16(id) || isar_feature_aa32_fp16_arith(id); -} - -static inline bool isar_feature_any_predinv(const ARMISARegisters *id) -{ - return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id); -} - -static inline bool isar_feature_any_pmuv3p1(const ARMISARegisters *id) -{ - return isar_feature_aa64_pmuv3p1(id) || isar_feature_aa32_pmuv3p1(id); -} - -static inline bool isar_feature_any_pmuv3p4(const ARMISARegisters *id) -{ - return isar_feature_aa64_pmuv3p4(id) || isar_feature_aa32_pmuv3p4(id); -} - -static inline bool isar_feature_any_pmuv3p5(const ARMISARegisters *id) -{ - return isar_feature_aa64_pmuv3p5(id) || isar_feature_aa32_pmuv3p5(id); -} - -static inline bool isar_feature_any_ccidx(const ARMISARegisters *id) -{ - return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id); -} - -static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id) -{ - return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id); -} - -static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id) -{ - return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id); -} - -static inline bool isar_feature_any_ras(const ARMISARegisters *id) -{ - return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id); -} - -static inline bool isar_feature_any_half_evt(const ARMISARegisters *id) -{ - return isar_feature_aa64_half_evt(id) || isar_feature_aa32_half_evt(id); -} - -static inline bool isar_feature_any_evt(const ARMISARegisters *id) -{ - return isar_feature_aa64_evt(id) || isar_feature_aa32_evt(id); -} - -/* - * Forward to the above feature tests given an ARMCPU pointer. - */ -#define cpu_isar_feature(name, cpu) \ - ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); }) - #endif diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 1cb9d5b81a..1e9c6c85ae 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -32,6 +32,7 @@ #include "qapi/visitor.h" #include "hw/qdev-properties.h" #include "internals.h" +#include "cpu-features.h" #include "cpregs.h" void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index abe72e35ae..79a3659c0c 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -9,6 +9,7 @@ #include "qemu/log.h" #include "cpu.h" #include "internals.h" +#include "cpu-features.h" #include "cpregs.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index b7ace24bfc..28f546a5ff 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -23,6 +23,7 @@ #include "gdbstub/helpers.h" #include "sysemu/tcg.h" #include "internals.h" +#include "cpu-features.h" #include "cpregs.h" typedef struct RegisterSysregXmlParam { diff --git a/target/arm/helper.c b/target/arm/helper.c index b29edb26af..5dc0d20a84 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -11,6 +11,7 @@ #include "trace.h" #include "cpu.h" #include "internals.h" +#include "cpu-features.h" #include "exec/helper-proto.h" #include "qemu/main-loop.h" #include "qemu/timer.h" diff --git a/target/arm/internals.h b/target/arm/internals.h index 1dd9182a54..f7224e6f4d 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -28,6 +28,7 @@ #include "hw/registerfields.h" #include "tcg/tcg-gvec-desc.h" #include "syndrome.h" +#include "cpu-features.h" /* register banks for CPU modes */ #define BANK_USRSYS 0 diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 4bb68646e4..3c175c93a7 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -28,6 +28,7 @@ #include "sysemu/kvm_int.h" #include "kvm_arm.h" #include "internals.h" +#include "cpu-features.h" #include "hw/acpi/acpi.h" #include "hw/acpi/ghes.h" diff --git a/target/arm/machine.c b/target/arm/machine.c index fc4a4a4064..9e20b41189 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -5,6 +5,7 @@ #include "sysemu/tcg.h" #include "kvm_arm.h" #include "internals.h" +#include "cpu-features.h" #include "migration/cpu.h" static bool vfp_needed(void *opaque) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 95db9ec4c3..53713e0300 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -13,6 +13,7 @@ #include "exec/exec-all.h" #include "cpu.h" #include "internals.h" +#include "cpu-features.h" #include "idau.h" #ifdef CONFIG_TCG # include "tcg/oversized-guest.h" diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index a9a8c0a059..08db1dbcc7 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -26,6 +26,7 @@ #include "hw/qdev-properties.h" #include "qemu/units.h" #include "internals.h" +#include "cpu-features.h" #include "cpregs.h" static uint64_t make_ccsidr64(unsigned assoc, unsigned linesize, diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c index cea1adb7b6..3d7fdce5c3 100644 --- a/target/arm/tcg/hflags.c +++ b/target/arm/tcg/hflags.c @@ -8,6 +8,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "internals.h" +#include "cpu-features.h" #include "exec/helper-proto.h" #include "cpregs.h" diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c index 0045c18f80..a26adb75aa 100644 --- a/target/arm/tcg/m_helper.c +++ b/target/arm/tcg/m_helper.c @@ -9,6 +9,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "internals.h" +#include "cpu-features.h" #include "gdbstub/helpers.h" #include "exec/helper-proto.h" #include "qemu/main-loop.h" diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c index 403f8b09d3..ea08936a85 100644 --- a/target/arm/tcg/op_helper.c +++ b/target/arm/tcg/op_helper.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec/helper-proto.h" #include "internals.h" +#include "cpu-features.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "cpregs.h" diff --git a/target/arm/tcg/pauth_helper.c b/target/arm/tcg/pauth_helper.c index 4da2962ad5..c4b143024f 100644 --- a/target/arm/tcg/pauth_helper.c +++ b/target/arm/tcg/pauth_helper.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "internals.h" +#include "cpu-features.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "exec/helper-proto.h" diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c index 59bff8b452..4fdd85359e 100644 --- a/target/arm/tcg/tlb_helper.c +++ b/target/arm/tcg/tlb_helper.c @@ -8,6 +8,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "internals.h" +#include "cpu-features.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index b4046611f5..9efe00cf6c 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -8,7 +8,7 @@ #include "exec/translator.h" #include "exec/helper-gen.h" #include "internals.h" - +#include "cpu-features.h" /* internal defines */ diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c index 789bba36cc..3e5e37abbe 100644 --- a/target/arm/vfp_helper.c +++ b/target/arm/vfp_helper.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec/helper-proto.h" #include "internals.h" +#include "cpu-features.h" #ifdef CONFIG_TCG #include "qemu/log.h" #include "fpu/softfloat.h" From 326077724a0c71e06e0147c210494b4ea36033c9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Oct 2023 17:35:06 +0100 Subject: [PATCH 04/41] target/arm: Move ID_AA64MMFR1 and ID_AA64MMFR2 tests together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our list of isar_feature functions is not in any particular order, but tests on fields of the same ID register tend to be grouped together. A few functions that are tests of fields in ID_AA64MMFR1 and ID_AA64MMFR2 are not in the same place as the rest; move them into their groups. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231024163510.2972081-3-peter.maydell@linaro.org --- target/arm/cpu-features.h | 60 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index bfc9bfafe7..fc85a8fe13 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -641,6 +641,21 @@ static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0; } +static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0; +} + +static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2; +} + +static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; +} + static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; @@ -676,6 +691,21 @@ static inline bool isar_feature_aa64_evt(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 2; } +static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; +} + +static inline bool isar_feature_aa64_lva(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0; +} + +static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0; +} + static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; @@ -794,36 +824,6 @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0; } -static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; -} - -static inline bool isar_feature_aa64_lva(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0; -} - -static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0; -} - -static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0; -} - -static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2; -} - -static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; -} - static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; From 5181c751af28cbb49d924d474fcbeff6014c8319 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Oct 2023 17:35:07 +0100 Subject: [PATCH 05/41] target/arm: Move ID_AA64MMFR0 tests up to before MMFR1 and MMFR2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the ID_AA64MMFR0 feature test functions up so they are before the ones for ID_AA64MMFR1 and ID_AA64MMFR2. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231024163510.2972081-4-peter.maydell@linaro.org --- target/arm/cpu-features.h | 120 +++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index fc85a8fe13..90200a4b98 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -606,6 +606,66 @@ static inline bool isar_feature_aa64_rme(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0; } +static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; +} + +static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); + return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id)); +} + +static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2; +} + +static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); + return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); +} + +static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0; +} + +static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1; +} + +static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0; +} + +static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id)); +} + +static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id)); +} + +static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id)); +} + +static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0; +} + static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; @@ -764,66 +824,6 @@ static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; } -static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) -{ - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; -} - -static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); - return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id)); -} - -static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2; -} - -static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); - return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); -} - -static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id) -{ - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0; -} - -static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1; -} - -static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id) -{ - return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0; -} - -static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); - return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id)); -} - -static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); - return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id)); -} - -static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id) -{ - unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2); - return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id)); -} - -static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0; -} - static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; From 338ddfb1f3db73ef960c069db6098b88dc88b0d0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Oct 2023 17:35:08 +0100 Subject: [PATCH 06/41] target/arm: Move ID_AA64ISAR* test functions together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the feature test functions that test ID_AA64ISAR* fields together. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231024163510.2972081-5-peter.maydell@linaro.org --- target/arm/cpu-features.h | 70 +++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index 90200a4b98..e73120ef97 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -451,6 +451,16 @@ static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0; } +static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; +} + +static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; +} + static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; @@ -514,16 +524,6 @@ static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0; } -static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; -} - -static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; -} - static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; @@ -554,6 +554,31 @@ static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0; } +static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; +} + +static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; +} + +static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; +} + +static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; +} + +static inline bool isar_feature_aa64_mops(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS); +} + static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) { /* We always set the AdvSIMD and FP fields identically. */ @@ -804,26 +829,6 @@ static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id) FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; } -static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; -} - -static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; -} - -static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; -} - -static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0; -} - static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; @@ -922,11 +927,6 @@ static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; } -static inline bool isar_feature_aa64_mops(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS); -} - /* * Feature tests for "does this exist in either 32-bit or 64-bit?" */ From e677d7d47062b6714aeffd92cbc015d4ae2b9eaf Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Oct 2023 17:35:09 +0100 Subject: [PATCH 07/41] target/arm: Move ID_AA64PFR* tests together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move all the ID_AA64PFR* feature test functions together. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231024163510.2972081-6-peter.maydell@linaro.org --- target/arm/cpu-features.h | 86 +++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index e73120ef97..0ed05b8b19 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -631,6 +631,49 @@ static inline bool isar_feature_aa64_rme(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0; } +static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; +} + +static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) +{ + int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2); + if (key >= 2) { + return true; /* FEAT_CSV2_2 */ + } + if (key == 1) { + key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC); + return key >= 2; /* FEAT_CSV2_1p2 */ + } + return false; +} + +static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; +} + +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_mte_insn_reg(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; +} + +static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; +} + +static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0; +} + static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id) { return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1; @@ -791,26 +834,6 @@ static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0; } -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_mte_insn_reg(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; -} - -static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; -} - -static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0; -} - static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && @@ -829,29 +852,6 @@ static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id) FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; } -static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; -} - -static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id) -{ - int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2); - if (key >= 2) { - return true; /* FEAT_CSV2_2 */ - } - if (key == 1) { - key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC); - return key >= 2; /* FEAT_CSV2_1p2 */ - } - return false; -} - -static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) -{ - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; -} - static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8; From 1036ce4e6a2fa0f865e2e6514d198db931b5510f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Oct 2023 17:35:10 +0100 Subject: [PATCH 08/41] target/arm: Move ID_AA64DFR* feature tests together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move all the ID_AA64DFR* feature test functions together. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231024163510.2972081-7-peter.maydell@linaro.org --- target/arm/cpu-features.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index 0ed05b8b19..66212cd7ec 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -857,6 +857,11 @@ static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8; } +static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; +} + static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; @@ -922,11 +927,6 @@ static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64); } -static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id) -{ - return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0; -} - /* * Feature tests for "does this exist in either 32-bit or 64-bit?" */ From 307521d6e29e559c89afa9dbd337ae75fe3c436d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Oct 2023 18:24:38 +0100 Subject: [PATCH 09/41] target/arm: Fix syndrome for FGT traps on ERET In commit 442c9d682c94fc2 when we converted the ERET, ERETAA, ERETAB instructions to decodetree, the conversion accidentally lost the correct setting of the syndrome register when taking a trap because of the FEAT_FGT HFGITR_EL1.ERET bit. Instead of reporting a correct full syndrome value with the EC and IL bits, we only reported the low two bits of the syndrome, because the call to syn_erettrap() got dropped. Fix the syndrome values for these traps by reinstating the syn_erettrap() calls. Fixes: 442c9d682c94fc2 ("target/arm: Convert ERET, ERETAA, ERETAB to decodetree") Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20231024172438.2990945-1-peter.maydell@linaro.org --- target/arm/tcg/translate-a64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index ad78b8b120..41484d8ae5 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -1606,7 +1606,7 @@ static bool trans_ERET(DisasContext *s, arg_ERET *a) return false; } if (s->fgt_eret) { - gen_exception_insn_el(s, 0, EXCP_UDEF, 0, 2); + gen_exception_insn_el(s, 0, EXCP_UDEF, syn_erettrap(0), 2); return true; } dst = tcg_temp_new_i64(); @@ -1633,7 +1633,7 @@ static bool trans_ERETA(DisasContext *s, arg_reta *a) } /* The FGT trap takes precedence over an auth trap. */ if (s->fgt_eret) { - gen_exception_insn_el(s, 0, EXCP_UDEF, a->m ? 3 : 2, 2); + gen_exception_insn_el(s, 0, EXCP_UDEF, syn_erettrap(a->m ? 3 : 2), 2); return true; } dst = tcg_temp_new_i64(); From 0c436de6ba2718698e3f2cf4b662e38ff566711b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:07 +0200 Subject: [PATCH 10/41] hw/arm/allwinner-a10: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-2-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/cubieboard.c | 1 + include/hw/arm/allwinner-a10.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c index 8c7fa91529..29146f5018 100644 --- a/hw/arm/cubieboard.c +++ b/hw/arm/cubieboard.c @@ -21,6 +21,7 @@ #include "hw/boards.h" #include "hw/qdev-properties.h" #include "hw/arm/allwinner-a10.h" +#include "hw/arm/boot.h" #include "hw/i2c/i2c.h" static struct arm_boot_info cubieboard_binfo = { diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h index cd1465c613..2eb83a17ea 100644 --- a/include/hw/arm/allwinner-a10.h +++ b/include/hw/arm/allwinner-a10.h @@ -1,7 +1,6 @@ #ifndef HW_ARM_ALLWINNER_A10_H #define HW_ARM_ALLWINNER_A10_H -#include "hw/arm/boot.h" #include "hw/timer/allwinner-a10-pit.h" #include "hw/intc/allwinner-a10-pic.h" #include "hw/net/allwinner_emac.h" From 0e246c6209b6058646ae48ec768afdd1bc76e962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:08 +0200 Subject: [PATCH 11/41] hw/arm/allwinner-h3: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-3-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/orangepi.c | 1 + include/hw/arm/allwinner-h3.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c index 10653361ed..d0eca54cd9 100644 --- a/hw/arm/orangepi.c +++ b/hw/arm/orangepi.c @@ -25,6 +25,7 @@ #include "hw/boards.h" #include "hw/qdev-properties.h" #include "hw/arm/allwinner-h3.h" +#include "hw/arm/boot.h" static struct arm_boot_info orangepi_binfo; diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h index f15d6d7cc7..24ba4e1bf4 100644 --- a/include/hw/arm/allwinner-h3.h +++ b/include/hw/arm/allwinner-h3.h @@ -36,7 +36,6 @@ #define HW_ARM_ALLWINNER_H3_H #include "qom/object.h" -#include "hw/arm/boot.h" #include "hw/timer/allwinner-a10-pit.h" #include "hw/intc/arm_gic.h" #include "hw/misc/allwinner-h3-ccu.h" From 6f4d538aa1b7923e1bf2917f38569888482c3a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:09 +0200 Subject: [PATCH 12/41] hw/arm/allwinner-r40: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-4-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/bananapi_m2u.c | 1 + include/hw/arm/allwinner-r40.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/bananapi_m2u.c b/hw/arm/bananapi_m2u.c index 74121d8966..a7c7a9f96d 100644 --- a/hw/arm/bananapi_m2u.c +++ b/hw/arm/bananapi_m2u.c @@ -26,6 +26,7 @@ #include "hw/i2c/i2c.h" #include "hw/qdev-properties.h" #include "hw/arm/allwinner-r40.h" +#include "hw/arm/boot.h" static struct arm_boot_info bpim2u_binfo; diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h index 72710d3edc..6e1ac9d4c1 100644 --- a/include/hw/arm/allwinner-r40.h +++ b/include/hw/arm/allwinner-r40.h @@ -21,7 +21,6 @@ #define HW_ARM_ALLWINNER_R40_H #include "qom/object.h" -#include "hw/arm/boot.h" #include "hw/timer/allwinner-a10-pit.h" #include "hw/intc/arm_gic.h" #include "hw/sd/allwinner-sdhost.h" From 6fda3b91bf28aa88791fc77954abba0b1648c296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:10 +0200 Subject: [PATCH 13/41] hw/arm/fsl-imx25: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-5-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/imx25_pdk.c | 1 + include/hw/arm/fsl-imx25.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c index b4f7f4e8a7..7dfddd49e2 100644 --- a/hw/arm/imx25_pdk.c +++ b/hw/arm/imx25_pdk.c @@ -27,6 +27,7 @@ #include "qapi/error.h" #include "hw/qdev-properties.h" #include "hw/arm/fsl-imx25.h" +#include "hw/arm/boot.h" #include "hw/boards.h" #include "qemu/error-report.h" #include "sysemu/qtest.h" diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h index 1b1086e945..df2f83980f 100644 --- a/include/hw/arm/fsl-imx25.h +++ b/include/hw/arm/fsl-imx25.h @@ -17,7 +17,6 @@ #ifndef FSL_IMX25_H #define FSL_IMX25_H -#include "hw/arm/boot.h" #include "hw/intc/imx_avic.h" #include "hw/misc/imx25_ccm.h" #include "hw/char/imx_serial.h" From 88e763dab4ea49bb177affeaa4596ee3270e3287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:11 +0200 Subject: [PATCH 14/41] hw/arm/fsl-imx31: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-6-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/kzm.c | 1 + include/hw/arm/fsl-imx31.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c index b1b281c9ac..9be91ebeaa 100644 --- a/hw/arm/kzm.c +++ b/hw/arm/kzm.c @@ -16,6 +16,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/arm/fsl-imx31.h" +#include "hw/arm/boot.h" #include "hw/boards.h" #include "qemu/error-report.h" #include "exec/address-spaces.h" diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h index c116a73e0b..40c593a5cf 100644 --- a/include/hw/arm/fsl-imx31.h +++ b/include/hw/arm/fsl-imx31.h @@ -17,7 +17,6 @@ #ifndef FSL_IMX31_H #define FSL_IMX31_H -#include "hw/arm/boot.h" #include "hw/intc/imx_avic.h" #include "hw/misc/imx31_ccm.h" #include "hw/char/imx_serial.h" From e77bf48586444ede4d37508d276358407c69ccc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:12 +0200 Subject: [PATCH 15/41] hw/arm/fsl-imx6: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-7-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/sabrelite.c | 1 + include/hw/arm/fsl-imx6.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c index 41191245b8..56f184b9ae 100644 --- a/hw/arm/sabrelite.c +++ b/hw/arm/sabrelite.c @@ -13,6 +13,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/arm/fsl-imx6.h" +#include "hw/arm/boot.h" #include "hw/boards.h" #include "hw/qdev-properties.h" #include "qemu/error-report.h" diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h index 5b4d48da08..519b871014 100644 --- a/include/hw/arm/fsl-imx6.h +++ b/include/hw/arm/fsl-imx6.h @@ -17,7 +17,6 @@ #ifndef FSL_IMX6_H #define FSL_IMX6_H -#include "hw/arm/boot.h" #include "hw/cpu/a9mpcore.h" #include "hw/misc/imx6_ccm.h" #include "hw/misc/imx6_src.h" From 8727076bb97de473c48939e8900e583f91d93063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:13 +0200 Subject: [PATCH 16/41] hw/arm/fsl-imx6ul: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-8-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/mcimx6ul-evk.c | 1 + include/hw/arm/fsl-imx6ul.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c index 3ac1e2ea9b..500427e94b 100644 --- a/hw/arm/mcimx6ul-evk.c +++ b/hw/arm/mcimx6ul-evk.c @@ -13,6 +13,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/arm/fsl-imx6ul.h" +#include "hw/arm/boot.h" #include "hw/boards.h" #include "hw/qdev-properties.h" #include "qemu/error-report.h" diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h index 63012628ff..14390f6014 100644 --- a/include/hw/arm/fsl-imx6ul.h +++ b/include/hw/arm/fsl-imx6ul.h @@ -17,7 +17,6 @@ #ifndef FSL_IMX6UL_H #define FSL_IMX6UL_H -#include "hw/arm/boot.h" #include "hw/cpu/a15mpcore.h" #include "hw/misc/imx6ul_ccm.h" #include "hw/misc/imx6_src.h" From f27cbd94ee57897db09d816d8cfbc19d3c1ac85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:14 +0200 Subject: [PATCH 17/41] hw/arm/fsl-imx7: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-9-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/mcimx7d-sabre.c | 1 + include/hw/arm/fsl-imx7.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c index d1778122b6..693a1023b6 100644 --- a/hw/arm/mcimx7d-sabre.c +++ b/hw/arm/mcimx7d-sabre.c @@ -15,6 +15,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/arm/fsl-imx7.h" +#include "hw/arm/boot.h" #include "hw/boards.h" #include "hw/qdev-properties.h" #include "qemu/error-report.h" diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h index 2cbfc6b2b2..411fa1c2e3 100644 --- a/include/hw/arm/fsl-imx7.h +++ b/include/hw/arm/fsl-imx7.h @@ -19,7 +19,6 @@ #ifndef FSL_IMX7_H #define FSL_IMX7_H -#include "hw/arm/boot.h" #include "hw/cpu/a15mpcore.h" #include "hw/intc/imx_gpcv2.h" #include "hw/misc/imx7_ccm.h" From d95a3a75800342a9f5cdb5afe9fe7974e0b59209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:15 +0200 Subject: [PATCH 18/41] hw/arm/xlnx-versal: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-10-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/xlnx-versal-virt.c | 1 + include/hw/arm/xlnx-versal.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 88c561ff63..537118224f 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -19,6 +19,7 @@ #include "cpu.h" #include "hw/qdev-properties.h" #include "hw/arm/xlnx-versal.h" +#include "hw/arm/boot.h" #include "qom/object.h" #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt") diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 7b419f88c2..b710d71fb0 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -13,7 +13,6 @@ #define XLNX_VERSAL_H #include "hw/sysbus.h" -#include "hw/arm/boot.h" #include "hw/cpu/cluster.h" #include "hw/or-irq.h" #include "hw/sd/sdhci.h" From f3205af4c7f29ba4fc0f995d48e450787f93853e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:53:16 +0200 Subject: [PATCH 19/41] hw/arm/xlnx-zynqmp: Remove 'hw/arm/boot.h' from header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/arm/boot.h" is only required on the source file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Message-id: 20231025065316.56817-11-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/xlnx-zcu102.c | 1 + include/hw/arm/xlnx-zynqmp.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index c5a07cfe19..4667cb333c 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/arm/xlnx-zynqmp.h" +#include "hw/arm/boot.h" #include "hw/boards.h" #include "qemu/error-report.h" #include "qemu/log.h" diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 687c75e3b0..96358d51eb 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -18,7 +18,6 @@ #ifndef XLNX_ZYNQMP_H #define XLNX_ZYNQMP_H -#include "hw/arm/boot.h" #include "hw/intc/arm_gic.h" #include "hw/net/cadence_gem.h" #include "hw/char/cadence_uart.h" From 85500a1aef1cdfb2878d88a3d88db56ad972fb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:22 +0200 Subject: [PATCH 20/41] hw/sd/pxa2xx: Realize sysbus device before accessing it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sysbus_mmio_map() and sysbus_connect_irq() should not be called on unrealized device. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Message-id: 20231020130331.50048-2-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/sd/pxa2xx_mmci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index 124fbf8bbd..9f7a880bac 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -483,11 +483,11 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, dev = qdev_new(TYPE_PXA2XX_MMCI); sbd = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbd, &error_fatal); sysbus_mmio_map(sbd, 0, base); sysbus_connect_irq(sbd, 0, irq); qdev_connect_gpio_out_named(dev, "rx-dma", 0, rx_dma); qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma); - sysbus_realize_and_unref(sbd, &error_fatal); return PXA2XX_MMCI(dev); } From d8239c475b9aed7984b3c01942b08c03b469ee8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:23 +0200 Subject: [PATCH 21/41] hw/sd/pxa2xx: Do not open-code sysbus_create_simple() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Message-id: 20231020130331.50048-3-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/sd/pxa2xx_mmci.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index 9f7a880bac..4749e935d8 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -479,13 +479,8 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma) { DeviceState *dev; - SysBusDevice *sbd; - dev = qdev_new(TYPE_PXA2XX_MMCI); - sbd = SYS_BUS_DEVICE(dev); - sysbus_realize_and_unref(sbd, &error_fatal); - sysbus_mmio_map(sbd, 0, base); - sysbus_connect_irq(sbd, 0, irq); + dev = sysbus_create_simple(TYPE_PXA2XX_MMCI, base, irq); qdev_connect_gpio_out_named(dev, "rx-dma", 0, rx_dma); qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma); From 217ceefee0dad668fe1557131c30be66c97ea699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:24 +0200 Subject: [PATCH 22/41] hw/pcmcia/pxa2xx: Realize sysbus device before accessing it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sysbus_mmio_map() should not be called on unrealized device. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Message-id: 20231020130331.50048-4-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/pcmcia/pxa2xx.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c index fcca7e571b..e7264feb45 100644 --- a/hw/pcmcia/pxa2xx.c +++ b/hw/pcmcia/pxa2xx.c @@ -142,15 +142,12 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, hwaddr base) { DeviceState *dev; - PXA2xxPCMCIAState *s; dev = qdev_new(TYPE_PXA2XX_PCMCIA); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); - s = PXA2XX_PCMCIA(dev); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); - return s; + return PXA2XX_PCMCIA(dev); } static void pxa2xx_pcmcia_initfn(Object *obj) From 77d3fa5c3080c930af34f906263b0d883351eea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:25 +0200 Subject: [PATCH 23/41] hw/pcmcia/pxa2xx: Do not open-code sysbus_create_simple() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Thomas Huth Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231020130331.50048-5-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/pcmcia/pxa2xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c index e7264feb45..3d512a292c 100644 --- a/hw/pcmcia/pxa2xx.c +++ b/hw/pcmcia/pxa2xx.c @@ -143,9 +143,7 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, { DeviceState *dev; - dev = qdev_new(TYPE_PXA2XX_PCMCIA); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + dev = sysbus_create_simple(TYPE_PXA2XX_PCMCIA, base, NULL); return PXA2XX_PCMCIA(dev); } From cbf08c18512600650b8b25d1b7d7aa3a83846dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:26 +0200 Subject: [PATCH 24/41] hw/pcmcia/pxa2xx: Inline pxa2xx_pcmcia_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Thomas Huth Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231020130331.50048-6-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/pxa2xx.c | 12 ++++++++---- hw/pcmcia/pxa2xx.c | 10 ---------- include/hw/arm/pxa.h | 2 -- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 07d5dd8691..601ddd8766 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -2205,8 +2205,10 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *cpu_type) sysbus_create_simple("sysbus-ohci", 0x4c000000, qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1)); - s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000); - s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000); + s->pcmcia[0] = PXA2XX_PCMCIA(sysbus_create_simple(TYPE_PXA2XX_PCMCIA, + 0x20000000, NULL)); + s->pcmcia[1] = PXA2XX_PCMCIA(sysbus_create_simple(TYPE_PXA2XX_PCMCIA, + 0x30000000, NULL)); sysbus_create_simple(TYPE_PXA2XX_RTC, 0x40900000, qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM)); @@ -2338,8 +2340,10 @@ PXA2xxState *pxa255_init(unsigned int sdram_size) s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi"); } - s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000); - s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000); + s->pcmcia[0] = PXA2XX_PCMCIA(sysbus_create_simple(TYPE_PXA2XX_PCMCIA, + 0x20000000, NULL)); + s->pcmcia[1] = PXA2XX_PCMCIA(sysbus_create_simple(TYPE_PXA2XX_PCMCIA, + 0x30000000, NULL)); sysbus_create_simple(TYPE_PXA2XX_RTC, 0x40900000, qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM)); diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c index 3d512a292c..e3111fdf1a 100644 --- a/hw/pcmcia/pxa2xx.c +++ b/hw/pcmcia/pxa2xx.c @@ -138,16 +138,6 @@ static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level) qemu_set_irq(s->irq, level); } -PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, - hwaddr base) -{ - DeviceState *dev; - - dev = sysbus_create_simple(TYPE_PXA2XX_PCMCIA, base, NULL); - - return PXA2XX_PCMCIA(dev); -} - static void pxa2xx_pcmcia_initfn(Object *obj) { SysBusDevice *sbd = SYS_BUS_DEVICE(obj); diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h index 54eb895e42..4c6caee113 100644 --- a/include/hw/arm/pxa.h +++ b/include/hw/arm/pxa.h @@ -100,8 +100,6 @@ void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly, #define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia" OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxPCMCIAState, PXA2XX_PCMCIA) -PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, - hwaddr base); int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card); int pxa2xx_pcmcia_detach(void *opaque); void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq); From ead17ebf537c6bde0daa19d61a6913b595940e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:27 +0200 Subject: [PATCH 25/41] hw/intc/pxa2xx: Convert to Resettable interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Factor reset code out of the DeviceRealize() handler. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Thomas Huth Message-id: 20231020130331.50048-7-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/pxa2xx_pic.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c index 47132ab982..2eb869a605 100644 --- a/hw/arm/pxa2xx_pic.c +++ b/hw/arm/pxa2xx_pic.c @@ -271,12 +271,9 @@ static int pxa2xx_pic_post_load(void *opaque, int version_id) return 0; } -DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) +static void pxa2xx_pic_reset_hold(Object *obj) { - DeviceState *dev = qdev_new(TYPE_PXA2XX_PIC); - PXA2xxPICState *s = PXA2XX_PIC(dev); - - s->cpu = cpu; + PXA2xxPICState *s = PXA2XX_PIC(obj); s->int_pending[0] = 0; s->int_pending[1] = 0; @@ -284,6 +281,14 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) s->int_enabled[1] = 0; s->is_fiq[0] = 0; s->is_fiq[1] = 0; +} + +DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) +{ + DeviceState *dev = qdev_new(TYPE_PXA2XX_PIC); + PXA2xxPICState *s = PXA2XX_PIC(dev); + + s->cpu = cpu; sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); @@ -319,9 +324,11 @@ static const VMStateDescription vmstate_pxa2xx_pic_regs = { static void pxa2xx_pic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); dc->desc = "PXA2xx PIC"; dc->vmsd = &vmstate_pxa2xx_pic_regs; + rc->phases.hold = pxa2xx_pic_reset_hold; } static const TypeInfo pxa2xx_pic_info = { From ee5c9b5b19af0179d76b7afc8e7b00cedb0e615d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:28 +0200 Subject: [PATCH 26/41] hw/intc/pxa2xx: Pass CPU reference using QOM link property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOM objects shouldn't access each other internals fields except using the QOM API. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Thomas Huth Message-id: 20231020130331.50048-8-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/pxa2xx_pic.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c index 2eb869a605..7e180635c2 100644 --- a/hw/arm/pxa2xx_pic.c +++ b/hw/arm/pxa2xx_pic.c @@ -15,6 +15,7 @@ #include "cpu.h" #include "hw/arm/pxa.h" #include "hw/sysbus.h" +#include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qom/object.h" #include "target/arm/cpregs.h" @@ -288,7 +289,8 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) DeviceState *dev = qdev_new(TYPE_PXA2XX_PIC); PXA2xxPICState *s = PXA2XX_PIC(dev); - s->cpu = cpu; + object_property_set_link(OBJECT(dev), "arm-cpu", + OBJECT(cpu), &error_abort); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); @@ -321,11 +323,18 @@ static const VMStateDescription vmstate_pxa2xx_pic_regs = { }, }; +static Property pxa2xx_pic_properties[] = { + DEFINE_PROP_LINK("arm-cpu", PXA2xxPICState, cpu, + TYPE_ARM_CPU, ARMCPU *), + DEFINE_PROP_END_OF_LIST(), +}; + static void pxa2xx_pic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); ResettableClass *rc = RESETTABLE_CLASS(klass); + device_class_set_props(dc, pxa2xx_pic_properties); dc->desc = "PXA2xx PIC"; dc->vmsd = &vmstate_pxa2xx_pic_regs; rc->phases.hold = pxa2xx_pic_reset_hold; From 25c4ff29d1688989ca6246e1a34e57505283ea2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:29 +0200 Subject: [PATCH 27/41] hw/intc/pxa2xx: Factor pxa2xx_pic_realize() out of pxa2xx_pic_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Thomas Huth Message-id: 20231020130331.50048-9-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/pxa2xx_pic.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c index 7e180635c2..1373a0d275 100644 --- a/hw/arm/pxa2xx_pic.c +++ b/hw/arm/pxa2xx_pic.c @@ -287,12 +287,18 @@ static void pxa2xx_pic_reset_hold(Object *obj) DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) { DeviceState *dev = qdev_new(TYPE_PXA2XX_PIC); - PXA2xxPICState *s = PXA2XX_PIC(dev); object_property_set_link(OBJECT(dev), "arm-cpu", OBJECT(cpu), &error_abort); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + + return dev; +} + +static void pxa2xx_pic_realize(DeviceState *dev, Error **errp) +{ + PXA2xxPICState *s = PXA2XX_PIC(dev); qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS); @@ -300,12 +306,9 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_pic_ops, s, "pxa2xx-pic", 0x00100000); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); /* Enable IC coprocessor access. */ - define_arm_cp_regs_with_opaque(cpu, pxa_pic_cp_reginfo, s); - - return dev; + define_arm_cp_regs_with_opaque(s->cpu, pxa_pic_cp_reginfo, s); } static const VMStateDescription vmstate_pxa2xx_pic_regs = { @@ -335,6 +338,7 @@ static void pxa2xx_pic_class_init(ObjectClass *klass, void *data) ResettableClass *rc = RESETTABLE_CLASS(klass); device_class_set_props(dc, pxa2xx_pic_properties); + dc->realize = pxa2xx_pic_realize; dc->desc = "PXA2xx PIC"; dc->vmsd = &vmstate_pxa2xx_pic_regs; rc->phases.hold = pxa2xx_pic_reset_hold; From bf348bf9ab5459004927873c37e79f2040887d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Oct 2023 15:03:30 +0200 Subject: [PATCH 28/41] hw/arm/pxa2xx: Realize PXA2XX_I2C device before accessing it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qbus_new(), called in i2c_init_bus(), should not be called on unrealized device. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Thomas Huth Message-id: 20231020130331.50048-10-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/pxa2xx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 601ddd8766..f0bf407e66 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -1513,14 +1513,15 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, qdev_prop_set_uint32(dev, "size", region_size + 1); qdev_prop_set_uint32(dev, "offset", base & region_size); + /* FIXME: Should the slave device really be on a separate bus? */ + i2cbus = i2c_init_bus(dev, "dummy"); + i2c_dev = SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(i2c_dev, &error_fatal); sysbus_mmio_map(i2c_dev, 0, base & ~region_size); sysbus_connect_irq(i2c_dev, 0, irq); s = PXA2XX_I2C(i2c_dev); - /* FIXME: Should the slave device really be on a separate bus? */ - i2cbus = i2c_init_bus(dev, "dummy"); s->slave = PXA2XX_I2C_SLAVE(i2c_slave_create_simple(i2cbus, TYPE_PXA2XX_I2C_SLAVE, 0)); From f0109f721e8994deabd35b69d96d6d0bdfec0425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 25 Oct 2023 08:59:09 +0200 Subject: [PATCH 29/41] hw/arm: Avoid using 'first_cpu' when first ARM CPU is reachable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer using a well known local first CPU rather than a global one. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20231025065909.57344-1-philmd@linaro.org Signed-off-by: Peter Maydell --- hw/arm/bananapi_m2u.c | 2 +- hw/arm/exynos4_boards.c | 7 ++++--- hw/arm/orangepi.c | 2 +- hw/arm/realview.c | 2 +- hw/arm/xilinx_zynq.c | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/hw/arm/bananapi_m2u.c b/hw/arm/bananapi_m2u.c index a7c7a9f96d..8f24b18d8c 100644 --- a/hw/arm/bananapi_m2u.c +++ b/hw/arm/bananapi_m2u.c @@ -128,7 +128,7 @@ static void bpim2u_init(MachineState *machine) bpim2u_binfo.loader_start = r40->memmap[AW_R40_DEV_SDRAM]; bpim2u_binfo.ram_size = machine->ram_size; bpim2u_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC; - arm_load_kernel(ARM_CPU(first_cpu), machine, &bpim2u_binfo); + arm_load_kernel(&r40->cpus[0], machine, &bpim2u_binfo); } static void bpim2u_machine_init(MachineClass *mc) diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c index ef5bcbc212..b0e13eb4f0 100644 --- a/hw/arm/exynos4_boards.c +++ b/hw/arm/exynos4_boards.c @@ -134,9 +134,10 @@ exynos4_boards_init_common(MachineState *machine, static void nuri_init(MachineState *machine) { - exynos4_boards_init_common(machine, EXYNOS4_BOARD_NURI); + Exynos4BoardState *s = exynos4_boards_init_common(machine, + EXYNOS4_BOARD_NURI); - arm_load_kernel(ARM_CPU(first_cpu), machine, &exynos4_board_binfo); + arm_load_kernel(s->soc.cpu[0], machine, &exynos4_board_binfo); } static void smdkc210_init(MachineState *machine) @@ -146,7 +147,7 @@ static void smdkc210_init(MachineState *machine) lan9215_init(SMDK_LAN9118_BASE_ADDR, qemu_irq_invert(s->soc.irq_table[exynos4210_get_irq(37, 1)])); - arm_load_kernel(ARM_CPU(first_cpu), machine, &exynos4_board_binfo); + arm_load_kernel(s->soc.cpu[0], machine, &exynos4_board_binfo); } static void nuri_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c index d0eca54cd9..f3784d45ca 100644 --- a/hw/arm/orangepi.c +++ b/hw/arm/orangepi.c @@ -106,7 +106,7 @@ static void orangepi_init(MachineState *machine) orangepi_binfo.loader_start = h3->memmap[AW_H3_DEV_SDRAM]; orangepi_binfo.ram_size = machine->ram_size; orangepi_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC; - arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo); + arm_load_kernel(&h3->cpus[0], machine, &orangepi_binfo); } static void orangepi_machine_init(MachineClass *mc) diff --git a/hw/arm/realview.c b/hw/arm/realview.c index 8f89526596..132217b2ed 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -384,7 +384,7 @@ static void realview_init(MachineState *machine, realview_binfo.ram_size = ram_size; realview_binfo.board_id = realview_board_id[board_type]; realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); - arm_load_kernel(ARM_CPU(first_cpu), machine, &realview_binfo); + arm_load_kernel(cpu, machine, &realview_binfo); } static void realview_eb_init(MachineState *machine) diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index 8dc2ea83a9..dbb9793aa1 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -349,7 +349,7 @@ static void zynq_init(MachineState *machine) zynq_binfo.board_setup_addr = BOARD_SETUP_ADDR; zynq_binfo.write_board_setup = zynq_write_board_setup; - arm_load_kernel(ARM_CPU(first_cpu), machine, &zynq_binfo); + arm_load_kernel(cpu, machine, &zynq_binfo); } static void zynq_machine_class_init(ObjectClass *oc, void *data) From 6f83dc67168d17856744275e2a0d7a6addf6cfb9 Mon Sep 17 00:00:00 2001 From: Glenn Miles Date: Tue, 24 Oct 2023 14:19:45 -0500 Subject: [PATCH 30/41] misc/led: LED state is set opposite of what is expected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Testing of the LED state showed that when the LED polarity was set to GPIO_POLARITY_ACTIVE_LOW and a low logic value was set on the input GPIO of the LED, the LED was being turn off when it was expected to be turned on. Fixes: ddb67f6402 ("hw/misc/led: Allow connecting from GPIO output") Signed-off-by: Glenn Miles Reviewed-by: Peter Maydell Reviewed-by: Andrew Jeffery Message-id: 20231024191945.4135036-1-milesg@linux.vnet.ibm.com Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- hw/misc/led.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/misc/led.c b/hw/misc/led.c index f6d6d68bce..42bb43a39a 100644 --- a/hw/misc/led.c +++ b/hw/misc/led.c @@ -63,7 +63,7 @@ static void led_set_state_gpio_handler(void *opaque, int line, int new_state) LEDState *s = LED(opaque); assert(line == 0); - led_set_state(s, !!new_state != s->gpio_active_high); + led_set_state(s, !!new_state == s->gpio_active_high); } static void led_reset(DeviceState *dev) From c755c943aa2e24df8eb135d3080c8097d1d5d40f Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:12 +0200 Subject: [PATCH 31/41] hw/net/cadence_gem: use REG32 macro for register definitions Replace register defines with the REG32 macro from registerfields.h in the Cadence GEM device. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-2-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 527 +++++++++++++++++++++---------------------- 1 file changed, 261 insertions(+), 266 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 37e209cda6..bea2224dd8 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -28,6 +28,7 @@ #include "hw/irq.h" #include "hw/net/cadence_gem.h" #include "hw/qdev-properties.h" +#include "hw/registerfields.h" #include "migration/vmstate.h" #include "qapi/error.h" #include "qemu/log.h" @@ -44,136 +45,131 @@ } \ } while (0) -#define GEM_NWCTRL (0x00000000 / 4) /* Network Control reg */ -#define GEM_NWCFG (0x00000004 / 4) /* Network Config reg */ -#define GEM_NWSTATUS (0x00000008 / 4) /* Network Status reg */ -#define GEM_USERIO (0x0000000C / 4) /* User IO reg */ -#define GEM_DMACFG (0x00000010 / 4) /* DMA Control reg */ -#define GEM_TXSTATUS (0x00000014 / 4) /* TX Status reg */ -#define GEM_RXQBASE (0x00000018 / 4) /* RX Q Base address reg */ -#define GEM_TXQBASE (0x0000001C / 4) /* TX Q Base address reg */ -#define GEM_RXSTATUS (0x00000020 / 4) /* RX Status reg */ -#define GEM_ISR (0x00000024 / 4) /* Interrupt Status reg */ -#define GEM_IER (0x00000028 / 4) /* Interrupt Enable reg */ -#define GEM_IDR (0x0000002C / 4) /* Interrupt Disable reg */ -#define GEM_IMR (0x00000030 / 4) /* Interrupt Mask reg */ -#define GEM_PHYMNTNC (0x00000034 / 4) /* Phy Maintenance reg */ -#define GEM_RXPAUSE (0x00000038 / 4) /* RX Pause Time reg */ -#define GEM_TXPAUSE (0x0000003C / 4) /* TX Pause Time reg */ -#define GEM_TXPARTIALSF (0x00000040 / 4) /* TX Partial Store and Forward */ -#define GEM_RXPARTIALSF (0x00000044 / 4) /* RX Partial Store and Forward */ -#define GEM_JUMBO_MAX_LEN (0x00000048 / 4) /* Max Jumbo Frame Size */ -#define GEM_HASHLO (0x00000080 / 4) /* Hash Low address reg */ -#define GEM_HASHHI (0x00000084 / 4) /* Hash High address reg */ -#define GEM_SPADDR1LO (0x00000088 / 4) /* Specific addr 1 low reg */ -#define GEM_SPADDR1HI (0x0000008C / 4) /* Specific addr 1 high reg */ -#define GEM_SPADDR2LO (0x00000090 / 4) /* Specific addr 2 low reg */ -#define GEM_SPADDR2HI (0x00000094 / 4) /* Specific addr 2 high reg */ -#define GEM_SPADDR3LO (0x00000098 / 4) /* Specific addr 3 low reg */ -#define GEM_SPADDR3HI (0x0000009C / 4) /* Specific addr 3 high reg */ -#define GEM_SPADDR4LO (0x000000A0 / 4) /* Specific addr 4 low reg */ -#define GEM_SPADDR4HI (0x000000A4 / 4) /* Specific addr 4 high reg */ -#define GEM_TIDMATCH1 (0x000000A8 / 4) /* Type ID1 Match reg */ -#define GEM_TIDMATCH2 (0x000000AC / 4) /* Type ID2 Match reg */ -#define GEM_TIDMATCH3 (0x000000B0 / 4) /* Type ID3 Match reg */ -#define GEM_TIDMATCH4 (0x000000B4 / 4) /* Type ID4 Match reg */ -#define GEM_WOLAN (0x000000B8 / 4) /* Wake on LAN reg */ -#define GEM_IPGSTRETCH (0x000000BC / 4) /* IPG Stretch reg */ -#define GEM_SVLAN (0x000000C0 / 4) /* Stacked VLAN reg */ -#define GEM_MODID (0x000000FC / 4) /* Module ID reg */ -#define GEM_OCTTXLO (0x00000100 / 4) /* Octets transmitted Low reg */ -#define GEM_OCTTXHI (0x00000104 / 4) /* Octets transmitted High reg */ -#define GEM_TXCNT (0x00000108 / 4) /* Error-free Frames transmitted */ -#define GEM_TXBCNT (0x0000010C / 4) /* Error-free Broadcast Frames */ -#define GEM_TXMCNT (0x00000110 / 4) /* Error-free Multicast Frame */ -#define GEM_TXPAUSECNT (0x00000114 / 4) /* Pause Frames Transmitted */ -#define GEM_TX64CNT (0x00000118 / 4) /* Error-free 64 TX */ -#define GEM_TX65CNT (0x0000011C / 4) /* Error-free 65-127 TX */ -#define GEM_TX128CNT (0x00000120 / 4) /* Error-free 128-255 TX */ -#define GEM_TX256CNT (0x00000124 / 4) /* Error-free 256-511 */ -#define GEM_TX512CNT (0x00000128 / 4) /* Error-free 512-1023 TX */ -#define GEM_TX1024CNT (0x0000012C / 4) /* Error-free 1024-1518 TX */ -#define GEM_TX1519CNT (0x00000130 / 4) /* Error-free larger than 1519 TX */ -#define GEM_TXURUNCNT (0x00000134 / 4) /* TX under run error counter */ -#define GEM_SINGLECOLLCNT (0x00000138 / 4) /* Single Collision Frames */ -#define GEM_MULTCOLLCNT (0x0000013C / 4) /* Multiple Collision Frames */ -#define GEM_EXCESSCOLLCNT (0x00000140 / 4) /* Excessive Collision Frames */ -#define GEM_LATECOLLCNT (0x00000144 / 4) /* Late Collision Frames */ -#define GEM_DEFERTXCNT (0x00000148 / 4) /* Deferred Transmission Frames */ -#define GEM_CSENSECNT (0x0000014C / 4) /* Carrier Sense Error Counter */ -#define GEM_OCTRXLO (0x00000150 / 4) /* Octets Received register Low */ -#define GEM_OCTRXHI (0x00000154 / 4) /* Octets Received register High */ -#define GEM_RXCNT (0x00000158 / 4) /* Error-free Frames Received */ -#define GEM_RXBROADCNT (0x0000015C / 4) /* Error-free Broadcast Frames RX */ -#define GEM_RXMULTICNT (0x00000160 / 4) /* Error-free Multicast Frames RX */ -#define GEM_RXPAUSECNT (0x00000164 / 4) /* Pause Frames Received Counter */ -#define GEM_RX64CNT (0x00000168 / 4) /* Error-free 64 byte Frames RX */ -#define GEM_RX65CNT (0x0000016C / 4) /* Error-free 65-127B Frames RX */ -#define GEM_RX128CNT (0x00000170 / 4) /* Error-free 128-255B Frames RX */ -#define GEM_RX256CNT (0x00000174 / 4) /* Error-free 256-512B Frames RX */ -#define GEM_RX512CNT (0x00000178 / 4) /* Error-free 512-1023B Frames RX */ -#define GEM_RX1024CNT (0x0000017C / 4) /* Error-free 1024-1518B Frames RX */ -#define GEM_RX1519CNT (0x00000180 / 4) /* Error-free 1519-max Frames RX */ -#define GEM_RXUNDERCNT (0x00000184 / 4) /* Undersize Frames Received */ -#define GEM_RXOVERCNT (0x00000188 / 4) /* Oversize Frames Received */ -#define GEM_RXJABCNT (0x0000018C / 4) /* Jabbers Received Counter */ -#define GEM_RXFCSCNT (0x00000190 / 4) /* Frame Check seq. Error Counter */ -#define GEM_RXLENERRCNT (0x00000194 / 4) /* Length Field Error Counter */ -#define GEM_RXSYMERRCNT (0x00000198 / 4) /* Symbol Error Counter */ -#define GEM_RXALIGNERRCNT (0x0000019C / 4) /* Alignment Error Counter */ -#define GEM_RXRSCERRCNT (0x000001A0 / 4) /* Receive Resource Error Counter */ -#define GEM_RXORUNCNT (0x000001A4 / 4) /* Receive Overrun Counter */ -#define GEM_RXIPCSERRCNT (0x000001A8 / 4) /* IP header Checksum Err Counter */ -#define GEM_RXTCPCCNT (0x000001AC / 4) /* TCP Checksum Error Counter */ -#define GEM_RXUDPCCNT (0x000001B0 / 4) /* UDP Checksum Error Counter */ +REG32(NWCTRL, 0x0) /* Network Control reg */ +REG32(NWCFG, 0x4) /* Network Config reg */ +REG32(NWSTATUS, 0x8) /* Network Status reg */ +REG32(USERIO, 0xc) /* User IO reg */ +REG32(DMACFG, 0x10) /* DMA Control reg */ +REG32(TXSTATUS, 0x14) /* TX Status reg */ +REG32(RXQBASE, 0x18) /* RX Q Base address reg */ +REG32(TXQBASE, 0x1c) /* TX Q Base address reg */ +REG32(RXSTATUS, 0x20) /* RX Status reg */ +REG32(ISR, 0x24) /* Interrupt Status reg */ +REG32(IER, 0x28) /* Interrupt Enable reg */ +REG32(IDR, 0x2c) /* Interrupt Disable reg */ +REG32(IMR, 0x30) /* Interrupt Mask reg */ +REG32(PHYMNTNC, 0x34) /* Phy Maintenance reg */ +REG32(RXPAUSE, 0x38) /* RX Pause Time reg */ +REG32(TXPAUSE, 0x3c) /* TX Pause Time reg */ +REG32(TXPARTIALSF, 0x40) /* TX Partial Store and Forward */ +REG32(RXPARTIALSF, 0x44) /* RX Partial Store and Forward */ +REG32(JUMBO_MAX_LEN, 0x48) /* Max Jumbo Frame Size */ +REG32(HASHLO, 0x80) /* Hash Low address reg */ +REG32(HASHHI, 0x84) /* Hash High address reg */ +REG32(SPADDR1LO, 0x88) /* Specific addr 1 low reg */ +REG32(SPADDR1HI, 0x8c) /* Specific addr 1 high reg */ +REG32(SPADDR2LO, 0x90) /* Specific addr 2 low reg */ +REG32(SPADDR2HI, 0x94) /* Specific addr 2 high reg */ +REG32(SPADDR3LO, 0x98) /* Specific addr 3 low reg */ +REG32(SPADDR3HI, 0x9c) /* Specific addr 3 high reg */ +REG32(SPADDR4LO, 0xa0) /* Specific addr 4 low reg */ +REG32(SPADDR4HI, 0xa4) /* Specific addr 4 high reg */ +REG32(TIDMATCH1, 0xa8) /* Type ID1 Match reg */ +REG32(TIDMATCH2, 0xac) /* Type ID2 Match reg */ +REG32(TIDMATCH3, 0xb0) /* Type ID3 Match reg */ +REG32(TIDMATCH4, 0xb4) /* Type ID4 Match reg */ +REG32(WOLAN, 0xb8) /* Wake on LAN reg */ +REG32(IPGSTRETCH, 0xbc) /* IPG Stretch reg */ +REG32(SVLAN, 0xc0) /* Stacked VLAN reg */ +REG32(MODID, 0xfc) /* Module ID reg */ +REG32(OCTTXLO, 0x100) /* Octects transmitted Low reg */ +REG32(OCTTXHI, 0x104) /* Octects transmitted High reg */ +REG32(TXCNT, 0x108) /* Error-free Frames transmitted */ +REG32(TXBCNT, 0x10c) /* Error-free Broadcast Frames */ +REG32(TXMCNT, 0x110) /* Error-free Multicast Frame */ +REG32(TXPAUSECNT, 0x114) /* Pause Frames Transmitted */ +REG32(TX64CNT, 0x118) /* Error-free 64 TX */ +REG32(TX65CNT, 0x11c) /* Error-free 65-127 TX */ +REG32(TX128CNT, 0x120) /* Error-free 128-255 TX */ +REG32(TX256CNT, 0x124) /* Error-free 256-511 */ +REG32(TX512CNT, 0x128) /* Error-free 512-1023 TX */ +REG32(TX1024CNT, 0x12c) /* Error-free 1024-1518 TX */ +REG32(TX1519CNT, 0x130) /* Error-free larger than 1519 TX */ +REG32(TXURUNCNT, 0x134) /* TX under run error counter */ +REG32(SINGLECOLLCNT, 0x138) /* Single Collision Frames */ +REG32(MULTCOLLCNT, 0x13c) /* Multiple Collision Frames */ +REG32(EXCESSCOLLCNT, 0x140) /* Excessive Collision Frames */ +REG32(LATECOLLCNT, 0x144) /* Late Collision Frames */ +REG32(DEFERTXCNT, 0x148) /* Deferred Transmission Frames */ +REG32(CSENSECNT, 0x14c) /* Carrier Sense Error Counter */ +REG32(OCTRXLO, 0x150) /* Octects Received register Low */ +REG32(OCTRXHI, 0x154) /* Octects Received register High */ +REG32(RXCNT, 0x158) /* Error-free Frames Received */ +REG32(RXBROADCNT, 0x15c) /* Error-free Broadcast Frames RX */ +REG32(RXMULTICNT, 0x160) /* Error-free Multicast Frames RX */ +REG32(RXPAUSECNT, 0x164) /* Pause Frames Received Counter */ +REG32(RX64CNT, 0x168) /* Error-free 64 byte Frames RX */ +REG32(RX65CNT, 0x16c) /* Error-free 65-127B Frames RX */ +REG32(RX128CNT, 0x170) /* Error-free 128-255B Frames RX */ +REG32(RX256CNT, 0x174) /* Error-free 256-512B Frames RX */ +REG32(RX512CNT, 0x178) /* Error-free 512-1023B Frames RX */ +REG32(RX1024CNT, 0x17c) /* Error-free 1024-1518B Frames RX */ +REG32(RX1519CNT, 0x180) /* Error-free 1519-max Frames RX */ +REG32(RXUNDERCNT, 0x184) /* Undersize Frames Received */ +REG32(RXOVERCNT, 0x188) /* Oversize Frames Received */ +REG32(RXJABCNT, 0x18c) /* Jabbers Received Counter */ +REG32(RXFCSCNT, 0x190) /* Frame Check seq. Error Counter */ +REG32(RXLENERRCNT, 0x194) /* Length Field Error Counter */ +REG32(RXSYMERRCNT, 0x198) /* Symbol Error Counter */ +REG32(RXALIGNERRCNT, 0x19c) /* Alignment Error Counter */ +REG32(RXRSCERRCNT, 0x1a0) /* Receive Resource Error Counter */ +REG32(RXORUNCNT, 0x1a4) /* Receive Overrun Counter */ +REG32(RXIPCSERRCNT, 0x1a8) /* IP header Checksum Err Counter */ +REG32(RXTCPCCNT, 0x1ac) /* TCP Checksum Error Counter */ +REG32(RXUDPCCNT, 0x1b0) /* UDP Checksum Error Counter */ -#define GEM_1588S (0x000001D0 / 4) /* 1588 Timer Seconds */ -#define GEM_1588NS (0x000001D4 / 4) /* 1588 Timer Nanoseconds */ -#define GEM_1588ADJ (0x000001D8 / 4) /* 1588 Timer Adjust */ -#define GEM_1588INC (0x000001DC / 4) /* 1588 Timer Increment */ -#define GEM_PTPETXS (0x000001E0 / 4) /* PTP Event Frame Transmitted (s) */ -#define GEM_PTPETXNS (0x000001E4 / 4) /* - * PTP Event Frame Transmitted (ns) - */ -#define GEM_PTPERXS (0x000001E8 / 4) /* PTP Event Frame Received (s) */ -#define GEM_PTPERXNS (0x000001EC / 4) /* PTP Event Frame Received (ns) */ -#define GEM_PTPPTXS (0x000001E0 / 4) /* PTP Peer Frame Transmitted (s) */ -#define GEM_PTPPTXNS (0x000001E4 / 4) /* PTP Peer Frame Transmitted (ns) */ -#define GEM_PTPPRXS (0x000001E8 / 4) /* PTP Peer Frame Received (s) */ -#define GEM_PTPPRXNS (0x000001EC / 4) /* PTP Peer Frame Received (ns) */ +REG32(1588S, 0x1d0) /* 1588 Timer Seconds */ +REG32(1588NS, 0x1d4) /* 1588 Timer Nanoseconds */ +REG32(1588ADJ, 0x1d8) /* 1588 Timer Adjust */ +REG32(1588INC, 0x1dc) /* 1588 Timer Increment */ +REG32(PTPETXS, 0x1e0) /* PTP Event Frame Transmitted (s) */ +REG32(PTPETXNS, 0x1e4) /* PTP Event Frame Transmitted (ns) */ +REG32(PTPERXS, 0x1e8) /* PTP Event Frame Received (s) */ +REG32(PTPERXNS, 0x1ec) /* PTP Event Frame Received (ns) */ +REG32(PTPPTXS, 0x1e0) /* PTP Peer Frame Transmitted (s) */ +REG32(PTPPTXNS, 0x1e4) /* PTP Peer Frame Transmitted (ns) */ +REG32(PTPPRXS, 0x1e8) /* PTP Peer Frame Received (s) */ +REG32(PTPPRXNS, 0x1ec) /* PTP Peer Frame Received (ns) */ /* Design Configuration Registers */ -#define GEM_DESCONF (0x00000280 / 4) -#define GEM_DESCONF2 (0x00000284 / 4) -#define GEM_DESCONF3 (0x00000288 / 4) -#define GEM_DESCONF4 (0x0000028C / 4) -#define GEM_DESCONF5 (0x00000290 / 4) -#define GEM_DESCONF6 (0x00000294 / 4) +REG32(DESCONF, 0x280) +REG32(DESCONF2, 0x284) +REG32(DESCONF3, 0x288) +REG32(DESCONF4, 0x28c) +REG32(DESCONF5, 0x290) +REG32(DESCONF6, 0x294) #define GEM_DESCONF6_64B_MASK (1U << 23) -#define GEM_DESCONF7 (0x00000298 / 4) +REG32(DESCONF7, 0x298) -#define GEM_INT_Q1_STATUS (0x00000400 / 4) -#define GEM_INT_Q1_MASK (0x00000640 / 4) +REG32(INT_Q1_STATUS, 0x400) +REG32(INT_Q1_MASK, 0x640) -#define GEM_TRANSMIT_Q1_PTR (0x00000440 / 4) -#define GEM_TRANSMIT_Q7_PTR (GEM_TRANSMIT_Q1_PTR + 6) +REG32(TRANSMIT_Q1_PTR, 0x440) +REG32(TRANSMIT_Q7_PTR, 0x458) -#define GEM_RECEIVE_Q1_PTR (0x00000480 / 4) -#define GEM_RECEIVE_Q7_PTR (GEM_RECEIVE_Q1_PTR + 6) +REG32(RECEIVE_Q1_PTR, 0x480) +REG32(RECEIVE_Q7_PTR, 0x498) -#define GEM_TBQPH (0x000004C8 / 4) -#define GEM_RBQPH (0x000004D4 / 4) +REG32(TBQPH, 0x4c8) +REG32(RBQPH, 0x4d4) -#define GEM_INT_Q1_ENABLE (0x00000600 / 4) -#define GEM_INT_Q7_ENABLE (GEM_INT_Q1_ENABLE + 6) +REG32(INT_Q1_ENABLE, 0x600) +REG32(INT_Q7_ENABLE, 0x618) -#define GEM_INT_Q1_DISABLE (0x00000620 / 4) -#define GEM_INT_Q7_DISABLE (GEM_INT_Q1_DISABLE + 6) +REG32(INT_Q1_DISABLE, 0x620) +REG32(INT_Q7_DISABLE, 0x638) -#define GEM_INT_Q1_MASK (0x00000640 / 4) -#define GEM_INT_Q7_MASK (GEM_INT_Q1_MASK + 6) - -#define GEM_SCREENING_TYPE1_REGISTER_0 (0x00000500 / 4) +REG32(SCREENING_TYPE1_REG0, 0x500) #define GEM_ST1R_UDP_PORT_MATCH_ENABLE (1 << 29) #define GEM_ST1R_DSTC_ENABLE (1 << 28) @@ -184,7 +180,7 @@ #define GEM_ST1R_QUEUE_SHIFT (0) #define GEM_ST1R_QUEUE_WIDTH (3 - GEM_ST1R_QUEUE_SHIFT + 1) -#define GEM_SCREENING_TYPE2_REGISTER_0 (0x00000540 / 4) +REG32(SCREENING_TYPE2_REG0, 0x540) #define GEM_ST2R_COMPARE_A_ENABLE (1 << 18) #define GEM_ST2R_COMPARE_A_SHIFT (13) @@ -196,8 +192,8 @@ #define GEM_ST2R_QUEUE_SHIFT (0) #define GEM_ST2R_QUEUE_WIDTH (3 - GEM_ST2R_QUEUE_SHIFT + 1) -#define GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 (0x000006e0 / 4) -#define GEM_TYPE2_COMPARE_0_WORD_0 (0x00000700 / 4) +REG32(SCREENING_TYPE2_ETHERTYPE_REG0, 0x6e0) +REG32(TYPE2_COMPARE_0_WORD_0, 0x700) #define GEM_T2CW1_COMPARE_OFFSET_SHIFT (7) #define GEM_T2CW1_COMPARE_OFFSET_WIDTH (8 - GEM_T2CW1_COMPARE_OFFSET_SHIFT + 1) @@ -325,7 +321,7 @@ static inline uint64_t tx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc) { uint64_t ret = desc[0]; - if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) { + if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { ret |= (uint64_t)desc[2] << 32; } return ret; @@ -370,7 +366,7 @@ static inline uint64_t rx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc) { uint64_t ret = desc[0] & ~0x3UL; - if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) { + if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { ret |= (uint64_t)desc[2] << 32; } return ret; @@ -380,10 +376,10 @@ static inline int gem_get_desc_len(CadenceGEMState *s, bool rx_n_tx) { int ret = 2; - if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) { + if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { ret += 2; } - if (s->regs[GEM_DMACFG] & (rx_n_tx ? GEM_DMACFG_RX_BD_EXT + if (s->regs[R_DMACFG] & (rx_n_tx ? GEM_DMACFG_RX_BD_EXT : GEM_DMACFG_TX_BD_EXT)) { ret += 2; } @@ -456,8 +452,8 @@ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static uint32_t gem_get_max_buf_len(CadenceGEMState *s, bool tx) { uint32_t size; - if (s->regs[GEM_NWCFG] & GEM_NWCFG_JUMBO_FRAME) { - size = s->regs[GEM_JUMBO_MAX_LEN]; + if (s->regs[R_NWCFG] & GEM_NWCFG_JUMBO_FRAME) { + size = s->regs[R_JUMBO_MAX_LEN]; if (size > s->jumbo_max_len) { size = s->jumbo_max_len; qemu_log_mask(LOG_GUEST_ERROR, "GEM_JUMBO_MAX_LEN reg cannot be" @@ -466,7 +462,7 @@ static uint32_t gem_get_max_buf_len(CadenceGEMState *s, bool tx) } else if (tx) { size = 1518; } else { - size = s->regs[GEM_NWCFG] & GEM_NWCFG_RCV_1538 ? 1538 : 1518; + size = s->regs[R_NWCFG] & GEM_NWCFG_RCV_1538 ? 1538 : 1518; } return size; } @@ -474,10 +470,10 @@ static uint32_t gem_get_max_buf_len(CadenceGEMState *s, bool tx) static void gem_set_isr(CadenceGEMState *s, int q, uint32_t flag) { if (q == 0) { - s->regs[GEM_ISR] |= flag & ~(s->regs[GEM_IMR]); + s->regs[R_ISR] |= flag & ~(s->regs[R_IMR]); } else { - s->regs[GEM_INT_Q1_STATUS + q - 1] |= flag & - ~(s->regs[GEM_INT_Q1_MASK + q - 1]); + s->regs[R_INT_Q1_STATUS + q - 1] |= flag & + ~(s->regs[R_INT_Q1_MASK + q - 1]); } } @@ -491,43 +487,43 @@ static void gem_init_register_masks(CadenceGEMState *s) unsigned int i; /* Mask of register bits which are read only */ memset(&s->regs_ro[0], 0, sizeof(s->regs_ro)); - s->regs_ro[GEM_NWCTRL] = 0xFFF80000; - s->regs_ro[GEM_NWSTATUS] = 0xFFFFFFFF; - s->regs_ro[GEM_DMACFG] = 0x8E00F000; - s->regs_ro[GEM_TXSTATUS] = 0xFFFFFE08; - s->regs_ro[GEM_RXQBASE] = 0x00000003; - s->regs_ro[GEM_TXQBASE] = 0x00000003; - s->regs_ro[GEM_RXSTATUS] = 0xFFFFFFF0; - s->regs_ro[GEM_ISR] = 0xFFFFFFFF; - s->regs_ro[GEM_IMR] = 0xFFFFFFFF; - s->regs_ro[GEM_MODID] = 0xFFFFFFFF; + s->regs_ro[R_NWCTRL] = 0xFFF80000; + s->regs_ro[R_NWSTATUS] = 0xFFFFFFFF; + s->regs_ro[R_DMACFG] = 0x8E00F000; + s->regs_ro[R_TXSTATUS] = 0xFFFFFE08; + s->regs_ro[R_RXQBASE] = 0x00000003; + s->regs_ro[R_TXQBASE] = 0x00000003; + s->regs_ro[R_RXSTATUS] = 0xFFFFFFF0; + s->regs_ro[R_ISR] = 0xFFFFFFFF; + s->regs_ro[R_IMR] = 0xFFFFFFFF; + s->regs_ro[R_MODID] = 0xFFFFFFFF; for (i = 0; i < s->num_priority_queues; i++) { - s->regs_ro[GEM_INT_Q1_STATUS + i] = 0xFFFFFFFF; - s->regs_ro[GEM_INT_Q1_ENABLE + i] = 0xFFFFF319; - s->regs_ro[GEM_INT_Q1_DISABLE + i] = 0xFFFFF319; - s->regs_ro[GEM_INT_Q1_MASK + i] = 0xFFFFFFFF; + s->regs_ro[R_INT_Q1_STATUS + i] = 0xFFFFFFFF; + s->regs_ro[R_INT_Q1_ENABLE + i] = 0xFFFFF319; + s->regs_ro[R_INT_Q1_DISABLE + i] = 0xFFFFF319; + s->regs_ro[R_INT_Q1_MASK + i] = 0xFFFFFFFF; } /* Mask of register bits which are clear on read */ memset(&s->regs_rtc[0], 0, sizeof(s->regs_rtc)); - s->regs_rtc[GEM_ISR] = 0xFFFFFFFF; + s->regs_rtc[R_ISR] = 0xFFFFFFFF; for (i = 0; i < s->num_priority_queues; i++) { - s->regs_rtc[GEM_INT_Q1_STATUS + i] = 0x00000CE6; + s->regs_rtc[R_INT_Q1_STATUS + i] = 0x00000CE6; } /* Mask of register bits which are write 1 to clear */ memset(&s->regs_w1c[0], 0, sizeof(s->regs_w1c)); - s->regs_w1c[GEM_TXSTATUS] = 0x000001F7; - s->regs_w1c[GEM_RXSTATUS] = 0x0000000F; + s->regs_w1c[R_TXSTATUS] = 0x000001F7; + s->regs_w1c[R_RXSTATUS] = 0x0000000F; /* Mask of register bits which are write only */ memset(&s->regs_wo[0], 0, sizeof(s->regs_wo)); - s->regs_wo[GEM_NWCTRL] = 0x00073E60; - s->regs_wo[GEM_IER] = 0x07FFFFFF; - s->regs_wo[GEM_IDR] = 0x07FFFFFF; + s->regs_wo[R_NWCTRL] = 0x00073E60; + s->regs_wo[R_IER] = 0x07FFFFFF; + s->regs_wo[R_IDR] = 0x07FFFFFF; for (i = 0; i < s->num_priority_queues; i++) { - s->regs_wo[GEM_INT_Q1_ENABLE + i] = 0x00000CE6; - s->regs_wo[GEM_INT_Q1_DISABLE + i] = 0x00000CE6; + s->regs_wo[R_INT_Q1_ENABLE + i] = 0x00000CE6; + s->regs_wo[R_INT_Q1_DISABLE + i] = 0x00000CE6; } } @@ -561,7 +557,7 @@ static bool gem_can_receive(NetClientState *nc) s = qemu_get_nic_opaque(nc); /* Do nothing if receive is not enabled. */ - if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_RXENA)) { + if (!(s->regs[R_NWCTRL] & GEM_NWCTRL_RXENA)) { if (s->can_rx_state != 1) { s->can_rx_state = 1; DB_PRINT("can't receive - no enable\n"); @@ -598,10 +594,10 @@ static void gem_update_int_status(CadenceGEMState *s) { int i; - qemu_set_irq(s->irq[0], !!s->regs[GEM_ISR]); + qemu_set_irq(s->irq[0], !!s->regs[R_ISR]); for (i = 1; i < s->num_priority_queues; ++i) { - qemu_set_irq(s->irq[i], !!s->regs[GEM_INT_Q1_STATUS + i - 1]); + qemu_set_irq(s->irq[i], !!s->regs[R_INT_Q1_STATUS + i - 1]); } } @@ -615,39 +611,39 @@ static void gem_receive_updatestats(CadenceGEMState *s, const uint8_t *packet, uint64_t octets; /* Total octets (bytes) received */ - octets = ((uint64_t)(s->regs[GEM_OCTRXLO]) << 32) | - s->regs[GEM_OCTRXHI]; + octets = ((uint64_t)(s->regs[R_OCTRXLO]) << 32) | + s->regs[R_OCTRXHI]; octets += bytes; - s->regs[GEM_OCTRXLO] = octets >> 32; - s->regs[GEM_OCTRXHI] = octets; + s->regs[R_OCTRXLO] = octets >> 32; + s->regs[R_OCTRXHI] = octets; /* Error-free Frames received */ - s->regs[GEM_RXCNT]++; + s->regs[R_RXCNT]++; /* Error-free Broadcast Frames counter */ if (!memcmp(packet, broadcast_addr, 6)) { - s->regs[GEM_RXBROADCNT]++; + s->regs[R_RXBROADCNT]++; } /* Error-free Multicast Frames counter */ if (packet[0] == 0x01) { - s->regs[GEM_RXMULTICNT]++; + s->regs[R_RXMULTICNT]++; } if (bytes <= 64) { - s->regs[GEM_RX64CNT]++; + s->regs[R_RX64CNT]++; } else if (bytes <= 127) { - s->regs[GEM_RX65CNT]++; + s->regs[R_RX65CNT]++; } else if (bytes <= 255) { - s->regs[GEM_RX128CNT]++; + s->regs[R_RX128CNT]++; } else if (bytes <= 511) { - s->regs[GEM_RX256CNT]++; + s->regs[R_RX256CNT]++; } else if (bytes <= 1023) { - s->regs[GEM_RX512CNT]++; + s->regs[R_RX512CNT]++; } else if (bytes <= 1518) { - s->regs[GEM_RX1024CNT]++; + s->regs[R_RX1024CNT]++; } else { - s->regs[GEM_RX1519CNT]++; + s->regs[R_RX1519CNT]++; } } @@ -706,13 +702,13 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet) int i, is_mc; /* Promiscuous mode? */ - if (s->regs[GEM_NWCFG] & GEM_NWCFG_PROMISC) { + if (s->regs[R_NWCFG] & GEM_NWCFG_PROMISC) { return GEM_RX_PROMISCUOUS_ACCEPT; } if (!memcmp(packet, broadcast_addr, 6)) { /* Reject broadcast packets? */ - if (s->regs[GEM_NWCFG] & GEM_NWCFG_BCAST_REJ) { + if (s->regs[R_NWCFG] & GEM_NWCFG_BCAST_REJ) { return GEM_RX_REJECT; } return GEM_RX_BROADCAST_ACCEPT; @@ -720,13 +716,13 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet) /* Accept packets -w- hash match? */ is_mc = is_multicast_ether_addr(packet); - if ((is_mc && (s->regs[GEM_NWCFG] & GEM_NWCFG_MCAST_HASH)) || - (!is_mc && (s->regs[GEM_NWCFG] & GEM_NWCFG_UCAST_HASH))) { + if ((is_mc && (s->regs[R_NWCFG] & GEM_NWCFG_MCAST_HASH)) || + (!is_mc && (s->regs[R_NWCFG] & GEM_NWCFG_UCAST_HASH))) { uint64_t buckets; unsigned hash_index; hash_index = calc_mac_hash(packet); - buckets = ((uint64_t)s->regs[GEM_HASHHI] << 32) | s->regs[GEM_HASHLO]; + buckets = ((uint64_t)s->regs[R_HASHHI] << 32) | s->regs[R_HASHLO]; if ((buckets >> hash_index) & 1) { return is_mc ? GEM_RX_MULTICAST_HASH_ACCEPT : GEM_RX_UNICAST_HASH_ACCEPT; @@ -734,7 +730,7 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet) } /* Check all 4 specific addresses */ - gem_spaddr = (uint8_t *)&(s->regs[GEM_SPADDR1LO]); + gem_spaddr = (uint8_t *)&(s->regs[R_SPADDR1LO]); for (i = 3; i >= 0; i--) { if (s->sar_active[i] && !memcmp(packet, gem_spaddr + 8 * i, 6)) { return GEM_RX_SAR_ACCEPT + i; @@ -754,7 +750,7 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, int i, j; for (i = 0; i < s->num_type1_screeners; i++) { - reg = s->regs[GEM_SCREENING_TYPE1_REGISTER_0 + i]; + reg = s->regs[R_SCREENING_TYPE1_REG0 + i]; matched = false; mismatched = false; @@ -786,7 +782,7 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, } for (i = 0; i < s->num_type2_screeners; i++) { - reg = s->regs[GEM_SCREENING_TYPE2_REGISTER_0 + i]; + reg = s->regs[R_SCREENING_TYPE2_REG0 + i]; matched = false; mismatched = false; @@ -799,7 +795,7 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, qemu_log_mask(LOG_GUEST_ERROR, "Out of range ethertype " "register index: %d\n", et_idx); } - if (type == s->regs[GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 + + if (type == s->regs[R_SCREENING_TYPE2_ETHERTYPE_REG0 + et_idx]) { matched = true; } else { @@ -823,8 +819,8 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, "register index: %d\n", cr_idx); } - cr0 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2]; - cr1 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2 + 1]; + cr0 = s->regs[R_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2]; + cr1 = s->regs[R_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2 + 1]; offset = extract32(cr1, GEM_T2CW1_OFFSET_VALUE_SHIFT, GEM_T2CW1_OFFSET_VALUE_WIDTH); @@ -871,11 +867,11 @@ static uint32_t gem_get_queue_base_addr(CadenceGEMState *s, bool tx, int q) switch (q) { case 0: - base_addr = s->regs[tx ? GEM_TXQBASE : GEM_RXQBASE]; + base_addr = s->regs[tx ? R_TXQBASE : R_RXQBASE]; break; case 1 ... (MAX_PRIORITY_QUEUES - 1): - base_addr = s->regs[(tx ? GEM_TRANSMIT_Q1_PTR : - GEM_RECEIVE_Q1_PTR) + q - 1]; + base_addr = s->regs[(tx ? R_TRANSMIT_Q1_PTR : + R_RECEIVE_Q1_PTR) + q - 1]; break; default: g_assert_not_reached(); @@ -898,8 +894,8 @@ static hwaddr gem_get_desc_addr(CadenceGEMState *s, bool tx, int q) { hwaddr desc_addr = 0; - if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) { - desc_addr = s->regs[tx ? GEM_TBQPH : GEM_RBQPH]; + if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { + desc_addr = s->regs[tx ? R_TBQPH : R_RBQPH]; } desc_addr <<= 32; desc_addr |= tx ? s->tx_desc_addr[q] : s->rx_desc_addr[q]; @@ -930,7 +926,7 @@ static void gem_get_rx_desc(CadenceGEMState *s, int q) /* Descriptor owned by software ? */ if (rx_desc_get_ownership(s->rx_desc[q]) == 1) { DB_PRINT("descriptor 0x%" HWADDR_PRIx " owned by sw.\n", desc_addr); - s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF; + s->regs[R_RXSTATUS] |= GEM_RXSTATUS_NOBUF; gem_set_isr(s, q, GEM_INT_RXUSED); /* Handle interrupt consequences */ gem_update_int_status(s); @@ -958,7 +954,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) } /* Discard packets with receive length error enabled ? */ - if (s->regs[GEM_NWCFG] & GEM_NWCFG_LERR_DISC) { + if (s->regs[R_NWCFG] & GEM_NWCFG_LERR_DISC) { unsigned type_len; /* Fish the ethertype / length field out of the RX packet */ @@ -975,13 +971,13 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) /* * Determine configured receive buffer offset (probably 0) */ - rxbuf_offset = (s->regs[GEM_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >> + rxbuf_offset = (s->regs[R_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >> GEM_NWCFG_BUFF_OFST_S; /* The configure size of each receive buffer. Determines how many * buffers needed to hold this packet. */ - rxbufsize = ((s->regs[GEM_DMACFG] & GEM_DMACFG_RBUFSZ_M) >> + rxbufsize = ((s->regs[R_DMACFG] & GEM_DMACFG_RBUFSZ_M) >> GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL; bytes_to_copy = size; @@ -1001,7 +997,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) } /* Strip of FCS field ? (usually yes) */ - if (s->regs[GEM_NWCFG] & GEM_NWCFG_STRIP_FCS) { + if (s->regs[R_NWCFG] & GEM_NWCFG_STRIP_FCS) { rxbuf_ptr = (void *)buf; } else { unsigned crc_val; @@ -1107,7 +1103,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) /* Count it */ gem_receive_updatestats(s, buf, size); - s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD; + s->regs[R_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD; gem_set_isr(s, q, GEM_INT_RXCMPL); /* Handle interrupt consequences */ @@ -1126,39 +1122,39 @@ static void gem_transmit_updatestats(CadenceGEMState *s, const uint8_t *packet, uint64_t octets; /* Total octets (bytes) transmitted */ - octets = ((uint64_t)(s->regs[GEM_OCTTXLO]) << 32) | - s->regs[GEM_OCTTXHI]; + octets = ((uint64_t)(s->regs[R_OCTTXLO]) << 32) | + s->regs[R_OCTTXHI]; octets += bytes; - s->regs[GEM_OCTTXLO] = octets >> 32; - s->regs[GEM_OCTTXHI] = octets; + s->regs[R_OCTTXLO] = octets >> 32; + s->regs[R_OCTTXHI] = octets; /* Error-free Frames transmitted */ - s->regs[GEM_TXCNT]++; + s->regs[R_TXCNT]++; /* Error-free Broadcast Frames counter */ if (!memcmp(packet, broadcast_addr, 6)) { - s->regs[GEM_TXBCNT]++; + s->regs[R_TXBCNT]++; } /* Error-free Multicast Frames counter */ if (packet[0] == 0x01) { - s->regs[GEM_TXMCNT]++; + s->regs[R_TXMCNT]++; } if (bytes <= 64) { - s->regs[GEM_TX64CNT]++; + s->regs[R_TX64CNT]++; } else if (bytes <= 127) { - s->regs[GEM_TX65CNT]++; + s->regs[R_TX65CNT]++; } else if (bytes <= 255) { - s->regs[GEM_TX128CNT]++; + s->regs[R_TX128CNT]++; } else if (bytes <= 511) { - s->regs[GEM_TX256CNT]++; + s->regs[R_TX256CNT]++; } else if (bytes <= 1023) { - s->regs[GEM_TX512CNT]++; + s->regs[R_TX512CNT]++; } else if (bytes <= 1518) { - s->regs[GEM_TX1024CNT]++; + s->regs[R_TX1024CNT]++; } else { - s->regs[GEM_TX1519CNT]++; + s->regs[R_TX1519CNT]++; } } @@ -1175,7 +1171,7 @@ static void gem_transmit(CadenceGEMState *s) int q = 0; /* Do nothing if transmit is not enabled. */ - if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) { + if (!(s->regs[R_NWCTRL] & GEM_NWCTRL_TXENA)) { return; } @@ -1200,7 +1196,7 @@ static void gem_transmit(CadenceGEMState *s) while (tx_desc_get_used(desc) == 0) { /* Do nothing if transmit is not enabled. */ - if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) { + if (!(s->regs[R_NWCTRL] & GEM_NWCTRL_TXENA)) { return; } print_gem_tx_desc(desc, q); @@ -1258,14 +1254,14 @@ static void gem_transmit(CadenceGEMState *s) } DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]); - s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL; + s->regs[R_TXSTATUS] |= GEM_TXSTATUS_TXCMPL; gem_set_isr(s, q, GEM_INT_TXCMPL); /* Handle interrupt consequences */ gem_update_int_status(s); /* Is checksum offload enabled? */ - if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) { + if (s->regs[R_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) { net_checksum_calculate(s->tx_packet, total_bytes, CSUM_ALL); } @@ -1273,7 +1269,7 @@ static void gem_transmit(CadenceGEMState *s) gem_transmit_updatestats(s, s->tx_packet, total_bytes); /* Send the packet somewhere */ - if (s->phy_loop || (s->regs[GEM_NWCTRL] & + if (s->phy_loop || (s->regs[R_NWCTRL] & GEM_NWCTRL_LOCALLOOP)) { qemu_receive_packet(qemu_get_queue(s->nic), s->tx_packet, total_bytes); @@ -1289,9 +1285,8 @@ static void gem_transmit(CadenceGEMState *s) /* read next descriptor */ if (tx_desc_get_wrap(desc)) { - - if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) { - packet_desc_addr = s->regs[GEM_TBQPH]; + if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { + packet_desc_addr = s->regs[R_TBQPH]; packet_desc_addr <<= 32; } else { packet_desc_addr = 0; @@ -1307,7 +1302,7 @@ static void gem_transmit(CadenceGEMState *s) } if (tx_desc_get_used(desc)) { - s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED; + s->regs[R_TXSTATUS] |= GEM_TXSTATUS_USED; /* IRQ TXUSED is defined only for queue 0 */ if (q == 0) { gem_set_isr(s, 0, GEM_INT_TXUSED); @@ -1353,30 +1348,30 @@ static void gem_reset(DeviceState *d) /* Set post reset register values */ memset(&s->regs[0], 0, sizeof(s->regs)); - s->regs[GEM_NWCFG] = 0x00080000; - s->regs[GEM_NWSTATUS] = 0x00000006; - s->regs[GEM_DMACFG] = 0x00020784; - s->regs[GEM_IMR] = 0x07ffffff; - s->regs[GEM_TXPAUSE] = 0x0000ffff; - s->regs[GEM_TXPARTIALSF] = 0x000003ff; - s->regs[GEM_RXPARTIALSF] = 0x000003ff; - s->regs[GEM_MODID] = s->revision; - s->regs[GEM_DESCONF] = 0x02D00111; - s->regs[GEM_DESCONF2] = 0x2ab10000 | s->jumbo_max_len; - s->regs[GEM_DESCONF5] = 0x002f2045; - s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK; - s->regs[GEM_INT_Q1_MASK] = 0x00000CE6; - s->regs[GEM_JUMBO_MAX_LEN] = s->jumbo_max_len; + s->regs[R_NWCFG] = 0x00080000; + s->regs[R_NWSTATUS] = 0x00000006; + s->regs[R_DMACFG] = 0x00020784; + s->regs[R_IMR] = 0x07ffffff; + s->regs[R_TXPAUSE] = 0x0000ffff; + s->regs[R_TXPARTIALSF] = 0x000003ff; + s->regs[R_RXPARTIALSF] = 0x000003ff; + s->regs[R_MODID] = s->revision; + s->regs[R_DESCONF] = 0x02D00111; + s->regs[R_DESCONF2] = 0x2ab10000 | s->jumbo_max_len; + s->regs[R_DESCONF5] = 0x002f2045; + s->regs[R_DESCONF6] = GEM_DESCONF6_64B_MASK; + s->regs[R_INT_Q1_MASK] = 0x00000CE6; + s->regs[R_JUMBO_MAX_LEN] = s->jumbo_max_len; if (s->num_priority_queues > 1) { queues_mask = MAKE_64BIT_MASK(1, s->num_priority_queues - 1); - s->regs[GEM_DESCONF6] |= queues_mask; + s->regs[R_DESCONF6] |= queues_mask; } /* Set MAC address */ a = &s->conf.macaddr.a[0]; - s->regs[GEM_SPADDR1LO] = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); - s->regs[GEM_SPADDR1HI] = a[4] | (a[5] << 8); + s->regs[R_SPADDR1LO] = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); + s->regs[R_SPADDR1HI] = a[4] | (a[5] << 8); for (i = 0; i < 4; i++) { s->sar_active[i] = false; @@ -1437,11 +1432,11 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) DB_PRINT("offset: 0x%04x read: 0x%08x\n", (unsigned)offset*4, retval); switch (offset) { - case GEM_ISR: + case R_ISR: DB_PRINT("lowering irqs on ISR read\n"); /* The interrupts get updated at the end of the function. */ break; - case GEM_PHYMNTNC: + case R_PHYMNTNC: if (retval & GEM_PHYMNTNC_OP_R) { uint32_t phy_addr, reg_num; @@ -1495,7 +1490,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, /* Handle register write side effects */ switch (offset) { - case GEM_NWCTRL: + case R_NWCTRL: if (val & GEM_NWCTRL_RXENA) { for (i = 0; i < s->num_priority_queues; ++i) { gem_get_rx_desc(s, i); @@ -1515,56 +1510,56 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, } break; - case GEM_TXSTATUS: + case R_TXSTATUS: gem_update_int_status(s); break; - case GEM_RXQBASE: + case R_RXQBASE: s->rx_desc_addr[0] = val; break; - case GEM_RECEIVE_Q1_PTR ... GEM_RECEIVE_Q7_PTR: - s->rx_desc_addr[offset - GEM_RECEIVE_Q1_PTR + 1] = val; + case R_RECEIVE_Q1_PTR ... R_RECEIVE_Q7_PTR: + s->rx_desc_addr[offset - R_RECEIVE_Q1_PTR + 1] = val; break; - case GEM_TXQBASE: + case R_TXQBASE: s->tx_desc_addr[0] = val; break; - case GEM_TRANSMIT_Q1_PTR ... GEM_TRANSMIT_Q7_PTR: - s->tx_desc_addr[offset - GEM_TRANSMIT_Q1_PTR + 1] = val; + case R_TRANSMIT_Q1_PTR ... R_TRANSMIT_Q7_PTR: + s->tx_desc_addr[offset - R_TRANSMIT_Q1_PTR + 1] = val; break; - case GEM_RXSTATUS: + case R_RXSTATUS: gem_update_int_status(s); break; - case GEM_IER: - s->regs[GEM_IMR] &= ~val; + case R_IER: + s->regs[R_IMR] &= ~val; gem_update_int_status(s); break; - case GEM_JUMBO_MAX_LEN: - s->regs[GEM_JUMBO_MAX_LEN] = val & MAX_JUMBO_FRAME_SIZE_MASK; + case R_JUMBO_MAX_LEN: + s->regs[R_JUMBO_MAX_LEN] = val & MAX_JUMBO_FRAME_SIZE_MASK; break; - case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE: - s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val; + case R_INT_Q1_ENABLE ... R_INT_Q7_ENABLE: + s->regs[R_INT_Q1_MASK + offset - R_INT_Q1_ENABLE] &= ~val; gem_update_int_status(s); break; - case GEM_IDR: - s->regs[GEM_IMR] |= val; + case R_IDR: + s->regs[R_IMR] |= val; gem_update_int_status(s); break; - case GEM_INT_Q1_DISABLE ... GEM_INT_Q7_DISABLE: - s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_DISABLE] |= val; + case R_INT_Q1_DISABLE ... R_INT_Q7_DISABLE: + s->regs[R_INT_Q1_MASK + offset - R_INT_Q1_DISABLE] |= val; gem_update_int_status(s); break; - case GEM_SPADDR1LO: - case GEM_SPADDR2LO: - case GEM_SPADDR3LO: - case GEM_SPADDR4LO: - s->sar_active[(offset - GEM_SPADDR1LO) / 2] = false; + case R_SPADDR1LO: + case R_SPADDR2LO: + case R_SPADDR3LO: + case R_SPADDR4LO: + s->sar_active[(offset - R_SPADDR1LO) / 2] = false; break; - case GEM_SPADDR1HI: - case GEM_SPADDR2HI: - case GEM_SPADDR3HI: - case GEM_SPADDR4HI: - s->sar_active[(offset - GEM_SPADDR1HI) / 2] = true; + case R_SPADDR1HI: + case R_SPADDR2HI: + case R_SPADDR3HI: + case R_SPADDR4HI: + s->sar_active[(offset - R_SPADDR1HI) / 2] = true; break; - case GEM_PHYMNTNC: + case R_PHYMNTNC: if (val & GEM_PHYMNTNC_OP_W) { uint32_t phy_addr, reg_num; From b46b526c082840d35d0c9dc2690a1cb159bda176 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:13 +0200 Subject: [PATCH 32/41] hw/net/cadence_gem: use FIELD for screening registers Describe screening registers fields using the FIELD macros. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-3-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 94 ++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index bea2224dd8..dd00556232 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -170,35 +170,38 @@ REG32(INT_Q1_DISABLE, 0x620) REG32(INT_Q7_DISABLE, 0x638) REG32(SCREENING_TYPE1_REG0, 0x500) - -#define GEM_ST1R_UDP_PORT_MATCH_ENABLE (1 << 29) -#define GEM_ST1R_DSTC_ENABLE (1 << 28) -#define GEM_ST1R_UDP_PORT_MATCH_SHIFT (12) -#define GEM_ST1R_UDP_PORT_MATCH_WIDTH (27 - GEM_ST1R_UDP_PORT_MATCH_SHIFT + 1) -#define GEM_ST1R_DSTC_MATCH_SHIFT (4) -#define GEM_ST1R_DSTC_MATCH_WIDTH (11 - GEM_ST1R_DSTC_MATCH_SHIFT + 1) -#define GEM_ST1R_QUEUE_SHIFT (0) -#define GEM_ST1R_QUEUE_WIDTH (3 - GEM_ST1R_QUEUE_SHIFT + 1) + FIELD(SCREENING_TYPE1_REG0, QUEUE_NUM, 0, 4) + FIELD(SCREENING_TYPE1_REG0, DSTC_MATCH, 4, 8) + FIELD(SCREENING_TYPE1_REG0, UDP_PORT_MATCH, 12, 16) + FIELD(SCREENING_TYPE1_REG0, DSTC_ENABLE, 28, 1) + FIELD(SCREENING_TYPE1_REG0, UDP_PORT_MATCH_EN, 29, 1) + FIELD(SCREENING_TYPE1_REG0, DROP_ON_MATCH, 30, 1) REG32(SCREENING_TYPE2_REG0, 0x540) - -#define GEM_ST2R_COMPARE_A_ENABLE (1 << 18) -#define GEM_ST2R_COMPARE_A_SHIFT (13) -#define GEM_ST2R_COMPARE_WIDTH (17 - GEM_ST2R_COMPARE_A_SHIFT + 1) -#define GEM_ST2R_ETHERTYPE_ENABLE (1 << 12) -#define GEM_ST2R_ETHERTYPE_INDEX_SHIFT (9) -#define GEM_ST2R_ETHERTYPE_INDEX_WIDTH (11 - GEM_ST2R_ETHERTYPE_INDEX_SHIFT \ - + 1) -#define GEM_ST2R_QUEUE_SHIFT (0) -#define GEM_ST2R_QUEUE_WIDTH (3 - GEM_ST2R_QUEUE_SHIFT + 1) + FIELD(SCREENING_TYPE2_REG0, QUEUE_NUM, 0, 4) + FIELD(SCREENING_TYPE2_REG0, VLAN_PRIORITY, 4, 3) + FIELD(SCREENING_TYPE2_REG0, VLAN_ENABLE, 8, 1) + FIELD(SCREENING_TYPE2_REG0, ETHERTYPE_REG_INDEX, 9, 3) + FIELD(SCREENING_TYPE2_REG0, ETHERTYPE_ENABLE, 12, 1) + FIELD(SCREENING_TYPE2_REG0, COMPARE_A, 13, 5) + FIELD(SCREENING_TYPE2_REG0, COMPARE_A_ENABLE, 18, 1) + FIELD(SCREENING_TYPE2_REG0, COMPARE_B, 19, 5) + FIELD(SCREENING_TYPE2_REG0, COMPARE_B_ENABLE, 24, 1) + FIELD(SCREENING_TYPE2_REG0, COMPARE_C, 25, 5) + FIELD(SCREENING_TYPE2_REG0, COMPARE_C_ENABLE, 30, 1) + FIELD(SCREENING_TYPE2_REG0, DROP_ON_MATCH, 31, 1) REG32(SCREENING_TYPE2_ETHERTYPE_REG0, 0x6e0) -REG32(TYPE2_COMPARE_0_WORD_0, 0x700) -#define GEM_T2CW1_COMPARE_OFFSET_SHIFT (7) -#define GEM_T2CW1_COMPARE_OFFSET_WIDTH (8 - GEM_T2CW1_COMPARE_OFFSET_SHIFT + 1) -#define GEM_T2CW1_OFFSET_VALUE_SHIFT (0) -#define GEM_T2CW1_OFFSET_VALUE_WIDTH (6 - GEM_T2CW1_OFFSET_VALUE_SHIFT + 1) +REG32(TYPE2_COMPARE_0_WORD_0, 0x700) + FIELD(TYPE2_COMPARE_0_WORD_0, MASK_VALUE, 0, 16) + FIELD(TYPE2_COMPARE_0_WORD_0, COMPARE_VALUE, 16, 16) + +REG32(TYPE2_COMPARE_0_WORD_1, 0x704) + FIELD(TYPE2_COMPARE_0_WORD_1, OFFSET_VALUE, 0, 7) + FIELD(TYPE2_COMPARE_0_WORD_1, COMPARE_OFFSET, 7, 2) + FIELD(TYPE2_COMPARE_0_WORD_1, DISABLE_MASK, 9, 1) + FIELD(TYPE2_COMPARE_0_WORD_1, COMPARE_VLAN_ID, 10, 1) /*****************************************/ #define GEM_NWCTRL_TXSTART 0x00000200 /* Transmit Enable */ @@ -755,10 +758,9 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, mismatched = false; /* Screening is based on UDP Port */ - if (reg & GEM_ST1R_UDP_PORT_MATCH_ENABLE) { + if (FIELD_EX32(reg, SCREENING_TYPE1_REG0, UDP_PORT_MATCH_EN)) { uint16_t udp_port = rxbuf_ptr[14 + 22] << 8 | rxbuf_ptr[14 + 23]; - if (udp_port == extract32(reg, GEM_ST1R_UDP_PORT_MATCH_SHIFT, - GEM_ST1R_UDP_PORT_MATCH_WIDTH)) { + if (udp_port == FIELD_EX32(reg, SCREENING_TYPE1_REG0, UDP_PORT_MATCH)) { matched = true; } else { mismatched = true; @@ -766,10 +768,9 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, } /* Screening is based on DS/TC */ - if (reg & GEM_ST1R_DSTC_ENABLE) { + if (FIELD_EX32(reg, SCREENING_TYPE1_REG0, DSTC_ENABLE)) { uint8_t dscp = rxbuf_ptr[14 + 1]; - if (dscp == extract32(reg, GEM_ST1R_DSTC_MATCH_SHIFT, - GEM_ST1R_DSTC_MATCH_WIDTH)) { + if (dscp == FIELD_EX32(reg, SCREENING_TYPE1_REG0, DSTC_MATCH)) { matched = true; } else { mismatched = true; @@ -777,7 +778,7 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, } if (matched && !mismatched) { - return extract32(reg, GEM_ST1R_QUEUE_SHIFT, GEM_ST1R_QUEUE_WIDTH); + return FIELD_EX32(reg, SCREENING_TYPE1_REG0, QUEUE_NUM); } } @@ -786,10 +787,10 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, matched = false; mismatched = false; - if (reg & GEM_ST2R_ETHERTYPE_ENABLE) { + if (FIELD_EX32(reg, SCREENING_TYPE2_REG0, ETHERTYPE_ENABLE)) { uint16_t type = rxbuf_ptr[12] << 8 | rxbuf_ptr[13]; - int et_idx = extract32(reg, GEM_ST2R_ETHERTYPE_INDEX_SHIFT, - GEM_ST2R_ETHERTYPE_INDEX_WIDTH); + int et_idx = FIELD_EX32(reg, SCREENING_TYPE2_REG0, + ETHERTYPE_REG_INDEX); if (et_idx > s->num_type2_screeners) { qemu_log_mask(LOG_GUEST_ERROR, "Out of range ethertype " @@ -805,27 +806,27 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, /* Compare A, B, C */ for (j = 0; j < 3; j++) { - uint32_t cr0, cr1, mask; + uint32_t cr0, cr1, mask, compare; uint16_t rx_cmp; int offset; - int cr_idx = extract32(reg, GEM_ST2R_COMPARE_A_SHIFT + j * 6, - GEM_ST2R_COMPARE_WIDTH); + int cr_idx = extract32(reg, R_SCREENING_TYPE2_REG0_COMPARE_A_SHIFT + j * 6, + R_SCREENING_TYPE2_REG0_COMPARE_A_LENGTH); - if (!(reg & (GEM_ST2R_COMPARE_A_ENABLE << (j * 6)))) { + if (!extract32(reg, R_SCREENING_TYPE2_REG0_COMPARE_A_ENABLE_SHIFT + j * 6, + R_SCREENING_TYPE2_REG0_COMPARE_A_ENABLE_LENGTH)) { continue; } + if (cr_idx > s->num_type2_screeners) { qemu_log_mask(LOG_GUEST_ERROR, "Out of range compare " "register index: %d\n", cr_idx); } cr0 = s->regs[R_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2]; - cr1 = s->regs[R_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2 + 1]; - offset = extract32(cr1, GEM_T2CW1_OFFSET_VALUE_SHIFT, - GEM_T2CW1_OFFSET_VALUE_WIDTH); + cr1 = s->regs[R_TYPE2_COMPARE_0_WORD_1 + cr_idx * 2]; + offset = FIELD_EX32(cr1, TYPE2_COMPARE_0_WORD_1, OFFSET_VALUE); - switch (extract32(cr1, GEM_T2CW1_COMPARE_OFFSET_SHIFT, - GEM_T2CW1_COMPARE_OFFSET_WIDTH)) { + switch (FIELD_EX32(cr1, TYPE2_COMPARE_0_WORD_1, COMPARE_OFFSET)) { case 3: /* Skip UDP header */ qemu_log_mask(LOG_UNIMP, "TCP compare offsets" "unimplemented - assuming UDP\n"); @@ -843,9 +844,10 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, } rx_cmp = rxbuf_ptr[offset] << 8 | rxbuf_ptr[offset]; - mask = extract32(cr0, 0, 16); + mask = FIELD_EX32(cr0, TYPE2_COMPARE_0_WORD_0, MASK_VALUE); + compare = FIELD_EX32(cr0, TYPE2_COMPARE_0_WORD_0, COMPARE_VALUE); - if ((rx_cmp & mask) == (extract32(cr0, 16, 16) & mask)) { + if ((rx_cmp & mask) == (compare & mask)) { matched = true; } else { mismatched = true; @@ -853,7 +855,7 @@ static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr, } if (matched && !mismatched) { - return extract32(reg, GEM_ST2R_QUEUE_SHIFT, GEM_ST2R_QUEUE_WIDTH); + return FIELD_EX32(reg, SCREENING_TYPE2_REG0, QUEUE_NUM); } } From bd8a922d2fc99445b2814c3a53d6be0f99555ea3 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:14 +0200 Subject: [PATCH 33/41] hw/net/cadence_gem: use FIELD to describe NWCTRL register fields Use the FIELD macro to describe the NWCTRL register fields. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-4-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 53 +++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index dd00556232..1bcc9b6811 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -46,6 +46,38 @@ } while (0) REG32(NWCTRL, 0x0) /* Network Control reg */ + FIELD(NWCTRL, LOOPBACK , 0, 1) + FIELD(NWCTRL, LOOPBACK_LOCAL , 1, 1) + FIELD(NWCTRL, ENABLE_RECEIVE, 2, 1) + FIELD(NWCTRL, ENABLE_TRANSMIT, 3, 1) + FIELD(NWCTRL, MAN_PORT_EN , 4, 1) + FIELD(NWCTRL, CLEAR_ALL_STATS_REGS , 5, 1) + FIELD(NWCTRL, INC_ALL_STATS_REGS, 6, 1) + FIELD(NWCTRL, STATS_WRITE_EN, 7, 1) + FIELD(NWCTRL, BACK_PRESSURE, 8, 1) + FIELD(NWCTRL, TRANSMIT_START , 9, 1) + FIELD(NWCTRL, TRANSMIT_HALT, 10, 1) + FIELD(NWCTRL, TX_PAUSE_FRAME_RE, 11, 1) + FIELD(NWCTRL, TX_PAUSE_FRAME_ZE, 12, 1) + FIELD(NWCTRL, STATS_TAKE_SNAP, 13, 1) + FIELD(NWCTRL, STATS_READ_SNAP, 14, 1) + FIELD(NWCTRL, STORE_RX_TS, 15, 1) + FIELD(NWCTRL, PFC_ENABLE, 16, 1) + FIELD(NWCTRL, PFC_PRIO_BASED, 17, 1) + FIELD(NWCTRL, FLUSH_RX_PKT_PCLK , 18, 1) + FIELD(NWCTRL, TX_LPI_EN, 19, 1) + FIELD(NWCTRL, PTP_UNICAST_ENA, 20, 1) + FIELD(NWCTRL, ALT_SGMII_MODE, 21, 1) + FIELD(NWCTRL, STORE_UDP_OFFSET, 22, 1) + FIELD(NWCTRL, EXT_TSU_PORT_EN, 23, 1) + FIELD(NWCTRL, ONE_STEP_SYNC_MO, 24, 1) + FIELD(NWCTRL, PFC_CTRL , 25, 1) + FIELD(NWCTRL, EXT_RXQ_SEL_EN , 26, 1) + FIELD(NWCTRL, OSS_CORRECTION_FIELD, 27, 1) + FIELD(NWCTRL, SEL_MII_ON_RGMII, 28, 1) + FIELD(NWCTRL, TWO_PT_FIVE_GIG, 29, 1) + FIELD(NWCTRL, IFG_EATS_QAV_CREDIT, 30, 1) + REG32(NWCFG, 0x4) /* Network Config reg */ REG32(NWSTATUS, 0x8) /* Network Status reg */ REG32(USERIO, 0xc) /* User IO reg */ @@ -204,11 +236,6 @@ REG32(TYPE2_COMPARE_0_WORD_1, 0x704) FIELD(TYPE2_COMPARE_0_WORD_1, COMPARE_VLAN_ID, 10, 1) /*****************************************/ -#define GEM_NWCTRL_TXSTART 0x00000200 /* Transmit Enable */ -#define GEM_NWCTRL_TXENA 0x00000008 /* Transmit Enable */ -#define GEM_NWCTRL_RXENA 0x00000004 /* Receive Enable */ -#define GEM_NWCTRL_LOCALLOOP 0x00000002 /* Local Loopback */ - #define GEM_NWCFG_STRIP_FCS 0x00020000 /* Strip FCS field */ #define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with len err */ #define GEM_NWCFG_BUFF_OFST_M 0x0000C000 /* Receive buffer offset mask */ @@ -560,7 +587,7 @@ static bool gem_can_receive(NetClientState *nc) s = qemu_get_nic_opaque(nc); /* Do nothing if receive is not enabled. */ - if (!(s->regs[R_NWCTRL] & GEM_NWCTRL_RXENA)) { + if (!FIELD_EX32(s->regs[R_NWCTRL], NWCTRL, ENABLE_RECEIVE)) { if (s->can_rx_state != 1) { s->can_rx_state = 1; DB_PRINT("can't receive - no enable\n"); @@ -1173,7 +1200,7 @@ static void gem_transmit(CadenceGEMState *s) int q = 0; /* Do nothing if transmit is not enabled. */ - if (!(s->regs[R_NWCTRL] & GEM_NWCTRL_TXENA)) { + if (!FIELD_EX32(s->regs[R_NWCTRL], NWCTRL, ENABLE_TRANSMIT)) { return; } @@ -1198,7 +1225,7 @@ static void gem_transmit(CadenceGEMState *s) while (tx_desc_get_used(desc) == 0) { /* Do nothing if transmit is not enabled. */ - if (!(s->regs[R_NWCTRL] & GEM_NWCTRL_TXENA)) { + if (!FIELD_EX32(s->regs[R_NWCTRL], NWCTRL, ENABLE_TRANSMIT)) { return; } print_gem_tx_desc(desc, q); @@ -1271,8 +1298,8 @@ static void gem_transmit(CadenceGEMState *s) gem_transmit_updatestats(s, s->tx_packet, total_bytes); /* Send the packet somewhere */ - if (s->phy_loop || (s->regs[R_NWCTRL] & - GEM_NWCTRL_LOCALLOOP)) { + if (s->phy_loop || FIELD_EX32(s->regs[R_NWCTRL], NWCTRL, + LOOPBACK_LOCAL)) { qemu_receive_packet(qemu_get_queue(s->nic), s->tx_packet, total_bytes); } else { @@ -1493,15 +1520,15 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, /* Handle register write side effects */ switch (offset) { case R_NWCTRL: - if (val & GEM_NWCTRL_RXENA) { + if (FIELD_EX32(val, NWCTRL, ENABLE_RECEIVE)) { for (i = 0; i < s->num_priority_queues; ++i) { gem_get_rx_desc(s, i); } } - if (val & GEM_NWCTRL_TXSTART) { + if (FIELD_EX32(val, NWCTRL, TRANSMIT_START)) { gem_transmit(s); } - if (!(val & GEM_NWCTRL_TXENA)) { + if (!(FIELD_EX32(val, NWCTRL, ENABLE_TRANSMIT))) { /* Reset to start of Q when transmit disabled. */ for (i = 0; i < s->num_priority_queues; i++) { s->tx_desc_addr[i] = gem_get_tx_queue_base_addr(s, i); From 87a49c3f80c5cb80754f59ddd7006c57d69020ac Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:15 +0200 Subject: [PATCH 34/41] hw/net/cadence_gem: use FIELD to describe NWCFG register fields Use de FIELD macro to describe the NWCFG register fields. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-5-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 60 ++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 1bcc9b6811..cf8b1261ed 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -79,6 +79,35 @@ REG32(NWCTRL, 0x0) /* Network Control reg */ FIELD(NWCTRL, IFG_EATS_QAV_CREDIT, 30, 1) REG32(NWCFG, 0x4) /* Network Config reg */ + FIELD(NWCFG, SPEED, 0, 1) + FIELD(NWCFG, FULL_DUPLEX, 1, 1) + FIELD(NWCFG, DISCARD_NON_VLAN_FRAMES, 2, 1) + FIELD(NWCFG, JUMBO_FRAMES, 3, 1) + FIELD(NWCFG, PROMISC, 4, 1) + FIELD(NWCFG, NO_BROADCAST, 5, 1) + FIELD(NWCFG, MULTICAST_HASH_EN, 6, 1) + FIELD(NWCFG, UNICAST_HASH_EN, 7, 1) + FIELD(NWCFG, RECV_1536_BYTE_FRAMES, 8, 1) + FIELD(NWCFG, EXTERNAL_ADDR_MATCH_EN, 9, 1) + FIELD(NWCFG, GIGABIT_MODE_ENABLE, 10, 1) + FIELD(NWCFG, PCS_SELECT, 11, 1) + FIELD(NWCFG, RETRY_TEST, 12, 1) + FIELD(NWCFG, PAUSE_ENABLE, 13, 1) + FIELD(NWCFG, RECV_BUF_OFFSET, 14, 2) + FIELD(NWCFG, LEN_ERR_DISCARD, 16, 1) + FIELD(NWCFG, FCS_REMOVE, 17, 1) + FIELD(NWCFG, MDC_CLOCK_DIV, 18, 3) + FIELD(NWCFG, DATA_BUS_WIDTH, 21, 2) + FIELD(NWCFG, DISABLE_COPY_PAUSE_FRAMES, 23, 1) + FIELD(NWCFG, RECV_CSUM_OFFLOAD_EN, 24, 1) + FIELD(NWCFG, EN_HALF_DUPLEX_RX, 25, 1) + FIELD(NWCFG, IGNORE_RX_FCS, 26, 1) + FIELD(NWCFG, SGMII_MODE_ENABLE, 27, 1) + FIELD(NWCFG, IPG_STRETCH_ENABLE, 28, 1) + FIELD(NWCFG, NSP_ACCEPT, 29, 1) + FIELD(NWCFG, IGNORE_IPG_RX_ER, 30, 1) + FIELD(NWCFG, UNI_DIRECTION_ENABLE, 31, 1) + REG32(NWSTATUS, 0x8) /* Network Status reg */ REG32(USERIO, 0xc) /* User IO reg */ REG32(DMACFG, 0x10) /* DMA Control reg */ @@ -236,17 +265,6 @@ REG32(TYPE2_COMPARE_0_WORD_1, 0x704) FIELD(TYPE2_COMPARE_0_WORD_1, COMPARE_VLAN_ID, 10, 1) /*****************************************/ -#define GEM_NWCFG_STRIP_FCS 0x00020000 /* Strip FCS field */ -#define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with len err */ -#define GEM_NWCFG_BUFF_OFST_M 0x0000C000 /* Receive buffer offset mask */ -#define GEM_NWCFG_BUFF_OFST_S 14 /* Receive buffer offset shift */ -#define GEM_NWCFG_RCV_1538 0x00000100 /* Receive 1538 bytes frame */ -#define GEM_NWCFG_UCAST_HASH 0x00000080 /* accept unicast if hash match */ -#define GEM_NWCFG_MCAST_HASH 0x00000040 /* accept multicast if hash match */ -#define GEM_NWCFG_BCAST_REJ 0x00000020 /* Reject broadcast packets */ -#define GEM_NWCFG_PROMISC 0x00000010 /* Accept all packets */ -#define GEM_NWCFG_JUMBO_FRAME 0x00000008 /* Jumbo Frames enable */ - #define GEM_DMACFG_ADDR_64B (1U << 30) #define GEM_DMACFG_TX_BD_EXT (1U << 29) #define GEM_DMACFG_RX_BD_EXT (1U << 28) @@ -482,7 +500,7 @@ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static uint32_t gem_get_max_buf_len(CadenceGEMState *s, bool tx) { uint32_t size; - if (s->regs[R_NWCFG] & GEM_NWCFG_JUMBO_FRAME) { + if (FIELD_EX32(s->regs[R_NWCFG], NWCFG, JUMBO_FRAMES)) { size = s->regs[R_JUMBO_MAX_LEN]; if (size > s->jumbo_max_len) { size = s->jumbo_max_len; @@ -492,7 +510,8 @@ static uint32_t gem_get_max_buf_len(CadenceGEMState *s, bool tx) } else if (tx) { size = 1518; } else { - size = s->regs[R_NWCFG] & GEM_NWCFG_RCV_1538 ? 1538 : 1518; + size = FIELD_EX32(s->regs[R_NWCFG], + NWCFG, RECV_1536_BYTE_FRAMES) ? 1538 : 1518; } return size; } @@ -732,13 +751,13 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet) int i, is_mc; /* Promiscuous mode? */ - if (s->regs[R_NWCFG] & GEM_NWCFG_PROMISC) { + if (FIELD_EX32(s->regs[R_NWCFG], NWCFG, PROMISC)) { return GEM_RX_PROMISCUOUS_ACCEPT; } if (!memcmp(packet, broadcast_addr, 6)) { /* Reject broadcast packets? */ - if (s->regs[R_NWCFG] & GEM_NWCFG_BCAST_REJ) { + if (FIELD_EX32(s->regs[R_NWCFG], NWCFG, NO_BROADCAST)) { return GEM_RX_REJECT; } return GEM_RX_BROADCAST_ACCEPT; @@ -746,8 +765,8 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet) /* Accept packets -w- hash match? */ is_mc = is_multicast_ether_addr(packet); - if ((is_mc && (s->regs[R_NWCFG] & GEM_NWCFG_MCAST_HASH)) || - (!is_mc && (s->regs[R_NWCFG] & GEM_NWCFG_UCAST_HASH))) { + if ((is_mc && (FIELD_EX32(s->regs[R_NWCFG], NWCFG, MULTICAST_HASH_EN))) || + (!is_mc && FIELD_EX32(s->regs[R_NWCFG], NWCFG, UNICAST_HASH_EN))) { uint64_t buckets; unsigned hash_index; @@ -983,7 +1002,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) } /* Discard packets with receive length error enabled ? */ - if (s->regs[R_NWCFG] & GEM_NWCFG_LERR_DISC) { + if (FIELD_EX32(s->regs[R_NWCFG], NWCFG, LEN_ERR_DISCARD)) { unsigned type_len; /* Fish the ethertype / length field out of the RX packet */ @@ -1000,8 +1019,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) /* * Determine configured receive buffer offset (probably 0) */ - rxbuf_offset = (s->regs[R_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >> - GEM_NWCFG_BUFF_OFST_S; + rxbuf_offset = FIELD_EX32(s->regs[R_NWCFG], NWCFG, RECV_BUF_OFFSET); /* The configure size of each receive buffer. Determines how many * buffers needed to hold this packet. @@ -1026,7 +1044,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) } /* Strip of FCS field ? (usually yes) */ - if (s->regs[R_NWCFG] & GEM_NWCFG_STRIP_FCS) { + if (FIELD_EX32(s->regs[R_NWCFG], NWCFG, FCS_REMOVE)) { rxbuf_ptr = (void *)buf; } else { unsigned crc_val; From 01f9175dbc0f85cd89ddeb5dd515580082a20af8 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:16 +0200 Subject: [PATCH 35/41] hw/net/cadence_gem: use FIELD to describe DMACFG register fields Use de FIELD macro to describe the DMACFG register fields. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-6-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 48 ++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index cf8b1261ed..e3724b8447 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -110,7 +110,27 @@ REG32(NWCFG, 0x4) /* Network Config reg */ REG32(NWSTATUS, 0x8) /* Network Status reg */ REG32(USERIO, 0xc) /* User IO reg */ + REG32(DMACFG, 0x10) /* DMA Control reg */ + FIELD(DMACFG, SEND_BCAST_TO_ALL_QS, 31, 1) + FIELD(DMACFG, DMA_ADDR_BUS_WIDTH, 30, 1) + FIELD(DMACFG, TX_BD_EXT_MODE_EN , 29, 1) + FIELD(DMACFG, RX_BD_EXT_MODE_EN , 28, 1) + FIELD(DMACFG, FORCE_MAX_AMBA_BURST_TX, 26, 1) + FIELD(DMACFG, FORCE_MAX_AMBA_BURST_RX, 25, 1) + FIELD(DMACFG, FORCE_DISCARD_ON_ERR, 24, 1) + FIELD(DMACFG, RX_BUF_SIZE, 16, 8) + FIELD(DMACFG, CRC_ERROR_REPORT, 13, 1) + FIELD(DMACFG, INF_LAST_DBUF_SIZE_EN, 12, 1) + FIELD(DMACFG, TX_PBUF_CSUM_OFFLOAD, 11, 1) + FIELD(DMACFG, TX_PBUF_SIZE, 10, 1) + FIELD(DMACFG, RX_PBUF_SIZE, 8, 2) + FIELD(DMACFG, ENDIAN_SWAP_PACKET, 7, 1) + FIELD(DMACFG, ENDIAN_SWAP_MGNT, 6, 1) + FIELD(DMACFG, HDR_DATA_SPLIT_EN, 5, 1) + FIELD(DMACFG, AMBA_BURST_LEN , 0, 5) +#define GEM_DMACFG_RBUFSZ_MUL 64 /* DMA RX Buffer Size multiplier */ + REG32(TXSTATUS, 0x14) /* TX Status reg */ REG32(RXQBASE, 0x18) /* RX Q Base address reg */ REG32(TXQBASE, 0x1c) /* TX Q Base address reg */ @@ -265,13 +285,6 @@ REG32(TYPE2_COMPARE_0_WORD_1, 0x704) FIELD(TYPE2_COMPARE_0_WORD_1, COMPARE_VLAN_ID, 10, 1) /*****************************************/ -#define GEM_DMACFG_ADDR_64B (1U << 30) -#define GEM_DMACFG_TX_BD_EXT (1U << 29) -#define GEM_DMACFG_RX_BD_EXT (1U << 28) -#define GEM_DMACFG_RBUFSZ_M 0x00FF0000 /* DMA RX Buffer Size mask */ -#define GEM_DMACFG_RBUFSZ_S 16 /* DMA RX Buffer Size shift */ -#define GEM_DMACFG_RBUFSZ_MUL 64 /* DMA RX Buffer Size multiplier */ -#define GEM_DMACFG_TXCSUM_OFFL 0x00000800 /* Transmit checksum offload */ #define GEM_TXSTATUS_TXCMPL 0x00000020 /* Transmit Complete */ #define GEM_TXSTATUS_USED 0x00000001 /* sw owned descriptor encountered */ @@ -369,7 +382,7 @@ static inline uint64_t tx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc) { uint64_t ret = desc[0]; - if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { + if (FIELD_EX32(s->regs[R_DMACFG], DMACFG, DMA_ADDR_BUS_WIDTH)) { ret |= (uint64_t)desc[2] << 32; } return ret; @@ -414,7 +427,7 @@ static inline uint64_t rx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc) { uint64_t ret = desc[0] & ~0x3UL; - if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { + if (FIELD_EX32(s->regs[R_DMACFG], DMACFG, DMA_ADDR_BUS_WIDTH)) { ret |= (uint64_t)desc[2] << 32; } return ret; @@ -424,11 +437,11 @@ static inline int gem_get_desc_len(CadenceGEMState *s, bool rx_n_tx) { int ret = 2; - if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { + if (FIELD_EX32(s->regs[R_DMACFG], DMACFG, DMA_ADDR_BUS_WIDTH)) { ret += 2; } - if (s->regs[R_DMACFG] & (rx_n_tx ? GEM_DMACFG_RX_BD_EXT - : GEM_DMACFG_TX_BD_EXT)) { + if (s->regs[R_DMACFG] & (rx_n_tx ? R_DMACFG_RX_BD_EXT_MODE_EN_MASK + : R_DMACFG_TX_BD_EXT_MODE_EN_MASK)) { ret += 2; } @@ -942,7 +955,7 @@ static hwaddr gem_get_desc_addr(CadenceGEMState *s, bool tx, int q) { hwaddr desc_addr = 0; - if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { + if (FIELD_EX32(s->regs[R_DMACFG], DMACFG, DMA_ADDR_BUS_WIDTH)) { desc_addr = s->regs[tx ? R_TBQPH : R_RBQPH]; } desc_addr <<= 32; @@ -1024,8 +1037,9 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) /* The configure size of each receive buffer. Determines how many * buffers needed to hold this packet. */ - rxbufsize = ((s->regs[R_DMACFG] & GEM_DMACFG_RBUFSZ_M) >> - GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL; + rxbufsize = FIELD_EX32(s->regs[R_DMACFG], DMACFG, RX_BUF_SIZE); + rxbufsize *= GEM_DMACFG_RBUFSZ_MUL; + bytes_to_copy = size; /* Hardware allows a zero value here but warns against it. To avoid QEMU @@ -1308,7 +1322,7 @@ static void gem_transmit(CadenceGEMState *s) gem_update_int_status(s); /* Is checksum offload enabled? */ - if (s->regs[R_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) { + if (FIELD_EX32(s->regs[R_DMACFG], DMACFG, TX_PBUF_CSUM_OFFLOAD)) { net_checksum_calculate(s->tx_packet, total_bytes, CSUM_ALL); } @@ -1332,7 +1346,7 @@ static void gem_transmit(CadenceGEMState *s) /* read next descriptor */ if (tx_desc_get_wrap(desc)) { - if (s->regs[R_DMACFG] & GEM_DMACFG_ADDR_64B) { + if (FIELD_EX32(s->regs[R_DMACFG], DMACFG, DMA_ADDR_BUS_WIDTH)) { packet_desc_addr = s->regs[R_TBQPH]; packet_desc_addr <<= 32; } else { From 466da857160aa060c4e4abb8d0d885eaae4e4bf9 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:17 +0200 Subject: [PATCH 36/41] hw/net/cadence_gem: use FIELD to describe [TX|RX]STATUS register fields Use de FIELD macro to describe the TXSTATUS and RXSTATUS register fields. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-7-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index e3724b8447..d7fdc77514 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -132,9 +132,30 @@ REG32(DMACFG, 0x10) /* DMA Control reg */ #define GEM_DMACFG_RBUFSZ_MUL 64 /* DMA RX Buffer Size multiplier */ REG32(TXSTATUS, 0x14) /* TX Status reg */ + FIELD(TXSTATUS, TX_USED_BIT_READ_MIDFRAME, 12, 1) + FIELD(TXSTATUS, TX_FRAME_TOO_LARGE, 11, 1) + FIELD(TXSTATUS, TX_DMA_LOCKUP, 10, 1) + FIELD(TXSTATUS, TX_MAC_LOCKUP, 9, 1) + FIELD(TXSTATUS, RESP_NOT_OK, 8, 1) + FIELD(TXSTATUS, LATE_COLLISION, 7, 1) + FIELD(TXSTATUS, TRANSMIT_UNDER_RUN, 6, 1) + FIELD(TXSTATUS, TRANSMIT_COMPLETE, 5, 1) + FIELD(TXSTATUS, AMBA_ERROR, 4, 1) + FIELD(TXSTATUS, TRANSMIT_GO, 3, 1) + FIELD(TXSTATUS, RETRY_LIMIT, 2, 1) + FIELD(TXSTATUS, COLLISION, 1, 1) + FIELD(TXSTATUS, USED_BIT_READ, 0, 1) + REG32(RXQBASE, 0x18) /* RX Q Base address reg */ REG32(TXQBASE, 0x1c) /* TX Q Base address reg */ REG32(RXSTATUS, 0x20) /* RX Status reg */ + FIELD(RXSTATUS, RX_DMA_LOCKUP, 5, 1) + FIELD(RXSTATUS, RX_MAC_LOCKUP, 4, 1) + FIELD(RXSTATUS, RESP_NOT_OK, 3, 1) + FIELD(RXSTATUS, RECEIVE_OVERRUN, 2, 1) + FIELD(RXSTATUS, FRAME_RECEIVED, 1, 1) + FIELD(RXSTATUS, BUF_NOT_AVAILABLE, 0, 1) + REG32(ISR, 0x24) /* Interrupt Status reg */ REG32(IER, 0x28) /* Interrupt Enable reg */ REG32(IDR, 0x2c) /* Interrupt Disable reg */ @@ -286,11 +307,6 @@ REG32(TYPE2_COMPARE_0_WORD_1, 0x704) /*****************************************/ -#define GEM_TXSTATUS_TXCMPL 0x00000020 /* Transmit Complete */ -#define GEM_TXSTATUS_USED 0x00000001 /* sw owned descriptor encountered */ - -#define GEM_RXSTATUS_FRMRCVD 0x00000002 /* Frame received */ -#define GEM_RXSTATUS_NOBUF 0x00000001 /* Buffer unavailable */ /* GEM_ISR GEM_IER GEM_IDR GEM_IMR */ #define GEM_INT_TXCMPL 0x00000080 /* Transmit Complete */ @@ -987,7 +1003,7 @@ static void gem_get_rx_desc(CadenceGEMState *s, int q) /* Descriptor owned by software ? */ if (rx_desc_get_ownership(s->rx_desc[q]) == 1) { DB_PRINT("descriptor 0x%" HWADDR_PRIx " owned by sw.\n", desc_addr); - s->regs[R_RXSTATUS] |= GEM_RXSTATUS_NOBUF; + s->regs[R_RXSTATUS] |= R_RXSTATUS_BUF_NOT_AVAILABLE_MASK; gem_set_isr(s, q, GEM_INT_RXUSED); /* Handle interrupt consequences */ gem_update_int_status(s); @@ -1164,7 +1180,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) /* Count it */ gem_receive_updatestats(s, buf, size); - s->regs[R_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD; + s->regs[R_RXSTATUS] |= R_RXSTATUS_FRAME_RECEIVED_MASK; gem_set_isr(s, q, GEM_INT_RXCMPL); /* Handle interrupt consequences */ @@ -1315,7 +1331,7 @@ static void gem_transmit(CadenceGEMState *s) } DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]); - s->regs[R_TXSTATUS] |= GEM_TXSTATUS_TXCMPL; + s->regs[R_TXSTATUS] |= R_TXSTATUS_TRANSMIT_COMPLETE_MASK; gem_set_isr(s, q, GEM_INT_TXCMPL); /* Handle interrupt consequences */ @@ -1363,7 +1379,7 @@ static void gem_transmit(CadenceGEMState *s) } if (tx_desc_get_used(desc)) { - s->regs[R_TXSTATUS] |= GEM_TXSTATUS_USED; + s->regs[R_TXSTATUS] |= R_TXSTATUS_USED_BIT_READ_MASK; /* IRQ TXUSED is defined only for queue 0 */ if (q == 0) { gem_set_isr(s, 0, GEM_INT_TXUSED); From 987e80601724207ffb747d6a12d718d3829b9c7b Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:18 +0200 Subject: [PATCH 37/41] hw/net/cadence_gem: use FIELD to describe IRQ register fields Use de FIELD macro to describe the IRQ related register fields. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-8-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 51 +++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index d7fdc77514..7e6cab7107 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -157,9 +157,42 @@ REG32(RXSTATUS, 0x20) /* RX Status reg */ FIELD(RXSTATUS, BUF_NOT_AVAILABLE, 0, 1) REG32(ISR, 0x24) /* Interrupt Status reg */ + FIELD(ISR, TX_LOCKUP, 31, 1) + FIELD(ISR, RX_LOCKUP, 30, 1) + FIELD(ISR, TSU_TIMER, 29, 1) + FIELD(ISR, WOL, 28, 1) + FIELD(ISR, RECV_LPI, 27, 1) + FIELD(ISR, TSU_SEC_INCR, 26, 1) + FIELD(ISR, PTP_PDELAY_RESP_XMIT, 25, 1) + FIELD(ISR, PTP_PDELAY_REQ_XMIT, 24, 1) + FIELD(ISR, PTP_PDELAY_RESP_RECV, 23, 1) + FIELD(ISR, PTP_PDELAY_REQ_RECV, 22, 1) + FIELD(ISR, PTP_SYNC_XMIT, 21, 1) + FIELD(ISR, PTP_DELAY_REQ_XMIT, 20, 1) + FIELD(ISR, PTP_SYNC_RECV, 19, 1) + FIELD(ISR, PTP_DELAY_REQ_RECV, 18, 1) + FIELD(ISR, PCS_LP_PAGE_RECV, 17, 1) + FIELD(ISR, PCS_AN_COMPLETE, 16, 1) + FIELD(ISR, EXT_IRQ, 15, 1) + FIELD(ISR, PAUSE_FRAME_XMIT, 14, 1) + FIELD(ISR, PAUSE_TIME_ELAPSED, 13, 1) + FIELD(ISR, PAUSE_FRAME_RECV, 12, 1) + FIELD(ISR, RESP_NOT_OK, 11, 1) + FIELD(ISR, RECV_OVERRUN, 10, 1) + FIELD(ISR, LINK_CHANGE, 9, 1) + FIELD(ISR, USXGMII_INT, 8, 1) + FIELD(ISR, XMIT_COMPLETE, 7, 1) + FIELD(ISR, AMBA_ERROR, 6, 1) + FIELD(ISR, RETRY_EXCEEDED, 5, 1) + FIELD(ISR, XMIT_UNDER_RUN, 4, 1) + FIELD(ISR, TX_USED, 3, 1) + FIELD(ISR, RX_USED, 2, 1) + FIELD(ISR, RECV_COMPLETE, 1, 1) + FIELD(ISR, MGNT_FRAME_SENT, 0, 1) REG32(IER, 0x28) /* Interrupt Enable reg */ REG32(IDR, 0x2c) /* Interrupt Disable reg */ REG32(IMR, 0x30) /* Interrupt Mask reg */ + REG32(PHYMNTNC, 0x34) /* Phy Maintenance reg */ REG32(RXPAUSE, 0x38) /* RX Pause Time reg */ REG32(TXPAUSE, 0x3c) /* TX Pause Time reg */ @@ -308,12 +341,6 @@ REG32(TYPE2_COMPARE_0_WORD_1, 0x704) /*****************************************/ -/* GEM_ISR GEM_IER GEM_IDR GEM_IMR */ -#define GEM_INT_TXCMPL 0x00000080 /* Transmit Complete */ -#define GEM_INT_AMBA_ERR 0x00000040 -#define GEM_INT_TXUSED 0x00000008 -#define GEM_INT_RXUSED 0x00000004 -#define GEM_INT_RXCMPL 0x00000002 #define GEM_PHYMNTNC_OP_R 0x20000000 /* read operation */ #define GEM_PHYMNTNC_OP_W 0x10000000 /* write operation */ @@ -1004,7 +1031,7 @@ static void gem_get_rx_desc(CadenceGEMState *s, int q) if (rx_desc_get_ownership(s->rx_desc[q]) == 1) { DB_PRINT("descriptor 0x%" HWADDR_PRIx " owned by sw.\n", desc_addr); s->regs[R_RXSTATUS] |= R_RXSTATUS_BUF_NOT_AVAILABLE_MASK; - gem_set_isr(s, q, GEM_INT_RXUSED); + gem_set_isr(s, q, R_ISR_RX_USED_MASK); /* Handle interrupt consequences */ gem_update_int_status(s); } @@ -1104,7 +1131,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) if (size > gem_get_max_buf_len(s, false)) { qemu_log_mask(LOG_GUEST_ERROR, "rx frame too long\n"); - gem_set_isr(s, q, GEM_INT_AMBA_ERR); + gem_set_isr(s, q, R_ISR_AMBA_ERROR_MASK); return -1; } @@ -1181,7 +1208,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) gem_receive_updatestats(s, buf, size); s->regs[R_RXSTATUS] |= R_RXSTATUS_FRAME_RECEIVED_MASK; - gem_set_isr(s, q, GEM_INT_RXCMPL); + gem_set_isr(s, q, R_ISR_RECV_COMPLETE_MASK); /* Handle interrupt consequences */ gem_update_int_status(s); @@ -1294,7 +1321,7 @@ static void gem_transmit(CadenceGEMState *s) HWADDR_PRIx " too large: size 0x%x space 0x%zx\n", packet_desc_addr, tx_desc_get_length(desc), gem_get_max_buf_len(s, true) - (p - s->tx_packet)); - gem_set_isr(s, q, GEM_INT_AMBA_ERR); + gem_set_isr(s, q, R_ISR_AMBA_ERROR_MASK); break; } @@ -1332,7 +1359,7 @@ static void gem_transmit(CadenceGEMState *s) DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]); s->regs[R_TXSTATUS] |= R_TXSTATUS_TRANSMIT_COMPLETE_MASK; - gem_set_isr(s, q, GEM_INT_TXCMPL); + gem_set_isr(s, q, R_ISR_XMIT_COMPLETE_MASK); /* Handle interrupt consequences */ gem_update_int_status(s); @@ -1382,7 +1409,7 @@ static void gem_transmit(CadenceGEMState *s) s->regs[R_TXSTATUS] |= R_TXSTATUS_USED_BIT_READ_MASK; /* IRQ TXUSED is defined only for queue 0 */ if (q == 0) { - gem_set_isr(s, 0, GEM_INT_TXUSED); + gem_set_isr(s, 0, R_ISR_TX_USED_MASK); } gem_update_int_status(s); } From ce077875da2493787985d4a747bacc924b279081 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:19 +0200 Subject: [PATCH 38/41] hw/net/cadence_gem: use FIELD to describe DESCONF6 register fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the FIELD macro to describe the DESCONF6 register fields. Signed-off-by: Luc Michel Reviewed-by: Philippe Mathieu-Daudé Message-id: 20231017194422.4124691-9-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 7e6cab7107..dffcc64df2 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -283,7 +283,7 @@ REG32(DESCONF3, 0x288) REG32(DESCONF4, 0x28c) REG32(DESCONF5, 0x290) REG32(DESCONF6, 0x294) -#define GEM_DESCONF6_64B_MASK (1U << 23) + FIELD(DESCONF6, DMA_ADDR_64B, 23, 1) REG32(DESCONF7, 0x298) REG32(INT_Q1_STATUS, 0x400) @@ -1463,7 +1463,7 @@ static void gem_reset(DeviceState *d) s->regs[R_DESCONF] = 0x02D00111; s->regs[R_DESCONF2] = 0x2ab10000 | s->jumbo_max_len; s->regs[R_DESCONF5] = 0x002f2045; - s->regs[R_DESCONF6] = GEM_DESCONF6_64B_MASK; + s->regs[R_DESCONF6] = R_DESCONF6_DMA_ADDR_64B_MASK; s->regs[R_INT_Q1_MASK] = 0x00000CE6; s->regs[R_JUMBO_MAX_LEN] = s->jumbo_max_len; From 1b09eeb122aaf1666a9c5aa789eb219443772685 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:20 +0200 Subject: [PATCH 39/41] hw/net/cadence_gem: use FIELD to describe PHYMNTNC register fields Use the FIELD macro to describe the PHYMNTNC register fields. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-10-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index dffcc64df2..373d3ee071 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -194,6 +194,14 @@ REG32(IDR, 0x2c) /* Interrupt Disable reg */ REG32(IMR, 0x30) /* Interrupt Mask reg */ REG32(PHYMNTNC, 0x34) /* Phy Maintenance reg */ + FIELD(PHYMNTNC, DATA, 0, 16) + FIELD(PHYMNTNC, REG_ADDR, 18, 5) + FIELD(PHYMNTNC, PHY_ADDR, 23, 5) + FIELD(PHYMNTNC, OP, 28, 2) + FIELD(PHYMNTNC, ST, 30, 2) +#define MDIO_OP_READ 0x3 +#define MDIO_OP_WRITE 0x2 + REG32(RXPAUSE, 0x38) /* RX Pause Time reg */ REG32(TXPAUSE, 0x3c) /* TX Pause Time reg */ REG32(TXPARTIALSF, 0x40) /* TX Partial Store and Forward */ @@ -342,13 +350,6 @@ REG32(TYPE2_COMPARE_0_WORD_1, 0x704) -#define GEM_PHYMNTNC_OP_R 0x20000000 /* read operation */ -#define GEM_PHYMNTNC_OP_W 0x10000000 /* write operation */ -#define GEM_PHYMNTNC_ADDR 0x0F800000 /* Address bits */ -#define GEM_PHYMNTNC_ADDR_SHFT 23 -#define GEM_PHYMNTNC_REG 0x007C0000 /* register bits */ -#define GEM_PHYMNTNC_REG_SHIFT 18 - /* Marvell PHY definitions */ #define BOARD_PHY_ADDRESS 0 /* PHY address we will emulate a device at */ @@ -1541,12 +1542,12 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) /* The interrupts get updated at the end of the function. */ break; case R_PHYMNTNC: - if (retval & GEM_PHYMNTNC_OP_R) { + if (FIELD_EX32(retval, PHYMNTNC, OP) == MDIO_OP_READ) { uint32_t phy_addr, reg_num; - phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT; + phy_addr = FIELD_EX32(retval, PHYMNTNC, PHY_ADDR); if (phy_addr == s->phy_addr) { - reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT; + reg_num = FIELD_EX32(retval, PHYMNTNC, REG_ADDR); retval &= 0xFFFF0000; retval |= gem_phy_read(s, reg_num); } else { @@ -1664,12 +1665,12 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, s->sar_active[(offset - R_SPADDR1HI) / 2] = true; break; case R_PHYMNTNC: - if (val & GEM_PHYMNTNC_OP_W) { + if (FIELD_EX32(val, PHYMNTNC, OP) == MDIO_OP_WRITE) { uint32_t phy_addr, reg_num; - phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT; + phy_addr = FIELD_EX32(val, PHYMNTNC, PHY_ADDR); if (phy_addr == s->phy_addr) { - reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT; + reg_num = FIELD_EX32(val, PHYMNTNC, REG_ADDR); gem_phy_write(s, reg_num, val); } } From 71a082a3fa9845360224c66029eea8d972b8b8bd Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:21 +0200 Subject: [PATCH 40/41] hw/net/cadence_gem: perform PHY access on write only The MDIO access is done only on a write to the PHYMNTNC register. A subsequent read is used to retrieve the result but does not trigger an MDIO access by itself. Refactor the PHY access logic to perform all accesses (MDIO reads and writes) at PHYMNTNC write time. Signed-off-by: Luc Michel Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-11-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 56 ++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 373d3ee071..06a101bfcd 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1521,6 +1521,38 @@ static void gem_phy_write(CadenceGEMState *s, unsigned reg_num, uint16_t val) s->phy_regs[reg_num] = val; } +static void gem_handle_phy_access(CadenceGEMState *s) +{ + uint32_t val = s->regs[R_PHYMNTNC]; + uint32_t phy_addr, reg_num; + + phy_addr = FIELD_EX32(val, PHYMNTNC, PHY_ADDR); + + if (phy_addr != s->phy_addr) { + /* no phy at this address */ + if (FIELD_EX32(val, PHYMNTNC, OP) == MDIO_OP_READ) { + s->regs[R_PHYMNTNC] = FIELD_DP32(val, PHYMNTNC, DATA, 0xffff); + } + return; + } + + reg_num = FIELD_EX32(val, PHYMNTNC, REG_ADDR); + + switch (FIELD_EX32(val, PHYMNTNC, OP)) { + case MDIO_OP_READ: + s->regs[R_PHYMNTNC] = FIELD_DP32(val, PHYMNTNC, DATA, + gem_phy_read(s, reg_num)); + break; + + case MDIO_OP_WRITE: + gem_phy_write(s, reg_num, val); + break; + + default: + break; /* only clause 22 operations are supported */ + } +} + /* * gem_read32: * Read a GEM register. @@ -1541,20 +1573,6 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) DB_PRINT("lowering irqs on ISR read\n"); /* The interrupts get updated at the end of the function. */ break; - case R_PHYMNTNC: - if (FIELD_EX32(retval, PHYMNTNC, OP) == MDIO_OP_READ) { - uint32_t phy_addr, reg_num; - - phy_addr = FIELD_EX32(retval, PHYMNTNC, PHY_ADDR); - if (phy_addr == s->phy_addr) { - reg_num = FIELD_EX32(retval, PHYMNTNC, REG_ADDR); - retval &= 0xFFFF0000; - retval |= gem_phy_read(s, reg_num); - } else { - retval |= 0xFFFF; /* No device at this address */ - } - } - break; } /* Squash read to clear bits */ @@ -1665,15 +1683,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, s->sar_active[(offset - R_SPADDR1HI) / 2] = true; break; case R_PHYMNTNC: - if (FIELD_EX32(val, PHYMNTNC, OP) == MDIO_OP_WRITE) { - uint32_t phy_addr, reg_num; - - phy_addr = FIELD_EX32(val, PHYMNTNC, PHY_ADDR); - if (phy_addr == s->phy_addr) { - reg_num = FIELD_EX32(val, PHYMNTNC, REG_ADDR); - gem_phy_write(s, reg_num, val); - } - } + gem_handle_phy_access(s); break; } From df93de987f423a0ed918c425f5dbd9a25d3c6229 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 17 Oct 2023 21:44:22 +0200 Subject: [PATCH 41/41] hw/net/cadence_gem: enforce 32 bits variable size for CRC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CRC was stored in an unsigned variable in gem_receive. Change it for a uint32_t to ensure we have the correct variable size here. Signed-off-by: Luc Michel Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: sai.pavan.boddu@amd.com Message-id: 20231017194422.4124691-12-luc.michel@amd.com Signed-off-by: Peter Maydell --- hw/net/cadence_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 06a101bfcd..5b989f5b52 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1105,7 +1105,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) if (FIELD_EX32(s->regs[R_NWCFG], NWCFG, FCS_REMOVE)) { rxbuf_ptr = (void *)buf; } else { - unsigned crc_val; + uint32_t crc_val; if (size > MAX_FRAME_SIZE - sizeof(crc_val)) { size = MAX_FRAME_SIZE - sizeof(crc_val);