vserver 1.9.5.x5
[linux-2.6.git] / arch / parisc / kernel / head.S
1 /* This file is subject to the terms and conditions of the GNU General Public
2  * License.  See the file "COPYING" in the main directory of this archive
3  * for more details.
4  *
5  * Copyright (C) 1999 by Helge Deller
6  * Copyright 1999 SuSE GmbH (Philipp Rumpf)
7  * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
8  * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com)
9  * Copyright (C) 2001 Grant Grundler (Hewlett Packard)
10  * Copyright (C) 2004 Kyle McMartin <kyle@debian.org>
11  *
12  * Initial Version 04-23-1999 by Helge Deller <deller@gmx.de>
13  */
14
15 #include <linux/autoconf.h>     /* for CONFIG_SMP */
16
17 #include <asm/offsets.h>
18 #include <asm/psw.h>
19 #include <asm/pdc.h>
20         
21 #include <asm/assembly.h>
22 #include <asm/pgtable.h>
23
24         .level  LEVEL
25
26         .data
27
28         .export boot_args
29 boot_args:
30         .word 0 /* arg0 */
31         .word 0 /* arg1 */
32         .word 0 /* arg2 */
33         .word 0 /* arg3 */
34
35         .text
36         .align  4
37         .import init_thread_union,data
38         .import fault_vector_20,code    /* IVA parisc 2.0 32 bit */
39 #ifndef __LP64__
40         .import fault_vector_11,code    /* IVA parisc 1.1 32 bit */
41         .import $global$                /* forward declaration */
42 #endif /*!LP64*/
43         .export stext
44         .export _stext,data             /* Kernel want it this way! */
45 _stext:
46 stext:
47         .proc
48         .callinfo
49
50         /* Make sure sr4-sr7 are set to zero for the kernel address space */
51         mtsp    %r0,%sr4
52         mtsp    %r0,%sr5
53         mtsp    %r0,%sr6
54         mtsp    %r0,%sr7
55
56         /* Clear BSS (shouldn't the boot loader do this?) */
57
58         .import __bss_start,data
59         .import __bss_stop,data
60
61         load32          PA(__bss_start),%r3
62         load32          PA(__bss_stop),%r4
63 $bss_loop:
64         cmpb,<<,n       %r3,%r4,$bss_loop
65         stw,ma          %r0,4(%r3)
66
67         /* Save away the arguments the boot loader passed in (32 bit args) */
68         load32          PA(boot_args),%r1
69         stw,ma          %arg0,4(%r1)
70         stw,ma          %arg1,4(%r1)
71         stw,ma          %arg2,4(%r1)
72         stw,ma          %arg3,4(%r1)
73
74         /* Initialize startup VM. Just map first 8 MB of memory */
75         load32          PA(pg0),%r1
76
77 #ifdef __LP64__
78         load32          PA(pmd0),%r5
79         shrd            %r5,PxD_VALUE_SHIFT,%r3 
80 #else
81         shr             %r1,PxD_VALUE_SHIFT,%r3
82 #endif
83         ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3      
84         
85         load32          PA(swapper_pg_dir),%r4
86         mtctl           %r4,%cr24       /* Initialize kernel root pointer */
87         mtctl           %r4,%cr25       /* Initialize user root pointer */
88
89 #ifdef __LP64__
90         stw             %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
91         shrd            %r1,PxD_VALUE_SHIFT,%r3
92         ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
93         ldo             ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r5
94 #else
95         ldo             ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
96 #endif
97         ldi             ASM_PT_INITIAL,%r1
98
99 1:
100 #ifdef __LP64__
101         stw             %r3,0(%r5)
102 #else
103         stw             %r3,0(%r4)
104 #endif
105         
106         ldo             (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
107         addib,>         -1,%r1,1b
108
109 #ifdef __LP64__
110         ldo             ASM_PMD_ENTRY_SIZE(%r5),%r5
111 #else
112         ldo             ASM_PGD_ENTRY_SIZE(%r4),%r4
113 #endif
114
115         ldo             _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
116         load32          PA(pg0),%r1
117
118 $pgt_fill_loop:
119         STREGM          %r3,ASM_PTE_ENTRY_SIZE(%r1)
120         ldo             ASM_PAGE_SIZE(%r3),%r3
121         bb,>=           %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop
122         nop
123
124         /* Load the return address...er...crash 'n burn */
125         copy            %r0,%r2
126
127         /* And the RFI Target address too */
128         load32          start_kernel,%r11
129
130         /* And the initial task pointer */
131         load32          init_thread_union,%r6
132         mtctl           %r6,%cr30
133
134         /* And the stack pointer too */
135         ldo             THREAD_SZ_ALGN(%r6),%sp
136
137         /* And the interrupt stack */
138         load32          interrupt_stack,%r6
139         mtctl           %r6,%cr31
140
141 #ifdef CONFIG_SMP
142         /* Set the smp rendevous address into page zero.
143         ** It would be safer to do this in init_smp_config() but
144         ** it's just way easier to deal with here because
145         ** of 64-bit function ptrs and the address is local to this file.
146         */
147         load32          PA(smp_slave_stext),%r10
148         stw             %r10,0x10(%r0)  /* MEM_RENDEZ */
149         stw             %r0,0x28(%r0)   /* MEM_RENDEZ_HI - assume addr < 4GB */
150
151         /* FALLTHROUGH */
152         .procend
153
154         /*
155         ** Code Common to both Monarch and Slave processors.
156         ** Entry:
157         **
158         **  1.1:        
159         **    %r11 must contain RFI target address.
160         **    %r25/%r26 args to pass to target function
161         **    %r2  in case rfi target decides it didn't like something
162         **
163         **  2.0w:
164         **    %r3  PDCE_PROC address
165         **    %r11 RFI target address
166         **
167         ** Caller must init: SR4-7, %sp, %r10, %cr24/25, 
168         */
169 common_stext:
170         .proc
171         .callinfo
172 #else
173         /* Clear PDC entry point - we won't use it */
174         stw             %r0,0x10(%r0)   /* MEM_RENDEZ */
175         stw             %r0,0x28(%r0)   /* MEM_RENDEZ_HI */
176 #endif /*CONFIG_SMP*/
177
178 #ifdef __LP64__
179         tophys_r1       %sp
180
181         /* Save the rfi target address */
182         ldd             TI_TASK-THREAD_SZ_ALGN(%sp), %r10
183         tophys_r1       %r10
184         std             %r11,  TASK_PT_GR11(%r10)
185         /* Switch to wide mode Superdome doesn't support narrow PDC
186         ** calls.
187         */
188 1:      mfia            %rp             /* clear upper part of pcoq */
189         ldo             2f-1b(%rp),%rp
190         depdi           0,31,32,%rp
191         bv              (%rp)
192         ssm             PSW_SM_W,%r0
193
194         /* Set Wide mode as the "Default" (eg for traps)
195         ** First trap occurs *right* after (or part of) rfi for slave CPUs.
196         ** Someday, palo might not do this for the Monarch either.
197         */
198 2:
199 #define MEM_PDC_LO 0x388
200 #define MEM_PDC_HI 0x35C
201         ldw             MEM_PDC_LO(%r0),%r3
202         ldw             MEM_PDC_HI(%r0),%r6
203         depd            %r6, 31, 32, %r3        /* move to upper word */
204
205         ldo             PDC_PSW(%r0),%arg0              /* 21 */
206         ldo             PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */
207         ldo             PDC_PSW_WIDE_BIT(%r0),%arg2     /* 2 */
208         load32          PA(stext_pdc_ret), %rp
209         bv              (%r3)
210         copy            %r0,%arg3
211
212 stext_pdc_ret:
213         /* restore rfi target address*/
214         ldd             TI_TASK-THREAD_SZ_ALGN(%sp), %r10
215         tophys_r1       %r10
216         ldd             TASK_PT_GR11(%r10), %r11
217         tovirt_r1       %sp
218 #endif
219         
220         /* PARANOID: clear user scratch/user space SR's */
221         mtsp    %r0,%sr0
222         mtsp    %r0,%sr1
223         mtsp    %r0,%sr2
224         mtsp    %r0,%sr3
225
226         /* Initialize Protection Registers */
227         mtctl   %r0,%cr8
228         mtctl   %r0,%cr9
229         mtctl   %r0,%cr12
230         mtctl   %r0,%cr13
231
232         /* Prepare to RFI! Man all the cannons! */
233
234         /* Initialize the global data pointer */
235         loadgp
236
237         /* Set up our interrupt table.  HPMCs might not work after this! 
238          *
239          * We need to install the correct iva for PA1.1 or PA2.0. The
240          * following short sequence of instructions can determine this
241          * (without being illegal on a PA1.1 machine).
242          */
243 #ifndef __LP64__
244         ldi             32,%r10
245         mtctl           %r10,%cr11
246         .level 2.0
247         mfctl,w         %cr11,%r10
248         .level 1.1
249         comib,<>,n      0,%r10,$is_pa20
250         ldil            L%PA(fault_vector_11),%r10
251         b               $install_iva
252         ldo             R%PA(fault_vector_11)(%r10),%r10
253
254 $is_pa20:
255         .level          LEVEL /* restore 1.1 || 2.0w */
256 #endif /*!LP64*/
257         load32          PA(fault_vector_20),%r10
258
259 $install_iva:
260         mtctl           %r10,%cr14
261
262 #ifdef __LP64__
263         b               aligned_rfi
264         nop
265
266         .align          256
267 aligned_rfi:
268         ssm             0,0
269         nop             /* 1 */
270         nop             /* 2 */
271         nop             /* 3 */
272         nop             /* 4 */
273         nop             /* 5 */
274         nop             /* 6 */
275         nop             /* 7 */
276         nop             /* 8 */
277 #endif
278
279 #ifdef __LP64__ /* move to psw.h? */
280 #define         PSW_BITS        PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R
281 #else
282 #define         PSW_BITS        PSW_SM_Q
283 #endif
284
285 $rfi:   
286         /* turn off troublesome PSW bits */
287         rsm             PSW_BITS,%r0
288
289         /* kernel PSW:
290          *  - no interruptions except HPMC and TOC (which are handled by PDC)
291          *  - Q bit set (IODC / PDC interruptions)
292          *  - big-endian
293          *  - virtually mapped
294          */
295         load32          KERNEL_PSW,%r10
296         mtctl           %r10,%ipsw
297
298         /* Set the space pointers for the post-RFI world
299         ** Clear the two-level IIA Space Queue, effectively setting
300         ** Kernel space.
301         */
302         mtctl           %r0,%cr17       /* Clear IIASQ tail */
303         mtctl           %r0,%cr17       /* Clear IIASQ head */
304
305         /* Load RFI target into PC queue */
306         mtctl           %r11,%cr18      /* IIAOQ head */
307         ldo             4(%r11),%r11
308         mtctl           %r11,%cr18      /* IIAOQ tail */
309
310         /* Jump to hyperspace */
311         rfi
312         nop
313
314         .procend
315
316 #ifdef CONFIG_SMP
317
318         .import smp_init_current_idle_task,data
319         .import smp_callin,code
320
321 #ifndef __LP64__
322 smp_callin_rtn:
323         .proc
324         .callinfo
325         break   1,1             /*  Break if returned from start_secondary */
326         nop
327         nop
328         .procend
329 #endif /*!LP64*/
330
331 /***************************************************************************
332 * smp_slave_stext is executed by all non-monarch Processors when the Monarch
333 * pokes the slave CPUs in smp.c:smp_boot_cpus().
334 *
335 * Once here, registers values are initialized in order to branch to virtual
336 * mode. Once all available/eligible CPUs are in virtual mode, all are
337 * released and start out by executing their own idle task.
338 *****************************************************************************/
339 smp_slave_stext:
340         .proc
341         .callinfo
342
343         /*
344         ** Initialize Space registers
345         */
346         mtsp       %r0,%sr4
347         mtsp       %r0,%sr5
348         mtsp       %r0,%sr6
349         mtsp       %r0,%sr7
350
351         /*  Initialize the SP - monarch sets up smp_init_current_idle_task */
352         load32          PA(smp_init_current_idle_task),%sp
353         LDREG           0(%sp),%sp      /* load task address */
354         tophys_r1       %sp
355         LDREG           TASK_THREAD_INFO(%sp),%sp
356         mtctl           %sp,%cr30       /* store in cr30 */
357         ldo             THREAD_SZ_ALGN(%sp),%sp
358
359         /* point CPU to kernel page tables */
360         load32          PA(swapper_pg_dir),%r4
361         mtctl           %r4,%cr24       /* Initialize kernel root pointer */
362         mtctl           %r4,%cr25       /* Initialize user root pointer */
363
364 #ifdef __LP64__
365         /* Setup PDCE_PROC entry */
366         copy            %arg0,%r3
367 #else
368         /* Load RFI *return* address in case smp_callin bails */
369         load32          smp_callin_rtn,%r2
370 #endif
371         
372         /* Load RFI target address.  */
373         load32          smp_callin,%r11
374         
375         /* ok...common code can handle the rest */
376         b               common_stext
377         nop
378
379         .procend
380 #endif /* CONFIG_SMP */
381 #ifndef __LP64__
382         .data
383
384         .align  4
385         .export $global$,data
386
387         .type   $global$,@object
388         .size   $global$,4
389 $global$:       
390         .word 0
391 #endif /*!LP64*/