/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
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. */
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6,
.access = PL1_RW, .accessfn = access_mte,
.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,
.opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
.type = ARM_CP_NO_RAW,
* then define only a RAZ/WI version of PSTATE.TCO.
*/
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_el0_cacheop_reginfo);
} else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) {
#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
* the same simd_desc() encoding due to restrictions on size.
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
cpu->dcz_blocksize = 7; /* 512 bytes */
#endif
+ cpu->gm_blocksize = 6; /* 256 bytes */
cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
cpu->sme_vq.supported = SVE_VQ_POW2_MAP;
}
}
-#define LDGM_STGM_SIZE (4 << GMID_EL1_BS)
-
uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
{
int mmu_idx = cpu_mmu_index(env, false);
uintptr_t ra = GETPC();
+ int gm_bs = env_archcpu(env)->gm_blocksize;
+ int gm_bs_bytes = 4 << gm_bs;
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. */
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD,
- LDGM_STGM_SIZE, MMU_DATA_LOAD,
- LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra);
+ gm_bs_bytes, MMU_DATA_LOAD,
+ gm_bs_bytes / (2 * TAG_GRANULE), ra);
/* The tag is squashed to zero if the page does not support tags. */
if (!tag_mem) {
return 0;
}
- QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6);
/*
- * We are loading 64-bits worth of tags. The ordering of elements
- * within the word corresponds to a 64-bit little-endian operation.
+ * The ordering of elements within the word corresponds to
+ * 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)
{
int mmu_idx = cpu_mmu_index(env, false);
uintptr_t ra = GETPC();
+ int gm_bs = env_archcpu(env)->gm_blocksize;
+ int gm_bs_bytes = 4 << gm_bs;
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. */
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE,
- LDGM_STGM_SIZE, MMU_DATA_LOAD,
- LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra);
+ gm_bs_bytes, MMU_DATA_LOAD,
+ gm_bs_bytes / (2 * TAG_GRANULE), ra);
/*
* Tag store only happens if the page support tags,
return;
}
- QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6);
/*
- * We are storing 64-bits worth of tags. The ordering of elements
- * within the word corresponds to a 64-bit little-endian operation.
+ * The ordering of elements within the word corresponds to
+ * 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)
gen_helper_stgm(cpu_env, addr, tcg_rt);
} else {
MMUAccessType acc = MMU_DATA_STORE;
- int size = 4 << GMID_EL1_BS;
+ int size = 4 << s->gm_blocksize;
clean_addr = clean_data_tbi(s, addr);
tcg_gen_andi_i64(clean_addr, clean_addr, -size);
gen_helper_ldgm(tcg_rt, cpu_env, addr);
} else {
MMUAccessType acc = MMU_DATA_LOAD;
- int size = 4 << GMID_EL1_BS;
+ int size = 4 << s->gm_blocksize;
clean_addr = clean_data_tbi(s, addr);
tcg_gen_andi_i64(clean_addr, clean_addr, -size);
dc->cp_regs = arm_cpu->cp_regs;
dc->features = env->features;
dc->dcz_blocksize = arm_cpu->dcz_blocksize;
+ dc->gm_blocksize = arm_cpu->gm_blocksize;
#ifdef CONFIG_USER_ONLY
/* In sve_probe_page, we assume TBI is enabled. */
int8_t btype;
/* A copy of cpu->dcz_blocksize. */
uint8_t dcz_blocksize;
+ /* A copy of cpu->gm_blocksize. */
+ uint8_t gm_blocksize;
/* True if this page is guarded. */
bool guarded_page;
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */