Skip to content

Add JVT CSR #782

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

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
106 changes: 106 additions & 0 deletions arch/csr/jvt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# yaml-language-server: $schema=../../schemas/csr_schema.json

$schema: "csr_schema.json#"
kind: csr
name: jvt
long_name: Table Jump Base Vector and Control Register
address: 0x017
description:
- id: csr-jvt-purpose
normative: true
text: |
The `jvt` register is an XLEN-bit WARL read/write register that holds the jump table configuration,
consisting of the jump table base address (BASE) and the jump table mode (MODE).
- id: csr-jvt-architectural
normative: false
text: |
`jvt` CSR adds architectural state to the system software context (such as an OS process), therefore
must be saved/restored on context switches.
priv_mode: U
length: XLEN
definedBy: Zcmt
fields:
BASE:
location_rv64: 63-6
location_rv32: 31-6
description: |
The value in the BASE field must always be aligned on a 64-byte boundary. Note that the CSR contains only
bits XLEN-1 through 6 of the address base. When computing jump-table accesses, the lower six bits of base
are filled with zeroes to obtain an XLEN-bit jump-table base address `jvt.base` that is always aligned on a
64-byte boundary.

`jvt.base` is a virtual address, whenever virtual memory is enabled.

The memory pointed to by `jvt.base` is treated as instruction memory for the purpose of executing table
jump instructions, implying execute access permission.
type(): |
if (JVT_READ_ONLY) {
return CsrFieldType::RO;
}
else {
return CsrFieldType::RW;
}
reset_value: UNDEFINED_LEGAL
sw_write(csr_value): |
if ((mode() != PrivMode::M) && implemented?(ExtensionName::Smstateen)) {
if (CSR[mstateen0].JVT == 1'b0) {
unimplemented_csr();
}
}
else if ((mode() == PrivMode::U) && implemented?(ExtensionName::Ssstaten)) {
if (CSR[sstateen0].JVT == 1'b0) {
unimplemented_csr();
}
}
else if ((mode() == PrivMode::VS) && implemented?(ExtensionName::Ssstaten)) {
if (CSR[hstateen0].JVT == 1'b0) {
unimplemented_csr();
}
}
else if ((mode() == PrivMode::VU) && implemented?(ExtensionName::Ssstateen)) {
if ((CSR[sstateen0].JVT == 1'b0) || (CSR[hstateen0].JVT == 1'b0)) {
unimplemented_csr();
}
}
else {
if (JVT_BASE_TYPE == "custom") {
unpredictable("jvt.BASE has custom behavior");
} else {
return csr_value.BASE & (JVT_BASE_MASK >> 6);
}
return csr_value.BASE == 0 ? 0 : UNDEFINED_LEGAL_DETERMINISTIC;
}
MODE:
location: 5-0
description: |
`jvt.mode` is a WARL field, so can only be programmed to modes which are implemented. Therefore the
discovery mechanism is to attempt to program different modes and read back the values to see which
are available. Jump table mode must be implemented.
type: RO
reset_value: 0
sw_read(): |
# If the Smstateen extension is implemented, then bit 2 in `mstateen0`, `sstateen0`, and `hstateen0` is
# implemented. If bit 2 of a controlling `stateen0` CSR is zero, then access to the `jvt` CSR and execution
# of a `cm.jalt` or `cm.jt` instruction by a lower privilege level results in an illegal-instruction trap (or, if
# appropriate, a virtual-instruction trap).

if ((mode() != PrivMode::M) && implemented?(ExtensionName::Smstateen)) {
if (CSR[mstateen0].JVT == 1'b0) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
}
else if ((mode() == PrivMode::U) && implemented?(ExtensionName::Ssstaten)) {
if (CSR[sstateen0].JVT == 1'b0) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
}
else if ((mode() == PrivMode::VS) && implemented?(ExtensionName::Ssstaten)) {
if (CSR[hstateen0].JVT == 1'b0) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
}
else if ((mode() == PrivMode::VU) && implemented?(ExtensionName::Ssstateen)) {
if ((CSR[sstateen0].JVT == 1'b0) || (CSR[hstateen0].JVT == 1'b0)) {
raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
}
26 changes: 26 additions & 0 deletions arch/ext/Zcmt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,29 @@ versions:
# - [Zcb, "1.0.0"]
# - [Zcmp, "1.0.0"]
# - [Zcmt, "1.0.0"]

params:
JVT_BASE_TYPE:
schema:
type: string
enum: [mask, custom]
description: |
Type of the jvt.BASE CSR field. One of:

* mask: jvt.BASE contains one or more implemented bits, which are indicated by JVT_BASE_MASK.
* custom: Custom behavior. Will cause hart to enter 'unpredictable' state on a write to jvt.BASE.
JVT_BASE_MASK:
schema:
type: integer
minimum: 64
maximum: 0x7ffffffffffffff # 58 bits
required_if(): return JVT_BASE_TYPE == "mask";
description: |
Mask representing the implemented bits of jvt.BASE. Includes the implicitly-zero bits of jvt.BASE, so JVT_BASE_MASK[5:0] must always be 0.
extra_validation: |
assert JVT_BASE_MASK < 0xffffffc0 if MXLEN == 32
JVT_READ_ONLY:
schema:
type: boolean
description: |
If Zcmt is implemented, JVT is implemented, but can contain a read-only value
Loading