lib: Emulate AMO instructions when Zaamo is not available

The AMO instructions are very critical for Linux so allow low-end
RISC-V implementations without Zaamo to boot Linux by emulating AMO
instructions using Zalrsc when OpenSBI is compiled without Zaamo.

Signed-off-by: Chao-ying Fu <cfu@mips.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250519121207.976949-1-apatel@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Chao-ying Fu
2025-05-19 17:42:06 +05:30
committed by Anup Patel
parent 017a161788
commit 8a3071222a
6 changed files with 709 additions and 18 deletions

View File

@@ -986,13 +986,14 @@
#define INSN_MATCH_VS4RV 0x62800027
#define INSN_MATCH_VS8RV 0xe2800027
#define INSN_MASK_VECTOR_LOAD_STORE 0x7f
#define INSN_MATCH_VECTOR_LOAD 0x07
#define INSN_MATCH_VECTOR_STORE 0x27
#define INSN_OPCODE_MASK 0x7f
#define INSN_OPCODE_VECTOR_LOAD 0x07
#define INSN_OPCODE_VECTOR_STORE 0x27
#define INSN_OPCODE_AMO 0x2f
#define IS_VECTOR_LOAD_STORE(insn) \
((((insn) & INSN_MASK_VECTOR_LOAD_STORE) == INSN_MATCH_VECTOR_LOAD) || \
(((insn) & INSN_MASK_VECTOR_LOAD_STORE) == INSN_MATCH_VECTOR_STORE))
((((insn) & INSN_OPCODE_MASK) == INSN_OPCODE_VECTOR_LOAD) || \
(((insn) & INSN_OPCODE_MASK) == INSN_OPCODE_VECTOR_STORE))
#define IS_VECTOR_INSN_MATCH(insn, match, mask) \
(((insn) & (mask)) == ((match) & (mask)))
@@ -1286,6 +1287,17 @@
#error "Unexpected __riscv_xlen"
#endif
#define MASK_FUNCT3 0x7000
#define SHIFT_FUNCT3 12
#define MASK_RS1 0xf8000
#define MASK_CSR 0xfff00000
#define SHIFT_CSR 20
#define MASK_AQRL 0x06000000
#define SHIFT_AQRL 25
#define VM_MASK 0x1
#define VIEW_MASK 0x3
#define VSEW_MASK 0x3
@@ -1353,10 +1365,11 @@
#define REG_PTR(insn, pos, regs) \
(ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
#define GET_RM(insn) ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
#define GET_FUNC3(insn) ((insn & MASK_FUNCT3) >> SHIFT_FUNCT3)
#define GET_RM(insn) GET_FUNC3(insn)
#define GET_RS1_NUM(insn) ((insn & MASK_RS1) >> 15)
#define GET_CSR_NUM(insn) ((insn & MASK_CSR) >> SHIFT_CSR)
#define GET_AQRL(insn) ((insn & MASK_AQRL) >> SHIFT_AQRL)
#define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
#define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
@@ -1381,13 +1394,6 @@
#define GET_VEMUL(vlmul, view, vsew) ((vlmul + view - vsew) & 7)
#define GET_EMUL(vemul) (1UL << ((vemul) >= 4 ? 0 : (vemul)))
#define MASK_FUNCT3 0x7000
#define MASK_RS1 0xf8000
#define MASK_CSR 0xfff00000
#define SHIFT_FUNCT3 12
#define SHIFT_CSR 20
#define CSRRW 1
#define CSRRS 2
#define CSRRC 3

View File

@@ -0,0 +1,17 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 MIPS
*
*/
#ifndef __SBI_ILLEGAL_ATOMIC_H__
#define __SBI_ILLEGAL_ATOMIC_H__
#include <sbi/sbi_types.h>
struct sbi_trap_regs;
int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs);
#endif

View File

@@ -14,6 +14,10 @@
struct sbi_trap_context;
typedef int (*illegal_insn_func)(ulong insn, struct sbi_trap_regs *regs);
int truly_illegal_insn(ulong insn, struct sbi_trap_regs *regs);
int sbi_illegal_insn_handler(struct sbi_trap_context *tcntx);
#endif