|
| 1 | + |
| 2 | +LatticeMico32 Memory Managerment Unit |
| 3 | +===================================== |
| 4 | + |
| 5 | +:Author: Yann Sionneau |
| 6 | +:Contact: yann.sionneau@gmail.com |
| 7 | +:Version: 1.0 |
| 8 | +:Date: June 2013 |
| 9 | +:Copyright: Permission is granted to copy, distribute and/or modify this |
| 10 | + document under the terms of the BSD License. |
| 11 | + |
| 12 | + |
| 13 | +Overview |
| 14 | +-------- |
| 15 | + |
| 16 | +This document describes the LatticeMico32 MMU (Memory Management Unit) |
| 17 | +features and how it can be configured. |
| 18 | + |
| 19 | +This MMU is not part of the original LatticeMico32 CPU, it has been added |
| 20 | +by Yann Sionneau with the help of the Milkymist community in general and |
| 21 | +Michael Walle in particular. |
| 22 | + |
| 23 | +The LM32 MMU has been designed with "simplicity" in head, KISS (Keep It |
| 24 | +Simple Stupid) is the motto. |
| 25 | + |
| 26 | +Only the minimum has been implemented to have the minimalistic features |
| 27 | +which would allow a modern Operating System like Linux or \*BSD to run, |
| 28 | +providing virtual memory and memory protection. |
| 29 | + |
| 30 | +The Caches are designed to be VIPT (Virtually Indexed Physically Tagged) to |
| 31 | +allow the TLB lookup to take place in parallel of the cache lookup so that |
| 32 | +we don't need to stale the pipeline. |
| 33 | + |
| 34 | + |
| 35 | +Features |
| 36 | +-------- |
| 37 | + |
| 38 | + * 1024 entries ITLB (Instruction Translation Lookaside Buffer) |
| 39 | + * 1024 entries DTLB (Data Translation Lookaside Buffer) |
| 40 | + * CPU exceptions generated upon |
| 41 | + |
| 42 | + * ITLB miss |
| 43 | + * DTLB miss |
| 44 | + * DTLB page fault (writing to a read-only page) |
| 45 | + |
| 46 | + * I/D TLB lookup in parallel of the I/D Cache lookup to avoid lookup penalties |
| 47 | + * 4 kB pages |
| 48 | + |
| 49 | +As you can see, it is quite minimalistic, here is a list of what's not |
| 50 | +featured by this MMU: |
| 51 | + |
| 52 | + * No hardware page tree walker |
| 53 | + * No dirty or present bit |
| 54 | + * No ASID (Address Space Identifier) |
| 55 | + * No lockable TLB entries |
| 56 | + * Only 1 page size supported: 4 kB |
| 57 | + |
| 58 | + |
| 59 | +TLB Layout |
| 60 | +---------- |
| 61 | + |
| 62 | +Let's name our 32 bits virtual address "vaddr". |
| 63 | + |
| 64 | +Let's name our 32 bits physical address "paddr". |
| 65 | + |
| 66 | +Let's say vaddr[0] is the Lowest Significant Bit and vaddr[31] the Most |
| 67 | +Significant Bit. |
| 68 | + |
| 69 | +Let's say vaddr[11:0] is the part of vaddr represented by its 12 Lowest |
| 70 | +Significant Bits. |
| 71 | + |
| 72 | +Deep inside, the TLB is a **Direct-mapped**, **VIVT** (Virtually Indexed |
| 73 | +Virtually Tagged) Cache. |
| 74 | + |
| 75 | +When the LM32 core is synthetized with MMU support, the CPU pipeline Data |
| 76 | +and Instruction Caches turn into **VIPT** (Virtually Indexed Physically |
| 77 | +Tagged) Caches. |
| 78 | + |
| 79 | +The TLB is indexed by vaddr[21:12]: The bottom 10 LSB of the virtual PFN |
| 80 | +(Page Frame Number). |
| 81 | + |
| 82 | +A TLB entry holds: Physical PFN, Physical Tag, Cache inhibit flag (for |
| 83 | +DTLB), Read-only flag (for DTLB), Valid entry tag |
| 84 | + |
| 85 | +More precisely: |
| 86 | + |
| 87 | + * A valid DTLB entry: paddr[31:12], vaddr[31:22], paddr[2], paddr[1], 1 |
| 88 | + * An invalid DTLB entry: paddr[31:12], vaddr[21:22], paddr[2], paddr[1], 0 |
| 89 | + * A valid ITLB entry: paddr[31:12], vaddr[31:22], 1 |
| 90 | + * An invalid ITLB entry: paddr[31:12], vaddr[31:22], 0 |
| 91 | + |
| 92 | +The meaning of paddr[2] and paddr[1] will be explained later on in the |
| 93 | +section which explains how to program the MMU using LM32 assembly |
| 94 | +instructions. |
| 95 | + |
| 96 | + |
| 97 | +Interact with the TLB |
| 98 | +--------------------- |
| 99 | + |
| 100 | +In order to interact with the TLB, three CSR (Control and Status Registers) |
| 101 | +have been added to the LM32 CPU: |
| 102 | + |
| 103 | ++-------------+--------------------------------------------------+--------+ |
| 104 | +| CSR | Description | R/W | |
| 105 | ++=============+==================================================+========+ |
| 106 | +| TLBVADDR | You can write the virtual pfn of the entry you | R/W | |
| 107 | +| | want to update or invalidate or cause a TLB | | |
| 108 | +| | flush. You can read the virtual pfn causing a | | |
| 109 | +| | TLB miss or fault. | | |
| 110 | ++-------------+--------------------------------------------------+--------+ |
| 111 | +| TLBPADDR | Your can write the physical pfn of the entry you | W only | |
| 112 | +| | want to update. | | |
| 113 | ++-------------+--------------------------------------------------+--------+ |
| 114 | +| TLBBADVADDR | You can read the virtual address which caused | R only | |
| 115 | +| | the TLB exception. | | |
| 116 | ++-------------+--------------------------------------------------+--------+ |
| 117 | + |
| 118 | + * TLBVADDR: holds a virtual address |
| 119 | + * TLBPADDR: holds a physical address |
| 120 | + |
| 121 | +A CSR register can be written to like this: |
| 122 | + |
| 123 | +The following code writes the content of the R1 register to TLBVADDR CSR:: |
| 124 | + |
| 125 | + wcsr TLBVADDR, r1 |
| 126 | + |
| 127 | +A CSR register can be read from like this: |
| 128 | + |
| 129 | +The following code writes the content of TLBPADDR CSR to the R1 register:: |
| 130 | + |
| 131 | + rcsr r1, TLBPADDR |
| 132 | + |
| 133 | + |
| 134 | +Add or Update a TLB entry |
| 135 | +~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 136 | + |
| 137 | +First, make sure vaddr[2:0] == "000" (or 3'b0 in verilog) as those 3 bits |
| 138 | +will be used for other TLB operations. |
| 139 | + |
| 140 | +Then, write the virtual address to the TLBVADDR CSR. |
| 141 | + |
| 142 | +Then you need to do a logical "OR" operation on the physical address to set |
| 143 | +paddr[2:0] according to your needs: |
| 144 | + |
| 145 | + * paddr[2] set to 1 means the page won't be cached by LM32 Data Cache |
| 146 | + (only for Data Cache / DTLB) |
| 147 | + * paddr[1] set to 1 means the Page is Read-only (only valid for DTLB) |
| 148 | + * paddr[0] set to 1 means you want to update DTLB, use 0 for ITLB |
| 149 | + |
| 150 | +Then, you need to write the OR'ed physical address to the TLBPADDR CSR. |
| 151 | + |
| 152 | +The TLB entry update will be triggered by the write to TLBPADDR CSR. |
| 153 | + |
| 154 | +Code samples:: |
| 155 | + |
| 156 | + #define PAGE_SIZE (1 << 12) |
| 157 | + #define PAGE_MASK (PAGE_SIZE - 1) |
| 158 | + |
| 159 | + void update_dtlb_entry(unsigned int vaddr, unsigned int paddr, |
| 160 | + bool read-only, bool not_cached) |
| 161 | + { |
| 162 | + paddr &= ~PAGE_MASK; /* Make sure page offset is zeroed */ |
| 163 | + vaddr &= ~PAGE_MASK; /* Make sure page offset is zeroed */ |
| 164 | + paddr |= 1; /* This means we are addressing DTLB */ |
| 165 | + |
| 166 | + if (read-only) |
| 167 | + paddr |= 2; |
| 168 | + |
| 169 | + if (not_cached) |
| 170 | + paddr |= 4; |
| 171 | + |
| 172 | + asm volatile("wcsr TLBVADDR, %0" :: "r"(vaddr) : ); |
| 173 | + asm volatile("wcsr TLBPADDR, %0" :: "r"(paddr) : ); |
| 174 | + } |
| 175 | + |
| 176 | + void update_itlb_entry(unsigned int vaddr, unsigned int paddr) |
| 177 | + { |
| 178 | + paddr &= ~PAGE_MASK; /* Make sure page offset is zeroed */ |
| 179 | + vaddr &= ~PAGE_MASK; /* Make sure page offset is zeroed */ |
| 180 | + /* We don't set paddr[0] which means we are addressing ITLB */ |
| 181 | + |
| 182 | + asm volatile("wcsr TLBVADDR, %0" :: "r"(vaddr) : ); |
| 183 | + asm volatile("wcsr TLBPADDR, %0" :: "r"(paddr) : ); |
| 184 | + } |
| 185 | + |
| 186 | + |
| 187 | +Invalidate a TLB entry or flush the entire TLB |
| 188 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 189 | + |
| 190 | +First, you need to do a logical "OR" operation on the virtual address to |
| 191 | +set vaddr[2:0] according to your needs: |
| 192 | + |
| 193 | + * vaddr[2] set to 1 will trigger a flush of the entire selected TLB |
| 194 | + * vaddr[1] set to 1 will trigger the invalidation of the entry indexed by |
| 195 | + vaddr[21:12] inside the selected TLB |
| 196 | + * vaddr[0] set to 1 means you want to operate on DTLB, use 0 for ITLB |
| 197 | + |
| 198 | +The action is triggered upon the write of the OR'ed virtual address to the |
| 199 | +TLBVADDR CSR. |
| 200 | + |
| 201 | +Code samples:: |
| 202 | + |
| 203 | + #define PAGE_SIZE (1 << 12) |
| 204 | + #define PAGE_MASK (PAGE_SIZE - 1) |
| 205 | + |
| 206 | + void invalidate_dtlb_entry(unsigned int vaddr) |
| 207 | + { |
| 208 | + vaddr &= ~PAGE_MASK; /* Make sure page offset is zeroed */ |
| 209 | + /* |
| 210 | + * 1 because we are addressing DTLB |
| 211 | + * 2 because we want to invalidate a specific line |
| 212 | + */ |
| 213 | + vaddr |= 1 | 2; |
| 214 | + |
| 215 | + asm volatile("wcsr TLBVADDR, %0" :: "r"(vaddr) : ); |
| 216 | + } |
| 217 | + |
| 218 | + void invalidate_itlb_entry(unsigned int vaddr) |
| 219 | + { |
| 220 | + vaddr &= ~PAGE_MASK; /* Make sure page offset is zeroed */ |
| 221 | + vaddr |= 2; /* 2 because we want to invalidate a specific line */ |
| 222 | + |
| 223 | + asm volatile("wcsr TLBVADDR, %0" :: "r"(vaddr) : ); |
| 224 | + } |
| 225 | + |
| 226 | + void flush_dtlb(void) |
| 227 | + { |
| 228 | + unsigned int cmd = 1 | 4; |
| 229 | + asm volatile("wcsr TLBVADDR, %0" :: "r"(cmd) : ); |
| 230 | + } |
| 231 | + |
| 232 | + void flush_itlb(void) |
| 233 | + { |
| 234 | + unsigned int cmd = 4; |
| 235 | + asm volatile("wcsr TLBVADDR, %0" :: "r"(cmd) : ); |
| 236 | + } |
| 237 | + |
| 238 | + |
| 239 | +A sum up of TLB actions |
| 240 | +~~~~~~~~~~~~~~~~~~~~~~~ |
| 241 | + |
| 242 | +To summarize all possible TLB actions: |
| 243 | + |
| 244 | + * Writing to TLBPADDR triggers the update of a TLB entry according to the |
| 245 | + content of TLBVADDR and TLBPADDR |
| 246 | + * Writing to TLBVADDR either prepares for updating a TLB entry if it is |
| 247 | + followed by a write operation to TLBPADDR or immediately triggers an |
| 248 | + action determined by bits vaddr[2:0] written to TLBVADDR. In the latter |
| 249 | + case, the action is performed on the TLB entry indexed by vaddr[21:12]. |
| 250 | + |
| 251 | +Possible actions triggered by writing to TLBVADDR: |
| 252 | + |
| 253 | ++------------+------------------------------------------------------------+ |
| 254 | +| vaddr[2:0] | action | |
| 255 | ++============+============================================================+ |
| 256 | +| 000 | No Operation, used for updating TLB entry by writting to | |
| 257 | +| | TLBPADDR | |
| 258 | ++------------+------------------------------------------------------------+ |
| 259 | +| 011 | Invalidate DTLB entry indexed by vaddr[21:12] | |
| 260 | ++------------+------------------------------------------------------------+ |
| 261 | +| 010 | Invalidate ITLB entry indexed by vaddr[21:12] | |
| 262 | ++------------+------------------------------------------------------------+ |
| 263 | +| 101 | Flush DTLB | |
| 264 | ++------------+------------------------------------------------------------+ |
| 265 | +| 100 | Flush ITLB | |
| 266 | ++------------+------------------------------------------------------------+ |
| 267 | +| 11x | Not deterministic, do not use untill it's defined by a | |
| 268 | +| | future MMU revision | |
| 269 | ++------------+------------------------------------------------------------+ |
| 270 | + |
| 271 | + |
| 272 | +Interact with the MMU |
| 273 | +--------------------- |
| 274 | + |
| 275 | +In order to interact with the MMU, a new CSR (Control and Status Register) |
| 276 | +has been added: PSW (Processor Status Word) |
| 277 | + |
| 278 | ++-------+--------+--------------------------------------------------------+ |
| 279 | +| Bits | Name | Description | |
| 280 | ++=======+========+========================================================+ |
| 281 | +| 31:12 | | *unused* | |
| 282 | ++-------+--------+--------------------------------------------------------+ |
| 283 | +| 11 | BUSR | Breakpoint backup of USR | |
| 284 | ++-------+--------+--------------------------------------------------------+ |
| 285 | +| 10 | EUSR | Exception backup of USR | |
| 286 | ++-------+--------+--------------------------------------------------------+ |
| 287 | +| 9 | USR | User mode bit | |
| 288 | ++-------+--------+--------------------------------------------------------+ |
| 289 | +| 8 | BDTLBE | Breakpoint backup of DTLBE | |
| 290 | ++-------+--------+--------------------------------------------------------+ |
| 291 | +| 7 | EDTLBE | Exception backup of DTLBE | |
| 292 | ++-------+--------+--------------------------------------------------------+ |
| 293 | +| 6 | DTLBE | DTLB enabled | |
| 294 | ++-------+--------+--------------------------------------------------------+ |
| 295 | +| 5 | BITLBE | Breakpoint backup of ITLBE | |
| 296 | ++-------+--------+--------------------------------------------------------+ |
| 297 | +| 4 | EITLBE | Exception backup of ITLBE | |
| 298 | ++-------+--------+--------------------------------------------------------+ |
| 299 | +| 3 | ITLBE | ITLB enabled | |
| 300 | ++-------+--------+--------------------------------------------------------+ |
| 301 | +| 2 | IE.BIE | See note below | |
| 302 | ++-------+--------+ | |
| 303 | +| 1 | IE.EIE | | |
| 304 | ++-------+--------+ | |
| 305 | +| 0 | IE.IE | | |
| 306 | ++-------+--------+--------------------------------------------------------+ |
| 307 | + |
| 308 | +.. Note:: |
| 309 | + |
| 310 | + PSW[2:0] is a real mirror of IE[2:0] as described in the LatticeMico32 |
| 311 | + Processor Reference Manual p. 10 Table 5 "Fields of the IE CSR". In any |
| 312 | + condition: PSW[2:0] == IE[2:0]. IE CSR is mirrored in the lower bits of |
| 313 | + PSW CSR for compatibility reasons. Old programs (ignorant of the MMU) |
| 314 | + will keep using IE CSR, newer programs can use PSW to deal with MMU and |
| 315 | + interrupts. |
| 316 | + |
| 317 | + |
| 318 | +Activate the MMU |
| 319 | +~~~~~~~~~~~~~~~~ |
| 320 | + |
| 321 | +Activating the MMU is done by activating each TLB by writing 1 into |
| 322 | +PSW[ITLBE] and PSW[DTLBE]:: |
| 323 | + |
| 324 | + void enable_mmu(void) |
| 325 | + { |
| 326 | + asm volatile("rcsr r1, PSW\n\t" |
| 327 | + "ori r1, r1, 72\n\t" |
| 328 | + "wcsr PSW, r1" ::: "r1"); |
| 329 | + } |
| 330 | + |
| 331 | + |
| 332 | +Deactivate the MMU |
| 333 | +~~~~~~~~~~~~~~~~~~ |
| 334 | + |
| 335 | +Deactivating the MMU is done by deactivating each TLB by writing 0 into |
| 336 | +PSW[ITLBE] and PSW[DTLBE]:: |
| 337 | + |
| 338 | + void disable_mmu(void) |
| 339 | + { |
| 340 | + unsigned int mask = ~(72); |
| 341 | + asm volatile("rcsr r1, PSW\n\t" |
| 342 | + "and r1, r1, %0\n\t" |
| 343 | + "wcsr PSW, r1" :: "r"(mask) : "r1"); |
| 344 | + } |
| 345 | + |
| 346 | + |
| 347 | +TLB lookups |
| 348 | +----------- |
| 349 | + |
| 350 | +This section explains in details how the TLB lookup takes place: what |
| 351 | +happens in which condition. |
| 352 | + |
| 353 | +If the TLBs are disabled, nothing special happens, LM32 will behave as if |
| 354 | +it has been synthetized without MMU support (except for the presence of |
| 355 | +PSW, TLBVADDR and TLBPADDR). |
| 356 | + |
| 357 | +If DTLB is enabled: |
| 358 | + |
| 359 | +In parallel of the Data Cache lookup, the DTLB lookup happens. |
| 360 | + |
| 361 | +DTLB is indexed by vaddr[21:11]. |
| 362 | + |
| 363 | +If the DTLB entry is invalid (i.e. invalid bit is set), then the DTLB |
| 364 | +generates a DTLB miss exception. |
| 365 | + |
| 366 | +If the DTLB entry is valid, the DTLB compares vaddr[31:22] with the DTLB |
| 367 | +entry tag, if this comparison fails: the DTLB generates a DTLB miss |
| 368 | +exception as well. |
| 369 | + |
| 370 | +If the DTLB entry is valid and the vaddr[31:22] matches the DTLB entry tag: |
| 371 | + |
| 372 | + * Then if the memory access was a READ (lb, lbu, lh, lhu, lw) |
| 373 | + |
| 374 | + * the Data Cache compares the tag of its selected line with the |
| 375 | + paddr[31:12] extracted from the DTLB to check if we Hit or Miss the |
| 376 | + Data Cache |
| 377 | + * Then the usual Cache refill happens (using the physical address) in |
| 378 | + case of a cache miss |
| 379 | + * Then if the memory access was a WRITE (sb, sh, sw) |
| 380 | + |
| 381 | + * The read-only bit flag contained in the DTLB entry is checked |
| 382 | + * If it is set: it triggers a DTLB fault CPU exception |
| 383 | + * If it's not set: The Data Cache does the same tag comparison as with |
| 384 | + the READ operation to check for Cache Hit/Miss |
| 385 | + |
| 386 | +All these behaviours are summed up in the following table: |
| 387 | + |
| 388 | ++------------+-----+------------------------------------------------------+ |
| 389 | +| Exception | EID | Condition | |
| 390 | ++------------+-----+------------------------------------------------------+ |
| 391 | +| ITLB miss | 8 | If **any** of these conditions holds: | |
| 392 | +| | | | |
| 393 | +| | | * ITLB entry is invalid | |
| 394 | +| | | * ITLB entry tag does not match vaddr[31:22] | |
| 395 | ++------------+-----+------------------------------------------------------+ |
| 396 | +| DTLB miss | 9 | If **any** of these conditions holds: | |
| 397 | +| | | | |
| 398 | +| | | * DTLB entry is invalid | |
| 399 | +| | | * DTLB entry tag does not match vaddr[31:22] | |
| 400 | ++------------+-----+------------------------------------------------------+ |
| 401 | +| DTLB fault | 10 | If **all** of these conditions holds: | |
| 402 | +| | | | |
| 403 | +| | | * DTLB entry is valid | |
| 404 | +| | | * the tag entry matches vaddr[31:22] | |
| 405 | +| | | * the read-only bit is set | |
| 406 | +| | | * the CPU is doing a memory store | |
| 407 | ++------------+-----+------------------------------------------------------+ |
| 408 | +| Privilege | 11 | If PSW[USR] == 1 and one of these instructions is | |
| 409 | +| | | exeucted: | |
| 410 | +| | | | |
| 411 | +| | | * iret | |
| 412 | +| | | * bret | |
| 413 | +| | | * wcsr | |
| 414 | ++------------+-----+------------------------------------------------------+ |
| 415 | + |
| 416 | + |
| 417 | +CSR registers special behaviours |
| 418 | +-------------------------------- |
| 419 | + |
| 420 | +Upon any exception, PSW CSR is modified automatically by the CPU pipeline |
| 421 | +itself: |
| 422 | + |
| 423 | + * PSW[ITLBE] is saved in PSW[EITLBE] and the former is cleared |
| 424 | + * PSW[DTLBE] is saved in PSW[EDTLBE] and the former is cleared |
| 425 | + * PSW[USR] is saved in PSW[EUSR] and the former is cleared |
| 426 | + * TLBVADDR is pre-charged with the virtual PFN (page frame number) which |
| 427 | + caused an exception (in case of TLB miss or fault only) |
| 428 | + |
| 429 | + * TLBVADDR[0] is set to 1 when then exception is caused by DTLB, else it |
| 430 | + is clear |
| 431 | + * In case of DTLB miss or fault, TLBVADDR[31:12] is pre-charged the |
| 432 | + virtual PFN whose load or store operation caused the exception |
| 433 | + * In case of ITLB miss, TLBVADDR[31:12] is pre-charged with the virtual |
| 434 | + PFN of the instruction whose fetch caused the exception |
| 435 | + * This mechanism allows for faster TLB miss handling because TLBVADDR is |
| 436 | + already pre-charged with the right value |
| 437 | + * Since TLBVADDR is pre-charged with the virtual PFN: page offset bits |
| 438 | + (TLBVADDR[11:1]) are not set |
| 439 | + |
| 440 | + * TLBBADVADDR\ :sup:`\*\*` is written with a virtual address when an |
| 441 | + exception is caused by a TLB miss |
| 442 | + |
| 443 | + * In case of ITLB miss, TLBBADVADDR[31:2] contains the PC address whose |
| 444 | + fetch triggered the ITLB miss exception. Instructions being 32 bits |
| 445 | + aligned, PC[1:0] is always 00. |
| 446 | + * In case of DTLB miss or fault, TLBBADVADDR[31:0] contains the virtual |
| 447 | + address whose load or store operation caused the exception |
| 448 | + * Unlike TLBVADDR, TLBBADVADDR page offset bits are set according to |
| 449 | + what caused the exception |
| 450 | + |
| 451 | +(\*) In LM32 pipeline, exception happens in the e\ **X**\ ecute stage, even |
| 452 | +though they may be triggered in the **F**\ etch or **M**\ emory stage for |
| 453 | +example. Load and Store instructions therefore stall the pipeline for 1 |
| 454 | +cycle during the e\ **X**\ ecute stage if the DTLB is activated. |
| 455 | + |
| 456 | +(\*\*) TLBBADVADDR is the same CSR ID as TLBPADDR. The former is read-only |
| 457 | +and the latter is write-only. |
| 458 | + |
| 459 | +Upon any breakpoint hit, PSW CSR is also modified by the CPU pipeline: |
| 460 | + |
| 461 | + * PSW[ITLBE] is saved in PSW[BITLBE] and the former is cleared |
| 462 | + * PSW[DTLBE] is saved in PSW[BDTLBE] and the former is cleared |
| 463 | + * PSW[USR] is saved in PSW[BUSR] and the former is cleared |
| 464 | + |
| 465 | +This means MMU is **turned off** upon CPU exception or breakpoint hit. |
| 466 | + |
| 467 | +Upon return from exception (**iret** instruction), PSW CSR is also modified |
| 468 | +by the CPU pipeline: |
| 469 | + |
| 470 | + * PSW[ITLBE] is restored using the value from PSW[EITLBE] |
| 471 | + * PSW[DTLBE] is restored using the value from PSW[EDTLBE] |
| 472 | + * PSW[USR] is restored using the value from PSW[EUSR] |
| 473 | + |
| 474 | +Upon return from breakpoint (\textbf{bret} instruction), PSW CSR is also |
| 475 | +modified by the CPU pipeline: |
| 476 | + |
| 477 | + * PSW[ITLBE] is restored using the value from PSW[BITLBE] |
| 478 | + * PSW[DTLBE] is restored using the value from PSW[BDTLBE] |
| 479 | + * PSW[USR] is restored using the value from PSW[BUSR] |
0 commit comments