summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShravan Narayan <shravanrn@gmail.com>2024-07-15 17:06:24 -0500
committerShravan Narayan <shravanrn@gmail.com>2024-09-06 16:48:31 -0500
commitc6853eb4857908072fd1d7c28dffb1d2613a0ee6 (patch)
tree78ef4f5369ee821c94aa643f7b82ebca726d6ad4 /src
parente3b16dae4166b138bbd04bbe67281f4fa47fd4de (diff)
downloadwabt-c6853eb4857908072fd1d7c28dffb1d2613a0ee6.tar.gz
wabt-c6853eb4857908072fd1d7c28dffb1d2613a0ee6.tar.bz2
wabt-c6853eb4857908072fd1d7c28dffb1d2613a0ee6.zip
wasm2c: Segue support for CPUs without wrgsbase instructions
Diffstat (limited to 'src')
-rw-r--r--src/c-writer.cc6
-rw-r--r--src/prebuilt/wasm2c_source_declarations.cc44
-rw-r--r--src/template/wasm2c.declarations.c28
3 files changed, 63 insertions, 15 deletions
diff --git a/src/c-writer.cc b/src/c-writer.cc
index 1a091957..986ace55 100644
--- a/src/c-writer.cc
+++ b/src/c-writer.cc
@@ -2449,17 +2449,17 @@ bool CWriter::IsSingleUnsharedMemory() {
void CWriter::InstallSegueBase(Memory* memory, bool save_old_value) {
NonIndented([&] { Write("#if WASM_RT_USE_SEGUE", Newline()); });
if (save_old_value) {
- Write("uintptr_t segue_saved_base = WASM_RT_SEGUE_READ_BASE();", Newline());
+ Write("void* segue_saved_base = wasm_rt_segue_read_base();", Newline());
}
auto primary_memory =
ExternalInstanceRef(ModuleFieldType::Memory, memory->name);
- Write("WASM_RT_SEGUE_WRITE_BASE(", primary_memory, ".data);", Newline());
+ Write("wasm_rt_segue_write_base(", primary_memory, ".data);", Newline());
NonIndented([&] { Write("#endif", Newline()); });
}
void CWriter::RestoreSegueBase() {
NonIndented([&] { Write("#if WASM_RT_USE_SEGUE", Newline()); });
- Write("WASM_RT_SEGUE_WRITE_BASE(segue_saved_base);", Newline());
+ Write("wasm_rt_segue_write_base(segue_saved_base);", Newline());
NonIndented([&] { Write("#endif", Newline()); });
}
diff --git a/src/prebuilt/wasm2c_source_declarations.cc b/src/prebuilt/wasm2c_source_declarations.cc
index 11aac524..000b25c8 100644
--- a/src/prebuilt/wasm2c_source_declarations.cc
+++ b/src/prebuilt/wasm2c_source_declarations.cc
@@ -64,15 +64,25 @@ R"w2c_template(// "address namespaces". GCC does not support the memcpy requ
)w2c_template"
R"w2c_template(// this leaves only clang for now.
)w2c_template"
-R"w2c_template(// (5) The OS doesn't replace the segment register on context switch which
+R"w2c_template(// (5) The OS provides a way to query if (rd|wr)gsbase is allowed by the kernel
+)w2c_template"
+R"w2c_template(// or the implementation has to use a syscall for this.
+)w2c_template"
+R"w2c_template(// (6) The OS doesn't replace the segment register on context switch which
)w2c_template"
R"w2c_template(// eliminates windows for now
)w2c_template"
+R"w2c_template(//
+)w2c_template"
+R"w2c_template(// While more OS can be supported in the future, we only support linux for now
+)w2c_template"
R"w2c_template(#if WASM_RT_ALLOW_SEGUE && !WABT_BIG_ENDIAN && \
)w2c_template"
R"w2c_template( (defined(__x86_64__) || defined(_M_X64)) && IS_SINGLE_UNSHARED_MEMORY && \
)w2c_template"
-R"w2c_template( __clang__ && __has_builtin(__builtin_ia32_wrgsbase64) && !defined(_WIN32)
+R"w2c_template( __clang__ && __has_builtin(__builtin_ia32_wrgsbase64) && \
+)w2c_template"
+R"w2c_template( !defined(_WIN32) && defined(__linux__)
)w2c_template"
R"w2c_template(#define WASM_RT_USE_SEGUE 1
)w2c_template"
@@ -89,11 +99,33 @@ R"w2c_template(
)w2c_template"
R"w2c_template(// POSIX uses FS for TLS, GS is free
)w2c_template"
-R"w2c_template(#define WASM_RT_SEGUE_READ_BASE() __builtin_ia32_rdgsbase64()
+R"w2c_template(static inline void* wasm_rt_segue_read_base() {
)w2c_template"
-R"w2c_template(#define WASM_RT_SEGUE_WRITE_BASE(base) \
+R"w2c_template( if (wasm_rt_fsgsbase_inst_supported) {
+)w2c_template"
+R"w2c_template( return (void*)__builtin_ia32_rdgsbase64();
+)w2c_template"
+R"w2c_template( } else {
+)w2c_template"
+R"w2c_template( return wasm_rt_syscall_get_segue_base();
+)w2c_template"
+R"w2c_template( }
)w2c_template"
-R"w2c_template( __builtin_ia32_wrgsbase64((uintptr_t)base)
+R"w2c_template(}
+)w2c_template"
+R"w2c_template(static inline void wasm_rt_segue_write_base(void* base) {
+)w2c_template"
+R"w2c_template( if (wasm_rt_fsgsbase_inst_supported) {
+)w2c_template"
+R"w2c_template( __builtin_ia32_wrgsbase64((uintptr_t)base);
+)w2c_template"
+R"w2c_template( } else {
+)w2c_template"
+R"w2c_template( wasm_rt_syscall_set_segue_base(base);
+)w2c_template"
+R"w2c_template( }
+)w2c_template"
+R"w2c_template(}
)w2c_template"
R"w2c_template(#define MEM_ADDR_MEMOP(mem, addr, n) ((uint8_t __seg_gs*)(uintptr_t)addr)
)w2c_template"
@@ -194,7 +226,7 @@ R"w2c_template(#include <stdio.h>
)w2c_template"
R"w2c_template(#define WASM_RT_CHECK_BASE(mem) \
)w2c_template"
-R"w2c_template( if (((uintptr_t)((mem)->data)) != ((uintptr_t)WASM_RT_SEGUE_READ_BASE())) { \
+R"w2c_template( if (((uintptr_t)((mem)->data)) != ((uintptr_t)wasm_rt_segue_read_base())) { \
)w2c_template"
R"w2c_template( puts("Segment register mismatch\n"); \
)w2c_template"
diff --git a/src/template/wasm2c.declarations.c b/src/template/wasm2c.declarations.c
index 5261a25b..efe9dbbe 100644
--- a/src/template/wasm2c.declarations.c
+++ b/src/template/wasm2c.declarations.c
@@ -32,11 +32,16 @@
// for accessing pointers, and supports memcpy on pointers with custom
// "address namespaces". GCC does not support the memcpy requirement, so
// this leaves only clang for now.
-// (5) The OS doesn't replace the segment register on context switch which
+// (5) The OS provides a way to query if (rd|wr)gsbase is allowed by the kernel
+// or the implementation has to use a syscall for this.
+// (6) The OS doesn't replace the segment register on context switch which
// eliminates windows for now
+//
+// While more OS can be supported in the future, we only support linux for now
#if WASM_RT_ALLOW_SEGUE && !WABT_BIG_ENDIAN && \
(defined(__x86_64__) || defined(_M_X64)) && IS_SINGLE_UNSHARED_MEMORY && \
- __clang__ && __has_builtin(__builtin_ia32_wrgsbase64) && !defined(_WIN32)
+ __clang__ && __has_builtin(__builtin_ia32_wrgsbase64) && \
+ !defined(_WIN32) && defined(__linux__)
#define WASM_RT_USE_SEGUE 1
#else
#define WASM_RT_USE_SEGUE 0
@@ -45,9 +50,20 @@
#if WASM_RT_USE_SEGUE
// POSIX uses FS for TLS, GS is free
-#define WASM_RT_SEGUE_READ_BASE() __builtin_ia32_rdgsbase64()
-#define WASM_RT_SEGUE_WRITE_BASE(base) \
- __builtin_ia32_wrgsbase64((uintptr_t)base)
+static inline void* wasm_rt_segue_read_base() {
+ if (wasm_rt_fsgsbase_inst_supported) {
+ return (void*)__builtin_ia32_rdgsbase64();
+ } else {
+ return wasm_rt_syscall_get_segue_base();
+ }
+}
+static inline void wasm_rt_segue_write_base(void* base) {
+ if (wasm_rt_fsgsbase_inst_supported) {
+ __builtin_ia32_wrgsbase64((uintptr_t)base);
+ } else {
+ wasm_rt_syscall_set_segue_base(base);
+ }
+}
#define MEM_ADDR_MEMOP(mem, addr, n) ((uint8_t __seg_gs*)(uintptr_t)addr)
#else
#define MEM_ADDR_MEMOP(mem, addr, n) MEM_ADDR(mem, addr, n)
@@ -103,7 +119,7 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a,
#if WASM_RT_USE_SEGUE && WASM_RT_SANITY_CHECKS
#include <stdio.h>
#define WASM_RT_CHECK_BASE(mem) \
- if (((uintptr_t)((mem)->data)) != ((uintptr_t)WASM_RT_SEGUE_READ_BASE())) { \
+ if (((uintptr_t)((mem)->data)) != ((uintptr_t)wasm_rt_segue_read_base())) { \
puts("Segment register mismatch\n"); \
abort(); \
}