-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[llvm-exegesis] Validate that address annotations are aligned #75554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[llvm-exegesis] Validate that address annotations are aligned #75554
Conversation
This patch adds in validation at two different levels that address annotations are page aligned. This is necessary as otherwise the mmap calls will fail as MAP_FIXED/MAP_FIXED_NOREPLACE require page aligned addresses. This happens silently in the subprocess. This patch adds validation at snippet parsing time to give feedback to the user and also adds asserts at code generation/address usage time to ensure that other users of the Exegesis APIs conform to the same requirements.
@llvm/pr-subscribers-tools-llvm-exegesis Author: Aiden Grossman (boomanaiden154) ChangesThis patch adds in validation at two different levels that address annotations are page aligned. This is necessary as otherwise the mmap calls will fail as MAP_FIXED/MAP_FIXED_NOREPLACE require page aligned addresses. This happens silently in the subprocess. This patch adds validation at snippet parsing time to give feedback to the user and also adds asserts at code generation/address usage time to ensure that other users of the Exegesis APIs conform to the same requirements. Full diff: https://github.com/llvm/llvm-project/pull/75554.diff 5 Files Affected:
diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-alignment-page-boundary.s b/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-alignment-page-boundary.s
new file mode 100644
index 00000000000000..121ac7c90af824
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-alignment-page-boundary.s
@@ -0,0 +1,14 @@
+# REQUIRES: exegesis-can-measure-latency, x86_64-linux
+
+# Test that we error out if the requested address is not aligned to a page
+# boundary. Here we test out mapping at 2^12+4, which is off from a page
+# boundary by four bytes.
+
+# RUN: not llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess 2>&1 | FileCheck %s
+
+# LLVM-EXEGESIS-MEM-DEF test1 4096 414D47
+# LLVM-EXEGESIS-MEM-MAP test1 65540
+
+nop
+
+# CHECK: invalid comment 'LLVM-EXEGESIS-MEM-MAP test1 65540', expected <ADDRESS> to be a multiple of the platform page size.
diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-snippet-alignment-page-boundary.s b/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-snippet-alignment-page-boundary.s
new file mode 100644
index 00000000000000..4f5dfb9a9f5a74
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-snippet-alignment-page-boundary.s
@@ -0,0 +1,13 @@
+# REQUIRES: exegesis-can-measure-latency, x86_64-linux
+
+# Test that we error out if the requested snippet address is not aligned to
+# a page boundary. Here we test out mapping at 2^12+4 which is off from a page
+# boundary by four bytes.
+
+# RUN: not llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess 2>&1 | FileCheck %s
+
+# LLVM-EXEGESIS-SNIPPET-ADDRESS 65540
+
+nop
+
+# CHECK: invalid comment 'LLVM-EXEGESIS-SNIPPET-ADDRESS 65540, expected <ADDRESS> to be a multiple of the platform page size.
diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp
index e17d239faa47e2..c2fad7c731a7d2 100644
--- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp
@@ -36,6 +36,10 @@
#include "perfmon/perf_event.h"
#endif // HAVE_LIBPFM
+#ifdef __linux__
+#include <unistd.h>
+#endif
+
namespace llvm {
namespace exegesis {
@@ -53,6 +57,13 @@ static bool generateSnippetSetupCode(
if (GenerateMemoryInstructions) {
BBF.addInstructions(ET.generateMemoryInitialSetup());
for (const MemoryMapping &MM : Key.MemoryMappings) {
+#ifdef __linux__
+ // The frontend that generates that parses the memory mapping information
+ // from the user should validate that the requested address is a multiple
+ // of the page size. Assert that this is true here.
+ assert(MM.Address % getpagesize() == 0 &&
+ "Memory mappings need to be aligned to page boundaries.");
+#endif
BBF.addInstructions(ET.generateMmap(
MM.Address, Key.MemoryValues.at(MM.MemoryValueName).SizeBytes,
ET.getAuxiliaryMemoryStartAddress() +
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 41960c23a10d19..12e774e1a4b8d6 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -418,6 +418,12 @@ class SubProcessFunctionExecutorImpl
exit(ChildProcessExitCodeE::RSeqDisableFailed);
#endif // GLIBC_INITS_RSEQ
+ // The frontend that generates the memory annotation structures should
+ // validate that the address to map the snippet in at is a multiple of
+ // the page size. Assert that this is true here.
+ assert(Key.SnippetAddress % getpagesize() == 0 &&
+ "The snippet address needs to be aligned to a page boundary.");
+
size_t FunctionDataCopySize = this->Function.FunctionBytes.size();
void *MapAddress = NULL;
int MapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index 286c606cd6fb19..7258fcb4279c7d 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -23,6 +23,10 @@
#include "llvm/Support/SourceMgr.h"
#include <string>
+#ifdef __linux__
+#include <unistd.h>
+#endif // __linux__
+
namespace llvm {
namespace exegesis {
namespace {
@@ -118,6 +122,19 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
MemoryMapping MemMap;
MemMap.MemoryValueName = Parts[0].trim().str();
MemMap.Address = std::stol(Parts[1].trim().str());
+
+#ifdef __linux__
+ // Validate that the annotation is a multiple of the platform's page
+ // size.
+ if (MemMap.Address % getpagesize() != 0) {
+ errs() << "invalid comment 'LLVM-EXEGESIS-MEM-MAP " << CommentText
+ << "', expected <ADDRESS> to be a multiple of the platform page "
+ "size.";
+ ++InvalidComments;
+ return;
+ }
+#endif // __linux__
+
// validate that the annotation refers to an already existing memory
// definition
auto MemValIT = Result->Key.MemoryValues.find(Parts[0].trim().str());
@@ -142,6 +159,20 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
++InvalidComments;
return;
}
+
+#ifdef __linux__
+ // Validate that the address in the annotation is a multiple of the
+ // platform's page size.
+ if (Result->Key.SnippetAddress % getpagesize() != 0) {
+ errs() << "invalid comment 'LLVM-EXEGESIS-SNIPPET-ADDRESS "
+ << CommentText
+ << ", expected <ADDRESS> to be a multiple of the platform page "
+ "size.";
+ ++InvalidComments;
+ return;
+ }
+#endif // __linux__
+
return;
}
}
|
This patch adds in validation at two different levels that address annotations are page aligned. This is necessary as otherwise the mmap calls will fail as MAP_FIXED/MAP_FIXED_NOREPLACE require page aligned addresses. This happens silently in the subprocess. This patch adds validation at snippet parsing time to give feedback to the user and also adds asserts at code generation/address usage time to ensure that other users of the Exegesis APIs conform to the same requirements.