target/arm: Allow cpu to configure GM blocksize

Previously we hard-coded the blocksize with GMID_EL1_BS.
But the value we choose for -cpu max does not match the
value that cortex-a710 uses.

Mirror the way we handle dcz_blocksize.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20230811214031.171020-3-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2023-08-31 09:45:14 +01:00 committed by Peter Maydell
parent ae4acc696f
commit 851ec6eba5
7 changed files with 45 additions and 28 deletions

View file

@ -1075,6 +1075,8 @@ struct ArchCPU {
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */ /* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
uint8_t dcz_blocksize; uint8_t dcz_blocksize;
/* GM blocksize, in log_2(words), ie low 4 bits of GMID_EL0 */
uint8_t gm_blocksize;
uint64_t rvbar_prop; /* Property/input signals. */ uint64_t rvbar_prop; /* Property/input signals. */

View file

@ -7748,10 +7748,6 @@ static const ARMCPRegInfo mte_reginfo[] = {
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6, .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6,
.access = PL1_RW, .accessfn = access_mte, .access = PL1_RW, .accessfn = access_mte,
.fieldoffset = offsetof(CPUARMState, cp15.gcr_el1) }, .fieldoffset = offsetof(CPUARMState, cp15.gcr_el1) },
{ .name = "GMID_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 4,
.access = PL1_R, .accessfn = access_aa64_tid5,
.type = ARM_CP_CONST, .resetvalue = GMID_EL1_BS },
{ .name = "TCO", .state = ARM_CP_STATE_AA64, { .name = "TCO", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7, .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
.type = ARM_CP_NO_RAW, .type = ARM_CP_NO_RAW,
@ -9342,6 +9338,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
* then define only a RAZ/WI version of PSTATE.TCO. * then define only a RAZ/WI version of PSTATE.TCO.
*/ */
if (cpu_isar_feature(aa64_mte, cpu)) { if (cpu_isar_feature(aa64_mte, cpu)) {
ARMCPRegInfo gmid_reginfo = {
.name = "GMID_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 4,
.access = PL1_R, .accessfn = access_aa64_tid5,
.type = ARM_CP_CONST, .resetvalue = cpu->gm_blocksize,
};
define_one_arm_cp_reg(cpu, &gmid_reginfo);
define_arm_cp_regs(cpu, mte_reginfo); define_arm_cp_regs(cpu, mte_reginfo);
define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo); define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo);
} else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) { } else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) {

View file

@ -1246,12 +1246,6 @@ void arm_log_exception(CPUState *cs);
#endif /* !CONFIG_USER_ONLY */ #endif /* !CONFIG_USER_ONLY */
/*
* The log2 of the words in the tag block, for GMID_EL1.BS.
* The is the maximum, 256 bytes, which manipulates 64-bits of tags.
*/
#define GMID_EL1_BS 6
/* /*
* SVE predicates are 1/8 the size of SVE vectors, and cannot use * SVE predicates are 1/8 the size of SVE vectors, and cannot use
* the same simd_desc() encoding due to restrictions on size. * the same simd_desc() encoding due to restrictions on size.

View file

@ -868,6 +868,7 @@ void aarch64_max_tcg_initfn(Object *obj)
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
cpu->dcz_blocksize = 7; /* 512 bytes */ cpu->dcz_blocksize = 7; /* 512 bytes */
#endif #endif
cpu->gm_blocksize = 6; /* 256 bytes */
cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ); cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
cpu->sme_vq.supported = SVE_VQ_POW2_MAP; cpu->sme_vq.supported = SVE_VQ_POW2_MAP;

View file

@ -421,46 +421,54 @@ void HELPER(st2g_stub)(CPUARMState *env, uint64_t ptr)
} }
} }
#define LDGM_STGM_SIZE (4 << GMID_EL1_BS)
uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr) uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
{ {
int mmu_idx = cpu_mmu_index(env, false); int mmu_idx = cpu_mmu_index(env, false);
uintptr_t ra = GETPC(); uintptr_t ra = GETPC();
int gm_bs = env_archcpu(env)->gm_blocksize;
int gm_bs_bytes = 4 << gm_bs;
void *tag_mem; void *tag_mem;
ptr = QEMU_ALIGN_DOWN(ptr, LDGM_STGM_SIZE); ptr = QEMU_ALIGN_DOWN(ptr, gm_bs_bytes);
/* Trap if accessing an invalid page. */ /* Trap if accessing an invalid page. */
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD, tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD,
LDGM_STGM_SIZE, MMU_DATA_LOAD, gm_bs_bytes, MMU_DATA_LOAD,
LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra); gm_bs_bytes / (2 * TAG_GRANULE), ra);
/* The tag is squashed to zero if the page does not support tags. */ /* The tag is squashed to zero if the page does not support tags. */
if (!tag_mem) { if (!tag_mem) {
return 0; return 0;
} }
QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6);
/* /*
* We are loading 64-bits worth of tags. The ordering of elements * The ordering of elements within the word corresponds to
* within the word corresponds to a 64-bit little-endian operation. * a little-endian operation.
*/ */
return ldq_le_p(tag_mem); switch (gm_bs) {
case 6:
/* 256 bytes -> 16 tags -> 64 result bits */
return ldq_le_p(tag_mem);
default:
/* cpu configured with unsupported gm blocksize. */
g_assert_not_reached();
}
} }
void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val) void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
{ {
int mmu_idx = cpu_mmu_index(env, false); int mmu_idx = cpu_mmu_index(env, false);
uintptr_t ra = GETPC(); uintptr_t ra = GETPC();
int gm_bs = env_archcpu(env)->gm_blocksize;
int gm_bs_bytes = 4 << gm_bs;
void *tag_mem; void *tag_mem;
ptr = QEMU_ALIGN_DOWN(ptr, LDGM_STGM_SIZE); ptr = QEMU_ALIGN_DOWN(ptr, gm_bs_bytes);
/* Trap if accessing an invalid page. */ /* Trap if accessing an invalid page. */
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE, tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE,
LDGM_STGM_SIZE, MMU_DATA_LOAD, gm_bs_bytes, MMU_DATA_LOAD,
LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra); gm_bs_bytes / (2 * TAG_GRANULE), ra);
/* /*
* Tag store only happens if the page support tags, * Tag store only happens if the page support tags,
@ -470,12 +478,18 @@ void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
return; return;
} }
QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6);
/* /*
* We are storing 64-bits worth of tags. The ordering of elements * The ordering of elements within the word corresponds to
* within the word corresponds to a 64-bit little-endian operation. * a little-endian operation.
*/ */
stq_le_p(tag_mem, val); switch (gm_bs) {
case 6:
stq_le_p(tag_mem, val);
break;
default:
/* cpu configured with unsupported gm blocksize. */
g_assert_not_reached();
}
} }
void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val) void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val)

View file

@ -3786,7 +3786,7 @@ static bool trans_STGM(DisasContext *s, arg_ldst_tag *a)
gen_helper_stgm(cpu_env, addr, tcg_rt); gen_helper_stgm(cpu_env, addr, tcg_rt);
} else { } else {
MMUAccessType acc = MMU_DATA_STORE; MMUAccessType acc = MMU_DATA_STORE;
int size = 4 << GMID_EL1_BS; int size = 4 << s->gm_blocksize;
clean_addr = clean_data_tbi(s, addr); clean_addr = clean_data_tbi(s, addr);
tcg_gen_andi_i64(clean_addr, clean_addr, -size); tcg_gen_andi_i64(clean_addr, clean_addr, -size);
@ -3818,7 +3818,7 @@ static bool trans_LDGM(DisasContext *s, arg_ldst_tag *a)
gen_helper_ldgm(tcg_rt, cpu_env, addr); gen_helper_ldgm(tcg_rt, cpu_env, addr);
} else { } else {
MMUAccessType acc = MMU_DATA_LOAD; MMUAccessType acc = MMU_DATA_LOAD;
int size = 4 << GMID_EL1_BS; int size = 4 << s->gm_blocksize;
clean_addr = clean_data_tbi(s, addr); clean_addr = clean_data_tbi(s, addr);
tcg_gen_andi_i64(clean_addr, clean_addr, -size); tcg_gen_andi_i64(clean_addr, clean_addr, -size);
@ -13896,6 +13896,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->cp_regs = arm_cpu->cp_regs; dc->cp_regs = arm_cpu->cp_regs;
dc->features = env->features; dc->features = env->features;
dc->dcz_blocksize = arm_cpu->dcz_blocksize; dc->dcz_blocksize = arm_cpu->dcz_blocksize;
dc->gm_blocksize = arm_cpu->gm_blocksize;
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
/* In sve_probe_page, we assume TBI is enabled. */ /* In sve_probe_page, we assume TBI is enabled. */

View file

@ -151,6 +151,8 @@ typedef struct DisasContext {
int8_t btype; int8_t btype;
/* A copy of cpu->dcz_blocksize. */ /* A copy of cpu->dcz_blocksize. */
uint8_t dcz_blocksize; uint8_t dcz_blocksize;
/* A copy of cpu->gm_blocksize. */
uint8_t gm_blocksize;
/* True if this page is guarded. */ /* True if this page is guarded. */
bool guarded_page; bool guarded_page;
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */ /* Bottom two bits of XScale c15_cpar coprocessor access control reg */