Skip to content

Commit

Permalink
[gcs] Support Guarded Control Stacks (#100)
Browse files Browse the repository at this point in the history
Add support for Guarded Control Stacks in all components, and allow allocating
new stacks in the simulator.
  • Loading branch information
mmc28a authored Jun 19, 2024
1 parent 16609c8 commit 3c40723
Show file tree
Hide file tree
Showing 17 changed files with 798 additions and 105 deletions.
4 changes: 3 additions & 1 deletion SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ options = {
'CCFLAGS' : ['-O3'],
},
'simulator:aarch64' : {
'CCFLAGS' : ['-DVIXL_INCLUDE_SIMULATOR_AARCH64'],
'CCFLAGS' : ['-DVIXL_INCLUDE_SIMULATOR_AARCH64',
'-pthread'],
'LINKFLAGS' : ['-pthread']
},
'symbols:on' : {
'CCFLAGS' : ['-g'],
Expand Down
35 changes: 35 additions & 0 deletions src/aarch64/assembler-aarch64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1918,6 +1918,12 @@ void Assembler::sys(int op, const Register& xt) {
}


void Assembler::sysl(int op, const Register& xt) {
VIXL_ASSERT(xt.Is64Bits());
Emit(SYSL | SysOp(op) | Rt(xt));
}


void Assembler::dc(DataCacheOp op, const Register& rt) {
if (op == CVAP) VIXL_ASSERT(CPUHas(CPUFeatures::kDCPoP));
if (op == CVADP) VIXL_ASSERT(CPUHas(CPUFeatures::kDCCVADP));
Expand All @@ -1930,6 +1936,35 @@ void Assembler::ic(InstructionCacheOp op, const Register& rt) {
sys(op, rt);
}

void Assembler::gcspushm(const Register& rt) {
VIXL_ASSERT(CPUHas(CPUFeatures::kGCS));
sys(GCSPUSHM, rt);
}

void Assembler::gcspopm(const Register& rt) {
VIXL_ASSERT(CPUHas(CPUFeatures::kGCS));
sysl(GCSPOPM, rt);
}


void Assembler::gcsss1(const Register& rt) {
VIXL_ASSERT(CPUHas(CPUFeatures::kGCS));
sys(GCSSS1, rt);
}


void Assembler::gcsss2(const Register& rt) {
VIXL_ASSERT(CPUHas(CPUFeatures::kGCS));
sysl(GCSSS2, rt);
}


void Assembler::chkfeat(const Register& rd) {
VIXL_ASSERT(rd.Is(x16));
USE(rd);
hint(CHKFEAT);
}


void Assembler::hint(SystemHint code) { hint(static_cast<int>(code)); }

Expand Down
18 changes: 18 additions & 0 deletions src/aarch64/assembler-aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,9 @@ class Assembler : public vixl::internal::AssemblerBase {
// System instruction with pre-encoded op (op1:crn:crm:op2).
void sys(int op, const Register& xt = xzr);

// System instruction with result.
void sysl(int op, const Register& xt = xzr);

// System data cache operation.
void dc(DataCacheOp op, const Register& rt);

Expand Down Expand Up @@ -7072,6 +7075,21 @@ class Assembler : public vixl::internal::AssemblerBase {
// Unsigned Minimum.
void umin(const Register& rd, const Register& rn, const Operand& op);

// Check feature status.
void chkfeat(const Register& rd);

// Guarded Control Stack Push.
void gcspushm(const Register& rt);

// Guarded Control Stack Pop.
void gcspopm(const Register& rt);

// Guarded Control Stack Switch Stack 1.
void gcsss1(const Register& rt);

// Guarded Control Stack Switch Stack 2.
void gcsss2(const Register& rt);

// Emit generic instructions.

// Emit raw instructions into the instruction stream.
Expand Down
13 changes: 11 additions & 2 deletions src/aarch64/constants-aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ enum SystemHint {
BTI = 32,
BTI_c = 34,
BTI_j = 36,
BTI_jc = 38
BTI_jc = 38,
CHKFEAT = 40
};

enum BranchTargetIdentifier {
Expand Down Expand Up @@ -534,6 +535,13 @@ enum DataCacheOp {
CIGDVAC = CacheOpEncoder<3, 7, 14, 5>::value
};

enum GCSOp {
GCSPUSHM = CacheOpEncoder<3, 7, 7, 0>::value,
GCSPOPM = CacheOpEncoder<3, 7, 7, 1>::value,
GCSSS1 = CacheOpEncoder<3, 7, 7, 2>::value,
GCSSS2 = CacheOpEncoder<3, 7, 7, 3>::value
};

// Some SVE instructions support a predicate constraint pattern. This is
// interpreted as a VL-dependent value, and is typically used to initialise
// predicates, or to otherwise limit the number of processed elements.
Expand Down Expand Up @@ -942,7 +950,8 @@ enum SystemSysOp {
SystemSysFixed = 0xD5080000,
SystemSysFMask = 0xFFF80000,
SystemSysMask = 0xFFF80000,
SYS = SystemSysFixed | 0x00000000
SYS = SystemSysFixed | 0x00000000,
SYSL = SystemSysFixed | 0x00200000
};

// Exception.
Expand Down
158 changes: 80 additions & 78 deletions src/aarch64/cpu-features-auditor-aarch64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1276,91 +1276,93 @@ VIXL_SIMPLE_SVE_VISITOR_LIST(VIXL_DEFINE_SIMPLE_SVE_VISITOR)

void CPUFeaturesAuditor::VisitSystem(const Instruction* instr) {
RecordInstructionFeaturesScope scope(this);
if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
CPUFeatures required;
switch (instr->GetInstructionBits()) {
case PACIA1716:
case PACIB1716:
case AUTIA1716:
case AUTIB1716:
case PACIAZ:
case PACIASP:
case PACIBZ:
case PACIBSP:
case AUTIAZ:
case AUTIASP:
case AUTIBZ:
case AUTIBSP:
case XPACLRI:
required.Combine(CPUFeatures::kPAuth);
break;
default:
switch (instr->GetImmHint()) {
case ESB:
required.Combine(CPUFeatures::kRAS);
break;
case BTI:
case BTI_j:
case BTI_c:
case BTI_jc:
required.Combine(CPUFeatures::kBTI);
break;
default:
break;
}
break;
}

// These are all HINT instructions, and behave as NOPs if the corresponding
// features are not implemented, so we record the corresponding features
// only if they are available.
if (available_.Has(required)) scope.Record(required);
} else if (instr->Mask(SystemSysMask) == SYS) {
switch (instr->GetSysOp()) {
// DC instruction variants.
case CGVAC:
case CGDVAC:
case CGVAP:
case CGDVAP:
case CIGVAC:
case CIGDVAC:
case GVA:
case GZVA:
scope.Record(CPUFeatures::kMTE);
break;
case CVAP:
scope.Record(CPUFeatures::kDCPoP);
break;
case CVADP:
scope.Record(CPUFeatures::kDCCVADP);
break;
case IVAU:
case CVAC:
case CVAU:
case CIVAC:
case ZVA:
// No special CPU features.
break;
}
} else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
switch (instr->Mask(SystemPStateMask)) {
case CFINV:
scope.Record(CPUFeatures::kFlagM);
break;
case AXFLAG:
case XAFLAG:
scope.Record(CPUFeatures::kAXFlag);
break;
}
} else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
if (instr->Mask(SystemSysRegMask) == MRS) {
CPUFeatures required;
switch (form_hash_) {
case "pacib1716_hi_hints"_h:
case "pacia1716_hi_hints"_h:
case "pacibsp_hi_hints"_h:
case "paciasp_hi_hints"_h:
case "pacibz_hi_hints"_h:
case "paciaz_hi_hints"_h:
case "autib1716_hi_hints"_h:
case "autia1716_hi_hints"_h:
case "autibsp_hi_hints"_h:
case "autiasp_hi_hints"_h:
case "autibz_hi_hints"_h:
case "autiaz_hi_hints"_h:
case "xpaclri_hi_hints"_h:
required.Combine(CPUFeatures::kPAuth);
break;
case "esb_hi_hints"_h:
required.Combine(CPUFeatures::kRAS);
break;
case "bti_hb_hints"_h:
required.Combine(CPUFeatures::kBTI);
break;
}

// The instructions above are all HINTs and behave as NOPs if the
// corresponding features are not implemented, so we record the corresponding
// features only if they are available.
if (available_.Has(required)) scope.Record(required);

switch (form_hash_) {
case "cfinv_m_pstate"_h:
scope.Record(CPUFeatures::kFlagM);
break;
case "axflag_m_pstate"_h:
case "xaflag_m_pstate"_h:
scope.Record(CPUFeatures::kAXFlag);
break;
case "mrs_rs_systemmove"_h:
switch (instr->GetImmSystemRegister()) {
case RNDR:
case RNDRRS:
scope.Record(CPUFeatures::kRNG);
break;
}
}
break;
case "sys_cr_systeminstrs"_h:
switch (instr->GetSysOp()) {
// DC instruction variants.
case CGVAC:
case CGDVAC:
case CGVAP:
case CGDVAP:
case CIGVAC:
case CIGDVAC:
case GVA:
case GZVA:
scope.Record(CPUFeatures::kMTE);
break;
case CVAP:
scope.Record(CPUFeatures::kDCPoP);
break;
case CVADP:
scope.Record(CPUFeatures::kDCCVADP);
break;
case IVAU:
case CVAC:
case CVAU:
case CIVAC:
case ZVA:
// No special CPU features.
break;
case GCSPUSHM:
case GCSSS1:
scope.Record(CPUFeatures::kGCS);
break;
}
break;
case "sysl_rc_systeminstrs"_h:
switch (instr->GetSysOp()) {
case GCSPOPM:
case GCSSS2:
scope.Record(CPUFeatures::kGCS);
break;
}
break;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/aarch64/decoder-constants-aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -3764,7 +3764,7 @@ static const DecodeMapping kDecodeMapping[] = {
{"001110"_b, "autiaz_hi_hints"},
{"001111"_b, "autibz_hi_hints"},
{"0100xx"_b, "bti_hb_hints"},
{"010100"_b, "chkfeat_hi_hints"},
{"010100"_b, "chkfeat_hf_hints"},
{"0101x1"_b, "hint_hm_hints"},
{"01x110"_b, "hint_hm_hints"},
{"10xxxx"_b, "hint_hm_hints"},
Expand Down
1 change: 1 addition & 0 deletions src/aarch64/decoder-visitor-map-aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -2591,6 +2591,7 @@
{"dmb_bo_barriers"_h, &VISITORCLASS::VisitSystem}, \
{"dsb_bo_barriers"_h, &VISITORCLASS::VisitSystem}, \
{"hint_hm_hints"_h, &VISITORCLASS::VisitSystem}, \
{"chkfeat_hf_hints"_h, &VISITORCLASS::VisitSystem}, \
{"mrs_rs_systemmove"_h, &VISITORCLASS::VisitSystem}, \
{"msr_sr_systemmove"_h, &VISITORCLASS::VisitSystem}, \
{"psb_hc_hints"_h, &VISITORCLASS::VisitSystem}, \
Expand Down
34 changes: 27 additions & 7 deletions src/aarch64/disasm-aarch64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2018,7 +2018,7 @@ void Disassembler::DisassembleNoArgs(const Instruction *instr) {

void Disassembler::VisitSystem(const Instruction *instr) {
const char *mnemonic = mnemonic_.c_str();
const char *form = "(System)";
const char *form = "";
const char *suffix = NULL;

switch (form_hash_) {
Expand Down Expand Up @@ -2047,6 +2047,10 @@ void Disassembler::VisitSystem(const Instruction *instr) {
break;
}
break;
case "chkfeat_hf_hints"_h:
mnemonic = "chkfeat";
form = "x16";
break;
case "hint_hm_hints"_h:
form = "'IH";
break;
Expand All @@ -2067,9 +2071,6 @@ void Disassembler::VisitSystem(const Instruction *instr) {
break;
}
case Hash("sys_cr_systeminstrs"): {
mnemonic = "dc";
suffix = ", 'Xt";

const std::map<uint32_t, const char *> dcop = {
{IVAU, "ivau"},
{CVAC, "cvac"},
Expand All @@ -2092,17 +2093,36 @@ void Disassembler::VisitSystem(const Instruction *instr) {
if (dcop.count(sysop)) {
if (sysop == IVAU) {
mnemonic = "ic";
} else {
mnemonic = "dc";
}
form = dcop.at(sysop);
suffix = ", 'Xt";
} else if (sysop == GCSSS1) {
mnemonic = "gcsss1";
form = "'Xt";
} else if (sysop == GCSPUSHM) {
mnemonic = "gcspushm";
form = "'Xt";
} else {
mnemonic = "sys";
form = "'G1, 'Kn, 'Km, 'G2";
if (instr->GetRt() == 31) {
suffix = NULL;
if (instr->GetRt() < 31) {
suffix = ", 'Xt";
}
break;
}
break;
}
case "sysl_rc_systeminstrs"_h:
uint32_t sysop = instr->GetSysOp();
if (sysop == GCSPOPM) {
mnemonic = "gcspopm";
form = (instr->GetRt() == 31) ? "" : "'Xt";
} else if (sysop == GCSSS2) {
mnemonic = "gcsss2";
form = "'Xt";
}
break;
}
Format(instr, mnemonic, form, suffix);
}
Expand Down
Loading

0 comments on commit 3c40723

Please sign in to comment.