The NX bit is not just about security
A developer debugging a bare-metal hypervisor on ARM64 for postmarketOS encounters a mysterious bug: enabling the CTR_EL0 intercept causes random system lockups. After ruling out emulation errors and out-of-spec hardware, they discover that the issue is caused by speculative execution of a dynamic branch to a function pointer, which can mispredict to address 0x0 and trigger a fault. The fix involves using a static branch instead, highlighting that the NX bit and speculative execution have implications beyond security.
How do the two instructions differ? `blr x0` is dynamic, `bl get_ctr_el0` is static. Dynamic dispatches employ branch prediction, static branches know where they lead ahead of time and cannot mispredict.