Version Information: Version 1.0 +Caplifive
Other formats: This document is also available in the following formats:
1. Introduction
Capstone is a CPU instruction set architecture (ISA) that creates a single unified architectural abstraction for achieving multiple security goals, thus liberating software developers from the burden of working with the distinct fundamental primitives exposed by numerous security extensions that often do not interoperate easily.
1.1. Supported Properties
The ultimate goal of Capstone is to provide a unified architectural abstraction for multiple security goals. This goal requires Capstone to support the following properties.
- Exclusive access
Software should be guaranteed exclusive access to certain memory regions if needed. This is in spite of the existence of software traditionally entitled to higher privileges such as the OS kernel and the hypervisor.
- Revocable delegation
Software components should be able to delegate authority to other components in a revocable manner. For example, after an untrusted library function has been granted access to a memory region, the caller should be able to revoke this access.
- Dynamically extensible hierarchy
The hierarchy of authority should be dynamically extensible, rather than predefined by the architecture such as hypervisor-kernel-user found in traditional platforms. This makes it possible to use the same set of abstractions for memory isolation and memory sharing regardless of where a software component lies in the hierarchy.
- Safe context switching
A mechanism that protects the confidentiality and integrity of the execution context of software during control flow transfers across security domain boundaries, including asynchronous ones such as those for interrupt and exception handling, should be provided.
1.2. Major Design Elements
The Capstone architecture design is based on the idea of capabilities, which are unforgeable tokens that represent authority to perform memory accesses and control flow transfers, among other operations. Capstone extends the basic capability model with new capability types including the following.
- Linear capabilities
Linear capabilities are guaranteed not to alias with other capabilities that both grant memory access and are in architecturally visible locations (i.e., their actual contents might affect the execution of the whole system). Operations on linear capabilities maintain this property. For example, instructions can only move, but not copy, linear capabilities between general-purpose registers. They can hence enable safe exclusive access to memory regions. Capabilities that do not have this property are called non-linear capabilities.
- Revocation capabilities
Revocation capabilities cannot be used to perform memory accesses or control flow transfers. Instead, they convey the authority to revoke other capabilities. Each revocation capability is derived from a linear capability and can later be used to revoke (i.e., invalidate) capabilities derived from it. This mechanism enables revocable and arbitrarily extensible chains of delegation of authority.
- Uninitialised capabilities
Uninitialised capabilities convey write-only authority to memory. They can be turned into linear capabilities after the memory region has been “initialised”, i.e., when the whole memory region has been overwritten with fresh data. Uninitialised capabilities enable safe initialisation of memory regions and prevent secret leakage without incurring extra performance overhead.
1.3. Capstone-RISC-V ISA Overview
While Capstone does not assume any specific modern ISA, we choose to propose a Capstone variant to RISC-V due to its open nature and the availability of toolchains and simulators.
The Capstone-RISC-V ISA is an RV64IZicsr variant that makes the following types of changes to the base architecture:
-
Each general-purpose register is extended to 129 bits to accommodate 128-bit capabilities.
-
Part of the machine state is extended and new instructions are added to support it.
-
New instructions for manipulating capabilities are added.
-
New instructions for memory accesses using capabilities are added.
-
New instructions for control flow transfers using capabilities are added.
-
Semantics of some existing instructions are adjusted to support capabilities.
-
Semantics of interrupts and exceptions are adjusted to support capabilities.
1.4. Caplifive Extension
This document describes a version of Capstone-RISC-V with the Caplifive extension, which enables Capstone to support guest machines with traditional access control abstractions. This is achieved through the idea of caplification: it allows exposing capability-backed physical memory regions to lower privilege levels through a modified PMP (Physical Memory Protection) structure which requires valid capabilities in its entries instead of arbitrary ranges and permissions.
Compared to vanilla Capstone-RISC-V, Capstone-RISC-V with Caplifive defines domain internal structures which can consist of privilege levels found in traditional architectures. The highest privilege level operates using capabilities in the same way as in vanilla Capstone-RISC-V, whereas lower privilege levels are exposed to an abstraction compatible with that on traditional architectures. In particular, Caplifive allows software in lower privilege levels to access memory using raw addresses and potentially through virtual memory, as long as the access is allowed according to the capabilities configured in the modified PMP structure. Note that such details are internal to each domain itself. Across domains, software interacts using capabilities in the same way as in vanilla Capstone-RISC-V.
The Caplifive extension additionally includes the following changes:
-
Introduction of C-mode and a mechanism to enter it from M-mode.
-
Mechanism to post V-interrupts to a domain.
-
Mechanism to expose capabilities in C-mode to lower privilege levels.
1.5. Assembly Mnemonics
Each Capstone-RISC-V instruction is given a mnemonic prefixed with CS.
.
In contexts where it is clear we are discussing Capstone-RISC-V instructions,
we will omit the CS.
prefix for brevity.
In assembly code, the list of operands to an instruction is supplied following the
instruction mnemonic, with the operands separated by commas, in the order of
rd
, rs1
, rs2
, imm
for any operand the instruction expects.
1.6. Notations
When specifying the semantics of instructions, we use the following notations to represent the type of each operand:
- I
-
Integer register.
- C
-
Capability register.
- S
-
Sign-extended immediate.
- Z
-
Zero-extended immediate.
1.7. Bibliography
The initial motivation, design, evaluation, and analysis of Capstone have been discussed in the following paper:
-
Capstone: A Capability-based Foundation for Trustless Secure Memory Access by Jason Zhijingcheng Yu, Conrad Watt, Aditya Badole, Trevor E. Carlson, Prateek Saxena. In Proceedings of the 32nd USENIX Security Symposium. Anaheim, CA, USA. August 2023.
2. Programming Model
The Capstone-RISC-V ISA has extended part of the machine state, including both some registers and the memory, to enable the storage and handling of capabilities.
2.1. Modes
At any point in time, a hart operates in one of the following modes (mode ID in parentheses):
-
U-mode (0)
-
S-mode (1)
-
M-mode (3)
-
C-mode (3)
U-, S-, and M-modes already exist in the base RV64IZicsr ISA. When operating in those modes, the hart follows the same behaviours as defined in RV64IZicsr, e.g., using physical addresses for memory accesses in M-mode and virtual addresses for memory accesses if the virtual memory is enabled in S-mode and U-mode.
C-mode (capability mode) is an extra privilege level
introduced in the Caplifive extension.
It replaces M-mode when CAPSTONE_EN = 1
(CAPSTONE_EN
is a single-bit hart-local state).
When operating in C-mode, the hart is required to use capabilities for
accessing the memory (including fetching instructions).
C-mode exposes the same set of interfaces to S-mode and
U-mode as M-mode does.
For example, C-mode can handle undelegated interrupts and exceptions from S-mode
and U-mode.
Whether CAPSTONE_EN = 1
is therefore transparent to S-mode and U-mode, which
can interact with C-mode in the same way as with M-mode.
2.2. Domains
When CAPSTONE_EN = 1
, the run-time state of the system is organised in individual compartments
called domains.
Each domain includes the execution context of a logical thread.
A hart at any point in time executes in exactly one domain.
When a domain is running on a hart, the following events are notable:
-
Execution of CALL and RETURN instructions: Those instructions receive arguments that specify another domain and trigger a synchronous domain switch.
-
Exceptions: An exception is triggered by the execution of a specific instruction in the current domain. Since the event is local to the domain itself, it does not trigger a domain switch. Instead, exceptions are handled within the same domain that triggers them.
-
Interrupts: Unlike exceptions, interrupts are triggered by external factors rather than by specific instructions executed in the domain. We distinguish two types of interrupts which are handled differently:
-
H-interrupts (hardware interrupts): Those are interrupts the hart receives from interrupt controllers (either hart-local or platform-wide). Since such interrupts are not intended for specific domains (interrupt controllers and the I/O devices behind them are not aware of domains), a switch to a dedicated interrupt handler domain is required to handle them.
-
V-interrupts (virtual interrupts): Those are asynchronous events sent between domains. Unlike H-interrupts, a V-interrupt targets a specific domain and therefore does not trigger a domain switch, but is instead handled within the domain itself.
-
We call the first domain that runs on a hart after its reset the genesis domain of the hart.
2.3. Capabilities
2.3.1. Width
The width of a capability is 128 bits. We represent this as
CLEN = 128
and CLENBYTES = 16
. Note that this does not
affect the width of a raw address, which is XLEN = 64
bits,
or equivalently, XLENBYTES = 8
bytes, same as
in RV64IZicsr.
2.3.2. Fields
Each capability has the following architecturally-visible fields:
Name | Range | Description |
---|---|---|
|
|
Whether the capability is valid: |
|
|
The type of the capability:
|
|
|
Not applicable when |
|
|
The base memory address of the memory region associated with the capability |
|
|
Not applicable when |
|
|
Not applicable when |
|
|
Only applicable when |
|
|
Only applicable when |
The range of the perms
field has a partial order <=p
defined as follows:
<=p = { (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (1, 1), (1, 3), (1, 5), (1, 7), (2, 2), (2, 3), (2, 6), (2, 7), (3, 3), (3, 7), (4, 4), (4, 5), (4, 6), (4, 7), (5, 5), (5, 7), (6, 6), (6, 7), (7, 7) }
We say a capability c
aliases with a capability d
if and only if the intersection
between [c.base, c.end]
and [d.base, d.end]
is non-empty.
For two revocation capabilities c
and d
(i.e., c.type = d.type = 2
),
we say c <t d
if and only if
-
c
aliases withd
-
The creation of
c
was earlier than the creation ofd
In addition to the above fields, an implementation also needs to maintain
sufficient metadata to test the <t
relation.
It will be clear that for any pair of aliasing revocation capabilities,
the order of their creations is well-defined.
Note: the implementation of valid
field
Note: addition/compression to capability fields
For different types of capabilities, a specific subset of the fields is used. The table below summarises the fields used for each type of capabilities.
Type | type |
valid |
cursor |
base |
end |
perms |
async |
reg |
---|---|---|---|---|---|---|---|---|
Linear |
|
Yes |
Yes |
Yes |
Yes |
Yes |
- |
- |
Non-linear |
|
Yes |
Yes |
Yes |
Yes |
Yes |
- |
- |
Revocation |
|
Yes |
Yes |
Yes |
Yes |
Yes |
- |
- |
Uninitialised |
|
Yes |
Yes |
Yes |
Yes |
Yes |
- |
- |
Sealed |
|
Yes |
- |
Yes |
- |
- |
Yes |
- |
Sealed-return |
|
Yes |
Yes |
- |
- |
Yes |
Yes |
When the async
field of a sealed-return capability is 0
(synchronous),
some memory accesses are granted by this capability.
The following table shows the memory accesses granted in such scenarios,
where size
is the size of the memory access in bytes.
Note
|
In an earlier version a sealed-return capability has a cursor and grants direct load/store accesses. This is no more the case. |
In other scenarios and for other capability types without the perms
field, no read/write/execute
memory accesses are granted by the capability.
The following figure shows the overview of different types of capabilities in the Capstone-RISC-V ISA, and the operations that change the type of a capability.
2.4. Extension to General-Purpose Registers
The Capstone-RISC-V ISA extends each of the 32 general-purpose
registers, so it contains either a capability or a raw XLEN
-bit
integer.
The type of data contained in a register is maintained and type confusion is not allowed, except for x0
/c0
as discussed below.
In assembly code, the type of data expected in a register operand
is indicated by the alias used for the register, as summarised
in the following table.
Index | XLEN -bit integer |
Capability |
---|---|---|
0 |
|
|
1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
|
21 |
|
|
22 |
|
|
23 |
|
|
24 |
|
|
25 |
|
|
26 |
|
|
27 |
|
|
28 |
|
|
29 |
|
|
30 |
|
|
31 |
|
|
x0
/c0
is a read-only register that can be used both as an
integer and as a capability, depending on the context. When used
as an integer, it has the value 0
.
When used as a capability, it has the value
{ valid = 0, type = 0, cursor = 0, base = 0, end = 0, perms = 0 }
.
Any attempt to write to x0
/c0
will be silently ignored (no
exceptions are raised).
In this document,
for i = 0, 1, …, 31
, we use x[i]
to refer to the general-purpose
register with index i
.
2.5. Extension to Other Registers
2.5.1. Program Counter
The program counter (pc
) is changed to contain a capability only.
During the instruction fetch stage, an exception is raised when any of the following conditions is met:
If no exception is raised:
-
The instruction pointed to by
pc.cursor
is fetched and executed. -
Set
pc.cursor
topc.cursor + 4
at the end of the instruction.
2.6. M-Mode Registers in C-Mode
The following M-mode CSRs are available in C-mode without any changes:
-
mstatus
-
medeleg
-
mideleg
-
mip
-
mie
-
mcause
-
mtval
-
mtval2
-
mtinst
We also refer to the above CSRs using their aliases (with the m
- prefix replaced c
-)
in the C-mode context.
The M-mode CSRs mtvec
, mscratch
, and mepc
have their corresponding
capability-extended replacements available in C-mode, as described in the
following section.
2.7. Added Registers
The Capstone-RISC-V ISA adds the following registers. The +h sign indicates that the register is available in the hypervisor extension.
Mnemonic | CCSR encoding | CSR encoding | Description |
---|---|---|---|
|
|
- |
The PC entry for the exception and V-interrupt handler (replacing |
|
|
- |
The sealed capability for the H-interrupt handler |
|
|
- |
The exception program counter register (replacing |
|
|
- |
Replacing |
|
|
- |
Capability for use with MMU-based memory accesses |
|
- |
|
The H-interrupt status register |
|
- |
|
The H-interrupt delegation register. If a bit is set, the H-interrupt is transformed into the corresponding V-interrupt directly |
|
- |
|
The H-interrupt number register. Indicates the type of the H-interrupt |
|
- |
|
Offset to add to the logical address to obtain the physical address |
Some of the registers only allow capability values and have special semantics related to the system-wide machine state. They are referred to as capability control and status registers (CCSRs). Under their respective constraints, CCSRs can be manipulated using control and status instructions.
The manipulation constraints for each CCSR are indicated below.
Mnemonic | Read | Write |
---|---|---|
|
No constraint |
No constraint |
|
Not allowed |
The original content must not be a capability |
|
No constraint |
No constraint |
Some of the registers are added as control and status registers (CSRs). These registers are manipulated by the same instructions that manipulate CSRs as in RV64IZicsr. When the manipulation constraints of these additional CSRs are not satisfied, the behaviour of these instructions follows the RV64IZicsr convention for other CSRs.
The manipulation constraints for each additional CSR are indicated below.
Mnemonic | Read | Write |
---|---|---|
|
No constraint |
No constraint |
|
No constraint |
No constraint |
Note: ctvec
and cih
2.8. Register Scopes
Each register has a scope that is either of the following:
-
Domain: the register is specific to a domain
-
Hart: the register is specific not to a domain, but to a hart
2.8.1. Domain-Scoped Registers
-
PC:
pc
-
GPRs:
x1
,x2
, …,x31
-
CCSRs:
ctvec
,cepc
,cpmp0-15
,cscratch
-
64-bit CSRs:
mstatus
,mideleg
,medeleg
,mip
,mie
,mcause
,mtval
,mtval2
,mtinst
,stvec
,scause
,stval
,sepc
,sscratch
,satp
,offsetmmu
Note that the complete domain-scope state also includes the privilege
level, which is not reflected in any of the registers above.
Hence, we propose a modified mstatus
register that includes
the current privilege level (0 — 3) in bits 38 and 39, but only in the context of
saving or restoring domain-scoped registers.
2.8.2. Hart-Scoped Registers
Registers cis
, cid
, and cih
are hart-scoped.
2.9. Register Effects
Domain-scoped registers that can immediately affect the behaviours of a domain in C-mode include
pc
, ctvec
, cscratch
, mstatus
, mideleg
, medeleg
, mip
, mie
.
We call such registers C-effective registers.
2.10. Context Layout in Memory
Under certain circumstances, a set of registers need to be mapped to memory locations in an architecturally-defined layout. For example, some registers need to be saved or restored upon context switches. In such cases, unless otherwise specified, the layout for both domain-scoped registers and C-effective registers follows the following order without any padding:
-
C-effective registers (PC and CCSRs, 16 bytes):
pc
,ctvec
,cscratch
-
C-effective registers (CSRs, 8 bytes):
mstatus
,mideleg
,medeleg
,mip
,mie
-
offsetmmu
(8 bytes) -
cpmp0-15
,cepc
(16 bytes) -
x1
,x2
, …,x31
(16 bytes) -
mcause
,mtval
,mtval2
,mtinst
,stvec
,scause
,stval
,sepc
,sscratch
,satp
(8 bytes)
Note
|
The layout described above takes care of the alignment maintains the same register offsets for domain-scoped contexts and C-effective contexts, making it possible to use a domain-scoped context as a C-effective context. When a C-effective context swapped in (loaded into the CPU state), and a domain-scoped context is swapped out (offloaded from the CPU state into memory), registers that are domain-scoped but not C-effective are scrubbed. |
2.11. Extension to Memory
The memory is addressed using an XLEN
-bit integer at byte-level
granularity.
In addition to raw integers, each CLEN
-bit aligned address can
also store a capability.
The type of data contained in a memory location is maintained and
confusion of the type is not allowed.
Note: maintaining the type of data
The physical memory can only be accessed through capabilities.
Address Space | Access Method |
---|---|
|
Capabilities |
Note: undefined behaviour
2.12. Instruction Set
The Capstone-RISC-V instruction set is based on the RV64IZicsr instruction set.
The (uncompressed) instructions are fixed 32-bit wide, and laid out in memory
in little-endian order. In the encoding space of the RV64IZicsr instruction set,
Capstone-RISC-V instructions occupies the “custom-2” subset, i.e., the opcode
of all Capstone-RISC-V instructions is 0b1011011
.
Capstone-RISC-V instruction encodings follow three basic formats: R-type, I-type and S-type, as described below (more details are also provided in the RISC-V ISA Manual).
R-type instructions receive up to three register operands, and I-type/S-type instructions receive up to two register operands and a 12-bit-wide immediate operand.
The Capstone-RISC-V ISA also uses a register operand of R-type as an immediate operand in some instructions, which is called register-immediate (RI) type for convenience in this document.
The RI-type instruction format is derived from the R-type instruction format. An RI-type instruction receives up to two register operands and a 5-bit-wide immediate operand.
Unless otherwise specified, the instructions introduced in Capstone-RISC-V on top of
the base RV64IZicsr instruction set are available in C-mode only.
Attempts to execute them in other modes trigger Illegal instruction (2)
exceptions.
2.13. System Reset
Upon reset, the system state must conform to the following specifications.
3. Capability Manipulation Instructions
Capstone provides instructions for creating, modifying, and destroying capabilities. Note that due to the guarantee of provenance of capabilities, those instructions are the only way to manipulate capabilities. In particular, it is not possible to manipulate capabilities by manipulating the content of a memory location or register using other instructions.
3.1. Cursor, Bounds, and Permissions Manipulation
3.1.1. Capability Movement
Capabilities can be moved between registers with the MOVC instruction.
No exception could be raised for MOVC.
-
If
rs1 = rd
, the instruction is a no-op. -
Otherwise
-
Write
x[rs1]
tox[rd]
. -
If
x[rs1]
is not a non-linear capability (i.e.,type != 1
), writecnull
tox[rs1]
.
-
3.1.2. Cursor Increment
The CINCOFFSET and CINCOFFSETIMM instructions increment the cursor
of a
capability by a given amount (offset).
CINCOFFSET
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Set
val
tox[rs2]
. -
MOVC rd, rs1
. -
Set
x[rd].cursor
tox[rd].cursor + val
.
CINCOFFSETIMM
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
MOVC rd, rs1
. -
Set
x[rd].cursor
tox[rd].cursor + imm
.
3.1.3. Cursor Setter
The cursor
field of a capability can also be directly set with the SCC instruction.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Set
val
tox[rs2]
. -
MOVC rd, rs1
. -
Set
x[rd].cursor
toval
.
3.1.4. Field Query
The LCC instruction is used to read a field from a capability.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
If
imm > 7
, writezero
tox[rd]
-
Otherwise, write
field
tox[rd]
according to the LCC multiplexing table.
imm |
field |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3.1.5. Bounds Shrinking
The bounds (base
and end
fields) of a capability can be shrunk with the SHRINK instruction.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Set
x[rd].base
tox[rs1]
andx[rd].end
tox[rs2]
. -
If
x[rd].cursor < x[rs1]
, setx[rd].cursor
tox[rs1]
. -
If
x[rd].cursor > x[rs2]
, setx[rd].cursor
tox[rs2]
.
Another instruction, SHRINKTO, provides more convenience for certain common special cases of shrinking.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
MOVC rd, rs1
. -
Set
x[rd].base
tox[rd].cursor
andx[rd].end
tox[rd].cursor + imm - 1
.
3.1.6. Bounds Splitting
The SPLIT instruction can split a capability into two by splitting the bounds.
It attempts to split the capability x[rs1]
into two capabilities,
one with bounds [x[rs1].base, x[rs2])
and the other with bounds [x[rs2], x[rs1].end)
.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
If
rs1 = rd
, the instruction is a no-op. -
Set
val
tox[rs2]
. -
Write
x[rs1]
tox[rd]
. -
Set
x[rs1].end
toval
,x[rs1].cursor
tox[rs1].base
. -
Set
x[rd].base
toval + 1
,x[rd].cursor
toval + 1
.
3.1.7. Permission Tightening
The TIGHTEN instruction tightens the permissions (perms
field) of a capability.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
MOVC rd, rs1
. -
If
imm > 7
, setx[rd].perms
to0
. Otherwise, setx[rd].perms
toimm
.
3.2. Type Manipulation
Some instructions can affect the type
field of a capability directly.
In general, the type
field cannot be set arbitrarily.
Instead, it is changed as the side effect of certain semantically significant operations.
3.2.1. Delinearisation
The DELIN instruction delinearises a linear capability.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Set
x[rd].type
to1
(non-linear).
3.2.2. Initialisation
The INIT instruction transforms an uninitialised capability into a linear capability after its associated memory region has been fully initialised (written with new data).
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Set
val
tox[rs2]
. -
MOVC rd, rs1
. -
Set
x[rd].type
to0
(linear), andx[rd].cursor
tox[rd].base + val
.
3.2.3. Sealing
The SEAL instruction seals a linear capability.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
MOVC rd, rs1
. -
Set
x[rd].type
to2
(sealed), andx[rd].async
to0
(synchronous).
3.3. Dropping
The DROP instruction invalidates a capability.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
If
x[rs1].valid
is0
(invalid), the instruction is a no-op. -
Otherwise, set
x[rs1].valid
to0
(invalid).
3.4. Revocation
3.4.1. Revocation Capability Creation
The MREV instruction creates a revocation capability.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Write
x[rs1]
tox[rd]
. -
Set
x[rd].type
to2
(revocation).
3.4.2. Revocation Operation
The REVOKE instruction revokes a capability.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
For each capability
c
in the system (in either a register or memory location),c.valid
is set to0
(invalid) if any of the following conditions are met: -
x[rs1].type
is set to0
(linear) if at least one of the following conditions are met:-
For every invalidated capability
c
, the type ofc
is non-linear (i.e.,c.type
is1
). -
2 <=p x[rs1].perms
does not hold.
-
-
Otherwise, set
x[rs1].type
to3
(uninitialised), andx[rs1].cursor
tox[rs1].base
.
4. Memory Access Instructions
Capstone provides instructions to load and store capabilities from/to memory regions.
4.1. Load Capabilities
The LDC instruction loads a capability or an integer scalar from the memory depending on the type of data at the specified memory location.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Set
cap
tox[rs1]
. -
Load the capability at the memory location
cap.cursor + imm, cap.cursor + imm + CLENBYTES)
intox[rd]
. -
If
x[rd].type
is not1
(non-linear), writecnull
to the memory location[cap.cursor + imm, cap.cursor + imm + CLENBYTES)
.
4.2. Store Capabilities
The STC instruction stores a capability or an integer scalar to the memory, depending on the type of data contained in the specified source register.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Store
x[rs2]
to the memory location[x[rs1].cursor + imm, x[rs1].cursor + imm + CLENBYTES)
. -
If
x[rs1].type
is3
(uninitialised), setx[rs1].cursor
tox[rs1].cursor + CLENBYTES
. -
If
x[rs2]
is a capability andx[rs2].type
is not1
(non-linear), writecnull
tox[rs2]
.
5. Control Flow Instructions
5.1. Jump to Capabilities
The CJALR and CBNZ instructions allow jumping to a capability, i.e., setting the program counter to a given capability, in a unconditional or conditional manner.
5.1.1. CJALR
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Set
cap
tox[rs1]
. -
Set
pc.cursor
topc.cursor + 4
, writepc
tox[rd]
. -
Set
cap.cursor
tocap.cursor + imm
, writecap
topc
. -
If
rs1 != rd
andx[rs1].type != 1
, writecnull
tox[rs1]
.
5.1.2. CBNZ
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
If
x[rs1]
is0
, the instruction is a no-op. -
Otherwise
-
Write
x[rd]
topc
. -
Set
pc.cursor
topc.cursor + imm
. -
If
x[rd].type != 1
, writecnull
tox[rd]
.
-
5.2. Domain Crossing
Domains in the Capstone-RISC-V ISA are individual software compartments that are protected by a safe context switching mechanism, i.e., domain crossing. The mechanism is provided by the CALL and RETURN instructions.
5.2.1. CALL
The CALL instruction is used to call a sealed capability, i.e., to switch to another domain.
We define d
as the following:
-
If
rs1 != 0
, thend
is the content ofx[rs1]
. -
Otherwise, then
d
is the content ofcih
.
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
If
rs1 != 0
,MOVC cra, rs1
, or otherwiseCSRRW cra, cih, c0
. -
Swap C-effective registers with the memory content at address
cra.base
. -
Set
cra.type
to5
(sealed-return),cra.cursor
tocra.base
,cra.reg
tord
, andcra.async
to0
(synchronous).
5.2.2. RETURN
An exception is raised when any of the following conditions is met:
If no exception is raised:
When x[rd].async = 0
(synchronous):
-
Write
x[rd]
tocap
andcnull
tox[rd]
. -
Set
pc.cursor
tox[rs1]
. -
Swap C-effective registers with the memory content at address
cap.base
. -
If
cap.type = 5
andcap.reg != 0
, writecap
tox[cap.reg]
and setx[cap.reg].type
to4
(sealed). Otherwise, writecap
tocih
and setcih.type
to4
(sealed).
When x[rd].async = 1
(asynchronous):
-
Write
x[rs2]
toposted_ints
. -
Set
x[rd].type
to4
(sealed),x[rd].async
to0
(synchronous). -
Write the resulting
x[rd]
tocih
, andcnull
tox[rd]
. -
Set
pc.cursor
tox[rs1]
. -
Swap out the C-effective registers, and swap in domain-scoped registers from the memory content at address
cih.base
. -
Set
mip
tomip | posted_ints
.
6. Control and Status Instructions
The CCSRRW instruction is used to read and write specified capability control and status registers (CCSRs).
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
If the read constraint is satisfied
-
The content of the CCSR specified by
imm
is written tox[rd]
. -
If
x[rd].type
is not1
(non-linear), writecnull
to the CCSR specified byimm
.
-
-
Otherwise, write
cnull
tox[rd]
. -
If the write constraint is satisfied
-
Write
x[rs1]
to the CCSR specified byimm
. -
If
x[rs1].type
is not1
(non-linear), writecnull
tox[rs1]
.
-
-
Otherwise, preserve the current content of the CCSR specified by
imm
.
The CAPENTER instruction enables C-mode. Unlike the other added instructions which are for C-mode only, CAPENTER can be used in M-mode.
When C-mode is enabled, the CAPENTER instruction also initialises the genesis capabilities and create the initial execution context of the genesis domain.
An exception is raised when the following condition is met:
If no exception is raised:
-
If
rs1 == 0
andrs2 == 0
-
Set
pc = { valid = 1, type = 1, cursor = pc, base = INIT_CODE_BASE, end = INIT_CODE_END - 1, perms = 7 }
. -
Set
x10 = { valid = 1, type = 1, cursor = INIT_DATA_BASE, base = INIT_DATA_BASE, end = INIT_DATA_END - 1, perms = 7 }
. -
Set
x11 = { valid = 1, type = 2, cursor = 0, base = 0, end = 2^XLEN - 1, perms = 7 }
, which, once revoked, will invalidate the initial capabilities inpc
andx10
as defined above. -
Set
CAPSTONE_EN
to1
.
-
-
Otherwise
-
Set
pc = { valid = 1, type = 1, cursor = pc, base = x[rs1], end = x[rs2] - 1, perms = 7 }
. -
Set
x10 = { valid = 1, type = 1, cursor = 0, base = 0, end = x[rs1] - 1, perms = 7 }
. -
Set
x11 = { valid = 1, type = 1, cursor = x[rs2], base = x[rs2], end = 2^XLEN - 1, perms = 7 }
. -
Set
CAPSTONE_EN
to1
.
-
INIT_CODE_BASE
, INIT_CODE_END
, INIT_DATA_BASE
, and INIT_DATA_END
are
implementation-defined.
7. Adjustments to Existing Instructions
For most of the existing instructions in RV64IZicsr, their behaviour is unmodified.
The cursor
field (if type != 4
) or base
field (if type = 4
) of the capability is used
if a register containing a capability is used as an operand.
The following instructions in RV64IZicsr are adjusted in Capstone:
7.1. Memory Access Instructions
In RV64IZicsr, memory access instructions include load instructions
(i.e., lb
, lh
, ld
, lw
, lbu
, lhu
, lwu
), and store instructions (i.e., sb
, sh
, sw
, sd
).
These instructions take an integer as a raw address, and load or store a value from/to this address.
In Capstone, these instructions are extended to take a capability as an address
when executed in C-mode. In non-C modes, the behaviours of those instructions
are unchanged.
7.1.1. Load Instructions
In the Capstone-RISC-V ISA, RV64IZicsr load instructions are modified to load integers of different sizes using capabilities.
Note: size
of load instructions
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Load the content at the memory location
[x[rs1].cursor + imm, x[rs1].cursor + imm + size)
as a signed integer tox[rd]
.
If no exception is raised:
-
Load the content at the memory location
[x[rs1].cursor + imm, x[rs1].cursor + imm + size)
as an unsigned integer tox[rd]
.
7.1.2. Store Instructions
Note: size
of store instructions
An exception is raised when any of the following conditions is met:
If no exception is raised:
-
Store
x[rs2]
to the memory location[x[rs1].cursor + imm, x[rs1].cursor + imm + size)
as an integer.
7.2. Control Flow Instructions
In RV64IZicsr, conditional branch instructions (i.e., beq
, bne
, blt
, bge
, bltu
, and bgeu
),
and unconditional jump instructions (i.e., jal
and jalr
) are used to control the flow of execution.
In Capstone, these instructions are adjusted to support the situation where the program counter is a capability when executed in C-mode.
In non-C modes, the behaviours of those instructions are unchanged.
7.2.1. Branch Instructions
The following adjustments are made to these instructions:
7.2.2. Jump Instructions
The following adjustments are made to these instructions:
7.3. Illegal Instructions
C-mode can execute the following M-mode privileged instructions defined in Zicsr:
-
ECALL
-
EBREAK
-
MRET (also referred to as CRET in the C-mode context)
When a CSR that is available in M-mode but not
available in C-mode is accessed
in C-mode, an illegal instruction (2)
exception is raised.
8. Interrupts and Exceptions
The mechanisms described in this section only apply when C-mode is enabled,
i.e., when CAPSTONE_EN = 1
.
8.1. Exception Codes
We extend RV64IZicsr with the following extra exception codes:
Exception | Exception code |
---|---|
Unexpected operand type |
24 |
Invalid capability |
25 |
Unexpected capability type |
26 |
Insufficient capability permissions |
27 |
Capability out of bound |
28 |
Illegal operand value |
29 |
Insufficient system resources |
30 |
Those extra exception codes are only visible to C-mode. In other words, only C-mode software is allowed to handle those exceptions. They cannot be delegated to S-mode or U-mode.
For interrupts, the same encodings as in RV64IZicsr are used.
Note: Implementation specified exception
8.2. Exception Data
To provide the exception handler with extra exception-related
information along with the exception code,
Capstone-RISC-V follows the base RV64IZicsr and uses the CSRs xepc
, xtval
, xtval2
,
and xtinst
.
The only difference is that cepc
will hold a capability if the excepting state has a capability
pc
as in the case of a horizontal trap in C-mode.
For exceptions defined in RV64IZicsr, the data written to those CSRs remain unchanged. The data provided for the added exception types defined above are as follows:
Exception | xtval |
xtval2 |
xtinst |
---|---|---|---|
|
The instruction itself (or the lowest XLEN bits if it is wider than XLEN) |
||
|
The instruction itself (or the lowest XLEN bits if it is wider than XLEN) |
||
|
The instruction itself (or the lowest XLEN bits if it is wider than XLEN) |
||
|
The instruction itself (or the lowest XLEN bits if it is wider than XLEN) |
||
|
The instruction itself (or the lowest XLEN bits if it is wider than XLEN) |
||
|
The instruction itself (or the lowest XLEN bits if it is wider than XLEN) |
8.3. Overview of Interrupt and Exception Handling
With CAPSTONE_EN = 0
, the interrupt (H-interrupts only, as the notion of the V-interrupt does
not apply here) and exception handling mechanisms are same as
they are defined in RV64IZicsr.
With CAPSTONE_EN = 1
, the handling of exceptions and V-interrupts uses the same mechanisms
for exception and interrupt handling in RV64IZicsr, with the following minor changes:
-
C-mode replaces M-mode.
-
ctvec
does not support the vectored mode, and should be a capability. -
When the CPU traps into C-mode,
ctvec
andpc
must not both be integers. Ifctvec
is a capability,pc
is written intocepc
and replaced withctvec
, and ifctvec
is linear,ctvec
is replaced withctvec.cursor
. Ifctvec
is not a capability andpc
is a capability, then thepc.cursor
is written intocepc
and replaced withctvec
. Uponmret
, ifctvec
is not a capability, it is replaced withpc
withctvec.cursor
set to the originalctvec
value. -
cepc
can contain a capability. -
Extra exception and interrupt types are defined.
The handling of H-interrupts with CAPSTONE_EN = 1
is new.
The hart transfers the control flow to a dedicated H-interrupt handler domain
(specified in cih
).
The current context is saved and sealed in a sealed-return capability which
is then supplied to the H-interrupt handler domain as an argument.
When handling is complete,
the H-interrupt handler domain can use the RETURN instruction to resume the
execution of the excepted domain.
This process resembles that of a CALL-RETURN
pair, except that it is asynchronous, rather than synchronous,
to the execution of the original domain.
8.4. H-Interrupt Status
The cis
CSR encodes the control and status associated with H-interrupts.
The diagram below shows its layout.
cis
CSR layoutThe layout of cis
follows that of mip
in RV64IZicsr.
When a bit is set, the corresponding
H-interrupt is pending.
All the fields are read-write.
8.5. H-Interrupt Delegation
The cid
CSR specifies types of H-interrupts to delegate as V-interrupts
to the running domain. The layout of cid
is identical to that of cis
.
When a bit is set in cid
, the corresponding H-interrupt is not taken to
the interrupt handling domain defined in cih
, but handled within the currently
running domain as a corresponding C-mode V-interrupt.
8.6. Interaction with the Interrupt Controller
When the interrupt controller attempts to change the pending status of
an interrupt line for a hart, either mip
or cis
is affected.
Assuming the interrupt corresponds to bit x
in mip
and cis
,
the following is the criteria for deciding which of the two to operate
on:
-
If
CAPSTONE_EN = 0
,mip
is affected. -
If
CAPSTONE_EN = 1
,-
If
x
is clear incid
,cis
is affected. -
If
x
is set incid
,mip
is affected.
-
For example, if the interrupt controller wishes to clear the
machine timer interrupt pending bit (MTIP) when CAPSTONE_EN = 1
and the MTIP
bit in cid
is set, the MTIP
bit in mip
will
be cleared.
8.7. H-Interrupt Delivery
The H-interrupt delivery process starts with a certain event
typically asynchronous to the execution of the hart.
The sources of such events include the external interrupt controller,
the timer, and other CPU cores, which correspond to the external,
timer, and software H-interrupt types (i.e., x = E
, T
, and S
).
When such an event occurs, the xIP
field in the cis
register
is set to 1
to indicate that the H-interrupt is pending.
At any point during the execution of a hart,
if any xIP
field is set and at the same
time the cih
register contains
a capability, the H-interrupt is delivered to the H-interrupt handler
domain.
Note: global H-interrupt enable/disable
8.8. H-Interrupt Handling
The H-interrupt is ignored if any of the following conditions is met:
Otherwise:
-
Swap out the domain-scoped registers, and swap in C-effective registers from the memory content at address
cih.base
. -
Set
cih.type
to5
(sealed-return),cih.cursor
tocih.base
,cih.reg
to0
, andcih.async
to1
(upon interrupt). -
Write
cih
to the registercra
, andcnull
to the registercih
. -
Write the interrupt code to the register
a0
.
Appendix A: Instruction Listing
A.1. Capstone Instructions
Mnemonic | Format | Func3 | Func7 | rs1 | rs2 | rd | imm [4:0] | imm[11:0] |
---|---|---|---|---|---|---|---|---|
R |
|
|
C |
- |
- |
- |
- |
|
R |
|
|
I |
I |
C |
- |
- |
|
I |
|
- |
C |
- |
C |
- |
Z |
|
RI |
|
|
C |
- |
C |
Z |
- |
|
R |
|
|
- |
- |
C |
- |
- |
|
RI |
|
|
C |
- |
I |
Z |
- |
|
R |
|
|
C |
I |
C |
- |
- |
|
R |
|
|
C |
I |
C |
- |
- |
|
R |
|
|
C |
- |
C |
- |
- |
|
R |
|
|
C |
- |
C |
- |
- |
|
R |
|
|
C |
I |
C |
- |
- |
|
R |
|
|
C |
- |
C |
- |
- |
|
R |
|
|
C |
- |
- |
- |
- |
|
R |
|
|
C |
I |
C |
- |
- |
|
I |
|
- |
C |
- |
C |
- |
S |
Mnemonic | Format | emode |
Func3 | Func7 | rs1 | rs2 | rd | imm[11:0] |
---|---|---|---|---|---|---|---|---|
I |
- |
|
- |
C |
- |
C |
S |
|
S |
- |
|
- |
C |
C |
- |
S |
Mnemonic | Format | Func3 | Func7 | rs1 | rs2 | rd | imm[11:0] |
---|---|---|---|---|---|---|---|
R |
|
|
C |
- |
C |
- |
|
R |
|
|
C |
I |
- |
- |
|
I |
|
- |
C |
- |
C |
S |
|
I |
|
- |
I |
- |
C |
S |
Mnemonic | Format | Func3 | Func7 | rs1 | rs2 | rd | imm[11:0] |
---|---|---|---|---|---|---|---|
I |
|
- |
C |
- |
C |
Z |
|
R |
|
|
I |
I |
- |
- |
A.2. Adjusted RV64IZicsr Memory Access Instructions
Mnemonic | Format | Func3 | Func7 | rs1 | rs2 | rd | imm[11:0] |
---|---|---|---|---|---|---|---|
I |
|
- |
C |
- |
I |
S |
|
I |
|
- |
C |
- |
I |
S |
|
I |
|
- |
C |
- |
I |
S |
|
I |
|
- |
C |
- |
I |
S |
|
I |
|
- |
C |
- |
I |
S |
|
I |
|
- |
C |
- |
I |
S |
|
I |
|
- |
C |
- |
I |
S |
Mnemonic | Format | Func3 | Func7 | rs1 | rs2 | rd | imm[11:0] |
---|---|---|---|---|---|---|---|
S |
|
- |
C |
I |
- |
S |
|
S |
|
- |
C |
I |
- |
S |
|
S |
|
- |
C |
I |
- |
S |
|
S |
|
- |
C |
I |
- |
S |