|
| 1 | +# Copyright (c) Katherine Hsu |
| 2 | +# SPDX-License-Identifier: BSD-3-Clause-Clear |
| 3 | + |
| 4 | +# yaml-language-server: $schema=../../schemas/csr_schema.json |
| 5 | + |
| 6 | +$schema: "csr_schema.json#" |
| 7 | +kind: csr |
| 8 | +name: jvt |
| 9 | +long_name: Table Jump Base Vector and Control Register |
| 10 | +address: 0x017 |
| 11 | +description: |
| 12 | + - id: csr-jvt-purpose |
| 13 | + normative: true |
| 14 | + text: | |
| 15 | + The `jvt` register is an XLEN-bit WARL read/write register that holds the jump table configuration, |
| 16 | + consisting of the jump table base address (BASE) and the jump table mode (MODE). |
| 17 | + - id: csr-jvt-architectural |
| 18 | + normative: false |
| 19 | + text: | |
| 20 | + `jvt` CSR adds architectural state to the system software context (such as an OS process), therefore |
| 21 | + must be saved/restored on context switches. |
| 22 | +priv_mode: U |
| 23 | +length: XLEN |
| 24 | +definedBy: Zcmt |
| 25 | +fields: |
| 26 | + BASE: |
| 27 | + location_rv64: 63-6 |
| 28 | + location_rv32: 31-6 |
| 29 | + description: | |
| 30 | + The value in the BASE field must always be aligned on a 64-byte boundary. Note that the CSR contains only |
| 31 | + bits XLEN-1 through 6 of the address base. When computing jump-table accesses, the lower six bits of base |
| 32 | + are filled with zeroes to obtain an XLEN-bit jump-table base address `jvt.base` that is always aligned on a |
| 33 | + 64-byte boundary. |
| 34 | +
|
| 35 | + `jvt.base` is a virtual address, whenever virtual memory is enabled. |
| 36 | +
|
| 37 | + The memory pointed to by `jvt.base` is treated as instruction memory for the purpose of executing table |
| 38 | + jump instructions, implying execute access permission. |
| 39 | + type(): | |
| 40 | + if (JVT_READ_ONLY) { |
| 41 | + return CsrFieldType::RO; |
| 42 | + } |
| 43 | + else { |
| 44 | + return CsrFieldType::RW; |
| 45 | + } |
| 46 | + reset_value: UNDEFINED_LEGAL |
| 47 | + sw_write(csr_value): | |
| 48 | + if ((mode() != PrivilegeMode::M) && implemented?(ExtensionName::Smstateen)) { |
| 49 | + if (CSR[mstateen0].JVT == 1'b0) { |
| 50 | + unimplemented_csr($encoding); |
| 51 | + } |
| 52 | + } |
| 53 | + else if ((mode() == PrivilegeMode::U) && implemented?(ExtensionName::Ssstateen)) { |
| 54 | + if (CSR[sstateen0].JVT == 1'b0) { |
| 55 | + unimplemented_csr($encoding); |
| 56 | + } |
| 57 | + } |
| 58 | + else if ((mode() == PrivilegeMode::VS) && implemented?(ExtensionName::Ssstateen)) { |
| 59 | + if (CSR[hstateen0].JVT == 1'b0) { |
| 60 | + unimplemented_csr($encoding); |
| 61 | + } |
| 62 | + } |
| 63 | + else if ((mode() == PrivilegeMode::VU) && implemented?(ExtensionName::Ssstateen)) { |
| 64 | + if ((CSR[sstateen0].JVT == 1'b0) || (CSR[hstateen0].JVT == 1'b0)) { |
| 65 | + unimplemented_csr($encoding); |
| 66 | + } |
| 67 | + } |
| 68 | + else { |
| 69 | + if (JVT_BASE_TYPE == "custom") { |
| 70 | + unpredictable("jvt.BASE has custom behavior"); |
| 71 | + } else { |
| 72 | + return csr_value.BASE & (JVT_BASE_MASK >> 6); |
| 73 | + } |
| 74 | + return csr_value.BASE == 0 ? 0 : UNDEFINED_LEGAL_DETERMINISTIC; |
| 75 | + } |
| 76 | + MODE: |
| 77 | + location: 5-0 |
| 78 | + description: | |
| 79 | + `jvt.mode` is a WARL field, so can only be programmed to modes which are implemented. Therefore the |
| 80 | + discovery mechanism is to attempt to program different modes and read back the values to see which |
| 81 | + are available. Jump table mode must be implemented. |
| 82 | + type(): | |
| 83 | + if (JVT_READ_ONLY) { |
| 84 | + return CsrFieldType::RO; |
| 85 | + } |
| 86 | + else { |
| 87 | + return CsrFieldType::RW; |
| 88 | + } |
| 89 | + reset_value: 0 |
| 90 | + sw_write(csr_value): | |
| 91 | + if (JVT_READ_ONLY || (csr_value.MODE != 0)) { |
| 92 | + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); |
| 93 | + } |
| 94 | + return 0; |
| 95 | +sw_read(): | |
| 96 | + # If the Smstateen extension is implemented, then bit 2 in `mstateen0`, `sstateen0`, and `hstateen0` is |
| 97 | + # implemented. If bit 2 of a controlling `stateen0` CSR is zero, then access to the `jvt` CSR and execution |
| 98 | + # of a `cm.jalt` or `cm.jt` instruction by a lower privilege level results in an illegal-instruction trap (or, if |
| 99 | + # appropriate, a virtual-instruction trap). |
| 100 | +
|
| 101 | + if ((mode() != PrivilegeMode::M) && implemented?(ExtensionName::Smstateen)) { |
| 102 | + if (CSR[mstateen0].JVT == 1'b0) { |
| 103 | + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); |
| 104 | + } |
| 105 | + } |
| 106 | + else if ((mode() == PrivilegeMode::U) && implemented?(ExtensionName::Ssstateen)) { |
| 107 | + if (CSR[sstateen0].JVT == 1'b0) { |
| 108 | + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); |
| 109 | + } |
| 110 | + } |
| 111 | + else if ((mode() == PrivilegeMode::VS) && implemented?(ExtensionName::Ssstateen)) { |
| 112 | + if (CSR[hstateen0].JVT == 1'b0) { |
| 113 | + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); |
| 114 | + } |
| 115 | + } |
| 116 | + else if ((mode() == PrivilegeMode::VU) && implemented?(ExtensionName::Ssstateen)) { |
| 117 | + if ((CSR[sstateen0].JVT == 1'b0) || (CSR[hstateen0].JVT == 1'b0)) { |
| 118 | + raise(ExceptionCode::VirtualInstruction, mode(), $encoding); |
| 119 | + } |
| 120 | + } |
0 commit comments