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