Skip to content

Commit

Permalink
[AArch64][v8.5A] Add speculation restriction system registers
Browse files Browse the repository at this point in the history
This adds some new system registers which can be used to restrict
certain types of speculative execution.

Patch by Pablo Barrio and David Spickett!

Differential revision: https://reviews.llvm.org/D52482

llvm-svn: 343218
  • Loading branch information
ostannard committed Sep 27, 2018
1 parent dc837e3 commit 8459d34
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 5 deletions.
7 changes: 5 additions & 2 deletions llvm/lib/Target/AArch64/AArch64.td
Expand Up @@ -211,6 +211,9 @@ def FeatureFRInt3264 : SubtargetFeature<"fptoint", "HasFRInt3264", "true",
"Enable FRInt[32|64][Z|X] instructions that round a floating-point number to "
"an integer (in FP format) forcing it to fit into a 32- or 64-bit int" >;

def FeatureSpecRestrict : SubtargetFeature<"specrestrict", "HasSpecRestrict",
"true", "Enable architectural speculation restriction" >;

def FeatureSpecCtrl : SubtargetFeature<"specctrl", "HasSpecCtrl", "true",
"Enable speculation control barrier" >;

Expand Down Expand Up @@ -241,8 +244,8 @@ def HasV8_4aOps : SubtargetFeature<"v8.4a", "HasV8_4aOps", "true",

def HasV8_5aOps : SubtargetFeature<
"v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions",
[HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecCtrl,
FeaturePredCtrl, FeatureCacheDeepPersist]
[HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecRestrict,
FeatureSpecCtrl, FeaturePredCtrl, FeatureCacheDeepPersist]
>;

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
Expand Up @@ -2686,7 +2686,7 @@ bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *N) {
unsigned Reg = PMapper->Encoding;
uint64_t Immed = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
unsigned State;
if (Reg == AArch64PState::PAN || Reg == AArch64PState::UAO) {
if (Reg == AArch64PState::PAN || Reg == AArch64PState::UAO || Reg == AArch64PState::SSBS) {
assert(Immed < 2 && "Bad imm");
State = AArch64::MSRpstateImm1;
} else {
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AArch64/AArch64Subtarget.h
Expand Up @@ -97,6 +97,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
// Armv8.5-A Extensions
bool HasAlternativeNZCV = false;
bool HasFRInt3264 = false;
bool HasSpecRestrict = false;
bool HasSpecCtrl = false;
bool HasPredCtrl = false;
bool HasCCDP = false;
Expand Down Expand Up @@ -316,6 +317,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
bool hasAggressiveFMA() const { return HasAggressiveFMA; }
bool hasAlternativeNZCV() const { return HasAlternativeNZCV; }
bool hasFRInt3264() const { return HasFRInt3264; }
bool hasSpecRestrict() { return HasSpecRestrict; }
bool hasSpecCtrl() { return HasSpecCtrl; }
bool hasPredCtrl() { return HasPredCtrl; }
bool hasCCDP() { return HasCCDP; }
Expand Down
20 changes: 20 additions & 0 deletions llvm/lib/Target/AArch64/AArch64SystemOperands.td
Expand Up @@ -301,6 +301,9 @@ def : PState<"UAO", 0b00011>;
// v8.4a timining insensitivity of data processing instructions
let Requires = [{ {AArch64::HasV8_4aOps} }] in
def : PState<"DIT", 0b11010>;
// v8.5a Spectre Mitigation
let Requires = [{ {AArch64::FeatureSpecRestrict} }] in
def : PState<"SSBS", 0b11001>;

//===----------------------------------------------------------------------===//
// PSB instruction options.
Expand Down Expand Up @@ -507,6 +510,9 @@ def : ROSysReg<"AIDR_EL1", 0b11, 0b001, 0b0000, 0b0000, 0b111>;
def : ROSysReg<"DCZID_EL0", 0b11, 0b011, 0b0000, 0b0000, 0b111>;
def : ROSysReg<"ID_PFR0_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b000>;
def : ROSysReg<"ID_PFR1_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b001>;
def : ROSysReg<"ID_PFR2_EL1", 0b11, 0b000, 0b0000, 0b0011, 0b100> {
let Requires = [{ {AArch64::FeatureSpecRestrict} }];
}
def : ROSysReg<"ID_DFR0_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b010>;
def : ROSysReg<"ID_AFR0_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b011>;
def : ROSysReg<"ID_MMFR0_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b100>;
Expand Down Expand Up @@ -621,6 +627,15 @@ def : ROSysReg<"RNDR", 0b11, 0b011, 0b0010, 0b0100, 0b000>;
def : ROSysReg<"RNDRRS", 0b11, 0b011, 0b0010, 0b0100, 0b001>;
}

// v8.5a Software Context Number registers
let Requires = [{ {AArch64::FeatureSpecRestrict} }] in {
def : RWSysReg<"SCXTNUM_EL0", 0b11, 0b011, 0b1101, 0b0000, 0b111>;
def : RWSysReg<"SCXTNUM_EL1", 0b11, 0b000, 0b1101, 0b0000, 0b111>;
def : RWSysReg<"SCXTNUM_EL2", 0b11, 0b100, 0b1101, 0b0000, 0b111>;
def : RWSysReg<"SCXTNUM_EL3", 0b11, 0b110, 0b1101, 0b0000, 0b111>;
def : RWSysReg<"SCXTNUM_EL12", 0b11, 0b101, 0b1101, 0b0000, 0b111>;
}

//===----------------------
// Write-only regs
//===----------------------
Expand Down Expand Up @@ -1353,6 +1368,11 @@ def : RWSysReg<"ZCR_EL3", 0b11, 0b110, 0b0001, 0b0010, 0b000>;
def : RWSysReg<"ZCR_EL12", 0b11, 0b101, 0b0001, 0b0010, 0b000>;
}

// V8.5a Spectre mitigation SSBS register
// Op0 Op1 CRn CRm Op2
let Requires = [{ {AArch64::FeatureSpecRestrict} }] in
def : RWSysReg<"SSBS", 0b11, 0b011, 0b0100, 0b0010, 0b110>;

// Cyclone specific system registers
// Op0 Op1 CRn CRm Op2
let Requires = [{ {AArch64::ProcCyclone} }] in
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Expand Up @@ -998,7 +998,8 @@ class AArch64Operand : public MCParsedAsmOperand {
if (!isSysReg()) return false;
return (SysReg.PStateField == AArch64PState::PAN ||
SysReg.PStateField == AArch64PState::DIT ||
SysReg.PStateField == AArch64PState::UAO);
SysReg.PStateField == AArch64PState::UAO ||
SysReg.PStateField == AArch64PState::SSBS);
}

bool isSystemPStateFieldWithImm0_15() const {
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
Expand Up @@ -1721,7 +1721,8 @@ static DecodeStatus DecodeSystemPStateInstruction(MCInst &Inst, uint32_t insn,
}

if ((pstate_field == AArch64PState::PAN ||
pstate_field == AArch64PState::UAO) && crm > 1)
pstate_field == AArch64PState::UAO ||
pstate_field == AArch64PState::SSBS) && crm > 1)
return Fail;

Inst.addOperand(MCOperand::createImm(pstate_field));
Expand Down
10 changes: 10 additions & 0 deletions llvm/test/MC/AArch64/armv8.5a-specrestrict-error.s
@@ -0,0 +1,10 @@
// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=+specrestrict < %s 2>&1 | FileCheck %s
// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=+v8.5a < %s 2>&1 | FileCheck %s
// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=-specrestrict < %s 2>&1 | FileCheck %s --check-prefix=NOSPECID

msr SSBS, #2

// CHECK: error: immediate must be an integer in range [0, 1].
// CHECK-NEXT: msr SSBS, #2
// NOSPECID: error: expected writable system register or pstate
// NOSPECID-NEXT: msr {{ssbs|SSBS}}, #2
69 changes: 69 additions & 0 deletions llvm/test/MC/AArch64/armv8.5a-specrestrict.s
@@ -0,0 +1,69 @@
// RUN: llvm-mc -triple aarch64 -show-encoding -mattr=+specrestrict < %s | FileCheck %s
// RUN: llvm-mc -triple aarch64 -show-encoding -mattr=+v8.5a < %s | FileCheck %s
// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=-specrestrict < %s 2>&1 | FileCheck %s --check-prefix=NOSPECID

mrs x9, ID_PFR2_EL1

// CHECK: mrs x9, {{id_pfr2_el1|ID_PFR2_EL1}} // encoding: [0x89,0x03,0x38,0xd5]
// NOSPECID: error: expected readable system register
// NOSPECID-NEXT: mrs x9, ID_PFR2_EL1

mrs x8, SCXTNUM_EL0
mrs x7, SCXTNUM_EL1
mrs x6, SCXTNUM_EL2
mrs x5, SCXTNUM_EL3
mrs x4, SCXTNUM_EL12

// CHECK: mrs x8, {{scxtnum_el0|SCXTNUM_EL0}} // encoding: [0xe8,0xd0,0x3b,0xd5]
// CHECK: mrs x7, {{scxtnum_el1|SCXTNUM_EL1}} // encoding: [0xe7,0xd0,0x38,0xd5]
// CHECK: mrs x6, {{scxtnum_el2|SCXTNUM_EL2}} // encoding: [0xe6,0xd0,0x3c,0xd5]
// CHECK: mrs x5, {{scxtnum_el3|SCXTNUM_EL3}} // encoding: [0xe5,0xd0,0x3e,0xd5]
// CHECK: mrs x4, {{scxtnum_el12|SCXTNUM_EL12}} // encoding: [0xe4,0xd0,0x3d,0xd5]
// NOSPECID: error: expected readable system register
// NOSPECID-NEXT: mrs x8, {{scxtnum_el0|SCXTNUM_EL0}}
// NOSPECID: error: expected readable system register
// NOSPECID-NEXT: mrs x7, {{scxtnum_el1|SCXTNUM_EL1}}
// NOSPECID: error: expected readable system register
// NOSPECID-NEXT: mrs x6, {{scxtnum_el2|SCXTNUM_EL2}}
// NOSPECID: error: expected readable system register
// NOSPECID-NEXT: mrs x5, {{scxtnum_el3|SCXTNUM_EL3}}
// NOSPECID: error: expected readable system register
// NOSPECID-NEXT: mrs x4, {{scxtnum_el12|SCXTNUM_EL12}}

msr SCXTNUM_EL0, x8
msr SCXTNUM_EL1, x7
msr SCXTNUM_EL2, x6
msr SCXTNUM_EL3, x5
msr SCXTNUM_EL12, x4

// CHECK: msr {{scxtnum_el0|SCXTNUM_EL0}}, x8 // encoding: [0xe8,0xd0,0x1b,0xd5]
// CHECK: msr {{scxtnum_el1|SCXTNUM_EL1}}, x7 // encoding: [0xe7,0xd0,0x18,0xd5]
// CHECK: msr {{scxtnum_el2|SCXTNUM_EL2}}, x6 // encoding: [0xe6,0xd0,0x1c,0xd5]
// CHECK: msr {{scxtnum_el3|SCXTNUM_EL3}}, x5 // encoding: [0xe5,0xd0,0x1e,0xd5]
// CHECK: msr {{scxtnum_el12|SCXTNUM_EL12}}, x4 // encoding: [0xe4,0xd0,0x1d,0xd5]
// NOSPECID: error: expected writable system register
// NOSPECID-NEXT: {{scxtnum_el0|SCXTNUM_EL0}}
// NOSPECID: error: expected writable system register
// NOSPECID-NEXT: {{scxtnum_el1|SCXTNUM_EL1}}
// NOSPECID: error: expected writable system register
// NOSPECID-NEXT: {{scxtnum_el2|SCXTNUM_EL2}}
// NOSPECID: error: expected writable system register
// NOSPECID-NEXT: {{scxtnum_el3|SCXTNUM_EL3}}
// NOSPECID: error: expected writable system register
// NOSPECID-NEXT: {{scxtnum_el12|SCXTNUM_EL12}}

mrs x2, SSBS

// CHECK: mrs x2, {{ssbs|SSBS}} // encoding: [0xc2,0x42,0x3b,0xd5]
// NOSPECID: error: expected readable system register
// NOSPECID-NEXT: mrs x2, {{ssbs|SSBS}}

msr SSBS, x3
msr SSBS, #1

// CHECK: msr {{ssbs|SSBS}}, x3 // encoding: [0xc3,0x42,0x1b,0xd5]
// CHECK: msr {{ssbs|SSBS}}, #1 // encoding: [0x3f,0x41,0x03,0xd5]
// NOSPECID: error: expected writable system register or pstate
// NOSPECID-NEXT: msr {{ssbs|SSBS}}, x3
// NOSPECID: error: expected writable system register or pstate
// NOSPECID-NEXT: msr {{ssbs|SSBS}}, #1
52 changes: 52 additions & 0 deletions llvm/test/MC/Disassembler/AArch64/armv8.5a-specrestrict.txt
@@ -0,0 +1,52 @@
# RUN: llvm-mc -triple=aarch64 -mattr=+specrestrict -disassemble < %s | FileCheck %s
# RUN: llvm-mc -triple=aarch64 -mattr=+v8.5a -disassemble < %s | FileCheck %s
# RUN: llvm-mc -triple=aarch64 -mattr=-specrestrict -disassemble < %s | FileCheck %s --check-prefix=NOSPECID

[0x81 0x03 0x38 0xd5]

# CHECK: mrs x1, {{id_pfr2_el1|ID_PFR2_EL1}}
# NOSPECID: mrs x1, S3_0_C0_C3_4

[0xe8 0xd0 0x3b 0xd5]
[0xe7 0xd0 0x38 0xd5]
[0xe6 0xd0 0x3c 0xd5]
[0xe5 0xd0 0x3e 0xd5]
[0xe4 0xd0 0x3d 0xd5]

# CHECK: mrs x8, {{scxtnum_el0|SCXTNUM_EL0}}
# CHECK: mrs x7, {{scxtnum_el1|SCXTNUM_EL1}}
# CHECK: mrs x6, {{scxtnum_el2|SCXTNUM_EL2}}
# CHECK: mrs x5, {{scxtnum_el3|SCXTNUM_EL3}}
# CHECK: mrs x4, {{scxtnum_el12|SCXTNUM_EL12}}
# NOSPECID: mrs x8, S3_3_C13_C0_7
# NOSPECID: mrs x7, S3_0_C13_C0_7
# NOSPECID: mrs x6, S3_4_C13_C0_7
# NOSPECID: mrs x5, S3_6_C13_C0_7
# NOSPECID: mrs x4, S3_5_C13_C0_7

[0xe8 0xd0 0x1b 0xd5]
[0xe7 0xd0 0x18 0xd5]
[0xe6 0xd0 0x1c 0xd5]
[0xe5 0xd0 0x1e 0xd5]
[0xe4 0xd0 0x1d 0xd5]

# CHECK: msr {{scxtnum_el0|SCXTNUM_EL0}}, x8
# CHECK: msr {{scxtnum_el1|SCXTNUM_EL1}}, x7
# CHECK: msr {{scxtnum_el2|SCXTNUM_EL2}}, x6
# CHECK: msr {{scxtnum_el3|SCXTNUM_EL3}}, x5
# CHECK: msr {{scxtnum_el12|SCXTNUM_EL12}}, x4
# NOSPECID: msr S3_3_C13_C0_7, x8
# NOSPECID: msr S3_0_C13_C0_7, x7
# NOSPECID: msr S3_4_C13_C0_7, x6
# NOSPECID: msr S3_6_C13_C0_7, x5
# NOSPECID: msr S3_5_C13_C0_7, x4

[0x3f 0x41 0x03 0xd5]
[0xc3 0x42 0x1b 0xd5]
[0xc2 0x42 0x3b 0xd5]
# CHECK: msr SSBS, #1
# CHECK: msr SSBS, x3
# CHECK: mrs x2, SSBS
# NOSPECID: msr S0_3_C4_C1_1, xzr
# NOSPECID: msr S3_3_C4_C2_6, x3
# NOSPECID: mrs x2, S3_3_C4_C2_6

0 comments on commit 8459d34

Please sign in to comment.