source: trunk/packages/xen-common/xen-common/extras/mini-os/arch/ia64/fw.S @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 11.2 KB
Line 
1/*
2 * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>
3 * Parts taken from FreeBSD.
4 *
5 ***************************************************************************
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. 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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30
31#include "asm.h"
32#include "page.h"
33#include "ia64_cpu.h"
34#include "ia64_fpu.h"
35#include "offsets.h"
36#include "xen/xen.h"
37
38
39/*
40 * ia64_change_mode:    change mode to/from physical mode
41 *
42 * Arguments:
43 *      r14     psr for desired mode
44 *
45 * Modifies:
46 *      r15-r20 scratch
47 *      ar.bsp  translated to new mode
48 *      sp      translated to new mode
49 *      iip     translated to new mode
50 */
51ENTRY(ia64_change_mode)
52        rsm     psr.i | psr.ic
53        mov     r19=ar.rsc              // save rsc while we change mode
54        tbit.nz p8,p9=r14,17            // Uses psr.dt-physical or virtual ?
55                        // p8 == true: switch to virtual
56                        // p9 == true: switch to physical
57        ;;
58        mov     ar.rsc=IA64_RSE_LAZY    // turn off RSE
59        mov     r16=rp
60        ;;
61        flushrs                         // clean the rse
62        srlz.i
63        ;;
641:      mov     r15=ip
65        mov     r17=ar.bsp
66        mov     r18=ar.rnat
67        ;;
68        add     r15=2f-1b,r15           // address to rfi to
69                /* !!! must be the same like in  minios-ia64.lds */
70(p8)    movl    r20=(KERNEL_START - (1<<KERNEL_PHYS_START_SHIFT))
71        ;;
72                        // (p8): switch to virtual
73                        // (p9): switch to physical
74
75                // from virtual to physical
76(p9)    tpa     r15=r15                 // ip
77(p9)    tpa     r16=r16                 // rp
78(p9)    tpa     r17=r17                 // ar.bsp
79(p9)    tpa     sp=sp                   // sp
80        ;;              /* Needed only for assembler violate ... warnings. */
81                // from physical to virtual
82(p8)    add     r15=r20,r15             // ip
83(p8)    add     r16=r20,r16             // rp
84(p8)    add     r17=r20,r17             // ar.bsp
85(p8)    add     sp=r20,sp               // sp
86        ;;
87        mov     ar.bspstore=r17
88        mov     rp=r16
89        ;;
90        mov     ar.rnat=r18
91        mov     cr.iip=r15
92        mov     cr.ipsr=r14             // psr for new mode
93        mov     cr.ifs=r0
94        ;;
95        rfi
96        ;;
972:      mov     ar.rsc=r19              // restore ar.rsc
98        ;;
99        br.ret.sptk.few rp              // now in new mode
100END(ia64_change_mode)
101
102/*
103 * ia64_physical_mode:  change mode to physical mode
104 *
105 * Return:
106 *  ret0  psr to restore
107 *
108 * Modifies:
109 *  r15-r18 scratch
110 *  ar.bsp  tranlated to physical mode
111 *  psr.i cleared
112 */
113ENTRY(ia64_physical_mode)
114        mov     r14=psr
115        movl    r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|        \
116                        IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH)
117        ;;
118        mov     ret0=r14
119        movl    r16=IA64_PSR_BN
120        ;;
121        andcm   r14=r14,r15     // clear various xT bits
122        ;;
123        or      r14=r14,r16     // make sure BN=1
124        or      ret0=ret0,r16   // make sure BN=1
125        ;;
126        br.cond.sptk.many ia64_change_mode
127END(ia64_physical_mode)
128
129/*
130 * ia64_call_efi_physical:      call an EFI procedure in physical mode
131 *
132 * Arguments:
133 *      in0             Address of EFI procedure descriptor
134 *      in1-in5         Arguments to EFI procedure
135 *
136 * Return:
137 *      ret0-ret3       return values from EFI
138 *
139 */
140ENTRY(ia64_call_efi_physical)
141        .prologue
142        .regstk 6,4,5,0
143        .save   ar.pfs,loc0
144        alloc   loc0=ar.pfs,6,4,5,0
145        ;;
146        .save   rp,loc1
147        mov     loc1=rp
148        ;;
149        .body
150        br.call.sptk.many rp=ia64_physical_mode
151        ;;
152
153        mov     loc2=r8                 // psr to restore mode
154        mov     loc3=gp                 // save kernel gp
155        ld8     r14=[in0],8             // function address
156        ;;
157        ld8     gp=[in0]                // function gp value
158#if defined(BIG_ENDIAN)
159        mux1    r14=r14,@rev            // swap because mini-os is in BE
160        mov     ar.rsc=3
161        ;;
162#endif
163        mov     out0=in1
164        mov     out1=in2
165        mov     out2=in3
166        mov     out3=in4
167        mov     out4=in5
168        mov     b6=r14
169        ;;
170#if defined(BIG_ENDIAN)
171        mux1    gp=gp,@rev              // swap because mini-os is in BE
172        rum IA64_PSR_BE
173        ;;
174#endif
175
176        br.call.sptk.many rp=b6         // call EFI procedure
177
178#if defined(BIG_ENDIAN)
179        ;;
180        sum IA64_PSR_BE
181        mov     ar.rsc=IA64_RSE_EAGER
182#endif
183        mov     gp=loc3                 // restore kernel gp
184        mov     r14=loc2                // psr to restore mode
185        ;;
186        br.call.sptk.many rp=ia64_change_mode
187        ;;
188        mov     rp=loc1
189        mov     ar.pfs=loc0
190        ;;
191        br.ret.sptk.many rp
192END(ia64_call_efi_physical)
193       
194
195/*
196 * struct ia64_pal_result ia64_call_pal_static(uint64_t proc,
197 *      uint64_t arg1, uint64_t arg2, uint64_t arg3)
198 */
199ENTRY(ia64_call_pal_static)
200       
201        .regstk 4,5,0,0
202palret  =       loc0
203entry   =       loc1
204rpsave  =       loc2
205pfssave =       loc3
206psrsave =       loc4
207
208        alloc   pfssave=ar.pfs,4,5,0,0
209        ;;
210        mov     rpsave=rp
211
212        movl    entry=@gprel(ia64_pal_entry)
2131:      mov     palret=ip               // for return address
214        ;;
215        add     entry=entry,gp
216        mov     psrsave=psr
217        mov     r28=in0                 // procedure number
218        ;;
219        ld8     entry=[entry]           // read entry point
220        mov     r29=in1                 // copy arguments
221        mov     r30=in2
222        mov     r31=in3
223        ;;
224        mov     b6=entry
225        add     palret=2f-1b,palret     // calculate return address
226        ;;
227        mov     b0=palret
228        rsm     psr.i                   // disable interrupts
229        ;;
230#if defined(BIG_ENDIAN)
231        rum     IA64_PSR_BE             // set psr.be==0
232        ;;
233#endif
234        br.cond.sptk b6                 // call into firmware
235        ;;
236#if defined(BIG_ENDIAN)
237        sum     IA64_PSR_BE             // set psr.be==1
238        ;;
239#endif
240        ssm     psr.i                   // enable interrupts
241        ;;
2422:      mov     psr.l=psrsave
243        mov     rp=rpsave
244        mov     ar.pfs=pfssave
245        ;;
246        srlz.d
247        br.ret.sptk rp
248
249END(ia64_call_pal_static)
250
251/*
252 * Call a efi function.
253 * in0: func descriptor
254 * in1: param1
255 * ...
256 * in5: param5
257 */
258ENTRY(ia64_call_efi_func)
259        alloc   loc0=ar.pfs,6,3,5,0
260
261        mov     loc1=gp
262        mov     loc2=rp
263
264        mov     out0=in1
265        mov     out1=in2
266        mov     out2=in3
267        mov     out3=in4
268        mov     out4=in5
269
270        ld8     r14=[in0],8             // get function address
271        ;;
272        ld8     gp=[in0]                // function gp value
273        ;;
274#if defined(BIG_ENDIAN)
275        mux1    r14=r14,@rev            // swap if mini-os is in BE
276        mux1    gp=gp,@rev              // swap if mini-os is in BE
277#endif
278        ;;
279        mov     b6=r14
280
281#if defined(BIG_ENDIAN)
282        rum     IA64_PSR_BE
283        ;;
284#endif
285
286        br.call.sptk.many rp=b6         // call EFI procedure
287       
288#if defined(BIG_ENDIAN)
289        sum     IA64_PSR_BE
290        ;;
291#endif
292       
293        mov     ar.pfs=loc0
294        mov     gp=loc1
295        mov     rp=loc2
296        br.ret.sptk rp
297
298END(ia64_call_efi_func)
299
300
301/* Restore the context from the thread context.
302 */
303ENTRY(restore_context)
304{       .mmi
305        invala
306        mov     ar.rsc=IA64_RSE_LAZY
307        add     r29=SW_SP,in0
308}
309        add     r30=SW_RP,in0
310        add     r31=SW_PR,in0
311        ;;
312        ld8     r12=[r29],SW_LC-SW_SP           // load sp
313        ld8     r16=[r30],SW_BSP-SW_RP          // load rp
314        ;;
315        ld8     r17=[r31],SW_RNAT-SW_PR         // load pr
316        ld8     r18=[r30],SW_PFS-SW_BSP         // load bsp
317        mov     rp=r16
318        ;;
319        ld8     r16=[r31],SW_R4-SW_RNAT         // load rnat
320        mov     pr=r17,-1                       // set pr
321        mov     ar.bspstore=r18
322        ;;
323        ld8     r18=[r30],SW_UNATA-SW_PFS       // load pfs
324        ld8     r17=[r29],SW_UNATB-SW_LC        // load lc
325        mov     ar.rnat=r16
326        ;;
327        ld8     r16=[r30],SW_R5-SW_UNATA        // load unat_a
328        mov     ar.pfs=r18
329        mov     ar.lc=r17
330        ;;
331        ld8.fill r4=[r31],SW_R6-SW_R4           // load r4
332        mov     ar.unat=r16
333        ;;
334        ld8.fill r5=[r30],SW_R7-SW_R5           // load r5
335        ld8     r16=[r29],SW_B3-SW_UNATB        // load unat_b
336        mov     ar.rsc=IA64_RSE_EAGER
337        ;;
338        ld8.fill r6=[r31],SW_B1-SW_R6           // load r6
339        ld8.fill r7=[r30],SW_B2-SW_R7           // load r7
340        ;;
341        ld8     r17=[r31],SW_B4-SW_B1           // load b1
342        ld8     r18=[r30],SW_B5-SW_B2           // load b2
343        mov     ar.unat=r16                     // unat_b
344        ;;
345        ld8     r16=[r29],SW_F2-SW_B3           // load b3
346        mov     b1=r17
347        mov     b2=r18
348        ;;
349        ld8     r17=[r31],SW_F3-SW_B4           // load b4
350        ld8     r18=[r30],SW_F4-SW_B5           // load b5
351        mov     b3=r16
352        ;;
353        ldf.fill f2=[r29]                       // load f2
354        mov     b4=r17
355        mov     b5=r18
356        ;;
357        ldf.fill f3=[r31],SW_F5-SW_F3           // load f3
358        ldf.fill f4=[r30],SW_F4-SW_F2           // load f4
359        ;;
360        ldf.fill f5=[r31],SW_F5-SW_F3           // load f5
361        ldf.fill f16=[r30],SW_F4-SW_F2          // load f16
362        ;;
363        ldf.fill f17=[r31],SW_F5-SW_F3          // load f17
364        ldf.fill f18=[r30],SW_F4-SW_F2          // load f18
365        ;;
366        ldf.fill f19=[r31],SW_F5-SW_F3          // load f19
367        ldf.fill f20=[r30],SW_F4-SW_F2          // load f20
368        ;;
369        ldf.fill f21=[r31],SW_F5-SW_F3          // load f21
370        ldf.fill f22=[r30],SW_F4-SW_F2          // load f22
371        ;;
372        ldf.fill f23=[r31],SW_F5-SW_F3          // load f23
373        ldf.fill f24=[r30],SW_F4-SW_F2          // load f24
374        ;;
375        ldf.fill f25=[r31],SW_F5-SW_F3          // load f25
376        ldf.fill f26=[r30],SW_F4-SW_F2          // load f26
377        ;;
378        ldf.fill f27=[r31],SW_F5-SW_F3          // load f27
379        ldf.fill f28=[r30],SW_F4-SW_F2          // load f28
380        ;;
381        ldf.fill f29=[r31],SW_F5-SW_F3          // load f29
382        ldf.fill f30=[r30],SW_F4-SW_F2          // load f30
383        ;;
384        ldf.fill f31=[r30],SW_F4-SW_F2          // load f31
385        add             r8=1,r0
386        br.ret.sptk     rp
387        ;;
388END(restore_context)
389
390/*
391 * void switch_context(struct thread* old, struct thread* new)
392 */
393ENTRY(switch_context)
394
395        mov     ar.rsc=IA64_RSE_LAZY
396        mov     r16=ar.unat
397        add     r31=SW_UNATB,in0
398        add     r30=SW_SP,in0
399        ;;
400{       .mmi
401        flushrs
402        st8     [r30]=sp,SW_RP-SW_SP            // sp
403        mov     r17=rp
404        ;;
405}
406        st8     [r31]=r16,SW_PR-SW_UNATB        // unat (before)
407        st8     [r30]=r17,SW_BSP-SW_RP          // rp
408        mov     r16=pr
409        ;;
410        st8     [r31]=r16,SW_PFS-SW_PR          // pr
411        mov     r17=ar.bsp
412        mov     r16=ar.pfs
413        ;;
414        st8     [r31]=r16,SW_RNAT-SW_PFS        // save pfs
415        st8     [r30]=r17,SW_R4-SW_BSP          // save bsp
416        mov     r16=ar.rnat
417        ;;
418        st8     [r31]=r16,SW_R5-SW_RNAT         // save rnat
419        mov     ar.rsc=IA64_RSE_EAGER
420        ;;
421{       .mmi
422        .mem.offset     8,0
423        st8.spill       [r30]=r4,SW_R6-SW_R4    // r4
424        .mem.offset     16,0
425        st8.spill       [r31]=r5,SW_R7-SW_R5    // r5
426        mov             r16=b1
427        ;;
428}
429{       .mmi
430        .mem.offset     8,0
431        st8.spill       [r30]=r4,SW_B1-SW_R6    // r6
432        .mem.offset     16,0
433        st8.spill       [r31]=r5,SW_B2-SW_R7    // r7
434        mov             r17=b2
435        ;;
436}
437        st8     [r30]=r16,SW_UNATA-SW_B1        // b1
438        st8     [r31]=r17,SW_B3-SW_B2           // b2
439        mov     r18=ar.unat
440        mov     r19=b3
441        mov     r20=b4
442        mov     r21=b5
443        ;;
444        st8     [r30]=r18,SW_B4-SW_UNATA        // unat (after)
445        st8     [r31]=r19,SW_B5-SW_B3           // b3
446        ;;
447        st8     [r30]=r20,SW_LC-SW_B4           // b4
448        st8     [r31]=r21,SW_F2-SW_B5           // b5
449        mov     r17=ar.lc
450        ;;
451        st8             [r30]=r17,SW_F3-SW_LC   // ar.lc
452        stf.spill       [r31]=f2,SW_F4-SW_F2
453        ;;
454        stf.spill       [r30]=f3,SW_F5-SW_F3
455        stf.spill       [r31]=f4,SW_F4-SW_F2
456        ;;
457        stf.spill       [r30]=f5,SW_F5-SW_F3
458        stf.spill       [r31]=f16,SW_F4-SW_F2
459        ;;
460        stf.spill       [r30]=f17,SW_F5-SW_F3
461        stf.spill       [r31]=f18,SW_F4-SW_F2
462        ;;
463        stf.spill       [r30]=f19,SW_F5-SW_F3
464        stf.spill       [r31]=f20,SW_F4-SW_F2
465        ;;
466        stf.spill       [r30]=f21,SW_F5-SW_F3
467        stf.spill       [r31]=f22,SW_F4-SW_F2
468        ;;
469        stf.spill       [r30]=f23,SW_F5-SW_F3
470        stf.spill       [r31]=f24,SW_F4-SW_F2
471        ;;
472        stf.spill       [r30]=f25,SW_F5-SW_F3
473        stf.spill       [r31]=f26,SW_F4-SW_F2
474        ;;
475        stf.spill       [r30]=f27,SW_F5-SW_F3
476        stf.spill       [r31]=f28,SW_F4-SW_F2
477        ;;
478        stf.spill       [r30]=f29,SW_F4-SW_F2
479        stf.spill       [r31]=f30
480        ;;
481        stf.spill       [r30]=f31
482        add             r8=0,r0
483        mf
484//      br.ret.sptk     rp
485
486{       .mfb
487        mov             r32=r33
488        nop             0
489        br.sptk         restore_context
490        ;;
491}
492
493END(switch_context)
494
495/*
496 * The function is used to start a new thread.
497 */
498ENTRY(thread_starter)
499
500        .prologue
501        .save   ar.pfs,loc0
502        alloc   loc0=ar.pfs,0,1,1,0
503        ;;
504        .body
505        ;;
506        mov     b7=r4                   // the function pointer
507        mov     out0=r6                 // the argument
508        ;;
509        br.call.sptk.many rp=b7         // Call the thread function
510        ;;
511        br.call.sptk.many rp=exit_thread        // call exit_thread
512        ;;
513END(thread_starter)
514
515ENTRY(__hypercall)
516        mov r2=r37
517        break 0x1000
518        br.ret.sptk.many b0
519        ;;
520END(__hypercall)
521
522/*
523 * Stub for suspend.
524 * Just force the stacked registers to be written in memory.
525 */
526ENTRY(xencomm_arch_hypercall_suspend)
527        ;;
528        alloc   r20=ar.pfs,0,0,6,0
529        mov     r2=__HYPERVISOR_sched_op
530        ;;
531        /* We don't want to deal with RSE.  */
532        flushrs
533        mov     r33=r32
534        mov     r32=2           // SCHEDOP_shutdown
535        ;;
536        break   0x1000
537        ;;
538        br.ret.sptk.many b0
539END(xencomm_arch_hypercall_suspend)
540
Note: See TracBrowser for help on using the repository browser.