Merge tag 'platform-drivers-x86-v5.2-1' of git://git.infradead.org/linux-platform...
[linux-2.6-block.git] / arch / parisc / kernel / entry.S
CommitLineData
1da177e4
LT
1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * kernel entry points (interruptions, system call wrappers)
5 * Copyright (C) 1999,2000 Philipp Rumpf
6 * Copyright (C) 1999 SuSE GmbH Nuernberg
7 * Copyright (C) 2000 Hewlett-Packard (John Marvin)
8 * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
0013a854 25#include <asm/asm-offsets.h>
1da177e4
LT
26
27/* we have the following possibilities to act on an interruption:
28 * - handle in assembly and use shadowed registers only
29 * - save registers to kernel stack and handle in assembly or C */
30
31
896a3756 32#include <asm/psw.h>
3d73cf5e 33#include <asm/cache.h> /* for L1_CACHE_SHIFT */
1da177e4
LT
34#include <asm/assembly.h> /* for LDREG/STREG defines */
35#include <asm/pgtable.h>
1da177e4
LT
36#include <asm/signal.h>
37#include <asm/unistd.h>
88776c0e 38#include <asm/ldcw.h>
5b00ca0b 39#include <asm/traps.h>
1da177e4 40#include <asm/thread_info.h>
3847dab7 41#include <asm/alternative.h>
1da177e4 42
c5e76552
HD
43#include <linux/linkage.h>
44
413059f2 45#ifdef CONFIG_64BIT
1da177e4
LT
46 .level 2.0w
47#else
1da177e4
LT
48 .level 2.0
49#endif
50
01ab6057 51 .import pa_tlb_lock,data
88776c0e 52 .macro load_pa_tlb_lock reg
b37d1c18
MP
53 mfctl %cr25,\reg
54 addil L%(PAGE_SIZE << (PGD_ALLOC_ORDER - 1)),\reg
88776c0e 55 .endm
1da177e4
LT
56
57 /* space_to_prot macro creates a prot id from a space id */
58
59#if (SPACEID_SHIFT) == 0
60 .macro space_to_prot spc prot
61 depd,z \spc,62,31,\prot
62 .endm
63#else
64 .macro space_to_prot spc prot
65 extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot
66 .endm
67#endif
68
69 /* Switch to virtual mapping, trashing only %r1 */
70 .macro virt_map
896a3756
GG
71 /* pcxt_ssm_bug */
72 rsm PSW_SM_I, %r0 /* barrier for "Relied upon Translation */
1da177e4
LT
73 mtsp %r0, %sr4
74 mtsp %r0, %sr5
b63a2bbc 75 mtsp %r0, %sr6
896a3756
GG
76 tovirt_r1 %r29
77 load32 KERNEL_PSW, %r1
78
79 rsm PSW_SM_QUIET,%r0 /* second "heavy weight" ctl op */
1da177e4
LT
80 mtctl %r0, %cr17 /* Clear IIASQ tail */
81 mtctl %r0, %cr17 /* Clear IIASQ head */
896a3756 82 mtctl %r1, %ipsw
1da177e4
LT
83 load32 4f, %r1
84 mtctl %r1, %cr18 /* Set IIAOQ tail */
85 ldo 4(%r1), %r1
86 mtctl %r1, %cr18 /* Set IIAOQ head */
87 rfir
88 nop
894:
90 .endm
91
92 /*
93 * The "get_stack" macros are responsible for determining the
94 * kernel stack value.
95 *
1da177e4
LT
96 * If sr7 == 0
97 * Already using a kernel stack, so call the
98 * get_stack_use_r30 macro to push a pt_regs structure
99 * on the stack, and store registers there.
100 * else
101 * Need to set up a kernel stack, so call the
102 * get_stack_use_cr30 macro to set up a pointer
103 * to the pt_regs structure contained within the
104 * task pointer pointed to by cr30. Set the stack
105 * pointer to point to the end of the task structure.
106 *
1da177e4
LT
107 * Note that we use shadowed registers for temps until
108 * we can save %r26 and %r29. %r26 is used to preserve
109 * %r8 (a shadowed register) which temporarily contained
110 * either the fault type ("code") or the eirr. We need
111 * to use a non-shadowed register to carry the value over
112 * the rfir in virt_map. We use %r26 since this value winds
113 * up being passed as the argument to either do_cpu_irq_mask
114 * or handle_interruption. %r29 is used to hold a pointer
115 * the register save area, and once again, it needs to
116 * be a non-shadowed register so that it survives the rfir.
117 *
118 * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame.
119 */
120
121 .macro get_stack_use_cr30
122
123 /* we save the registers in the task struct */
124
b63a2bbc 125 copy %r30, %r17
1da177e4 126 mfctl %cr30, %r1
b63a2bbc
JDA
127 ldo THREAD_SZ_ALGN(%r1), %r30
128 mtsp %r0,%sr7
129 mtsp %r16,%sr3
1da177e4
LT
130 tophys %r1,%r9
131 LDREG TI_TASK(%r9), %r1 /* thread_info -> task_struct */
132 tophys %r1,%r9
133 ldo TASK_REGS(%r9),%r9
b63a2bbc 134 STREG %r17,PT_GR30(%r9)
1da177e4
LT
135 STREG %r29,PT_GR29(%r9)
136 STREG %r26,PT_GR26(%r9)
b63a2bbc 137 STREG %r16,PT_SR7(%r9)
1da177e4 138 copy %r9,%r29
1da177e4
LT
139 .endm
140
141 .macro get_stack_use_r30
142
143 /* we put a struct pt_regs on the stack and save the registers there */
144
145 tophys %r30,%r9
b63a2bbc 146 copy %r30,%r1
1da177e4 147 ldo PT_SZ_ALGN(%r30),%r30
b63a2bbc 148 STREG %r1,PT_GR30(%r9)
1da177e4
LT
149 STREG %r29,PT_GR29(%r9)
150 STREG %r26,PT_GR26(%r9)
b63a2bbc 151 STREG %r16,PT_SR7(%r9)
1da177e4
LT
152 copy %r9,%r29
153 .endm
154
155 .macro rest_stack
156 LDREG PT_GR1(%r29), %r1
157 LDREG PT_GR30(%r29),%r30
158 LDREG PT_GR29(%r29),%r29
159 .endm
160
161 /* default interruption handler
162 * (calls traps.c:handle_interruption) */
163 .macro def code
164 b intr_save
165 ldi \code, %r8
166 .align 32
167 .endm
168
169 /* Interrupt interruption handler
170 * (calls irq.c:do_cpu_irq_mask) */
171 .macro extint code
172 b intr_extint
173 mfsp %sr7,%r16
174 .align 32
175 .endm
176
177 .import os_hpmc, code
178
179 /* HPMC handler */
180 .macro hpmc code
181 nop /* must be a NOP, will be patched later */
182 load32 PA(os_hpmc), %r3
183 bv,n 0(%r3)
184 nop
185 .word 0 /* checksum (will be patched) */
1138b671 186 .word 0 /* address of handler */
1da177e4
LT
187 .word 0 /* length of handler */
188 .endm
189
190 /*
191 * Performance Note: Instructions will be moved up into
192 * this part of the code later on, once we are sure
193 * that the tlb miss handlers are close to final form.
194 */
195
196 /* Register definitions for tlb miss handler macros */
197
25985edc
LDM
198 va = r8 /* virtual address for which the trap occurred */
199 spc = r24 /* space for which the trap occurred */
1da177e4 200
413059f2 201#ifndef CONFIG_64BIT
1da177e4
LT
202
203 /*
204 * itlb miss interruption handler (parisc 1.1 - 32 bit)
205 */
206
207 .macro itlb_11 code
208
209 mfctl %pcsq, spc
210 b itlb_miss_11
211 mfctl %pcoq, va
212
213 .align 32
214 .endm
215#endif
216
217 /*
218 * itlb miss interruption handler (parisc 2.0)
219 */
220
221 .macro itlb_20 code
222 mfctl %pcsq, spc
413059f2 223#ifdef CONFIG_64BIT
1da177e4
LT
224 b itlb_miss_20w
225#else
226 b itlb_miss_20
227#endif
228 mfctl %pcoq, va
229
230 .align 32
231 .endm
232
413059f2 233#ifndef CONFIG_64BIT
1da177e4
LT
234 /*
235 * naitlb miss interruption handler (parisc 1.1 - 32 bit)
1da177e4
LT
236 */
237
238 .macro naitlb_11 code
239
240 mfctl %isr,spc
f311847c 241 b naitlb_miss_11
1da177e4 242 mfctl %ior,va
1da177e4
LT
243
244 .align 32
245 .endm
246#endif
247
248 /*
249 * naitlb miss interruption handler (parisc 2.0)
1da177e4
LT
250 */
251
252 .macro naitlb_20 code
253
254 mfctl %isr,spc
413059f2 255#ifdef CONFIG_64BIT
f311847c 256 b naitlb_miss_20w
1da177e4 257#else
f311847c 258 b naitlb_miss_20
1da177e4
LT
259#endif
260 mfctl %ior,va
1da177e4
LT
261
262 .align 32
263 .endm
264
413059f2 265#ifndef CONFIG_64BIT
1da177e4
LT
266 /*
267 * dtlb miss interruption handler (parisc 1.1 - 32 bit)
268 */
269
270 .macro dtlb_11 code
271
272 mfctl %isr, spc
273 b dtlb_miss_11
274 mfctl %ior, va
275
276 .align 32
277 .endm
278#endif
279
280 /*
281 * dtlb miss interruption handler (parisc 2.0)
282 */
283
284 .macro dtlb_20 code
285
286 mfctl %isr, spc
413059f2 287#ifdef CONFIG_64BIT
1da177e4
LT
288 b dtlb_miss_20w
289#else
290 b dtlb_miss_20
291#endif
292 mfctl %ior, va
293
294 .align 32
295 .endm
296
413059f2 297#ifndef CONFIG_64BIT
1da177e4
LT
298 /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */
299
300 .macro nadtlb_11 code
301
302 mfctl %isr,spc
303 b nadtlb_miss_11
304 mfctl %ior,va
305
306 .align 32
307 .endm
308#endif
309
310 /* nadtlb miss interruption handler (parisc 2.0) */
311
312 .macro nadtlb_20 code
313
314 mfctl %isr,spc
413059f2 315#ifdef CONFIG_64BIT
1da177e4
LT
316 b nadtlb_miss_20w
317#else
318 b nadtlb_miss_20
319#endif
320 mfctl %ior,va
321
322 .align 32
323 .endm
324
413059f2 325#ifndef CONFIG_64BIT
1da177e4
LT
326 /*
327 * dirty bit trap interruption handler (parisc 1.1 - 32 bit)
328 */
329
330 .macro dbit_11 code
331
332 mfctl %isr,spc
333 b dbit_trap_11
334 mfctl %ior,va
335
336 .align 32
337 .endm
338#endif
339
340 /*
341 * dirty bit trap interruption handler (parisc 2.0)
342 */
343
344 .macro dbit_20 code
345
346 mfctl %isr,spc
413059f2 347#ifdef CONFIG_64BIT
1da177e4
LT
348 b dbit_trap_20w
349#else
350 b dbit_trap_20
351#endif
352 mfctl %ior,va
353
354 .align 32
355 .endm
356
1da177e4
LT
357 /* In LP64, the space contains part of the upper 32 bits of the
358 * fault. We have to extract this and place it in the va,
359 * zeroing the corresponding bits in the space register */
360 .macro space_adjust spc,va,tmp
413059f2 361#ifdef CONFIG_64BIT
1da177e4
LT
362 extrd,u \spc,63,SPACEID_SHIFT,\tmp
363 depd %r0,63,SPACEID_SHIFT,\spc
364 depd \tmp,31,SPACEID_SHIFT,\va
365#endif
366 .endm
367
368 .import swapper_pg_dir,code
369
370 /* Get the pgd. For faults on space zero (kernel space), this
371 * is simply swapper_pg_dir. For user space faults, the
372 * pgd is stored in %cr25 */
373 .macro get_pgd spc,reg
374 ldil L%PA(swapper_pg_dir),\reg
375 ldo R%PA(swapper_pg_dir)(\reg),\reg
376 or,COND(=) %r0,\spc,%r0
377 mfctl %cr25,\reg
378 .endm
379
380 /*
381 space_check(spc,tmp,fault)
382
383 spc - The space we saw the fault with.
384 tmp - The place to store the current space.
385 fault - Function to call on failure.
386
387 Only allow faults on different spaces from the
388 currently active one if we're the kernel
389
390 */
391 .macro space_check spc,tmp,fault
392 mfsp %sr7,\tmp
87613bb9 393 /* check against %r0 which is same value as LINUX_GATEWAY_SPACE */
1da177e4
LT
394 or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page
395 * as kernel, so defeat the space
396 * check if it is */
397 copy \spc,\tmp
398 or,COND(=) %r0,\tmp,%r0 /* nullify if executing as kernel */
399 cmpb,COND(<>),n \tmp,\spc,\fault
400 .endm
401
402 /* Look up a PTE in a 2-Level scheme (faulting at each
403 * level if the entry isn't present
404 *
405 * NOTE: we use ldw even for LP64, since the short pointers
406 * can address up to 1TB
407 */
408 .macro L2_ptep pmd,pte,index,va,fault
f24ffde4 409#if CONFIG_PGTABLE_LEVELS == 3
9b437bca 410 extru \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
1da177e4 411#else
6a45716a
HD
412# if defined(CONFIG_64BIT)
413 extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
414 #else
415 # if PAGE_SIZE > 4096
416 extru \va,31-ASM_PGDIR_SHIFT,32-ASM_PGDIR_SHIFT,\index
417 # else
9b437bca 418 extru \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
6a45716a
HD
419 # endif
420# endif
1da177e4 421#endif
9b437bca 422 dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */
1da177e4
LT
423 copy %r0,\pte
424 ldw,s \index(\pmd),\pmd
425 bb,>=,n \pmd,_PxD_PRESENT_BIT,\fault
9b437bca 426 dep %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
32c1ceea 427 SHLREG \pmd,PxD_VALUE_SHIFT,\pmd
9b437bca
JDA
428 extru \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
429 dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */
01ab6057 430 shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd /* pmd is now pte */
1da177e4
LT
431 .endm
432
433 /* Look up PTE in a 3-Level scheme.
434 *
435 * Here we implement a Hybrid L2/L3 scheme: we allocate the
436 * first pmd adjacent to the pgd. This means that we can
437 * subtract a constant offset to get to it. The pmd and pgd
438 * sizes are arranged so that a single pmd covers 4GB (giving
439 * a full LP64 process access to 8TB) so our lookups are
440 * effectively L2 for the first 4GB of the kernel (i.e. for
441 * all ILP32 processes and all the kernel for machines with
442 * under 4GB of memory) */
443 .macro L3_ptep pgd,pte,index,va,fault
f24ffde4 444#if CONFIG_PGTABLE_LEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
1da177e4 445 extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
2fd83038 446 extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
1da177e4 447 ldw,s \index(\pgd),\pgd
2fd83038 448 extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
1da177e4 449 bb,>=,n \pgd,_PxD_PRESENT_BIT,\fault
2fd83038 450 extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
1da177e4 451 shld \pgd,PxD_VALUE_SHIFT,\index
2fd83038 452 extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
1da177e4 453 copy \index,\pgd
2fd83038 454 extrd,u,*<> \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
1da177e4 455 ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd
2fd83038 456#endif
1da177e4
LT
457 L2_ptep \pgd,\pte,\index,\va,\fault
458 .endm
459
32a7901f 460 /* Acquire pa_tlb_lock lock and check page is present. */
01ab6057 461 .macro tlb_lock spc,ptp,pte,tmp,tmp1,fault
f0a18819 462#ifdef CONFIG_SMP
3847dab7 46398: cmpib,COND(=),n 0,\spc,2f
88776c0e 464 load_pa_tlb_lock \tmp
f0a18819
JDA
4651: LDCW 0(\tmp),\tmp1
466 cmpib,COND(=) 0,\tmp1,1b
467 nop
01ab6057 468 LDREG 0(\ptp),\pte
32a7901f 469 bb,<,n \pte,_PAGE_PRESENT_BIT,3f
9e5c6021 470 LDCW 0(\tmp),\tmp1
01ab6057 471 b \fault
9e5c6021 472 stw \spc,0(\tmp)
3847dab7 47399: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
f0a18819 474#endif
32a7901f
JDA
4752: LDREG 0(\ptp),\pte
476 bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault
4773:
f0a18819
JDA
478 .endm
479
01ab6057 480 /* Release pa_tlb_lock lock without reloading lock address. */
9e5c6021 481 .macro tlb_unlock0 spc,tmp,tmp1
f0a18819 482#ifdef CONFIG_SMP
3847dab7 48398: or,COND(=) %r0,\spc,%r0
9e5c6021
JDA
484 LDCW 0(\tmp),\tmp1
485 or,COND(=) %r0,\spc,%r0
486 stw \spc,0(\tmp)
3847dab7 48799: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
f0a18819
JDA
488#endif
489 .endm
490
01ab6057 491 /* Release pa_tlb_lock lock. */
9e5c6021 492 .macro tlb_unlock1 spc,tmp,tmp1
f0a18819 493#ifdef CONFIG_SMP
3847dab7
HD
49498: load_pa_tlb_lock \tmp
49599: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
9e5c6021 496 tlb_unlock0 \spc,\tmp,\tmp1
f0a18819
JDA
497#endif
498 .endm
499
1da177e4
LT
500 /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and
501 * don't needlessly dirty the cache line if it was already set */
01ab6057 502 .macro update_accessed ptp,pte,tmp,tmp1
1da177e4
LT
503 ldi _PAGE_ACCESSED,\tmp1
504 or \tmp1,\pte,\tmp
505 and,COND(<>) \tmp1,\pte,%r0
01ab6057 506 STREG \tmp,0(\ptp)
1da177e4
LT
507 .endm
508
509 /* Set the dirty bit (and accessed bit). No need to be
510 * clever, this is only used from the dirty fault */
01ab6057 511 .macro update_dirty ptp,pte,tmp
1da177e4
LT
512 ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp
513 or \tmp,\pte,\pte
01ab6057 514 STREG \pte,0(\ptp)
1da177e4
LT
515 .endm
516
736d2169
HD
517 /* We have (depending on the page size):
518 * - 38 to 52-bit Physical Page Number
519 * - 12 to 26-bit page offset
520 */
afca2523
HD
521 /* bitshift difference between a PFN (based on kernel's PAGE_SIZE)
522 * to a CPU TLB 4k PFN (4k => 12 bits to shift) */
736d2169
HD
523 #define PAGE_ADD_SHIFT (PAGE_SHIFT-12)
524 #define PAGE_ADD_HUGE_SHIFT (REAL_HPAGE_SHIFT-12)
afca2523
HD
525
526 /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
736d2169
HD
527 .macro convert_for_tlb_insert20 pte,tmp
528#ifdef CONFIG_HUGETLB_PAGE
529 copy \pte,\tmp
530 extrd,u \tmp,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
531 64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
532
533 depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\
534 (63-58)+PAGE_ADD_SHIFT,\pte
535 extrd,u,*= \tmp,_PAGE_HPAGE_BIT+32,1,%r0
536 depdi _HUGE_PAGE_SIZE_ENCODING_DEFAULT,63,\
537 (63-58)+PAGE_ADD_HUGE_SHIFT,\pte
538#else /* Huge pages disabled */
afca2523
HD
539 extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
540 64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
541 depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\
542 (63-58)+PAGE_ADD_SHIFT,\pte
736d2169 543#endif
afca2523
HD
544 .endm
545
1da177e4
LT
546 /* Convert the pte and prot to tlb insertion values. How
547 * this happens is quite subtle, read below */
736d2169 548 .macro make_insert_tlb spc,pte,prot,tmp
1da177e4
LT
549 space_to_prot \spc \prot /* create prot id from space */
550 /* The following is the real subtlety. This is depositing
551 * T <-> _PAGE_REFTRAP
552 * D <-> _PAGE_DIRTY
553 * B <-> _PAGE_DMB (memory break)
554 *
555 * Then incredible subtlety: The access rights are
1c4c6597 556 * _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE
1da177e4
LT
557 * See 3-14 of the parisc 2.0 manual
558 *
559 * Finally, _PAGE_READ goes in the top bit of PL1 (so we
560 * trigger an access rights trap in user space if the user
561 * tries to read an unreadable page */
562 depd \pte,8,7,\prot
563
564 /* PAGE_USER indicates the page can be read with user privileges,
565 * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1
1c4c6597 566 * contains _PAGE_READ) */
1da177e4
LT
567 extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0
568 depdi 7,11,3,\prot
569 /* If we're a gateway page, drop PL2 back to zero for promotion
570 * to kernel privilege (so we can execute the page as kernel).
571 * Any privilege promotion page always denys read and write */
572 extrd,u,*= \pte,_PAGE_GATEWAY_BIT+32,1,%r0
573 depd %r0,11,2,\prot /* If Gateway, Set PL2 to 0 */
574
2fd83038
HD
575 /* Enforce uncacheable pages.
576 * This should ONLY be use for MMIO on PA 2.0 machines.
577 * Memory/DMA is cache coherent on all PA2.0 machines we support
578 * (that means T-class is NOT supported) and the memory controllers
579 * on most of those machines only handles cache transactions.
580 */
581 extrd,u,*= \pte,_PAGE_NO_CACHE_BIT+32,1,%r0
2678251b 582 depdi 1,12,1,\prot
1da177e4 583
2fd83038 584 /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
736d2169 585 convert_for_tlb_insert20 \pte \tmp
1da177e4
LT
586 .endm
587
588 /* Identical macro to make_insert_tlb above, except it
589 * makes the tlb entry for the differently formatted pa11
590 * insertion instructions */
591 .macro make_insert_tlb_11 spc,pte,prot
592 zdep \spc,30,15,\prot
593 dep \pte,8,7,\prot
594 extru,= \pte,_PAGE_NO_CACHE_BIT,1,%r0
595 depi 1,12,1,\prot
596 extru,= \pte,_PAGE_USER_BIT,1,%r0
597 depi 7,11,3,\prot /* Set for user space (1 rsvd for read) */
598 extru,= \pte,_PAGE_GATEWAY_BIT,1,%r0
599 depi 0,11,2,\prot /* If Gateway, Set PL2 to 0 */
600
601 /* Get rid of prot bits and convert to page addr for iitlba */
602
1152a68c
HD
603 depi 0,31,ASM_PFN_PTE_SHIFT,\pte
604 SHRREG \pte,(ASM_PFN_PTE_SHIFT-(31-26)),\pte
1da177e4
LT
605 .endm
606
607 /* This is for ILP32 PA2.0 only. The TLB insertion needs
608 * to extend into I/O space if the address is 0xfXXXXXXX
609 * so we extend the f's into the top word of the pte in
610 * this case */
611 .macro f_extend pte,tmp
612 extrd,s \pte,42,4,\tmp
613 addi,<> 1,\tmp,%r0
614 extrd,s \pte,63,25,\pte
615 .endm
616
617 /* The alias region is an 8MB aligned 16MB to do clear and
618 * copy user pages at addresses congruent with the user
619 * virtual address.
620 *
621 * To use the alias page, you set %r26 up with the to TLB
622 * entry (identifying the physical page) and %r23 up with
623 * the from tlb entry (or nothing if only a to entry---for
624 * clear_user_page_asm) */
2f649c1f 625 .macro do_alias spc,tmp,tmp1,va,pte,prot,fault,patype
1da177e4
LT
626 cmpib,COND(<>),n 0,\spc,\fault
627 ldil L%(TMPALIAS_MAP_START),\tmp
413059f2 628#if defined(CONFIG_64BIT) && (TMPALIAS_MAP_START >= 0x80000000)
1da177e4
LT
629 /* on LP64, ldi will sign extend into the upper 32 bits,
630 * which is behaviour we don't want */
631 depdi 0,31,32,\tmp
632#endif
633 copy \va,\tmp1
9b437bca 634 depi 0,31,23,\tmp1
1da177e4 635 cmpb,COND(<>),n \tmp,\tmp1,\fault
f311847c
JB
636 mfctl %cr19,\tmp /* iir */
637 /* get the opcode (first six bits) into \tmp */
638 extrw,u \tmp,5,6,\tmp
639 /*
640 * Only setting the T bit prevents data cache movein
641 * Setting access rights to zero prevents instruction cache movein
642 *
643 * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go
644 * to type field and _PAGE_READ goes to top bit of PL1
645 */
646 ldi (_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot
647 /*
648 * so if the opcode is one (i.e. this is a memory management
649 * instruction) nullify the next load so \prot is only T.
650 * Otherwise this is a normal data operation
651 */
652 cmpiclr,= 0x01,\tmp,%r0
653 ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
2f649c1f 654.ifc \patype,20
1da177e4 655 depd,z \prot,8,7,\prot
2f649c1f
JB
656.else
657.ifc \patype,11
5e185581 658 depw,z \prot,8,7,\prot
2f649c1f
JB
659.else
660 .error "undefined PA type to do_alias"
661.endif
662.endif
1da177e4
LT
663 /*
664 * OK, it is in the temp alias region, check whether "from" or "to".
665 * Check "subtle" note in pacache.S re: r23/r26.
666 */
413059f2 667#ifdef CONFIG_64BIT
1da177e4
LT
668 extrd,u,*= \va,41,1,%r0
669#else
670 extrw,u,= \va,9,1,%r0
671#endif
672 or,COND(tr) %r23,%r0,\pte
673 or %r26,%r0,\pte
674 .endm
675
676
677 /*
4182d0cd
HD
678 * Fault_vectors are architecturally required to be aligned on a 2K
679 * boundary
1da177e4
LT
680 */
681
4df3c9ec 682 .section .text.hot
4182d0cd 683 .align 2048
1da177e4 684
c5e76552 685ENTRY(fault_vector_20)
1da177e4
LT
686 /* First vector is invalid (0) */
687 .ascii "cows can fly"
688 .byte 0
689 .align 32
690
691 hpmc 1
692 def 2
693 def 3
694 extint 4
695 def 5
5b00ca0b 696 itlb_20 PARISC_ITLB_TRAP
1da177e4
LT
697 def 7
698 def 8
699 def 9
700 def 10
701 def 11
702 def 12
703 def 13
704 def 14
705 dtlb_20 15
1da177e4 706 naitlb_20 16
1da177e4
LT
707 nadtlb_20 17
708 def 18
709 def 19
710 dbit_20 20
711 def 21
712 def 22
713 def 23
714 def 24
715 def 25
716 def 26
717 def 27
718 def 28
719 def 29
720 def 30
721 def 31
c5e76552 722END(fault_vector_20)
1da177e4 723
413059f2 724#ifndef CONFIG_64BIT
1da177e4 725
1da177e4
LT
726 .align 2048
727
c5e76552 728ENTRY(fault_vector_11)
1da177e4
LT
729 /* First vector is invalid (0) */
730 .ascii "cows can fly"
731 .byte 0
732 .align 32
733
734 hpmc 1
735 def 2
736 def 3
737 extint 4
738 def 5
5b00ca0b 739 itlb_11 PARISC_ITLB_TRAP
1da177e4
LT
740 def 7
741 def 8
742 def 9
743 def 10
744 def 11
745 def 12
746 def 13
747 def 14
748 dtlb_11 15
1da177e4 749 naitlb_11 16
1da177e4
LT
750 nadtlb_11 17
751 def 18
752 def 19
753 dbit_11 20
754 def 21
755 def 22
756 def 23
757 def 24
758 def 25
759 def 26
760 def 27
761 def 28
762 def 29
763 def 30
764 def 31
c5e76552 765END(fault_vector_11)
1da177e4
LT
766
767#endif
d7dd2ff1
JB
768 /* Fault vector is separately protected and *must* be on its own page */
769 .align PAGE_SIZE
1da177e4
LT
770
771 .import handle_interruption,code
772 .import do_cpu_irq_mask,code
773
1da177e4
LT
774 /*
775 * Child Returns here
776 *
a44e060f 777 * copy_thread moved args into task save area.
1da177e4
LT
778 */
779
8801ccb9 780ENTRY(ret_from_kernel_thread)
1da177e4
LT
781 /* Call schedule_tail first though */
782 BL schedule_tail, %r2
783 nop
784
ff0ab8af 785 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1da177e4 786 LDREG TASK_PT_GR25(%r1), %r26
413059f2 787#ifdef CONFIG_64BIT
1da177e4 788 LDREG TASK_PT_GR27(%r1), %r27
1da177e4
LT
789#endif
790 LDREG TASK_PT_GR26(%r1), %r1
791 ble 0(%sr7, %r1)
792 copy %r31, %r2
363806dd
AV
793 b finish_child_return
794 nop
8801ccb9 795END(ret_from_kernel_thread)
1da177e4 796
1da177e4
LT
797
798 /*
799 * struct task_struct *_switch_to(struct task_struct *prev,
800 * struct task_struct *next)
801 *
802 * switch kernel stacks and return prev */
f39cce65 803ENTRY_CFI(_switch_to)
1da177e4
LT
804 STREG %r2, -RP_OFFSET(%r30)
805
618febd6 806 callee_save_float
1da177e4
LT
807 callee_save
808
809 load32 _switch_to_ret, %r2
810
811 STREG %r2, TASK_PT_KPC(%r26)
812 LDREG TASK_PT_KPC(%r25), %r2
813
814 STREG %r30, TASK_PT_KSP(%r26)
815 LDREG TASK_PT_KSP(%r25), %r30
816 LDREG TASK_THREAD_INFO(%r25), %r25
817 bv %r0(%r2)
818 mtctl %r25,%cr30
819
8801ccb9 820ENTRY(_switch_to_ret)
1da177e4
LT
821 mtctl %r0, %cr0 /* Needed for single stepping */
822 callee_rest
618febd6 823 callee_rest_float
1da177e4
LT
824
825 LDREG -RP_OFFSET(%r30), %r2
826 bv %r0(%r2)
827 copy %r26, %r28
8801ccb9 828ENDPROC_CFI(_switch_to)
1da177e4
LT
829
830 /*
831 * Common rfi return path for interruptions, kernel execve, and
832 * sys_rt_sigreturn (sometimes). The sys_rt_sigreturn syscall will
833 * return via this path if the signal was received when the process
834 * was running; if the process was blocked on a syscall then the
835 * normal syscall_exit path is used. All syscalls for traced
836 * proceses exit via intr_restore.
837 *
838 * XXX If any syscalls that change a processes space id ever exit
839 * this way, then we will need to copy %sr3 in to PT_SR[3..7], and
840 * adjust IASQ[0..1].
841 *
1da177e4
LT
842 */
843
873d50e2 844 .align PAGE_SIZE
1da177e4 845
f39cce65 846ENTRY_CFI(syscall_exit_rfi)
1da177e4
LT
847 mfctl %cr30,%r16
848 LDREG TI_TASK(%r16), %r16 /* thread_info -> task_struct */
849 ldo TASK_REGS(%r16),%r16
850 /* Force iaoq to userspace, as the user has had access to our current
851 * context via sigcontext. Also Filter the PSW for the same reason.
852 */
853 LDREG PT_IAOQ0(%r16),%r19
854 depi 3,31,2,%r19
855 STREG %r19,PT_IAOQ0(%r16)
856 LDREG PT_IAOQ1(%r16),%r19
857 depi 3,31,2,%r19
858 STREG %r19,PT_IAOQ1(%r16)
859 LDREG PT_PSW(%r16),%r19
860 load32 USER_PSW_MASK,%r1
413059f2 861#ifdef CONFIG_64BIT
1da177e4
LT
862 load32 USER_PSW_HI_MASK,%r20
863 depd %r20,31,32,%r1
864#endif
865 and %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
866 load32 USER_PSW,%r1
867 or %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
868 STREG %r19,PT_PSW(%r16)
869
870 /*
871 * If we aren't being traced, we never saved space registers
872 * (we don't store them in the sigcontext), so set them
873 * to "proper" values now (otherwise we'll wind up restoring
874 * whatever was last stored in the task structure, which might
25985edc 875 * be inconsistent if an interrupt occurred while on the gateway
4b3f686d
ML
876 * page). Note that we may be "trashing" values the user put in
877 * them, but we don't support the user changing them.
1da177e4
LT
878 */
879
880 STREG %r0,PT_SR2(%r16)
881 mfsp %sr3,%r19
882 STREG %r19,PT_SR0(%r16)
883 STREG %r19,PT_SR1(%r16)
884 STREG %r19,PT_SR3(%r16)
885 STREG %r19,PT_SR4(%r16)
886 STREG %r19,PT_SR5(%r16)
887 STREG %r19,PT_SR6(%r16)
888 STREG %r19,PT_SR7(%r16)
889
8801ccb9 890ENTRY(intr_return)
1da177e4
LT
891 /* check for reschedule */
892 mfctl %cr30,%r1
893 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
894 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
895
4650f0a5 896 .import do_notify_resume,code
1da177e4
LT
897intr_check_sig:
898 /* As above */
899 mfctl %cr30,%r1
4650f0a5 900 LDREG TI_FLAGS(%r1),%r19
6fd84c08 901 ldi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r20
4650f0a5
KM
902 and,COND(<>) %r19, %r20, %r0
903 b,n intr_restore /* skip past if we've nothing to do */
904
905 /* This check is critical to having LWS
906 * working. The IASQ is zero on the gateway
907 * page and we cannot deliver any signals until
908 * we get off the gateway page.
909 *
910 * Only do signals if we are returning to user space
911 */
912 LDREG PT_IASQ0(%r16), %r20
87613bb9 913 cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */
4650f0a5 914 LDREG PT_IASQ1(%r16), %r20
87613bb9 915 cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */
4650f0a5 916
9352aead
JDA
917 /* NOTE: We need to enable interrupts if we have to deliver
918 * signals. We used to do this earlier but it caused kernel
919 * stack overflows. */
920 ssm PSW_SM_I, %r0
921
4650f0a5
KM
922 copy %r0, %r25 /* long in_syscall = 0 */
923#ifdef CONFIG_64BIT
924 ldo -16(%r30),%r29 /* Reference param save area */
925#endif
926
927 BL do_notify_resume,%r2
928 copy %r16, %r26 /* struct pt_regs *regs */
929
3fe4c55e 930 b,n intr_check_sig
1da177e4
LT
931
932intr_restore:
933 copy %r16,%r29
934 ldo PT_FR31(%r29),%r1
935 rest_fp %r1
936 rest_general %r29
937
896a3756
GG
938 /* inverse of virt_map */
939 pcxt_ssm_bug
940 rsm PSW_SM_QUIET,%r0 /* prepare for rfi */
1da177e4 941 tophys_r1 %r29
1da177e4
LT
942
943 /* Restore space id's and special cr's from PT_REGS
896a3756
GG
944 * structure pointed to by r29
945 */
1da177e4
LT
946 rest_specials %r29
947
896a3756
GG
948 /* IMPORTANT: rest_stack restores r29 last (we are using it)!
949 * It also restores r1 and r30.
950 */
1da177e4
LT
951 rest_stack
952
953 rfi
954 nop
1da177e4 955
50a34dbd
KM
956#ifndef CONFIG_PREEMPT
957# define intr_do_preempt intr_restore
958#endif /* !CONFIG_PREEMPT */
959
1da177e4
LT
960 .import schedule,code
961intr_do_resched:
50a34dbd
KM
962 /* Only call schedule on return to userspace. If we're returning
963 * to kernel space, we may schedule if CONFIG_PREEMPT, otherwise
964 * we jump back to intr_restore.
965 */
1da177e4 966 LDREG PT_IASQ0(%r16), %r20
872f6deb 967 cmpib,COND(=) 0, %r20, intr_do_preempt
1da177e4
LT
968 nop
969 LDREG PT_IASQ1(%r16), %r20
872f6deb 970 cmpib,COND(=) 0, %r20, intr_do_preempt
1da177e4
LT
971 nop
972
9352aead
JDA
973 /* NOTE: We need to enable interrupts if we schedule. We used
974 * to do this earlier but it caused kernel stack overflows. */
975 ssm PSW_SM_I, %r0
976
413059f2 977#ifdef CONFIG_64BIT
1da177e4
LT
978 ldo -16(%r30),%r29 /* Reference param save area */
979#endif
980
981 ldil L%intr_check_sig, %r2
99ac7947 982#ifndef CONFIG_64BIT
1da177e4 983 b schedule
99ac7947
RC
984#else
985 load32 schedule, %r20
986 bv %r0(%r20)
987#endif
1da177e4
LT
988 ldo R%intr_check_sig(%r2), %r2
989
50a34dbd
KM
990 /* preempt the current task on returning to kernel
991 * mode from an interrupt, iff need_resched is set,
992 * and preempt_count is 0. otherwise, we continue on
993 * our merry way back to the current running task.
994 */
995#ifdef CONFIG_PREEMPT
996 .import preempt_schedule_irq,code
997intr_do_preempt:
998 rsm PSW_SM_I, %r0 /* disable interrupts */
999
1000 /* current_thread_info()->preempt_count */
1001 mfctl %cr30, %r1
1002 LDREG TI_PRE_COUNT(%r1), %r19
872f6deb 1003 cmpib,COND(<>) 0, %r19, intr_restore /* if preempt_count > 0 */
50a34dbd
KM
1004 nop /* prev insn branched backwards */
1005
1006 /* check if we interrupted a critical path */
1007 LDREG PT_PSW(%r16), %r20
1008 bb,<,n %r20, 31 - PSW_SM_I, intr_restore
1009 nop
1010
1011 BL preempt_schedule_irq, %r2
1012 nop
1013
9c2c5457 1014 b,n intr_restore /* ssm PSW_SM_I done by intr_restore */
50a34dbd 1015#endif /* CONFIG_PREEMPT */
1da177e4 1016
1da177e4
LT
1017 /*
1018 * External interrupts.
1019 */
1020
1021intr_extint:
872f6deb 1022 cmpib,COND(=),n 0,%r16,1f
6cc4525d 1023
1da177e4 1024 get_stack_use_cr30
6cc4525d 1025 b,n 2f
1da177e4
LT
1026
10271:
1da177e4 1028 get_stack_use_r30
6cc4525d 10292:
1da177e4
LT
1030 save_specials %r29
1031 virt_map
1032 save_general %r29
1033
1034 ldo PT_FR0(%r29), %r24
1035 save_fp %r24
1036
1037 loadgp
1038
1039 copy %r29, %r26 /* arg0 is pt_regs */
1040 copy %r29, %r16 /* save pt_regs */
1041
1042 ldil L%intr_return, %r2
1043
413059f2 1044#ifdef CONFIG_64BIT
1da177e4
LT
1045 ldo -16(%r30),%r29 /* Reference param save area */
1046#endif
1047
1048 b do_cpu_irq_mask
1049 ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */
8801ccb9 1050ENDPROC_CFI(syscall_exit_rfi)
1da177e4
LT
1051
1052
1053 /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
1054
f39cce65 1055ENTRY_CFI(intr_save) /* for os_hpmc */
1da177e4 1056 mfsp %sr7,%r16
872f6deb 1057 cmpib,COND(=),n 0,%r16,1f
1da177e4
LT
1058 get_stack_use_cr30
1059 b 2f
1060 copy %r8,%r26
1061
10621:
1063 get_stack_use_r30
1064 copy %r8,%r26
1065
10662:
1067 save_specials %r29
1068
1069 /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
5b00ca0b 1070 cmpib,COND(=),n PARISC_ITLB_TRAP,%r26,skip_save_ior
1da177e4 1071
1da177e4 1072
5b00ca0b 1073 mfctl %isr, %r16
896a3756 1074 nop /* serialize mfctl on PA 2.0 to avoid 4 cycle penalty */
5b00ca0b 1075 mfctl %ior, %r17
1da177e4 1076
896a3756 1077
413059f2 1078#ifdef CONFIG_64BIT
1da177e4
LT
1079 /*
1080 * If the interrupted code was running with W bit off (32 bit),
1081 * clear the b bits (bits 0 & 1) in the ior.
896a3756 1082 * save_specials left ipsw value in r8 for us to test.
1da177e4
LT
1083 */
1084 extrd,u,*<> %r8,PSW_W_BIT,1,%r0
1085 depdi 0,1,2,%r17
1086
5b00ca0b
HD
1087 /* adjust isr/ior: get high bits from isr and deposit in ior */
1088 space_adjust %r16,%r17,%r1
1da177e4
LT
1089#endif
1090 STREG %r16, PT_ISR(%r29)
1091 STREG %r17, PT_IOR(%r29)
1092
5b00ca0b
HD
1093#if 0 && defined(CONFIG_64BIT)
1094 /* Revisit when we have 64-bit code above 4Gb */
1095 b,n intr_save2
1da177e4
LT
1096
1097skip_save_ior:
5b00ca0b
HD
1098 /* We have a itlb miss, and when executing code above 4 Gb on ILP64, we
1099 * need to adjust iasq/iaoq here in the same way we adjusted isr/ior
1100 * above.
1101 */
1102 extrd,u,* %r8,PSW_W_BIT,1,%r1
1103 cmpib,COND(=),n 1,%r1,intr_save2
1104 LDREG PT_IASQ0(%r29), %r16
1105 LDREG PT_IAOQ0(%r29), %r17
1106 /* adjust iasq/iaoq */
1107 space_adjust %r16,%r17,%r1
1108 STREG %r16, PT_IASQ0(%r29)
1109 STREG %r17, PT_IAOQ0(%r29)
1110#else
1111skip_save_ior:
1112#endif
1113
1114intr_save2:
1da177e4
LT
1115 virt_map
1116 save_general %r29
1117
1118 ldo PT_FR0(%r29), %r25
1119 save_fp %r25
1120
1121 loadgp
1122
1123 copy %r29, %r25 /* arg1 is pt_regs */
413059f2 1124#ifdef CONFIG_64BIT
1da177e4
LT
1125 ldo -16(%r30),%r29 /* Reference param save area */
1126#endif
1127
1128 ldil L%intr_check_sig, %r2
1129 copy %r25, %r16 /* save pt_regs */
1130
1131 b handle_interruption
1132 ldo R%intr_check_sig(%r2), %r2
f39cce65 1133ENDPROC_CFI(intr_save)
1da177e4
LT
1134
1135
1136 /*
1137 * Note for all tlb miss handlers:
1138 *
1139 * cr24 contains a pointer to the kernel address space
1140 * page directory.
1141 *
1142 * cr25 contains a pointer to the current user address
1143 * space page directory.
1144 *
1145 * sr3 will contain the space id of the user address space
1146 * of the current running thread while that thread is
1147 * running in the kernel.
1148 */
1149
1150 /*
1151 * register number allocations. Note that these are all
1152 * in the shadowed registers
1153 */
1154
1155 t0 = r1 /* temporary register 0 */
25985edc 1156 va = r8 /* virtual address for which the trap occurred */
1da177e4
LT
1157 t1 = r9 /* temporary register 1 */
1158 pte = r16 /* pte/phys page # */
1159 prot = r17 /* prot bits */
25985edc 1160 spc = r24 /* space for which the trap occurred */
1da177e4
LT
1161 ptp = r25 /* page directory/page table pointer */
1162
413059f2 1163#ifdef CONFIG_64BIT
1da177e4
LT
1164
1165dtlb_miss_20w:
1166 space_adjust spc,va,t0
1167 get_pgd spc,ptp
1168 space_check spc,t0,dtlb_fault
1169
1170 L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w
1171
01ab6057
JDA
1172 tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20w
1173 update_accessed ptp,pte,t0,t1
1da177e4 1174
736d2169 1175 make_insert_tlb spc,pte,prot,t1
1da177e4
LT
1176
1177 idtlbt pte,prot
1178
9e5c6021 1179 tlb_unlock1 spc,t0,t1
1da177e4
LT
1180 rfir
1181 nop
1182
1183dtlb_check_alias_20w:
2f649c1f 1184 do_alias spc,t0,t1,va,pte,prot,dtlb_fault,20
1da177e4
LT
1185
1186 idtlbt pte,prot
1187
1188 rfir
1189 nop
1190
1191nadtlb_miss_20w:
1192 space_adjust spc,va,t0
1193 get_pgd spc,ptp
1194 space_check spc,t0,nadtlb_fault
1195
f311847c 1196 L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w
1da177e4 1197
01ab6057
JDA
1198 tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20w
1199 update_accessed ptp,pte,t0,t1
1da177e4 1200
736d2169 1201 make_insert_tlb spc,pte,prot,t1
1da177e4
LT
1202
1203 idtlbt pte,prot
1204
9e5c6021 1205 tlb_unlock1 spc,t0,t1
1da177e4
LT
1206 rfir
1207 nop
1208
f311847c 1209nadtlb_check_alias_20w:
2f649c1f 1210 do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,20
1da177e4 1211
1da177e4
LT
1212 idtlbt pte,prot
1213
1214 rfir
1215 nop
1216
1217#else
1218
1219dtlb_miss_11:
1220 get_pgd spc,ptp
1221
1222 space_check spc,t0,dtlb_fault
1223
1224 L2_ptep ptp,pte,t0,va,dtlb_check_alias_11
1225
01ab6057
JDA
1226 tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_11
1227 update_accessed ptp,pte,t0,t1
1da177e4
LT
1228
1229 make_insert_tlb_11 spc,pte,prot
1230
01ab6057 1231 mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */
1da177e4
LT
1232 mtsp spc,%sr1
1233
1234 idtlba pte,(%sr1,va)
1235 idtlbp prot,(%sr1,va)
1236
01ab6057 1237 mtsp t1, %sr1 /* Restore sr1 */
1da177e4 1238
9e5c6021 1239 tlb_unlock1 spc,t0,t1
1da177e4
LT
1240 rfir
1241 nop
1242
1243dtlb_check_alias_11:
2f649c1f 1244 do_alias spc,t0,t1,va,pte,prot,dtlb_fault,11
1da177e4
LT
1245
1246 idtlba pte,(va)
1247 idtlbp prot,(va)
1248
1249 rfir
1250 nop
1251
1252nadtlb_miss_11:
1253 get_pgd spc,ptp
1254
1255 space_check spc,t0,nadtlb_fault
1256
f311847c 1257 L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11
1da177e4 1258
01ab6057
JDA
1259 tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_11
1260 update_accessed ptp,pte,t0,t1
1da177e4
LT
1261
1262 make_insert_tlb_11 spc,pte,prot
1263
01ab6057 1264 mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */
1da177e4
LT
1265 mtsp spc,%sr1
1266
1267 idtlba pte,(%sr1,va)
1268 idtlbp prot,(%sr1,va)
1269
01ab6057 1270 mtsp t1, %sr1 /* Restore sr1 */
1da177e4 1271
9e5c6021 1272 tlb_unlock1 spc,t0,t1
1da177e4
LT
1273 rfir
1274 nop
1275
f311847c 1276nadtlb_check_alias_11:
2f649c1f 1277 do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,11
f311847c
JB
1278
1279 idtlba pte,(va)
1280 idtlbp prot,(va)
1281
1282 rfir
1283 nop
1284
1da177e4
LT
1285dtlb_miss_20:
1286 space_adjust spc,va,t0
1287 get_pgd spc,ptp
1288 space_check spc,t0,dtlb_fault
1289
1290 L2_ptep ptp,pte,t0,va,dtlb_check_alias_20
1291
01ab6057
JDA
1292 tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20
1293 update_accessed ptp,pte,t0,t1
1da177e4 1294
736d2169 1295 make_insert_tlb spc,pte,prot,t1
1da177e4 1296
01ab6057 1297 f_extend pte,t1
1da177e4
LT
1298
1299 idtlbt pte,prot
1300
9e5c6021 1301 tlb_unlock1 spc,t0,t1
1da177e4
LT
1302 rfir
1303 nop
1304
1305dtlb_check_alias_20:
2f649c1f 1306 do_alias spc,t0,t1,va,pte,prot,dtlb_fault,20
1da177e4
LT
1307
1308 idtlbt pte,prot
1309
1310 rfir
1311 nop
1312
1313nadtlb_miss_20:
1314 get_pgd spc,ptp
1315
1316 space_check spc,t0,nadtlb_fault
1317
f311847c 1318 L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20
1da177e4 1319
01ab6057
JDA
1320 tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20
1321 update_accessed ptp,pte,t0,t1
1da177e4 1322
736d2169 1323 make_insert_tlb spc,pte,prot,t1
1da177e4 1324
01ab6057 1325 f_extend pte,t1
1da177e4 1326
01ab6057 1327 idtlbt pte,prot
1da177e4 1328
9e5c6021 1329 tlb_unlock1 spc,t0,t1
1da177e4
LT
1330 rfir
1331 nop
1332
f311847c 1333nadtlb_check_alias_20:
2f649c1f 1334 do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,20
f311847c
JB
1335
1336 idtlbt pte,prot
1337
1338 rfir
1339 nop
1340
1da177e4
LT
1341#endif
1342
1343nadtlb_emulate:
1344
1345 /*
1346 * Non access misses can be caused by fdc,fic,pdc,lpa,probe and
1347 * probei instructions. We don't want to fault for these
1348 * instructions (not only does it not make sense, it can cause
1349 * deadlocks, since some flushes are done with the mmap
1350 * semaphore held). If the translation doesn't exist, we can't
1351 * insert a translation, so have to emulate the side effects
1352 * of the instruction. Since we don't insert a translation
1353 * we can get a lot of faults during a flush loop, so it makes
1354 * sense to try to do it here with minimum overhead. We only
1355 * emulate fdc,fic,pdc,probew,prober instructions whose base
1356 * and index registers are not shadowed. We defer everything
1357 * else to the "slow" path.
1358 */
1359
1360 mfctl %cr19,%r9 /* Get iir */
1361
1362 /* PA 2.0 Arch Ref. Book pg 382 has a good description of the insn bits.
1363 Checks for fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw */
1364
1365 /* Checks for fdc,fdce,pdc,"fic,4f" only */
1366 ldi 0x280,%r16
1367 and %r9,%r16,%r17
1368 cmpb,<>,n %r16,%r17,nadtlb_probe_check
1369 bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */
1370 BL get_register,%r25
1371 extrw,u %r9,15,5,%r8 /* Get index register # */
872f6deb 1372 cmpib,COND(=),n -1,%r1,nadtlb_fault /* have to use slow path */
1da177e4
LT
1373 copy %r1,%r24
1374 BL get_register,%r25
1375 extrw,u %r9,10,5,%r8 /* Get base register # */
872f6deb 1376 cmpib,COND(=),n -1,%r1,nadtlb_fault /* have to use slow path */
1da177e4
LT
1377 BL set_register,%r25
1378 add,l %r1,%r24,%r1 /* doesn't affect c/b bits */
1379
1380nadtlb_nullify:
896a3756 1381 mfctl %ipsw,%r8
1da177e4
LT
1382 ldil L%PSW_N,%r9
1383 or %r8,%r9,%r8 /* Set PSW_N */
896a3756 1384 mtctl %r8,%ipsw
1da177e4
LT
1385
1386 rfir
1387 nop
1388
1389 /*
1390 When there is no translation for the probe address then we
ad61dd30 1391 must nullify the insn and return zero in the target register.
1da177e4
LT
1392 This will indicate to the calling code that it does not have
1393 write/read privileges to this address.
1394
1395 This should technically work for prober and probew in PA 1.1,
1396 and also probe,r and probe,w in PA 2.0
1397
1398 WARNING: USE ONLY NON-SHADOW REGISTERS WITH PROBE INSN!
1399 THE SLOW-PATH EMULATION HAS NOT BEEN WRITTEN YET.
1400
1401 */
1402nadtlb_probe_check:
1403 ldi 0x80,%r16
1404 and %r9,%r16,%r17
1405 cmpb,<>,n %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/
1406 BL get_register,%r25 /* Find the target register */
1407 extrw,u %r9,31,5,%r8 /* Get target register */
872f6deb 1408 cmpib,COND(=),n -1,%r1,nadtlb_fault /* have to use slow path */
1da177e4
LT
1409 BL set_register,%r25
1410 copy %r0,%r1 /* Write zero to target register */
1411 b nadtlb_nullify /* Nullify return insn */
1412 nop
1413
1414
413059f2 1415#ifdef CONFIG_64BIT
1da177e4
LT
1416itlb_miss_20w:
1417
1418 /*
1419 * I miss is a little different, since we allow users to fault
1420 * on the gateway page which is in the kernel address space.
1421 */
1422
1423 space_adjust spc,va,t0
1424 get_pgd spc,ptp
1425 space_check spc,t0,itlb_fault
1426
1427 L3_ptep ptp,pte,t0,va,itlb_fault
1428
01ab6057
JDA
1429 tlb_lock spc,ptp,pte,t0,t1,itlb_fault
1430 update_accessed ptp,pte,t0,t1
1da177e4 1431
736d2169 1432 make_insert_tlb spc,pte,prot,t1
1da177e4
LT
1433
1434 iitlbt pte,prot
1435
9e5c6021 1436 tlb_unlock1 spc,t0,t1
1da177e4
LT
1437 rfir
1438 nop
1439
f311847c
JB
1440naitlb_miss_20w:
1441
1442 /*
1443 * I miss is a little different, since we allow users to fault
1444 * on the gateway page which is in the kernel address space.
1445 */
1446
1447 space_adjust spc,va,t0
1448 get_pgd spc,ptp
1449 space_check spc,t0,naitlb_fault
1450
1451 L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w
1452
01ab6057
JDA
1453 tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20w
1454 update_accessed ptp,pte,t0,t1
f311847c 1455
736d2169 1456 make_insert_tlb spc,pte,prot,t1
f311847c
JB
1457
1458 iitlbt pte,prot
1459
9e5c6021 1460 tlb_unlock1 spc,t0,t1
f311847c
JB
1461 rfir
1462 nop
1463
1464naitlb_check_alias_20w:
2f649c1f 1465 do_alias spc,t0,t1,va,pte,prot,naitlb_fault,20
f311847c
JB
1466
1467 iitlbt pte,prot
1468
1469 rfir
1470 nop
1471
1da177e4
LT
1472#else
1473
1474itlb_miss_11:
1475 get_pgd spc,ptp
1476
1477 space_check spc,t0,itlb_fault
1478
1479 L2_ptep ptp,pte,t0,va,itlb_fault
1480
01ab6057
JDA
1481 tlb_lock spc,ptp,pte,t0,t1,itlb_fault
1482 update_accessed ptp,pte,t0,t1
1da177e4
LT
1483
1484 make_insert_tlb_11 spc,pte,prot
1485
01ab6057 1486 mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */
1da177e4
LT
1487 mtsp spc,%sr1
1488
1489 iitlba pte,(%sr1,va)
1490 iitlbp prot,(%sr1,va)
1491
01ab6057 1492 mtsp t1, %sr1 /* Restore sr1 */
1da177e4 1493
9e5c6021 1494 tlb_unlock1 spc,t0,t1
1da177e4
LT
1495 rfir
1496 nop
1497
f311847c
JB
1498naitlb_miss_11:
1499 get_pgd spc,ptp
1500
1501 space_check spc,t0,naitlb_fault
1502
1503 L2_ptep ptp,pte,t0,va,naitlb_check_alias_11
1504
01ab6057
JDA
1505 tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_11
1506 update_accessed ptp,pte,t0,t1
f311847c
JB
1507
1508 make_insert_tlb_11 spc,pte,prot
1509
01ab6057 1510 mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */
f311847c
JB
1511 mtsp spc,%sr1
1512
1513 iitlba pte,(%sr1,va)
1514 iitlbp prot,(%sr1,va)
1515
01ab6057 1516 mtsp t1, %sr1 /* Restore sr1 */
f311847c 1517
9e5c6021 1518 tlb_unlock1 spc,t0,t1
f311847c
JB
1519 rfir
1520 nop
1521
1522naitlb_check_alias_11:
2f649c1f 1523 do_alias spc,t0,t1,va,pte,prot,itlb_fault,11
f311847c
JB
1524
1525 iitlba pte,(%sr0, va)
1526 iitlbp prot,(%sr0, va)
1527
1528 rfir
1529 nop
1530
1531
1da177e4
LT
1532itlb_miss_20:
1533 get_pgd spc,ptp
1534
1535 space_check spc,t0,itlb_fault
1536
1537 L2_ptep ptp,pte,t0,va,itlb_fault
1538
01ab6057
JDA
1539 tlb_lock spc,ptp,pte,t0,t1,itlb_fault
1540 update_accessed ptp,pte,t0,t1
1da177e4 1541
736d2169 1542 make_insert_tlb spc,pte,prot,t1
1da177e4 1543
01ab6057 1544 f_extend pte,t1
1da177e4
LT
1545
1546 iitlbt pte,prot
1547
9e5c6021 1548 tlb_unlock1 spc,t0,t1
1da177e4
LT
1549 rfir
1550 nop
1551
f311847c
JB
1552naitlb_miss_20:
1553 get_pgd spc,ptp
1554
1555 space_check spc,t0,naitlb_fault
1556
1557 L2_ptep ptp,pte,t0,va,naitlb_check_alias_20
1558
01ab6057
JDA
1559 tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20
1560 update_accessed ptp,pte,t0,t1
f311847c 1561
736d2169 1562 make_insert_tlb spc,pte,prot,t1
f311847c 1563
01ab6057 1564 f_extend pte,t1
f311847c
JB
1565
1566 iitlbt pte,prot
1567
9e5c6021 1568 tlb_unlock1 spc,t0,t1
f311847c
JB
1569 rfir
1570 nop
1571
1572naitlb_check_alias_20:
2f649c1f 1573 do_alias spc,t0,t1,va,pte,prot,naitlb_fault,20
f311847c
JB
1574
1575 iitlbt pte,prot
1576
1577 rfir
1578 nop
1579
1da177e4
LT
1580#endif
1581
413059f2 1582#ifdef CONFIG_64BIT
1da177e4
LT
1583
1584dbit_trap_20w:
1585 space_adjust spc,va,t0
1586 get_pgd spc,ptp
1587 space_check spc,t0,dbit_fault
1588
1589 L3_ptep ptp,pte,t0,va,dbit_fault
1590
01ab6057
JDA
1591 tlb_lock spc,ptp,pte,t0,t1,dbit_fault
1592 update_dirty ptp,pte,t1
1da177e4 1593
736d2169 1594 make_insert_tlb spc,pte,prot,t1
1da177e4
LT
1595
1596 idtlbt pte,prot
1da177e4 1597
9e5c6021 1598 tlb_unlock0 spc,t0,t1
1da177e4
LT
1599 rfir
1600 nop
1601#else
1602
1603dbit_trap_11:
1604
1605 get_pgd spc,ptp
1606
1607 space_check spc,t0,dbit_fault
1608
1609 L2_ptep ptp,pte,t0,va,dbit_fault
1610
01ab6057
JDA
1611 tlb_lock spc,ptp,pte,t0,t1,dbit_fault
1612 update_dirty ptp,pte,t1
1da177e4
LT
1613
1614 make_insert_tlb_11 spc,pte,prot
1615
1616 mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */
1617 mtsp spc,%sr1
1618
1619 idtlba pte,(%sr1,va)
1620 idtlbp prot,(%sr1,va)
1621
1622 mtsp t1, %sr1 /* Restore sr1 */
1da177e4 1623
9e5c6021 1624 tlb_unlock0 spc,t0,t1
1da177e4
LT
1625 rfir
1626 nop
1627
1628dbit_trap_20:
1629 get_pgd spc,ptp
1630
1631 space_check spc,t0,dbit_fault
1632
1633 L2_ptep ptp,pte,t0,va,dbit_fault
1634
01ab6057
JDA
1635 tlb_lock spc,ptp,pte,t0,t1,dbit_fault
1636 update_dirty ptp,pte,t1
1da177e4 1637
736d2169 1638 make_insert_tlb spc,pte,prot,t1
1da177e4
LT
1639
1640 f_extend pte,t1
1641
01ab6057 1642 idtlbt pte,prot
1da177e4 1643
9e5c6021 1644 tlb_unlock0 spc,t0,t1
1da177e4
LT
1645 rfir
1646 nop
1647#endif
1648
1649 .import handle_interruption,code
1650
1651kernel_bad_space:
1652 b intr_save
1653 ldi 31,%r8 /* Use an unused code */
1654
1655dbit_fault:
1656 b intr_save
1657 ldi 20,%r8
1658
1659itlb_fault:
1660 b intr_save
cd2b8520 1661 ldi PARISC_ITLB_TRAP,%r8
1da177e4
LT
1662
1663nadtlb_fault:
1664 b intr_save
1665 ldi 17,%r8
1666
f311847c
JB
1667naitlb_fault:
1668 b intr_save
1669 ldi 16,%r8
1670
1da177e4
LT
1671dtlb_fault:
1672 b intr_save
1673 ldi 15,%r8
1674
1675 /* Register saving semantics for system calls:
1676
1677 %r1 clobbered by system call macro in userspace
1678 %r2 saved in PT_REGS by gateway page
1679 %r3 - %r18 preserved by C code (saved by signal code)
1680 %r19 - %r20 saved in PT_REGS by gateway page
1681 %r21 - %r22 non-standard syscall args
1682 stored in kernel stack by gateway page
1683 %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page
1684 %r27 - %r30 saved in PT_REGS by gateway page
1685 %r31 syscall return pointer
1686 */
1687
1688 /* Floating point registers (FIXME: what do we do with these?)
1689
1690 %fr0 - %fr3 status/exception, not preserved
1691 %fr4 - %fr7 arguments
1692 %fr8 - %fr11 not preserved by C code
1693 %fr12 - %fr21 preserved by C code
1694 %fr22 - %fr31 not preserved by C code
1695 */
1696
1697 .macro reg_save regs
1698 STREG %r3, PT_GR3(\regs)
1699 STREG %r4, PT_GR4(\regs)
1700 STREG %r5, PT_GR5(\regs)
1701 STREG %r6, PT_GR6(\regs)
1702 STREG %r7, PT_GR7(\regs)
1703 STREG %r8, PT_GR8(\regs)
1704 STREG %r9, PT_GR9(\regs)
1705 STREG %r10,PT_GR10(\regs)
1706 STREG %r11,PT_GR11(\regs)
1707 STREG %r12,PT_GR12(\regs)
1708 STREG %r13,PT_GR13(\regs)
1709 STREG %r14,PT_GR14(\regs)
1710 STREG %r15,PT_GR15(\regs)
1711 STREG %r16,PT_GR16(\regs)
1712 STREG %r17,PT_GR17(\regs)
1713 STREG %r18,PT_GR18(\regs)
1714 .endm
1715
1716 .macro reg_restore regs
1717 LDREG PT_GR3(\regs), %r3
1718 LDREG PT_GR4(\regs), %r4
1719 LDREG PT_GR5(\regs), %r5
1720 LDREG PT_GR6(\regs), %r6
1721 LDREG PT_GR7(\regs), %r7
1722 LDREG PT_GR8(\regs), %r8
1723 LDREG PT_GR9(\regs), %r9
1724 LDREG PT_GR10(\regs),%r10
1725 LDREG PT_GR11(\regs),%r11
1726 LDREG PT_GR12(\regs),%r12
1727 LDREG PT_GR13(\regs),%r13
1728 LDREG PT_GR14(\regs),%r14
1729 LDREG PT_GR15(\regs),%r15
1730 LDREG PT_GR16(\regs),%r16
1731 LDREG PT_GR17(\regs),%r17
1732 LDREG PT_GR18(\regs),%r18
1733 .endm
1734
415bfae9 1735 .macro fork_like name
f39cce65 1736ENTRY_CFI(sys_\name\()_wrapper)
1da177e4
LT
1737 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1738 ldo TASK_REGS(%r1),%r1
1739 reg_save %r1
ff0ab8af 1740 mfctl %cr27, %r28
bbbfde78
JDA
1741 ldil L%sys_\name, %r31
1742 be R%sys_\name(%sr4,%r31)
ff0ab8af 1743 STREG %r28, PT_CR27(%r1)
f39cce65 1744ENDPROC_CFI(sys_\name\()_wrapper)
415bfae9 1745 .endm
1da177e4 1746
415bfae9
AV
1747fork_like clone
1748fork_like fork
1749fork_like vfork
1da177e4
LT
1750
1751 /* Set the return value for the child */
8801ccb9 1752ENTRY(child_return)
1da177e4
LT
1753 BL schedule_tail, %r2
1754 nop
363806dd 1755finish_child_return:
ff0ab8af
AV
1756 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1757 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1758
1759 LDREG PT_CR27(%r1), %r3
1760 mtctl %r3, %cr27
1761 reg_restore %r1
1762 b syscall_exit
1da177e4 1763 copy %r0,%r28
8801ccb9 1764END(child_return)
1da177e4 1765
f39cce65 1766ENTRY_CFI(sys_rt_sigreturn_wrapper)
1da177e4
LT
1767 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
1768 ldo TASK_REGS(%r26),%r26 /* get pt regs */
1769 /* Don't save regs, we are going to restore them from sigcontext. */
1770 STREG %r2, -RP_OFFSET(%r30)
413059f2 1771#ifdef CONFIG_64BIT
1da177e4
LT
1772 ldo FRAME_SIZE(%r30), %r30
1773 BL sys_rt_sigreturn,%r2
1774 ldo -16(%r30),%r29 /* Reference param save area */
1775#else
1776 BL sys_rt_sigreturn,%r2
1777 ldo FRAME_SIZE(%r30), %r30
1778#endif
1779
1780 ldo -FRAME_SIZE(%r30), %r30
1781 LDREG -RP_OFFSET(%r30), %r2
1782
1783 /* FIXME: I think we need to restore a few more things here. */
1784 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1785 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1786 reg_restore %r1
1787
1788 /* If the signal was received while the process was blocked on a
1789 * syscall, then r2 will take us to syscall_exit; otherwise r2 will
1790 * take us to syscall_exit_rfi and on to intr_return.
1791 */
1792 bv %r0(%r2)
1793 LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
f39cce65 1794ENDPROC_CFI(sys_rt_sigreturn_wrapper)
1da177e4 1795
8801ccb9 1796ENTRY(syscall_exit)
1da177e4
LT
1797 /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
1798 * via syscall_exit_rfi if the signal was received while the process
1799 * was running.
1800 */
1801
1802 /* save return value now */
1803
1804 mfctl %cr30, %r1
1805 LDREG TI_TASK(%r1),%r1
1806 STREG %r28,TASK_PT_GR28(%r1)
1807
1da177e4
LT
1808 /* Seems to me that dp could be wrong here, if the syscall involved
1809 * calling a module, and nothing got round to restoring dp on return.
1810 */
1811 loadgp
1812
1da177e4
LT
1813syscall_check_resched:
1814
1815 /* check for reschedule */
1816
1817 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */
1818 bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
1819
4650f0a5 1820 .import do_signal,code
1da177e4 1821syscall_check_sig:
4650f0a5 1822 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
6fd84c08 1823 ldi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r26
4650f0a5
KM
1824 and,COND(<>) %r19, %r26, %r0
1825 b,n syscall_restore /* skip past if we've nothing to do */
1826
1827syscall_do_signal:
1828 /* Save callee-save registers (for sigcontext).
1829 * FIXME: After this point the process structure should be
1830 * consistent with all the relevant state of the process
1831 * before the syscall. We need to verify this.
1832 */
1833 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1834 ldo TASK_REGS(%r1), %r26 /* struct pt_regs *regs */
1835 reg_save %r26
1836
1837#ifdef CONFIG_64BIT
1838 ldo -16(%r30),%r29 /* Reference param save area */
1839#endif
1840
1841 BL do_notify_resume,%r2
1842 ldi 1, %r25 /* long in_syscall = 1 */
1843
1844 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1845 ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
1846 reg_restore %r20
1847
1848 b,n syscall_check_sig
1da177e4
LT
1849
1850syscall_restore:
1da177e4
LT
1851 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1852
ecd3d4bc
KM
1853 /* Are we being ptraced? */
1854 ldw TASK_FLAGS(%r1),%r19
34360f08 1855 ldi _TIF_SYSCALL_TRACE_MASK,%r2
ecd3d4bc
KM
1856 and,COND(=) %r19,%r2,%r0
1857 b,n syscall_restore_rfi
1da177e4
LT
1858
1859 ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */
1860 rest_fp %r19
1861
1862 LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */
1863 mtsar %r19
1864
1865 LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */
1866 LDREG TASK_PT_GR19(%r1),%r19
1867 LDREG TASK_PT_GR20(%r1),%r20
1868 LDREG TASK_PT_GR21(%r1),%r21
1869 LDREG TASK_PT_GR22(%r1),%r22
1870 LDREG TASK_PT_GR23(%r1),%r23
1871 LDREG TASK_PT_GR24(%r1),%r24
1872 LDREG TASK_PT_GR25(%r1),%r25
1873 LDREG TASK_PT_GR26(%r1),%r26
1874 LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */
1875 LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */
1876 LDREG TASK_PT_GR29(%r1),%r29
1877 LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */
1878
1879 /* NOTE: We use rsm/ssm pair to make this operation atomic */
8f6c0c2b 1880 LDREG TASK_PT_GR30(%r1),%r1 /* Get user sp */
1da177e4 1881 rsm PSW_SM_I, %r0
8f6c0c2b
JDA
1882 copy %r1,%r30 /* Restore user sp */
1883 mfsp %sr3,%r1 /* Get user space id */
1da177e4
LT
1884 mtsp %r1,%sr7 /* Restore sr7 */
1885 ssm PSW_SM_I, %r0
1886
1887 /* Set sr2 to zero for userspace syscalls to work. */
1888 mtsp %r0,%sr2
1889 mtsp %r1,%sr4 /* Restore sr4 */
1890 mtsp %r1,%sr5 /* Restore sr5 */
1891 mtsp %r1,%sr6 /* Restore sr6 */
1892
1893 depi 3,31,2,%r31 /* ensure return to user mode. */
1894
413059f2 1895#ifdef CONFIG_64BIT
1da177e4
LT
1896 /* decide whether to reset the wide mode bit
1897 *
1898 * For a syscall, the W bit is stored in the lowest bit
1899 * of sp. Extract it and reset W if it is zero */
1900 extrd,u,*<> %r30,63,1,%r1
1901 rsm PSW_SM_W, %r0
1902 /* now reset the lowest bit of sp if it was set */
1903 xor %r30,%r1,%r30
1904#endif
1905 be,n 0(%sr3,%r31) /* return to user space */
1906
1907 /* We have to return via an RFI, so that PSW T and R bits can be set
1908 * appropriately.
1909 * This sets up pt_regs so we can return via intr_restore, which is not
1910 * the most efficient way of doing things, but it works.
1911 */
1912syscall_restore_rfi:
1913 ldo -1(%r0),%r2 /* Set recovery cntr to -1 */
1914 mtctl %r2,%cr0 /* for immediate trap */
1915 LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */
1916 ldi 0x0b,%r20 /* Create new PSW */
1917 depi -1,13,1,%r20 /* C, Q, D, and I bits */
1918
ecd3d4bc
KM
1919 /* The values of SINGLESTEP_BIT and BLOCKSTEP_BIT are
1920 * set in thread_info.h and converted to PA bitmap
1da177e4
LT
1921 * numbers in asm-offsets.c */
1922
ecd3d4bc
KM
1923 /* if ((%r19.SINGLESTEP_BIT)) { %r20.27=1} */
1924 extru,= %r19,TIF_SINGLESTEP_PA_BIT,1,%r0
1da177e4
LT
1925 depi -1,27,1,%r20 /* R bit */
1926
ecd3d4bc
KM
1927 /* if ((%r19.BLOCKSTEP_BIT)) { %r20.7=1} */
1928 extru,= %r19,TIF_BLOCKSTEP_PA_BIT,1,%r0
1da177e4
LT
1929 depi -1,7,1,%r20 /* T bit */
1930
1931 STREG %r20,TASK_PT_PSW(%r1)
1932
1933 /* Always store space registers, since sr3 can be changed (e.g. fork) */
1934
1935 mfsp %sr3,%r25
1936 STREG %r25,TASK_PT_SR3(%r1)
1937 STREG %r25,TASK_PT_SR4(%r1)
1938 STREG %r25,TASK_PT_SR5(%r1)
1939 STREG %r25,TASK_PT_SR6(%r1)
1940 STREG %r25,TASK_PT_SR7(%r1)
1941 STREG %r25,TASK_PT_IASQ0(%r1)
1942 STREG %r25,TASK_PT_IASQ1(%r1)
1943
1944 /* XXX W bit??? */
1945 /* Now if old D bit is clear, it means we didn't save all registers
1946 * on syscall entry, so do that now. This only happens on TRACEME
1947 * calls, or if someone attached to us while we were on a syscall.
1948 * We could make this more efficient by not saving r3-r18, but
1949 * then we wouldn't be able to use the common intr_restore path.
1950 * It is only for traced processes anyway, so performance is not
1951 * an issue.
1952 */
1953 bb,< %r2,30,pt_regs_ok /* Branch if D set */
1954 ldo TASK_REGS(%r1),%r25
1955 reg_save %r25 /* Save r3 to r18 */
1956
1957 /* Save the current sr */
1958 mfsp %sr0,%r2
1959 STREG %r2,TASK_PT_SR0(%r1)
1960
1961 /* Save the scratch sr */
1962 mfsp %sr1,%r2
1963 STREG %r2,TASK_PT_SR1(%r1)
1964
1965 /* sr2 should be set to zero for userspace syscalls */
1966 STREG %r0,TASK_PT_SR2(%r1)
1967
1da177e4 1968 LDREG TASK_PT_GR31(%r1),%r2
34360f08
JDA
1969 depi 3,31,2,%r2 /* ensure return to user mode. */
1970 STREG %r2,TASK_PT_IAOQ0(%r1)
1da177e4
LT
1971 ldo 4(%r2),%r2
1972 STREG %r2,TASK_PT_IAOQ1(%r1)
34360f08 1973 b intr_restore
1da177e4 1974 copy %r25,%r16
34360f08
JDA
1975
1976pt_regs_ok:
1977 LDREG TASK_PT_IAOQ0(%r1),%r2
1978 depi 3,31,2,%r2 /* ensure return to user mode. */
1979 STREG %r2,TASK_PT_IAOQ0(%r1)
1980 LDREG TASK_PT_IAOQ1(%r1),%r2
1981 depi 3,31,2,%r2
1982 STREG %r2,TASK_PT_IAOQ1(%r1)
1da177e4 1983 b intr_restore
34360f08 1984 copy %r25,%r16
1da177e4 1985
1da177e4 1986syscall_do_resched:
366dd4ea
HD
1987 load32 syscall_check_resched,%r2 /* if resched, we start over again */
1988 load32 schedule,%r19
1989 bv %r0(%r19) /* jumps to schedule() */
413059f2 1990#ifdef CONFIG_64BIT
1da177e4
LT
1991 ldo -16(%r30),%r29 /* Reference param save area */
1992#else
1993 nop
1994#endif
8801ccb9 1995END(syscall_exit)
1da177e4 1996
c5e76552 1997
d75f054a 1998#ifdef CONFIG_FUNCTION_TRACER
366dd4ea 1999
d75f054a 2000 .import ftrace_function_trampoline,code
366dd4ea 2001 .align L1_CACHE_BYTES
c8921d72 2002ENTRY_CFI(mcount, caller)
366dd4ea
HD
2003_mcount:
2004 .export _mcount,data
366dd4ea
HD
2005 /*
2006 * The 64bit mcount() function pointer needs 4 dwords, of which the
2007 * first two are free. We optimize it here and put 2 instructions for
2008 * calling mcount(), and 2 instructions for ftrace_stub(). That way we
2009 * have all on one L1 cacheline.
2010 */
d75f054a 2011 b ftrace_function_trampoline
366dd4ea
HD
2012 copy %r3, %arg2 /* caller original %sp */
2013ftrace_stub:
2014 .globl ftrace_stub
2015 .type ftrace_stub, @function
2016#ifdef CONFIG_64BIT
2017 bve (%rp)
2018#else
2019 bv %r0(%rp)
2020#endif
d75f054a 2021 nop
366dd4ea
HD
2022#ifdef CONFIG_64BIT
2023 .dword mcount
2024 .dword 0 /* code in head.S puts value of global gp here */
2025#endif
c8921d72 2026ENDPROC_CFI(mcount)
d75f054a 2027
5fece5ad 2028#ifdef CONFIG_FUNCTION_GRAPH_TRACER
366dd4ea 2029 .align 8
c8921d72 2030ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE)
366dd4ea
HD
2031 .export parisc_return_to_handler,data
2032parisc_return_to_handler:
2033 copy %r3,%r1
2034 STREG %r0,-RP_OFFSET(%sp) /* store 0 as %rp */
2035 copy %sp,%r3
2036 STREGM %r1,FRAME_SIZE(%sp)
2037 STREG %ret0,8(%r3)
2038 STREG %ret1,16(%r3)
d75f054a 2039
366dd4ea
HD
2040#ifdef CONFIG_64BIT
2041 loadgp
2042#endif
2043
2044 /* call ftrace_return_to_handler(0) */
5fece5ad
HD
2045 .import ftrace_return_to_handler,code
2046 load32 ftrace_return_to_handler,%ret0
2047 load32 .Lftrace_ret,%r2
366dd4ea
HD
2048#ifdef CONFIG_64BIT
2049 ldo -16(%sp),%ret1 /* Reference param save area */
5fece5ad
HD
2050 bve (%ret0)
2051#else
2052 bv %r0(%ret0)
366dd4ea 2053#endif
366dd4ea 2054 ldi 0,%r26
5fece5ad 2055.Lftrace_ret:
366dd4ea
HD
2056 copy %ret0,%rp
2057
2058 /* restore original return values */
2059 LDREG 8(%r3),%ret0
2060 LDREG 16(%r3),%ret1
2061
2062 /* return from function */
2063#ifdef CONFIG_64BIT
2064 bve (%rp)
2065#else
d75f054a 2066 bv %r0(%rp)
366dd4ea
HD
2067#endif
2068 LDREGM -FRAME_SIZE(%sp),%r3
f39cce65 2069ENDPROC_CFI(return_to_handler)
366dd4ea 2070
5fece5ad
HD
2071#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2072
d75f054a
HD
2073#endif /* CONFIG_FUNCTION_TRACER */
2074
200c8804
HD
2075#ifdef CONFIG_IRQSTACKS
2076/* void call_on_stack(unsigned long param1, void *func,
2077 unsigned long new_stack) */
c8921d72 2078ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP)
8801ccb9 2079ENTRY(_call_on_stack)
200c8804
HD
2080 copy %sp, %r1
2081
2082 /* Regarding the HPPA calling conventions for function pointers,
2083 we assume the PIC register is not changed across call. For
2084 CONFIG_64BIT, the argument pointer is left to point at the
2085 argument region allocated for the call to call_on_stack. */
c8921d72
HD
2086
2087 /* Switch to new stack. We allocate two frames. */
2088 ldo 2*FRAME_SIZE(%arg2), %sp
200c8804 2089# ifdef CONFIG_64BIT
200c8804 2090 /* Save previous stack pointer and return pointer in frame marker */
c8921d72 2091 STREG %rp, -FRAME_SIZE-RP_OFFSET(%sp)
200c8804
HD
2092 /* Calls always use function descriptor */
2093 LDREG 16(%arg1), %arg1
2094 bve,l (%arg1), %rp
c8921d72
HD
2095 STREG %r1, -FRAME_SIZE-REG_SZ(%sp)
2096 LDREG -FRAME_SIZE-RP_OFFSET(%sp), %rp
200c8804 2097 bve (%rp)
c8921d72 2098 LDREG -FRAME_SIZE-REG_SZ(%sp), %sp
200c8804 2099# else
200c8804 2100 /* Save previous stack pointer and return pointer in frame marker */
c8921d72
HD
2101 STREG %r1, -FRAME_SIZE-REG_SZ(%sp)
2102 STREG %rp, -FRAME_SIZE-RP_OFFSET(%sp)
200c8804
HD
2103 /* Calls use function descriptor if PLABEL bit is set */
2104 bb,>=,n %arg1, 30, 1f
2105 depwi 0,31,2, %arg1
2106 LDREG 0(%arg1), %arg1
21071:
2108 be,l 0(%sr4,%arg1), %sr0, %r31
2109 copy %r31, %rp
c8921d72 2110 LDREG -FRAME_SIZE-RP_OFFSET(%sp), %rp
200c8804 2111 bv (%rp)
c8921d72 2112 LDREG -FRAME_SIZE-REG_SZ(%sp), %sp
200c8804 2113# endif /* CONFIG_64BIT */
f39cce65 2114ENDPROC_CFI(call_on_stack)
200c8804 2115#endif /* CONFIG_IRQSTACKS */
d75f054a 2116
f39cce65 2117ENTRY_CFI(get_register)
1da177e4
LT
2118 /*
2119 * get_register is used by the non access tlb miss handlers to
2120 * copy the value of the general register specified in r8 into
2121 * r1. This routine can't be used for shadowed registers, since
2122 * the rfir will restore the original value. So, for the shadowed
2123 * registers we put a -1 into r1 to indicate that the register
2124 * should not be used (the register being copied could also have
2125 * a -1 in it, but that is OK, it just means that we will have
2126 * to use the slow path instead).
2127 */
1da177e4
LT
2128 blr %r8,%r0
2129 nop
2130 bv %r0(%r25) /* r0 */
2131 copy %r0,%r1
2132 bv %r0(%r25) /* r1 - shadowed */
2133 ldi -1,%r1
2134 bv %r0(%r25) /* r2 */
2135 copy %r2,%r1
2136 bv %r0(%r25) /* r3 */
2137 copy %r3,%r1
2138 bv %r0(%r25) /* r4 */
2139 copy %r4,%r1
2140 bv %r0(%r25) /* r5 */
2141 copy %r5,%r1
2142 bv %r0(%r25) /* r6 */
2143 copy %r6,%r1
2144 bv %r0(%r25) /* r7 */
2145 copy %r7,%r1
2146 bv %r0(%r25) /* r8 - shadowed */
2147 ldi -1,%r1
2148 bv %r0(%r25) /* r9 - shadowed */
2149 ldi -1,%r1
2150 bv %r0(%r25) /* r10 */
2151 copy %r10,%r1
2152 bv %r0(%r25) /* r11 */
2153 copy %r11,%r1
2154 bv %r0(%r25) /* r12 */
2155 copy %r12,%r1
2156 bv %r0(%r25) /* r13 */
2157 copy %r13,%r1
2158 bv %r0(%r25) /* r14 */
2159 copy %r14,%r1
2160 bv %r0(%r25) /* r15 */
2161 copy %r15,%r1
2162 bv %r0(%r25) /* r16 - shadowed */
2163 ldi -1,%r1
2164 bv %r0(%r25) /* r17 - shadowed */
2165 ldi -1,%r1
2166 bv %r0(%r25) /* r18 */
2167 copy %r18,%r1
2168 bv %r0(%r25) /* r19 */
2169 copy %r19,%r1
2170 bv %r0(%r25) /* r20 */
2171 copy %r20,%r1
2172 bv %r0(%r25) /* r21 */
2173 copy %r21,%r1
2174 bv %r0(%r25) /* r22 */
2175 copy %r22,%r1
2176 bv %r0(%r25) /* r23 */
2177 copy %r23,%r1
2178 bv %r0(%r25) /* r24 - shadowed */
2179 ldi -1,%r1
2180 bv %r0(%r25) /* r25 - shadowed */
2181 ldi -1,%r1
2182 bv %r0(%r25) /* r26 */
2183 copy %r26,%r1
2184 bv %r0(%r25) /* r27 */
2185 copy %r27,%r1
2186 bv %r0(%r25) /* r28 */
2187 copy %r28,%r1
2188 bv %r0(%r25) /* r29 */
2189 copy %r29,%r1
2190 bv %r0(%r25) /* r30 */
2191 copy %r30,%r1
2192 bv %r0(%r25) /* r31 */
2193 copy %r31,%r1
f39cce65 2194ENDPROC_CFI(get_register)
1da177e4 2195
c5e76552 2196
f39cce65 2197ENTRY_CFI(set_register)
1da177e4
LT
2198 /*
2199 * set_register is used by the non access tlb miss handlers to
2200 * copy the value of r1 into the general register specified in
2201 * r8.
2202 */
1da177e4
LT
2203 blr %r8,%r0
2204 nop
2205 bv %r0(%r25) /* r0 (silly, but it is a place holder) */
2206 copy %r1,%r0
2207 bv %r0(%r25) /* r1 */
2208 copy %r1,%r1
2209 bv %r0(%r25) /* r2 */
2210 copy %r1,%r2
2211 bv %r0(%r25) /* r3 */
2212 copy %r1,%r3
2213 bv %r0(%r25) /* r4 */
2214 copy %r1,%r4
2215 bv %r0(%r25) /* r5 */
2216 copy %r1,%r5
2217 bv %r0(%r25) /* r6 */
2218 copy %r1,%r6
2219 bv %r0(%r25) /* r7 */
2220 copy %r1,%r7
2221 bv %r0(%r25) /* r8 */
2222 copy %r1,%r8
2223 bv %r0(%r25) /* r9 */
2224 copy %r1,%r9
2225 bv %r0(%r25) /* r10 */
2226 copy %r1,%r10
2227 bv %r0(%r25) /* r11 */
2228 copy %r1,%r11
2229 bv %r0(%r25) /* r12 */
2230 copy %r1,%r12
2231 bv %r0(%r25) /* r13 */
2232 copy %r1,%r13
2233 bv %r0(%r25) /* r14 */
2234 copy %r1,%r14
2235 bv %r0(%r25) /* r15 */
2236 copy %r1,%r15
2237 bv %r0(%r25) /* r16 */
2238 copy %r1,%r16
2239 bv %r0(%r25) /* r17 */
2240 copy %r1,%r17
2241 bv %r0(%r25) /* r18 */
2242 copy %r1,%r18
2243 bv %r0(%r25) /* r19 */
2244 copy %r1,%r19
2245 bv %r0(%r25) /* r20 */
2246 copy %r1,%r20
2247 bv %r0(%r25) /* r21 */
2248 copy %r1,%r21
2249 bv %r0(%r25) /* r22 */
2250 copy %r1,%r22
2251 bv %r0(%r25) /* r23 */
2252 copy %r1,%r23
2253 bv %r0(%r25) /* r24 */
2254 copy %r1,%r24
2255 bv %r0(%r25) /* r25 */
2256 copy %r1,%r25
2257 bv %r0(%r25) /* r26 */
2258 copy %r1,%r26
2259 bv %r0(%r25) /* r27 */
2260 copy %r1,%r27
2261 bv %r0(%r25) /* r28 */
2262 copy %r1,%r28
2263 bv %r0(%r25) /* r29 */
2264 copy %r1,%r29
2265 bv %r0(%r25) /* r30 */
2266 copy %r1,%r30
2267 bv %r0(%r25) /* r31 */
2268 copy %r1,%r31
f39cce65 2269ENDPROC_CFI(set_register)
c5e76552 2270