diff options
author | Wojciech Muła <wojciech_mula@poczta.onet.pl> | 2024-04-24 06:58:59 +0200 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2024-05-20 18:37:48 -0700 |
commit | ab24ff26666e14b3b6c4a8c8bb2c209d2587bb3e (patch) | |
tree | 98780651ffcc8ea390e77bce5869983f31be5ab4 /pk/syscall.c | |
parent | 86ed1b3b062bc81c2f42d6676a71cfba52880915 (diff) | |
download | riscv-pk-ab24ff26666e14b3b6c4a8c8bb2c209d2587bb3e.zip riscv-pk-ab24ff26666e14b3b6c4a8c8bb2c209d2587bb3e.tar.gz riscv-pk-ab24ff26666e14b3b6c4a8c8bb2c209d2587bb3e.tar.bz2 |
Implementation of riscv_hwprobe syscall from Linux (#325)
See: https://www.kernel.org/doc/html/latest/arch/riscv/hwprobe.html
Diffstat (limited to 'pk/syscall.c')
-rw-r--r-- | pk/syscall.c | 51 |
1 files changed, 51 insertions, 0 deletions
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 <stdint.h> #include <string.h> #include <errno.h> @@ -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[] = { |