[llvm] [llvm-exegesis] Validate that address annotations are aligned (PR #75554)

Aiden Grossman via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 14 17:36:02 PST 2023


https://github.com/boomanaiden154 created https://github.com/llvm/llvm-project/pull/75554

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.

>From 6f45ede2c3b4c0f66248477b0ce98054f86d89e9 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Thu, 14 Dec 2023 17:31:45 -0800
Subject: [PATCH] [llvm-exegesis] Validate that address annotations are aligned

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.
---
 ...mory-annotations-alignment-page-boundary.s | 14 +++++++++
 ...otations-snippet-alignment-page-boundary.s | 13 ++++++++
 llvm/tools/llvm-exegesis/lib/Assembler.cpp    | 11 +++++++
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     |  6 ++++
 llvm/tools/llvm-exegesis/lib/SnippetFile.cpp  | 31 +++++++++++++++++++
 5 files changed, 75 insertions(+)
 create mode 100644 llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-alignment-page-boundary.s
 create mode 100644 llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-snippet-alignment-page-boundary.s

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;
     }
   }



More information about the llvm-commits mailing list