From c9d15228ab7839b749d0ee3faf7cfd159dfc185e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Thu, 25 Jun 2020 04:00:03 +0000 Subject: [PATCH] userland/arch/aarch64/inline_asm/futex_ldxr_stxr.c --- README.adoc | 1 + .../arch/aarch64/inline_asm/futex_ldxr_stxr.c | 55 +++++++++++++++++++ userland/linux/futex.c | 1 + 3 files changed, 57 insertions(+) create mode 100644 userland/arch/aarch64/inline_asm/futex_ldxr_stxr.c diff --git a/README.adoc b/README.adoc index 4cfcbee..6f05f82 100644 --- a/README.adoc +++ b/README.adoc @@ -22968,6 +22968,7 @@ Examples: * link:userland/arch/aarch64/inline_asm/wfe_ldxr_stxr.cpp[] * link:userland/arch/aarch64/inline_asm/wfe_ldxr_str.cpp[] +* link:userland/arch/aarch64/inline_asm/futex_ldxr_stxr.c[]: tests that ldxr and stxr do not interact with futexes. This was leading to problems in <> at one point: https://gem5.atlassian.net/browse/GEM5-537 SEV is not the only thing that can wake up a WFE, it is only an explicit software way to do it. diff --git a/userland/arch/aarch64/inline_asm/futex_ldxr_stxr.c b/userland/arch/aarch64/inline_asm/futex_ldxr_stxr.c new file mode 100644 index 0000000..3fb4d66 --- /dev/null +++ b/userland/arch/aarch64/inline_asm/futex_ldxr_stxr.c @@ -0,0 +1,55 @@ +/* https://cirosantilli.com/linux-kernel-module-cheat#futex-system-call + * https://cirosantilli.com/linux-kernel-module-cheat#arm-wfe-global-monitor-events */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include + +static int futex1 = 1; +static int futex2 = 1; +atomic_int ldxr_done = 0; +atomic_int stdr_wake_done = 0; +static uint64_t ldxr_var = 0; + +void __attribute__ ((noinline)) busy_loop( + unsigned long long max, + unsigned long long max2 +) { + for (unsigned long long i = 0; i < max2; i++) { + for (unsigned long long j = 0; j < max; j++) { + __asm__ __volatile__ ("" : "+g" (i), "+g" (j) : :); + } + } +} + +void* thread_main(void *arg) { + (void)arg; + __asm__ __volatile__ ("ldxr x0, [%0]" : : "r" (&ldxr_var) : "x0"); + ldxr_done = 1; + lkmc_futex(&futex1, FUTEX_WAIT, futex1, NULL, NULL, 0); + lkmc_futex(&futex2, FUTEX_WAIT, futex2, NULL, NULL, 0); + return NULL; +} + +int main(void) { + pthread_t thread; + pthread_create(&thread, NULL, thread_main, NULL); + while (!ldxr_done) {} + /* Wait for thread1 to sleep on futex1. */ + busy_loop(1000, 1); + /* Wrongly wake up the thread with a SEV. */ + __asm__ __volatile__ ("mov x0, 1;ldxr x0, [%0]; stxr w1, x0, [%0]" : : "r" (&ldxr_var) : "x0", "x1"); + /* Wait for thread1 to sleep on futex2. */ + busy_loop(1000, 1); + /* Wrongly wake thread from futex1 again. */ + /* But it is now sleeping on futex2, so this is wrong. */ + lkmc_futex(&futex1, FUTEX_WAKE, 1, NULL, NULL, 0); + assert(!pthread_join(thread, NULL)); +} diff --git a/userland/linux/futex.c b/userland/linux/futex.c index 2e25bec..7a8d44b 100644 --- a/userland/linux/futex.c +++ b/userland/linux/futex.c @@ -1,5 +1,6 @@ /* https://cirosantilli.com/linux-kernel-module-cheat#futex-system-call */ +#define _GNU_SOURCE #include #include #include