The forward-edge CFI introduces landing pad instructions that enable software to indicate valid targets for indirect calls and indirect jumps in a program.
A landing pad (lpcul
) instruction is defined as the instruction that must be
placed at the program locations that can be valid targets of indirect jumps or
calls.
To enforce that the target of an indirect call or indirect jump must be a valid
landing pad instruction, the hart maintains an expected landing pad (ELP
) state
to determine if a landing pad instruction is required at the target of a JALR
instruction. The ELP
state can be one of:
-
0 -
NO_LP_EXPECTED
-
1 -
LP_EXPECTED
A JALR
with rd = x1
or rd = x5
is an indirect call; it updates ELP
to
LP_EXPECTED
. A JALR
with rd != x1
and rd != x5
and where rs1 != x1
and
rs1 != x5
is an indirect jump; it updates the ELP
to LP_EXPECTED
.
When ELP
is set to LP_EXPECTED
and the next instruction in the instruction
stream is not lpcll
, then an illegal instruction exception is raised. If the
next instruction in the instruction stream is lpcll
then the ELP
updates to
NO_LP_EXPECTED
.
Note
|
Tracking of |
The forward-edge CFI also supports labeling of landing pads. By itself a landing
pad allows, for example, an indirect call to land on any lpcll
in the program.
This significantly reduces the number of valid targets for an indirect call.
Labeling of the landing pads enables software to achieve greater precision in
pairing up indirect call sites or indirect jump sites with valid targets. To
support labeled landing pads, the indirect call/jump sites establish an expected
landing pad label in the landing pad label register (lplr
). If the target of
the indirect call/jump is a valid landing pad instruction, the expected label
established in the lplr
is matched with the target’s label. If a mismatch is
detected then the label check instruction causes an illegal instruction
exception.
Each landing pad may be labeled with a label that may be upto 25-bits wide. The
lplr
has three subfields - a 9-bit lower label (LL
), a 8-bit middle label
(ML
), and an 8-bit upper label (UL
).
The forward-edge CFI provides a lpsll
instruction to establish the expected
LL
in the lplr
, a lpsml
instruction to establish the ML
, and a lpsul
instruction to establish the UL
in the lplr
.
The lpcll
instructions embed a 9-bit immediate field. The instruction compares
this value to the LL
and on a mismatch causes an illegal-instruction exception.
For label widths up to 17-bit a companion instruction lpcml
is provided. The
lpcml
embeds a 8-bit immediate value that is compared to the ML
and on a
mismatch causes an illegal-instruction exception.
For label widths greater than 17-bit a second companion instruction lpcul
is
provided. The lpcul
embeds a 8-bit immediate value that is compared to the UL
and on a mismatch causes an illegal-instruction exception.
The forward-edge CFI introduces the following instructions for landing
pad operations. All instructions are encoded using the SYSTEM major opcode and
using the mop.rr
instructions defined by the Zimops extension.
(mop.rr) |
31 |
25 |
24 |
23 |
22 |
15 |
14 |
12 |
11 |
7 |
6 |
0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
mnemonic |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
When privilege level is M, the forward-edge CFI is active when MFCFIEN
is 1 in
mstatus
register.
When menvcfg.CFI
is 0, then Zisslpcfi is not enabled for privilege modes less than
M and forward-edge CFI is not active at privilege levels less than M.
When V=0
and menvcfg.CFI
is 1, then forward-edge CFI is active at S-mode if
mstatus.SFCFIEN
is 1 and is active at U-mode if mstatus.UFCFIEN
is 1.
When henvcfg.CFI
is 0, then Zisslpcfi is not enabled for use when V=1
.
When V=1
and menvcfg.CFI
and henvcfg.CFI
are both 1, then forward-edge CFI
is active at S-mode if vsstatus.SFCFIEN
is 1 and is active at U-mode if
vsstatus.UFCFIEN
is 1.
The term xFCFIACT
is used to determine if forward-edge CFI is active at
privilege level x
and is defined as follows:
xFCFIACT
determinationif ( privilege == M-mode )
xFCFIACT = mstatus.MFCFIEN
else if ( menvcfg.CFI == 1 && V == 0 && privilege == S-mode )
xFCFIACT = mstatus.SFCFIEN
else if ( menvcfg.CFI == 1 && V == 0 && privilege == U-mode )
xFCFIACT = mstatus.UFCFIEN
else if ( menvcfg.CFI == 1 && henvcfg.CFI == 1 & V == 1 && privilege == S-mode )
xFCFIACT = vsstatus.SFCFIEN
else if ( menvcfg.CFI == 1 && henvcfg.CFI == 1 & V == 1 && privilege == U-mode )
xFCFIACT = vsstatus.UFCFIEN
else
xFCFIACT = 0
When forward-edge CFI is not active(xFCFIACT = 0
):
-
The implementation does not update expected landing pad (
ELP
) state on indirect call or jump and does not require the instruction at the target of a indirect call or jump to be a landing pad instruction. -
The implementation does not update expected landing pad (
ELP
) whenlpcll
is executed. -
The instructions defined for forward-edge CFI revert to their Zimops defined behavior and write 0 to [rd].
lpcll
is the valid landing pad instructions at target of indirect jumps and
indirect calls. When a forward-edge CFI is active, the instructions cause an
illegal instruction exception if they are not placed at a 4-byte aligned pc
.
The lpcll
has the lower landing pad label embedded in the LLPL
field.
lpcll
causes an illegal instruction exception if the LLPL
field in the
instruction does not match the lplr.LL
field.
When the instructions cause an illegal-instruction exception, the ELP
does not
change.
The operation of the lpcll
instruction is as follows:
lpcll
operationIf xFCFIACT != 0
// If PC not 4-byte aligned then illegal-instruction
if pc[1:0] != 0
Cause illegal-instruction exception
// If lower landing pad label not matched -> illegal-instruction
else if (inst.LLPL != lplr.LL)
Cause illegal-instruction exception
else
ELP = NO_LP_EXPECTED
else
[rd] = 0;
endif
The lpcml
instruction matches the 8-bit wide middle label in its MLPL
field with
the lplr.ML
field and causes an illegal instruction exception on a mismatch. The
lpcml
is not a valid target for an indirect call or jump.
The lpcul
instruction matches the 8-bit wide upper label in its ULPL
field with
the lplr.UL
field and causes an illegal instruction exception on a mismatch. The
lpcul
is not a valid target for an indirect call or jump.
The operation of the lpcml
instruction is as follows:
lpcml
operationIf xFCFIACT != 0
if (lplr.ML != inst.MLPL)
cause illegal-instruction exception
else
[dst] = 0;
endif
The operation of the lpcul
instruction is as follows:
lpcul
operationIf xFCFIACT != 0
if (lplr.UL != inst.ULPL)
cause illegal-instruction exception
else
[dst] = 0;
endif
Before performing an indirect call or indirect jump to a labeled landing pad,
the lplr
is loaded with the expected landing pad label - a constant determined
at compilation time.
A lpsll
instruction is provided to set the value of the lower label (LL
) field
of the lplr
.
The operation of this instruction is as follows:
lpsll
operationIf xFCFIACT == 1
lplr.LL = inst.LLPL
lplr.ML = lplr.UL = 0
else
[rd] = 0;
endif
Note
|
The following instruction sequence may be emitted at indirect call sites by the compiler to set up the landing pad label register when labels that are upto 9-bit wide are used: : # x10 is expected to have address of function bar() lpsll $0x1de # setup lplr.LL with value 0x1de jalr %ra, %x10 : The following instruction sequence may be emitted at indirect call sites by the compiler to set up the landing pads at entrypoint of function bar(): bar: lpcll $0x1de # Verifies that LPLR.LL matches 0x1de |
A lpsml
instruction is provided to set the value of the middle label (ML
) field
of the lplr
. This instruction is used when labels wider than 9-bit are used.
The operation of this instruction is as follows:
lpsml
operationIf xFCFIACT == 1
lplr.ML = inst.MLPL
else
[rd] = 0;
endif
Note
|
The following instruction sequence may be emitted at indirect call sites by the compiler to set up the landing pad label register when labels that are upto 17-bit wide are used: : # x10 is expected to have address of function bar() lpsll $0x1de # setup lplr.LL with value 0x1de lpsml $0x17 # setup lplr.ML with value 0x17 jalr %ra, %x10 : The following instruction sequence may be emitted at indirect call sites by the compiler to set up the landing pads at entrypoint of function bar(): bar: lpcll $0x1de # Verifies that LPLR.LL matches 0x1de lpcml $0x17 # Verifies that LPLR.ML matches 0x17 : # continue if landing pad checks succeed |
A lpsul
instruction is provided to set the value of upper label (UL
) field lplr
.
This instruction is used when labels wider than 17-bit are used.
The operation of this instruction is as follows:
lpsul
operationIf xFCFIACT == 1
lplr.ML = inst.MLPL
else
[rd] = 0;
endif
Note
|
The following instruction sequence may be emitted at indirect call sites by the compiler to set up the landing pad label register when labels that are upto 25-bit wide are used: : # x10 is expected to have address of function bar() lpsll $0x1de # setup lplr.LL with value 0x1de lpsml $0x17 # setup lplr.ML with value 0x17 lpsul $0x13 # setup lplr.UL with value 0x13 jalr %ra, %x10 : The following instruction sequence may be emitted at indirect call sites by the compiler to set up the landing pads at entrypoint of function bar(): bar: lpcll $0x1de # Verifies that LPLR.LL matches 0x1de lpcml $0x17 # Verifies that LPLR.ML matches 0x17 lpcul $0x13 # Verifies that LPLR.ML matches 0x13 : # continue if landing pad checks succeed : |
A trap may need to be delivered to the same or higher privilege level on
completion of JALR but before the instruction at the target of JALR was decoded.
To avoid losing previous ELP state, MPELP and SPELP bits are provided in the
mcfistatus CSR for M-mode and HS/S-mode respectively. The SPELP
bits can be
accessed through the scfistatus
CSR. To avoid losing ELP
state on traps to
VS-mode, SPELP
bits are provided in vcfistatus
(VS-modes version of
scfistatus
) to hold the ELP
. When a trap is taken into VS-mode, the SPELP
bits of vcfistatus
CSR are updated with ELP
. When V=1
, scfistatus
aliases to vcfistatus
CSR. The xPELP
fields in mcfistatus
and vcfistatus
are WARL fields. The trap handler should preserve the lplr
CSR.
When a trap is taken into privilege mode x
, the xELP
bits are updated with
current ELP
and ELP
is set to NO_LP_EXPECTED
.
MRET
or SRET
instruction is used to return from a trap in M-mode or S-mode
respectively. When executing an xRET
instruction, the ELP
is set to xPELP
and xPELP is set to NO_LP_EXPECTED
. The trap handler should put back the
preserved lplr
value before invoking SRET
or MRET
.