Earlier quoted context omitted.
No, NX precedes Spectre by a long shot. It was originally intended so an attacker couldn't use a buffer overflow to change the PC and execute directly out of the attacker-controlled buffer.
That is exactly what the poster to whom you replied said. So Arm did not add another means to disable this kind of speculative execution, after Spectre was discovered, but they just reused the existing NX flag, expanding its functionality.
The NX bit is not just about security
41–50 of 51 posts
Re: The NX bit is not just about security
#42On this theme of it not being just about security: if you have a bug like a use after free and it happens to cover a function pointer, the nx bit can ensure that when you follow that pointer through a call, you get a clean trap as close to the failure point as possible. If it blindly executed stale bytes as code, maybe the crash and stack trace doesn't look as nice. But then, a lot of correctness bugs like that are a…
Re: The NX bit is not just about security
#43Earlier quoted context omitted.
(Total guess) this feels like an attempt at restricting what parts of the hardware pipeline need to know what; if prefetches need to key off of both the device bit and the nx bit, then both of those need to be piped into the frontend, whereas if device is only relevant for data prefetches then only the nx bit needs to be available there (while device would be piped into the backend where the data prefetcher lives).
Not really. To the front end, one needs to pipe only appropriate logical combinations of the flags that describe the memory properties, not the flags as they are stored in some control register. So a control register should contain flags that are meaningful for the programmer, while the kind of flags that hardware happens to need can be generated with a few logic gates from them and routed through hardware wherever t…
Re: The NX bit is not just about security
#44Honestly feels like a misdesign in ARM. Where does it ever make sense for Device memory to not be data prefetchable, but allow instruction prefetch? It should IMHO disable all prefetch…
The problem is that unlike data prefetch, the so-called "instruction prefetch" is not actually prefetch at all. It's simply speculative execution. Which doesn't look any different to regular execution. The fetcher has no idea that its predicted branch is about to invalidated and flushed, otherwise it would never have issued that fetch. Actually, on a modern OoO core, [0] it's very rare for the instruction fetcher to…
Re: The NX bit is not just about security
#45Earlier quoted context omitted.
Not really. To the front end, one needs to pipe only appropriate logical combinations of the flags that describe the memory properties, not the flags as they are stored in some control register. So a control register should contain flags that are meaningful for the programmer, while the kind of flags that hardware happens to need can be generated with a few logic gates from them and routed through hardware wherever t…
x86_64 seems not to care much. I've had a UART mapped as normal memory, and it somehow still worked.
Standard UARTs are accessed in the x86 I/O space, which is uncacheable and strongly ordered, not in the normal memory space.
Non-standard UARTs that are on PCIe add-on cards might be mapped into memory, but when the computer boots, the BIOS already maps the PCIe memory as uncacheable, with the Memory Type Range Registers.
So if you do nothing, you get uncacheable memory for your UART, as you should.
To map the UART in normal memory, i.e. write-back cacheable, you must do this explicitly in the UART device driver, either by allocating a dedicated MTRR for it, or more likely, by locking a memory page for it in the virtual address translation tables and using the PAT bits to set the memory type (Page Attribute Table).
If you really mapped the UART as normal memory, i.e. write-back cacheable, it can work correctly only if you are incredibly lucky, because the writes to the UART control registers will not happen when you do them in your program, so I do not believe that you did that. With normal memory, not only you cannot predict when the UART registers will be written, but if you do multiple writes to the same register, all but the last will be omitted, so there is no way for the UART to work correctly.
On x86-64, any memory-mapped peripheral must be mapped into uncacheable memory, except for memory banks that are located on PCIe cards, like the GPU memories, which should be mapped as write-combining memory.
Re: The NX bit is not just about security
#46Earlier quoted context omitted.
The problem is that unlike data prefetch, the so-called "instruction prefetch" is not actually prefetch at all. It's simply speculative execution. Which doesn't look any different to regular execution. The fetcher has no idea that its predicted branch is about to invalidated and flushed, otherwise it would never have issued that fetch. Actually, on a modern OoO core, [0] it's very rare for the instruction fetcher to…
Looks like you know some internal details of the A53 cores, can you share the source?
The "how" it does dual-issue is not documented at all, so I'm speculating. There is no smoking gun saying "register renaming". While it would be possible to implement its known capabilities without any kind of renaming, it would be so much simpler to implement it with register renaming.
The thing is.. once your forwarding network and hazard detection gets complicated enough, it basically becomes a janky form of register renaming. So it's cleaner to just implement proper register renaming, and actually saves hardware.
While the A53 might issue in-order, the pipelines have different lengths and they don't finish executing in order.
I find the fact the A53 can speculate a few instructions past a cache miss to be very interesting, along with the fact it can issue two writes to the same logical register in a single cycle.
Also, the smoking gun is that the A510 (same lineage as the A53) is documented to do out-of-order issue (see chipsandcheese again [1]), so it must be doing register renaming. ARM still insist on still calling it an in-order core because it's OoO is so much more limited to modern OoO cores, but it's more OoO than early PowerPC designs (including the G3) that everyone is happy applying the OoO label to.
[0] https://chipsandcheese.com/p/arms-cortex-a53-tiny-but-import... [1] https://chipsandcheese.com/p/arms-cortex-a510-two-kids-in-a-...
Re: The NX bit is not just about security
#47Earlier quoted context omitted.
So in this specific case, if I understood correctly, here’s what should happen: Interrupt(?) fires to trigger hypervisor, hypervisor figures out what it needs to do, jumps to that code, does its job, returns. The “figured out what it needs to do” is the issue right? So what was actually happening was: Same start… CPU predicts what hypervisor will do, speculatively loads instructions from mispredicted branch target, t…
No, that instruction does not read memory. That instruction is itself IN the inaccessible memory. It does not really matter how execution ended up in the HV in the first place. The misprediction happens due to having a branch-to-register instruction.
Re: The NX bit is not just about security
#48Earlier quoted context omitted.
L take. RAM is too slow for self-modifying code to be anywhere but F tier. This isn't 6502 land.
But it could be, there are bits about doing computation in RAM, self modifying code could work.
Now, if the RAM in the CPU cache gets computational ability as well, that all changes, but not sure really that would be better than SIMD/SEE/AVX stuff or expanding what can be done with the new tile registers Intel's rolling out.
Re: The NX bit is not just about security
#49Earlier quoted context omitted.
In an attempt to go fast and beat benchmarks and other computers, CPUs attempt to speculatively execute code, and then later undo the results of the speculation if it turns out it was wrong. This causes all sorts of security issues (spectre, meltdown, and friends et al.) even when it's done relatively competently. When it's done in competently as on this ARM implementation, then you can't even run perfectly good and…
Speculative instruction fetches fetch code from "a location that you never asked it to execute code at" by design. If it already knew you asked it to execute code there, it wouldn't be speculative. The Armv8/9-A architecture reference manual is clear that speculative instruction fetches are permitted in Device memory unless that memory is also marked NX. So if your hardware has side-effects from a certain address, bu…
Sure, but (a) the speculation is supposed to be transparent; and (b) ARM's response to a failure in speculative execution is arguably broken.
> The Armv8/9-A architecture reference manual
Sure, but before then marking memory as not readable would make it non-executable, and also mostly before then there was no or minimal speculation.
> then your code is not "perfectly good and correct".
Certainly it won't work on that machine. It might have worked perfectly well on prior machines, and we could argue all day about how reasonable ARM's implementation decisions were, but I will merely say that a documented flaw is, in fact, still a flaw.
Re: The NX bit is not just about security
#50Earlier quoted context omitted.
No, that instruction does not read memory. That instruction is itself IN the inaccessible memory. It does not really matter how execution ended up in the HV in the first place. The misprediction happens due to having a branch-to-register instruction.
Ah, thanks. So instruction loads also count as data loads?
He had to also mark the memory as inaccessible for code loads.
Which, honestly is kinda stupid. Because nobody asked the processor to start executing there. It just took it upon itself to try to start executing there, later decided that was a bad thing, and then borked itself.
People talk about how terrible x86 is, but honestly, one of the reasons that x86 won for decades was because of making things that programmers did that might be suboptimal still work, even if a bit slowly (misaligned data accesses, for example). ARM does that now for that specific case, but didn't before 2002.
So there's an implementation tradeoff for whether you decide to spend transistors to reduce the number of sharp edges on the tool. Obviously ARM just doesn't give a shit about this particular sharp edge.