From ab24ff26666e14b3b6c4a8c8bb2c209d2587bb3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Mu=C5=82a?= Date: Wed, 24 Apr 2024 06:58:59 +0200 Subject: Implementation of riscv_hwprobe syscall from Linux (#325) See: https://www.kernel.org/doc/html/latest/arch/riscv/hwprobe.html --- machine/minit.c | 2 ++ machine/mtrap.h | 1 + pk/syscall.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ pk/syscall.h | 1 + 4 files changed, 55 insertions(+) diff --git a/machine/minit.c b/machine/minit.c index 95ddaa1..55f50cb 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -17,6 +17,7 @@ uintptr_t mem_size; volatile uint64_t* mtime; volatile uint32_t* plic_priorities; +uint64_t misa_image; size_t plic_ndevs; void* kernel_start; void* kernel_end; @@ -126,6 +127,7 @@ static void memory_init() static void hart_init() { + misa_image = read_csr(misa); mstatus_init(); fp_init(); #ifndef BBL_BOOT_MACHINE diff --git a/machine/mtrap.h b/machine/mtrap.h index 2f2e499..41071f3 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -35,6 +35,7 @@ extern uintptr_t mem_size; extern volatile uint64_t* mtime; extern volatile uint32_t* plic_priorities; extern size_t plic_ndevs; +extern uint64_t misa_image; typedef struct { volatile uint32_t* ipi; diff --git a/pk/syscall.c b/pk/syscall.c index 3dd0bf7..dc0d35f 100644 --- a/pk/syscall.c +++ b/pk/syscall.c @@ -8,6 +8,7 @@ #include "mmap.h" #include "boot.h" #include "usermem.h" +#include #include #include @@ -662,6 +663,55 @@ int sys_getdents(int fd, void* dirbuf, int count) return 0; //stub } +// Partial implementation on riscv_hwprobe from Linux +// See: https://www.kernel.org/doc/html/latest/arch/riscv/hwprobe.html + +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 +#define RISCV_HWPROBE_IMA_FD (1 << 0) +#define RISCV_HWPROBE_IMA_C (1 << 1) +#define RISCV_HWPROBE_IMA_V (1 << 2) +#define RISCV_HWPROBE_EXT_ZBA (1 << 3) +#define RISCV_HWPROBE_EXT_ZBB (1 << 4) +#define RISCV_HWPROBE_EXT_ZBS (1 << 5) +#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6) + +struct riscv_hwprobe { + int64_t key; + uint64_t value; +}; + +long sys_riscv_hwprobe(struct riscv_hwprobe* probes, size_t count, size_t reserved_cpusetsize, void* reserved_cpuset, unsigned int reserved_flags) +{ + if ((reserved_cpusetsize != 0) || (reserved_cpuset != NULL) || (reserved_flags != 0)) { + return -EBADF; + } + + for (size_t i=0; i < count; i++) { + struct riscv_hwprobe kv; + memcpy_from_user(&kv, &probes[i], sizeof(kv)); + + if (kv.key == RISCV_HWPROBE_KEY_IMA_EXT_0) { + kv.value = 0; + #define supports_extension(letter) (misa_image & (1 << (letter - 'A'))) + + if (supports_extension('C')) + kv.value |= RISCV_HWPROBE_IMA_C; + if (supports_extension('V')) + kv.value |= RISCV_HWPROBE_IMA_V; + + #undef supports_extension + } else { + // "If a key is unknown to the kernel, its key field will be cleared to -1, and its value set to 0" + kv.key = -1; + kv.value = 0; + } + + memcpy_to_user(&probes[i], &kv, sizeof(kv)); + } + + return 0; +} + static int sys_stub_success() { return 0; @@ -719,6 +769,7 @@ long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, unsigned l [SYS_chdir] = sys_chdir, [SYS_readlinkat] = sys_readlinkat, [SYS_readv] = sys_readv, + [SYS_riscv_hwprobe] = sys_riscv_hwprobe, }; const static void* old_syscall_table[] = { diff --git a/pk/syscall.h b/pk/syscall.h index 6731edd..2d430fa 100644 --- a/pk/syscall.h +++ b/pk/syscall.h @@ -59,6 +59,7 @@ #define SYS_madvise 233 #define SYS_statx 291 #define SYS_readv 65 +#define SYS_riscv_hwprobe 258 #define OLD_SYSCALL_THRESHOLD 1024 #define SYS_open 1024 -- cgit v1.1