helper.c (910e4f24975f53645d308aa6c895f4599dd47c43) helper.c (761c46425e2d2a7a65cbbd1ee65f0abce769618c)
1/*
2 * ARM generic helpers.
3 *
4 * This code is licensed under the GNU GPL v2 or later.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8

--- 3668 unchanged lines hidden (view full) ---

3677 "PMSAv7 RGNR write >= # supported regions, %" PRIu32
3678 " > %" PRIu32 "\n", (uint32_t)value, nrgs);
3679 return;
3680 }
3681
3682 raw_write(env, ri, value);
3683}
3684
1/*
2 * ARM generic helpers.
3 *
4 * This code is licensed under the GNU GPL v2 or later.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8

--- 3668 unchanged lines hidden (view full) ---

3677 "PMSAv7 RGNR write >= # supported regions, %" PRIu32
3678 " > %" PRIu32 "\n", (uint32_t)value, nrgs);
3679 return;
3680 }
3681
3682 raw_write(env, ri, value);
3683}
3684
3685static void prbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
3686 uint64_t value)
3687{
3688 ARMCPU *cpu = env_archcpu(env);
3689
3690 tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
3691 env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] = value;
3692}
3693
3694static uint64_t prbar_read(CPUARMState *env, const ARMCPRegInfo *ri)
3695{
3696 return env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]];
3697}
3698
3699static void prlar_write(CPUARMState *env, const ARMCPRegInfo *ri,
3700 uint64_t value)
3701{
3702 ARMCPU *cpu = env_archcpu(env);
3703
3704 tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
3705 env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] = value;
3706}
3707
3708static uint64_t prlar_read(CPUARMState *env, const ARMCPRegInfo *ri)
3709{
3710 return env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]];
3711}
3712
3713static void prselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3714 uint64_t value)
3715{
3716 ARMCPU *cpu = env_archcpu(env);
3717
3718 /*
3719 * Ignore writes that would select not implemented region.
3720 * This is architecturally UNPREDICTABLE.
3721 */
3722 if (value >= cpu->pmsav7_dregion) {
3723 return;
3724 }
3725
3726 env->pmsav7.rnr[M_REG_NS] = value;
3727}
3728
3729static void hprbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
3730 uint64_t value)
3731{
3732 ARMCPU *cpu = env_archcpu(env);
3733
3734 tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
3735 env->pmsav8.hprbar[env->pmsav8.hprselr] = value;
3736}
3737
3738static uint64_t hprbar_read(CPUARMState *env, const ARMCPRegInfo *ri)
3739{
3740 return env->pmsav8.hprbar[env->pmsav8.hprselr];
3741}
3742
3743static void hprlar_write(CPUARMState *env, const ARMCPRegInfo *ri,
3744 uint64_t value)
3745{
3746 ARMCPU *cpu = env_archcpu(env);
3747
3748 tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
3749 env->pmsav8.hprlar[env->pmsav8.hprselr] = value;
3750}
3751
3752static uint64_t hprlar_read(CPUARMState *env, const ARMCPRegInfo *ri)
3753{
3754 return env->pmsav8.hprlar[env->pmsav8.hprselr];
3755}
3756
3757static void hprenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3758 uint64_t value)
3759{
3760 uint32_t n;
3761 uint32_t bit;
3762 ARMCPU *cpu = env_archcpu(env);
3763
3764 /* Ignore writes to unimplemented regions */
3765 int rmax = MIN(cpu->pmsav8r_hdregion, 32);
3766 value &= MAKE_64BIT_MASK(0, rmax);
3767
3768 tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
3769
3770 /* Register alias is only valid for first 32 indexes */
3771 for (n = 0; n < rmax; ++n) {
3772 bit = extract32(value, n, 1);
3773 env->pmsav8.hprlar[n] = deposit32(
3774 env->pmsav8.hprlar[n], 0, 1, bit);
3775 }
3776}
3777
3778static uint64_t hprenr_read(CPUARMState *env, const ARMCPRegInfo *ri)
3779{
3780 uint32_t n;
3781 uint32_t result = 0x0;
3782 ARMCPU *cpu = env_archcpu(env);
3783
3784 /* Register alias is only valid for first 32 indexes */
3785 for (n = 0; n < MIN(cpu->pmsav8r_hdregion, 32); ++n) {
3786 if (env->pmsav8.hprlar[n] & 0x1) {
3787 result |= (0x1 << n);
3788 }
3789 }
3790 return result;
3791}
3792
3793static void hprselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3794 uint64_t value)
3795{
3796 ARMCPU *cpu = env_archcpu(env);
3797
3798 /*
3799 * Ignore writes that would select not implemented region.
3800 * This is architecturally UNPREDICTABLE.
3801 */
3802 if (value >= cpu->pmsav8r_hdregion) {
3803 return;
3804 }
3805
3806 env->pmsav8.hprselr = value;
3807}
3808
3809static void pmsav8r_regn_write(CPUARMState *env, const ARMCPRegInfo *ri,
3810 uint64_t value)
3811{
3812 ARMCPU *cpu = env_archcpu(env);
3813 uint8_t index = (extract32(ri->opc0, 0, 1) << 4) |
3814 (extract32(ri->crm, 0, 3) << 1) | extract32(ri->opc2, 2, 1);
3815
3816 tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
3817
3818 if (ri->opc1 & 4) {
3819 if (index >= cpu->pmsav8r_hdregion) {
3820 return;
3821 }
3822 if (ri->opc2 & 0x1) {
3823 env->pmsav8.hprlar[index] = value;
3824 } else {
3825 env->pmsav8.hprbar[index] = value;
3826 }
3827 } else {
3828 if (index >= cpu->pmsav7_dregion) {
3829 return;
3830 }
3831 if (ri->opc2 & 0x1) {
3832 env->pmsav8.rlar[M_REG_NS][index] = value;
3833 } else {
3834 env->pmsav8.rbar[M_REG_NS][index] = value;
3835 }
3836 }
3837}
3838
3839static uint64_t pmsav8r_regn_read(CPUARMState *env, const ARMCPRegInfo *ri)
3840{
3841 ARMCPU *cpu = env_archcpu(env);
3842 uint8_t index = (extract32(ri->opc0, 0, 1) << 4) |
3843 (extract32(ri->crm, 0, 3) << 1) | extract32(ri->opc2, 2, 1);
3844
3845 if (ri->opc1 & 4) {
3846 if (index >= cpu->pmsav8r_hdregion) {
3847 return 0x0;
3848 }
3849 if (ri->opc2 & 0x1) {
3850 return env->pmsav8.hprlar[index];
3851 } else {
3852 return env->pmsav8.hprbar[index];
3853 }
3854 } else {
3855 if (index >= cpu->pmsav7_dregion) {
3856 return 0x0;
3857 }
3858 if (ri->opc2 & 0x1) {
3859 return env->pmsav8.rlar[M_REG_NS][index];
3860 } else {
3861 return env->pmsav8.rbar[M_REG_NS][index];
3862 }
3863 }
3864}
3865
3866static const ARMCPRegInfo pmsav8r_cp_reginfo[] = {
3867 { .name = "PRBAR",
3868 .cp = 15, .opc1 = 0, .crn = 6, .crm = 3, .opc2 = 0,
3869 .access = PL1_RW, .type = ARM_CP_NO_RAW,
3870 .accessfn = access_tvm_trvm,
3871 .readfn = prbar_read, .writefn = prbar_write },
3872 { .name = "PRLAR",
3873 .cp = 15, .opc1 = 0, .crn = 6, .crm = 3, .opc2 = 1,
3874 .access = PL1_RW, .type = ARM_CP_NO_RAW,
3875 .accessfn = access_tvm_trvm,
3876 .readfn = prlar_read, .writefn = prlar_write },
3877 { .name = "PRSELR", .resetvalue = 0,
3878 .cp = 15, .opc1 = 0, .crn = 6, .crm = 2, .opc2 = 1,
3879 .access = PL1_RW, .accessfn = access_tvm_trvm,
3880 .writefn = prselr_write,
3881 .fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]) },
3882 { .name = "HPRBAR", .resetvalue = 0,
3883 .cp = 15, .opc1 = 4, .crn = 6, .crm = 3, .opc2 = 0,
3884 .access = PL2_RW, .type = ARM_CP_NO_RAW,
3885 .readfn = hprbar_read, .writefn = hprbar_write },
3886 { .name = "HPRLAR",
3887 .cp = 15, .opc1 = 4, .crn = 6, .crm = 3, .opc2 = 1,
3888 .access = PL2_RW, .type = ARM_CP_NO_RAW,
3889 .readfn = hprlar_read, .writefn = hprlar_write },
3890 { .name = "HPRSELR", .resetvalue = 0,
3891 .cp = 15, .opc1 = 4, .crn = 6, .crm = 2, .opc2 = 1,
3892 .access = PL2_RW,
3893 .writefn = hprselr_write,
3894 .fieldoffset = offsetof(CPUARMState, pmsav8.hprselr) },
3895 { .name = "HPRENR",
3896 .cp = 15, .opc1 = 4, .crn = 6, .crm = 1, .opc2 = 1,
3897 .access = PL2_RW, .type = ARM_CP_NO_RAW,
3898 .readfn = hprenr_read, .writefn = hprenr_write },
3899};
3900
3685static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
3686 /* Reset for all these registers is handled in arm_cpu_reset(),
3687 * because the PMSAv7 is also used by M-profile CPUs, which do
3688 * not register cpregs but still need the state to be reset.
3689 */
3690 { .name = "DRBAR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 0,
3691 .access = PL1_RW, .type = ARM_CP_NO_RAW,
3692 .fieldoffset = offsetof(CPUARMState, pmsav7.drbar),

--- 4509 unchanged lines hidden (view full) ---

8202 };
8203 /* MPUIR is specific to PMSA V6+ */
8204 ARMCPRegInfo id_mpuir_reginfo = {
8205 .name = "MPUIR",
8206 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
8207 .access = PL1_R, .type = ARM_CP_CONST,
8208 .resetvalue = cpu->pmsav7_dregion << 8
8209 };
3901static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
3902 /* Reset for all these registers is handled in arm_cpu_reset(),
3903 * because the PMSAv7 is also used by M-profile CPUs, which do
3904 * not register cpregs but still need the state to be reset.
3905 */
3906 { .name = "DRBAR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 0,
3907 .access = PL1_RW, .type = ARM_CP_NO_RAW,
3908 .fieldoffset = offsetof(CPUARMState, pmsav7.drbar),

--- 4509 unchanged lines hidden (view full) ---

8418 };
8419 /* MPUIR is specific to PMSA V6+ */
8420 ARMCPRegInfo id_mpuir_reginfo = {
8421 .name = "MPUIR",
8422 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
8423 .access = PL1_R, .type = ARM_CP_CONST,
8424 .resetvalue = cpu->pmsav7_dregion << 8
8425 };
8426 /* HMPUIR is specific to PMSA V8 */
8427 ARMCPRegInfo id_hmpuir_reginfo = {
8428 .name = "HMPUIR",
8429 .cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 4,
8430 .access = PL2_R, .type = ARM_CP_CONST,
8431 .resetvalue = cpu->pmsav8r_hdregion
8432 };
8210 static const ARMCPRegInfo crn0_wi_reginfo = {
8211 .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
8212 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
8213 .type = ARM_CP_NOP | ARM_CP_OVERRIDE
8214 };
8215#ifdef CONFIG_USER_ONLY
8216 static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
8217 { .name = "MIDR_EL1",

--- 26 unchanged lines hidden (view full) ---

8244 define_one_arm_cp_reg(cpu, &id_v8_midr_alias_cp_reginfo);
8245 }
8246 } else {
8247 define_arm_cp_regs(cpu, id_pre_v8_midr_cp_reginfo);
8248 }
8249 define_arm_cp_regs(cpu, id_cp_reginfo);
8250 if (!arm_feature(env, ARM_FEATURE_PMSA)) {
8251 define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
8433 static const ARMCPRegInfo crn0_wi_reginfo = {
8434 .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
8435 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
8436 .type = ARM_CP_NOP | ARM_CP_OVERRIDE
8437 };
8438#ifdef CONFIG_USER_ONLY
8439 static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
8440 { .name = "MIDR_EL1",

--- 26 unchanged lines hidden (view full) ---

8467 define_one_arm_cp_reg(cpu, &id_v8_midr_alias_cp_reginfo);
8468 }
8469 } else {
8470 define_arm_cp_regs(cpu, id_pre_v8_midr_cp_reginfo);
8471 }
8472 define_arm_cp_regs(cpu, id_cp_reginfo);
8473 if (!arm_feature(env, ARM_FEATURE_PMSA)) {
8474 define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
8475 } else if (arm_feature(env, ARM_FEATURE_PMSA) &&
8476 arm_feature(env, ARM_FEATURE_V8)) {
8477 uint32_t i = 0;
8478 char *tmp_string;
8479
8480 define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
8481 define_one_arm_cp_reg(cpu, &id_hmpuir_reginfo);
8482 define_arm_cp_regs(cpu, pmsav8r_cp_reginfo);
8483
8484 /* Register alias is only valid for first 32 indexes */
8485 for (i = 0; i < MIN(cpu->pmsav7_dregion, 32); ++i) {
8486 uint8_t crm = 0b1000 | extract32(i, 1, 3);
8487 uint8_t opc1 = extract32(i, 4, 1);
8488 uint8_t opc2 = extract32(i, 0, 1) << 2;
8489
8490 tmp_string = g_strdup_printf("PRBAR%u", i);
8491 ARMCPRegInfo tmp_prbarn_reginfo = {
8492 .name = tmp_string, .type = ARM_CP_ALIAS | ARM_CP_NO_RAW,
8493 .cp = 15, .opc1 = opc1, .crn = 6, .crm = crm, .opc2 = opc2,
8494 .access = PL1_RW, .resetvalue = 0,
8495 .accessfn = access_tvm_trvm,
8496 .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
8497 };
8498 define_one_arm_cp_reg(cpu, &tmp_prbarn_reginfo);
8499 g_free(tmp_string);
8500
8501 opc2 = extract32(i, 0, 1) << 2 | 0x1;
8502 tmp_string = g_strdup_printf("PRLAR%u", i);
8503 ARMCPRegInfo tmp_prlarn_reginfo = {
8504 .name = tmp_string, .type = ARM_CP_ALIAS | ARM_CP_NO_RAW,
8505 .cp = 15, .opc1 = opc1, .crn = 6, .crm = crm, .opc2 = opc2,
8506 .access = PL1_RW, .resetvalue = 0,
8507 .accessfn = access_tvm_trvm,
8508 .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
8509 };
8510 define_one_arm_cp_reg(cpu, &tmp_prlarn_reginfo);
8511 g_free(tmp_string);
8512 }
8513
8514 /* Register alias is only valid for first 32 indexes */
8515 for (i = 0; i < MIN(cpu->pmsav8r_hdregion, 32); ++i) {
8516 uint8_t crm = 0b1000 | extract32(i, 1, 3);
8517 uint8_t opc1 = 0b100 | extract32(i, 4, 1);
8518 uint8_t opc2 = extract32(i, 0, 1) << 2;
8519
8520 tmp_string = g_strdup_printf("HPRBAR%u", i);
8521 ARMCPRegInfo tmp_hprbarn_reginfo = {
8522 .name = tmp_string,
8523 .type = ARM_CP_NO_RAW,
8524 .cp = 15, .opc1 = opc1, .crn = 6, .crm = crm, .opc2 = opc2,
8525 .access = PL2_RW, .resetvalue = 0,
8526 .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
8527 };
8528 define_one_arm_cp_reg(cpu, &tmp_hprbarn_reginfo);
8529 g_free(tmp_string);
8530
8531 opc2 = extract32(i, 0, 1) << 2 | 0x1;
8532 tmp_string = g_strdup_printf("HPRLAR%u", i);
8533 ARMCPRegInfo tmp_hprlarn_reginfo = {
8534 .name = tmp_string,
8535 .type = ARM_CP_NO_RAW,
8536 .cp = 15, .opc1 = opc1, .crn = 6, .crm = crm, .opc2 = opc2,
8537 .access = PL2_RW, .resetvalue = 0,
8538 .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
8539 };
8540 define_one_arm_cp_reg(cpu, &tmp_hprlarn_reginfo);
8541 g_free(tmp_string);
8542 }
8252 } else if (arm_feature(env, ARM_FEATURE_V7)) {
8253 define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
8254 }
8255 }
8256
8257 if (arm_feature(env, ARM_FEATURE_MPIDR)) {
8258 ARMCPRegInfo mpidr_cp_reginfo[] = {
8259 { .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,

--- 105 unchanged lines hidden (view full) ---

8365 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
8366 /* Normally we would always end the TB on an SCTLR write, but Linux
8367 * arch/arm/mach-pxa/sleep.S expects two instructions following
8368 * an MMU enable to execute from cache. Imitate this behaviour.
8369 */
8370 sctlr.type |= ARM_CP_SUPPRESS_TB_END;
8371 }
8372 define_one_arm_cp_reg(cpu, &sctlr);
8543 } else if (arm_feature(env, ARM_FEATURE_V7)) {
8544 define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
8545 }
8546 }
8547
8548 if (arm_feature(env, ARM_FEATURE_MPIDR)) {
8549 ARMCPRegInfo mpidr_cp_reginfo[] = {
8550 { .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,

--- 105 unchanged lines hidden (view full) ---

8656 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
8657 /* Normally we would always end the TB on an SCTLR write, but Linux
8658 * arch/arm/mach-pxa/sleep.S expects two instructions following
8659 * an MMU enable to execute from cache. Imitate this behaviour.
8660 */
8661 sctlr.type |= ARM_CP_SUPPRESS_TB_END;
8662 }
8663 define_one_arm_cp_reg(cpu, &sctlr);
8664
8665 if (arm_feature(env, ARM_FEATURE_PMSA) &&
8666 arm_feature(env, ARM_FEATURE_V8)) {
8667 ARMCPRegInfo vsctlr = {
8668 .name = "VSCTLR", .state = ARM_CP_STATE_AA32,
8669 .cp = 15, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
8670 .access = PL2_RW, .resetvalue = 0x0,
8671 .fieldoffset = offsetoflow32(CPUARMState, cp15.vsctlr),
8672 };
8673 define_one_arm_cp_reg(cpu, &vsctlr);
8674 }
8373 }
8374
8375 if (cpu_isar_feature(aa64_lor, cpu)) {
8376 define_arm_cp_regs(cpu, lor_reginfo);
8377 }
8378 if (cpu_isar_feature(aa64_pan, cpu)) {
8379 define_one_arm_cp_reg(cpu, &pan_reginfo);
8380 }

--- 3300 unchanged lines hidden ---
8675 }
8676
8677 if (cpu_isar_feature(aa64_lor, cpu)) {
8678 define_arm_cp_regs(cpu, lor_reginfo);
8679 }
8680 if (cpu_isar_feature(aa64_pan, cpu)) {
8681 define_one_arm_cp_reg(cpu, &pan_reginfo);
8682 }

--- 3300 unchanged lines hidden ---