Skip to content

Commit

Permalink
core-asm-riscv.h: support riscv zicboz ext cbo.zero instruction
Browse files Browse the repository at this point in the history
Zicboz is part of RISC-V CMO extension to support cache block based
instructions to manipulate clean, flush, inval, and zero etc. So far
only cbo.zero can be used for userspace, and this should provide a basic
capability to DCache.

Signed-off-by: Hsieh-Tseng Shen <woodrow.shen@sifive.com>
  • Loading branch information
woodrow-shen authored and ColinIanKing committed May 30, 2024
1 parent d47c0c3 commit 1af1862
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Makefile.config
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,7 @@ cpufeatures: \
ASM_RISCV_FENCE \
ASM_RISCV_FENCE_I \
ASM_RISCV_SFENCE_VMA \
ASM_RISCV_CBO_ZERO \
ASM_S390_PTLB \
ASM_SH4_RTE \
ASM_SH4_SLEEP \
Expand Down Expand Up @@ -1375,6 +1376,9 @@ ASM_RISCV_FENCE_I:
ASM_RISCV_SFENCE_VMA:
$(call check,test-asm-riscv-sfence-vma,HAVE_ASM_RISCV_SFENCE_VMA,RISC-V sfence.vma instruction)

ASM_RISCV_CBO_ZERO:
$(call check,test-asm-riscv-cbo_zero,HAVE_ASM_RISCV_CBO_ZERO,RISC-V cbo.zero instruction)

ASM_S390_PTLB:
$(call check,test-asm-s390-ptlb,HAVE_ASM_S390_PTLB,s390 ptlb instruction)

Expand Down
44 changes: 44 additions & 0 deletions core-asm-riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,38 @@
#include "core-arch.h"

#if defined(STRESS_ARCH_RISCV)
#define STRESS_ZICBOZ_CBO_ZERO (4)
#define STRESS_ZICBOZ_RS1 (10)
#define STRESS_ZICBOZ_FUNCT3 (2)
#define STRESS_ZICBOZ_OPCODE (15)

#if defined(__NR_riscv_hwprobe)
#include <asm/hwprobe.h>
#endif

#if defined(__BYTE_ORDER__) && \
defined(__ORDER_BIG_ENDIAN__)
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define __bswap32(x) ((uint32_t)__builtin_bswap32(x))
#else
#define __bswap32(x) (x)
#endif
#endif

#define MK_CBO(op) __bswap32((uint32_t)(op) << 20 | \
STRESS_ZICBOZ_RS1 << 15 | \
STRESS_ZICBOZ_FUNCT3 << 12 | \
0 << 7 | \
STRESS_ZICBOZ_OPCODE )

#define CBO_INSN(base, op) \
({ \
__asm__ __volatile__( \
"mv a0, %0\n" \
"li a1, %1\n" \
".4byte %2\n" \
: : "r" (base), "i" (op), "i" (MK_CBO(op)) : "a0", "a1", "memory"); \
})

static inline uint64_t ALWAYS_INLINE stress_asm_riscv_rdtime(void)
{
Expand Down Expand Up @@ -57,6 +89,18 @@ static inline void ALWAYS_INLINE stress_asm_riscv_pause(void)
__asm__ __volatile__ (".4byte 0x100000F");
}

/* cbo.zero instrution */
#if defined(HAVE_ASM_RISCV_CBO_ZERO)
static inline void ALWAYS_INLINE stress_asm_riscv_cbo_zero(char *addr)
{
__asm__ __volatile__(
"mv a0, %0\n"
"li a1, %1\n"
".4byte %2\n"
: : "r" (addr), "i" (STRESS_ZICBOZ_CBO_ZERO), "i" (MK_CBO(STRESS_ZICBOZ_CBO_ZERO)) : "a0", "a1", "memory");
}
#endif

/* #if defined(STRESS_ARCH_RISCV) */
#endif

Expand Down
83 changes: 83 additions & 0 deletions test/test-asm-riscv-cbo_zero.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2024 Woodrow Shen
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <stdint.h>
#include <sched.h>
#include <sys/syscall.h>
#include <unistd.h>
#if defined(__riscv) || \
defined(__riscv__)
#include <asm/hwprobe.h>
#endif

#if defined(__BYTE_ORDER__) && \
defined(__ORDER_BIG_ENDIAN__)
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define __bswap32(x) ((uint32_t)__builtin_bswap32(x))
#else
#define __bswap32(x) (x)
#endif
#endif

#define MK_CBO(op) __bswap32((uint32_t)(op) << 20 | 10 << 15 | 2 << 12 | 0 << 7 | 15)

#define CBO_INSN(base, op) \
({ \
asm volatile( \
"mv a0, %0\n" \
"li a1, %1\n" \
".4byte %2\n" \
: : "r" (base), "i" (op), "i" (MK_CBO(op)) : "a0", "a1", "memory"); \
})

static void cbo_zero(char *base) { CBO_INSN(base, 4); }

static char mem[4096] __attribute__((aligned(4096))) = { [0 ... 4095] = 0xaa };

#if defined(__riscv) || \
defined(__riscv__)
int main(void)
{
#if defined(HAVE_SYSCALL) && \
defined(__NR_riscv_hwprobe)
int ret;
struct riscv_hwprobe pair;
cpu_set_t cpus;

ret = sched_getaffinity(0, sizeof(cpu_set_t), &cpus);

pair.key = RISCV_HWPROBE_KEY_IMA_EXT_0;
ret = (int)syscall(__NR_riscv_hwprobe, &pair, 1, sizeof(cpu_set_t), &cpus, 0);

if (pair.value & RISCV_HWPROBE_EXT_ZICBOZ) {
uint64_t block_size;
pair.key = RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE;

ret = (int)syscall(__NR_riscv_hwprobe, &pair, 1, sizeof(cpu_set_t), &cpus, 0);
block_size = pair.value;

for (int i = 0; i < 4096 / block_size; ++i) {
cbo_zero(&mem[i * block_size]);
}
}
#endif
return 0;
}
#else
#error not RISC-V so no cbo.zero instruction
#endif

0 comments on commit 1af1862

Please sign in to comment.