ia64 work.
[helenos.git] / arch / ia64 / src / ivt.S
blobe53be4a787847f5bce800150de069c82d447d7b1
2 # Copyright (C) 2005 Jakub Vana
3 # Copyright (C) 2005 Jakub Jermar
4 # All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
10 # - Redistributions of source code must retain the above copyright
11 #   notice, this list of conditions and the following disclaimer.
12 # - Redistributions in binary form must reproduce the above copyright
13 #   notice, this list of conditions and the following disclaimer in the
14 #   documentation and/or other materials provided with the distribution.
15 # - The name of the author may not be used to endorse or promote products
16 #   derived from this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <arch/stack.h>
31 #include <arch/register.h>
32 #include <arch/mm/page.h>
33 #include <align.h>
35 #define STACK_ITEMS             14
36 #define STACK_FRAME_SIZE        ALIGN_UP((STACK_ITEMS*STACK_ITEM_SIZE) + STACK_SCRATCH_AREA_SIZE, STACK_ALIGNMENT)
38 #if (STACK_ITEMS % 2 == 0)
39 #       define STACK_FRAME_BIAS 8
40 #else
41 #       define STACK_FRAME_BIAS 16
42 #endif
44 /** Partitioning of bank 0 registers. */
45 #define R_OFFS          r16
46 #define R_HANDLER       r17
47 #define R_RET           r18
48 #define R_KSTACK_BSP    r22     /* keep in sync with before_thread_runs_arch() */
49 #define R_KSTACK        r23     /* keep in sync with before_thread_runs_arch() */
51 /** Heavyweight interrupt handler
52  *
53  * This macro roughly follows steps from 1 to 19 described in
54  * Intel Itanium Architecture Software Developer's Manual, Chapter 3.4.2.
55  *
56  * HEAVYWEIGHT_HANDLER macro must cram into 16 bundles (48 instructions).
57  * This goal is achieved by using procedure calls after RSE becomes operational.
58  *
59  * Some steps are skipped (enabling and disabling interrupts).
60  * Some steps are not fully supported yet (e.g. dealing with floating-point
61  * context).
62  *
63  * @param offs Offset from the beginning of IVT.
64  * @param handler Interrupt handler address.
65  */
66 .macro HEAVYWEIGHT_HANDLER offs, handler=universal_handler
67     .org ivt + \offs
68         mov R_OFFS = \offs
69         movl R_HANDLER = \handler ;;
70         br heavyweight_handler
71 .endm
73 .global heavyweight_handler
74 heavyweight_handler:
75     /* 1. copy interrupt registers into bank 0 */
76     
77         /*
78          * Note that r24-r31 from bank 0 can be used only as long as PSR.ic = 0.
79          */
80         mov r24 = cr.iip
81         mov r25 = cr.ipsr
82         mov r26 = cr.iipa
83         mov r27 = cr.isr
84         mov r28 = cr.ifa
85         
86     /* 2. preserve predicate register into bank 0 */
87         mov r29 = pr ;;
88         
89     /* 3. switch to kernel memory stack */
90         mov r30 = cr.ipsr
91         shr.u r31 = r12, VRN_SHIFT ;;
93         shr.u r30 = r30, PSR_CPL_SHIFT ;;
94         and r30 = PSR_CPL_MASK_SHIFTED, r30 ;;
96         /*
97          * Set p3 to true if the interrupted context executed in kernel mode.
98          * Set p4 to false if the interrupted context didn't execute in kernel mode.
99          */
100         cmp.eq p3, p4 = r30, r0 ;;
101         cmp.eq p1, p2 = r30, r0 ;;      /* remember IPSR setting in p1 and p2 */
103         /*
104          * Set p3 to true if the stack register references kernel address space.
105          * Set p4 to false if the stack register doesn't reference kernel address space.
106          */
107         (p3) cmp.eq p3, p4 = VRN_KERNEL, r31 ;;
108         
109         /*
110          * Now, p4 is true iff the stack needs to be switched to kernel stack.
111          */
112         mov r30 = r12
113         (p4) mov r12 = R_KSTACK ;;
114         
115         add r31 = -STACK_FRAME_BIAS, r12 ;;
116         add r12 = -STACK_FRAME_SIZE, r12
118     /* 4. save registers in bank 0 into memory stack */ 
119         st8 [r31] = r30, -8 ;;          /* save old stack pointer */ 
120         
121         st8 [r31] = r29, -8 ;;          /* save predicate registers */
123         st8 [r31] = r24, -8 ;;          /* save cr.iip */
124         st8 [r31] = r25, -8 ;;          /* save cr.ipsr */
125         st8 [r31] = r26, -8 ;;          /* save cr.iipa */
126         st8 [r31] = r27, -8 ;;          /* save cr.isr */
127         st8 [r31] = r28, -8 ;;          /* save cr.ifa */
129     /* 5. RSE switch from interrupted context */
130         mov r24 = ar.rsc
131         mov r25 = ar.pfs
132         cover
133         mov r26 = cr.ifs
134         
135         st8 [r31] = r24, -8 ;;          /* save ar.rsc */
136         st8 [r31] = r25, -8 ;;          /* save ar.pfs */
137         st8 [r31] = r26, -8             /* save ar.ifs */
138         
139         and r24 = ~(RSC_PL_MASK), r24 ;;
140         and r30 = ~(RSC_MODE_MASK), r24 ;;
141         mov ar.rsc = r30 ;;             /* update RSE state */
142         
143         mov r27 = ar.rnat
144         mov r28 = ar.bspstore ;;
145         
146         /*
147          * Inspect BSPSTORE to figure out whether it is necessary to switch to kernel BSPSTORE.
148          */
149         (p1) shr.u r30 = r28, VRN_SHIFT ;;
150         (p1) cmp.eq p1, p2 = VRN_KERNEL, r30 ;;
151         
152         /*
153          * If BSPSTORE needs to be switched, p1 is false and p2 is true.
154          */
155         (p1) mov r30 = r28
156         (p2) mov r30 = R_KSTACK_BSP ;;
157         (p2) mov ar.bspstore = r30 ;;
158         
159         mov r29 = ar.bsp
160         
161         st8 [r31] = r27, -8 ;;          /* save ar.rnat */
162         st8 [r31] = r30, -8 ;;          /* save new value written to ar.bspstore */
163         st8 [r31] = r28, -8 ;;          /* save ar.bspstore */
164         st8 [r31] = r29, -8             /* save ar.bsp */
165         
166         mov ar.rsc = r24                /* restore RSE's setting + kernel privileges */
167         
168     /* steps 6 - 15 are done by heavyweight_handler_inner() */
169         mov R_RET = b0                  /* save b0 belonging to interrupted context */
170         br.call.sptk.many b0 = heavyweight_handler_inner
171 0:      mov b0 = R_RET                  /* restore b0 belonging to the interrupted context */
173     /* 16. RSE switch to interrupted context */
174         cover                           /* allocate zerro size frame (step 1 (from Intel Docs)) */
176         add r31 = STACK_SCRATCH_AREA_SIZE, r12 ;;
178         ld8 r30 = [r31], +8 ;;          /* load ar.bsp */
179         ld8 r29 = [r31], +8 ;;          /* load ar.bspstore */
180         ld8 r28 = [r31], +8 ;;          /* load ar.bspstore_new */
181         sub r27 = r30 , r28 ;;          /* calculate loadrs (step 2) */
182         shl r27 = r27, 16
184         mov r24 = ar.rsc ;;
185         and r30 = ~3, r24 ;;
186         or  r24 = r30 , r27 ;;     
187         mov ar.rsc = r24 ;;             /* place RSE in enforced lazy mode */
189         loadrs                          /* (step 3) */
191         ld8 r27 = [r31], +8 ;;          /* load ar.rnat */
192         ld8 r26 = [r31], +8 ;;          /* load cr.ifs */
193         ld8 r25 = [r31], +8 ;;          /* load ar.pfs */
194         ld8 r24 = [r31], +8 ;;          /* load ar.rsc */
196         mov ar.bspstore = r29 ;;        /* (step 4) */
197         mov ar.rnat = r27               /* (step 5) */
199         mov ar.pfs = r25                /* (step 6) */
200         mov cr.ifs = r26        
202         mov ar.rsc = r24                /* (step 7) */
204     /* 17. restore interruption state from memory stack */
205         ld8 r28 = [r31], +8 ;;          /* load cr.ifa */               
206         ld8 r27 = [r31], +8 ;;          /* load cr.isr */
207         ld8 r26 = [r31], +8 ;;          /* load cr.iipa */
208         ld8 r25 = [r31], +8 ;;          /* load cr.ipsr */
209         ld8 r24 = [r31], +8 ;;          /* load cr.iip */
211         mov cr.iip = r24
212         mov cr.ipsr = r25
213         mov cr.iipa = r26
214         mov cr.isr = r27
215         mov cr.ifa = r28
217     /* 18. restore predicate registers from memory stack */
218         ld8 r29 = [r31], +8 ;;          /* load predicate registers */
219         mov pr = r29
220         
221     /* 19. return from interruption */
222         ld8 r12 = [r31]                 /* load stack pointer */ 
223         rfi ;;
225 .global heavyweight_handler_inner
226 heavyweight_handler_inner:
227         /*
228          * From this point, the rest of the interrupted context
229          * will be preserved in stacked registers and backing store.
230          */
231         alloc loc0 = ar.pfs, 0, 47, 2, 0 ;;
232         
233         /* bank 0 is going to be shadowed, copy essential data from there */
234         mov loc1 = R_RET        /* b0 belonging to interrupted context */
235         mov loc2 = R_HANDLER
236         mov out0 = R_OFFS
237         
238         add out1 = STACK_SCRATCH_AREA_SIZE, r12
240     /* 6. switch to bank 1 and reenable PSR.ic */
241         ssm PSR_IC_MASK
242         bsw.1 ;;
243         srlz.d
244         
245     /* 7. preserve branch and application registers */
246         mov loc3 = ar.unat
247         mov loc4 = ar.lc
248         mov loc5 = ar.ec
249         mov loc6 = ar.ccv
250         mov loc7 = ar.csd
251         mov loc8 = ar.ssd
252         
253         mov loc9 = b0
254         mov loc10 = b1
255         mov loc11 = b2
256         mov loc12 = b3
257         mov loc13 = b4
258         mov loc14 = b5
259         mov loc15 = b6
260         mov loc16 = b7
261         
262     /* 8. preserve general and floating-point registers */
263         /* TODO: save floating-point context */
264         mov loc17 = r1
265         mov loc18 = r2
266         mov loc19 = r3
267         mov loc20 = r4
268         mov loc21 = r5
269         mov loc22 = r6
270         mov loc23 = r7
271         mov loc24 = r8
272         mov loc25 = r9
273         mov loc26 = r10
274         mov loc27 = r11
275         /* skip r12 (stack pointer) */
276         mov loc28 = r13
277         mov loc29 = r14
278         mov loc30 = r15
279         mov loc31 = r16
280         mov loc32 = r17
281         mov loc33 = r18
282         mov loc34 = r19
283         mov loc35 = r20
284         mov loc36 = r21
285         mov loc37 = r22
286         mov loc38 = r23
287         mov loc39 = r24
288         mov loc40 = r25
289         mov loc41 = r26
290         mov loc42 = r27
291         mov loc43 = r28
292         mov loc44 = r29
293         mov loc45 = r30
294         mov loc46 = r31
295     
296     /* 9. skipped (will not enable interrupts) */
297         /*
298          * ssm PSR_I_MASK
299          * ;;
300          * srlz.d
301          */
303     /* 10. call handler */
304         movl r1 = _hardcoded_load_address
305     
306         mov b1 = loc2
307         br.call.sptk.many b0 = b1
309     /* 11. return from handler */
311         
312     /* 12. skipped (will not disable interrupts) */
313         /*
314          * rsm PSR_I_MASK
315          * ;;
316          * srlz.d
317          */
319     /* 13. restore general and floating-point registers */
320         /* TODO: restore floating-point context */
321         mov r1 = loc17
322         mov r2 = loc18
323         mov r3 = loc19
324         mov r4 = loc20
325         mov r5 = loc21
326         mov r6 = loc22
327         mov r7 = loc23
328         mov r8 = loc24
329         mov r9 = loc25
330         mov r10 = loc26
331         mov r11 = loc27
332         /* skip r12 (stack pointer) */
333         mov r13 = loc28
334         mov r14 = loc29
335         mov r15 = loc30
336         mov r16 = loc31
337         mov r17 = loc32
338         mov r18 = loc33
339         mov r19 = loc34
340         mov r20 = loc35
341         mov r21 = loc36
342         mov r22 = loc37
343         mov r23 = loc38
344         mov r24 = loc39
345         mov r25 = loc40
346         mov r26 = loc41 
347         mov r27 = loc42
348         mov r28 = loc43
349         mov r29 = loc44
350         mov r30 = loc45
351         mov r31 = loc46
352         
353     /* 14. restore branch and application registers */
354         mov ar.unat = loc3
355         mov ar.lc = loc4
356         mov ar.ec = loc5
357         mov ar.ccv = loc6
358         mov ar.csd = loc7
359         mov ar.ssd = loc8
360         
361         mov b0 = loc9
362         mov b1 = loc10
363         mov b2 = loc11
364         mov b3 = loc12
365         mov b4 = loc13
366         mov b5 = loc14
367         mov b6 = loc15
368         mov b7 = loc16
369         
370     /* 15. disable PSR.ic and switch to bank 0 */
371         rsm PSR_IC_MASK
372         bsw.0 ;;
373         srlz.d
375         mov R_RET = loc1
376         mov ar.pfs = loc0
377         br.ret.sptk.many b0
379 .global ivt
380 .align 32768
381 ivt:
382         HEAVYWEIGHT_HANDLER 0x0000
383         HEAVYWEIGHT_HANDLER 0x0400
384         HEAVYWEIGHT_HANDLER 0x0800
385         HEAVYWEIGHT_HANDLER 0x0c00 alternate_instruction_tlb_fault
386         HEAVYWEIGHT_HANDLER 0x1000 alternate_data_tlb_fault
387         HEAVYWEIGHT_HANDLER 0x1400 data_nested_tlb_fault
388         HEAVYWEIGHT_HANDLER 0x1800
389         HEAVYWEIGHT_HANDLER 0x1c00
390         HEAVYWEIGHT_HANDLER 0x2000 data_dirty_bit_fault
391         HEAVYWEIGHT_HANDLER 0x2400 instruction_access_bit_fault
392         HEAVYWEIGHT_HANDLER 0x2800 data_access_bit_fault
393         HEAVYWEIGHT_HANDLER 0x2c00 break_instruction
394         HEAVYWEIGHT_HANDLER 0x3000 external_interrupt   /* For external interrupt, heavyweight handler is used. */
395         HEAVYWEIGHT_HANDLER 0x3400
396         HEAVYWEIGHT_HANDLER 0x3800
397         HEAVYWEIGHT_HANDLER 0x3c00
398         HEAVYWEIGHT_HANDLER 0x4000
399         HEAVYWEIGHT_HANDLER 0x4400
400         HEAVYWEIGHT_HANDLER 0x4800
401         HEAVYWEIGHT_HANDLER 0x4c00
403         HEAVYWEIGHT_HANDLER 0x5000 page_not_present
404         HEAVYWEIGHT_HANDLER 0x5100
405         HEAVYWEIGHT_HANDLER 0x5200
406         HEAVYWEIGHT_HANDLER 0x5300
407         HEAVYWEIGHT_HANDLER 0x5400 general_exception
408         HEAVYWEIGHT_HANDLER 0x5500
409         HEAVYWEIGHT_HANDLER 0x5600
410         HEAVYWEIGHT_HANDLER 0x5700
411         HEAVYWEIGHT_HANDLER 0x5800
412         HEAVYWEIGHT_HANDLER 0x5900
413         HEAVYWEIGHT_HANDLER 0x5a00
414         HEAVYWEIGHT_HANDLER 0x5b00
415         HEAVYWEIGHT_HANDLER 0x5c00
416         HEAVYWEIGHT_HANDLER 0x5d00
417         HEAVYWEIGHT_HANDLER 0x5e00
418         HEAVYWEIGHT_HANDLER 0x5f00
419         
420         HEAVYWEIGHT_HANDLER 0x6000
421         HEAVYWEIGHT_HANDLER 0x6100
422         HEAVYWEIGHT_HANDLER 0x6200
423         HEAVYWEIGHT_HANDLER 0x6300
424         HEAVYWEIGHT_HANDLER 0x6400
425         HEAVYWEIGHT_HANDLER 0x6500
426         HEAVYWEIGHT_HANDLER 0x6600
427         HEAVYWEIGHT_HANDLER 0x6700
428         HEAVYWEIGHT_HANDLER 0x6800
429         HEAVYWEIGHT_HANDLER 0x6900
430         HEAVYWEIGHT_HANDLER 0x6a00
431         HEAVYWEIGHT_HANDLER 0x6b00
432         HEAVYWEIGHT_HANDLER 0x6c00
433         HEAVYWEIGHT_HANDLER 0x6d00
434         HEAVYWEIGHT_HANDLER 0x6e00
435         HEAVYWEIGHT_HANDLER 0x6f00
437         HEAVYWEIGHT_HANDLER 0x7000
438         HEAVYWEIGHT_HANDLER 0x7100
439         HEAVYWEIGHT_HANDLER 0x7200
440         HEAVYWEIGHT_HANDLER 0x7300
441         HEAVYWEIGHT_HANDLER 0x7400
442         HEAVYWEIGHT_HANDLER 0x7500
443         HEAVYWEIGHT_HANDLER 0x7600
444         HEAVYWEIGHT_HANDLER 0x7700
445         HEAVYWEIGHT_HANDLER 0x7800
446         HEAVYWEIGHT_HANDLER 0x7900
447         HEAVYWEIGHT_HANDLER 0x7a00
448         HEAVYWEIGHT_HANDLER 0x7b00
449         HEAVYWEIGHT_HANDLER 0x7c00
450         HEAVYWEIGHT_HANDLER 0x7d00
451         HEAVYWEIGHT_HANDLER 0x7e00
452         HEAVYWEIGHT_HANDLER 0x7f00