From patchwork Fri Mar 13 14:00:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= X-Patchwork-Id: 1254412 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=remlab.net Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48f6s54l7rz9sNg for ; Sat, 14 Mar 2020 01:04:57 +1100 (AEDT) Received: from localhost ([::1]:59402 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCkvn-0003Pw-JB for incoming@patchwork.ozlabs.org; Fri, 13 Mar 2020 10:04:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42841) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCkrb-0005bJ-Fk for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jCkrZ-00015x-Pf for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:35 -0400 Received: from poy.remlab.net ([2001:41d0:2:5a1a::]:49722 helo=ns207790.ip-94-23-215.eu) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1jCkrR-0000XA-D7; Fri, 13 Mar 2020 10:00:29 -0400 Received: from basile.remlab.net (ip6-localhost [IPv6:::1]) by ns207790.ip-94-23-215.eu (Postfix) with ESMTP id 166455FAA2; Fri, 13 Mar 2020 15:00:24 +0100 (CET) From: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= To: qemu-arm@nongnu.org Subject: [PATCH 1/5] target/arm: MTE processor state Date: Fri, 13 Mar 2020 16:00:19 +0200 Message-Id: <20200313140023.83844-1-remi@remlab.net> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:41d0:2:5a1a:: X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Rémi Denis-Courmont This adds architectural definitions and internal processor state for the ARMv8.5-MemTag, a.k.a. MTE extension: - a new ISAR register feature field, - new ATA flag bits for tag access in SCR, HCR and SCTLR registers, - a TCO flag in PSTATE and SPSR_ELx registers, - new CPU registers for pseudo-random tags generation. Signed-off-by: Rémi Denis-Courmont --- target/arm/cpu.h | 17 +++++++++++++++++ target/arm/helper-a64.c | 2 ++ target/arm/helper.c | 17 +++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 4ffd991b6f..e19ce0d746 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -267,6 +267,14 @@ typedef struct CPUARMState { uint64_t elr_el[4]; /* AArch64 exception link regs */ uint64_t sp_el[4]; /* AArch64 banked stack pointers */ + /* Tag registers */ + uint64_t gcr_el1; + uint64_t rgsr_el1; + union { + uint64_t tfsre0_el1; + uint64_t tfsr_el[4]; + }; + /* System control coprocessor (cp15) */ struct { uint32_t c0_cpuid; @@ -1259,6 +1267,7 @@ void pmu_init(ARMCPU *cpu); #define PSTATE_SS (1U << 21) #define PSTATE_PAN (1U << 22) #define PSTATE_UAO (1U << 23) +#define PSTATE_TCO (1U << 25) #define PSTATE_V (1U << 28) #define PSTATE_C (1U << 29) #define PSTATE_Z (1U << 30) @@ -2949,6 +2958,9 @@ typedef enum ARMASIdx { ARMASIdx_S = 1, } ARMASIdx; +#define ARM_LOG2_TAG_GRANULE 4 +#define ARM_TAG_GRANULE (UINT64_C(1) << ARM_LOG2_TAG_GRANULE) + /* Return the Exception Level targeted by debug exceptions. */ static inline int arm_debug_target_el(CPUARMState *env) { @@ -3777,6 +3789,11 @@ static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; } +static inline unsigned isar_feature_aa64_mte(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE); +} + static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c index bc0649a44a..5c8d081d4c 100644 --- a/target/arm/helper-a64.c +++ b/target/arm/helper-a64.c @@ -1036,6 +1036,8 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc) env->aarch64 = 1; spsr &= aarch64_pstate_valid_mask(&env_archcpu(env)->isar); + /* TCO bit is copied from CPSR, not SPSR */ + spsr = (spsr & ~PSTATE_TCO) | (env->pstate & PSTATE_TCO); pstate_write(env, spsr); if (!arm_singlestep_active(env)) { env->pstate &= ~PSTATE_SS; diff --git a/target/arm/helper.c b/target/arm/helper.c index b61ee73d18..38500e4f92 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1993,6 +1993,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) if (cpu_isar_feature(aa64_pauth, cpu)) { valid_mask |= SCR_API | SCR_APK; } + if (cpu_isar_feature(aa64_mte, cpu) >= 2) { + valid_mask |= SCR_ATA; + } /* Clear all-context RES0 bits. */ value &= valid_mask; @@ -4691,6 +4694,11 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, value &= ~SCTLR_M; } + if (cpu_isar_feature(aa64_mte, cpu) < 2) { + /* ATA and ATA0 are RES0 without full MTE implementation */ + value &= ~(SCTLR_ATA | SCTLR_ATA0); + } + raw_write(env, ri, value); /* ??? Lots of these bits are not implemented. */ /* This may enable/disable the MMU, so do a TLB flush. */ @@ -5226,6 +5234,15 @@ static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask) if (cpu_isar_feature(aa64_pauth, cpu)) { valid_mask |= HCR_API | HCR_APK; } + switch (cpu_isar_feature(aa64_mte, cpu)) { + default: + valid_mask |= HCR_ATA; + /* fall through */ + case 1: + valid_mask |= HCR_DCT; + case 0: + break; + } } /* Clear RES0 bits. */ From patchwork Fri Mar 13 14:00:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= X-Patchwork-Id: 1254413 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=remlab.net Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48f6vB27xTz9sQx for ; Sat, 14 Mar 2020 01:06:44 +1100 (AEDT) Received: from localhost ([::1]:59442 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCkxV-0005O6-DD for incoming@patchwork.ozlabs.org; Fri, 13 Mar 2020 10:06:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43037) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCkrk-0005qA-Au for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jCkrh-0001Rn-MK for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:44 -0400 Received: from poy.remlab.net ([2001:41d0:2:5a1a::]:49724 helo=ns207790.ip-94-23-215.eu) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1jCkrV-0000b0-MG; Fri, 13 Mar 2020 10:00:29 -0400 Received: from basile.remlab.net (ip6-localhost [IPv6:::1]) by ns207790.ip-94-23-215.eu (Postfix) with ESMTP id 683635FD2A; Fri, 13 Mar 2020 15:00:24 +0100 (CET) From: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= To: qemu-arm@nongnu.org Subject: [PATCH 2/5] target/arm: MTE user mode disassembly Date: Fri, 13 Mar 2020 16:00:20 +0200 Message-Id: <20200313140023.83844-2-remi@remlab.net> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:41d0:2:5a1a:: X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Rémi Denis-Courmont This adds TCG disassembler support for the EL0-accessible instructions from ARMv8.5-MemTag, and sets corresponding feature bit in the "maximum" emulated CPU. Signed-off-by: Rémi Denis-Courmont --- target/arm/cpu64.c | 7 ++ target/arm/helper.c | 30 +++++ target/arm/translate-a64.c | 236 +++++++++++++++++++++++++++++++++++-- 3 files changed, 266 insertions(+), 7 deletions(-) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 62d36f9e8d..a72dfd3d98 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -665,6 +665,13 @@ static void aarch64_max_initfn(Object *obj) t = cpu->isar.id_aa64pfr1; t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); +#ifdef CONFIG_USER_ONLY + /* All MTE instructions and processor states are supported for user + * mode. This corresponds to feature field value 1 (field value 2 + * implies MemTag memory support). + */ + t = FIELD_DP64(t, ID_AA64PFR1, MTE, 1); +#endif cpu->isar.id_aa64pfr1 = t; t = cpu->isar.id_aa64mmfr1; diff --git a/target/arm/helper.c b/target/arm/helper.c index 38500e4f92..ed56198623 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6839,6 +6839,33 @@ static const ARMCPRegInfo dcpodp_reg[] = { }; #endif /*CONFIG_USER_ONLY*/ +static uint64_t tco_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_TCO; +} + +static void tco_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val) +{ + if (val & PSTATE_TCO) { + env->pstate |= PSTATE_TCO; + } else { + env->pstate &= ~PSTATE_TCO; + } +} + +static const ARMCPRegInfo mte_reginfo[] = { + { .name = "DC_GVA", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 3, + .access = PL0_W, .type = ARM_CP_NOP }, + { .name = "DC_GZVA", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 4, + .access = PL0_W, .type = ARM_CP_DC_ZVA }, + { .name = "TCO", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7, + .access = PL0_RW, .type = ARM_CP_NO_RAW, + .readfn = tco_read, .writefn = tco_write }, + REGINFO_SENTINEL +}; #endif static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri, @@ -7956,6 +7983,9 @@ void register_cp_regs_for_features(ARMCPU *cpu) } } #endif /*CONFIG_USER_ONLY*/ + if (cpu_isar_feature(aa64_mte, cpu)) { + define_arm_cp_regs(cpu, mte_reginfo); + } #endif if (cpu_isar_feature(any_predinv, cpu)) { diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 8fffb52203..6d86480043 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -830,6 +830,31 @@ static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1) } } +/* Extract an Allocation Tag from an address */ +static void gen_extract_tag(TCGv_i64 dest, TCGv_i64 source) +{ + TCGv_i64 sign = tcg_temp_new_i64(); + + /* See ARMv8.5-A AllocationTagFromAddress pseudocode */ + tcg_gen_extract_i64(sign, source, 55, 1); + tcg_gen_extract_i64(dest, source, 56, 4); + tcg_gen_add_i64(dest, dest, sign); + tcg_gen_andi_i64(dest, dest, 0xf); + tcg_temp_free_i64(sign); +} + +/* Deposit an Allocation Tag into an address */ +static void gen_deposit_tag(TCGv_i64 dest, TCGv_i64 source, TCGv_i64 tag) +{ + TCGv_i64 tmp = tcg_temp_new_i64(); + + /* See ARMv8.5-A AddressWithAllocationTag pseudocode */ + tcg_gen_extract_i64(tmp, source, 55, 1); + tcg_gen_sub_i64(tmp, tag, tmp); + tcg_gen_deposit_i64(dest, source, tmp, 56, 4); + tcg_temp_free_i64(tmp); +} + /* * Load/Store generators */ @@ -1650,6 +1675,19 @@ static void handle_msr_i(DisasContext *s, uint32_t insn, tcg_temp_free_i32(t1); break; + case 0x1c: /* TCO */ + if (!dc_isar_feature(aa64_mte, s)) { + unallocated_encoding(s); + return; + } + if (crm & 1) { + set_pstate_bits(PSTATE_TCO); + } else { + clear_pstate_bits(PSTATE_TCO); + } + s->base.is_jmp = DISAS_NEXT; + break; + case 0x1e: /* DAIFSet */ t1 = tcg_const_i32(crm); gen_helper_msr_i_daifset(cpu_env, t1); @@ -2678,6 +2716,82 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn) tcg_temp_free_i64(clean_addr); } +/* LDG, LDGV(EL1), ST(Z)(2)G, STGV */ +static void disas_ldst_memtag(DisasContext *s, uint32_t insn) +{ + int opc = extract32(insn, 22, 2); + int op2 = extract32(insn, 10, 2); + bool tuple = opc & 2; + bool zero_data = opc & 1; + bool is_store = op2 != 0; + bool postindex = op2 == 1; + bool wback = op2 != 2; + uint64_t offset = sextract64(insn, 12, 9) << ARM_LOG2_TAG_GRANULE; + int rn = extract32(insn, 5, 5); + int rt = extract32(insn, 0, 5); + TCGv_i64 tcg_addr; + + if (!dc_isar_feature(aa64_mte, s) || extract32(insn, 30, 2) != 3) { + unallocated_encoding(s); + return; + } + + if (op2 == 0 && opc != 1) { + unallocated_encoding(s); + return; + } + + if (rn == 31) { + gen_check_sp_alignment(s); + } + + tcg_addr = read_cpu_reg_sp(s, rn, 1); + + if (!postindex) { + tcg_gen_addi_i64(tcg_addr, tcg_addr, offset); + } + + if (is_store) { + /* Store Allocation Tag (STG, ST2G, STZG, STZ2G) */ + if (zero_data) { + TCGv_i64 ptr = tcg_temp_new_i64(); + TCGv_i64 zero = tcg_const_i64(0); + + do_gpr_st(s, zero, tcg_addr, 3, false, 0, false, false); + tcg_gen_addi_i64(ptr, tcg_addr, 8); + do_gpr_st(s, zero, ptr, 3, false, 0, false, false); + + if (tuple) { + tcg_gen_addi_i64(ptr, ptr, 8); + do_gpr_st(s, zero, ptr, 3, false, 0, false, false); + tcg_gen_addi_i64(ptr, ptr, 8); + do_gpr_st(s, zero, ptr, 3, false, 0, false, false); + } + + tcg_temp_free_i64(zero); + tcg_temp_free_i64(ptr); + } + /* Write access permission should be checked here. + * If zero_data is true, do_gpr_st() does it but elsewise not. + */ + + if (wback) { + if (postindex) { + tcg_gen_addi_i64(tcg_addr, tcg_addr, offset); + } + tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr); + } + } else { + /* Load Allocation Tag (LDG) */ + TCGv_i64 tcg_tag = tcg_const_i64(0); + + tcg_gen_andi_i64(tcg_addr, tcg_addr, ~(ARM_TAG_GRANULE - 1)); + /* In principles, read access permission should be checked here. */ + gen_deposit_tag(cpu_reg(s, rt), tcg_addr, tcg_tag); + tcg_temp_free_i64(tcg_tag); + } +} + /* * LDNP (Load Pair - non-temporal hint) * LDP (Load Pair - non vector) @@ -2688,6 +2802,7 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn) * LDP (Load Pair of SIMD&FP) * STNP (Store Pair of SIMD&FP - non-temporal hint) * STP (Store Pair of SIMD&FP) + * STGP (Store Pair - allocate tag) * * 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0 * +-----+-------+---+---+-------+---+-----------------------------+ @@ -2736,8 +2851,12 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) size = 2 + extract32(opc, 1, 1); is_signed = extract32(opc, 0, 1); if (!is_load && is_signed) { - unallocated_encoding(s); - return; + if (size == 3 || !dc_isar_feature(aa64_mte, s)) { + unallocated_encoding(s); + return; + } + + size = 3; /* sic! */ } } @@ -3728,12 +3847,15 @@ static void disas_ldst(DisasContext *s, uint32_t insn) disas_ldst_single_struct(s, insn); break; case 0x19: /* LDAPR/STLR (unscaled immediate) */ - if (extract32(insn, 10, 2) != 0 || - extract32(insn, 21, 1) != 0) { + if (extract32(insn, 10, 2) != 0) { unallocated_encoding(s); break; } - disas_ldst_ldapr_stlr(s, insn); + if (extract32(insn, 21, 1) != 0) { + disas_ldst_memtag(s, insn); + } else { + disas_ldst_ldapr_stlr(s, insn); + } break; default: unallocated_encoding(s); @@ -3791,10 +3913,12 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn) bool setflags = extract32(insn, 29, 1); bool sub_op = extract32(insn, 30, 1); bool is_64bit = extract32(insn, 31, 1); + bool memtag = false; TCGv_i64 tcg_rn = cpu_reg_sp(s, rn); TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd); TCGv_i64 tcg_result; + TCGv_i64 tcg_rtag; switch (shift) { case 0x0: @@ -3802,11 +3926,23 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn) case 0x1: imm <<= 12; break; + case 0x2: + memtag = true; + + if (dc_isar_feature(aa64_mte, s) && is_64bit && !setflags) { + imm = extract32(imm, 6, 6) << ARM_LOG2_TAG_GRANULE; + break; + } + /* fall through */ default: unallocated_encoding(s); return; } + if (memtag) { + tcg_rtag = tcg_const_i64(0); + } + tcg_result = tcg_temp_new_i64(); if (!setflags) { if (sub_op) { @@ -3824,6 +3960,11 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn) tcg_temp_free_i64(tcg_imm); } + if (memtag) { + gen_deposit_tag(tcg_result, tcg_result, tcg_rtag); + tcg_temp_free_i64(tcg_rtag); + } + if (is_64bit) { tcg_gen_mov_i64(tcg_rd, tcg_result); } else { @@ -5281,6 +5422,72 @@ static void handle_crc32(DisasContext *s, tcg_temp_free_i32(tcg_bytes); } +/* SUBP, SUBPS (incl. CCMP) */ +static void handle_subp(DisasContext *s, bool setflags, unsigned int sf, + unsigned int rm, unsigned int rn, unsigned int rd) +{ + TCGv_i64 tcg_addr1, tcg_addr2; + TCGv_i64 tcg_result; + + if (!sf || !dc_isar_feature(aa64_mte, s)) { + unallocated_encoding(s); + return; + } + + tcg_addr1 = tcg_temp_new_i64(); + tcg_addr2 = tcg_temp_new_i64(); + tcg_result = cpu_reg(s, rd); + + tcg_gen_sextract_i64(tcg_addr1, cpu_reg_sp(s, rn), 0, 56); + tcg_gen_sextract_i64(tcg_addr2, cpu_reg_sp(s, rm), 0, 56); + + if (setflags) { + gen_sub_CC(1, tcg_result, tcg_addr1, tcg_addr2); + } else { + tcg_gen_sub_i64(tcg_result, tcg_addr1, tcg_addr2); + } + + tcg_temp_free_i64(tcg_addr2); + tcg_temp_free_i64(tcg_addr1); +} + +static void handle_irg(DisasContext *s, unsigned int sf, + unsigned int rm, unsigned int rn, unsigned int rd) +{ + TCGv_i64 rtag; + + if (!sf || !dc_isar_feature(aa64_mte, s)) { + unallocated_encoding(s); + return; + } + + rtag = tcg_temp_new_i64(); + tcg_gen_movi_i64(rtag, 0); + gen_deposit_tag(cpu_reg_sp(s, rd), cpu_reg_sp(s, rn), rtag); + tcg_temp_free_i64(rtag); +} + +static void handle_gmi(DisasContext *s, unsigned int sf, + unsigned int rm, unsigned int rn, unsigned int rd) +{ + TCGv_i64 tcg_one, tcg_tag; + + if (!sf || !dc_isar_feature(aa64_mte, s)) { + unallocated_encoding(s); + return; + } + + tcg_one = tcg_const_i64(1); + tcg_tag = tcg_temp_new_i64(); + + gen_extract_tag(tcg_tag, cpu_reg_sp(s, rn)); + tcg_gen_shl_i64(tcg_tag, tcg_one, tcg_tag); + tcg_gen_or_i64(cpu_reg(s, rd), cpu_reg(s, rm), tcg_tag); + + tcg_temp_free_i64(tcg_tag); + tcg_temp_free_i64(tcg_one); +} + /* Data-processing (2 source) * 31 30 29 28 21 20 16 15 10 9 5 4 0 * +----+---+---+-----------------+------+--------+------+------+ @@ -5297,17 +5504,32 @@ static void disas_data_proc_2src(DisasContext *s, uint32_t insn) rd = extract32(insn, 0, 5); if (extract32(insn, 29, 1)) { - unallocated_encoding(s); - return; + switch (opcode) { + case 0: + handle_subp(s, true, sf, rm, rn, rd); + break; + default: + unallocated_encoding(s); + return; + } } switch (opcode) { + case 0: + handle_subp(s, false, sf, rm, rn, rd); + break; case 2: /* UDIV */ handle_div(s, false, sf, rm, rn, rd); break; case 3: /* SDIV */ handle_div(s, true, sf, rm, rn, rd); break; + case 4: + handle_irg(s, sf, rm, rn, rd); + break; + case 5: + handle_gmi(s, sf, rm, rn, rd); + break; case 8: /* LSLV */ handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd); break; From patchwork Fri Mar 13 14:00:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= X-Patchwork-Id: 1254410 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=remlab.net Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48f6q13K1hz9sSV for ; Sat, 14 Mar 2020 01:03:09 +1100 (AEDT) Received: from localhost ([::1]:59360 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCku3-0000k6-8T for incoming@patchwork.ozlabs.org; Fri, 13 Mar 2020 10:03:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42834) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCkrb-0005b2-B7 for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jCkrZ-00015j-PM for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:35 -0400 Received: from poy.remlab.net ([2001:41d0:2:5a1a::]:49726 helo=ns207790.ip-94-23-215.eu) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1jCkrV-0000do-KU; Fri, 13 Mar 2020 10:00:29 -0400 Received: from basile.remlab.net (ip6-localhost [IPv6:::1]) by ns207790.ip-94-23-215.eu (Postfix) with ESMTP id B2F3E5FD7F; Fri, 13 Mar 2020 15:00:24 +0100 (CET) From: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= To: qemu-arm@nongnu.org Subject: [PATCH 3/5] target/arm: MTE unprivileged system mode disassembly Date: Fri, 13 Mar 2020 16:00:21 +0200 Message-Id: <20200313140023.83844-3-remi@remlab.net> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:41d0:2:5a1a:: X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Rémi Denis-Courmont This adds the MTE instructions that conditionally available at EL0, but undefined in Linux user mode. Signed-off-by: Rémi Denis-Courmont --- target/arm/helper.c | 56 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index ed56198623..dd64fcb4ef 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6837,6 +6837,18 @@ static const ARMCPRegInfo dcpodp_reg[] = { .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn }, REGINFO_SENTINEL }; + +static const ARMCPRegInfo mte_dcpodp_reginfo[] = { + { .name = "DC_CGVADP", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 3, + .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END, + .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn }, + { .name = "DC_CGDVADP", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 5, + .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END, + .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn }, + REGINFO_SENTINEL +}; #endif /*CONFIG_USER_ONLY*/ static uint64_t tco_read(CPUARMState *env, const ARMCPRegInfo *ri) @@ -6856,10 +6868,44 @@ static void tco_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val) static const ARMCPRegInfo mte_reginfo[] = { { .name = "DC_GVA", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 3, - .access = PL0_W, .type = ARM_CP_NOP }, + .access = PL0_W, .type = ARM_CP_NOP, +#ifndef CONFIG_USER_ONLY + .accessfn = aa64_zva_access, +#endif + }, { .name = "DC_GZVA", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 4, - .access = PL0_W, .type = ARM_CP_DC_ZVA }, + .access = PL0_W, .type = ARM_CP_DC_ZVA, +#ifndef CONFIG_USER_ONLY + .accessfn = aa64_zva_access, +#endif + }, + { .name = "DC_CGVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 3, + .access = PL0_W, .type = ARM_CP_NOP, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CGDVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 5, + .access = PL0_W, .type = ARM_CP_NOP, + .accessfn = aa64_cacheop_poc_access }, +#ifndef CONFIG_USER_ONLY + { .name = "DC_CGVAP", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 3, + .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END, + .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn }, + { .name = "DC_CGDVAP", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 5, + .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END, + .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn }, +#endif + { .name = "DC_CIGVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 3, + .access = PL0_W, .type = ARM_CP_NOP, + .accessfn = aa64_cacheop_poc_access }, + { .name = "DC_CIGDVAC", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 5, + .access = PL0_W, .type = ARM_CP_NOP, + .accessfn = aa64_cacheop_poc_access }, { .name = "TCO", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7, .access = PL0_RW, .type = ARM_CP_NO_RAW, @@ -7985,6 +8031,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) #endif /*CONFIG_USER_ONLY*/ if (cpu_isar_feature(aa64_mte, cpu)) { define_arm_cp_regs(cpu, mte_reginfo); + +#ifndef CONFIG_USER_ONLY + if (cpu_isar_feature(aa64_dcpodp, cpu)) { + define_one_arm_cp_reg(cpu, mte_dcpodp_reginfo); + } +#endif } #endif From patchwork Fri Mar 13 14:00:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= X-Patchwork-Id: 1254409 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=remlab.net Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48f6nB5C3Fz9sNg for ; Sat, 14 Mar 2020 01:01:33 +1100 (AEDT) Received: from localhost ([::1]:59326 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCksT-0006Gz-PZ for incoming@patchwork.ozlabs.org; Fri, 13 Mar 2020 10:01:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42843) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCkrb-0005bX-I9 for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jCkrZ-00015p-PH for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:35 -0400 Received: from poy.remlab.net ([2001:41d0:2:5a1a::]:49728 helo=ns207790.ip-94-23-215.eu) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1jCkrV-0000fY-K3; Fri, 13 Mar 2020 10:00:29 -0400 Received: from basile.remlab.net (ip6-localhost [IPv6:::1]) by ns207790.ip-94-23-215.eu (Postfix) with ESMTP id 0419B5FDA7; Fri, 13 Mar 2020 15:00:24 +0100 (CET) From: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= To: qemu-arm@nongnu.org Subject: [PATCH 4/5] target/arm: MTE privileged system mode assembly Date: Fri, 13 Mar 2020 16:00:22 +0200 Message-Id: <20200313140023.83844-4-remi@remlab.net> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:41d0:2:5a1a:: X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Rémi Denis-Courmont This adds all remaining MTE instructions for EL1, EL2 and EL3 on a processor with ID_AA64PFR1_EL1.MTE == 1. Signed-off-by: Rémi Denis-Courmont --- target/arm/cpu64.c | 8 +++--- target/arm/helper.c | 19 ++++++++++++++ target/arm/translate-a64.c | 52 +++++++++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index a72dfd3d98..749eb93872 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -665,13 +665,11 @@ static void aarch64_max_initfn(Object *obj) t = cpu->isar.id_aa64pfr1; t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); -#ifdef CONFIG_USER_ONLY - /* All MTE instructions and processor states are supported for user - * mode. This corresponds to feature field value 1 (field value 2 - * implies MemTag memory support). + /* All MTE instructions and processor states are supported. This + * corresponds to feature field value 1 (field value 2 implies MemTag + * memory support). */ t = FIELD_DP64(t, ID_AA64PFR1, MTE, 1); -#endif cpu->isar.id_aa64pfr1 = t; t = cpu->isar.id_aa64mmfr1; diff --git a/target/arm/helper.c b/target/arm/helper.c index dd64fcb4ef..630dc04302 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6906,10 +6906,29 @@ static const ARMCPRegInfo mte_reginfo[] = { .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 5, .access = PL0_W, .type = ARM_CP_NOP, .accessfn = aa64_cacheop_poc_access }, + { .name = "RGSR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 5, + .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, rgsr_el1) }, + { .name = "GCR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6, + .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, gcr_el1) }, { .name = "TCO", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7, .access = PL0_RW, .type = ARM_CP_NO_RAW, .readfn = tco_read, .writefn = tco_write }, + { .name = "TFSR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 6, .crm = 5, .opc2 = 0, + .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, tfsr_el[1]) }, + { .name = "TFSR_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 5, .opc2 = 0, + .access = PL2_RW, .type = ARM_CP_ALIAS, + .fieldoffset = offsetof(CPUARMState, tfsr_el[1]) }, + { .name = "TFSR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 6, .crm = 5, .opc2 = 0, + .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, tfsr_el[3]) }, + { .name = "TFSRE0_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 6, .crm = 6, .opc2 = 1, + .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, tfsre0_el1) }, REGINFO_SENTINEL }; #endif diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 6d86480043..9382f53794 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -2716,6 +2716,38 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn) tcg_temp_free_i64(clean_addr); } +#ifndef CONFIG_USER_ONLY +static void disas_ldst_memtag_vec(DisasContext *s, int rn, int rt, + bool is_load) +{ + TCGv_i64 tcg_addr; + + if (rn == rt) { + return; + } + + if (rn == 31) { + gen_check_sp_alignment(s); + } + + /* The starting point between the specified address and the aligned + * address is implementation defined. We start at the aligned address. + */ + tcg_addr = tcg_temp_new_i64(); + tcg_gen_andi_i64(tcg_addr, cpu_reg_sp(s, rn), + ~((16 * ARM_TAG_GRANULE) - 1)); + + /* In principles, memory access permissions should be checked here. */ + if (is_load) { + tcg_gen_movi_i64(cpu_reg(s, rt), 0); + } + + tcg_gen_addi_i64(cpu_reg_sp(s, rn), tcg_addr, 16 * ARM_TAG_GRANULE); + + tcg_temp_free_i64(tcg_addr); +} +#endif + /* LDG, LDGV(EL1), ST(Z)(2)G, STGV */ static void disas_ldst_memtag(DisasContext *s, uint32_t insn) { @@ -2736,9 +2768,23 @@ static void disas_ldst_memtag(DisasContext *s, uint32_t insn) return; } - if (op2 == 0 && opc != 1) { - unallocated_encoding(s); - return; + if (op2 == 0) { + switch (opc) { + case 1: + break; +#ifndef CONFIG_USER_ONLY + case 2: + case 3: + if (s->current_el > 0 && offset == 0) { + disas_ldst_memtag_vec(s, rn, rt, opc & 1); + return; + } +#endif + /* fall through */ + default: + unallocated_encoding(s); + return; + } } if (rn == 31) { From patchwork Fri Mar 13 14:00:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= X-Patchwork-Id: 1254411 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=remlab.net Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48f6qF64jBz9sNg for ; Sat, 14 Mar 2020 01:03:21 +1100 (AEDT) Received: from localhost ([::1]:59366 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCkuF-00012x-N3 for incoming@patchwork.ozlabs.org; Fri, 13 Mar 2020 10:03:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43027) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jCkrk-0005pN-0b for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jCkrh-0001S4-Pg for qemu-devel@nongnu.org; Fri, 13 Mar 2020 10:00:43 -0400 Received: from poy.remlab.net ([2001:41d0:2:5a1a::]:49730 helo=ns207790.ip-94-23-215.eu) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1jCkrV-0000go-KT; Fri, 13 Mar 2020 10:00:29 -0400 Received: from basile.remlab.net (ip6-localhost [IPv6:::1]) by ns207790.ip-94-23-215.eu (Postfix) with ESMTP id 4D9075FE21; Fri, 13 Mar 2020 15:00:25 +0100 (CET) From: =?utf-8?q?R=C3=A9mi_Denis-Courmont?= To: qemu-arm@nongnu.org Subject: [PATCH 5/5] target/arm: MTE tag check stubs Date: Fri, 13 Mar 2020 16:00:23 +0200 Message-Id: <20200313140023.83844-5-remi@remlab.net> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:41d0:2:5a1a:: X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Rémi Denis-Courmont This adds stub function calls for memory tag checking. Much like the SP alignment check stub, these do not have any effect and will be optimized at compilation time. Note: SVE tag checks are not included. Signed-off-by: Rémi Denis-Courmont --- target/arm/translate-a64.c | 88 +++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 9382f53794..769206106e 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -855,6 +855,17 @@ static void gen_deposit_tag(TCGv_i64 dest, TCGv_i64 source, TCGv_i64 tag) tcg_temp_free_i64(tmp); } +static void gen_check_tag_memidx(DisasContext *s, TCGv_i64 tcg_addr, int size, + bool iswrite, int mem_idx) +{ +} + +static void gen_check_tag(DisasContext *s, TCGv_i64 tcg_addr, int size, + bool iswrite) +{ + gen_check_tag_memidx(s, tcg_addr, size, iswrite, get_mem_index(s)); +} + /* * Load/Store generators */ @@ -2404,13 +2415,16 @@ static void gen_compare_and_swap(DisasContext *s, int rs, int rt, { TCGv_i64 tcg_rs = cpu_reg(s, rs); TCGv_i64 tcg_rt = cpu_reg(s, rt); + TCGv_i64 tcg_rn = cpu_reg_sp(s, rn); int memidx = get_mem_index(s); TCGv_i64 clean_addr; if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, tcg_rn, size, true); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, tcg_rn); tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt, memidx, size | MO_ALIGN | s->be_data); } @@ -2422,13 +2436,16 @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt, TCGv_i64 s2 = cpu_reg(s, rs + 1); TCGv_i64 t1 = cpu_reg(s, rt); TCGv_i64 t2 = cpu_reg(s, rt + 1); + TCGv_i64 dirty_addr = cpu_reg_sp(s, rn); TCGv_i64 clean_addr; int memidx = get_mem_index(s); if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, dirty_addr, size, true); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, dirty_addr); if (size == 2) { TCGv_i64 cmp = tcg_temp_new_i64(); @@ -2542,27 +2559,33 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) int is_lasr = extract32(insn, 15, 1); int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr; int size = extract32(insn, 30, 2); - TCGv_i64 clean_addr; + TCGv_i64 dirty_addr, clean_addr; switch (o2_L_o1_o0) { case 0x0: /* STXR */ case 0x1: /* STLXR */ + dirty_addr = cpu_reg_sp(s, rn); if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, dirty_addr, size, true); } if (is_lasr) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, dirty_addr); gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, false); return; case 0x4: /* LDXR */ case 0x5: /* LDAXR */ + dirty_addr = cpu_reg_sp(s, rn); if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, dirty_addr, size, false); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, dirty_addr); s->is_ldex = true; gen_load_exclusive(s, rt, rt2, clean_addr, size, false); if (is_lasr) { @@ -2578,11 +2601,14 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) /* fall through */ case 0x9: /* STLR */ /* Generate ISS for non-exclusive accesses including LASR. */ + dirty_addr = cpu_reg_sp(s, rn); if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, dirty_addr, size, true); } tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, dirty_addr); do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr); return; @@ -2595,10 +2621,13 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) /* fall through */ case 0xd: /* LDAR */ /* Generate ISS for non-exclusive accesses including LASR. */ + dirty_addr = cpu_reg_sp(s, rn); if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, dirty_addr, size, false); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, dirty_addr); do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false, true, rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr); tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); @@ -2606,13 +2635,16 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) case 0x2: case 0x3: /* CASP / STXP */ if (size & 2) { /* STXP / STLXP */ + dirty_addr = cpu_reg_sp(s, rn); if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, dirty_addr, size, true); } if (is_lasr) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, dirty_addr); gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, true); return; } @@ -2627,10 +2659,13 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn) case 0x6: case 0x7: /* CASPA / LDXP */ if (size & 2) { /* LDXP / LDAXP */ + dirty_addr = cpu_reg_sp(s, rn); if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, dirty_addr, size, false); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, dirty_addr); s->is_ldex = true; gen_load_exclusive(s, rt, rt2, clean_addr, size, true); if (is_lasr) { @@ -2881,6 +2916,7 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) bool is_signed = false; bool postindex = false; bool wback = false; + bool memtag = false; TCGv_i64 clean_addr, dirty_addr; @@ -2902,6 +2938,7 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) return; } + memtag = true; size = 3; /* sic! */ } } @@ -2947,6 +2984,10 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) if (!postindex) { tcg_gen_addi_i64(dirty_addr, dirty_addr, offset); } + if (!memtag && rn != 31) { + /* Check both loads or stores, size is doubled */ + gen_check_tag(s, dirty_addr, size + 1, !is_load); + } clean_addr = clean_data_tbi(s, dirty_addr); if (is_vector) { @@ -3088,6 +3129,10 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, clean_addr = clean_data_tbi(s, dirty_addr); if (is_vector) { + if (rn != 31) { + gen_check_tag(s, dirty_addr, size, is_store); + } + if (is_store) { do_fp_st(s, rt, clean_addr, size); } else { @@ -3098,6 +3143,10 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, int memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s); bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc); + if (rn != 31) { + gen_check_tag_memidx(s, dirty_addr, size, is_store, memidx); + } + if (is_store) { do_gpr_st_memidx(s, tcg_rt, clean_addr, size, memidx, iss_valid, rt, iss_sf, false); @@ -3192,6 +3241,9 @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn, ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0); tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm); + if (rn != 31) { + gen_check_tag(s, dirty_addr, size, is_store); + } clean_addr = clean_data_tbi(s, dirty_addr); if (is_vector) { @@ -3277,6 +3329,9 @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn, dirty_addr = read_cpu_reg_sp(s, rn, 1); offset = imm12 << size; tcg_gen_addi_i64(dirty_addr, dirty_addr, offset); + if (rn != 31) { + gen_check_tag(s, dirty_addr, size, is_store); + } clean_addr = clean_data_tbi(s, dirty_addr); if (is_vector) { @@ -3320,7 +3375,7 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn, int o3_opc = extract32(insn, 12, 4); bool r = extract32(insn, 22, 1); bool a = extract32(insn, 23, 1); - TCGv_i64 tcg_rs, clean_addr; + TCGv_i64 tcg_rs, dirty_addr, clean_addr; AtomicThreeOpFn *fn; if (is_vector || !dc_isar_feature(aa64_atomics, s)) { @@ -3367,10 +3422,14 @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn, return; } + dirty_addr = cpu_reg_sp(s, rn); + if (rn == 31) { gen_check_sp_alignment(s); + } else { + gen_check_tag(s, dirty_addr, size, true); } - clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn)); + clean_addr = clean_data_tbi(s, dirty_addr); if (o3_opc == 014) { /* @@ -3446,6 +3505,7 @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn, offset = sextract32(offset << size, 0, 10 + size); tcg_gen_addi_i64(dirty_addr, dirty_addr, offset); + gen_check_tag(s, dirty_addr, size, false); /* Note that "clean" and "dirty" here refer to TBI not PAC. */ clean_addr = clean_data_tbi(s, dirty_addr); @@ -3689,6 +3749,9 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) elements = (is_q ? 16 : 8) / ebytes; tcg_rn = cpu_reg_sp(s, rn); + if (is_postidx || rn != 31) { + gen_check_tag(s, tcg_rn, size, is_store); + } clean_addr = clean_data_tbi(s, tcg_rn); tcg_ebytes = tcg_const_i64(ebytes); @@ -3832,6 +3895,9 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) } tcg_rn = cpu_reg_sp(s, rn); + if (is_postidx || rn != 31) { + gen_check_tag(s, tcg_rn, size, !is_load); + } clean_addr = clean_data_tbi(s, tcg_rn); tcg_ebytes = tcg_const_i64(ebytes);