Skip to content

Commit 3125f46

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm] Add Zicfiss.
TEST=ci, local qemu Change-Id: Iea22fff14362a6eef937f22ab9121376c7e27014 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/460883 Reviewed-by: Alexander Aprelev <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent 7035823 commit 3125f46

File tree

8 files changed

+350
-12
lines changed

8 files changed

+350
-12
lines changed

runtime/vm/compiler/assembler/assembler_riscv.cc

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,19 +573,19 @@ void MicroAssembler::fencei() {
573573

574574
void MicroAssembler::ecall() {
575575
ASSERT(Supports(RV_I));
576-
EmitIType(ECALL, ZR, F3_0, ZR, SYSTEM);
576+
EmitIType(ECALL, ZR, PRIV, ZR, SYSTEM);
577577
}
578578
void MicroAssembler::ebreak() {
579579
ASSERT(Supports(RV_I));
580580
if (Supports(RV_C)) {
581581
c_ebreak();
582582
return;
583583
}
584-
EmitIType(EBREAK, ZR, F3_0, ZR, SYSTEM);
584+
EmitIType(EBREAK, ZR, PRIV, ZR, SYSTEM);
585585
}
586586
void MicroAssembler::SimulatorPrintObject(Register rs1) {
587587
ASSERT(Supports(RV_I));
588-
EmitIType(ECALL, rs1, F3_0, ZR, SYSTEM);
588+
EmitIType(ECALL, rs1, PRIV, ZR, SYSTEM);
589589
}
590590

591591
void MicroAssembler::csrrw(Register rd, uint32_t csr, Register rs1) {
@@ -1969,6 +1969,51 @@ void MicroAssembler::fleqd(Register rd, FRegister rs1, FRegister rs2) {
19691969
EmitRType(FCMPD, rs2, rs1, FLEQ, rd, OPFP);
19701970
}
19711971

1972+
void MicroAssembler::sspush(Register rs2) {
1973+
ASSERT((rs2 == Register(1)) || (rs2 == Register(5)));
1974+
ASSERT(Supports(RV_Zicfiss));
1975+
if (Supports(RV_C) && (rs2 == Register(1))) {
1976+
Emit16(C_SSPUSH);
1977+
} else {
1978+
EmitRType(SSPUSH, rs2, ZR, F3_100, ZR, SYSTEM);
1979+
}
1980+
}
1981+
1982+
void MicroAssembler::sspopchk(Register rs1) {
1983+
ASSERT((rs1 == Register(1)) || (rs1 == Register(5)));
1984+
ASSERT(Supports(RV_Zicfiss));
1985+
if (Supports(RV_C) && (rs1 == Register(5))) {
1986+
Emit16(C_SSPOPCHK);
1987+
} else {
1988+
EmitIType(SSPOPCHK, rs1, F3_100, ZR, SYSTEM);
1989+
}
1990+
}
1991+
1992+
void MicroAssembler::ssrdp(Register rd) {
1993+
ASSERT(Supports(RV_Zicfiss));
1994+
EmitIType(SSRDP, ZR, F3_100, rd, SYSTEM);
1995+
}
1996+
1997+
void MicroAssembler::ssamoswapw(Register rd,
1998+
Register rs2,
1999+
Address addr,
2000+
std::memory_order order) {
2001+
ASSERT(addr.offset() == 0);
2002+
ASSERT(Supports(RV_Zicfiss));
2003+
EmitRType(SSAMOSWAP, order, rs2, addr.base(), WIDTH32, rd, AMO);
2004+
}
2005+
2006+
#if XLEN >= 64
2007+
void MicroAssembler::ssamoswapd(Register rd,
2008+
Register rs2,
2009+
Address addr,
2010+
std::memory_order order) {
2011+
ASSERT(addr.offset() == 0);
2012+
ASSERT(Supports(RV_Zicfiss));
2013+
EmitRType(SSAMOSWAP, order, rs2, addr.base(), WIDTH64, rd, AMO);
2014+
}
2015+
#endif // XLEN >= 64
2016+
19722017
void MicroAssembler::lb(Register rd, Address addr, std::memory_order order) {
19732018
ASSERT(addr.offset() == 0);
19742019
ASSERT((order == std::memory_order_acquire) ||
@@ -2187,6 +2232,7 @@ void MicroAssembler::c_lui(Register rd, uintptr_t imm) {
21872232
ASSERT(Supports(RV_C));
21882233
ASSERT(rd != ZR);
21892234
ASSERT(rd != SP);
2235+
ASSERT(imm != 0);
21902236
Emit16(C_LUI | EncodeCRd(rd) | EncodeCUImm(imm));
21912237
}
21922238

@@ -2747,6 +2793,20 @@ void MicroAssembler::EmitR4Type(FRegister rs3,
27472793
Emit32(e);
27482794
}
27492795

2796+
void MicroAssembler::EmitIType(Funct12 funct12,
2797+
Register rs1,
2798+
Funct3 funct3,
2799+
Register rd,
2800+
Opcode opcode) {
2801+
uint32_t e = 0;
2802+
e |= EncodeFunct12(funct12);
2803+
e |= EncodeRs1(rs1);
2804+
e |= EncodeFunct3(funct3);
2805+
e |= EncodeRd(rd);
2806+
e |= EncodeOpcode(opcode);
2807+
Emit32(e);
2808+
}
2809+
27502810
void MicroAssembler::EmitIType(intptr_t imm,
27512811
Register rs1,
27522812
Funct3 funct3,

runtime/vm/compiler/assembler/assembler_riscv.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,21 @@ class MicroAssembler : public AssemblerBase {
708708
void fltqd(Register rd, FRegister rs1, FRegister rs2);
709709
void fleqd(Register rd, FRegister rs1, FRegister rs2);
710710

711+
// ==== Zicfiss: Shadow stack ====
712+
void sspush(Register rs2);
713+
void sspopchk(Register rs1);
714+
void ssrdp(Register rd);
715+
void ssamoswapw(Register rd,
716+
Register rs2,
717+
Address addr,
718+
std::memory_order order = std::memory_order_relaxed);
719+
#if XLEN >= 64
720+
void ssamoswapd(Register rd,
721+
Register rs2,
722+
Address addr,
723+
std::memory_order order = std::memory_order_relaxed);
724+
#endif // XLEN >= 64
725+
711726
// ==== Zalasr: Load-acquire, store-release ====
712727
void lb(Register rd, Address addr, std::memory_order order);
713728
void lh(Register rd, Address addr, std::memory_order order);
@@ -889,6 +904,11 @@ class MicroAssembler : public AssemblerBase {
889904
FRegister rd,
890905
Opcode opcode);
891906

907+
void EmitIType(Funct12 funct12,
908+
Register rs1,
909+
Funct3 funct3,
910+
Register rd,
911+
Opcode opcode);
892912
void EmitIType(intptr_t imm,
893913
Register rs1,
894914
Funct3 funct3,

runtime/vm/compiler/assembler/assembler_riscv_test.cc

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8597,6 +8597,144 @@ ASSEMBLER_TEST_RUN(StoreDoubleWordRelease, test) {
85978597
}
85988598
#endif // XLEN >= 64
85998599

8600+
ASSEMBLER_TEST_GENERATE(ShadowStack, assembler) {
8601+
__ SetExtensions(RV_G | RV_Zicfiss);
8602+
Label f;
8603+
__ sspush(RA);
8604+
__ jal(RA2, &f);
8605+
__ sspopchk(RA);
8606+
__ ret();
8607+
__ Bind(&f);
8608+
__ sspush(RA2);
8609+
__ sspopchk(RA2);
8610+
__ jr(RA2);
8611+
}
8612+
ASSEMBLER_TEST_RUN(ShadowStack, test) {
8613+
EXPECT_DISASSEMBLY(
8614+
"ce104073 sspush ra\n"
8615+
"00c002ef jal t0, +12\n"
8616+
"cdc0c073 sspopchk ra\n"
8617+
"00008067 ret\n"
8618+
"ce504073 sspush t0\n"
8619+
"cdc2c073 sspopchk t0\n"
8620+
"00028067 jr t0\n");
8621+
EXPECT_EQ(0, Call(test->entry(), 0));
8622+
}
8623+
8624+
ASSEMBLER_TEST_GENERATE(CompressedShadowStack, assembler) {
8625+
__ SetExtensions(RV_GC | RV_Zicfiss);
8626+
Label f;
8627+
__ sspush(RA);
8628+
__ jal(RA2, &f);
8629+
__ sspopchk(RA);
8630+
__ ret();
8631+
__ Bind(&f);
8632+
__ sspush(RA2);
8633+
__ sspopchk(RA2);
8634+
__ jr(RA2);
8635+
}
8636+
ASSEMBLER_TEST_RUN(CompressedShadowStack, test) {
8637+
EXPECT_DISASSEMBLY(
8638+
" 6081 sspush ra\n"
8639+
"00a002ef jal t0, +10\n"
8640+
"cdc0c073 sspopchk ra\n"
8641+
" 8082 ret\n"
8642+
"ce504073 sspush t0\n"
8643+
" 6281 sspopchk t0\n"
8644+
" 8282 jr t0\n");
8645+
EXPECT_EQ(0, Call(test->entry(), 0));
8646+
}
8647+
8648+
ASSEMBLER_TEST_GENERATE(ShadowStackAmoSwapWord, assembler) {
8649+
__ SetExtensions(RV_G | RV_Zicfiss);
8650+
__ ssamoswapw(A0, A1, Address(A0));
8651+
__ ret();
8652+
}
8653+
ASSEMBLER_TEST_RUN(ShadowStackAmoSwapWord, test) {
8654+
EXPECT_DISASSEMBLY(
8655+
"48b5252f ssamoswap.w a0, a1, (a0)\n"
8656+
"00008067 ret\n");
8657+
// Not running: would trap.
8658+
}
8659+
8660+
#if XLEN >= 64
8661+
ASSEMBLER_TEST_GENERATE(ShadowStackAmoSwapDoubleWord, assembler) {
8662+
__ SetExtensions(RV_G | RV_Zicfiss);
8663+
__ ssamoswapd(A0, A1, Address(A0));
8664+
__ ret();
8665+
}
8666+
ASSEMBLER_TEST_RUN(ShadowStackAmoSwapDoubleWord, test) {
8667+
EXPECT_DISASSEMBLY(
8668+
"48b5352f ssamoswap.d a0, a1, (a0)\n"
8669+
"00008067 ret\n");
8670+
// Not running: would trap.
8671+
}
8672+
#endif // XLEN >= 64
8673+
8674+
ASSEMBLER_TEST_GENERATE(ShadowStackLongJump, assembler) {
8675+
__ SetExtensions(RV_G | RV_Zicfiss);
8676+
Label nlr, func2, setjmp, longjmp, ss_disabled;
8677+
__ sspush(RA);
8678+
__ subi(SP, SP, 6 * target::kWordSize);
8679+
__ sx(RA, Address(SP, 5 * target::kWordSize));
8680+
__ sx(FP, Address(SP, 4 * target::kWordSize));
8681+
__ addi(FP, SP, 6 * target::kWordSize);
8682+
__ addi(A0, SP, 0 * target::kWordSize);
8683+
__ jal(&setjmp);
8684+
__ bnez(A0, &nlr);
8685+
__ addi(A0, SP, 0 * target::kWordSize);
8686+
__ jal(&func2);
8687+
__ Bind(&nlr);
8688+
__ lx(FP, Address(SP, 4 * target::kWordSize));
8689+
__ lx(RA, Address(SP, 5 * target::kWordSize));
8690+
__ addi(SP, SP, 6 * target::kWordSize);
8691+
__ sspopchk(RA);
8692+
__ ret();
8693+
8694+
__ Bind(&func2);
8695+
__ sspush(RA);
8696+
__ subi(SP, SP, 2 * target::kWordSize);
8697+
__ sx(RA, Address(SP, 1 * target::kWordSize));
8698+
__ sx(FP, Address(SP, 0 * target::kWordSize));
8699+
__ addi(FP, SP, 1 * target::kWordSize);
8700+
__ jal(&longjmp);
8701+
__ lx(FP, Address(SP, 0 * target::kWordSize));
8702+
__ lx(RA, Address(SP, 1 * target::kWordSize));
8703+
__ addi(SP, SP, 2 * target::kWordSize);
8704+
__ sspopchk(RA);
8705+
__ ret();
8706+
8707+
__ Bind(&setjmp);
8708+
__ sx(RA, Address(A0, 0 * target::kWordSize));
8709+
__ sx(SP, Address(A0, 1 * target::kWordSize));
8710+
__ sx(FP, Address(A0, 2 * target::kWordSize));
8711+
__ ssrdp(A1);
8712+
__ sx(A1, Address(A0, 3 * target::kWordSize));
8713+
__ li(A0, 0);
8714+
__ ret();
8715+
8716+
__ Bind(&longjmp);
8717+
__ lx(RA, Address(A0, 0 * target::kWordSize));
8718+
__ lx(SP, Address(A0, 1 * target::kWordSize));
8719+
__ lx(FP, Address(A0, 2 * target::kWordSize));
8720+
__ lx(A1, Address(A0, 3 * target::kWordSize));
8721+
__ beqz(A1, &ss_disabled);
8722+
__ csrw(0x011, A1);
8723+
__ Bind(&ss_disabled);
8724+
__ li(A0, 1);
8725+
__ ret();
8726+
}
8727+
ASSEMBLER_TEST_RUN(ShadowStackLongJump, test) {
8728+
#if defined(DART_INCLUDE_SIMULATOR)
8729+
Simulator::Current()->set_ss_enabled(true);
8730+
EXPECT_EQ(1, Call(test->entry()));
8731+
Simulator::Current()->set_ss_enabled(false);
8732+
EXPECT_EQ(1, Call(test->entry()));
8733+
#else
8734+
EXPECT_EQ(1, Call(test->entry()));
8735+
#endif
8736+
}
8737+
86008738
ASSEMBLER_TEST_GENERATE(LoadImmediate_MaxInt32, assembler) {
86018739
__ SetExtensions(RV_GC);
86028740
__ LoadImmediate(A0, kMaxInt32);

runtime/vm/compiler/assembler/disassembler_riscv.cc

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,14 @@ void RISCVDisassembler::DisassembleInstruction(CInstr instr) {
294294
case C_LUI:
295295
if (instr.rd() == SP) {
296296
Print("addi 'rd, 'rs1, 'i16imm", instr, RV_C);
297-
} else {
297+
} else if ((instr.rd() != ZR) && (instr.u_imm() != 0)) {
298298
Print("lui 'rd, 'uimm", instr, RV_C);
299+
} else if (instr.encoding() == C_SSPUSH) {
300+
Print("sspush ra", instr, RV_Zicfiss | RV_C);
301+
} else if (instr.encoding() == C_SSPOPCHK) {
302+
Print("sspopchk t0", instr, RV_Zicfiss | RV_C);
303+
} else {
304+
UnknownInstruction(instr);
299305
}
300306
break;
301307
case C_ADDI:
@@ -1104,7 +1110,7 @@ void RISCVDisassembler::DisassembleMISCMEM(Instr instr) {
11041110

11051111
void RISCVDisassembler::DisassembleSYSTEM(Instr instr) {
11061112
switch (instr.funct3()) {
1107-
case 0:
1113+
case PRIV:
11081114
switch (instr.funct12()) {
11091115
case ECALL:
11101116
if (instr.rs1() == ZR) {
@@ -1120,6 +1126,22 @@ void RISCVDisassembler::DisassembleSYSTEM(Instr instr) {
11201126
UnknownInstruction(instr);
11211127
}
11221128
break;
1129+
case F3_100: {
1130+
if ((instr.funct7() == SSPUSH) && (instr.rd() == ZR) &&
1131+
(instr.rs1() == ZR) &&
1132+
((instr.rs2() == Register(1)) || (instr.rs2() == Register(5)))) {
1133+
Print("sspush 'rs2", instr, RV_Zicfiss);
1134+
} else if ((instr.funct12() == SSPOPCHK) && (instr.rd() == ZR) &&
1135+
((instr.rs1() == Register(1)) ||
1136+
(instr.rs1() == Register(5)))) {
1137+
Print("sspopchk 'rs1", instr, RV_Zicfiss);
1138+
} else if ((instr.funct12() == SSRDP) && (instr.rs1() == ZR)) {
1139+
Print("ssrdp 'rd", instr, RV_Zicfiss);
1140+
} else {
1141+
UnknownInstruction(instr);
1142+
}
1143+
break;
1144+
}
11231145
case CSRRW:
11241146
if (instr.rd() == ZR) {
11251147
Print("csrw 'csr, 'rs1", instr, RV_I);
@@ -1309,6 +1331,9 @@ void RISCVDisassembler::DisassembleAMO32(Instr instr) {
13091331
case STOREORDERED:
13101332
Print("sw'order 'rs2, ('rs1)", instr, RV_Zalasr);
13111333
break;
1334+
case SSAMOSWAP:
1335+
Print("ssamoswap.w'order 'rd, 'rs2, ('rs1)", instr, RV_Zicfiss);
1336+
break;
13121337
default:
13131338
UnknownInstruction(instr);
13141339
}
@@ -1356,6 +1381,9 @@ void RISCVDisassembler::DisassembleAMO64(Instr instr) {
13561381
case STOREORDERED:
13571382
Print("sd'order 'rs2, ('rs1)", instr, RV_Zalasr);
13581383
break;
1384+
case SSAMOSWAP:
1385+
Print("ssamoswap.d'order 'rd, 'rs2, ('rs1)", instr, RV_Zicfiss);
1386+
break;
13591387
#endif
13601388
default:
13611389
UnknownInstruction(instr);

runtime/vm/compiler/stub_code_compiler_riscv.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,9 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub() {
14171417

14181418
#if defined(DART_TARGET_OS_FUCHSIA) || defined(DART_TARGET_OS_ANDROID)
14191419
__ sx(GP, Address(A3, target::Thread::saved_shadow_call_stack_offset()));
1420+
// TODO(riscv): Enable once Fuchsia/Android have Zimop in their baseline.
1421+
// __ ssrdp(TMP);
1422+
// __ sx(TMP, Address(A3, target::Thread::saved_ss_offset()));
14201423
#elif defined(USING_SHADOW_CALL_STACK)
14211424
#error Unimplemented
14221425
#endif
@@ -3001,6 +3004,12 @@ void StubCodeCompiler::GenerateJumpToFrameStub() {
30013004
// and Exceptions::JumpToFrame, otherwise the shadow call stack might
30023005
// eventually overflow.
30033006
__ lx(GP, Address(THR, target::Thread::saved_shadow_call_stack_offset()));
3007+
// TODO(riscv): Enable once Fuchsia/Android have Zimop in their baseline.
3008+
// __ lx(TMP, Address(THR, target::Thread::saved_ss_offset()));
3009+
// Label ss_disabled;
3010+
// __ beqz(TMP, &ss_disabled);
3011+
// __ csrw(0x011, TMP);
3012+
// __ Bind(&ss_disabled);
30043013
#elif defined(USING_SHADOW_CALL_STACK)
30053014
#error Unimplemented
30063015
#endif

0 commit comments

Comments
 (0)