aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojciech Muła <wojciech_mula@poczta.onet.pl>2024-04-24 06:58:59 +0200
committerAndrew Waterman <andrew@sifive.com>2024-05-20 18:37:48 -0700
commitab24ff26666e14b3b6c4a8c8bb2c209d2587bb3e (patch)
tree98780651ffcc8ea390e77bce5869983f31be5ab4
parent86ed1b3b062bc81c2f42d6676a71cfba52880915 (diff)
downloadriscv-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
-rw-r--r--machine/minit.c2
-rw-r--r--machine/mtrap.h1
-rw-r--r--pk/syscall.c51
-rw-r--r--pk/syscall.h1
4 files changed, 55 insertions, 0 deletions
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 <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[] = {
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