If the ZBB extension (Basic Bitops) would be available, then we could use more performant bitop routines. However, we would have to discover and enable them, which makes things more complicated.
Hence, emulate those routines in C for the moment. Signed-off-by: Ralf Ramsauer <[email protected]> [since v1: Improve comments] --- hypervisor/arch/riscv/include/asm/bitops.h | 54 ++++++++++++++++++---- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/hypervisor/arch/riscv/include/asm/bitops.h b/hypervisor/arch/riscv/include/asm/bitops.h index 4b7e31b1..eb1861b7 100644 --- a/hypervisor/arch/riscv/include/asm/bitops.h +++ b/hypervisor/arch/riscv/include/asm/bitops.h @@ -2,9 +2,11 @@ * Jailhouse, a Linux-based partitioning hypervisor * * Copyright (c) Siemens AG, 2020 + * Copyright (c) OTH Regensburg, 2022 * * Authors: - * Jan Kiszka <[email protected]> + * Konrad Schwarz <[email protected]> + * Ralf Ramsauer <[email protected]> * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. @@ -13,25 +15,61 @@ #ifndef _JAILHOUSE_ASM_BITOPS_H #define _JAILHOUSE_ASM_BITOPS_H +/* This routine is shared with arm-common */ static inline __attribute__((always_inline)) int test_bit(unsigned int nr, const volatile unsigned long *addr) { - return 0; + return ((1UL << (nr % BITS_PER_LONG)) & + (addr[nr / BITS_PER_LONG])) != 0; } -static inline int atomic_test_and_set_bit(int nr, volatile unsigned long *addr) +static inline long unsigned atomic_test_and_set_bit(int nr, volatile unsigned long *addr) { - return 0; + unsigned long res, mask; + + mask = 1UL << (nr % BITS_PER_LONG); + asm volatile("amoor.w.aqrl %0, %2, %1" + : "=r"(res), "+A"(addr[nr / BITS_PER_LONG]) + : "r" (mask) + : "memory"); + + return (res & mask) != 0; } -static inline unsigned long ffzl(unsigned long word) +/* + * Note: the RISC-V Bit Manipulation standard extension will undoubtedly have + * more performant implementations of these routines Returns the position of + * the least significant 1, MSB=31, LSB=0. + * CAUTION: in contrast to POSIX ffs(), LSB = 0 + */ +static inline unsigned long ffsl(unsigned long word) { - return 0; + register int result; + + if (!word) + return BITS_PER_LONG; + result = BITS_PER_LONG - 1; + + word = (word - 1) ^ word; + /* + * word now contains 0s followed by n 1s, if + * n - 1 was the least significant set bit + */ + + while (0 <= (long) word) { + word <<= 1; + --result; + } + return result; } -static inline unsigned long ffsl(unsigned long word) +/* + * Returns the position of the least significant 0, MSB=31, LSB=0 + * CAUTION: in contrast to the POSIX ffs(), LSB = 0 + */ +static inline unsigned long ffzl (register unsigned long word) { - return 0; + return ffsl(~word); } #endif /* !_JAILHOUSE_ASM_BITOPS_H */ -- 2.40.1 -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/jailhouse-dev/20230519204033.643200-27-ralf.ramsauer%40oth-regensburg.de.
