Skip to content

Commit 83fb1f3

Browse files
openeuler-ci-botgitee-org
authored andcommitted
!254 [Backport][BOLT] Keep X86 HLT instruction as a terminator in user mode (#154402)
From: @polaris_jiang Reviewed-by: @eastB233 Signed-off-by: @eastB233
2 parents 0d89a2c + bd29ac0 commit 83fb1f3

File tree

5 files changed

+48
-3
lines changed

5 files changed

+48
-3
lines changed

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,10 @@ class MCPlusBuilder {
579579
return false;
580580
}
581581

582+
/// Return true if the hlt instruction under the x86, otherwise, default to
583+
/// false.
584+
virtual bool isX86HLT(const MCInst &Inst) const { return false; }
585+
582586
/// Return the width, in bytes, of the memory access performed by \p Inst, if
583587
/// this is a pop instruction. Return zero otherwise.
584588
virtual int getPopSize(const MCInst &Inst) const {

bolt/lib/Core/MCPlusBuilder.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ using namespace bolt;
3131
using namespace MCPlus;
3232

3333
namespace opts {
34+
cl::opt<bool>
35+
TerminalHLT("terminal-x86-hlt",
36+
cl::desc("Assume that execution stops at x86 HLT instruction"),
37+
cl::init(true), cl::Hidden, cl::cat(BoltCategory));
38+
3439
cl::opt<bool>
3540
TerminalTrap("terminal-trap",
3641
cl::desc("Assume that execution stops at trap instruction"),
@@ -131,8 +136,13 @@ bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B,
131136
}
132137

133138
bool MCPlusBuilder::isTerminator(const MCInst &Inst) const {
134-
return Analysis->isTerminator(Inst) ||
135-
(opts::TerminalTrap && Info->get(Inst.getOpcode()).isTrap());
139+
if (isX86HLT(Inst))
140+
return opts::TerminalHLT;
141+
142+
if (Info->get(Inst.getOpcode()).isTrap())
143+
return opts::TerminalTrap;
144+
145+
return Analysis->isTerminator(Inst);
136146
}
137147

138148
void MCPlusBuilder::setTailCall(MCInst &Inst) const {

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ extern cl::opt<bool> KeepNops;
8383
extern cl::opt<bool> Lite;
8484
extern cl::list<std::string> ReorderData;
8585
extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;
86+
extern cl::opt<bool> TerminalHLT;
8687
extern cl::opt<bool> TerminalTrap;
8788
extern cl::opt<bool> TimeBuild;
8889
extern cl::opt<bool> TimeRewrite;
@@ -2141,7 +2142,9 @@ void RewriteInstance::adjustCommandLineOptions() {
21412142
if (!opts::KeepNops.getNumOccurrences())
21422143
opts::KeepNops = true;
21432144

2144-
// Linux kernel may resume execution after a trap instruction in some cases.
2145+
// Linux kernel may resume execution after a trap or x86 HLT instruction.
2146+
if (!opts::TerminalHLT.getNumOccurrences())
2147+
opts::TerminalHLT = false;
21452148
if (!opts::TerminalTrap.getNumOccurrences())
21462149
opts::TerminalTrap = false;
21472150
}

bolt/lib/Target/X86/X86MCPlusBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ class X86MCPlusBuilder : public MCPlusBuilder {
224224
return Inst.getOpcode() == X86::ENDBR32 || Inst.getOpcode() == X86::ENDBR64;
225225
}
226226

227+
bool isX86HLT(const MCInst &Inst) const override {
228+
return Inst.getOpcode() == X86::HLT;
229+
}
230+
227231
int getPopSize(const MCInst &Inst) const override {
228232
switch (Inst.getOpcode()) {
229233
case X86::POP16r:

bolt/test/X86/hlt-terminator.s

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Check that HLT instruction is handled differently depending on the flags.
2+
## It's a terminator in the user-level code, but the execution can resume in
3+
## ring 0.
4+
5+
# RUN: %clang %cflags %s -static -o %t.exe -nostdlib
6+
# RUN: llvm-bolt %t.exe --print-cfg --print-only=main --terminal-x86-hlt=0 \
7+
# RUN: -o %t.ring0 2>&1 | FileCheck %s --check-prefix=CHECK-RING0
8+
# RUN: llvm-bolt %t.exe --print-cfg --print-only=main \
9+
# RUN: -o %t.ring3 2>&1 | FileCheck %s --check-prefix=CHECK-RING3
10+
# RUN: llvm-objdump -d %t.ring0 --print-imm-hex | FileCheck %s --check-prefix=CHECK-BIN
11+
12+
# CHECK-RING0: BB Count : 1
13+
# CHECK-RING3: BB Count : 2
14+
15+
# CHECK-BIN: <main>:
16+
# CHECK-BIN-NEXT: f4 hlt
17+
# CHECK-BIN-NEXT: c3 retq
18+
19+
.global main
20+
.type main, %function
21+
main:
22+
hlt
23+
retq
24+
.size main, .-main

0 commit comments

Comments
 (0)