Lines Matching +full:auto +full:- +full:detected

1 //===- AArch64ErrataFix.cpp -----------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // the AArch64 Cortex-53 errata 843419 that affects r0p0, r0p1, r0p2 and r0p4
13 // more instructions is detected in the instruction stream, one of the
19 // - There is a set of necessary conditions required to trigger the erratum that
20 // can be detected at static link time.
21 // - There is a set of replacement instructions that can be used to remove at
23 // - We can overwrite an instruction in the erratum sequence with a branch to
25 // - We can place the replacement sequence within range of the branch.
26 //===----------------------------------------------------------------------===//
51 // the Cortex-A53-843419 erratum.
59 // Load and store bit patterns from ARMv8-A.
71 // LDN/STN multiple post-indexed
99 // LDN/STN single post-indexed
106 // opcode == 000 ST1 8-bit.
107 // opcode == 010 ST1 16-bit.
108 // opcode == 100 ST1 32 or 64-bit (Size determines which).
146 // Load/store no-allocate pair
156 // (post-indexed)
170 // (pre-index)
188 // Load/store register (immediate post-indexed)
200 // Load/store register (immediate pre-indexed)
218 // Rt is always in bit position 0 - 4.
221 // Rn is always in bit position 5 - 9.
288 // Scanner for Cortex-A53 errata 843419
290 // Developers Errata Notice (ARM-EPM-048406).
302 // - A single register load or store, of either integer or vector registers.
303 // - An STP or STNP, of either integer or vector registers.
304 // - An Advanced SIMD ST1 store instruction.
305 // - Must not write to Rn, but may optionally read from it.
316 // and 4.) in the Scanner for Cortex-A53 errata comment above.
339 uint64_t isecAddr = isec->getVA(0); in scanCortexA53Errata843419()
344 off += 0xff8 - initialPageOff; in scanCortexA53Errata843419()
346 bool optionalAllowed = limit - off > 12; in scanCortexA53Errata843419()
347 if (off >= limit || limit - off < 12) { in scanCortexA53Errata843419()
348 // Need at least 3 4-byte sized instructions to trigger erratum. in scanCortexA53Errata843419()
354 const uint8_t *buf = isec->content().begin(); in scanCortexA53Errata843419()
384 return d->kind() == InputSectionBase::Synthetic && d->name == ".text.patch"; in classof()
399 this->parent = p->getParent(); in Patch843419Section()
407 return patchee->getVA(patcheeOffset); in getLDSTAddr()
413 write32le(buf, read32le(patchee->content().begin() + patcheeOffset)); in writeTo()
416 target->relocateAlloc(*this, buf); in writeTo()
420 uint64_t p = patchSym->getVA() + 4; in writeTo()
421 target->relocateNoSym(buf + 4, R_AARCH64_JUMP26, s - p); in writeTo()
435 auto isCodeMapSymbol = [](const Symbol *b) { in init()
436 return b->getName() == "$x" || b->getName().starts_with("$x."); in init()
438 auto isDataMapSymbol = [](const Symbol *b) { in init()
439 return b->getName() == "$d" || b->getName().starts_with("$d."); in init()
444 for (Symbol *b : file->getLocalSymbols()) { in init()
445 auto *def = dyn_cast<Defined>(b); in init()
450 if (auto *sec = dyn_cast_or_null<InputSection>(def->section)) in init()
451 if (sec->flags & SHF_EXECINSTR) in init()
459 for (auto &kv : sectionMap) { in init()
462 return a->value < b->value; in init()
485 uint64_t prevIsecLimit = isd.sections.front()->outSecOff; in insertPatches()
486 uint64_t patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing(); in insertPatches()
487 uint64_t outSecAddr = isd.sections.front()->getParent()->addr; in insertPatches()
492 auto patchIt = patches.begin(); in insertPatches()
493 auto patchEnd = patches.end(); in insertPatches()
495 isecLimit = isec->outSecOff + isec->getSize(); in insertPatches()
498 if ((*patchIt)->getLDSTAddr() - outSecAddr >= prevIsecLimit) in insertPatches()
500 (*patchIt)->outSecOff = prevIsecLimit; in insertPatches()
503 patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing(); in insertPatches()
508 (*patchIt)->outSecOff = isecLimit; in insertPatches()
517 auto mergeCmp = [](const InputSection *a, const InputSection *b) { in insertPatches()
518 if (a->outSecOff != b->outSecOff) in insertPatches()
519 return a->outSecOff < b->outSecOff; in insertPatches()
548 auto relIt = llvm::find_if(isec->relocs(), [=](const Relocation &r) { in implementPatch()
551 if (relIt != isec->relocs().end() && in implementPatch()
552 (relIt->type == R_AARCH64_JUMP26 || relIt->expr == R_RELAX_TLS_IE_TO_LE)) in implementPatch()
555 log("detected cortex-a53-843419 erratum sequence starting at " + in implementPatch()
558 auto *ps = make<Patch843419Section>(isec, patcheeOffset); in implementPatch()
561 auto makeRelToPatch = [](uint64_t offset, Symbol *patchSym) { in implementPatch()
565 if (relIt != isec->relocs().end()) { in implementPatch()
566 ps->addReloc({relIt->expr, relIt->type, 0, relIt->addend, relIt->sym}); in implementPatch()
567 *relIt = makeRelToPatch(patcheeOffset, ps->patchSym); in implementPatch()
569 isec->addReloc(makeRelToPatch(patcheeOffset, ps->patchSym)); in implementPatch()
586 // scan is therefore [codeSym->value, dataSym->value) or [codeSym->value, in patchInputSectionDescription()
590 auto codeSym = mapSyms.begin(); in patchInputSectionDescription()
592 auto dataSym = std::next(codeSym); in patchInputSectionDescription()
593 uint64_t off = (*codeSym)->value; in patchInputSectionDescription()
594 uint64_t limit = (dataSym == mapSyms.end()) ? isec->content().size() in patchInputSectionDescription()
595 : (*dataSym)->value; in patchInputSectionDescription()
598 uint64_t startAddr = isec->getVA(off); in patchInputSectionDescription()
629 if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR)) in createFixes()
631 for (SectionCommand *cmd : os->commands) in createFixes()
632 if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) { in createFixes()