|
| 1 | +# Illegal Instruction Exception |
| 2 | +Illegal instruction is a synchronous exception because its origin comes from the software flow. |
| 3 | +### Causes of illegal instructions |
| 4 | +- Un familiar instruction that belongs to a specific RISCV extension that not supported bt the core. |
| 5 | +- Hw errors while fetching the instruction from the memory. |
| 6 | +- Custom instructions that not supported by RISCV spec (In most of the cases the compiler will not compile that). |
| 7 | +- Compiler errors (very rare but possible). |
| 8 | + |
| 9 | +### Cases in our core |
| 10 | +For more details, please refer to `/source/core_rrv/illegal_instruction.vh` |
| 11 | +- Some of the `Funct7` fields in R-type instructions do not zero |
| 12 | +- `Funct3` do not match the instruction. For example we try to execute S-type instruction and `Funct3 = 111`. |
| 13 | +- Un recognized OpCode that not supported by the core or not allowed by the spec. |
| 14 | + |
| 15 | +### Illegal Instruction Generation |
| 16 | +- We use the test `/verif/core_rrv/alive_illegal.c`. |
| 17 | +- We try to create an instruction with illegal `FUCT7`, we generate `slli` with funct7 = 0x7f instead of 0x0 |
| 18 | +``` |
| 19 | + // This instruction is trying to generate slli instruction with illegal FUNCT7. |
| 20 | + asm(".word 0xfff79793" : /* outputs / : / inputs / : / clobbers */); |
| 21 | +``` |
| 22 | +- This is a code snippet from the `elf.txt` file |
| 23 | +``` |
| 24 | + 1660: fd010113 addi sp,sp,-48 |
| 25 | + . |
| 26 | + . |
| 27 | + . |
| 28 | + 1674: 00200793 li a5,2 |
| 29 | + 1678: fef42423 sw a5,-24(s0) |
| 30 | + 167c: fff79793 0xfff79793 |
| 31 | + 1680: fec42703 lw a4,-20(s0) |
| 32 | + . |
| 33 | + . |
| 34 | + . |
| 35 | + 16b0: 00008067 ret |
| 36 | +``` |
| 37 | +### Illegal Instruction Mechanism |
| 38 | +1. Detection if illegal instruction inside the controller : |
| 39 | +`assign IllegalInstructionQ101H = (PreIllegalInstructionQ101H) && ! (flushQ102H || flushQ103H);` |
| 40 | +- In case of illegal instruction and flush, we do not start the the interrupt routine because the instruction will be flushed anyway. |
| 41 | +- When the illegal instruction is a part of the instruction flow than we erase that instruction by inserting `NOP` and jumps to the interrupt routine. |
| 42 | +2. Csr update |
| 43 | +Once we decide to take the exception we start to update and read csr's. T |
| 44 | +- We update the cause of the exception by modifying the `csr_mcause` csr by assign the `32'h00000002`. |
| 45 | +- Update `csr_mepc` with the return value PC of the illegal instruction. We will use it as return address from the interrupt routine. |
| 46 | +- Update `csr_mtval` with the illegal instruction machine code. In our case it will be `fff79793` |
| 47 | +- Set the `CSR_MSTATUS[MIE]` to the current value of `CSR_MSTATUS[MIE]` to store the previous machine interrupt enable mode. |
| 48 | +- Disable `CSR_MSTATUS[MIE]` when taking an exception to avoid nested interrupts. |
| 49 | +3. Jumps to Interrupt routine |
| 50 | +- Store the values of the registers |
| 51 | +- Perform the routine |
| 52 | +Jump to `csr_mtvec` value that keeps the address pf the routine. |
| 53 | +4. Return from interrupt routine |
| 54 | +- Restore the registers |
| 55 | +- update `CSR_MSTATUS[MIE]` with `CSR_MSTATUS[MIE]`. |
| 56 | +### crt0.s_boot_trap.s file |
| 57 | +``` |
| 58 | +csr_init: |
| 59 | + li t0, 0x100 # Load the immediate value 0x100 of trap handler address |
| 60 | + csrw mtvec, t0 # Write the value in t0 to the mtvec CSR |
| 61 | +``` |
| 62 | + |
| 63 | +- The address of the interrupt routine is `0x100` |
| 64 | +- Inside that file we store and restore the registers before jumping to the routine inside `interrupt_handler.h`. |
| 65 | +Please see `/app/crt0/crt0_boot_trap.S` and `/app/defines/interrupt_handler.h` |
| 66 | + |
| 67 | +### Interrupt_handler.h |
| 68 | +``` |
| 69 | + if ((mcause & 0xFFF) == ILLEGAL_INSTRUCTION_EXCEPTION) { |
| 70 | + csr_mepc = read_mepc(); |
| 71 | + csr_mtval = read_mtval(); |
| 72 | + rvc_printf("ILGL INST\n"); |
| 73 | + rvc_printf("MEPC:"); |
| 74 | + rvc_print_unsigned_int_hex(csr_mepc); |
| 75 | + rvc_printf("\n"); |
| 76 | + rvc_printf("MTVAL:"); |
| 77 | + rvc_print_unsigned_int_hex(csr_mtval); |
| 78 | + rvc_printf("\n"); |
| 79 | + } |
| 80 | +``` |
| 81 | + |
| 82 | + |
| 83 | + |
| 84 | + |
0 commit comments