aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremiah Griffin <jzgriffin@google.com>2024-05-01 15:53:57 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-05-01 15:53:57 +0000
commit07b7c15db5bf1e8d708331b32ed325353e2fac28 (patch)
tree81430dbd58cc7bf182f1919306652e5249b7fbc4
parent09fc54a7b8ae1f3aa3019fcc87756f6f99395cc0 (diff)
parent9934caf97a2d6244827a376312797bf6ef39ad62 (diff)
downloadbinary_translation-07b7c15db5bf1e8d708331b32ed325353e2fac28.tar.gz
Merge "kernel_api: Implement riscv_hwprobe" into main
-rw-r--r--kernel_api/riscv64/gen_syscall_emulation_riscv64_to_x86_64-inl.h3
-rw-r--r--kernel_api/riscv64/guest_types.h34
-rw-r--r--kernel_api/riscv64/syscall_emulation.cc54
-rw-r--r--kernel_api/tools/custom_syscalls.json6
4 files changed, 97 insertions, 0 deletions
diff --git a/kernel_api/riscv64/gen_syscall_emulation_riscv64_to_x86_64-inl.h b/kernel_api/riscv64/gen_syscall_emulation_riscv64_to_x86_64-inl.h
index 5c9ba7b4..4e241a15 100644
--- a/kernel_api/riscv64/gen_syscall_emulation_riscv64_to_x86_64-inl.h
+++ b/kernel_api/riscv64/gen_syscall_emulation_riscv64_to_x86_64-inl.h
@@ -524,6 +524,9 @@ long RunGuestSyscallImpl(long guest_nr,
case 259: // __NR_riscv_flush_icache
// missing on x86_64
return RunGuestSyscall___NR_riscv_flush_icache(arg_1, arg_2, arg_3);
+ case 258: // __NR_riscv_hwprobe
+ // missing on x86_64
+ return RunGuestSyscall___NR_riscv_hwprobe(arg_1, arg_2, arg_3, arg_4, arg_5);
case 293: // __NR_rseq
// missing prototype
KAPI_TRACE("unsupported syscall __NR_rseq");
diff --git a/kernel_api/riscv64/guest_types.h b/kernel_api/riscv64/guest_types.h
index 6fe7e810..55faefe1 100644
--- a/kernel_api/riscv64/guest_types.h
+++ b/kernel_api/riscv64/guest_types.h
@@ -107,6 +107,40 @@ CHECK_FIELD_LAYOUT(Guest_stat, st_atim, 576, 128);
CHECK_FIELD_LAYOUT(Guest_stat, st_mtim, 704, 128);
CHECK_FIELD_LAYOUT(Guest_stat, st_ctim, 832, 128);
+struct Guest_riscv_hwprobe {
+ int64_t key;
+ uint64_t value;
+};
+
+CHECK_STRUCT_LAYOUT(Guest_riscv_hwprobe, 128, 64);
+CHECK_FIELD_LAYOUT(Guest_riscv_hwprobe, key, 0, 64);
+CHECK_FIELD_LAYOUT(Guest_riscv_hwprobe, value, 64, 64);
+
+// Each RISCV_HWPROBE_KEY_* represents a capability key. These constants are sorted
+// such that each capability key appears in numeric order, followed by the possible
+// values for that key in numeric order.
+// clang-format off
+#define RISCV_HWPROBE_KEY_MVENDORID 0
+#define RISCV_HWPROBE_KEY_MARCHID 1
+#define RISCV_HWPROBE_KEY_MIMPID 2
+#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3
+#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0)
+#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_KEY_CPUPERF_0 5
+#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
+#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
+#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)
+#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
+#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
+#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
+// clang-format on
+
} // namespace berberis
#endif // BERBERIS_KERNEL_API_RISCV64_GUEST_TYPES_ARCH_H_
diff --git a/kernel_api/riscv64/syscall_emulation.cc b/kernel_api/riscv64/syscall_emulation.cc
index 0a56a728..f9ad1388 100644
--- a/kernel_api/riscv64/syscall_emulation.cc
+++ b/kernel_api/riscv64/syscall_emulation.cc
@@ -15,8 +15,10 @@
*/
#include <fcntl.h> // AT_FDCWD, AT_SYMLINK_NOFOLLOW
+#include <linux/sched.h>
#include <linux/unistd.h>
#include <sys/stat.h>
+#include <sys/sysinfo.h>
#include <sys/types.h>
#include <cerrno>
@@ -65,6 +67,35 @@ int FstatatForGuest(int dirfd, const char* path, struct stat* buf, int flags) {
return syscall(__NR_newfstatat, dirfd, real_path ? real_path : path, buf, flags);
}
+void Hwprobe(Guest_riscv_hwprobe& pair) {
+ switch (pair.key) {
+ case RISCV_HWPROBE_KEY_MVENDORID:
+ pair.value = 0;
+ break;
+ case RISCV_HWPROBE_KEY_MARCHID:
+ pair.value = 0;
+ break;
+ case RISCV_HWPROBE_KEY_MIMPID:
+ pair.value = 0;
+ break;
+ case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:
+ pair.value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA;
+ break;
+ case RISCV_HWPROBE_KEY_IMA_EXT_0:
+ pair.value = RISCV_HWPROBE_IMA_FD | RISCV_HWPROBE_IMA_C | RISCV_HWPROBE_IMA_V |
+ RISCV_HWPROBE_EXT_ZBA | RISCV_HWPROBE_EXT_ZBB | RISCV_HWPROBE_EXT_ZBS;
+ break;
+ case RISCV_HWPROBE_KEY_CPUPERF_0:
+ pair.value = RISCV_HWPROBE_MISALIGNED_FAST;
+ break;
+ default:
+ TRACE("unsupported __riscv_hwprobe capability key: %ld", pair.key);
+ pair.key = -1;
+ pair.value = 0;
+ break;
+ }
+}
+
long RunGuestSyscall___NR_execveat(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) {
UNUSED(arg_1, arg_2, arg_3, arg_4, arg_5);
KAPI_TRACE("unimplemented syscall __NR_execveat");
@@ -104,6 +135,29 @@ long RunGuestSyscall___NR_newfstatat(long arg_1, long arg_2, long arg_3, long ar
return result;
}
+long RunGuestSyscall___NR_riscv_hwprobe(long arg_1,
+ long arg_2,
+ long arg_3,
+ long arg_4,
+ long arg_5) {
+ UNUSED(arg_3, arg_4); // cpu_count, cpus_in
+
+ // There are currently no flags defined by the kernel. This may change in the future.
+ static constexpr unsigned int kFlagsAll = 0;
+
+ auto pairs = bit_cast<Guest_riscv_hwprobe*>(arg_1);
+ auto pair_count = bit_cast<size_t>(arg_2);
+ auto flags = static_cast<unsigned int>(bit_cast<unsigned long>(arg_5));
+ if ((flags & ~kFlagsAll) != 0) {
+ return -EINVAL;
+ }
+
+ for (size_t i = 0; i < pair_count; ++i) {
+ Hwprobe(pairs[i]);
+ }
+ return 0;
+}
+
long RunGuestSyscall___NR_riscv_flush_icache(long arg_1, long arg_2, long arg_3) {
static constexpr uint64_t kFlagsLocal = 1UL;
static constexpr uint64_t kFlagsAll = kFlagsLocal;
diff --git a/kernel_api/tools/custom_syscalls.json b/kernel_api/tools/custom_syscalls.json
index 356e80c4..b91ecce0 100644
--- a/kernel_api/tools/custom_syscalls.json
+++ b/kernel_api/tools/custom_syscalls.json
@@ -201,6 +201,12 @@
"params": ["void*", "void*", "int32"]
}
},
+ "__NR_riscv_hwprobe": {
+ "riscv64": {
+ "id": "258",
+ "params": ["struct riscv_hwprobe*", "size_t", "size_t", "unsigned long*", "unsigned int"]
+ }
+ },
"__NR_rt_sigaction": {
"custom_reason": "changes signal action"
},