diff --git a/README.adoc b/README.adoc index 87c5998..30cd573 100644 --- a/README.adoc +++ b/README.adoc @@ -18634,8 +18634,6 @@ However, likely no implementation likely does (TODO confirm), since: and power consumption is key in ARM applications. -SEV is not the only thing that can wake up a WFE, it is only an explicit software way to do it. Notably, global monitor operations on memory accesses of regions marked by LDAXR and STLXR instructions can also wake up a WFE sleeping core. This is done to allow spinlocks opens to automatically wake up WFE sleeping cores at free time without the need for a explicit SEV. - Quotes for the above <> G1.18.1 "Wait For Event and Send Event": ____ @@ -18693,6 +18691,20 @@ The following Raspberry Pi bibliography helped us get this sample up and running For how userland spinlocks and mutexes are implemented see <>. +====== ARM WFE global monitor events + +link:userland/arch/aarch64/inline_asm/wfe_ldxr_stxr.cpp[] + +SEV is not the only thing that can wake up a WFE, it is only an explicit software way to do it. + +Notably, global monitor operations on memory accesses of regions marked by <> can also wake up a WFE sleeping core. + +This is done to allow spinlocks opens to automatically wake up WFE sleeping cores at free time without the need for a explicit SEV. + +In the shown in the `wfe_ldrex_strex.cpp` example, which can only terminate in gem5 user mode simulation because due to this event. + +Note that that program still terminates when running on top of the Linux kernel as explained at: <>. + ====== WFE from userland WFE and SEV are usable from userland, and are part of an efficient spinlock implementation (which userland should arguably stay away from and rather use the <> which allow for non busy sleep instead), which maybe is not something that userland should ever tho and just stick to mutexes? diff --git a/userland/arch/aarch64/inline_asm/wfe_ldxr_stxr.cpp b/userland/arch/aarch64/inline_asm/wfe_ldxr_stxr.cpp new file mode 100644 index 0000000..4366d20 --- /dev/null +++ b/userland/arch/aarch64/inline_asm/wfe_ldxr_stxr.cpp @@ -0,0 +1,35 @@ +// https://cirosantilli.com/linux-kernel-module-cheat#arm-wfe-global-monitor-events + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include +#include + +#include + +std::atomic_ulong done; +int futex = 1; + +void myfunc() { + __asm__ __volatile__ ("ldxr x0, [%0];wfe;wfe" : : "r" (&futex) : "x0"); + done.store(futex); +} + +int main(int argc, char **argv) { + bool do_sev = true; + if (argc > 1) { + do_sev = (argv[1][0] != '0'); + } + done.store(0); + std::thread thread; + thread = std::thread(myfunc); + while (!done.load()) { + if (do_sev) { + __asm__ __volatile__ ("mov x0, 1;stxr w1, x0, [%0]" : : "r" (&futex) : "x0", "x1"); + } + } + thread.join(); +}