1/* $OpenBSD: locore.S,v 1.207 2023/12/12 07:37:20 deraadt Exp $ */ 2 3/* 4 * Copyright (c) 1998-2004 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Portitions of this file are derived from other sources, see 29 * the copyrights and acknowledgements below. 30 */ 31/* 32 * (c) Copyright 1988 HEWLETT-PACKARD COMPANY 33 * 34 * To anyone who acknowledges that this file is provided "AS IS" 35 * without any express or implied warranty: 36 * permission to use, copy, modify, and distribute this file 37 * for any purpose is hereby granted without fee, provided that 38 * the above copyright notice and this notice appears in all 39 * copies, and that the name of Hewlett-Packard Company not be 40 * used in advertising or publicity pertaining to distribution 41 * of the software without specific, written prior permission. 42 * Hewlett-Packard Company makes no representations about the 43 * suitability of this software for any purpose. 44 */ 45/* 46 * Copyright (c) 1990,1991,1992,1994 The University of Utah and 47 * the Computer Systems Laboratory (CSL). All rights reserved. 48 * 49 * Permission to use, copy, modify and distribute this software is hereby 50 * granted provided that (1) source code retains these copyright, permission, 51 * and disclaimer notices, and (2) redistributions including binaries 52 * reproduce the notices in supporting documentation, and (3) all advertising 53 * materials mentioning features or use of this software display the following 54 * acknowledgement: ``This product includes software developed by the 55 * Computer Systems Laboratory at the University of Utah.'' 56 * 57 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS 58 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF 59 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 60 * 61 * CSL requests users of this software to return to csl-dist@cs.utah.edu any 62 * improvements that they make and grant CSL redistribution rights. 63 * 64 * Utah $Hdr: locore.s 1.63 95/01/20$ 65 */ 66 67#include <sys/reboot.h> 68#include <machine/param.h> 69#include <machine/asm.h> 70#include <machine/psl.h> 71#include <machine/trap.h> 72#include <machine/iomod.h> 73#include <machine/pdc.h> 74#include <machine/frame.h> 75#include <machine/reg.h> 76#include "assym.h" 77 78/* 79 * hw-specific instructions 80 */ 81 82/* source: mklinux cache.s */ 83#define MFCPU_C_PCXST(r,x) .word 0x14001a00 | ((r) << 21) | ((x) << 16) 84#define MTCPU_PCXST(x,r) .word 0x14001600 | ((r) << 21) | ((x) << 16) 85 86/* source: PCXL and PCXL2 ERS */ 87/* Use MFCPU_C for DR0-8; MFCPU_T for DR25,27,28,29 */ 88#define MFCPU_C_PCXL(r,x) .word 0x14000600 | ((r) << 21) | ((x) << 16) 89#define MFCPU_T_PCXL(r,x) .word 0x14001800 | ((r) << 21) | ((x)) 90#define MTCPU_PCXL(x,r) .word 0x14000240 | ((r) << 21) | ((x) << 16) 91#define DR_PAGE0_PCXL .word 0x14000e00 92#define DR_PAGE1_PCXL .word 0x14000e40 93 94#define MFCPU_PCXU(r,x) .word 0x140008a0 | ((r) << 21) | ((x)) 95#define MTCPU_PCXU(x,r) .word 0x14001840 | ((r) << 21) | ((x) << 16) 96 97 .import $global$, data 98 .import pdc, data 99 .import cpu_info, data 100 .import panic, code 101 102LEAF_ENTRY($kernel_setup) 103 104 /* 105 * disable interrupts and turn off all bits in the psw so that 106 * we start in a known state. 107 */ 108 rsm RESET_PSL, r0 109 nop ! nop ! nop ! nop ! nop ! nop 110 111 /* get things ready for the kernel to run in virtual mode */ 112 ldi HPPA_PID_KERNEL, r1 113 mtctl r1, pidr1 114 mtctl r1, pidr2 115#if pbably_not_worth_it 116 mtctl r0, pidr3 117 mtctl r0, pidr4 118#endif 119 mtsp r0, sr0 120 mtsp r0, sr1 121 mtsp r0, sr2 122 mtsp r0, sr3 123 mtsp r0, sr4 124 mtsp r0, sr5 125 mtsp r0, sr6 126 mtsp r0, sr7 127 128 /* 129 * to keep the spl() routines consistent we need to put the correct 130 * spl level into eiem, and reset any pending interrupts 131 */ 132 ldi -1, r1 133 mtctl r0, eiem 134 mtctl r1, eirr 135 136 /* 137 * load address of interrupt vector table 138 */ 139 ldil L%$ivaaddr, t2 140 ldo R%$ivaaddr(t2), t2 141 mtctl t2, iva 142 143 /* 144 * set up the dp pointer so that we can do quick references off of it 145 */ 146 ldil L%$global$,dp 147 ldo R%$global$(dp),dp 148 149 /* 150 * Create a stack frame for us to call C with. Clear out the previous 151 * sp marker to mark that this is the first frame on the stack. 152 */ 153 copy arg1, sp 154 ldo 0(arg1), r3 155 stw,ma r0, HPPA_FRAME_SIZE(sp) 156 stw r0, HPPA_FRAME_CRP(sp) 157 stw r0, HPPA_FRAME_PSP(sp) 158 159 /* 160 * We need to set the Q bit so that we can take TLB misses after we 161 * turn on virtual memory. 162 */ 163 mtctl r0, pcsq 164 mtctl r0, pcsq 165 mtctl rp, pcoq 166 ldo 4(rp), rp 167 mtctl rp, pcoq 168 mtctl arg2, ipsw 169 rfi 170 nop 171 nop 172EXIT($kernel_setup) 173 174/* int 175 * pdc_call(func, pdc_flag, ...) 176 * iodcio_t func; 177 * int pdc_flag; 178 */ 179ENTRY(pdc_call,160) 180 181 mfctl eiem, t1 182 mtctl r0, eiem 183 stw rp, HPPA_FRAME_CRP(sp) 184 copy arg0, r31 185 copy sp, ret1 186 187 ldil L%kernelmapped, ret0 188 ldw R%kernelmapped(ret0), ret0 189 comb,= r0, ret0, pdc_call_unmapped1 190 nop 191 ldil L%pdc_stack, ret1 192 ldw R%pdc_stack(ret1), ret1 193 194pdc_call_unmapped1 195 copy sp, r1 196 ldo HPPA_FRAME_SIZE+24*4(ret1), sp 197 198 stw r1, HPPA_FRAME_PSP(sp) 199 200 /* save kernelmapped and eiem */ 201 stw ret0, HPPA_FRAME_ARG(21)(sp) 202 stw t1, HPPA_FRAME_ARG(22)(sp) 203 204 /* copy arguments */ 205 copy arg2, arg0 206 copy arg3, arg1 207 ldw HPPA_FRAME_ARG(4)(r1), arg2 208 ldw HPPA_FRAME_ARG(5)(r1), arg3 209 ldw HPPA_FRAME_ARG(6)(r1), t1 210 ldw HPPA_FRAME_ARG(7)(r1), t2 211 ldw HPPA_FRAME_ARG(8)(r1), t3 212 ldw HPPA_FRAME_ARG(9)(r1), t4 213 stw t1, HPPA_FRAME_ARG(4)(sp) /* XXX can use ,bc */ 214 stw t2, HPPA_FRAME_ARG(5)(sp) 215 stw t3, HPPA_FRAME_ARG(6)(sp) 216 stw t4, HPPA_FRAME_ARG(7)(sp) 217 ldw HPPA_FRAME_ARG(10)(r1), t1 218 ldw HPPA_FRAME_ARG(11)(r1), t2 219 ldw HPPA_FRAME_ARG(12)(r1), t3 220 ldw HPPA_FRAME_ARG(13)(r1), t4 221 stw t1, HPPA_FRAME_ARG(8)(sp) 222 stw t2, HPPA_FRAME_ARG(9)(sp) 223 stw t3, HPPA_FRAME_ARG(10)(sp) 224 stw t4, HPPA_FRAME_ARG(11)(sp) 225 226 /* save temp control regs */ 227 mfctl cr24, t1 228 mfctl cr25, t2 229 mfctl cr26, t3 230 mfctl cr27, t4 231 stw t1, HPPA_FRAME_ARG(12)(sp) /* XXX can use ,bc */ 232 stw t2, HPPA_FRAME_ARG(13)(sp) 233 stw t3, HPPA_FRAME_ARG(14)(sp) 234 stw t4, HPPA_FRAME_ARG(15)(sp) 235 mfctl cr28, t1 236 mfctl cr29, t2 237 mfctl cr30, t3 238 mfctl cr31, t4 239 stw t1, HPPA_FRAME_ARG(16)(sp) 240 stw t2, HPPA_FRAME_ARG(17)(sp) 241 stw t3, HPPA_FRAME_ARG(18)(sp) 242 stw t4, HPPA_FRAME_ARG(19)(sp) 243 244 comb,= r0, ret0, pdc_call_unmapped2 245 nop 246 247 copy arg0, t4 248 ldi PSL_Q, arg0 /* (!pdc_flag && args[0] == PDC_PIM)? PSL_M:0) */ 249 break HPPA_BREAK_KERNEL, HPPA_BREAK_SET_PSW 250 stw ret0, HPPA_FRAME_ARG(23)(sp) 251 copy t4, arg0 252 253pdc_call_unmapped2 254 .call 255 blr r0, rp 256 bv,n (r31) 257 nop 258 259 /* load temp control regs */ 260 ldw HPPA_FRAME_ARG(12)(sp), t1 261 ldw HPPA_FRAME_ARG(13)(sp), t2 262 ldw HPPA_FRAME_ARG(14)(sp), t3 263 ldw HPPA_FRAME_ARG(15)(sp), t4 264 mtctl t1, cr24 265 mtctl t2, cr25 266 mtctl t3, cr26 267 mtctl t4, cr27 268 ldw HPPA_FRAME_ARG(16)(sp), t1 269 ldw HPPA_FRAME_ARG(17)(sp), t2 270 ldw HPPA_FRAME_ARG(18)(sp), t3 271 ldw HPPA_FRAME_ARG(19)(sp), t4 272 mtctl t1, cr28 273 mtctl t2, cr29 274 mtctl t3, cr30 275 mtctl t4, cr31 276 277 ldw HPPA_FRAME_ARG(21)(sp), t1 278 ldw HPPA_FRAME_ARG(22)(sp), t2 279 comb,= r0, t1, pdc_call_unmapped3 280 nop 281 282 copy ret0, t3 283 ldw HPPA_FRAME_ARG(23)(sp), arg0 284 break HPPA_BREAK_KERNEL, HPPA_BREAK_SET_PSW 285 copy t3, ret0 286 287pdc_call_unmapped3 288 ldw HPPA_FRAME_PSP(sp), sp 289 ldw HPPA_FRAME_CRP(sp), rp 290 bv r0(rp) 291 mtctl t2, eiem 292EXIT(pdc_call) 293 294/* 295 * Kernel Gateway Page (must be at known address) 296 * System Call Gate 297 * Signal Return Gate 298 * 299 * GATEway instructions have to be at a fixed known locations 300 * because their addresses are hard coded in routines such as 301 * those in the C library. 302 */ 303 .align NBPG 304 .export gateway_page, entry 305gateway_page 306 nop /* @ 0.C0000000 (Nothing) */ 307 gate,n $bsd_syscall,r0 /* @ 0.C0000004 (HPUX/BSD) */ 308 nop /* @ 0.C0000008 (HPOSF UNIX) */ 309 nop /* @ 0.C000000C (HPOSF Mach) */ 310 nop 311 nop 312 nop 313 nop 314 315$bsd_syscall 316 /* 317 * set up a space register and a protection id so that 318 * we can access kernel memory 319 */ 320 mfctl eiem, r1 321 mtctl r0, eiem 322 mtsp r0, sr1 323 mfctl pidr1, ret0 324 ldi HPPA_PID_KERNEL, t2 325 mtctl t2, pidr1 326 327 .import $syscall,code 328 .call 329 ldil L%$syscall, t2 330 be R%$syscall(sr1, t2) 331 nop ! nop ! nop ! nop 332 333 .size gateway_page, .-gateway_page 334 .align NBPG 335 .export gateway_page_end, entry 336gateway_page_end 337 338 .export $syscall,entry 339 .proc 340 .callinfo calls 341 .entry 342$syscall 343 /* 344 * 345 * t1: syscall number 346 * t2: user 347 * t3: args 348 * t4: user stack 349 * 350 */ 351 mfctl cr29, t2 352 ldw CI_CURPROC(sr1, t2), t2 353 ldw P_ADDR(sr1, t2), t3 /* XXX can use ,sl */ 354 355 /* calculate kernel sp, load, create kernel stack frame */ 356 ldo NBPG(t3), t3 357 stw t3, P_MD_REGS(sr1, t2) 358 ldo TRAPFRAME_SIZEOF(t3), t3 359 stw t4, TF_R19 -TRAPFRAME_SIZEOF(sr1, t3) /* t4 for vfork() */ 360 stw t1, TF_R22 -TRAPFRAME_SIZEOF(sr1, t3) /* syscall # */ 361 /* gotta save the args, in case we gonna restart */ 362 stw arg3, TF_R23-TRAPFRAME_SIZEOF(sr1, t3) 363 stw arg2, TF_R24-TRAPFRAME_SIZEOF(sr1, t3) 364 stw arg1, TF_R25-TRAPFRAME_SIZEOF(sr1, t3) 365 stw arg0, TF_R26-TRAPFRAME_SIZEOF(sr1, t3) 366 stw r27, TF_R27-TRAPFRAME_SIZEOF(sr1, t3) /* dp */ 367 stw sp, TF_R30 -TRAPFRAME_SIZEOF(sr1, t3) /* user stack */ 368 copy t3, sp 369 stw,ma r0, HPPA_FRAME_SIZE+HPPA_FRAME_MAXARGS(sr1, sp) 370 stw r0, HPPA_FRAME_CRP(sr1, sp) 371 mfctl r29, t1 372 ldw CI_PSW(sr1, t1), t1 373 stw r1, TF_CR15-TRAPFRAME_SIZEOF(sr1, t3) /* eiem ,bc */ 374 stw t1, TF_CR22-TRAPFRAME_SIZEOF(sr1, t3) /* ipsw */ 375 mfsp sr3, t1 376 stw t1, TF_SR3-TRAPFRAME_SIZEOF(sr1, t3) 377 stw ret0, TF_CR8-TRAPFRAME_SIZEOF(sr1, t3) /* pidr1 */ 378 /* now we can allow interrupts to happen */ 379 mtctl r1, eiem 380 381 /* 382 * we believe that any callee-save registers 383 * will be saved accordingly in either syscall() 384 * or deeper called functions and caller-save 385 * are saved in userland. 386 */ 387 stw r2 , TF_R2 -TRAPFRAME_SIZEOF(sr1, t3) 388 stw r3 , TF_R3 -TRAPFRAME_SIZEOF(sr1, t3) 389 copy t3, r3 390 /* save callee-save registers */ 391 stw r4 , TF_R4 -TRAPFRAME_SIZEOF(sr1, t3) 392 stw r5 , TF_R5 -TRAPFRAME_SIZEOF(sr1, t3) 393 stw r6 , TF_R6 -TRAPFRAME_SIZEOF(sr1, t3) 394 stw r7 , TF_R7 -TRAPFRAME_SIZEOF(sr1, t3) 395 stw r8 , TF_R8 -TRAPFRAME_SIZEOF(sr1, t3) 396 stw r9 , TF_R9 -TRAPFRAME_SIZEOF(sr1, t3) 397 stw r10, TF_R10-TRAPFRAME_SIZEOF(sr1, t3) 398 stw r11, TF_R11-TRAPFRAME_SIZEOF(sr1, t3) 399 stw r12, TF_R12-TRAPFRAME_SIZEOF(sr1, t3) 400 stw r13, TF_R13-TRAPFRAME_SIZEOF(sr1, t3) 401 stw r14, TF_R14-TRAPFRAME_SIZEOF(sr1, t3) 402 stw r15, TF_R15-TRAPFRAME_SIZEOF(sr1, t3) 403 stw r16, TF_R16-TRAPFRAME_SIZEOF(sr1, t3) 404 stw r17, TF_R17-TRAPFRAME_SIZEOF(sr1, t3) 405 stw r18, TF_R18-TRAPFRAME_SIZEOF(sr1, t3) 406 /* 407 * Save the rest of the CPU context 408 */ 409 mfsp sr0, arg0 /* use ,bc */ 410 stw arg0, TF_IISQH-TRAPFRAME_SIZEOF(sr1, t3) 411 stw arg0, TF_IISQT-TRAPFRAME_SIZEOF(sr1, t3) 412 413 ldo 4(r31), arg1 414 stw r31, TF_IIOQH-TRAPFRAME_SIZEOF(sr1, t3) 415 stw arg1, TF_IIOQT-TRAPFRAME_SIZEOF(sr1, t3) 416 417 stw arg0, TF_CR20-TRAPFRAME_SIZEOF(sr1, t3) /* use ,bc */ 418 stw r31, TF_CR21-TRAPFRAME_SIZEOF(sr1, t3) 419 420 ldil L%TFF_LAST|TFF_SYS, arg1 421 stw r0, TF_CR19-TRAPFRAME_SIZEOF(sr1, t3) /* iir */ 422 stw arg1, TF_FLAGS-TRAPFRAME_SIZEOF(sr1, t3) 423 424 mfsp sr2, arg2 425 mfsp sr4, arg3 426 stw arg0, TF_SR0-TRAPFRAME_SIZEOF(sr1, t3) 427 stw arg0, TF_SR1-TRAPFRAME_SIZEOF(sr1, t3) 428 stw arg2, TF_SR2-TRAPFRAME_SIZEOF(sr1, t3) 429 stw arg3, TF_SR4-TRAPFRAME_SIZEOF(sr1, t3) 430 431 mfsp sr5, arg0 432 mfsp sr6, arg1 433 mfsp sr7, arg2 434 mfctl pidr2, arg3 435 stw arg0, TF_SR5-TRAPFRAME_SIZEOF(sr1, t3) 436 stw arg1, TF_SR6-TRAPFRAME_SIZEOF(sr1, t3) 437 stw arg2, TF_SR7-TRAPFRAME_SIZEOF(sr1, t3) 438 stw arg3, TF_CR9-TRAPFRAME_SIZEOF(sr1, t3) 439 440#if pbably_not_worth_it 441 mfctl pidr3, arg2 442 mfctl pidr4, arg3 443 stw arg2, TF_CR12-TRAPFRAME_SIZEOF(sr1, t3) 444 stw arg3, TF_CR13-TRAPFRAME_SIZEOF(sr1, t3) 445#endif 446 447#ifdef DDB 448 /* 449 * Save hpt mask and v2p translation table pointer 450 */ 451 mfctl eirr, arg0 452 mfctl vtop, arg1 453 stw arg0, TF_CR23-TRAPFRAME_SIZEOF(sr1, t3) 454 stw arg1, TF_CR25-TRAPFRAME_SIZEOF(sr1, t3) 455 456 mfctl cr28, arg1 457 stw arg1, TF_CR28-TRAPFRAME_SIZEOF(sr1, t3) 458#endif 459 460 /* setup kernel context */ 461 mtsp r0, sr0 462 mtsp r0, sr1 463 mtsp r0, sr2 464 mtsp r0, sr3 465 mtsp r0, sr4 466 mtsp r0, sr5 467 mtsp r0, sr6 468 mtsp r0, sr7 469 470 ldo -TRAPFRAME_SIZEOF(t3), arg0 471 ldo 4(t3), arg1 472 473 ldil L%$global$,dp 474 ldo R%$global$(dp),dp 475 476 /* do a syscall */ 477 .import syscall,code 478 ldil L%syscall, r1 479 ldo R%syscall(r1), r1 480 .call 481 blr r0, rp 482 bv,n 0(r1) 483 nop 484 485 mfctl cr29, r1 486 ldw CI_CURPROC(r1), r1 487 ldw P_MD_REGS(r1), t3 488 489 .exit 490 .procend 491 /* FALLTHROUGH */ 492 493 .export $syscall_return, entry 494 .proc 495 .callinfo no_calls 496 .entry 497$syscall_return 498 /* t3 == VA trapframe */ 499 500 /* disable interrupts, just in case */ 501#ifdef MULTIPROCESSOR 502 mfctl eiem, t1 503 stw t1, TF_CR15(t3) 504#endif 505 mtctl r0, eiem 506 507 /* 508 * 1a. Copy a `phys' part of the frame into temp store 509 * (see a note for trapall) 510 * hopefully no page fault would happen on or after the copy, 511 * and interrupts are disabled. 512 */ 513 mfctl cr29, t2 514 ldo CI_TRAP_SAVE(t2), t2 515 /* use ,bc each cache line */ 516 ldw 0(t3), r1 ! ldw 4(t3), t1 ! stw r1, 0(t2) ! stw t1, 4(t2) 517 ldw 8(t3), r1 ! ldw 12(t3), t1 ! stw r1, 8(t2) ! stw t1, 12(t2) 518 ldw 16(t3), r1 ! ldw 20(t3), t1 ! stw r1, 16(t2) ! stw t1, 20(t2) 519 ldw 24(t3), r1 ! ldw 28(t3), t1 ! stw r1, 24(t2) ! stw t1, 28(t2) 520 ldw 32(t3), r1 ! ldw 36(t3), t1 ! stw r1, 32(t2) ! stw t1, 36(t2) 521 ldw 40(t3), r1 ! ldw 44(t3), t1 ! stw r1, 40(t2) ! stw t1, 44(t2) 522 ldw 48(t3), r1 ! ldw 52(t3), t1 ! stw r1, 48(t2) ! stw t1, 52(t2) 523 ldw 56(t3), r1 ! ldw 60(t3), t1 ! stw r1, 56(t2) ! stw t1, 60(t2) 524 525 /* 1b. restore most of the general registers */ 526 ldw TF_CR11(t3), t1 527 mtctl t1, sar 528 ldw TF_R1(t3), r1 529 ldw TF_R2(t3), r2 530 ldw TF_R3(t3), r3 531 ldw TF_R4(t3), r4 532 ldw TF_R5(t3), r5 533 ldw TF_R6(t3), r6 534 ldw TF_R7(t3), r7 535 ldw TF_R8(t3), r8 536 ldw TF_R9(t3), r9 537 ldw TF_R10(t3), r10 538 ldw TF_R11(t3), r11 539 ldw TF_R12(t3), r12 540 ldw TF_R13(t3), r13 541 ldw TF_R14(t3), r14 542 ldw TF_R15(t3), r15 543 ldw TF_R16(t3), r16 544 ldw TF_R17(t3), r17 545 ldw TF_R18(t3), r18 546 ldw TF_R19(t3), t4 547 /* r20(t3) is used as a temporary and will be restored later */ 548 /* r21(t2) is used as a temporary and will be restored later */ 549 /* r22(t1) is used as a temporary and will be restored later */ 550 ldw TF_R23(t3), r23 551 ldw TF_R24(t3), r24 552 ldw TF_R25(t3), r25 553 ldw TF_R26(t3), r26 554 ldw TF_R27(t3), r27 555 ldw TF_R28(t3), r28 556 ldw TF_R29(t3), r29 557 /* r30 (sp) will be restored later */ 558 ldw TF_R31(t3), r31 559 560 /* 2. restore all the space regs and pid regs, except sr3, pidr1 */ 561 ldw TF_SR0(t3), t1 562 ldw TF_SR1(t3), t2 563 mtsp t1, sr0 564 mtsp t2, sr1 565 566 ldw TF_SR2(sr3, t3), t1 567 ldw TF_SR4(sr3, t3), t2 568 mtsp t1, sr2 569 mtsp t2, sr4 570 571 ldw TF_SR5(sr3, t3), t1 572 ldw TF_SR6(sr3, t3), t2 573 mtsp t1, sr5 574 mtsp t2, sr6 575 576 ldw TF_SR7(sr3, t3), t1 577 ldw TF_CR9(sr3, t3), t2 578 mtsp t1, sr7 579 mtctl t2, pidr2 580 581#if pbably_not_worth_it 582 ldw TF_CR12(sr3, t3), t1 583 ldw TF_CR13(sr3, t3), t2 584 mtctl t1, pidr3 585 mtctl t2, pidr4 586#endif 587 ldw TF_CR0(sr3, t3), t1 588 mtctl t1, rctr 589 ldw TF_CR27(sr3, t3), t1 590 ldw TF_CR30(sr3, t3), t2 591 mtctl t1, cr27 592 mtctl t2, cr30 593 594 /* 595 * clear the system mask, this puts us back into physical mode. 596 * reload trapframe pointer w/ correspondent PA value. 597 * sp will be left in virtual until restored from trapframe, 598 * since we don't use it anyway. 599 */ 600 ssm 0, r0 601 mfctl cr29, t3 602 ldo CI_TRAP_SAVE(t3), t3 603 nop ! nop ! nop ! nop ! nop 604 rsm RESET_PSL, r0 605$syscall_return_phys 606 607 /* clear cr26 to avoid information leak */ 608 mtctl r0, cr26 609 610 /* finally we can restore the space and offset queues and the ipsw */ 611 ldw TF_IISQH(t3), t1 612 ldw TF_IISQT(t3), t2 613 mtctl t1, pcsq 614 mtctl t2, pcsq 615 616 ldw TF_IIOQH(t3), t1 617 ldw TF_IIOQT(t3), t2 618 mtctl t1, pcoq 619 mtctl t2, pcoq 620 621 ldw TF_CR15(t3), t1 622 ldw TF_CR22(t3), t2 623 mtctl t1, eiem 624 mtctl t2, ipsw 625 626 ldw TF_SR3(t3), t1 627 ldw TF_CR8(t3), t2 628 mtsp t1, sr3 629 mtctl t2, pidr1 630 631 ldw TF_R22(t3), t1 632 ldw TF_R21(t3), t2 633 ldw TF_R30(t3), sp 634 ldw TF_R20(t3), t3 635 636 rfi 637 nop 638 .exit 639 .procend 640 .size $syscall, .-$syscall 641$syscall_end 642 643/* 644 * interrupt vector table 645 */ 646#define TLABEL(name) $trap$name 647#define TRAP(name,num) \ 648 mtctl r1, tr7 ! \ 649 .call ! \ 650 .import TLABEL(name), code ! \ 651 b TLABEL(name) ! \ 652 ldi num, r1 ! \ 653 .align 32 654 655#define ATRAP(name,num) \ 656 .export TLABEL(name)$num, entry ! \ 657 .label TLABEL(name)$num ! \ 658 TRAP(all,num) ! \ 659 .size TLABEL(name)$num, .-TLABEL(name)$num 660 661#define CTRAP(name,num,pre) \ 662 .export TLABEL(name)$num, entry ! \ 663 .label TLABEL(name)$num ! \ 664 pre ! \ 665 TRAP(name,num) ! \ 666 .size TLABEL(name)$num, .-TLABEL(name)$num 667 668#define STRAP(name,num,pre) \ 669 .export TLABEL(name)$num, entry ! \ 670 .label TLABEL(name)$num ! \ 671 pre ! \ 672 mtctl r1, tr7 ! \ 673 .export trap_ep_##num, entry ! \ 674 .label trap_ep_##num ! \ 675 .call ! \ 676 b __CONCAT($name,_l) ! \ 677 ldi num, r1 ! \ 678 b __CONCAT($name,_t)+8 ! \ 679 b __CONCAT($name,_s)+12 ! \ 680 b __CONCAT($name,_u)+16 ! \ 681 .size TLABEL(name)$num, .-TLABEL(name)$num 682 683#define ITLBPRE \ 684 mfctl pcoq,r9 ! \ 685 mfctl pcsq,r8 686#define DTLBPRE \ 687 mfctl ior, r9 ! \ 688 mfctl isr, r8 689 /* CR28XXX according to a popular belief cr28 should be read here */ 690 691#define HPMCPRE nop 692#define INTRPRE \ 693 mfctl eirr, r8 ! \ 694 mtctl r8, eirr 695 696 .align NBPG 697 .export $ivaaddr, entry 698 .export hpmc_v, entry 699$ivaaddr 700 ATRAP(null,T_NONEXIST) /* 0. invalid interrupt vector */ 701hpmc_v 702 CTRAP(hpmc,T_HPMC,HPMCPRE) /* 1. high priority machine check */ 703 ATRAP(power,T_POWERFAIL) /* 2. power failure */ 704 ATRAP(recnt,T_RECOVERY) /* 3. recovery counter trap */ 705 CTRAP(intr,T_INTERRUPT,INTRPRE) /* 4. external interrupt */ 706 ATRAP(lpmc,T_LPMC) /* 5. low-priority machine check */ 707 STRAP(itlb,T_ITLBMISS,ITLBPRE) /* 6. instruction TLB miss fault */ 708 ATRAP(iprot,T_IPROT) /* 7. instruction protection trap */ 709 ATRAP(ill,T_ILLEGAL) /* 8. Illegal instruction trap */ 710 CTRAP(ibrk,T_IBREAK,) /* 9. break instruction trap */ 711 ATRAP(privop,T_PRIV_OP) /* 10. privileged operation trap */ 712 ATRAP(privr,T_PRIV_REG) /* 11. privileged register trap */ 713 ATRAP(ovrfl,T_OVERFLOW) /* 12. overflow trap */ 714 ATRAP(cond,T_CONDITION) /* 13. conditional trap */ 715 CTRAP(excpt,T_EXCEPTION,) /* 14. assist exception trap */ 716 STRAP(dtlb,T_DTLBMISS,DTLBPRE) /* 15. data TLB miss fault */ 717 STRAP(itlbna,T_ITLBMISSNA,DTLBPRE)/* 16. ITLB non-access miss fault */ 718 STRAP(dtlbna,T_DTLBMISSNA,DTLBPRE)/* 17. DTLB non-access miss fault */ 719 ATRAP(dprot,T_DPROT) /* 18. data protection trap 720 unaligned data reference trap */ 721 ATRAP(dbrk,T_DBREAK) /* 19. data break trap */ 722 STRAP(tlbd,T_TLB_DIRTY,DTLBPRE) /* 20. TLB dirty bit trap */ 723 ATRAP(pgref,T_PAGEREF) /* 21. page reference trap */ 724 CTRAP(emu,T_EMULATION,) /* 22. assist emulation trap */ 725 ATRAP(hpl,T_HIGHERPL) /* 23. higher-privelege transfer trap*/ 726 ATRAP(lpl,T_LOWERPL) /* 24. lower-privilege transfer trap */ 727 ATRAP(tknbr,T_TAKENBR) /* 25. taken branch trap */ 728 ATRAP(dacc,T_DATACC) /* 26. data access rights trap */ 729 ATRAP(dpid,T_DATAPID) /* 27. data protection ID trap */ 730 ATRAP(dalgn,T_DATALIGN) /* 28. unaligned data ref trap */ 731 ATRAP(unk29,29) 732 ATRAP(unk30,30) 733 ATRAP(unk31,31) 734 ATRAP(unk32,32) 735 ATRAP(unk33,33) 736 ATRAP(unk34,34) 737 ATRAP(unk35,35) 738 ATRAP(unk36,36) 739 ATRAP(unk37,37) 740 ATRAP(unk38,38) 741 ATRAP(unk39,39) 742 ATRAP(unk40,40) 743 ATRAP(unk41,41) 744 ATRAP(unk42,42) 745 ATRAP(unk43,43) 746 ATRAP(unk44,44) 747 ATRAP(unk45,45) 748 ATRAP(unk46,46) 749 ATRAP(unk47,47) 750 ATRAP(unk48,48) 751 ATRAP(unk49,49) 752 ATRAP(unk50,50) 753 ATRAP(unk51,51) 754 ATRAP(unk52,52) 755 ATRAP(unk53,53) 756 ATRAP(unk54,54) 757 ATRAP(unk55,55) 758 ATRAP(unk56,56) 759 ATRAP(unk57,57) 760 ATRAP(unk58,58) 761 ATRAP(unk59,59) 762 ATRAP(unk60,60) 763 ATRAP(unk61,61) 764 ATRAP(unk62,62) 765 ATRAP(unk63,63) 766 /* 64 */ 767 .size $ivaaddr, .-$ivaaddr 768 769 .export TLABEL(excpt), entry 770ENTRY(TLABEL(excpt),0) 771 /* assume we never get this one w/o fpu [enabled] */ 772 copy rp, r1 773 copy arg0, r8 774 mfctl cr30, r9 775#if HFP_REGS != 0 776 ldo HFP_REGS(r9), r9 777#endif 778 .import fpu_save, code 779 .call 780 bl fpu_save, rp 781 copy r9, arg0 782 copy r1, rp 783 copy r8, arg0 784 mfctl cr29, r1 785 mtctl r0, ccr /* cause a reload after exception */ 786 ldw CI_FPU_STATE(r1), r16 787 stw r0, CI_FPU_STATE(r1) 788 stw r0, HFP_CPU(r16) 789 sync 790 791 /* now, check for trap */ 792 ldw 0(r9), r1 793 bb,>=,n r1, HPPA_FPU_T_POS, excpt_notrap 794 ldw 1*4(r9), r1 795 comb,<>,n r0, r1, excpt_emulate 796 ldw 2*4(r9), r1 797 comb,<>,n r0, r1, excpt_emulate 798 ldw 3*4(r9), r1 799 comb,<>,n r0, r1, excpt_emulate 800 ldw 4*4(r9), r1 801 comb,<>,n r0, r1, excpt_emulate 802 ldw 5*4(r9), r1 803 comb,<>,n r0, r1, excpt_emulate 804 ldw 6*4(r9), r1 805 comb,<>,n r0, r1, excpt_emulate 806 ldw 7*4(r9), r1 807 808excpt_emulate 809 bb,>=,n r1, 5, excpt_notrap /* HPPA_FPU_UNMPL not set */ 810 811 ldw 0(r9), r16 812 depi 0, HPPA_FPU_T_POS, 1, r16 813 .import $fpu_emulate, code 814 b $fpu_emulate 815 stw r16, 0(r9) 816 817excpt_notrap 818 sync 819 b TLABEL(all) 820 ldi T_EXCEPTION, r1 821EXIT(TLABEL(excpt)) 822 823 .export TLABEL(emu), entry 824ENTRY(TLABEL(emu),0) 825 826 /* 827 * Switch FPU/SFU context 828 * 829 * isr:ior - data address 830 * iir - instruction to emulate 831 * iisq:iioq - address of instruction to emulate 832 * 833 * note: ISR and IOR contain valid data only if the 834 * instruction is a coprocessor load or store. 835 * 836 */ 837 838 mfctl iir, r8 839 extru r8, 5, 6, r9 /* no sfu implementation right now */ 840 comib,= 4, r9, TLABEL(all) 841 ldi T_ILLEGAL, r1 842 843 /* 844 * pass through for all coprocessors now and 845 * do not check the uid here. 846 * in case that piece does not exist emulate 847 * or the trap will be generated later. 848 */ 849 850 ldil L%cpu_fpuena, r1 851 ldw R%cpu_fpuena(r1), r9 852 comib,= 0, r9, $fpusw_emu 853 854 /* if we are already enabled and hit again, emulate */ 855 mfctl ccr, r1 856 extru,<> r1, 25, 2, r0 857 b,n $fpusw_set 858 nop 859 860$fpusw_emu 861 mfctl cr29, r1 862 mtctl r0, ccr /* cause a reload after exception */ 863 ldw CI_FPU_STATE(r1), r16 864 stw r0, CI_FPU_STATE(r1) 865 stw r0, HFP_CPU(r16) 866 sync 867#if 0 868 /* here we emulate the fld/fst */ 869 mfctl iir, r1 870 extru r1, 5, 6, r1 871 comib,= 0xb, r9, TLABEL(all) 872 ldi T_ILLEGAL, r1 873 874 mfctl iir, r1 875 extru r1, 5, 6, r1 876 comib,= 0x9, r9, TLABEL(all) 877 ldi T_ILLEGAL, r1 878#endif 879 mfctl iir, r1 880 .import $fpu_emulate, code 881 b $fpu_emulate 882 nop 883 884$fpusw_set 885 /* enable coprocessor XXX */ 886 depi 3, 25, 2, r1 887 mtctl r1, ccr 888 889 mfctl cr29, r16 890 mfctl cr30, r9 891 ldw CI_FPU_STATE(r16), r16 892 893 comb,=,n r16, r0, $fpusw_nosave 894 comb,=,n r16, r9, $fpusw_done 895 896 copy arg0, r17 897 copy rp, r1 898#if HFP_REGS != 0 899 ldo HFP_REGS(r16), r16 900#endif 901 .import fpu_save, code 902 .call 903 bl fpu_save, rp 904 copy r16, arg0 905 copy r1, rp 906 copy r17, arg0 907 908 mfctl cr29, r1 909 ldw CI_FPU_STATE(r1), r16 910 stw r0, CI_FPU_STATE(r1) 911 stw r0, HFP_CPU(r16) 912 sync 913 914$fpusw_nosave 915 916#ifdef MULTIPROCESSOR 917 /* See if this process has FPU context on another CPU. */ 918 ldw HFP_CPU(r9), r1 919 comb,=,n r1, r0, $fpusw_noshoot 920 921 /* Perform FPU shootdown. */ 922 ldi (1 << HPPA_IPI_FPU_SAVE), r1 923 ldw HFP_CPU(r9), r16 924 stw r1, CI_IPI(r16) 925 ldi 1, r1 926 ldw CI_HPA(r16), r16 927 stw r1, 0(r16) 928 929$fpusw_spin 930 /* Wait for shootdown to complete. */ 931 sync 932 ldw HFP_CPU(r9), r1 933 comb,<>,n r1, r0, $fpusw_spin 934 935$fpusw_noshoot 936#endif 937 938 /* count switches */ 939 .import uvmexp, data 940 ldil L%(uvmexp+FPSWTCH), r1 941 ldw R%(uvmexp+FPSWTCH)(r1), r16 942 ldo 31*8+HFP_REGS(r9), r17 943 ldo 1(r16), r16 944 stw r16, R%(uvmexp+FPSWTCH)(r1) 945 946 fldds,ma -8(r17), fr31 947 fldds,ma -8(r17), fr30 948 fldds,ma -8(r17), fr29 949 fldds,ma -8(r17), fr28 950 fldds,ma -8(r17), fr27 951 fldds,ma -8(r17), fr26 952 fldds,ma -8(r17), fr25 953 fldds,ma -8(r17), fr24 954 fldds,ma -8(r17), fr23 955 fldds,ma -8(r17), fr22 956 fldds,ma -8(r17), fr21 957 fldds,ma -8(r17), fr20 958 fldds,ma -8(r17), fr19 959 fldds,ma -8(r17), fr18 960 fldds,ma -8(r17), fr17 961 fldds,ma -8(r17), fr16 962 fldds,ma -8(r17), fr15 963 fldds,ma -8(r17), fr14 964 fldds,ma -8(r17), fr13 965 fldds,ma -8(r17), fr12 966 fldds,ma -8(r17), fr11 967 fldds,ma -8(r17), fr10 968 fldds,ma -8(r17), fr9 969 fldds,ma -8(r17), fr8 970 fldds,ma -8(r17), fr7 971 fldds,ma -8(r17), fr6 972 fldds,ma -8(r17), fr5 973 fldds,ma -8(r17), fr4 974 fldds,ma -8(r17), fr3 975 fldds,ma -8(r17), fr2 976 fldds,ma -8(r17), fr1 977 fldds 0(r17), fr0 /* fr0 must be restored last */ 978 979 mfctl cr29, r1 980 stw r9, CI_FPU_STATE(r1) 981 stw r1, HFP_CPU(r9) 982 sync 983 984$fpusw_done 985 rfir 986 nop 987EXIT(TLABEL(emu)) 988 989 /* Construct the virtual address tag. */ 990#define VTAG ! \ 991 shd r0, r9, 1, r16 /* r16[1..15] = off[0..14] */ ! \ 992 dep r8, 31, 16, r16 /* put in the space id */ ! \ 993 depi 1, 0, 1, r16 /* and set the valid bit */ 994 995#if 0 996 .export dtlb_c, data 997 BSS(dtlb_c, 8) 998 .export tlbd_c, data 999 BSS(tlbd_c, 8) 1000 .export itlb_c, data 1001 BSS(itlb_c, 8) 1002 1003 .text 1004 /* XXX this touches tr5, which it should not, perhaps */ 1005 1006#define TLB_STATS_PRE(t) \ 1007 mfctl itmr, r17 ! \ 1008 mtctl r17, tr5 1009#define TLB_STATS_AFT(t) \ 1010 mfctl itmr, r16 ! \ 1011 mfctl tr5, r17 ! \ 1012 ldil L%__CONCAT(t,_c), r25 ! \ 1013 ldo R%__CONCAT(t,_c)(r25), r25 ! \ 1014 sub r16, r17, r16 ! \ 1015 ldw 0(r25), r24 ! \ 1016 ldw 4(r25), r17 ! \ 1017 ldo 1(r24), r24 ! \ 1018 ldo -2(r16), r16 /* for mtctl */ ! \ 1019 add r16, r17, r17 ! \ 1020 stw r24, 0(r25) ! \ 1021 stw r17, 4(r25) 1022 1023#else 1024#define TLB_STATS_PRE(t) /**/ 1025#define TLB_STATS_AFT(t) /**/ 1026#endif 1027 1028#if defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU) 1029#define TLB_PULL(bits,lbl) ! \ 1030 /* space:pgaddr -- r8:r9 */ ! \ 1031 mfctl vtop, r16 ! \ 1032 ldwax,s r8(r16), r17 /* space -> page directory */ ! \ 1033 extru r9, 9, 10, r25 ! \ 1034 combt,=,n r0, r17, lbl ! \ 1035 ldwax,s r25(r17), r24 /* page -> page table */ ! \ 1036 extru r9, 19, 10, r16 ! \ 1037 combt,=,n r0, r24, lbl ! \ 1038 ldwax,s r16(r24), r17 /* va -> pa:prot */ ! \ 1039 sh2addl r16, r24, r25 ! \ 1040 combt,=,n r0, r17, lbl ! \ 1041 copy r17, r16 ! \ 1042 depi (bits), 21+bits, 1+bits, r17 ! \ 1043 sub,= r16, r17, r0 /* do not store if unchanged */ ! \ 1044 stwas r17, 0(r25) /* store back w/ the bits */ ! \ 1045 shd r17, r0, 13, r25 ! \ 1046 dep r8, 30, 15, r25 /* mix0r the pid from the sid */! \ 1047 dep r0, 31, 12, r17 /* needed ? */ ! \ 1048 addi 2, r25, r25 ! \ 1049 extru r17, 24, 25, r17 1050 1051 .align 32 1052LEAF_ENTRY($tlbd_s) 1053ALTENTRY($tlbd_t) 1054 TLB_STATS_PRE(tlbd) 1055 TLB_PULL(1, TLABEL(all)) 1056 mfsp sr1, r16 1057 mtsp r8, sr1 1058 idtlba r17,(sr1, r9) 1059 idtlbp r25,(sr1, r9) 1060 mtsp r16, sr1 1061 TLB_STATS_AFT(tlbd) 1062 rfir 1063 nop 1064EXIT($tlbd_s) 1065 1066LEAF_ENTRY($itlb_s) 1067ALTENTRY($itlb_t) 1068 TLB_STATS_PRE(itlb) 1069 TLB_PULL(0, TLABEL(all)) 1070 extru,= r25, 5, 1, r0 /* gateway page needs to be public */ 1071 depi 0, 30, 15, r25 1072 mfsp sr1, r16 1073 mtsp r8, sr1 1074 iitlba r17,(sr1, r9) 1075 iitlbp r25,(sr1, r9) 1076 mtsp r16, sr1 1077 TLB_STATS_AFT(itlb) 1078 rfir 1079 nop 1080EXIT($itlb_s) 1081 1082LEAF_ENTRY($dtlb_s) 1083ALTENTRY($dtlb_t) 1084 TLB_STATS_PRE(dtlb) 1085 TLB_PULL(0, TLABEL(all)) 1086 mfsp sr1, r16 1087 mtsp r8, sr1 1088 idtlba r17,(sr1, r9) 1089 idtlbp r25,(sr1, r9) 1090 mtsp r16, sr1 1091 TLB_STATS_AFT(dtlb) 1092 rfir 1093 nop 1094EXIT($dtlb_s) 1095 1096LEAF_ENTRY($dtlbna_s) 1097ALTENTRY($itlbna_s) 1098ALTENTRY($dtlbna_t) 1099ALTENTRY($itlbna_t) 1100 TLB_STATS_PRE(dtlb) 1101 TLB_PULL(0, $dtlbna_t_fake) 1102 mfsp sr1, r16 1103 mtsp r8, sr1 1104 idtlba r17,(sr1, r9) 1105 idtlbp r25,(sr1, r9) 1106 mtsp r16, sr1 1107 TLB_STATS_AFT(dtlb) 1108 rfir 1109 nop 1110$dtlbna_s_fake 1111$dtlbna_t_fake 1112 /* parse prober/w insns, have to decent to trap() to set regs proper */ 1113 mfctl iir, r16 1114 extru r16, 6, 6, r24 1115 comib,=,n 1, r24, TLABEL(all) 1116 extru r16, 24, 6, r24 1117 subi,<> 0x23, r24, r0 1118 b TLABEL(all) 1119 /* otherwise generate a flush-only tlb entry */ 1120 copy r0, r17 1121 zdep r8, 30, 15, r25 1122 depi -13, 11, 7, r25 1123 ldo 2(r25), r25 /* 3? */ 1124 mfsp sr1, r16 1125 mtsp r8, sr1 1126 idtlba r17,(sr1, r9) 1127 idtlbp r25,(sr1, r9) 1128 mtsp r16, sr1 1129 TLB_STATS_AFT(dtlb) 1130 rfir 1131 nop 1132EXIT($dtlbna_s) 1133 1134#endif /* defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU) */ 1135 1136#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU) 1137 1138#define IITLBAF(r) .word 0x04000440 | ((r) << 16) 1139#define IITLBPF(r) .word 0x04000400 | ((r) << 16) 1140#define IDTLBAF(r) .word 0x04001440 | ((r) << 16) 1141#define IDTLBPF(r) .word 0x04001400 | ((r) << 16) 1142 1143/* 1144 * possible optimizations: 1145 * change pte to reduce number of shifts 1146 * reorder to reduce stalls 1147 */ 1148#define TLB_PULL_L(bits,lbl) ! \ 1149 /* space:pgaddr -- r8:r9 */ ! \ 1150 mfctl vtop, r16 ! \ 1151 ldwx,s r8(r16), r17 /* space -> page directory */ ! \ 1152 extru r9, 9, 10, r25 ! \ 1153 combt,=,n r0, r17, lbl ! \ 1154 ldwx,s r25(r17), r24 /* page -> page table */ ! \ 1155 extru r9, 19, 10, r16 ! \ 1156 combt,=,n r0, r24, lbl ! \ 1157 ldwx,s r16(r24), r17 /* va -> pa:prot */ ! \ 1158 sh2addl r16, r24, r25 ! \ 1159 combt,=,n r0, r17, lbl ! \ 1160 copy r17, r16 ! \ 1161 depi (bits), 21+bits, 1+bits, r17 ! \ 1162 sub,= r16, r17, r0 /* do not store if unchanged */ ! \ 1163 stws r17, 0(r25) /* store back w/ the bits */ ! \ 1164 shd r17, r0, 13, r25 ! \ 1165 dep r8, 30, 15, r25 /* mix0r the pid from the sid */! \ 1166 dep r0, 31, 12, r17 /* needed ? */ ! \ 1167 addi 2, r25, r25 ! \ 1168 extru r17, 24, 25, r17 /* tlbbtop(r17) */ ! \ 1169 sync 1170 1171 .align 32 1172LEAF_ENTRY($tlbd_l) 1173 TLB_STATS_PRE(tlbd) 1174 TLB_PULL_L(1, TLABEL(all)) 1175 IDTLBAF(17) 1176 IDTLBPF(25) 1177#ifdef USE_HPT 1178 /* invalidate instead of update */ 1179 mfctl cr28, r17 1180 ldw 0(r17), r24 1181 VTAG 1182 sub,<> r16, r24, r0 1183 stw r0, 0(r17) 1184#endif 1185 TLB_STATS_AFT(tlbd) 1186 rfir 1187 nop 1188EXIT($tlbd_l) 1189 1190 /* 1191 * from 7100lc ers, pg.6: 1192 * we found a post-silicon bug that makes cr28 1193 * unreliable for the itlb miss handler 1194 */ 1195LEAF_ENTRY($itlb_l) 1196 TLB_STATS_PRE(itlb) 1197 TLB_PULL_L(0, TLABEL(all)) 1198 extru,= r25, 5, 1, r0 /* gateway page needs to be public */ 1199 depi 0, 30, 15, r25 1200 IITLBAF(17) 1201 IITLBPF(25) 1202 TLB_STATS_AFT(itlb) 1203 rfir 1204 nop 1205EXIT($itlb_l) 1206 1207LEAF_ENTRY($dtlbna_l) 1208ALTENTRY($itlbna_l) 1209 TLB_STATS_PRE(dtlb) 1210 TLB_PULL_L(0, $dtlbna_l_fake) 1211 IDTLBAF(17) 1212 IDTLBPF(25) 1213 TLB_STATS_AFT(dtlb) 1214 rfir 1215 nop 1216$dtlbna_l_fake 1217 /* parse prober/w insns, have to decent to trap() to set regs proper */ 1218 mfctl iir, r16 1219 extru r16, 6, 6, r24 1220 comib,=,n 1, r24, TLABEL(all) 1221 extru r16, 24, 6, r24 1222 subi,<> 0x23, r24, r0 1223 b TLABEL(all) 1224 /* otherwise generate a flush-only tlb entry */ 1225 copy r0, r17 1226 zdep r8, 30, 15, r25 1227 depi -13, 11, 7, r25 1228 ldo 2(r25), r25 /* 3? */ 1229 IDTLBAF(17) 1230 IDTLBPF(25) 1231 TLB_STATS_AFT(dtlb) 1232 rfir 1233 nop 1234EXIT($dtlbna_l) 1235 1236LEAF_ENTRY($dtlb_l) 1237 TLB_STATS_PRE(dtlb) 1238 TLB_PULL_L(0, TLABEL(all)) 1239 IDTLBAF(17) 1240 IDTLBPF(25) 1241#ifdef USE_HPT 1242 /* 1243 * cache the next page mapping in the hpt. 1244 * 1245 * mapping for a page at the end of each 128k is uncachable 1246 * in the hvt since it'd be in the tlb itself and thus there 1247 * is no reason to cache it! 1248 * as a side effect this avoids recomputing hpt entry and 1249 * retraversing the whole page table each time. 1250 */ 1251 1252 ldo PAGE_SIZE(r9), r9 1253 extru,<> r9, 20, 5, r0 1254 b,n $dtlb_done_l /* skip if no simple advance */ 1255 /* do not check the PT overlap since the above 1256 * check already guaranties that */ 1257 1258 /* ripped from TLB_PULL_L(0) */ 1259 extru r9, 19, 10, r16 /* r24 was loaded in the TLB_PULL_L */ 1260 ldwx,s r16(r24), r17 /* va -> pa:prot */ 1261 sh2addl r16, r24, r25 1262 combt,=,n r0, r17, $dtlb_done_l 1263 copy r17, r16 1264 depi 0, 21, 1, r17 1265 sub,= r16, r17, r0 /* do not store if unchanged */ 1266 stws r17, 0(r25) /* store back w/ the bits */ 1267 shd r17, r0, 13, r25 1268 dep r8, 30, 15, r25 /* mix0r the pid from the sid */ 1269 dep r0, 31, 12, r17 /* needed ? */ 1270 addi 2, r25, r25 1271 extru r17, 24, 25, r17 1272 sync 1273 1274 mfctl cr28, r24 1275 VTAG 1276 ldo 16(r24), r24 1277 stw r16, 0(r24) 1278 stw r25, 4(r24) 1279 stw r17, 8(r24) 1280$dtlb_done_l 1281#endif 1282 TLB_STATS_AFT(dtlb) 1283 rfir 1284 nop 1285EXIT($dtlb_l) 1286#endif /* HP7100LC_CPU */ 1287 1288#if defined(HP8000_CPU) || defined(HP8200_CPU) || defined(HP8500_CPU) 1289 .level 2.0w 1290 1291 /* xlate 32bit->64bit pte */ 1292#define TLB_PCX2PCXU \ 1293 extrw,u r25, 14, 13, r16 ! \ 1294 depdi 0, 31, 32, r17 ! \ 1295 /* fix io mappings */ ! \ 1296 extrd,s r17, 42, 4, r1 ! \ 1297 addi,<> 1, r1, r0 ! \ 1298 depdi -1, 38, 32, r17 ! \ 1299 /* fix prom mappings */ ! \ 1300 extrd,s r17, 46, 8, r1 ! \ 1301 addi,<> 0x10, r1, r0 ! \ 1302 depdi 0, 38, 4, r17 ! \ 1303 /* weak ordering, dyn bp */ ! \ 1304 depwi 1, 31, 2, r16 ! \ 1305 depdi 0, 44, 30, r25 ! \ 1306 depd r16, 14, 15, r25 1307 1308LEAF_ENTRY($tlbd_u) 1309 TLB_STATS_PRE(tlbd) 1310 TLB_PULL_L(1, TLABEL(all)) 1311 TLB_PCX2PCXU 1312 idtlbt r17, r25 1313 TLB_STATS_AFT(tlbd) 1314 rfir 1315 nop 1316EXIT($tlbd_u) 1317 1318LEAF_ENTRY($itlb_u) 1319 TLB_STATS_PRE(itlb) 1320 TLB_PULL_L(0, TLABEL(all)) 1321 extru,= r25, 5, 1, r0 /* gateway page needs to be public */ 1322 depi 0, 30, 15, r25 1323 TLB_PCX2PCXU 1324 iitlbt r17, r25 1325 TLB_STATS_AFT(itlb) 1326 rfir 1327 nop 1328EXIT($itlb_u) 1329 1330LEAF_ENTRY($dtlbna_u) 1331ALTENTRY($itlbna_u) 1332 TLB_STATS_PRE(dtlb) 1333 TLB_PULL_L(0, $dtlbna_u_fake) 1334 TLB_PCX2PCXU 1335 idtlbt r17, r25 1336 TLB_STATS_AFT(dtlb) 1337 rfir 1338 nop 1339$dtlbna_u_fake 1340 /* parse prober/w insns, have to decent to trap() to set regs proper */ 1341 mfctl iir, r16 1342 extru r16, 6, 6, r24 1343 comib,=,n 1, r24, TLABEL(all) 1344 extru r16, 24, 6, r24 1345 subi,<> 0x23, r24, r0 1346 b TLABEL(all) 1347 /* otherwise generate a flush-only tlb entry */ 1348 copy r0, r17 1349 zdep r8, 30, 15, r25 1350 depi -13, 11, 7, r25 1351 ldo 2(r25), r25 /* 3? */ 1352 idtlbt r17, r25 1353 TLB_STATS_AFT(dtlb) 1354 rfir 1355 nop 1356EXIT($dtlbna_u) 1357 1358LEAF_ENTRY($dtlb_u) 1359 TLB_STATS_PRE(dtlb) 1360 TLB_PULL_L(0, TLABEL(all)) 1361 TLB_PCX2PCXU 1362 idtlbt r17, r25 1363 TLB_STATS_AFT(dtlb) 1364 rfir 1365 nop 1366EXIT($dtlb_u) 1367 1368 .level 1.1 1369#endif /* HP8000_CPU */ 1370 1371 .align 64 1372 .export TLABEL(all), entry 1373ENTRY(TLABEL(all),0) 1374 /* r1 still has trap type */ 1375 1376 /* 1377 * at this point we have: 1378 * psw copied into ipsw 1379 * psw = E(default), M(1 if HPMC, else 0) 1380 * PL = 0 1381 * r1, r8, r9, r16, r17, r24, r25 shadowed (maybe) 1382 * trap number in r1 (old r1 is saved in tr7) 1383 */ 1384 1385 /* do not overwrite cr28 */ 1386 mtctl t3, cr26 1387 1388 mfctl cr29, t3 1389 ldo CI_TRAP_SAVE(t3), t3 1390 stw t1, TF_R22(t3) /* use ,bc */ 1391 stw t2, TF_R21(t3) 1392 1393 mfctl cr26, t1 1394 stw sp, TF_R30(t3) /* sp */ 1395 stw t1, TF_R20(t3) /* t3 */ 1396 1397 /* 1398 * Now, save away other volatile state that prevents us from turning 1399 * the PC queue back on, namely, the pc queue and ipsw, and the 1400 * interrupt information. 1401 */ 1402 1403 mfctl eiem, t1 1404 mfctl ipsw, t2 1405 stw t1, TF_CR15(t3) /* use ,bc */ 1406 stw t2, TF_CR22(t3) 1407 1408 mfsp sr3, t1 1409 mfctl pidr1, t2 1410 stw t1, TF_SR3(t3) 1411 stw t2, TF_CR8(t3) 1412 1413 /* 1414 * Setup kernel context 1415 */ 1416 1417 ldi HPPA_PID_KERNEL,t1 1418 mtctl t1, pidr1 1419 mtsp r0, sr3 1420 1421 /* this will enable interrupts after `cold' */ 1422 mfctl cr29, t1 1423 ldw CI_PSW(t1), t2 1424 mtctl r0, eiem 1425 mtctl t2, ipsw 1426 1427 mfctl pcsq, t1 1428 mtctl r0, pcsq 1429 mfctl pcsq, t2 1430 stw t1, TF_IISQH(t3) /* use ,bc */ 1431 stw t2, TF_IISQT(t3) 1432 mtctl r0, pcsq 1433 1434 /* 1435 * Set up the kernel stack pointer. If the trap happened 1436 * while we were in unprivileged code, or in privileged 1437 * code in the SYSCALLGATE page, move to the kernel stack 1438 * in curproc's PCB; otherwise, start a new stack frame 1439 * on whatever kernel stack we're already on. 1440 * 1441 * This used to check only for a trap while we were in 1442 * unprivileged code, but this ignored the possibility 1443 * that a trap could come in during the period between 1444 * a gateway instruction to raise privilege and the 1445 * disabling of interrupts. During this period we're 1446 * still on the user's stack, and we must move to the 1447 * kernel stack. 1448 * 1449 * - fredette@ 1450 */ 1451 mfctl pcoq, t1 1452 ldil L%SYSCALLGATE, t2 1453 ldo TF_PHYS-1(sp), sp 1454 dep t1, 31, PGSHIFT, t2 1455 dep,<> t1, 31, 2, r0 1456 comb,<> t1, t2, $trap_from_kernel 1457 dep r0, 31, 6, sp 1458 1459 mfctl cr29, t2 1460 ldw CI_CURPROC(t2), t2 1461 depi 1, T_USER_POS, 1, r1 1462 depi 1, TFF_LAST_POS, 1, r1 1463 ldw P_ADDR(t2), sp 1464 ldo NBPG(sp), sp 1465 1466$trap_from_kernel 1467 ldil L%$trapnowvirt, t2 1468 ldo R%$trapnowvirt(t2), t2 1469 mtctl t2, pcoq 1470 stw t1, TF_IIOQH(t3) 1471 ldo 4(t2), t2 1472 mfctl pcoq, t1 1473 stw t1, TF_IIOQT(t3) 1474 mtctl t2, pcoq 1475 1476 mfctl isr, t1 1477 mfctl ior, t2 1478 stw t1, TF_CR20(t3) /* use ,bc */ 1479 stw t2, TF_CR21(t3) 1480 1481 mfctl iir, t2 1482 stw t2, TF_CR19(t3) 1483 stw r1, TF_FLAGS(t3) 1484 1485 mfctl rctr, t1 /* gotta get it before R is up */ 1486 1487 copy sp, t3 1488 ldo HPPA_FRAME_SIZE+TRAPFRAME_SIZEOF(sp), sp 1489 rfir 1490 nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop 1491$trapnowvirt 1492 /* 1493 * t3 contains the virtual address of the trapframe 1494 * sp is loaded w/ the right VA (we did not need it being physical) 1495 */ 1496 1497 mfctl ccr, t2 1498 stw t1, TF_CR0(sr3, t3) 1499 stw t2, TF_CR10(sr3, t3) 1500 1501 mfsp sr0, t1 1502 mfsp sr1, t2 1503 stw t1, TF_SR0(sr3, t3) 1504 stw t2, TF_SR1(sr3, t3) 1505 1506 mfsp sr2, t1 1507 mfsp sr4, t2 1508 stw t1, TF_SR2(sr3, t3) 1509 stw t2, TF_SR4(sr3, t3) 1510 1511 mfsp sr5, t2 1512 mfsp sr6, t1 1513 stw t2, TF_SR5(sr3, t3) 1514 stw t1, TF_SR6(sr3, t3) 1515 1516 mfsp sr7, t1 1517 mfctl pidr2, t2 1518 stw t1, TF_SR7(sr3, t3) 1519 stw t2, TF_CR9(sr3, t3) 1520 1521 mtsp r0, sr0 1522 mtsp r0, sr1 1523 mtsp r0, sr2 1524 mtsp r0, sr4 1525 mtsp r0, sr5 1526 mtsp r0, sr6 1527 mtsp r0, sr7 1528 1529#if pbably_not_worth_it 1530 mfctl pidr3, t1 1531 mfctl pidr4, t2 1532 stw t1, TF_CR12(t3) 1533 stw t2, TF_CR13(t3) 1534#endif 1535 1536 /* 1537 * Save all general registers that we haven't saved already 1538 */ 1539 1540 mfctl sar, t1 /* use ,bc each cache line */ 1541 stw t1, TF_CR11(t3) 1542 stw r1, TF_R1(t3) 1543 stw r2, TF_R2(t3) 1544 stw r3, TF_R3(t3) 1545 1546 copy sp, r3 1547 stw,mb r0, -HPPA_FRAME_SIZE(r3) 1548 1549 /* 1550 * Copy partially saved state from the store into the frame 1551 */ 1552 mfctl cr29, t2 1553 ldo CI_TRAP_SAVE(t2), t2 1554 /* use ,bc each cache line */ 1555 ldw 0(t2), r1 ! ldw 4(t2), t1 ! stw r1, 0(t3) ! stw t1, 4(t3) 1556 ldw 8(t2), r1 ! ldw 12(t2), t1 ! stw r1, 8(t3) ! stw t1, 12(t3) 1557 ldw 16(t2), r1 ! ldw 20(t2), t1 ! stw r1, 16(t3) ! stw t1, 20(t3) 1558 ldw 24(t2), r1 ! ldw 28(t2), t1 ! stw r1, 24(t3) ! stw t1, 28(t3) 1559 ldw 32(t2), r1 ! ldw 36(t2), t1 ! stw r1, 32(t3) ! stw t1, 36(t3) 1560 ldw 40(t2), r1 ! ldw 44(t2), t1 ! stw r1, 40(t3) ! stw t1, 44(t3) 1561 ldw 48(t2), r1 ! ldw 52(t2), t1 ! stw r1, 48(t3) ! stw t1, 52(t3) 1562 ldw 56(t2), r1 ! ldw 60(t2), t1 ! stw r1, 56(t3) ! stw t1, 60(t3) 1563 1564 stw r4, TF_R4(t3) 1565 stw r5, TF_R5(t3) 1566 stw r6, TF_R6(t3) 1567 stw r7, TF_R7(t3) 1568 stw r8, TF_R8(t3) 1569 stw r9, TF_R9(t3) 1570 stw r10, TF_R10(t3) 1571 stw r11, TF_R11(t3) 1572 stw r12, TF_R12(t3) 1573 stw r13, TF_R13(t3) 1574 stw r14, TF_R14(t3) 1575 stw r15, TF_R15(t3) 1576 stw r16, TF_R16(t3) 1577 stw r17, TF_R17(t3) 1578 stw r18, TF_R18(t3) 1579 stw r19, TF_R19(t3) /* t4 */ 1580 stw r23, TF_R23(t3) 1581 stw r24, TF_R24(t3) 1582 stw r25, TF_R25(t3) 1583 stw r26, TF_R26(t3) 1584 stw r27, TF_R27(t3) 1585 stw r28, TF_R28(t3) 1586 stw r29, TF_R29(t3) 1587 stw r31, TF_R31(t3) 1588 1589 /* 1590 * Save the necessary control registers that have not already saved. 1591 */ 1592 1593#ifdef DDB 1594 /* 1595 * Save hpt mask and v2p translation table pointer 1596 */ 1597 mfctl eirr, t1 1598 mfctl vtop, t2 1599 stw t1, TF_CR23(t3) 1600 stw t2, TF_CR25(t3) 1601 1602 mfctl cr28, t2 1603 stw t2, TF_CR28(t3) 1604#endif 1605 mfctl cr27, t1 1606 mfctl cr30, t2 1607 stw t1, TF_CR27(t3) 1608 stw t2, TF_CR30(t3) 1609 1610 /* 1611 * load the global pointer for the kernel 1612 */ 1613 1614 ldil L%$global$, dp 1615 ldo R%$global$(dp), dp 1616 1617 /* 1618 * call the C routine trap(). 1619 * form trap type in the first argument to trap() 1620 */ 1621 ldw TF_FLAGS(t3), arg0 1622 dep r0, 24, 25, arg0 1623 copy t3, arg1 1624 1625 copy arg0, r4 1626 copy arg1, r5 1627 1628 .import trap, code 1629 ldil L%trap,t1 1630 ldo R%trap(t1),t1 1631 .call 1632 blr r0,rp 1633 bv,n r0(t1) 1634 nop 1635 1636 copy r5, t3 1637 1638 /* see if curproc have changed */ 1639 extru,<> r4, TFF_LAST_POS, 1, r0 1640 b $syscall_return 1641 1642 /* see if curproc have really changed */ 1643 mfctl cr29, t1 1644 ldw CI_CURPROC(t1), t2 1645 sub,<> r0, t2, r0 1646 ldw P_MD_REGS(t2), t3 1647 1648 /* means curproc has actually changed */ 1649 b $syscall_return 1650 nop 1651EXIT(TLABEL(all)) 1652 1653#if defined(HP7000_CPU) 1654/* 1655 * void desidhash_s(void) 1656 */ 1657LEAF_ENTRY(desidhash_s) 1658 sync 1659 MFCPU_C_PCXST(DR_CPUCFG,22) /* t1 */ 1660 MFCPU_C_PCXST(DR_CPUCFG,22) 1661 nop 1662 nop 1663 depi 0, DR0_PCXS_DHE, 3, t1 /* 3: DR0_PCXS_DOMAIN|DR0_PCXS_IHE */ 1664 depi 1, DR0_PCXS_EQWSTO, 1, t1 1665 /* clear `write to clear' bits so they don't get reset */ 1666 depi 0, DR0_PCXS_DHPMC, 1, t1 1667 depi 0, DR0_PCXS_ILPMC, 1, t1 1668 sync 1669 MTCPU_PCXST(22,DR_CPUCFG) 1670 MTCPU_PCXST(22,DR_CPUCFG) 1671 nop 1672 nop 1673 bv 0(rp) 1674 extru t1, 4, 5, ret0 /* return chip revision */ 1675EXIT(desidhash_s) 1676#endif /* HP7000_CPU */ 1677 1678#if defined(HP7100_CPU) || defined(HP7200_CPU) 1679/* 1680 * void desidhash_t(void) 1681 */ 1682LEAF_ENTRY(desidhash_t) 1683 sync 1684 MFCPU_C_PCXST(DR_CPUCFG,22) /* t1 */ 1685 MFCPU_C_PCXST(DR_CPUCFG,22) 1686 nop 1687 nop 1688 depi 0, DR0_PCXT_IHE, 1, t1 1689 depi 0, DR0_PCXT_DHE, 1, t1 1690 /* clear `write to clear' bits so they don't get reset */ 1691 depi 0, DR0_PCXT_DHPMC, 1, t1 1692 depi 0, DR0_PCXT_ILPMC, 1, t1 1693 sync 1694 MTCPU_PCXST(22,DR_CPUCFG) 1695 MTCPU_PCXST(22,DR_CPUCFG) 1696 nop 1697 nop 1698 bv 0(rp) 1699 extru t1, 4, 5, ret0 /* return chip revision */ 1700EXIT(desidhash_t) 1701#endif /* HP7100_CPU || HP7200_CPU */ 1702 1703#ifdef HP7300LC_CPU 1704 .data 1705 BSS(eaio_l2_mask, 4) 1706LEAF_ENTRY(eaio_l2) 1707 ldil L%eaio_l2_mask, t2 1708 ldw R%eaio_l2_mask(t2), t1 1709 or t1, arg0, t1 1710 MTCPU_PCXL(22, DR0_PCXL2_ACCEL_IO) 1711 nop 1712 nop 1713 bv 0(rp) 1714 stw t1, R%eaio_l2_mask(t2) 1715EXIT(eaio_l2) 1716#endif /* HP7300LC_CPU */ 1717 1718#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU) 1719 1720/* 1721 * int 1722 * ibtlb_l(int i, pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz, u_int prot) 1723 */ 1724LEAF_ENTRY(ibtlb_l) 1725 rsm (PSL_R|PSL_I), t4 1726 nop ! nop ! nop ! nop ! nop ! nop ! nop 1727 1728 bv 0(rp) 1729 mtsm t4 1730EXIT(ibtlb_l) 1731 1732/* 1733 * int desidhash_l(void) 1734 */ 1735LEAF_ENTRY(desidhash_l) 1736 MFCPU_C_PCXL(DR_CPUCFG,22) /* t1 */ 1737 nop 1738 nop 1739 depi 0, DR0_PCXL_L2IHASH_EN, 2, t1 /* 2: DR0_PCXL_L2DHASH_EN */ 1740#if 0 /* better trust the PROM if it left some bits set here */ 1741 depi 0, DR0_PCXL_DUAL_DIS, 2, t1 1742#endif 1743 /* clear `write to clear' bits so they don't get reset */ 1744 depi 0, DR0_PCXL_L2IHPMC, 1, t1 1745 depi 0, DR0_PCXL_L2DHPMC, 1, t1 1746 depi 0, DR0_PCXL_L1IHPMC, 1, t1 1747 depi 0, DR0_PCXL_L2PARERR, 4, t1 1748 sync 1749 MTCPU_PCXL(22,DR_CPUCFG) 1750 nop 1751 nop 1752 bv 0(rp) 1753 extru t1, 4, 5, ret0 /* return chip revision */ 1754EXIT(desidhash_l) 1755 1756#endif /* HP7100LC_CPU */ 1757 1758#if defined(HP8000_CPU) || defined(HP8200_CPU) || defined(HP8500_CPU) 1759 .level 2.0w 1760LEAF_ENTRY(desidhash_u) 1761 MFCPU_PCXU(2,28) 1762 depdi 0, 54, 1, r28 1763 MTCPU_PCXU(28,2) 1764 bv r0(rp) 1765 copy r0, ret0 /* XXX dunno how to get chip rev */ 1766EXIT(desidhash_u) 1767 1768LEAF_ENTRY(ibtlb_u) 1769 /* TODO insert a locked large tlb entry */ 1770 bv 0(rp) 1771 nop 1772EXIT(ibtlb_u) 1773 1774LEAF_ENTRY(pbtlb_u) 1775 /* TODO purge a locked tlb entry */ 1776 bv 0(rp) 1777 nop 1778EXIT(pbtlb_u) 1779 .level 1.1 1780#endif /* HP8000_CPU */ 1781 1782/* 1783 * High Priority Machine Check Interrupt 1784 */ 1785 .export TLABEL(hpmc), entry 1786ENTRY(TLABEL(hpmc),0) 1787ALTENTRY(hpmc_tramp) 1788 1789 mtsp r0, sr0 1790 ldil L%hppa_vtop, t1 1791 ldw R%hppa_vtop(t1), t1 1792 mtctl t1, CR_VTOP 1793 1794 .import hpmc_dump, code 1795 ldil L%hpmc_dump, rp 1796 ldo R%hpmc_dump(rp), rp 1797 mfctl cr29, %arg2 1798 ldw CI_PSW(%arg2), %arg2 1799 depi 0, PSL_I_POS, 1, %arg2 1800 stw %arg2, CI_PSW(t1) 1801 ldil L%emrg_stack, arg1 1802 b $kernel_setup 1803 ldw R%emrg_stack(arg1), arg1 1804 1805 /* never returns, but still */ 1806 ldil L%HPPA_GBCAST, t1 1807 ldi CMD_RESET, t2 1808 stw t2, R%HPPA_GBCAST(t1) 1809hpmc_never_dies 1810 b hpmc_never_dies 1811 nop 1812ALTENTRY(hpmc_tramp_end) 1813EXIT(TLABEL(hpmc)) 1814 1815/* 1816 * transfer of control handler 1817 */ 1818ENTRY(hppa_toc,0) 1819 1820 mtsp r0, sr0 1821 ldil L%hppa_vtop, t1 1822 ldw R%hppa_vtop(t1), t1 1823 mtctl t1, CR_VTOP 1824 1825 /* TODO reload btlb */ 1826 1827 .import boot, code 1828 ldil L%boot, rp 1829 ldo R%boot(rp), rp 1830 mfctl cr29, %arg2 1831 ldw CI_PSW(%arg2), %arg2 1832 depi 0, PSL_I_POS, 1, %arg2 1833 stw %arg2, CI_PSW(t1) 1834 ldi 0, arg0 1835 ldil L%emrg_stack, arg1 1836 b $kernel_setup 1837 ldw R%emrg_stack(arg1), arg1 1838 1839ALTENTRY(hppa_toc_end) 1840 .word 0 1841EXIT(hppa_toc) 1842 1843/* 1844 * power fail recovery handler 1845 */ 1846ENTRY(hppa_pfr,0) 1847 1848 mtsp r0, sr0 1849 ldil L%hppa_vtop, t1 1850 ldw R%hppa_vtop(t1), t1 1851 mtctl t1, CR_VTOP 1852 1853 /* TODO reload btlb */ 1854 1855 .import boot, code 1856 ldil L%boot, rp 1857 ldo R%boot(rp), rp 1858 mfctl cr29, %arg2 1859 ldw CI_PSW(%arg2), %arg2 1860 depi 0, PSL_I_POS, 1, %arg2 1861 stw %arg2, CI_PSW(t1) 1862 ldi RB_HALT|RB_POWERDOWN, arg0 1863 ldil L%emrg_stack, arg1 1864 b $kernel_setup 1865 ldw R%emrg_stack(arg1), arg1 1866 1867ALTENTRY(hppa_pfr_end) 1868 .word 0 1869EXIT(hppa_pfr) 1870 1871#if 0 1872 .align 8 1873intr_ticks 1874 .word 0, 0 1875 1876#define INTR_PROF_PRE \ 1877 mfctl itmr, r9 ! \ 1878 mtctl r9, tr5 1879#define INTR_PROF_AFT \ 1880 mfctl itmr, r8 ! \ 1881 mfctl tr5, r9 ! \ 1882 ldil L%intr_ticks, r1 ! \ 1883 ldo R%intr_ticks(r1), r1 ! \ 1884 sub r8, r9, r8 ! \ 1885 ldw 0(r1), r16 ! \ 1886 ldw 4(r1), r17 ! \ 1887 add r8, r16, r16 ! \ 1888 addi 1, r17, r17 ! \ 1889 stw r16, 0(r1) ! \ 1890 stw r17, 4(r1) 1891#else 1892#define INTR_PROF_PRE /* */ 1893#define INTR_PROF_AFT /* */ 1894#endif 1895 1896 .import imask, data 1897 .import intr_table, data 1898 .align 32 1899ENTRY(TLABEL(intr),0) 1900 /* 1901 * r8 is set to eirr in the INTRPRE 1902 */ 1903 1904 INTR_PROF_PRE 1905 1906 ldil L%intr_table + 32*32, r1 1907 ldo R%intr_table + 32*32(r1), r1 1908 mfctl cr29, r17 1909 b $intr_cont 1910 ldw CI_IPENDING(r17), r24 1911 1912$intr_ffs 1913 addi -32, r1, r1 1914 bb,>= r8, 0, $intr_ffs 1915 zdep r8, 30, 31, r8 1916 1917 ldw 0(r1), r17 1918 bb,>=,n r17, 23, $intr_nocall 1919 1920 ldw 2*4(r1), r16 /* func */ 1921 ldw 3*4(r1), r9 /* arg: ioreg */ 1922 mtctl r1, tr7 1923 bv r0(r16) 1924 ldw 6*4(r1), r1 /* next: sub-intr_table */ 1925 1926$intr_nocall 1927 ldw 4*4(r1), r17 /* bit */ 1928 or r17, r24, r24 /* ipending */ 1929 1930 /* also return from nested handlers */ 1931$intr_cont 1932 comb,<>,n r0, r8, $intr_ffs 1933 ldw -32(r1), r0 /* preload cache */ 1934 1935 mfctl cr29, r17 1936 stw r24, CI_IPENDING(r17) 1937 ldw CI_CPL(r17), r17 1938 ldil L%imask, r16 1939 ldo R%imask(r16), r16 1940 ldwx,s r17(r16), r25 1941 1942 INTR_PROF_AFT 1943 1944 ldi T_INTERRUPT, r1 1945 andcm,= r24, r25, r0 1946 b TLABEL(all) 1947 nop 1948 1949 rfir 1950 nop 1951EXIT(TLABEL(intr)) 1952 1953/* 1954 * called with: 1955 * r1 sub intr_table 1956 * r9 ioregs 1957 * r24 ipending (in/out) 1958 * tr7 saved r1 (restore on return) 1959 * free: 1960 * r9, r16, r17, r25 1961 */ 1962 .align 32 1963LEAF_ENTRY(gsc_intr) 1964 ldw 0(r9), r16 /* irr */ 1965 1966 /* we know that first 5 bits are never used ... should skip */ 1967$gsc_intr_loop 1968 comb,=,n r0, r16, $intr_cont 1969 mfctl tr7, r1 1970$gsc_ffs 1971 addi 32, r1, r1 1972 bb,>= r16, 31, $gsc_ffs 1973 shd r0, r16, 1, r16 1974 1975 ldo -32(r1), r9 1976$gsc_share 1977 ldw 4*4(r9), r17 /* bit */ 1978 ldw 5*4(r9), r9 /* share */ 1979 1980 comb,<> r0, r9, $gsc_share 1981 or r17, r24, r24 /* ipending */ 1982 1983 b,n $gsc_intr_loop 1984EXIT(gsc_intr) 1985 1986 /* see above for calling conventions */ 1987 .align 32 1988LEAF_ENTRY(dino_intr) 1989 ldw 3*4(r9), r16 /* irr0 */ 1990 1991$dino_intr_loop 1992 comb,=,n r0, r16, $intr_cont 1993 mfctl tr7, r1 1994$dino_ffs 1995 addi 32, r1, r1 1996 bb,>= r16, 31, $dino_ffs 1997 shd r0, r16, 1, r16 1998 1999 ldo -32(r1), r9 2000$dino_share 2001 ldw 4*4(r9), r17 /* bit */ 2002 ldw 5*4(r9), r9 /* share */ 2003 2004 comb,<> r0, r9, $dino_share 2005 or r17, r24, r24 /* ipending */ 2006 2007 b,n $dino_intr_loop 2008EXIT(dino_intr) 2009 2010 .export TLABEL(ibrk), entry 2011ENTRY(TLABEL(ibrk),0) 2012 /* If called by a user process then always pass it to trap() */ 2013 mfctl pcoq, r8 2014 extru,= r8, 31, 2, r0 2015 b,n $ibrk_bad 2016 2017 /* don't accept breaks from data segments */ 2018 .import etext 2019 ldil L%etext, r9 2020 ldo R%etext(r9), r9 2021 comb,>>=,n r8, r9, $ibrk_bad 2022 2023 mfctl iir, r8 2024 extru r8, 31, 5, r9 2025 comib,<>,n HPPA_BREAK_KERNEL, r9, $ibrk_bad 2026 2027 /* now process all those `break' calls we make */ 2028 extru r8, 18, 13, r9 2029 comib,=,n HPPA_BREAK_GET_PSW, r9, $ibrk_getpsw 2030 comib,=,n HPPA_BREAK_SET_PSW, r9, $ibrk_setpsw 2031 comib,=,n HPPA_BREAK_SPLLOWER, r9, $ibrk_spllower 2032 2033$ibrk_bad 2034 /* illegal (unimplemented) break entry point */ 2035 b TLABEL(all) 2036 nop 2037 2038$ibrk_getpsw 2039 b $ibrk_exit 2040 mfctl ipsw, ret0 2041 2042$ibrk_setpsw 2043 mfctl ipsw, ret0 2044 b $ibrk_exit 2045 mtctl arg0, ipsw 2046 2047$ibrk_spllower 2048 /* skip the break */ 2049 mtctl r0, pcoq 2050 mfctl pcoq, r9 2051 mtctl r9, pcoq 2052 ldo 4(r9), r9 2053 mtctl r9, pcoq 2054 2055 mfctl cr29, r17 2056 ldw CI_IPENDING(r17), r8 2057 ldil L%imask, r9 2058 ldo R%imask(r9), r9 2059 ldw CI_CPL(r17), ret0 2060 ldwx,s arg0(r9), r16 2061 stw arg0, CI_CPL(r17) 2062 ldi T_INTERRUPT, r1 2063 andcm,= r8, r16, r0 2064 b TLABEL(all) 2065 nop 2066 rfir 2067 nop 2068 2069 /* insert other fast breaks here */ 2070 nop ! nop 2071 2072$ibrk_exit 2073 /* skip the break */ 2074 mtctl r0, pcoq 2075 mfctl pcoq, r9 2076 mtctl r9, pcoq 2077 ldo 4(r9), r9 2078 mtctl r9, pcoq 2079 2080 rfir 2081 nop 2082EXIT(TLABEL(ibrk)) 2083 2084LEAF_ENTRY(fpu_exit) 2085 /* enable coprocessor XXX */ 2086 depi 3, 25, 2, r1 2087 mtctl r1, ccr 2088 2089 ldil L%fpu_scratch, %r25 2090 ldo R%fpu_scratch(%r25), %r25 2091 fstds %fr0, 0(%r25) 2092 sync 2093 bv %r0(%rp) 2094 mtctl r0, ccr 2095EXIT(fpu_exit) 2096 2097LEAF_ENTRY(fpu_save) 2098 fstds,ma %fr0 , 8(arg0) 2099 fstds,ma %fr1 , 8(arg0) 2100 fstds,ma %fr2 , 8(arg0) 2101 fstds,ma %fr3 , 8(arg0) 2102 fstds,ma %fr4 , 8(arg0) 2103 fstds,ma %fr5 , 8(arg0) 2104 fstds,ma %fr6 , 8(arg0) 2105 fstds,ma %fr7 , 8(arg0) 2106 fstds,ma %fr8 , 8(arg0) 2107 fstds,ma %fr9 , 8(arg0) 2108 fstds,ma %fr10, 8(arg0) 2109 fstds,ma %fr11, 8(arg0) 2110 fstds,ma %fr12, 8(arg0) 2111 fstds,ma %fr13, 8(arg0) 2112 fstds,ma %fr14, 8(arg0) 2113 fstds,ma %fr15, 8(arg0) 2114 fstds,ma %fr16, 8(arg0) 2115 fstds,ma %fr17, 8(arg0) 2116 fstds,ma %fr18, 8(arg0) 2117 fstds,ma %fr19, 8(arg0) 2118 fstds,ma %fr20, 8(arg0) 2119 fstds,ma %fr21, 8(arg0) 2120 fstds,ma %fr22, 8(arg0) 2121 fstds,ma %fr23, 8(arg0) 2122 fstds,ma %fr24, 8(arg0) 2123 fstds,ma %fr25, 8(arg0) 2124 fstds,ma %fr26, 8(arg0) 2125 fstds,ma %fr27, 8(arg0) 2126 fstds,ma %fr28, 8(arg0) 2127 fstds,ma %fr29, 8(arg0) 2128 fstds,ma %fr30, 8(arg0) 2129 fstds %fr31, 0(arg0) 2130 bv r0(rp) 2131 sync 2132EXIT(fpu_save) 2133 2134#ifdef FPEMUL 2135 /* 2136 * Emulate FPU 2137 * 2138 * iisq:iioq - exception triggered instruction 2139 */ 2140ENTRY($fpu_emulate,320) 2141 copy r31, r9 2142 2143 mfctl cr29, r31 2144 ldw CI_STACK(r31), r31 2145 2146 /* stw r1 , TF_R1 (r31) shadowed */ 2147 stw r2 , TF_R2 (r31) 2148 stw r3 , TF_R3 (r31) 2149 stw r4 , TF_R4 (r31) 2150 stw r5 , TF_R5 (r31) 2151 stw r6 , TF_R6 (r31) 2152 stw r7 , TF_R7 (r31) 2153 /* stw r8 , TF_R8 (r31) shadowed */ 2154 /* stw r9 , TF_R9 (r31) shadowed */ 2155 stw r10, TF_R10(r31) 2156 stw r11, TF_R11(r31) 2157 stw r12, TF_R12(r31) 2158 stw r13, TF_R13(r31) 2159 stw r14, TF_R14(r31) 2160 stw r15, TF_R15(r31) 2161 /* stw r16, TF_R16(r31) shadowed */ 2162 /* stw r17, TF_R17(r31) shadowed */ 2163 stw r18, TF_R18(r31) 2164 stw r19, TF_R19(r31) 2165 stw r20, TF_R20(r31) 2166 stw r21, TF_R21(r31) 2167 stw r22, TF_R22(r31) 2168 stw r23, TF_R23(r31) 2169 /* stw r24, TF_R24(r31) shadowed */ 2170 /* stw r25, TF_R25(r31) shadowed */ 2171 stw r26, TF_R26(r31) 2172 stw r27, TF_R27(r31) 2173 stw r28, TF_R28(r31) 2174 stw r29, TF_R29(r31) 2175 stw sp, TF_R30(r31) 2176 stw r9, TF_R31(r31) 2177 copy r1, arg0 2178 mfctl sar, r1 2179 stw r1, TF_CR11(r31) 2180 stw arg0, TF_CR19(r31) 2181 2182 ldo TRAPFRAME_SIZEOF(r31), r3 2183 ldo TRAPFRAME_SIZEOF+HPPA_FRAME_SIZE(r31), sp 2184 2185 ldil L%$global$, dp 2186 ldo R%$global$(dp), dp 2187 2188 .import fpu_emulate, code 2189 ldil L%fpu_emulate,t1 2190 ldo R%fpu_emulate(t1),t1 2191 mfctl cr30, arg2 2192 .call 2193 blr r0,rp 2194 bv,n 0(t1) 2195 nop 2196 2197 mfctl cr30, r25 2198 ldi 32, r1 2199 2200 ldw 4(r25), r17 /* fpu exception reg 0 */ 2201 zdep ret0, 5, 6, r17 /* intentionally zero the insn */ 2202 stw r17, 4(r25) 2203 2204 mfctl cr29, r31 2205 ldw CI_STACK(r31), r31 2206 2207 ldw TF_CR11(r31), r1 2208 ldw TF_R2 (r31), r2 2209 ldw TF_R3 (r31), r3 2210 mtsar r1 2211 copy ret0, r1 2212 ldw TF_R4 (r31), r4 2213 ldw TF_R5 (r31), r5 2214 ldw TF_R6 (r31), r6 2215 ldw TF_R7 (r31), r7 2216 /* ldw TF_R8 (r31), r8 shadowed */ 2217 /* ldw TF_R9 (r31), r9 shadowed */ 2218 ldw TF_R10(r31), r10 2219 ldw TF_R11(r31), r11 2220 ldw TF_R12(r31), r12 2221 ldw TF_R13(r31), r13 2222 ldw TF_R14(r31), r14 2223 ldw TF_R15(r31), r15 2224 /* ldw TF_R16(r31), r16 shadowed */ 2225 /* ldw TF_R17(r31), r17 shadowed */ 2226 ldw TF_R18(r31), r18 2227 ldw TF_R19(r31), r19 2228 ldw TF_R20(r31), r20 2229 ldw TF_R21(r31), r21 2230 ldw TF_R22(r31), r22 2231 ldw TF_R23(r31), r23 2232 /* ldw TF_R24(r31), r24 shadowed */ 2233 /* ldw TF_R25(r31), r25 shadowed */ 2234 ldw TF_R26(r31), r26 2235 ldw TF_R27(r31), r27 2236 ldw TF_R28(r31), r28 2237 ldw TF_R29(r31), r29 2238 ldw TF_R30(r31), r30 2239 ldw TF_R31(r31), r31 2240 2241 bb,>=,n r1, 24, $fpu_emulate_done 2242 2243 b TLABEL(all) 2244 ldi T_EMULATION, r1 2245 2246$fpu_emulate_done 2247 comb,<> r0, r1, TLABEL(all) 2248 ldi T_EXCEPTION, r1 2249 2250 rfir 2251 nop 2252EXIT($fpu_emulate) 2253 2254#endif /* FPEMUL */ 2255 2256 .import dcache_stride, data 2257LEAF_ENTRY(fdcache) 2258 ldil L%dcache_stride,t1 2259 ldw R%dcache_stride(t1), arg3 2260 2261 mtsp arg0, sr1 /* move the space register to sr1 */ 2262 add arg1, arg2, arg0 /* get the last byte to flush in arg0 */ 2263 2264 zdep arg3, 27, 28, t1 /* get size of a 16X loop in t1 */ 2265 comb,< arg2, t1, fdc_short /* check for count < 16 * stride */ 2266 addi -1, t1, t1 /* compute size of large loop - 1 */ 2267 2268 andcm arg2, t1, t1 /* L = count - (count mod lenbigloop) */ 2269 add arg1, t1, t1 /* ub for big loop is lb + L */ 2270 2271 fdc,m arg3(sr1, arg1) /* Start flushing first cache line. */ 2272fdc_long 2273 fdc,m arg3(sr1, arg1) 2274 fdc,m arg3(sr1, arg1) 2275 fdc,m arg3(sr1, arg1) 2276 fdc,m arg3(sr1, arg1) 2277 fdc,m arg3(sr1, arg1) 2278 fdc,m arg3(sr1, arg1) 2279 fdc,m arg3(sr1, arg1) 2280 fdc,m arg3(sr1, arg1) 2281 fdc,m arg3(sr1, arg1) 2282 fdc,m arg3(sr1, arg1) 2283 fdc,m arg3(sr1, arg1) 2284 fdc,m arg3(sr1, arg1) 2285 fdc,m arg3(sr1, arg1) 2286 fdc,m arg3(sr1, arg1) 2287 fdc,m arg3(sr1, arg1) 2288 comb,<<,n arg1, t1, fdc_long 2289 fdc,m arg3(sr1, arg1) 2290fdc_short /* flush one line at a time */ 2291 comb,<<,n arg1, arg0, fdc_short 2292 fdc,m arg3(sr1, arg1) 2293 2294 addi -1, arg0, arg1 2295 fdc r0(sr1, arg1) 2296 2297 sync 2298 syncdma 2299 bv r0(r2) 2300 nop 2301EXIT(fdcache) 2302 2303 .import dcache_stride, data 2304LEAF_ENTRY(pdcache) 2305 ldil L%dcache_stride,t1 2306 ldw R%dcache_stride(t1), arg3 2307 2308 mtsp arg0, sr1 /* move the space register to sr1 */ 2309 add arg1, arg2, arg0 /* get the last byte to purge in arg0 */ 2310 2311 zdep arg3, 27, 28, t1 /* get size of a 16X loop in t1 */ 2312 comb,< arg2, t1, pdc_short /* check for count < 16 * stride */ 2313 addi -1, t1, t1 /* compute size of large loop - 1 */ 2314 2315 andcm arg2, t1, t1 /* L = count - (count mod lenbigloop) */ 2316 add arg1, t1, t1 /* ub for big loop is lb + L */ 2317 2318 pdc,m arg3(sr1, arg1) /* Start purging first cache line. */ 2319pdc_long 2320 pdc,m arg3(sr1, arg1) 2321 pdc,m arg3(sr1, arg1) 2322 pdc,m arg3(sr1, arg1) 2323 pdc,m arg3(sr1, arg1) 2324 pdc,m arg3(sr1, arg1) 2325 pdc,m arg3(sr1, arg1) 2326 pdc,m arg3(sr1, arg1) 2327 pdc,m arg3(sr1, arg1) 2328 pdc,m arg3(sr1, arg1) 2329 pdc,m arg3(sr1, arg1) 2330 pdc,m arg3(sr1, arg1) 2331 pdc,m arg3(sr1, arg1) 2332 pdc,m arg3(sr1, arg1) 2333 pdc,m arg3(sr1, arg1) 2334 pdc,m arg3(sr1, arg1) 2335 comb,<<,n arg1, t1, pdc_long 2336 pdc,m arg3(sr1, arg1) 2337pdc_short /* purge one line at a time */ 2338 comb,<<,n arg1, arg0, pdc_short 2339 pdc,m arg3(sr1, arg1) 2340 2341 addi -1, arg0, arg1 2342 pdc r0(sr1, arg1) 2343 2344 sync 2345 syncdma 2346 bv r0(r2) 2347 nop 2348EXIT(pdcache) 2349 2350 .import icache_stride, data 2351LEAF_ENTRY(ficache) 2352 ldil L%icache_stride,t1 2353 ldw R%icache_stride(t1), arg3 2354 2355 mtsp arg0, sr1 /* move the space register to sr1 */ 2356 add arg1, arg2, arg0 /* get the last byte to flush in arg0 */ 2357 2358 zdep arg3, 27, 28, t1 /* get size of a 16X loop in t1 */ 2359 comb,< arg2, t1, fic_short /* check for count < 16 * stride */ 2360 addi -1, t1, t1 /* compute size of large loop - 1 */ 2361 2362 andcm arg2, t1, t1 /* L = count - (count mod lenbigloop) */ 2363 add arg1, t1, t1 /* ub for big loop is lb + L */ 2364 2365 fic,m arg3(sr1, arg1) /* Start flushing first cache line. */ 2366fic_long 2367 fic,m arg3(sr1, arg1) 2368 fic,m arg3(sr1, arg1) 2369 fic,m arg3(sr1, arg1) 2370 fic,m arg3(sr1, arg1) 2371 fic,m arg3(sr1, arg1) 2372 fic,m arg3(sr1, arg1) 2373 fic,m arg3(sr1, arg1) 2374 fic,m arg3(sr1, arg1) 2375 fic,m arg3(sr1, arg1) 2376 fic,m arg3(sr1, arg1) 2377 fic,m arg3(sr1, arg1) 2378 fic,m arg3(sr1, arg1) 2379 fic,m arg3(sr1, arg1) 2380 fic,m arg3(sr1, arg1) 2381 fic,m arg3(sr1, arg1) 2382 comb,<<,n arg1, t1, fic_long 2383 fic,m arg3(sr1, arg1) 2384fic_short /* flush one line at a time */ 2385 comb,<<,n arg1, arg0, fic_short 2386 fic,m arg3(sr1, arg1) 2387 2388 addi -1, arg0, arg1 2389 fic r0(sr1, arg1) 2390 2391 sync 2392 syncdma 2393 bv r0(r2) 2394 nop 2395EXIT(ficache) 2396 2397#ifdef DDB 2398LEAF_ENTRY(setjmp) 2399/* 2400 * Save the other general registers whose contents are expected to remain 2401 * across function calls. According to the "HP 9000 Series 800 Assembly 2402 * Language Reference Manual", procedures can use general registers 19-26, 2403 * 28, 29, 1, and 31 without restoring them. Hence, we do not save these. 2404 */ 2405 stwm r3,4(arg0) 2406 stwm r4,4(arg0) 2407 stwm r5,4(arg0) 2408 stwm r6,4(arg0) 2409 stwm r7,4(arg0) 2410 stwm r8,4(arg0) 2411 stwm r9,4(arg0) 2412 stwm r10,4(arg0) 2413 stwm r11,4(arg0) 2414 stwm r12,4(arg0) 2415 stwm r13,4(arg0) 2416 stwm r14,4(arg0) 2417 stwm r15,4(arg0) 2418 stwm r16,4(arg0) 2419 stwm r17,4(arg0) 2420 stwm r18,4(arg0) 2421 stwm r27,4(arg0) /* Good idea to save the data pointer (dp) */ 2422 stwm rp,4(arg0) /* Save the return pointer */ 2423 stwm sp,4(arg0) /* Save the original stack pointer */ 2424 2425 bv 0(rp) 2426 copy r0, ret0 2427EXIT(setjmp) 2428 2429LEAF_ENTRY(longjmp) 2430/* 2431 * Restore general registers. 2432 */ 2433 ldwm 4(arg0),r3 2434 ldwm 4(arg0),r4 2435 ldwm 4(arg0),r5 2436 ldwm 4(arg0),r6 2437 ldwm 4(arg0),r7 2438 ldwm 4(arg0),r8 2439 ldwm 4(arg0),r9 2440 ldwm 4(arg0),r10 2441 ldwm 4(arg0),r11 2442 ldwm 4(arg0),r12 2443 ldwm 4(arg0),r13 2444 ldwm 4(arg0),r14 2445 ldwm 4(arg0),r15 2446 ldwm 4(arg0),r16 2447 ldwm 4(arg0),r17 2448 ldwm 4(arg0),r18 2449 ldwm 4(arg0),r27 2450 ldwm 4(arg0),rp /* Restore return address pointer, */ 2451 ldwm 4(arg0),sp /* stack pointer, */ 2452 2453 bv 0(rp) 2454 ldi 1, ret0 2455EXIT(longjmp) 2456#endif /* DDB */ 2457 2458 .align 32 2459 2460LEAF_ENTRY(copy_on_fault) 2461 mtsp r0, sr1 2462 mtsp r0, sr2 2463 stw r1, PCB_ONFAULT+U_PCB(r2) 2464 ldw HPPA_FRAME_CRP(sp), rp 2465 ldo -64(sp), sp 2466 bv 0(rp) 2467 ldi EFAULT, %ret0 2468EXIT(copy_on_fault) 2469 2470/* 2471 * int spstrcpy (pa_space_t ssp, const void *src, pa_space_t dsp, void *dst, 2472 * size_t size, size_t *rsize) 2473 * do a space to space strncpy, return actual copy size in the rsize; 2474 */ 2475LEAF_ENTRY(spstrcpy) 2476 ldw HPPA_FRAME_ARG(4)(sp), t2 2477 ldo 64(sp), sp 2478 add t2, arg1, t2 2479 stw rp, HPPA_FRAME_CRP(sp) 2480 /* setup fault handler */ 2481 mfctl cr29, t1 2482 ldw CI_CURPROC(t1), t3 2483 ldil L%copy_on_fault, t4 2484 ldw P_ADDR(t3), r2 2485 ldo R%copy_on_fault(t4), t4 2486 ldw PCB_ONFAULT+U_PCB(r2), r1 2487 stw t4, PCB_ONFAULT+U_PCB(r2) 2488 2489 mtsp arg0, sr1 2490 mtsp arg2, sr2 2491 copy arg1, arg0 2492 copy r0, ret0 2493 2494$spstrcpy_loop 2495 ldbs,ma 1(sr1, arg1), t1 2496 comb,= r0, t1, $spstrcpy_exit 2497 stbs,ma t1, 1(sr2, arg3) 2498 comb,<>,n t2, arg1, $spstrcpy_loop 2499 nop 2500 ldi ENAMETOOLONG, ret0 2501 2502$spstrcpy_exit 2503 mtsp r0, sr1 2504 mtsp r0, sr2 2505 stw r1, PCB_ONFAULT+U_PCB(r2) 2506 ldw HPPA_FRAME_CRP(sp), rp 2507 sub arg1, arg0, arg1 2508 ldo -64(sp), sp 2509 ldw HPPA_FRAME_ARG(5)(sp), arg0 2510 sub,= r0, arg0, r0 2511 stw arg1, 0(arg0) 2512 bv 0(rp) 2513 nop 2514EXIT(spstrcpy) 2515 2516/* 2517 * int spcopy32 (pa_space_t ssp, const uint32_t *src, pa_space_t dsp, 2518 * uint32_t *dst) 2519 * do an atomic space to space copy of a futex 2520 */ 2521LEAF_ENTRY(spcopy32) 2522 extru arg1, 31, 2, t3 2523 extru arg3, 31, 2, t4 2524 comb,<>,n 0, t3, $spcopy32_misaligned 2525 comb,<>,n 0, t4, $spcopy32_misaligned 2526 2527 ldo 64(sp), sp 2528 stw rp, HPPA_FRAME_CRP(sp) 2529 /* setup fault handler */ 2530 mfctl cr29, t1 2531 ldw CI_CURPROC(t1), t3 2532 ldil L%copy_on_fault, t2 2533 ldw P_ADDR(t3), r2 2534 ldo R%copy_on_fault(t2), t2 2535 ldw PCB_ONFAULT+U_PCB(r2), r1 2536 stw t2, PCB_ONFAULT+U_PCB(r2) 2537 2538 mtsp arg0, sr1 2539 mtsp arg2, sr2 2540 2541 ldw 0(sr1, arg1), t1 2542 stw t1, 0(sr2, arg3) 2543 2544 mtsp r0, sr1 2545 mtsp r0, sr2 2546 /* reset fault handler */ 2547 stw r1, PCB_ONFAULT+U_PCB(r2) 2548 ldw HPPA_FRAME_CRP(sp), rp 2549 ldo -64(sp), sp 2550 bv 0(rp) 2551 copy r0, ret0 2552 2553$spcopy32_misaligned 2554 bv 0(rp) 2555 ldi EFAULT, ret0 2556EXIT(spcopy32) 2557 2558/* 2559 * int cpu_switchto(struct proc *old, struct proc *new) 2560 * Switch from "old" proc to "new". 2561 */ 2562 .align 32 2563ENTRY(cpu_switchto,128) 2564 copy r3, r1 2565 stw rp, HPPA_FRAME_CRP(sp) 2566 copy sp, r3 2567 stwm r1, HPPA_FRAME_SIZE+16*4(sp) 2568 2569#ifdef DIAGNOSTIC 2570 b kstack_check 2571 nop 2572switch_error 2573 copy arg1, arg2 2574 copy arg0, arg1 2575 ldil L%panic, r1 2576 ldil L%Lcspstr, arg0 2577 ldo R%panic(r1), r1 2578 ldo R%Lcspstr(arg0), arg0 2579 .call 2580 blr %r0, rp 2581 bv,n %r0(r1) 2582 nop 2583Lcspstr 2584 .asciz "cpu_switch:old=%p, new=%p" 2585 .align 8 2586kstack_check 2587 /* 2588 * The new process' kernel stack must be reasonable. 2589 */ 2590 ldw P_ADDR(arg1), arg2 2591 ldw U_PCB+PCB_KSP(arg2), t1 2592 ldo NBPG(arg2), arg2 2593 comb,>>,n arg2, t1, switch_error 2594 nop 2595 sub t1, arg2, t1 2596 ldil L%USPACE, arg2 2597 ldo R%USPACE(arg2), arg2 2598 comb,<<=,n arg2, t1, switch_error 2599 nop 2600kstack_ok 2601#endif 2602 2603 /* Record new proc. */ 2604 ldi SONPROC, t1 2605 stb t1, P_STAT(arg1) 2606 mfctl cr29, t1 2607 stw arg1, CI_CURPROC(t1) 2608 2609 /* If old process exited, don't bother. */ 2610 comb,=,n r0, arg0, switch_exited 2611 2612 /* 2613 * 2. save old proc context 2614 * 2615 * arg0: old proc 2616 */ 2617 ldw P_ADDR(arg0), t1 2618 /* save callee-save registers */ 2619 stw r4, 1*4(r3) 2620 stw sp, U_PCB+PCB_KSP(t1) 2621 stw r5, 2*4(r3) 2622 stw r6, 3*4(r3) 2623 stw r7, 4*4(r3) 2624 stw r8, 5*4(r3) 2625 stw r9, 6*4(r3) 2626 stw r10, 7*4(r3) 2627 stw r11, 8*4(r3) 2628 stw r12, 9*4(r3) 2629 stw r13, 10*4(r3) 2630 stw r14, 11*4(r3) 2631 stw r15, 12*4(r3) 2632 stw r16, 13*4(r3) 2633 stw r17, 14*4(r3) 2634 stw r18, 15*4(r3) 2635 fdc r0(t1) 2636 stw r0, HPPA_FRAME_ARG(1)(sp) /* say no trampoline */ 2637 sync 2638 2639 /* don't need old curproc (arg0) starting from here */ 2640switch_exited 2641 /* 2642 * 3. restore new proc context 2643 * 2644 * arg1: new proc 2645 */ 2646 /* XXX disable interrupts? */ 2647 ldw P_ADDR(arg1), t2 2648 ldw P_MD_REGS(arg1), t1 2649 ldw U_PCB+PCB_KSP(t2), sp 2650 mtctl r0, ccr /* disable FPU */ 2651 ldw TF_CR30(t1), t2 2652 ldw TF_CR9(t1), t3 2653 mtctl t2, cr30 2654 mtctl t3, pidr2 2655 /* XXX enable interrupts? */ 2656 ldo -(HPPA_FRAME_SIZE+16*4)(sp), r3 2657 ldw HPPA_FRAME_ARG(0)(sp), arg0 2658 ldw HPPA_FRAME_ARG(1)(sp), t4 /* in case we're on trampoline */ 2659 sub,= r0, t4, r0 2660 b switch_return 2661 ldw 1*4(r3), r4 2662 ldw 2*4(r3), r5 2663 ldw 3*4(r3), r6 2664 ldw 4*4(r3), r7 2665 ldw 5*4(r3), r8 2666 ldw 6*4(r3), r9 2667 ldw 7*4(r3), r10 2668 ldw 8*4(r3), r11 2669 ldw 9*4(r3), r12 2670 ldw 10*4(r3), r13 2671 ldw 11*4(r3), r14 2672 ldw 12*4(r3), r15 2673 ldw 13*4(r3), r16 2674 ldw 14*4(r3), r17 2675 ldw 15*4(r3), r18 2676 2677switch_return 2678 ldw HPPA_FRAME_CRP(r3), rp 2679 bv 0(rp) 2680 ldwm -(HPPA_FRAME_SIZE+16*4)(sp), r3 2681EXIT(cpu_switchto) 2682 2683LEAF_ENTRY(cpu_idle_enter) 2684 bv 0(rp) 2685 nop 2686EXIT(cpu_idle_enter) 2687 2688LEAF_ENTRY(cpu_idle_cycle) 2689 bv 0(rp) 2690 nop 2691EXIT(cpu_idle_cycle) 2692 2693LEAF_ENTRY(cpu_idle_leave) 2694 bv 0(rp) 2695 nop 2696EXIT(cpu_idle_leave) 2697 2698ENTRY(proc_trampoline,0) 2699 copy r0, r3 2700 copy t4, r5 2701 copy arg0, r4 2702 bl proc_trampoline_mi, rp 2703 nop 2704 copy r4, arg0 2705 copy r5, t4 2706 .call 2707 blr r0, rp 2708 bv,n r0(t4) 2709 nop 2710 mfctl cr29, t1 2711 ldw CI_CURPROC(t1), t2 2712 .call 2713 b $syscall_return 2714 ldw P_MD_REGS(t2), t3 2715EXIT(proc_trampoline) 2716 2717#ifdef MULTIPROCESSOR 2718/* 2719 * Trampoline to spin up secondary processors. 2720 */ 2721ENTRY(hw_cpu_spinup_trampoline, 0) 2722 2723 /* 2724 * disable interrupts and turn off all bits in the psw so that 2725 * we start in a known state. 2726 */ 2727 rsm RESET_PSL, r0 2728 nop ! nop ! nop ! nop ! nop ! nop 2729 2730 /* get things ready for the kernel to run in virtual mode */ 2731 ldi HPPA_PID_KERNEL, r1 2732 mtctl r1, pidr1 2733 mtctl r1, pidr2 2734#if pbably_not_worth_it 2735 mtctl r0, pidr3 2736 mtctl r0, pidr4 2737#endif 2738 mtsp r0, sr0 2739 mtsp r0, sr1 2740 mtsp r0, sr2 2741 mtsp r0, sr3 2742 mtsp r0, sr4 2743 mtsp r0, sr5 2744 mtsp r0, sr6 2745 mtsp r0, sr7 2746 2747 /* 2748 * disable all coprocessors 2749 */ 2750 mtctl r0, ccr 2751 2752 /* 2753 * to keep the spl() routines consistent we need to put the correct 2754 * spl level into eiem, and reset any pending interrupts 2755 */ 2756 ldi -1, r1 2757 mtctl r0, eiem 2758 mtctl r1, eirr 2759 2760 /* 2761 * load address of interrupt vector table 2762 */ 2763 ldil L%$ivaaddr, t2 2764 ldo R%$ivaaddr(t2), t2 2765 mtctl t2, iva 2766 2767 /* 2768 * set up the dp pointer so that we can do quick references off of it 2769 */ 2770 ldil L%$global$,dp 2771 ldo R%$global$(dp),dp 2772 2773 /* 2774 * Store address of cpu_info in CR29. 2775 */ 2776 ldil L%cpu_hatch_info, r3 2777 ldw R%cpu_hatch_info(r3), r3 2778 mtctl r3, cr29 2779 2780 /* 2781 * Setup the stack frame for us to call C with and mark this as the 2782 * first frame on the stack. 2783 */ 2784 ldw CI_STACK(r3), sp 2785 stw,ma r0, HPPA_FRAME_SIZE(sp) 2786 stw r0, HPPA_FRAME_CRP(sp) 2787 stw r0, HPPA_FRAME_PSP(sp) 2788 2789 ldil L%TFF_LAST, t1 2790 stw t1, TF_FLAGS-TRAPFRAME_SIZEOF(sp) 2791 2792 /* Provide CPU with page tables. */ 2793 ldil L%hppa_vtop, t1 2794 ldw R%hppa_vtop(t1), t1 2795 mtctl t1, CR_VTOP 2796 2797 /* Turn on the Q bit so that we can handle TLB traps. */ 2798 ldil L%$q_enabled, t1 2799 ldo R%$q_enabled(t1), t1 2800 mtctl r0, pcsq 2801 mtctl r0, pcsq 2802 mtctl t1, pcoq 2803 ldo 4(t1), t1 2804 mtctl t1, pcoq 2805 ldi PSL_Q|PSL_I, t2 2806 mtctl t2, ipsw 2807 rfi 2808 nop 2809 2810$q_enabled 2811 2812 /* Call C routine to setup CPU. */ 2813 ldil L%cpu_hw_init, r1 2814 ldo R%cpu_hw_init(r1), r1 2815 .import cpu_hw_init, code 2816 .call 2817 blr r0, rp 2818 bv,n (r1) 2819 nop 2820 2821 /* Switch CPU mode. */ 2822 ldil L%$cpu_spinup_vm, t1 2823 ldo R%$cpu_spinup_vm(t1), t1 2824 mtctl r0, pcsq 2825 mtctl r0, pcsq 2826 mtctl t1, pcoq 2827 ldo 4(t1), t1 2828 mtctl t1, pcoq 2829 mfctl cr29, t2 2830 ldw CI_PSW(t2), t2 2831 mtctl t2, ipsw 2832 rfi 2833 nop 2834 2835$cpu_spinup_vm 2836 2837 /* 2838 * Okay, time to return to the land of C. 2839 */ 2840 b cpu_hatch 2841 nop 2842 2843EXIT(hw_cpu_spinup_trampoline) 2844#endif 2845 2846/* 2847 * Signal "trampoline" code. Invoked from RTE setup by sendsig(). 2848 */ 2849 .section .rodata 2850 .align 4 2851 .export sigcode, entry 2852 .label sigcode 2853 .proc 2854 .callinfo frame=0,calls, save_rp, save_sp 2855 .entry 2856sigcode: 2857 bb,>=,n arg3, 30, sigcode_call 2858 dep r0, 31, 2, arg3 2859 ldw 4(arg3), r19 2860 ldw 0(arg3), arg3 2861sigcode_call 2862 .call 2863 ble 0(sr0, arg3) 2864 copy r31, rp 2865 2866 ldil L%SYSCALLGATE, r1 2867 copy r4, arg0 2868 .call 2869 .globl sigcodecall 2870sigcodecall: 2871 ble 4(sr7, r1) 2872 ldi SYS_sigreturn, t1 2873 .globl sigcoderet 2874sigcoderet: 2875 break 0,0 2876ALTENTRY(esigcode) 2877 2878EXIT(sigcode) 2879 .globl sigfill 2880sigfill: 2881 break 0,0 2882esigfill: 2883 .align 4 2884 .globl sigfillsiz 2885sigfillsiz: 2886 .word esigfill - sigfill 2887 2888 .text 2889 2890 .end 2891