The NX bit is not just about security
summary
The author discovers that the NX (Non-Executable) bit on ARM architecture serves a critical functional purpose beyond security, specifically preventing system crashes caused by speculative instruction fetches. In certain ARM64 environments, marking memory as 'Device' only stops speculative data access, while instruction fetches still treat that memory as 'Normal' and may speculatively access forbidden regions like the bootrom. By correctly implementing the NX bit, the author prevents the CPU from mispredicting branches to address 0x0, thereby stabilizing the system.
key points
- A mysterious system lock-up during hypervisor development was traced back to the difference between static branches (bl) and dynamic dispatches (blr), where the latter triggered speculative fetches to address 0x0.
- ARM documentation specifies that marking a region as 'Device' memory prevents speculative data accesses, but only marking it as non-executable prevents speculative instruction fetches.
- The NX bit, often viewed solely as a security feature for Data Execution Prevention (DEP), is actually a necessary architectural attribute to ensure stability when dealing with MMIO and speculative execution.
who should read it
Low-level programmers, kernel developers, and security researchers interested in ARM architecture and hardware-level debugging.
discussion skeptical
consensus
Commenters agree that ARM's architectural decision to permit speculative instruction fetches from device memory—unless specifically marked as execute-never (NX)—is a significant design flaw. They conclude that while disabling data prefetching is insufficient, the NX bit is the only reliable way to prevent the CPU from speculatively executing inaccessible memory and crashing. The sentiment is generally critical of ARM for creating a 'sharp edge' that requires tedious manual workarounds from developers.
top insight
The distinction between data prefetching and instruction prefetching is that the latter is an inherent part of speculative execution in modern Out-of-Order (OoO) cores. Because the fetcher cannot know a branch prediction is invalid until after decoding, it inevitably issues fetches that are indistinguishable from regular execution to the memory bus, necessitating the NX bit to block these accesses at the hardware level.
Generated by an LLM from the article and thread. Check the sources before relying on it.