Home | History | Annotate | Line # | Download | only in hppa
      1 /*	$NetBSD: locore.S,v 1.8 2026/08/21 14:01:16 tls Exp $	*/
      2 /*	$OpenBSD: locore.S,v 1.158 2008/07/28 19:08:46 miod Exp $	*/
      3 
      4 /*
      5  * Copyright (c) 1998-2004 Michael Shalayeff
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
     21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     26  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     27  * THE POSSIBILITY OF SUCH DAMAGE.
     28  *
     29  * Portitions of this file are derived from other sources, see
     30  * the copyrights and acknowledgements below.
     31  */
     32 /*
     33  * Copyright (c) 1990,1991,1992,1994 The University of Utah and
     34  * the Computer Systems Laboratory (CSL).  All rights reserved.
     35  *
     36  * THE UNIVERSITY OF UTAH AND CSL PROVIDE THIS SOFTWARE IN ITS "AS IS"
     37  * CONDITION, AND DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
     38  * WHATSOEVER RESULTING FROM ITS USE.
     39  *
     40  * CSL requests users of this software to return to csl-dist (at) cs.utah.edu any
     41  * improvements that they make and grant CSL redistribution rights.
     42  *
     43  *	Utah $Hdr: locore.s 1.62 94/12/15$
     44  */
     45 /*
     46  *  (c) Copyright 1988 HEWLETT-PACKARD COMPANY
     47  *
     48  *  To anyone who acknowledges that this file is provided "AS IS"
     49  *  without any express or implied warranty:
     50  *      permission to use, copy, modify, and distribute this file
     51  *  for any purpose is hereby granted without fee, provided that
     52  *  the above copyright notice and this notice appears in all
     53  *  copies, and that the name of Hewlett-Packard Company not be
     54  *  used in advertising or publicity pertaining to distribution
     55  *  of the software without specific, written prior permission.
     56  *  Hewlett-Packard Company makes no representations about the
     57  *  suitability of this software for any purpose.
     58  */
     59 
     60 #include "opt_cputype.h"
     61 #include "opt_ddb.h"
     62 #include "opt_hppa_fpu.h"
     63 #include "opt_kgdb.h"
     64 #include "opt_multiprocessor.h"
     65 
     66 #include <sys/errno.h>
     67 #include <machine/param.h>
     68 #include <machine/asm.h>
     69 #include <machine/psl.h>
     70 #include <machine/trap.h>
     71 #include <machine/iomod.h>
     72 #include <machine/pdc.h>
     73 #include <machine/reg.h>
     74 #include <machine/cpu.h>
     75 
     76 #include "assym.h"
     77 
     78 /* Some aliases for the macros in assym.h. */
     79 #define	TRAPFRAME_SIZEOF	trapframe_SIZEOF
     80 
     81 /*
     82  * Very crude debugging macros that write to com1.
     83  */
     84 
     85 #if 1
     86 #define	COM1_TX_REG	(0xffd00000 + 0x5000 + 0x800)
     87 #else
     88 #define	COM1_TX_REG	(0xf0823000 + 0x800)
     89 #endif
     90 #define _DEBUG_PUTCHAR(reg1, reg2)		! \
     91 	ldil	L%COM1_TX_REG, %reg1		! \
     92 	stb	%reg2, R%COM1_TX_REG(%sr1, %reg1) ! \
     93 	ldil	L%10000000, %reg1		! \
     94 	ldi	1, %reg2			! \
     95 	comb,<>,n	%reg1, %r0, -8		! \
     96 	sub	%reg1, %reg2, %reg1
     97 #define DEBUG_PUTCHAR(reg1, reg2, ch)		! \
     98 	ldi	ch, %reg2			! \
     99 	_DEBUG_PUTCHAR(reg1,reg2)
    100 #define _DEBUG_DUMPN(reg1, reg2, reg3, p)	! \
    101 	extru	%reg3, p, 4, %reg2		! \
    102 	comib,>>,n	10, %reg2, 0		! \
    103 	addi	39, %reg2, %reg2		! \
    104 	addi	48, %reg2, %reg2		! \
    105 	_DEBUG_PUTCHAR(reg1,reg2)
    106 #define DEBUG_DUMP32(reg1, reg2, reg3)		! \
    107 	DEBUG_PUTCHAR(reg1,reg2,58)		! \
    108 	_DEBUG_DUMPN(reg1, reg2, reg3, 3)	! \
    109 	_DEBUG_DUMPN(reg1, reg2, reg3, 7)	! \
    110 	_DEBUG_DUMPN(reg1, reg2, reg3, 11)	! \
    111 	_DEBUG_DUMPN(reg1, reg2, reg3, 15)	! \
    112 	_DEBUG_DUMPN(reg1, reg2, reg3, 19)	! \
    113 	_DEBUG_DUMPN(reg1, reg2, reg3, 23)	! \
    114 	_DEBUG_DUMPN(reg1, reg2, reg3, 27)	! \
    115 	_DEBUG_DUMPN(reg1, reg2, reg3, 31)
    116 
    117 /*
    118  * hv-specific instructions
    119  */
    120 #define	DR_PAGE0	diag (0x70 << 5)
    121 #define	DR_PAGE1	diag (0x72 << 5)
    122 
    123 #define	MTCPU_T(x,t)	diag ((t) << 21) | ((x) << 16) | (0xb0 << 5)
    124 #define	MFCPU_T(r,x)	diag ((r) << 21) | ((x) << 16) | (0xd0 << 5)
    125 #define	MTCPU_C(x,t)	diag ((t) << 21) | ((x) << 16) | (0x12 << 5)
    126 #define	MFCPU_C(r,x)	diag ((r) << 21) | ((x) << 16) | (0x30 << 5)
    127 #define	MFCPU_U(r,x)	diag ((r) << 21) | ((x))       | (0x45 << 5)
    128 #define	MTCPU_U(x,r)	diag ((r) << 21) | ((x) << 16) | (0xc2 << 5)
    129 
    130 	.import	$global$, data
    131 	.import	boothowto, data
    132 	.import	bootdev, data
    133 	.import	esym, data
    134 	.import virtual_avail, data
    135 	.import	lwp0, data
    136 	.import	panic, code
    137 	.import fpu_csw, data
    138 	.import hppa_interrupt_register, data
    139 
    140 	BSS(pdc_stack, 4)	/* temp stack for PDC call */
    141 	BSS(kernelmapped, 4)	/* set when kernel is mapped */
    142 	BSS(hppa_vtop, 4)	/* a vtop translation table addr (pa=va) */
    143 
    144 	.text
    145 	.import kernel_setup, entry
    146 
    147 /*
    148  * This is the starting location for the kernel
    149  */
    150 ENTRY_NOPROFILE(start,0)
    151 /*
    152  *	bootapiver <= 2
    153  *		start(pdc, boothowto, bootdev, esym, bootapiver, argv, argc)
    154  *
    155  *	bootapiver == 3
    156  *		start(pdc, boothowto, bootdev, esym, bootapiver, bootinfo)
    157  *
    158  *	bootapiver == start
    159  *		qemu/seabios-hppa
    160  *
    161  *	pdc - PDC entry point
    162  *	boothowto - boot flags (see "reboot.h")
    163  *	bootdev - boot device (index into bdevsw)
    164  *	esym - end of symbol table (or &end if not present)
    165  *	bootapiver - /boot API version
    166  *	argv - options block passed from /boot
    167  *	argc - the length of the block
    168  *	bootinfo - pointer to a struct bootinfo.
    169  */
    170 
    171 	ldil	L%start, %r1
    172 	ldo	R%start(%r1), %r1
    173 	ldw	HPPA_FRAME_ARG(4)(%sp), %t1
    174 	copy	%r0, %r5
    175 	comb,=	%r1, %t1, .Lseabios
    176 	 nop
    177 
    178 	/*
    179 	 * save the boothowto, bootdev and esym arguments
    180 	 * don't save pdc - it's unused before pdc_init which
    181 	 * gets it from PAGE0
    182 	 */
    183 	ldil	L%boothowto,%r1
    184 	stw	%arg1,R%boothowto(%r1)
    185 	ldil	L%bootdev,%r1
    186 	stw	%arg2,R%bootdev(%r1)
    187 
    188 	/* bootinfo struct address for hppa_init, if bootapiver (%t1) is > 2 */
    189 	ldw	HPPA_FRAME_ARG(5)(%sp), %r5
    190 	comiclr,< 2, %t1, %r0
    191 	copy	%r0, %r5
    192 
    193 	comb,<>	%r0, %arg3, 1f
    194 	 nop
    195 
    196 .Lseabios:
    197 	ldil	L%end, %arg3
    198 	ldo	R%end(%arg3), %arg3
    199 
    200 1:
    201 	ldil	L%esym,%r1
    202 	stw	%arg3,R%esym(%r1)
    203 
    204 	/*
    205 	 * Put page aligned %arg3 into %t3. It is the start of available
    206 	 * memory.
    207 	 */
    208 	ldo	NBPG-1(%arg3), %t3
    209 	dep	%r0, 31, PGSHIFT, %t3
    210 
    211 	/* assuming size being page-aligned */
    212 #define STACK_ALLOC(n,s)		\
    213 	ldil	L%(n), %t1		! \
    214 	ldil	L%(s), %t2		! \
    215 	stw	%t3, R%(n)(%t1)		! \
    216 	add	%t3, %t2, %t3
    217 
    218 	STACK_ALLOC(pdc_stack, PDC_STACKSIZE)
    219 
    220 	/* zero fake trapframe and lwp0 u-area */
    221 	/* XXX - we should create a real trapframe for lwp0 */
    222 	copy	%t3, %t2
    223 	ldi	NBPG+TRAPFRAME_SIZEOF, %t1
    224 L$start_zero_tf:
    225 	stws,ma %r0, 4(%t2)
    226 	addib,>= -8, %t1, L$start_zero_tf
    227 	stws,ma %r0, 4(%t2)	/* XXX could use ,bc here, but gas is broken */
    228 
    229 	/*
    230 	 * kernel stack starts a page and a trapframe above uarea address.
    231 	 */
    232 	ldo	NBPG+TRAPFRAME_SIZEOF(%t3), %sp
    233 	mtctl	%t3, CR_FPPADDR
    234 
    235 	/* initialize the pcb */
    236 	stw	%r0, PCB_ONFAULT(%t3)
    237 	stw	%r0, PCB_SPACE(%t3)	/* XXX HPPA_SID_KERNEL == 0 */
    238 
    239 	/*
    240 	 * Setup various pointers.
    241 	 *
    242 	 * First free memory is %t3 plus normal U space. The last page of
    243 	 * USPACE is the redzone if DIAGNOSTIC (see param.h).
    244 	 */
    245 	ldil	L%USPACE, %r4
    246 	add	%t3, %r4, %r4
    247 
    248 	ldil	L%lwp0, %t2
    249 	stw	%t3, R%lwp0+L_PCB(%t2)		/* XXXuvm_lwp_getuarea */
    250 	ldo	NBPG(%t3), %t1
    251 	stw	%t1, R%lwp0+L_MD_REGS(%t2)
    252 
    253 	ldil	L%TFF_LAST, %t1
    254 	stw	%t1, TF_FLAGS-TRAPFRAME_SIZEOF(%sp)
    255 	stw	%t3, TF_CR30-TRAPFRAME_SIZEOF(%sp)
    256 
    257 	/*
    258 	 * disable all coprocessors
    259 	 */
    260 	mtctl	%r0, CR_CCR
    261 
    262 #ifdef MULTIPROCESSOR
    263 
    264 #define	PZ_MEM_RENDEZ		0x10
    265 #define	PZ_MEM_RENDEZ_HI	0x28
    266 
    267 	/* Setup SMP rendezvous address. */
    268 	ldil	L%hw_cpu_spinup_trampoline, %r1
    269 	ldo	R%hw_cpu_spinup_trampoline(%r1), %r1
    270 	stw	%r1, PZ_MEM_RENDEZ(%r0)
    271 	stw	%r0, PZ_MEM_RENDEZ_HI(%r0)
    272 #endif
    273 
    274 	/*
    275 	 * We need to set the Q bit so that we can take TLB misses after we
    276 	 * turn on virtual memory.
    277 	 */
    278 	copy	%sp, %arg0
    279 	ldil	L%qisnowon, %rp
    280 	ldo	R%qisnowon(%rp), %rp
    281 
    282 	b	kernel_setup
    283 	ldi	PSW_Q|PSW_I, %arg1
    284 
    285 qisnowon:
    286 	copy	%r4, %arg0
    287 	copy	%r5, %arg1
    288 	/*
    289 	 * call C routine hppa_init() to initialize VM
    290 	 */
    291 	.import hppa_init, code
    292 	CALL(hppa_init, %r1)
    293 
    294 	/*
    295 	 * Cannot change the queues or IPSW with the Q-bit on
    296 	 */
    297 	rsm	RESET_PSW, %r0
    298 	nop ! nop ! nop ! nop ! nop ! nop ! nop
    299 
    300 	/*
    301 	 * We need to do an rfi to get the C bit set
    302 	 */
    303 	mtctl	%r0, %pcsq
    304 	mtctl	%r0, %pcsq
    305 	ldil	L%virtual_mode, %t1
    306 	ldo	R%virtual_mode(%t1), %t1
    307 	mtctl	%t1, %pcoq
    308 	ldo	4(%t1), %t1
    309 	mtctl	%t1, %pcoq
    310 	GET_CURCPU(%t1)
    311 	ldw	CI_PSW(%t1), %t2
    312 	mtctl	%t2, %ipsw
    313 	rfi
    314 	nop
    315 	nop
    316 	nop
    317 	nop
    318 	nop
    319 	nop
    320 	nop
    321 
    322 virtual_mode:
    323 
    324 	ldil	L%kernelmapped, %t1
    325 	stw	%t1, R%kernelmapped(%t1)
    326 
    327 #ifdef DDB
    328 	.import	Debugger, code
    329 	/* have to call debugger from here, from virtual mode */
    330 	ldil	L%boothowto, %r1
    331 	ldw	R%boothowto(%r1), %r1
    332 	bb,>=	%r1, 25, L$noddb
    333 	nop
    334 
    335 	break	HPPA_BREAK_KERNEL, HPPA_BREAK_KGDB
    336 	nop
    337 L$noddb:
    338 #endif
    339 
    340 	.import main,code
    341 	CALL(main, %r1)
    342 	/* should never return... */
    343 	bv	(%rp)
    344 	nop
    345 EXIT(start)
    346 
    347 
    348 /*
    349  * void kernel_setup(register_t sp, register_t psw)
    350  */
    351 LEAF_ENTRY_NOPROFILE(kernel_setup)
    352 
    353 	/*
    354 	 * disable interrupts and turn off all bits in the psw so that
    355 	 * we start in a known state.
    356 	 */
    357 	rsm	RESET_PSW, %r0
    358 	nop ! nop ! nop ! nop ! nop ! nop
    359 
    360 	/*
    361 	 * go to virtual mode...
    362 	 * get things ready for the kernel to run in virtual mode
    363 	 */
    364 	ldi	HPPA_PID_KERNEL, %r1
    365 	mtctl	%r1, %pidr1
    366 	mtctl	%r1, %pidr2
    367 #if pbably_not_worth_it
    368 	mtctl	%r0, %pidr3
    369 	mtctl	%r0, %pidr4
    370 #endif
    371 	mtsp	%r0, %sr0
    372 	mtsp	%r0, %sr1
    373 	mtsp	%r0, %sr2
    374 	mtsp	%r0, %sr3
    375 	mtsp	%r0, %sr4
    376 	mtsp	%r0, %sr5
    377 	mtsp	%r0, %sr6
    378 	mtsp	%r0, %sr7
    379 
    380 	/*
    381 	 * to keep the spl() routines consistent we need to put the correct
    382 	 * spl level into eiem, and reset any pending interrupts
    383 	 */
    384 	ldi	-1, %r1
    385 	mtctl	%r0, %eiem		/* disable interrupts */
    386 	mtctl	%r1, %eirr
    387 
    388 	/*
    389 	 * load address of interrupt vector table
    390 	 */
    391 	ldil	L%ivaaddr, %t2
    392 	ldo	R%ivaaddr(%t2), %t2
    393 	mtctl	%t2, %iva
    394 
    395 	/*
    396 	 * set up the dp pointer so that we can do quick references off of it
    397 	 */
    398 	ldil	L%$global$, %dp
    399 	ldo	R%$global$(%dp), %dp
    400 
    401 	/*
    402 	 * Create a stack frame for us to call C with. Clear out the previous
    403 	 * sp marker to mark that this is the first frame on the stack.
    404 	 */
    405 	copy	%arg0, %sp
    406 	ldo	0(%arg0), %r3
    407 	stw,ma	%r0, HPPA_FRAME_SIZE(%sp)
    408 	stw	%r0, HPPA_FRAME_CRP(%sp)
    409 	stw	%r0, HPPA_FRAME_PSP(%sp)
    410 
    411 	/*
    412 	 * We need to set the Q bit so that we can take TLB misses after we
    413 	 * turn on virtual memory.
    414 	 */
    415 
    416 	mtctl	%r0, %pcsq
    417 	mtctl	%r0, %pcsq
    418 	mtctl	%rp, %pcoq
    419 	ldo	4(%rp), %rp
    420 	mtctl	%rp, %pcoq
    421 	mtctl	%arg1, %ipsw
    422 	rfi
    423 	nop
    424 	nop
    425 EXIT(kernel_setup)
    426 
    427 
    428 #ifdef MULTIPROCESSOR
    429 /*
    430  * Trampoline to spin up secondary processors.
    431  */
    432 LEAF_ENTRY_NOPROFILE(hw_cpu_spinup_trampoline)
    433 
    434 	/*
    435 	 * disable interrupts and turn off all bits in the psw so that
    436 	 * we start in a known state.
    437 	 */
    438 	rsm	RESET_PSW, %r0
    439 	nop ! nop ! nop ! nop ! nop ! nop
    440 
    441 	/* go to virtual mode...
    442 	/* get things ready for the kernel to run in virtual mode */
    443 	ldi	HPPA_PID_KERNEL, %r1
    444 	mtctl	%r1, %pidr1
    445 	mtctl	%r1, %pidr2
    446 #if pbably_not_worth_it
    447 	mtctl	%r0, %pidr3
    448 	mtctl	%r0, %pidr4
    449 #endif
    450 	mtsp	%r0, %sr0
    451 	mtsp	%r0, %sr1
    452 	mtsp	%r0, %sr2
    453 	mtsp	%r0, %sr3
    454 	mtsp	%r0, %sr4
    455 	mtsp	%r0, %sr5
    456 	mtsp	%r0, %sr6
    457 	mtsp	%r0, %sr7
    458 
    459 	/*
    460 	 * disable all coprocessors
    461 	 */
    462 	mtctl   %r0, CR_CCR
    463 
    464 	/*
    465 	 * to keep the spl() routines consistent we need to put the correct
    466 	 * spl level into eiem, and reset any pending interrupts
    467 	 */
    468 	ldi	-1, %r1
    469 	mtctl	%r0, %eiem		/* disable interrupts */
    470 	mtctl	%r1, %eirr
    471 
    472 	/*
    473 	 * load address of interrupt vector table
    474 	 */
    475 	ldil	L%ivaaddr, %t2
    476 	ldo	R%ivaaddr(%t2), %t2
    477 	mtctl	%t2, %iva
    478 
    479 	/*
    480 	 * set up the dp pointer so that we can do quick references off of it
    481 	 */
    482 	ldil	L%$global$, %dp
    483 	ldo	R%$global$(%dp), %dp
    484 
    485 	/*
    486 	 * Store address of cpu_info in CR_CURCPU.
    487 	 */
    488 	ldil	L%cpu_hatch_info, %r3
    489 	ldw	R%cpu_hatch_info(%r3), %r3
    490 	mtctl	%r3, CR_CURCPU
    491 
    492 	/*
    493 	 * Setup the stack frame for us to call C with and mark this as the
    494 	 * first frame on the stack.
    495 	 */
    496 	ldw	CI_STACK(%r3), %sp
    497 	stw,ma	%r0, HPPA_FRAME_SIZE(%sp)
    498 	stw	%r0, HPPA_FRAME_CRP(%sp)
    499 	stw	%r0, HPPA_FRAME_PSP(%sp)
    500 
    501 	/* Provide CPU with page tables. */
    502 	ldil	L%hppa_vtop, %t1
    503 	ldw	R%hppa_vtop(%t1), %t1
    504 	mtctl	%t1, CR_VTOP
    505 
    506 	/* Turn on the Q bit so that we can handle TLB traps. */
    507 	ldil	L%qenabled, %t1
    508 	ldo	R%qenabled(%t1), %t1
    509 	mtctl	%r0, %pcsq
    510 	mtctl	%r0, %pcsq
    511 	mtctl	%t1, %pcoq
    512 	ldo	4(%t1), %t1
    513 	mtctl	%t1, %pcoq
    514 	ldi	PSW_Q|PSW_I, %t2
    515 	mtctl	%t2, %ipsw
    516 	rfi
    517 	nop
    518 
    519 qenabled:
    520 	/* Call C routine to setup CPU. */
    521 	.import cpu_hw_init, code
    522 	CALL(cpu_hw_init, %r1)
    523 
    524 	/* Switch CPU mode. */
    525 	ldil	L%cpu_spinup_vm, %t1
    526 	ldo	R%cpu_spinup_vm(%t1), %t1
    527 	mtctl	%r0, %pcsq
    528 	mtctl	%r0, %pcsq
    529 	mtctl	%t1, %pcoq
    530 	ldo	4(%t1), %t1
    531 	mtctl	%t1, %pcoq
    532 	mfctl	CR_CURCPU, %t2
    533 	ldw	CI_PSW(%t2), %t2
    534 	mtctl	%t2, %ipsw
    535 	rfi
    536 	nop
    537 
    538 cpu_spinup_vm:
    539 
    540 	/*
    541 	 * Okay, time to return to the land of C.
    542 	 */
    543 	b	cpu_hatch
    544 	nop
    545 
    546 EXIT(hw_cpu_spinup_trampoline)
    547 #endif
    548 
    549 
    550 /*
    551  * int pdc_call(iodcio_t func,int pdc_flag, ...)
    552  */
    553 ENTRY(pdc_call,160)
    554 
    555 	mfctl	%eiem, %t1
    556 	mtctl	%r0, %eiem		/* disable interrupts */
    557 	stw	%rp, HPPA_FRAME_CRP(%sp)
    558 	copy	%arg0, %r31
    559 	copy	%sp, %ret1
    560 
    561 	ldil	L%kernelmapped, %ret0
    562 	ldw	R%kernelmapped(%ret0), %ret0
    563 	comb,=	%r0, %ret0, pdc_call_unmapped1
    564 	nop
    565 
    566 	ldil	L%pdc_stack, %ret1
    567 	ldw	R%pdc_stack(%ret1), %ret1
    568 
    569 pdc_call_unmapped1:
    570 	copy	%sp, %r1
    571 	ldo	HPPA_FRAME_SIZE+24*4(%ret1), %sp
    572 
    573 	stw	%r1, HPPA_FRAME_PSP(%sp)
    574 
    575 	/* save kernelmapped and eiem */
    576 	stw	%ret0, HPPA_FRAME_ARG(21)(%sp)
    577 	stw	%t1, HPPA_FRAME_ARG(22)(%sp)
    578 
    579 	/* copy arguments */
    580 	copy	%arg2, %arg0
    581 	copy	%arg3, %arg1
    582 	ldw	HPPA_FRAME_ARG(4)(%r1), %arg2
    583 	ldw	HPPA_FRAME_ARG(5)(%r1), %arg3
    584 	ldw	HPPA_FRAME_ARG(6)(%r1), %t1
    585 	ldw	HPPA_FRAME_ARG(7)(%r1), %t2
    586 	ldw	HPPA_FRAME_ARG(8)(%r1), %t3
    587 	ldw	HPPA_FRAME_ARG(9)(%r1), %t4
    588 	stw	%t1, HPPA_FRAME_ARG(4)(%sp)	/* XXX can use ,bc */
    589 	stw	%t2, HPPA_FRAME_ARG(5)(%sp)
    590 	stw	%t3, HPPA_FRAME_ARG(6)(%sp)
    591 	stw	%t4, HPPA_FRAME_ARG(7)(%sp)
    592 	ldw	HPPA_FRAME_ARG(10)(%r1), %t1
    593 	ldw	HPPA_FRAME_ARG(11)(%r1), %t2
    594 	ldw	HPPA_FRAME_ARG(12)(%r1), %t3
    595 	ldw	HPPA_FRAME_ARG(13)(%r1), %t4
    596 	stw	%t1, HPPA_FRAME_ARG(8)(%sp)
    597 	stw	%t2, HPPA_FRAME_ARG(9)(%sp)
    598 	stw	%t3, HPPA_FRAME_ARG(10)(%sp)
    599 	stw	%t4, HPPA_FRAME_ARG(11)(%sp)
    600 
    601 	/* save temp control regs */
    602 	mfctl	%cr24, %t1
    603 	mfctl	%cr25, %t2
    604 	mfctl	%cr26, %t3
    605 	mfctl	%cr27, %t4
    606 	stw	%t1, HPPA_FRAME_ARG(12)(%sp)	/* XXX can use ,bc */
    607 	stw	%t2, HPPA_FRAME_ARG(13)(%sp)
    608 	stw	%t3, HPPA_FRAME_ARG(14)(%sp)
    609 	stw	%t4, HPPA_FRAME_ARG(15)(%sp)
    610 	mfctl	%cr28, %t1
    611 	mfctl	%cr29, %t2
    612 	mfctl	%cr30, %t3
    613 	mfctl	%cr31, %t4
    614 	stw	%t1, HPPA_FRAME_ARG(16)(%sp)
    615 	stw	%t2, HPPA_FRAME_ARG(17)(%sp)
    616 	stw	%t3, HPPA_FRAME_ARG(18)(%sp)
    617 	stw	%t4, HPPA_FRAME_ARG(19)(%sp)
    618 
    619 	comb,=	%r0, %ret0, pdc_call_unmapped2
    620 	nop
    621 
    622 	copy	%arg0, %t4
    623 	ldi	PSW_Q, %arg0 /* (!pdc_flag && args[0] == PDC_PIM)? PSW_M:0) */
    624 	break	HPPA_BREAK_KERNEL, HPPA_BREAK_SET_PSW
    625 	nop
    626 	stw	%ret0, HPPA_FRAME_ARG(23)(%sp)
    627 	copy	%t4, %arg0
    628 
    629 pdc_call_unmapped2:
    630 	.call
    631 	blr	%r0, %rp
    632 	bv,n	(%r31)
    633 	nop
    634 
    635 	/* load temp control regs */
    636 	ldw	HPPA_FRAME_ARG(12)(%sp), %t1
    637 	ldw	HPPA_FRAME_ARG(13)(%sp), %t2
    638 	ldw	HPPA_FRAME_ARG(14)(%sp), %t3
    639 	ldw	HPPA_FRAME_ARG(15)(%sp), %t4
    640 	mtctl	%t1, %cr24
    641 	mtctl	%t2, %cr25
    642 	mtctl	%t3, %cr26
    643 	mtctl	%t4, %cr27
    644 	ldw	HPPA_FRAME_ARG(16)(%sp), %t1
    645 	ldw	HPPA_FRAME_ARG(17)(%sp), %t2
    646 	ldw	HPPA_FRAME_ARG(18)(%sp), %t3
    647 	ldw	HPPA_FRAME_ARG(19)(%sp), %t4
    648 	mtctl	%t1, %cr28
    649 	mtctl	%t2, %cr29
    650 	mtctl	%t3, %cr30
    651 	mtctl	%t4, %cr31
    652 
    653 	ldw	HPPA_FRAME_ARG(21)(%sp), %t1
    654 	ldw	HPPA_FRAME_ARG(22)(%sp), %t2
    655 	comb,=	%r0, %t1, pdc_call_unmapped3
    656 	nop
    657 
    658 	copy	%ret0, %t3
    659 	ldw	HPPA_FRAME_ARG(23)(%sp), %arg0
    660 	break	HPPA_BREAK_KERNEL, HPPA_BREAK_SET_PSW
    661 	nop
    662 	copy	%t3, %ret0
    663 
    664 pdc_call_unmapped3:
    665 	ldw	HPPA_FRAME_PSP(%sp), %sp
    666 	ldw	HPPA_FRAME_CRP(%sp), %rp
    667 	bv	%r0(%rp)
    668 	 mtctl	%t2, %eiem		/* enable interrupts */
    669 EXIT(pdc_call)
    670 
    671 /*
    672  * int splraise(int ncpl);
    673  */
    674 LEAF_ENTRY(splraise)
    675 	GET_CURCPU(%t1)
    676 	sh2addl	%arg0, %t1, %arg0
    677 	ldw	CI_IMASK(%arg0), %arg0
    678 	ldw	CI_CPL(%t1), %ret0
    679 	or	%ret0, %arg0, %arg0
    680 	bv	%r0(%rp)
    681 	stw	%arg0, CI_CPL(%t1)
    682 EXIT(splraise)
    683 
    684 /*
    685  * int spllower(int ncpl);
    686  */
    687 ENTRY(spllower,HPPA_FRAME_SIZE)
    688 	GET_CURCPU(%t1)
    689 
    690 	ldw	CI_IPENDING(%t1), %r1	; load ipending
    691 	andcm,<> %r1, %arg0, %r1	; and with complement of new cpl
    692 	bv	%r0(%rp)
    693 	stw	%arg0, CI_CPL(%t1)	; store new cpl
    694 
    695 	/*
    696 	 * Dispatch interrupts.  There's a chance
    697 	 * that we may end up not dispatching anything;
    698 	 * in between our load of ipending and this
    699 	 * disabling of interrupts, something else may
    700 	 * have come in and dispatched some or all
    701 	 * of what we previously saw in ipending.
    702 	 */
    703 	mfctl	%eiem, %arg1
    704 	mtctl	%r0, %eiem		; disable interrupts
    705 
    706 	ldw	CI_IPENDING(%t1), %r1	; load ipending
    707 	andcm,<> %r1, %arg0, %r1	; and with complement of new cpl
    708 	b,n	spllower_out		; branch if we got beaten
    709 
    710 spllower_dispatch:
    711 	/* start stack calling convention */
    712 	stw	%rp, HPPA_FRAME_CRP(%sp)
    713 	copy	%r3, %r1
    714 	copy	%sp, %r3
    715 	stw,ma	%r1, HPPA_FRAME_SIZE(%sp)
    716 
    717 	/* save ncpl and %eiem */
    718 	stw	%arg0, HPPA_FRAME_ARG(0)(%r3)
    719 	stw	%arg1, HPPA_FRAME_ARG(1)(%r3)
    720 
    721 	/* call hppa_intr_dispatch */
    722 	ldil	L%hppa_intr_dispatch, %r1
    723 	ldo	R%hppa_intr_dispatch(%r1), %r1
    724 	blr	%r0, %rp
    725 	.call
    726 	bv	%r0(%r1)
    727 	copy	%r0, %arg2		; call with a NULL frame
    728 
    729 	/* restore %eiem, we don't need ncpl */
    730 	ldw	HPPA_FRAME_ARG(1)(%r3), %arg1
    731 
    732 	/* end stack calling convention */
    733 	ldw	HPPA_FRAME_CRP(%r3), %rp
    734 	ldo	HPPA_FRAME_SIZE(%r3), %sp
    735 	ldw,mb	-HPPA_FRAME_SIZE(%sp), %r3
    736 
    737 spllower_out:
    738 	/*
    739 	 * Now return, storing %eiem in the delay slot.
    740 	 * (hppa_intr_dispatch leaves it zero).  I think
    741 	 * doing this in the delay slot is important to
    742 	 * prevent recursion, but I might be being too
    743 	 * paranoid.
    744 	 */
    745 	bv	%r0(%rp)
    746 	mtctl	%arg1, %eiem
    747 EXIT(spllower)
    748 
    749 /*
    750  * void hppa_intr_schedule(int mask);
    751  */
    752 ENTRY(hppa_intr_schedule,0)
    753 	GET_CURCPU(%t2)
    754 	mfctl	%eiem, %arg1
    755 	mtctl	%r0, %eiem			; disable interrupts
    756 	ldw	CI_IPENDING(%t2), %r1		; load ipending
    757 	or	%r1, %arg0, %r1			; or in mask
    758 	stw	%r1, CI_IPENDING(%t2)		; store ipending
    759 	ldw	CI_CPL(%t2), %arg0		; load cpl
    760 	andcm,= %r1, %arg0, %r1			; and ipending with ~cpl
    761 	b,n	spllower_dispatch		; dispatch if we can
    762 	bv	%r0(%rp)
    763 	mtctl	%arg1, %eiem
    764 EXIT(hppa_intr_schedule)
    765 
    766 /*
    767  * void cpu_die(void);
    768  */
    769 LEAF_ENTRY_NOPROFILE(cpu_die)
    770 	rsm	RESET_PSW, %r0
    771 	nop
    772 	nop
    773 	mtsp	%r0, %sr0
    774 	ldil	L%LBCAST_ADDR, %r25
    775 	ldi	CMD_RESET, %r26
    776 	stw	%r26, R%iomod_command(%r25)
    777 forever:				; Loop until bus reset takes effect.
    778 	b,n	forever
    779 	nop
    780 	nop
    781 EXIT(cpu_die)
    782 
    783 /* Include the system call and trap handling. */
    784 #include <hppa/hppa/trap.S>
    785 
    786 /* Include the userspace copyin/copyout functions. */
    787 #include <hppa/hppa/copy.S>
    788 
    789 /* Include the support functions. */
    790 #include <hppa/hppa/support.S>
    791 
    792 /*
    793  * struct lwp *
    794  * cpu_switchto(struct lwp *oldl, struct lwp *newl, bool returning)
    795  */
    796 	.align	32
    797 ENTRY(cpu_switchto,128)
    798 	/* start stack calling convention */
    799 	stw	%rp, HPPA_FRAME_CRP(%sp)
    800 	copy	%r3, %r1
    801 	copy	%sp, %r3
    802 	stwm	%r1, HPPA_FRAME_SIZE+16*4(%sp)
    803 					/* Frame marker and callee saves */
    804 	stw	%r3, HPPA_FRAME_PSP(%sp)
    805 
    806 #ifdef DIAGNOSTIC
    807 	b,n	switch_diag
    808 
    809 switch_error:
    810 	copy	%t1, %arg1
    811 	ldil	L%panic, %r1
    812 	ldil	L%Lcspstr, %arg0
    813 	ldo	R%panic(%r1), %r1
    814 	ldo	R%Lcspstr(%arg0), %arg0
    815 	.call
    816 	blr	%r0, %rp
    817 	bv,n	%r0(%r1)
    818 	nop
    819 Lcspstr:
    820 	.asciz	"cpu_switchto: 0x%08x stack/len 0x%08x"
    821 	.align	8
    822 
    823 switch_diag:
    824 	/*
    825 	 * Either we must be switching to the same LWP, or
    826 	 * the new LWP's kernel stack must be reasonable.
    827 	 */
    828 	comb,=,n %arg0, %arg1, kstack_ok
    829 
    830 	/*
    831 	 * cpu_lwp_fork sets the initial stack to a page above uarea address.
    832 	 * Check that the stack is above this value for oldl.
    833 	 */
    834 	ldw	L_PCB(%arg1), %arg2
    835 	ldw	PCB_KSP(%arg2), %t1		/* t1 for switch_error */
    836 	ldo	NBPG(%arg2), %arg2
    837 	comb,>>,n %arg2, %t1, switch_error
    838 	nop
    839 
    840 	/* make sure the stack hasn't grown too big (> USPACE) */
    841 	sub	%t1, %arg2, %t1			/* t1 for switch_error */
    842 	ldil	L%USPACE, %arg2
    843 	ldo	R%USPACE(%arg2), %arg2
    844 	comb,<<=,n %arg2, %t1, switch_error
    845 	nop
    846 kstack_ok:
    847 #endif
    848 
    849 	/*
    850 	 * save old LWP context
    851 	 *
    852 	 * arg0: old LWP (oldl)
    853 	 * arg1: new LWP (newl)
    854 	 */
    855 
    856 	ldw	L_PCB(%arg0), %t3	/* oldl pcb */
    857 	stw	%sp, PCB_KSP(%t3)
    858 	fdc	%r0(%t3)		/* flush oldl pcb  - surely fdc PCB_KSP(%t3) */
    859 
    860 	/*
    861 	 * Save the callee-save registers. We don't need to do
    862 	 * r3 here as it was done during stack calling convention.
    863 	 */
    864 	stw	%r4,   1*4(%r3)
    865 	stw	%r5,   2*4(%r3)
    866 	stw	%r6,   3*4(%r3)
    867 	stw	%r7,   4*4(%r3)
    868 	stw	%r8,   5*4(%r3)
    869 	stw	%r9,   6*4(%r3)
    870 	stw	%r10,  7*4(%r3)
    871 	stw	%r11,  8*4(%r3)
    872 	stw	%r12,  9*4(%r3)
    873 	stw	%r13, 10*4(%r3)
    874 	stw	%r14, 11*4(%r3)
    875 	stw	%r15, 12*4(%r3)
    876 	stw	%r16, 13*4(%r3)
    877 	stw	%r17, 14*4(%r3)
    878 	stw	%r18, 15*4(%r3)
    879 
    880 	/*
    881 	 * restore new LWP context
    882 	 *
    883 	 * arg0: old LWP (oldl)
    884 	 * arg1: new LWP (newl)
    885 	 */
    886 	ldw	L_MD(%arg1), %t1
    887 	ldw	L_PCB(%arg1), %t3
    888 	ldw	PCB_KSP(%t3), %sp		/* restore stack of newl */
    889 
    890 	fdc	%r0(%t3)			/* Flush newl PCB - why? */
    891 
    892 #if 0
    893 	ldw	TF_CR9(%t1), %t3		/* pmap_activate? */
    894 	mtctl	%t3, %pidr2			/* pmap_activate? */
    895 #endif
    896 	ldw	TF_CR30(%t1), %t2		/* pmap_activate? */
    897 	mtctl	%t2, CR_FPPADDR			/* pmap_activate? */
    898 
    899 	SET_CURLWP(%arg1, %t2)
    900 
    901 	ldo	-(HPPA_FRAME_SIZE+16*4)(%sp), %r3
    902 
    903 	ldw	 1*4(%r3), %r4
    904 	ldw	 2*4(%r3), %r5
    905 	ldw	 3*4(%r3), %r6
    906 	ldw	 4*4(%r3), %r7
    907 	ldw	 5*4(%r3), %r8
    908 	ldw	 6*4(%r3), %r9
    909 	ldw	 7*4(%r3), %r10
    910 	ldw	 8*4(%r3), %r11
    911 	ldw	 9*4(%r3), %r12
    912 	ldw	10*4(%r3), %r13
    913 	ldw	11*4(%r3), %r14
    914 	ldw	12*4(%r3), %r15
    915 	ldw	13*4(%r3), %r16
    916 	ldw	14*4(%r3), %r17
    917 	ldw	15*4(%r3), %r18
    918 
    919 	/*
    920 	 * Check for restartable atomic sequences (RAS)
    921 	 */
    922 	ldw	L_PROC(%arg1), %t1
    923 	ldw	P_RASLIST(%t1), %t1
    924 	comb,=,n %r0, %t1, noras
    925 
    926 	/*
    927 	 * Save some caller-saves we want to preserve.
    928 	 *
    929 	 * We save oldl (%arg0) and newl (%arg1) for the benefit of
    930 	 * lwp_trampoline() for when it calls lwp_startup().
    931 	 *
    932 	 * oldl (%arg0) is saved as it's the return value
    933 	 */
    934 	stw	%arg0, HPPA_FRAME_ARG(0)(%r3)		/* oldl */
    935 	stw	%arg1, HPPA_FRAME_ARG(1)(%r3)		/* newl */
    936 
    937 	copy	%arg1, %arg0
    938 
    939 	.import	hppa_ras, code
    940 	CALL(hppa_ras, %r1)
    941 
    942 	/* restore caller-saves */
    943 	ldw	HPPA_FRAME_ARG(1)(%r3), %arg1
    944 	ldw	HPPA_FRAME_ARG(0)(%r3), %arg0
    945 
    946 noras:
    947 
    948 	/*
    949 	 * We do have a hardware FPU.  Two paths: eager
    950 	 * (if selected by kernel config, or if emulation trap broken),
    951 	 * or lazy.
    952 	 */
    953 #ifndef HPPA_FPU_EAGER
    954 	.import fpu_eager, data
    955 	ldil	L%fpu_eager, %t1
    956 	ldw	R%fpu_eager(%t1), %t1
    957 	comib,=,n 0, %t1, L$fpu_lazy
    958 #endif
    959 	/*
    960 	 * Eager path - via C helper
    961 	 */
    962 	stw	%arg0, HPPA_FRAME_ARG(0)(%r3)
    963 	stw	%arg1, HPPA_FRAME_ARG(1)(%r3)
    964 	copy	%arg1, %arg0
    965 	CALL(hppa_fpu_switch, %r1)
    966 	ldw	HPPA_FRAME_ARG(1)(%r3), %arg1
    967 	ldw	HPPA_FRAME_ARG(0)(%r3), %arg0
    968 
    969 #ifndef HPPA_FPU_EAGER
    970 	b,n	switch_return
    971 
    972 	/*
    973 	 * Lazy path.  If the LWP
    974  	 * that we just switched to has its state in the
    975  	 * FPU, enable the FPU, else disable it, so if
    976  	 * the LWP does try to use the coprocessor
    977  	 * we'll get an assist emulation trap to swap
    978  	 * states.
    979  	 */
    980 L$fpu_lazy:
    981 	GET_CURCPU(%t1)
    982 	mfctl	CR_CCR, %r1
    983 	mfctl	CR_FPPADDR, %t2
    984 	ldw	CI_FPU_STATE(%t1), %t1
    985 	depi	0, 25, 2, %r1		; disables the FPU
    986 	comb,<>,n %t1, %t2, 0		; nullify if LWPs different
    987 	depi	3, 25, 2, %r1		; enables the FPU
    988 	mtctl	%r1, CR_CCR
    989 #endif
    990 
    991 switch_return:
    992 	copy	%arg0, %ret0
    993 
    994 	ldw	HPPA_FRAME_CRP(%r3), %rp
    995 	bv	0(%rp)
    996 	ldwm	-(HPPA_FRAME_SIZE+16*4)(%sp), %r3
    997 EXIT(cpu_switchto)
    998 
    999 /*
   1000  * This is the first code run in a new LWP after
   1001  * cpu_switchto() has switched to it for the first time.
   1002  *
   1003  * This happens courtesy of the setup in cpu_lwp_fork() which
   1004  * arranges for cpu_switchto() to call us with a frame containing
   1005  * the first kernel function to call, and its argument.
   1006  *
   1007  * cpu_switchto() also makes sure that %arg0 and %arg1 are (still)
   1008  * oldl and newl respectively.
   1009  */
   1010 ENTRY_NOPROFILE(lwp_trampoline,HPPA_FRAME_SIZE)
   1011 	/* no return point */
   1012 	stw	%r0, HPPA_FRAME_CRP(%sp)
   1013 
   1014 	/* %arg0, %arg1 are still valid from cpu_switchto */
   1015 	.import	lwp_startup, code
   1016 	CALL(lwp_startup, %r1)
   1017 
   1018 	/* get trampoline func (%t3) and arg (%arg0) */
   1019 	ldw	HPPA_FRAME_ARG(3)(%sp), %arg0
   1020 	ldw	HPPA_FRAME_ARG(2)(%sp), %t3
   1021 
   1022 	/* call the first kernel function */
   1023 	.call
   1024 	blr	%r0, %rp
   1025 	bv,n	%r0(%t3)
   1026 	nop
   1027 
   1028 	/*
   1029 	 * Since the first kernel function returned,
   1030 	 * this LWP was created by the fork()
   1031 	 * syscall, which we now return from.
   1032 	 */
   1033 	GET_CURLWP(%t2)
   1034 	.call
   1035 	b	syscall_return
   1036 	ldw	L_MD(%t2), %t3
   1037 EXIT(lwp_trampoline)
   1038 
   1039 /* Include the signal code, used in compat code */
   1040 #include <hppa/hppa/sigcode.S>
   1041 
   1042 	.end
   1043