-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[BOLT] Keep X86 HLT instruction as a terminator in user mode #154402
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
Conversation
@llvm/pr-subscribers-bolt Author: Maksim Panchenko (maksfb) ChangesThis is a follow-up to #150963. X86 HLT instruction may appear in the user-level code, in which case we should treat it as a terminator. Handle it as a non-terminator in the Linux kernel mode. Full diff: https://github.com/llvm/llvm-project/pull/154402.diff 4 Files Affected:
diff --git a/bolt/lib/Core/MCPlusBuilder.cpp b/bolt/lib/Core/MCPlusBuilder.cpp
index d8a2ac6f6837a..7f962e14ea115 100644
--- a/bolt/lib/Core/MCPlusBuilder.cpp
+++ b/bolt/lib/Core/MCPlusBuilder.cpp
@@ -30,6 +30,11 @@ using namespace bolt;
using namespace MCPlus;
namespace opts {
+cl::opt<bool>
+ TerminalHLT("terminal-x86-hlt",
+ cl::desc("Assume that execution stops at x86 HLT instruction"),
+ cl::init(true), cl::Hidden, cl::cat(BoltCategory));
+
cl::opt<bool>
TerminalTrap("terminal-trap",
cl::desc("Assume that execution stops at trap instruction"),
@@ -132,10 +137,13 @@ bool MCPlusBuilder::equals(const MCSpecifierExpr &A, const MCSpecifierExpr &B,
}
bool MCPlusBuilder::isTerminator(const MCInst &Inst) const {
- return (opts::TerminalTrap && Info->get(Inst.getOpcode()).isTrap()) ||
- Analysis->isTerminator(Inst)
- ? !isX86HLT(Inst)
- : false;
+ if (isX86HLT(Inst))
+ return opts::TerminalHLT;
+
+ if (Info->get(Inst.getOpcode()).isTrap())
+ return opts::TerminalTrap;
+
+ return Analysis->isTerminator(Inst);
}
void MCPlusBuilder::setTailCall(MCInst &Inst) const {
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index fe4a23cc01382..b2056ba2380fb 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -84,6 +84,7 @@ extern cl::opt<bool> KeepNops;
extern cl::opt<bool> Lite;
extern cl::list<std::string> ReorderData;
extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;
+extern cl::opt<bool> TerminalHLT;
extern cl::opt<bool> TerminalTrap;
extern cl::opt<bool> TimeBuild;
extern cl::opt<bool> TimeRewrite;
@@ -2177,7 +2178,9 @@ void RewriteInstance::adjustCommandLineOptions() {
if (!opts::KeepNops.getNumOccurrences())
opts::KeepNops = true;
- // Linux kernel may resume execution after a trap instruction in some cases.
+ // Linux kernel may resume execution after a trap or x86 HLT instruction.
+ if (!opts::TerminalHLT.getNumOccurrences())
+ opts::TerminalHLT = false;
if (!opts::TerminalTrap.getNumOccurrences())
opts::TerminalTrap = false;
}
diff --git a/bolt/test/X86/cfg_build_hlt.s b/bolt/test/X86/cfg_build_hlt.s
deleted file mode 100644
index a78134df34014..0000000000000
--- a/bolt/test/X86/cfg_build_hlt.s
+++ /dev/null
@@ -1,17 +0,0 @@
-## Check CFG for halt instruction
-
-# RUN: %clang %cflags %s -static -o %t.exe -nostdlib
-# RUN: llvm-bolt %t.exe --print-cfg --print-only=main -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-CFG
-# RUN: llvm-objdump -d %t --print-imm-hex | FileCheck %s --check-prefix=CHECK-BIN
-
-# CHECK-CFG: BB Count : 1
-# CHECK-BIN: <main>:
-# CHECK-BIN-NEXT: f4 hlt
-# CHECK-BIN-NEXT: c3 retq
-
-.global main
- .type main, %function
-main:
- hlt
- retq
-.size main, .-main
diff --git a/bolt/test/X86/hlt-terminator.s b/bolt/test/X86/hlt-terminator.s
new file mode 100644
index 0000000000000..8c15d71f337de
--- /dev/null
+++ b/bolt/test/X86/hlt-terminator.s
@@ -0,0 +1,24 @@
+## Check that HLT instruction is handled differently depending on the flags.
+## It's a terminator in the user-level code, but the execution can resume in
+## ring 0.
+
+# RUN: %clang %cflags %s -static -o %t.exe -nostdlib
+# RUN: llvm-bolt %t.exe --print-cfg --print-only=main --terminal-x86-hlt=0 \
+# RUN: -o %t.ring0 2>&1 | FileCheck %s --check-prefix=CHECK-RING0
+# RUN: llvm-bolt %t.exe --print-cfg --print-only=main \
+# RUN: -o %t.ring3- 2>&1 | FileCheck %s --check-prefix=CHECK-RING3
+# RUN: llvm-objdump -d %t.ring0 --print-imm-hex | FileCheck %s --check-prefix=CHECK-BIN
+
+# CHECK-RING0: BB Count : 1
+# CHECK-RING3: BB Count : 2
+
+# CHECK-BIN: <main>:
+# CHECK-BIN-NEXT: f4 hlt
+# CHECK-BIN-NEXT: c3 retq
+
+.global main
+ .type main, %function
+main:
+ hlt
+ retq
+.size main, .-main
|
bolt/test/X86/hlt-terminator.s
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a hyphen at the end of the output filename: %t.ring3-
This is a follow-up to llvm#150963. X86 HLT instruction may appear in the user-level code, in which case we should treat it as a terminator. Handle it as a non-terminator in the Linux kernel mode.
Thanks for the review. |
This is a follow-up to #150963. X86 HLT instruction may appear in the user-level code, in which case we should treat it as a terminator. Handle it as a non-terminator in the Linux kernel mode.