[PATCH] D67284: [LLD][ELF][ARM] Implement --fix-cortex-a8 to fix erratum 657417
Peter Smith via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 9 09:33:50 PDT 2019
peter.smith marked 27 inline comments as done.
peter.smith added a comment.
In D67284#1663011 <https://reviews.llvm.org/D67284#1663011>, @ruiu wrote:
> I'm halfway through reviewing it, and it looks like a straightforward implementation of a mitigation. Can I ask a (perhaps noob) question? If a CPU can be locked up by an instruction sequence that triggers the bug, and if the CPU is used by Android, does that mean a user application can lock up the entire system?
Yes it is possible for a user application to lock the entire system. From the erratum description: " If the deadlock condition occurs, it can only be interrupted by pulling the RESET pin on the processor." There are several more run-time conditions that make this rare, and it only occurs on models with a 32k instruction cache.
Thanks very much for the comments, I will post a new patch shortly that I hope will address the comments. I think the AArch64ErrataFix.cpp will need a patch after this as some of the refactoring cleanups could also be applied there. I'll do that when it is clear what needs to be done.
================
Comment at: ELF/ARMErrataFix.cpp:42
+// - There is a 32-bit Thumb-2 branch instruction with an address of the form
+// xxxxxxFFE. The first 2 bytes of the instruction are in 4KiB region 1, the
+// second 2 bytes are in region 2.
----------------
ruiu wrote:
> MaskRay wrote:
> > What are "region 1" and "region 2"?
> I guess that means first page and second page?
Memory region is the word used in the official erratum description and the Architecture reference manual. It is closely related to a page so in this case it can be thought of as a page. I think memory region is used in the spec as memory regions can also be used in a non-paged context. I'll update the description to make it clear what region 1 and 2 are.
================
Comment at: ELF/ARMErrataFix.cpp:88
+// Return true if the half-word is the first half of a 32-bit instruction.
+// armv7ar architecture reference manual 32-bit instruction encoding
+// First halfword of a 32-bit instruction is of form:
----------------
MaskRay wrote:
> 32-bit Thumb instruction encoding? (The heading as used in the manual)
Yes, I'll update the comment to improve the reference.
================
Comment at: ELF/ARMErrataFix.cpp:91
+// | 1 1 1 | op1 (2) | op2 (7) | x (4) |
+// With op1 == 0b00
+static bool is32bitInstruction(uint16_t hw) {
----------------
MaskRay wrote:
> op1 != 0b00 ?
>
> op1 == 0b00 encodes a 16-bit Thumb instruction.
Yes, I forgot to finish the sentence used in the manual. I'll fix up the comment.
================
Comment at: ELF/ARMErrataFix.cpp:181
+// the source.
+static bool branchToFirstRegion(const InputSection *isec, uint64_t off,
+ uint32_t instr) {
----------------
MaskRay wrote:
> > branchToFirstRegion
>
> Is "first region" the term used to refer to `destAddr < sourceAddr && (destAddr & 0xfffff000) == (sourceAddr & 0xfffff000);`
Yes it is, I'll update the function name to make it more explicit. I also worked out that I don't need the destAddr < sourceAddr part.
================
Comment at: ELF/ARMErrataFix.cpp:269
+ }
+ off += 0x1000;
+ return scanRes;
----------------
MaskRay wrote:
> Say `off % 0x1000 = 0xffc` before the assignment. The erratum sequence in the next page starts at 0xffa. This increment will skip that erratum sequence.
>
> Is this a possible scenario?
Yes I think there might be a case that gets recognized as an erratum where there is something like:
```
0x0ffc nop.w
label:
0x1000 b.w label
```
I will add a case to make sure the 0xffc is handled in a similar way to 0xffe and will add to the nopatch test case.
================
Comment at: ELF/ARMErrataFix.cpp:286
+ auto isArmMapSymbol = [](const Symbol *b) {
+ return b->getName() == "$a" || b->getName().startswith("$a.");
+ };
----------------
MaskRay wrote:
> In include/llvm/Object/ELFObjectFile.h and llvm-objdump, we just use `startswith("$a")`. Is there a reason to check `"$a."`? Below, you just use `return ms->getName().startswith("$t");`
Yes, $afoo without the . is not a mapping symbol. I'm thinking that it might be best to replace the map from InputSection -> vector<Symbol*> to InputSection -> std::pair<uint64_t offset, bool isThumb>, this would also work for AArch64.
================
Comment at: ELF/ARMErrataFix.cpp:297
+ for (InputFile *file : objectFiles) {
+ auto *f = cast<ObjFile<ELF32LE>>(file);
+ for (Symbol *b : f->getLocalSymbols()) {
----------------
MaskRay wrote:
> Should there be a check to reject ELF32BE beforehand?
> It can be placed in Driver.cpp:checkOptions.
LLD doesn't support ELF32BE. I'd have thought it would give an error, but without passing an emulation, it seems like I can get LLD will accept a big-endian ELF file without error, I'll need to write a follow up patch to give an error.
As an aside:
Big Endian is strange on AArch64 and even stranger in ARM. In general it only tends to get used in networking so I've not seen any requests to implement it.
- AArch64 BE: ELF is BE, instructions are LE, Data is BE
- ARM BE : ELF is BE, instructions in relocatable objects are BE, Data is BE. Older ARM architectures like v4, v5 and v6 executable/dso instructions have BE instructions. All newer architectures have LE instructions and the linker needs to do the byte swaps.
================
Comment at: ELF/ARMErrataFix.cpp:351
+ while (patchIt != patchEnd) {
+ if ((*patchIt)->getBranchAddr() - outSecAddr >= prevIsecLimit)
+ break;
----------------
MaskRay wrote:
> Is it guaranteed that getBranchAddr() is monotonically increasing?
Yes. The getBranchAddr() is essentially the address in the InputSection that has the patch applied to it. Within an InputSectionDescriptions the InputSections->outSecOff monotonically increase, and as the patches are added to the end of the list, the getBranchAddr() monotonically increases.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D67284/new/
https://reviews.llvm.org/D67284
More information about the llvm-commits
mailing list