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