Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 1 | ================================= |
| 2 | INTERNAL KERNEL ABI FOR FR-V ARCH |
| 3 | ================================= |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 4 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 5 | The internal FRV kernel ABI is not quite the same as the userspace ABI. A |
| 6 | number of the registers are used for special purposed, and the ABI is not |
| 7 | consistent between modules vs core, and MMU vs no-MMU. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 8 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 9 | This partly stems from the fact that FRV CPUs do not have a separate |
| 10 | supervisor stack pointer, and most of them do not have any scratch |
| 11 | registers, thus requiring at least one general purpose register to be |
| 12 | clobbered in such an event. Also, within the kernel core, it is possible to |
| 13 | simply jump or call directly between functions using a relative offset. |
| 14 | This cannot be extended to modules for the displacement is likely to be too |
| 15 | far. Thus in modules the address of a function to call must be calculated |
| 16 | in a register and then used, requiring two extra instructions. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 17 | |
| 18 | This document has the following sections: |
| 19 | |
| 20 | (*) System call register ABI |
| 21 | (*) CPU operating modes |
| 22 | (*) Internal kernel-mode register ABI |
| 23 | (*) Internal debug-mode register ABI |
| 24 | (*) Virtual interrupt handling |
| 25 | |
| 26 | |
| 27 | ======================== |
| 28 | SYSTEM CALL REGISTER ABI |
| 29 | ======================== |
| 30 | |
| 31 | When a system call is made, the following registers are effective: |
| 32 | |
| 33 | REGISTERS CALL RETURN |
| 34 | =============== ======================= ======================= |
| 35 | GR7 System call number Preserved |
| 36 | GR8 Syscall arg #1 Return value |
| 37 | GR9-GR13 Syscall arg #2-6 Preserved |
| 38 | |
| 39 | |
| 40 | =================== |
| 41 | CPU OPERATING MODES |
| 42 | =================== |
| 43 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 44 | The FR-V CPU has three basic operating modes. In order of increasing |
| 45 | capability: |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 46 | |
| 47 | (1) User mode. |
| 48 | |
| 49 | Basic userspace running mode. |
| 50 | |
| 51 | (2) Kernel mode. |
| 52 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 53 | Normal kernel mode. There are many additional control registers |
| 54 | available that may be accessed in this mode, in addition to all the |
| 55 | stuff available to user mode. This has two submodes: |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 56 | |
| 57 | (a) Exceptions enabled (PSR.T == 1). |
| 58 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 59 | Exceptions will invoke the appropriate normal kernel mode |
| 60 | handler. On entry to the handler, the PSR.T bit will be cleared. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 61 | |
| 62 | (b) Exceptions disabled (PSR.T == 0). |
| 63 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 64 | No exceptions or interrupts may happen. Any mandatory exceptions |
| 65 | will cause the CPU to halt unless the CPU is told to jump into |
| 66 | debug mode instead. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 67 | |
| 68 | (3) Debug mode. |
| 69 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 70 | No exceptions may happen in this mode. Memory protection and |
| 71 | management exceptions will be flagged for later consideration, but |
| 72 | the exception handler won't be invoked. Debugging traps such as |
| 73 | hardware breakpoints and watchpoints will be ignored. This mode is |
| 74 | entered only by debugging events obtained from the other two modes. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 75 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 76 | All kernel mode registers may be accessed, plus a few extra debugging |
| 77 | specific registers. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 78 | |
| 79 | |
| 80 | ================================= |
| 81 | INTERNAL KERNEL-MODE REGISTER ABI |
| 82 | ================================= |
| 83 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 84 | There are a number of permanent register assignments that are set up by |
| 85 | entry.S in the exception prologue. Note that there is a complete set of |
| 86 | exception prologues for each of user->kernel transition and kernel->kernel |
| 87 | transition. There are also user->debug and kernel->debug mode transition |
| 88 | prologues. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 89 | |
| 90 | |
| 91 | REGISTER FLAVOUR USE |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 92 | =============== ======= ============================================== |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 93 | GR1 Supervisor stack pointer |
| 94 | GR15 Current thread info pointer |
| 95 | GR16 GP-Rel base register for small data |
| 96 | GR28 Current exception frame pointer (__frame) |
| 97 | GR29 Current task pointer (current) |
| 98 | GR30 Destroyed by kernel mode entry |
| 99 | GR31 NOMMU Destroyed by debug mode entry |
| 100 | GR31 MMU Destroyed by TLB miss kernel mode entry |
| 101 | CCR.ICC2 Virtual interrupt disablement tracking |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 102 | CCCR.CC3 Cleared by exception prologue |
| 103 | (atomic op emulation) |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 104 | SCR0 MMU See mmu-layout.txt. |
| 105 | SCR1 MMU See mmu-layout.txt. |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 106 | SCR2 MMU Save for EAR0 (destroyed by icache insns |
| 107 | in debug mode) |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 108 | SCR3 MMU Save for GR31 during debug exceptions |
| 109 | DAMR/IAMR NOMMU Fixed memory protection layout. |
| 110 | DAMR/IAMR MMU See mmu-layout.txt. |
| 111 | |
| 112 | |
| 113 | Certain registers are also used or modified across function calls: |
| 114 | |
| 115 | REGISTER CALL RETURN |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 116 | =============== =============================== ====================== |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 117 | GR0 Fixed Zero - |
| 118 | GR2 Function call frame pointer |
| 119 | GR3 Special Preserved |
| 120 | GR3-GR7 - Clobbered |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 121 | GR8 Function call arg #1 Return value |
| 122 | (or clobbered) |
| 123 | GR9 Function call arg #2 Return value MSW |
| 124 | (or clobbered) |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 125 | GR10-GR13 Function call arg #3-#6 Clobbered |
| 126 | GR14 - Clobbered |
| 127 | GR15-GR16 Special Preserved |
| 128 | GR17-GR27 - Preserved |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 129 | GR28-GR31 Special Only accessed |
| 130 | explicitly |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 131 | LR Return address after CALL Clobbered |
| 132 | CCR/CCCR - Mostly Clobbered |
| 133 | |
| 134 | |
| 135 | ================================ |
| 136 | INTERNAL DEBUG-MODE REGISTER ABI |
| 137 | ================================ |
| 138 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 139 | This is the same as the kernel-mode register ABI for functions calls. The |
| 140 | difference is that in debug-mode there's a different stack and a different |
| 141 | exception frame. Almost all the global registers from kernel-mode |
| 142 | (including the stack pointer) may be changed. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 143 | |
| 144 | REGISTER FLAVOUR USE |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 145 | =============== ======= ============================================== |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 146 | GR1 Debug stack pointer |
| 147 | GR16 GP-Rel base register for small data |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 148 | GR31 Current debug exception frame pointer |
| 149 | (__debug_frame) |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 150 | SCR3 MMU Saved value of GR31 |
| 151 | |
| 152 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 153 | Note that debug mode is able to interfere with the kernel's emulated atomic |
| 154 | ops, so it must be exceedingly careful not to do any that would interact |
| 155 | with the main kernel in this regard. Hence the debug mode code (gdbstub) is |
| 156 | almost completely self-contained. The only external code used is the |
| 157 | sprintf family of functions. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 158 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 159 | Futhermore, break.S is so complicated because single-step mode does not |
| 160 | switch off on entry to an exception. That means unless manually disabled, |
| 161 | single-stepping will blithely go on stepping into things like interrupts. |
| 162 | See gdbstub.txt for more information. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 163 | |
| 164 | |
| 165 | ========================== |
| 166 | VIRTUAL INTERRUPT HANDLING |
| 167 | ========================== |
| 168 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 169 | Because accesses to the PSR is so slow, and to disable interrupts we have |
| 170 | to access it twice (once to read and once to write), we don't actually |
| 171 | disable interrupts at all if we don't have to. What we do instead is use |
| 172 | the ICC2 condition code flags to note virtual disablement, such that if we |
| 173 | then do take an interrupt, we note the flag, really disable interrupts, set |
| 174 | another flag and resume execution at the point the interrupt happened. |
| 175 | Setting condition flags as a side effect of an arithmetic or logical |
| 176 | instruction is really fast. This use of the ICC2 only occurs within the |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 177 | kernel - it does not affect userspace. |
| 178 | |
| 179 | The flags we use are: |
| 180 | |
| 181 | (*) CCR.ICC2.Z [Zero flag] |
| 182 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 183 | Set to virtually disable interrupts, clear when interrupts are |
| 184 | virtually enabled. Can be modified by logical instructions without |
| 185 | affecting the Carry flag. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 186 | |
| 187 | (*) CCR.ICC2.C [Carry flag] |
| 188 | |
| 189 | Clear to indicate hardware interrupts are really disabled, set otherwise. |
| 190 | |
| 191 | |
| 192 | What happens is this: |
| 193 | |
| 194 | (1) Normal kernel-mode operation. |
| 195 | |
| 196 | ICC2.Z is 0, ICC2.C is 1. |
| 197 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 198 | (2) An interrupt occurs. The exception prologue examines ICC2.Z and |
| 199 | determines that nothing needs doing. This is done simply with an |
| 200 | unlikely BEQ instruction. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 201 | |
| 202 | (3) The interrupts are disabled (local_irq_disable) |
| 203 | |
| 204 | ICC2.Z is set to 1. |
| 205 | |
| 206 | (4) If interrupts were then re-enabled (local_irq_enable): |
| 207 | |
| 208 | ICC2.Z would be set to 0. |
| 209 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 210 | A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would |
| 211 | be used to trap if interrupts were now virtually enabled, but |
| 212 | physically disabled - which they're not, so the trap isn't taken. The |
| 213 | kernel would then be back to state (1). |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 214 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 215 | (5) An interrupt occurs. The exception prologue examines ICC2.Z and |
| 216 | determines that the interrupt shouldn't actually have happened. It |
| 217 | jumps aside, and there disabled interrupts by setting PSR.PIL to 14 |
| 218 | and then it clears ICC2.C. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 219 | |
| 220 | (6) If interrupts were then saved and disabled again (local_irq_save): |
| 221 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 222 | ICC2.Z would be shifted into the save variable and masked off |
| 223 | (giving a 1). |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 224 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 225 | ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be |
| 226 | unaffected (ie: 0). |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 227 | |
| 228 | (7) If interrupts were then restored from state (6) (local_irq_restore): |
| 229 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 230 | ICC2.Z would be set to indicate the result of XOR'ing the saved |
| 231 | value (ie: 1) with 1, which gives a result of 0 - thus leaving |
| 232 | ICC2.Z set. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 233 | |
| 234 | ICC2.C would remain unaffected (ie: 0). |
| 235 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 236 | A TIHI #2 instruction would be used to again assay the current state, |
| 237 | but this would do nothing as Z==1. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 238 | |
| 239 | (8) If interrupts were then enabled (local_irq_enable): |
| 240 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 241 | ICC2.Z would be cleared. ICC2.C would be left unaffected. Both |
| 242 | flags would now be 0. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 243 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 244 | A TIHI #2 instruction again issued to assay the current state would |
| 245 | then trap as both Z==0 [interrupts virtually enabled] and C==0 |
| 246 | [interrupts really disabled] would then be true. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 247 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 248 | (9) The trap #2 handler would simply enable hardware interrupts |
| 249 | (set PSR.PIL to 0), set ICC2.C to 1 and return. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 250 | |
| 251 | (10) Immediately upon returning, the pending interrupt would be taken. |
| 252 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 253 | (11) The interrupt handler would take the path of actually processing the |
| 254 | interrupt (ICC2.Z is clear, BEQ fails as per step (2)). |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 255 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 256 | (12) The interrupt handler would then set ICC2.C to 1 since hardware |
| 257 | interrupts are definitely enabled - or else the kernel wouldn't be here. |
David Howells | 28baeba | 2006-02-14 13:53:20 -0800 | [diff] [blame] | 258 | |
| 259 | (13) On return from the interrupt handler, things would be back to state (1). |
| 260 | |
Horms | 0803926 | 2006-04-01 01:38:15 +0200 | [diff] [blame] | 261 | This trap (#2) is only available in kernel mode. In user mode it will |
| 262 | result in SIGILL. |