[llvm] [BOLT] Add support for Linux kernel .smp_locks section (PR #90798)
Maksim Panchenko via llvm-commits
llvm-commits at lists.llvm.org
Thu May 2 10:50:43 PDT 2024
================
@@ -439,79 +408,73 @@ void LinuxKernelRewriter::processLKKSymtab(bool IsGPL) {
/// .smp_locks section contains PC-relative references to instructions with LOCK
/// prefix. The prefix can be converted to NOP at boot time on non-SMP systems.
-void LinuxKernelRewriter::processLKSMPLocks() {
- ErrorOr<BinarySection &> SectionOrError =
+Error LinuxKernelRewriter::processSMPLocks() {
+ ErrorOr<BinarySection &> SMPLocksSection =
BC.getUniqueSectionByName(".smp_locks");
- if (!SectionOrError)
- return;
+ if (!SMPLocksSection)
+ return Error::success();
- uint64_t SectionSize = SectionOrError->getSize();
- const uint64_t SectionAddress = SectionOrError->getAddress();
- assert((SectionSize % 4) == 0 &&
- "The size of the .smp_locks section should be a multiple of 4");
+ const uint64_t SectionSize = SMPLocksSection->getSize();
+ const uint64_t SectionAddress = SMPLocksSection->getAddress();
+ if (SectionSize % SMP_LOCKS_ENTRY_SIZE)
+ return createStringError(errc::executable_format_error,
+ "bad size of .smp_locks section");
- for (uint64_t I = 0; I < SectionSize; I += 4) {
- const uint64_t EntryAddress = SectionAddress + I;
- ErrorOr<uint64_t> Offset = BC.getSignedValueAtAddress(EntryAddress, 4);
- assert(Offset && "Reading valid PC-relative offset for a .smp_locks entry");
- int32_t SignedOffset = *Offset;
- uint64_t RefAddress = EntryAddress + SignedOffset;
+ DataExtractor DE = DataExtractor(SMPLocksSection->getContents(),
+ BC.AsmInfo->isLittleEndian(),
+ BC.AsmInfo->getCodePointerSize());
+ DataExtractor::Cursor Cursor(0);
+ while (Cursor && Cursor.tell() < SectionSize) {
+ const uint64_t Offset = Cursor.tell();
+ const uint64_t IP = SectionAddress + Offset + (int32_t)DE.getU32(Cursor);
+
+ // Consume the status of the cursor.
+ if (!Cursor)
+ return createStringError(errc::executable_format_error,
+ "error while reading .smp_locks: %s",
+ toString(Cursor.takeError()).c_str());
- BinaryFunction *ContainingBF =
- BC.getBinaryFunctionContainingAddress(RefAddress);
- if (!ContainingBF)
+ if (opts::DumpSMPLocks)
+ BC.outs() << "SMP lock at 0x: " << Twine::utohexstr(IP) << '\n';
+
+ BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(IP);
+ if (!BF || !BC.shouldEmit(*BF))
continue;
- insertLKMarker(RefAddress, I, SignedOffset, true, ".smp_locks");
- }
-}
+ MCInst *Inst = BF->getInstructionAtOffset(IP - BF->getAddress());
+ if (!Inst)
+ return createStringError(errc::executable_format_error,
+ "no instruction matches lock at 0x%" PRIx64, IP);
-void LinuxKernelRewriter::updateLKMarkers() {
- if (LKMarkers.size() == 0)
- return;
+ // Check for duplicate entries.
+ if (BC.MIB->hasAnnotation(*Inst, "SMPLock"))
----------------
maksfb wrote:
Happened on BOLTed output during testing.
https://github.com/llvm/llvm-project/pull/90798
More information about the llvm-commits
mailing list