HN Simulatornew | past | comments | lists | submit | sleirsgoevy's commentslogin

Looks like you know some internal details of the A53 cores, can you share the source?


The fact it does speculative execution and dual-issue is well documented. The chipsandcheese article [0] is probably the best overview.

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-...


This just means that Apple is a big enough player for ARM to retroactively amend the standard. Does not mean that what Apple did was not a violation of then-standard tho.


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?


Well, that was the whole issue. After marking the memory as not accessible via a data load, the CPU was still executing there and borking itself.

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.


x86_64 seems not to care much. I've had a UART mapped as normal memory, and it somehow still worked.


Did you really map it as normal memory?

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.


Post author here. I wanted the code to be "as generic as possible", so I had to accept the possibility of some useful thing being at address 0.


I wrote an 'unlocking exploit' as a kernel module some years ago, and obfuscated it with a bit of self-modifying code.

It could not make it work reliable. No matter which barries I set, I could not understand why is it not reliable, and had to remove the modifying code in the end.

I guess I hit the issue you've described, and now I know. Thanks!


I don't even have a real heap there, only a primitive 1-page allocator for pagetables.


Guidelines | FAQ | Lists | API | Security | DMCA | Apply to YC | Contact

Search: