|
8 | 8 | #include "mmap.h" |
9 | 9 | #include "boot.h" |
10 | 10 | #include "usermem.h" |
| 11 | +#include <stdint.h> |
11 | 12 | #include <string.h> |
12 | 13 | #include <errno.h> |
13 | 14 |
|
@@ -662,6 +663,55 @@ int sys_getdents(int fd, void* dirbuf, int count) |
662 | 663 | return 0; //stub |
663 | 664 | } |
664 | 665 |
|
| 666 | +// Partial implementation on riscv_hwprobe from Linux |
| 667 | +// See: https://www.kernel.org/doc/html/latest/arch/riscv/hwprobe.html |
| 668 | + |
| 669 | +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 |
| 670 | +#define RISCV_HWPROBE_IMA_FD (1 << 0) |
| 671 | +#define RISCV_HWPROBE_IMA_C (1 << 1) |
| 672 | +#define RISCV_HWPROBE_IMA_V (1 << 2) |
| 673 | +#define RISCV_HWPROBE_EXT_ZBA (1 << 3) |
| 674 | +#define RISCV_HWPROBE_EXT_ZBB (1 << 4) |
| 675 | +#define RISCV_HWPROBE_EXT_ZBS (1 << 5) |
| 676 | +#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6) |
| 677 | + |
| 678 | +struct riscv_hwprobe { |
| 679 | + int64_t key; |
| 680 | + uint64_t value; |
| 681 | +}; |
| 682 | + |
| 683 | +long sys_riscv_hwprobe(struct riscv_hwprobe* probes, size_t count, size_t reserved_cpusetsize, void* reserved_cpuset, unsigned int reserved_flags) |
| 684 | +{ |
| 685 | + if ((reserved_cpusetsize != 0) || (reserved_cpuset != NULL) || (reserved_flags != 0)) { |
| 686 | + return -EBADF; |
| 687 | + } |
| 688 | + |
| 689 | + for (size_t i=0; i < count; i++) { |
| 690 | + struct riscv_hwprobe kv; |
| 691 | + memcpy_from_user(&kv, &probes[i], sizeof(kv)); |
| 692 | + |
| 693 | + if (kv.key == RISCV_HWPROBE_KEY_IMA_EXT_0) { |
| 694 | + kv.value = 0; |
| 695 | + #define supports_extension(letter) (misa_image & (1 << (letter - 'A'))) |
| 696 | + |
| 697 | + if (supports_extension('C')) |
| 698 | + kv.value |= RISCV_HWPROBE_IMA_C; |
| 699 | + if (supports_extension('V')) |
| 700 | + kv.value |= RISCV_HWPROBE_IMA_V; |
| 701 | + |
| 702 | + #undef supports_extension |
| 703 | + } else { |
| 704 | + // "If a key is unknown to the kernel, its key field will be cleared to -1, and its value set to 0" |
| 705 | + kv.key = -1; |
| 706 | + kv.value = 0; |
| 707 | + } |
| 708 | + |
| 709 | + memcpy_to_user(&probes[i], &kv, sizeof(kv)); |
| 710 | + } |
| 711 | + |
| 712 | + return 0; |
| 713 | +} |
| 714 | + |
665 | 715 | static int sys_stub_success() |
666 | 716 | { |
667 | 717 | return 0; |
@@ -719,6 +769,7 @@ long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, unsigned l |
719 | 769 | [SYS_chdir] = sys_chdir, |
720 | 770 | [SYS_readlinkat] = sys_readlinkat, |
721 | 771 | [SYS_readv] = sys_readv, |
| 772 | + [SYS_riscv_hwprobe] = sys_riscv_hwprobe, |
722 | 773 | }; |
723 | 774 |
|
724 | 775 | const static void* old_syscall_table[] = { |
|
0 commit comments