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