| 1 | /* |
| 2 | * QEMU ARM 'max' CPU |
| 3 | * |
| 4 | * Copyright (c) 2018 Linaro Ltd |
| 5 | * |
| 6 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 7 | */ |
| 8 | |
| 9 | #include "qemu/osdep.h" |
| 10 | #include "qemu/units.h" |
| 11 | #include "qemu/target-info.h" |
| 12 | #include "system/hw_accel.h" |
| 13 | #include "system/kvm.h" |
| 14 | #include "system/qtest.h" |
| 15 | #include "system/tcg.h" |
| 16 | #include "target/arm/internals.h" |
| 17 | #include "target/arm/cpregs.h" |
| 18 | |
| 19 | void aarch64_aa32_a57_init(ARMCPU *cpu, bool aarch64_enabled) |
| 20 | { |
| 21 | ARMISARegisters *isar = &cpu->isar; |
| 22 | |
| 23 | cpu->dtb_compatible = "arm,cortex-a57"; |
| 24 | set_feature(&cpu->env, ARM_FEATURE_V8); |
| 25 | set_feature(&cpu->env, ARM_FEATURE_NEON); |
| 26 | set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS); |
| 27 | set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); |
| 28 | set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ); |
| 29 | if (aarch64_enabled) { |
| 30 | set_feature(&cpu->env, ARM_FEATURE_AARCH64); |
| 31 | } |
| 32 | set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); |
| 33 | set_feature(&cpu->env, ARM_FEATURE_EL2); |
| 34 | set_feature(&cpu->env, ARM_FEATURE_EL3); |
| 35 | set_feature(&cpu->env, ARM_FEATURE_PMU); |
| 36 | if (kvm_enabled()) { |
| 37 | cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57; |
| 38 | } |
| 39 | cpu->midr = 0x411fd070; |
| 40 | cpu->revidr = 0x00000000; |
| 41 | cpu->reset_fpsid = 0x41034070; |
| 42 | cpu->isar.mvfr0 = 0x10110222; |
| 43 | cpu->isar.mvfr1 = 0x12111111; |
| 44 | cpu->isar.mvfr2 = 0x00000043; |
| 45 | cpu->ctr = 0x8444c004; |
| 46 | cpu->reset_sctlr = 0x00c50838; |
| 47 | SET_IDREG(isar, ID_PFR0, 0x00000131); |
| 48 | SET_IDREG(isar, ID_PFR1, 0x00011011); |
| 49 | SET_IDREG(isar, ID_DFR0, 0x03010066); |
| 50 | SET_IDREG(isar, ID_AFR0, 0x00000000); |
| 51 | SET_IDREG(isar, ID_MMFR0, 0x10101105); |
| 52 | SET_IDREG(isar, ID_MMFR1, 0x40000000); |
| 53 | SET_IDREG(isar, ID_MMFR2, 0x01260000); |
| 54 | SET_IDREG(isar, ID_MMFR3, 0x02102211); |
| 55 | SET_IDREG(isar, ID_ISAR0, 0x02101110); |
| 56 | SET_IDREG(isar, ID_ISAR1, 0x13112111); |
| 57 | SET_IDREG(isar, ID_ISAR2, 0x21232042); |
| 58 | SET_IDREG(isar, ID_ISAR3, 0x01112131); |
| 59 | SET_IDREG(isar, ID_ISAR4, 0x00011142); |
| 60 | SET_IDREG(isar, ID_ISAR5, 0x00011121); |
| 61 | SET_IDREG(isar, ID_ISAR6, 0); |
| 62 | if (aarch64_enabled) { |
| 63 | SET_IDREG(isar, ID_AA64PFR0, 0x00002222); |
| 64 | SET_IDREG(isar, ID_AA64DFR0, 0x10305106); |
| 65 | SET_IDREG(isar, ID_AA64ISAR0, 0x00011120); |
| 66 | SET_IDREG(isar, ID_AA64MMFR0, 0x00001124); |
| 67 | } |
| 68 | cpu->isar.dbgdidr = 0x3516d000; |
| 69 | cpu->isar.dbgdevid = 0x01110f13; |
| 70 | cpu->isar.dbgdevid1 = 0x2; |
| 71 | cpu->isar.reset_pmcr_el0 = 0x41013000; |
| 72 | SET_IDREG(isar, CLIDR, 0x0a200023); |
| 73 | /* 32KB L1 dcache */ |
| 74 | cpu->ccsidr[0] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 4, 64, 32 * KiB, 7); |
| 75 | /* 48KB L1 icache */ |
| 76 | cpu->ccsidr[1] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 3, 64, 48 * KiB, 2); |
| 77 | /* 2048KB L2 cache */ |
| 78 | cpu->ccsidr[2] = make_ccsidr(CCSIDR_FORMAT_LEGACY, 16, 64, 2 * MiB, 7); |
| 79 | if (aarch64_enabled) { |
| 80 | set_dczid_bs(cpu, 4); /* 64 bytes */ |
| 81 | cpu->gic_num_lrs = 4; |
| 82 | cpu->gic_vpribits = 5; |
| 83 | cpu->gic_vprebits = 5; |
| 84 | cpu->gic_pribits = 5; |
| 85 | } |
| 86 | define_cortex_a72_a57_a53_cp_reginfo(cpu); |
| 87 | } |
| 88 | |
| 89 | /* |
| 90 | * -cpu max: a CPU with as many features enabled as our emulation supports. |
| 91 | * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c; |
| 92 | * this only needs to handle 32 bits, and need not care about KVM. |
| 93 | */ |
| 94 | static void cpu_max_initfn(Object *obj) |
| 95 | { |
| 96 | ARMCPU *cpu = ARM_CPU(obj); |
| 97 | const bool aarch64_enabled = target_aarch64(); |
| 98 | |
| 99 | if (hwaccel_enabled()) { |
| 100 | assert(aarch64_enabled); |
| 101 | /* |
| 102 | * When hardware acceleration enabled, '-cpu max' is |
| 103 | * identical to '-cpu host' |
| 104 | */ |
| 105 | aarch64_host_initfn(obj); |
| 106 | return; |
| 107 | } |
| 108 | |
| 109 | if (tcg_enabled()) { |
| 110 | if (!aarch64_enabled) { |
| 111 | aarch32_max_v8_tcg_initfn(obj); |
| 112 | } else { |
| 113 | aarch64_max_v9_tcg_initfn(obj); |
| 114 | } |
| 115 | return; |
| 116 | } |
| 117 | |
| 118 | /* Ultimate fallback: -cpu max as cortex-a57. */ |
| 119 | assert(qtest_enabled()); |
| 120 | aarch64_aa32_a57_init(cpu, aarch64_enabled); |
| 121 | } |
| 122 | |
| 123 | static const ARMCPUInfo arm_max_cpu = { |
| 124 | .name = "max", |
| 125 | .initfn = cpu_max_initfn, |
| 126 | }; |
| 127 | |
| 128 | static void arm_max_cpu_register_types(void) |
| 129 | { |
| 130 | arm_cpu_register(&arm_max_cpu); |
| 131 | } |
| 132 | |
| 133 | type_init(arm_max_cpu_register_types) |