Browse Source

target/arm: Implement GCSPUSHM

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20251008215613.300150-49-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
pull/305/head
Richard Henderson 6 months ago
committed by Peter Maydell
parent
commit
3afe6037e7
  1. 15
      target/arm/cpregs-gcs.c
  2. 3
      target/arm/cpregs.h
  3. 29
      target/arm/tcg/translate-a64.c

15
target/arm/cpregs-gcs.c

@ -43,6 +43,16 @@ static void gcspr_write(CPUARMState *env, const ARMCPRegInfo *ri,
raw_write(env, ri, value & ~7);
}
static CPAccessResult access_gcspushm(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
{
int el = arm_current_el(env);
if (!(env->cp15.gcscr_el[el] & GCSCR_PUSHMEN)) {
return CP_ACCESS_TRAP_BIT | (el ? el : 1);
}
return CP_ACCESS_OK;
}
static const ARMCPRegInfo gcs_reginfo[] = {
{ .name = "GCSCRE0_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 5, .opc2 = 2,
@ -85,6 +95,11 @@ static const ARMCPRegInfo gcs_reginfo[] = {
.opc0 = 3, .opc1 = 6, .crn = 2, .crm = 5, .opc2 = 1,
.access = PL3_RW, .writefn = gcspr_write,
.fieldoffset = offsetof(CPUARMState, cp15.gcspr_el[2]) },
{ .name = "GCSPUSHM", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 0,
.access = PL0_W, .accessfn = access_gcspushm,
.fgt = FGT_NGCSPUSHM_EL1, .type = ARM_CP_GCSPUSHM },
};
void define_gcs_cpregs(ARMCPU *cpu)

3
target/arm/cpregs.h

@ -47,6 +47,8 @@ enum {
ARM_CP_DC_ZVA = 0x0005,
ARM_CP_DC_GVA = 0x0006,
ARM_CP_DC_GZVA = 0x0007,
/* Special: gcs instructions */
ARM_CP_GCSPUSHM = 0x0008,
/* Flag: reads produce resetvalue; writes ignored. */
ARM_CP_CONST = 1 << 4,
@ -871,6 +873,7 @@ typedef enum FGTBit {
DO_BIT(HFGITR, DVPRCTX),
DO_BIT(HFGITR, CPPRCTX),
DO_BIT(HFGITR, DCCVAC),
DO_REV_BIT(HFGITR, NGCSPUSHM_EL1),
DO_BIT(HFGITR, ATS1E1A),
} FGTBit;

29
target/arm/tcg/translate-a64.c

@ -26,6 +26,7 @@
#include "cpregs.h"
static TCGv_i64 cpu_X[32];
static TCGv_i64 cpu_gcspr[4];
static TCGv_i64 cpu_pc;
/* Load/store exclusive handling */
@ -77,6 +78,10 @@ static int scale_by_log2_tag_granule(DisasContext *s, int x)
/* initialize TCG globals. */
void a64_translate_init(void)
{
static const char gcspr_names[4][12] = {
"gcspr_el0", "gcspr_el1", "gcspr_el2", "gcspr_el3"
};
int i;
cpu_pc = tcg_global_mem_new_i64(tcg_env,
@ -90,6 +95,13 @@ void a64_translate_init(void)
cpu_exclusive_high = tcg_global_mem_new_i64(tcg_env,
offsetof(CPUARMState, exclusive_high), "exclusive_high");
for (i = 0; i < 4; i++) {
cpu_gcspr[i] =
tcg_global_mem_new_i64(tcg_env,
offsetof(CPUARMState, cp15.gcspr_el[i]),
gcspr_names[i]);
}
}
/*
@ -420,6 +432,18 @@ static MemOp check_ordered_align(DisasContext *s, int rn, int imm,
return finalize_memop(s, mop);
}
static void gen_add_gcs_record(DisasContext *s, TCGv_i64 value)
{
TCGv_i64 addr = tcg_temp_new_i64();
TCGv_i64 gcspr = cpu_gcspr[s->current_el];
int mmuidx = core_gcs_mem_index(s->mmu_idx);
MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
tcg_gen_addi_i64(addr, gcspr, -8);
tcg_gen_qemu_st_i64(value, clean_data_tbi(s, addr), mmuidx, mop);
tcg_gen_mov_i64(gcspr, addr);
}
typedef struct DisasCompare64 {
TCGCond cond;
TCGv_i64 value;
@ -2803,6 +2827,11 @@ static void handle_sys(DisasContext *s, bool isread,
}
}
return;
case ARM_CP_GCSPUSHM:
if (s->gcs_en) {
gen_add_gcs_record(s, cpu_reg(s, rt));
}
return;
default:
g_assert_not_reached();
}

Loading…
Cancel
Save