Initial commit
[wrt350n-kernel.git] / arch / parisc / kernel / head.S
bloba7b8859488bb9ca7014746151a8d1f2a766a71be
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-2007 by Helge Deller <deller@gmx.de>
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  */
15 #include <asm/asm-offsets.h>
16 #include <asm/psw.h>
17 #include <asm/pdc.h>
18         
19 #include <asm/assembly.h>
20 #include <asm/pgtable.h>
22 #include <linux/linkage.h>
24         .level  LEVEL
26         .data
27 ENTRY(boot_args)
28         .word 0 /* arg0 */
29         .word 0 /* arg1 */
30         .word 0 /* arg2 */
31         .word 0 /* arg3 */
32 END(boot_args)
34         .text
35         .align  4
36         .import init_thread_union,data
37         .import fault_vector_20,code    /* IVA parisc 2.0 32 bit */
38 #ifndef CONFIG_64BIT
39         .import fault_vector_11,code    /* IVA parisc 1.1 32 bit */
40         .import $global$                /* forward declaration */
41 #endif /*!CONFIG_64BIT*/
42         .export _stext,data             /* Kernel want it this way! */
43 _stext:
44 ENTRY(stext)
45         .proc
46         .callinfo
48         /* Make sure sr4-sr7 are set to zero for the kernel address space */
49         mtsp    %r0,%sr4
50         mtsp    %r0,%sr5
51         mtsp    %r0,%sr6
52         mtsp    %r0,%sr7
54         /* Clear BSS (shouldn't the boot loader do this?) */
56         .import __bss_start,data
57         .import __bss_stop,data
59         load32          PA(__bss_start),%r3
60         load32          PA(__bss_stop),%r4
61 $bss_loop:
62         cmpb,<<,n       %r3,%r4,$bss_loop
63         stw,ma          %r0,4(%r3)
65         /* Save away the arguments the boot loader passed in (32 bit args) */
66         load32          PA(boot_args),%r1
67         stw,ma          %arg0,4(%r1)
68         stw,ma          %arg1,4(%r1)
69         stw,ma          %arg2,4(%r1)
70         stw,ma          %arg3,4(%r1)
72         /* Initialize startup VM. Just map first 8/16 MB of memory */
73         load32          PA(swapper_pg_dir),%r4
74         mtctl           %r4,%cr24       /* Initialize kernel root pointer */
75         mtctl           %r4,%cr25       /* Initialize user root pointer */
77 #if PT_NLEVELS == 3
78         /* Set pmd in pgd */
79         load32          PA(pmd0),%r5
80         shrd            %r5,PxD_VALUE_SHIFT,%r3 
81         ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
82         stw             %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
83         ldo             ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
84 #else
85         /* 2-level page table, so pmd == pgd */
86         ldo             ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
87 #endif
89         /* Fill in pmd with enough pte directories */
90         load32          PA(pg0),%r1
91         SHRREG          %r1,PxD_VALUE_SHIFT,%r3
92         ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
94         ldi             ASM_PT_INITIAL,%r1
97         stw             %r3,0(%r4)
98         ldo             (PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
99         addib,>         -1,%r1,1b
100 #if PT_NLEVELS == 3
101         ldo             ASM_PMD_ENTRY_SIZE(%r4),%r4
102 #else
103         ldo             ASM_PGD_ENTRY_SIZE(%r4),%r4
104 #endif
107         /* Now initialize the PTEs themselves */
108         ldo             0+_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
109         ldi             (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */
110         load32          PA(pg0),%r1
112 $pgt_fill_loop:
113         STREGM          %r3,ASM_PTE_ENTRY_SIZE(%r1)
114         ldo             (1<<PFN_PTE_SHIFT)(%r3),%r3 /* add one PFN */
115         addib,>         -1,%r11,$pgt_fill_loop
116         nop
118         /* Load the return address...er...crash 'n burn */
119         copy            %r0,%r2
121         /* And the RFI Target address too */
122         load32          start_kernel,%r11
124         /* And the initial task pointer */
125         load32          init_thread_union,%r6
126         mtctl           %r6,%cr30
128         /* And the stack pointer too */
129         ldo             THREAD_SZ_ALGN(%r6),%sp
131 #ifdef CONFIG_SMP
132         /* Set the smp rendevous address into page zero.
133         ** It would be safer to do this in init_smp_config() but
134         ** it's just way easier to deal with here because
135         ** of 64-bit function ptrs and the address is local to this file.
136         */
137         load32          PA(smp_slave_stext),%r10
138         stw             %r10,0x10(%r0)  /* MEM_RENDEZ */
139         stw             %r0,0x28(%r0)   /* MEM_RENDEZ_HI - assume addr < 4GB */
141         /* FALLTHROUGH */
142         .procend
144         /*
145         ** Code Common to both Monarch and Slave processors.
146         ** Entry:
147         **
148         **  1.1:        
149         **    %r11 must contain RFI target address.
150         **    %r25/%r26 args to pass to target function
151         **    %r2  in case rfi target decides it didn't like something
152         **
153         **  2.0w:
154         **    %r3  PDCE_PROC address
155         **    %r11 RFI target address
156         **
157         ** Caller must init: SR4-7, %sp, %r10, %cr24/25, 
158         */
159 common_stext:
160         .proc
161         .callinfo
162 #else
163         /* Clear PDC entry point - we won't use it */
164         stw             %r0,0x10(%r0)   /* MEM_RENDEZ */
165         stw             %r0,0x28(%r0)   /* MEM_RENDEZ_HI */
166 #endif /*CONFIG_SMP*/
168 #ifdef CONFIG_64BIT
169         tophys_r1       %sp
171         /* Save the rfi target address */
172         ldd             TI_TASK-THREAD_SZ_ALGN(%sp), %r10
173         tophys_r1       %r10
174         std             %r11,  TASK_PT_GR11(%r10)
175         /* Switch to wide mode Superdome doesn't support narrow PDC
176         ** calls.
177         */
178 1:      mfia            %rp             /* clear upper part of pcoq */
179         ldo             2f-1b(%rp),%rp
180         depdi           0,31,32,%rp
181         bv              (%rp)
182         ssm             PSW_SM_W,%r0
184         /* Set Wide mode as the "Default" (eg for traps)
185         ** First trap occurs *right* after (or part of) rfi for slave CPUs.
186         ** Someday, palo might not do this for the Monarch either.
187         */
189 #define MEM_PDC_LO 0x388
190 #define MEM_PDC_HI 0x35C
191         ldw             MEM_PDC_LO(%r0),%r3
192         ldw             MEM_PDC_HI(%r0),%r6
193         depd            %r6, 31, 32, %r3        /* move to upper word */
195         ldo             PDC_PSW(%r0),%arg0              /* 21 */
196         ldo             PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */
197         ldo             PDC_PSW_WIDE_BIT(%r0),%arg2     /* 2 */
198         load32          PA(stext_pdc_ret), %rp
199         bv              (%r3)
200         copy            %r0,%arg3
202 stext_pdc_ret:
203         /* restore rfi target address*/
204         ldd             TI_TASK-THREAD_SZ_ALGN(%sp), %r10
205         tophys_r1       %r10
206         ldd             TASK_PT_GR11(%r10), %r11
207         tovirt_r1       %sp
208 #endif
209         
210         /* PARANOID: clear user scratch/user space SR's */
211         mtsp    %r0,%sr0
212         mtsp    %r0,%sr1
213         mtsp    %r0,%sr2
214         mtsp    %r0,%sr3
216         /* Initialize Protection Registers */
217         mtctl   %r0,%cr8
218         mtctl   %r0,%cr9
219         mtctl   %r0,%cr12
220         mtctl   %r0,%cr13
222         /* Initialize the global data pointer */
223         loadgp
225         /* Set up our interrupt table.  HPMCs might not work after this! 
226          *
227          * We need to install the correct iva for PA1.1 or PA2.0. The
228          * following short sequence of instructions can determine this
229          * (without being illegal on a PA1.1 machine).
230          */
231 #ifndef CONFIG_64BIT
232         ldi             32,%r10
233         mtctl           %r10,%cr11
234         .level 2.0
235         mfctl,w         %cr11,%r10
236         .level 1.1
237         comib,<>,n      0,%r10,$is_pa20
238         ldil            L%PA(fault_vector_11),%r10
239         b               $install_iva
240         ldo             R%PA(fault_vector_11)(%r10),%r10
242 $is_pa20:
243         .level          LEVEL /* restore 1.1 || 2.0w */
244 #endif /*!CONFIG_64BIT*/
245         load32          PA(fault_vector_20),%r10
247 $install_iva:
248         mtctl           %r10,%cr14
250         b               aligned_rfi  /* Prepare to RFI! Man all the cannons! */
251         nop
253         .align 128
254 aligned_rfi:
255         pcxt_ssm_bug
257         rsm             PSW_SM_QUIET,%r0        /* off troublesome PSW bits */
258         /* Don't need NOPs, have 8 compliant insn before rfi */
260         mtctl           %r0,%cr17       /* Clear IIASQ tail */
261         mtctl           %r0,%cr17       /* Clear IIASQ head */
263         /* Load RFI target into PC queue */
264         mtctl           %r11,%cr18      /* IIAOQ head */
265         ldo             4(%r11),%r11
266         mtctl           %r11,%cr18      /* IIAOQ tail */
268         load32          KERNEL_PSW,%r10
269         mtctl           %r10,%ipsw
270         
271         /* Jump through hyperspace to Virt Mode */
272         rfi
273         nop
275         .procend
277 #ifdef CONFIG_SMP
279         .import smp_init_current_idle_task,data
280         .import smp_callin,code
282 #ifndef CONFIG_64BIT
283 smp_callin_rtn:
284         .proc
285         .callinfo
286         break   1,1             /*  Break if returned from start_secondary */
287         nop
288         nop
289         .procend
290 #endif /*!CONFIG_64BIT*/
292 /***************************************************************************
293 * smp_slave_stext is executed by all non-monarch Processors when the Monarch
294 * pokes the slave CPUs in smp.c:smp_boot_cpus().
296 * Once here, registers values are initialized in order to branch to virtual
297 * mode. Once all available/eligible CPUs are in virtual mode, all are
298 * released and start out by executing their own idle task.
299 *****************************************************************************/
300 smp_slave_stext:
301         .proc
302         .callinfo
304         /*
305         ** Initialize Space registers
306         */
307         mtsp       %r0,%sr4
308         mtsp       %r0,%sr5
309         mtsp       %r0,%sr6
310         mtsp       %r0,%sr7
312         /*  Initialize the SP - monarch sets up smp_init_current_idle_task */
313         load32          PA(smp_init_current_idle_task),%sp
314         LDREG           0(%sp),%sp      /* load task address */
315         tophys_r1       %sp
316         LDREG           TASK_THREAD_INFO(%sp),%sp
317         mtctl           %sp,%cr30       /* store in cr30 */
318         ldo             THREAD_SZ_ALGN(%sp),%sp
320         /* point CPU to kernel page tables */
321         load32          PA(swapper_pg_dir),%r4
322         mtctl           %r4,%cr24       /* Initialize kernel root pointer */
323         mtctl           %r4,%cr25       /* Initialize user root pointer */
325 #ifdef CONFIG_64BIT
326         /* Setup PDCE_PROC entry */
327         copy            %arg0,%r3
328 #else
329         /* Load RFI *return* address in case smp_callin bails */
330         load32          smp_callin_rtn,%r2
331 #endif
332         
333         /* Load RFI target address.  */
334         load32          smp_callin,%r11
335         
336         /* ok...common code can handle the rest */
337         b               common_stext
338         nop
340         .procend
341 #endif /* CONFIG_SMP */
343 ENDPROC(stext)
345 #ifndef CONFIG_64BIT
346         .data
348         .align  4
349         .export $global$,data
351         .type   $global$,@object
352         .size   $global$,4
353 $global$:       
354         .word 0
355 #endif /*!CONFIG_64BIT*/