Re: [PATCH v3 1/5] LoongArch: Define instruction formats for AM{SWAP/ADD}.{B/H} and DBAR
From: Hengqi Chen
Date: Tue Apr 14 2026 - 22:27:08 EST
On Mon, Apr 13, 2026 at 12:05 PM Tiezhu Yang <yangtiezhu@xxxxxxxxxxx> wrote:
>
> The 8 and 16 bit read-modify-write atomic instructions amadd.{b/h} and
> amswap.{b/h} were newly added in the latest LoongArch Reference Manual,
> define the instruction format and check whether support via cpucfg.
>
> Furthermore, define the instruction format for DBAR which will be used
> to support BPF load-acquire and store-release instructions.
>
> This is preparation for later patch.
>
> Signed-off-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>
> ---
Acked-by: Hengqi Chen <hengqi.chen@xxxxxxxxx>
> arch/loongarch/include/asm/cpu-features.h | 1 +
> arch/loongarch/include/asm/cpu.h | 2 ++
> arch/loongarch/include/asm/inst.h | 10 ++++++++++
> arch/loongarch/include/uapi/asm/hwcap.h | 1 +
> arch/loongarch/kernel/cpu-probe.c | 4 ++++
> arch/loongarch/kernel/proc.c | 2 ++
> 6 files changed, 20 insertions(+)
>
> diff --git a/arch/loongarch/include/asm/cpu-features.h b/arch/loongarch/include/asm/cpu-features.h
> index 8eefe7a2098b..f9d3188accfc 100644
> --- a/arch/loongarch/include/asm/cpu-features.h
> +++ b/arch/loongarch/include/asm/cpu-features.h
> @@ -68,5 +68,6 @@
> #define cpu_has_msgint cpu_opt(LOONGARCH_CPU_MSGINT)
> #define cpu_has_avecint cpu_opt(LOONGARCH_CPU_AVECINT)
> #define cpu_has_redirectint cpu_opt(LOONGARCH_CPU_REDIRECTINT)
> +#define cpu_has_lam_bh cpu_opt(LOONGARCH_CPU_LAM_BH)
>
> #endif /* __ASM_CPU_FEATURES_H */
> diff --git a/arch/loongarch/include/asm/cpu.h b/arch/loongarch/include/asm/cpu.h
> index 1e60ab264cd0..b423b1f41145 100644
> --- a/arch/loongarch/include/asm/cpu.h
> +++ b/arch/loongarch/include/asm/cpu.h
> @@ -126,6 +126,7 @@ static inline char *id_to_core_name(unsigned int id)
> #define CPU_FEATURE_MSGINT 30 /* CPU has MSG interrupt */
> #define CPU_FEATURE_AVECINT 31 /* CPU has AVEC interrupt */
> #define CPU_FEATURE_REDIRECTINT 32 /* CPU has interrupt remapping */
> +#define CPU_FEATURE_LAM_BH 33 /* CPU has AM{SWAP/ADD}[_DB].{B/H} instructions */
>
> #define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG)
> #define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM)
> @@ -160,5 +161,6 @@ static inline char *id_to_core_name(unsigned int id)
> #define LOONGARCH_CPU_MSGINT BIT_ULL(CPU_FEATURE_MSGINT)
> #define LOONGARCH_CPU_AVECINT BIT_ULL(CPU_FEATURE_AVECINT)
> #define LOONGARCH_CPU_REDIRECTINT BIT_ULL(CPU_FEATURE_REDIRECTINT)
> +#define LOONGARCH_CPU_LAM_BH BIT_ULL(CPU_FEATURE_LAM_BH)
>
> #endif /* _ASM_CPU_H */
> diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
> index f9f207082d0e..76b723590023 100644
> --- a/arch/loongarch/include/asm/inst.h
> +++ b/arch/loongarch/include/asm/inst.h
> @@ -36,6 +36,7 @@
>
> enum reg0i15_op {
> break_op = 0x54,
> + dbar_op = 0x70e4,
> };
>
> enum reg0i26_op {
> @@ -194,6 +195,10 @@ enum reg3_op {
> fstxs_op = 0x7070,
> fstxd_op = 0x7078,
> scq_op = 0x70ae,
> + amswapb_op = 0x70b8,
> + amswaph_op = 0x70b9,
> + amaddb_op = 0x70ba,
> + amaddh_op = 0x70bb,
> amswapw_op = 0x70c0,
> amswapd_op = 0x70c1,
> amaddw_op = 0x70c2,
> @@ -543,6 +548,7 @@ static inline void emit_##NAME(union loongarch_instruction *insn, \
> }
>
> DEF_EMIT_REG0I15_FORMAT(break, break_op)
> +DEF_EMIT_REG0I15_FORMAT(dbar, dbar_op)
>
> /* like emit_break(imm) but returns a constant expression */
> #define __emit_break(imm) ((u32)((imm) | (break_op << 15)))
> @@ -763,6 +769,8 @@ DEF_EMIT_REG3_FORMAT(stxb, stxb_op)
> DEF_EMIT_REG3_FORMAT(stxh, stxh_op)
> DEF_EMIT_REG3_FORMAT(stxw, stxw_op)
> DEF_EMIT_REG3_FORMAT(stxd, stxd_op)
> +DEF_EMIT_REG3_FORMAT(amaddb, amaddb_op)
> +DEF_EMIT_REG3_FORMAT(amaddh, amaddh_op)
> DEF_EMIT_REG3_FORMAT(amaddw, amaddw_op)
> DEF_EMIT_REG3_FORMAT(amaddd, amaddd_op)
> DEF_EMIT_REG3_FORMAT(amandw, amandw_op)
> @@ -771,6 +779,8 @@ DEF_EMIT_REG3_FORMAT(amorw, amorw_op)
> DEF_EMIT_REG3_FORMAT(amord, amord_op)
> DEF_EMIT_REG3_FORMAT(amxorw, amxorw_op)
> DEF_EMIT_REG3_FORMAT(amxord, amxord_op)
> +DEF_EMIT_REG3_FORMAT(amswapb, amswapb_op)
> +DEF_EMIT_REG3_FORMAT(amswaph, amswaph_op)
> DEF_EMIT_REG3_FORMAT(amswapw, amswapw_op)
> DEF_EMIT_REG3_FORMAT(amswapd, amswapd_op)
>
> diff --git a/arch/loongarch/include/uapi/asm/hwcap.h b/arch/loongarch/include/uapi/asm/hwcap.h
> index 49519b4362c6..90e96113ba51 100644
> --- a/arch/loongarch/include/uapi/asm/hwcap.h
> +++ b/arch/loongarch/include/uapi/asm/hwcap.h
> @@ -19,5 +19,6 @@
> #define HWCAP_LOONGARCH_PTW (1 << 13)
> #define HWCAP_LOONGARCH_LSPW (1 << 14)
> #define HWCAP_LOONGARCH_SCQ (1 << 15)
> +#define HWCAP_LOONGARCH_LAM_BH (1 << 16)
>
> #endif /* _UAPI_ASM_HWCAP_H */
> diff --git a/arch/loongarch/kernel/cpu-probe.c b/arch/loongarch/kernel/cpu-probe.c
> index 657bbae6c1c7..93466fc7d33d 100644
> --- a/arch/loongarch/kernel/cpu-probe.c
> +++ b/arch/loongarch/kernel/cpu-probe.c
> @@ -177,6 +177,10 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
> c->options |= LOONGARCH_CPU_LAM;
> elf_hwcap |= HWCAP_LOONGARCH_LAM;
> }
> + if (config & CPUCFG2_LAM_BH) {
> + c->options |= LOONGARCH_CPU_LAM_BH;
> + elf_hwcap |= HWCAP_LOONGARCH_LAM_BH;
> + }
> if (config & CPUCFG2_SCQ) {
> c->options |= LOONGARCH_CPU_SCQ;
> elf_hwcap |= HWCAP_LOONGARCH_SCQ;
> diff --git a/arch/loongarch/kernel/proc.c b/arch/loongarch/kernel/proc.c
> index a8127e83da65..d4ce5b585453 100644
> --- a/arch/loongarch/kernel/proc.c
> +++ b/arch/loongarch/kernel/proc.c
> @@ -64,6 +64,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
> seq_puts(m, " cpucfg");
> if (cpu_has_lam)
> seq_puts(m, " lam");
> + if (cpu_has_lam_bh)
> + seq_puts(m, " lam_bh");
> if (cpu_has_scq)
> seq_puts(m, " scq");
> if (cpu_has_ual)
> --
> 2.42.0
>