diff --git a/spec/std/isa/csr/jvt.yaml b/spec/std/isa/csr/jvt.yaml new file mode 100644 index 000000000..dc69e00ed --- /dev/null +++ b/spec/std/isa/csr/jvt.yaml @@ -0,0 +1,120 @@ +# Copyright (c) Katherine Hsu +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# 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() != PrivilegeMode::M) && implemented?(ExtensionName::Smstateen)) { + if (CSR[mstateen0].JVT == 1'b0) { + unimplemented_csr($encoding); + } + } + else if ((mode() == PrivilegeMode::U) && implemented?(ExtensionName::Ssstateen)) { + if (CSR[sstateen0].JVT == 1'b0) { + unimplemented_csr($encoding); + } + } + else if ((mode() == PrivilegeMode::VS) && implemented?(ExtensionName::Ssstateen)) { + if (CSR[hstateen0].JVT == 1'b0) { + unimplemented_csr($encoding); + } + } + else if ((mode() == PrivilegeMode::VU) && implemented?(ExtensionName::Ssstateen)) { + if ((CSR[sstateen0].JVT == 1'b0) || (CSR[hstateen0].JVT == 1'b0)) { + unimplemented_csr($encoding); + } + } + 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(): | + if (JVT_READ_ONLY) { + return CsrFieldType::RO; + } + else { + return CsrFieldType::RW; + } + reset_value: 0 + sw_write(csr_value): | + if (JVT_READ_ONLY || (csr_value.MODE != 0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + return 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() != PrivilegeMode::M) && implemented?(ExtensionName::Smstateen)) { + if (CSR[mstateen0].JVT == 1'b0) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } + } + else if ((mode() == PrivilegeMode::U) && implemented?(ExtensionName::Ssstateen)) { + if (CSR[sstateen0].JVT == 1'b0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } + else if ((mode() == PrivilegeMode::VS) && implemented?(ExtensionName::Ssstateen)) { + if (CSR[hstateen0].JVT == 1'b0) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } + } + else if ((mode() == PrivilegeMode::VU) && implemented?(ExtensionName::Ssstateen)) { + if ((CSR[sstateen0].JVT == 1'b0) || (CSR[hstateen0].JVT == 1'b0)) { + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); + } + } diff --git a/spec/std/isa/ext/Zcmt.yaml b/spec/std/isa/ext/Zcmt.yaml index 9696d3761..35c945cfc 100644 --- a/spec/std/isa/ext/Zcmt.yaml +++ b/spec/std/isa/ext/Zcmt.yaml @@ -1,4 +1,4 @@ -# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Qualcomm Technologies, Inc. and Katherine Hsu # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../schemas/ext_schema.json @@ -95,6 +95,30 @@ versions: # - [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 MSTATEEN_JVT_TYPE: when: name: Smstateen