Skip to content
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

[gcs] Support Guarded Control Stacks #100

Merged
merged 1 commit into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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