1/* $NetBSD: trap.S,v 1.75 2023/07/23 10:09:36 skrll Exp $ */ 2 3/*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matthew Fredette. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* $OpenBSD: locore.S,v 1.158 2008/07/28 19:08:46 miod Exp $ */ 33 34/* 35 * Copyright (c) 1998-2004 Michael Shalayeff 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 51 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 53 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 55 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 56 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 * 59 * Portitions of this file are derived from other sources, see 60 * the copyrights and acknowledgements below. 61 */ 62/* 63 * (c) Copyright 1988 HEWLETT-PACKARD COMPANY 64 * 65 * To anyone who acknowledges that this file is provided "AS IS" 66 * without any express or implied warranty: 67 * permission to use, copy, modify, and distribute this file 68 * for any purpose is hereby granted without fee, provided that 69 * the above copyright notice and this notice appears in all 70 * copies, and that the name of Hewlett-Packard Company not be 71 * used in advertising or publicity pertaining to distribution 72 * of the software without specific, written prior permission. 73 * Hewlett-Packard Company makes no representations about the 74 * suitability of this software for any purpose. 75 */ 76/* 77 * Copyright (c) 1990,1991,1992,1994 The University of Utah and 78 * the Computer Systems Laboratory (CSL). All rights reserved. 79 * 80 * Permission to use, copy, modify and distribute this software is hereby 81 * granted provided that (1) source code retains these copyright, permission, 82 * and disclaimer notices, and (2) redistributions including binaries 83 * reproduce the notices in supporting documentation, and (3) all advertising 84 * materials mentioning features or use of this software display the following 85 * acknowledgement: ``This product includes software developed by the 86 * Computer Systems Laboratory at the University of Utah.'' 87 * 88 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS 89 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF 90 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 91 * 92 * CSL requests users of this software to return to csl-dist@cs.utah.edu any 93 * improvements that they make and grant CSL redistribution rights. 94 * 95 * Utah $Hdr: locore.s 1.63 95/01/20$ 96 */ 97 98#include "opt_multiprocessor.h" 99#include "opt_cputype.h" 100 101/* 102 * NOTICE: This is not a standalone file. To use it, #include it in 103 * your port's locore.S, like so: 104 * 105 * #include <hppa/hppa/trap.S> 106 */ 107 108 .section .data 109 110 /* Normal stack alignment */ 111 .align 64 112 .export emergency_stack_start, data 113emergency_stack_start: 114 .block 32768 115 .export emergency_stack_end, data 116emergency_stack_end: 117 118 .text 119 120/* 121 * Kernel Gateway Page (must be at known address) 122 * System Call Gate 123 * 124 * GATEway instructions have to be at a fixed known locations because their 125 * addresses are hard coded in routines such as those in the C library. 126 */ 127 128 .align NBPG 129 .export gateway_page, entry 130gateway_page: 131 nop /* @ 0.C0000000 (Nothing) */ 132 gate,n bsd_syscall,%r0 /* @ 0.C0000004 (HPUX/BSD) */ 133 nop /* @ 0.C0000008 (HPOSF UNIX) */ 134 nop /* @ 0.C000000C (HPOSF Mach) */ 135 nop 136 nop 137 nop 138 nop 139 140bsd_syscall: 141 /* 142 * Set up a space register and a protection id so that we can access 143 * kernel memory. 144 */ 145 mfctl %eiem, %r1 146 mtctl %r0, %eiem 147 mtsp %r0, %sr1 148 mfctl %pidr1, %ret0 149 ldi HPPA_PID_KERNEL, %t2 150 mtctl %t2, %pidr1 151 152 /* 153 * now call the syscall handler 154 */ 155 .import syscall_entry,code 156 .call 157 ldil L%syscall_entry, %t2 158 be R%syscall_entry(%sr1, %t2) 159 nop ! nop ! nop ! nop 160 .size gateway_page, .-gateway_page 161 162 .align NBPG 163 .export gateway_page_end, entry 164gateway_page_end: 165 166 .export syscall_entry,entry 167 .proc 168 .callinfo calls 169 .entry 170syscall_entry: 171 /* 172 * %r1: eiem 173 * %ret0: process protection id 174 * %t1: syscall number 175 * %sr0, %r31: return address 176 * %sp: user stack 177 * 178 */ 179 180 /* t2 = curlwp PCB */ 181 GET_CURLWP_SPACE(%sr1, %t3) 182 ldw L_PCB(%sr1, %t3), %t2 /* XXX can use ,sl */ 183 184 /* 185 * NB: Even though t4 is a caller-saved register, we save it anyways, as 186 * a convenience to __vfork14 and any other syscalls that absolutely 187 * must have a register that is saved for it. 188 */ 189 190 /* calculate kernel sp, load, create kernel stack frame */ 191 ldo NBPG+TRAPFRAME_SIZEOF(%t2), %t3 /* see cpu_lwp_fork */ 192 193 stw %t4, TF_R19-TRAPFRAME_SIZEOF(%sr1, %t3) /* t4 for vfork */ 194 stw %t1, TF_R22-TRAPFRAME_SIZEOF(%sr1, %t3) /* syscall # */ 195 copy %sp, %t4 196 197 /* gotta save the args, in case we gonna restart */ 198 stw %arg3, TF_R23 -TRAPFRAME_SIZEOF(%sr1, %t3) 199 stw %arg2, TF_R24 -TRAPFRAME_SIZEOF(%sr1, %t3) 200 stw %arg1, TF_R25 -TRAPFRAME_SIZEOF(%sr1, %t3) 201 stw %arg0, TF_R26 -TRAPFRAME_SIZEOF(%sr1, %t3) 202 stw %r27, TF_R27 -TRAPFRAME_SIZEOF(%sr1, %t3) /* dp */ 203 stw %sp, TF_R30 -TRAPFRAME_SIZEOF(%sr1, %t3) /* user stack */ 204 copy %t3, %sp 205 /* 206 * Make space for the syscall arguments. 207 * 208 * Match the offset from %sp to the trapframe with the offset in 209 * TLABEL(all) for the benefit of ddb. 210 */ 211 stwm %r0, HPPA_FRAME_SIZE+HPPA_FRAME_MAXARGS(%sr1, %sp) 212 213 /* Align correctly */ 214 ldo HPPA_FRAME_SIZE-1(%sp),%sp 215 depi 0, 31, 6, %sp 216 217 stw %r0, HPPA_FRAME_CRP(%sr1, %sp) 218 219 GET_CURCPU_SPACE(%sr1, %t1) 220 ldw CI_PSW(%sr1, %t1), %t1 221 stw %r1, TF_CR15-TRAPFRAME_SIZEOF(%sr1, %t3) /* eiem ,bc (block copy cache control hint) */ 222 stw %t1, TF_CR22-TRAPFRAME_SIZEOF(%sr1, %t3) /* ipsw */ 223 224 mfsp %sr3, %t1 225 stw %t1, TF_SR3-TRAPFRAME_SIZEOF(%sr1, %t3) 226 stw %ret0, TF_CR8-TRAPFRAME_SIZEOF(%sr1, %t3) /* pidr1 */ 227 228 /* now we can allow interrupts to happen */ 229 mtctl %r1, %eiem 230 231 /* 232 * Normally, we only have to save the caller-saved registers, because 233 * the callee-saved registers will be naturally saved and restored by 234 * our callee(s). However, see the longer comment in the trap handling 235 * code below for the reasons why we need to save and restore all of 236 * them. 237 */ 238 stw %r2 , TF_R2 -TRAPFRAME_SIZEOF(%sr1, %t3) 239 stw %r3 , TF_R3 -TRAPFRAME_SIZEOF(%sr1, %t3) 240 241 /* We can now set the frame pointer */ 242 copy %t3, %r3 243 244 stw %r4 , TF_R4 -TRAPFRAME_SIZEOF(%sr1, %t3) 245 stw %r5 , TF_R5 -TRAPFRAME_SIZEOF(%sr1, %t3) 246 stw %r6 , TF_R6 -TRAPFRAME_SIZEOF(%sr1, %t3) 247 stw %r7 , TF_R7 -TRAPFRAME_SIZEOF(%sr1, %t3) 248 stw %r8 , TF_R8 -TRAPFRAME_SIZEOF(%sr1, %t3) 249 stw %r9 , TF_R9 -TRAPFRAME_SIZEOF(%sr1, %t3) 250 stw %r10, TF_R10-TRAPFRAME_SIZEOF(%sr1, %t3) 251 stw %r11, TF_R11-TRAPFRAME_SIZEOF(%sr1, %t3) 252 stw %r12, TF_R12-TRAPFRAME_SIZEOF(%sr1, %t3) 253 stw %r13, TF_R13-TRAPFRAME_SIZEOF(%sr1, %t3) 254 stw %r14, TF_R14-TRAPFRAME_SIZEOF(%sr1, %t3) 255 stw %r15, TF_R15-TRAPFRAME_SIZEOF(%sr1, %t3) 256 stw %r16, TF_R16-TRAPFRAME_SIZEOF(%sr1, %t3) 257 stw %r17, TF_R17-TRAPFRAME_SIZEOF(%sr1, %t3) 258 stw %r18, TF_R18-TRAPFRAME_SIZEOF(%sr1, %t3) 259 260 stw %r0, 0(%sr1, %t3) /* terminate frame */ 261 copy %r0 , %r3 262 stw %r0, HPPA_FRAME_PSP(%sr1, %sp) 263 stw %r0, HPPA_FRAME_CRP(%sr1, %sp) 264 265 /* 266 * Copy Arguments 267 * 268 * Unfortunately mmap() under bsd requires 7 words; linux is confined to 269 * 5, and hpux to 6. Assuming the `long' syscall it gives us the 270 * maximum 9 words, which very much overkill for an average of 3. We 271 * keep it at 10, since bundling will keep it at the same speed as 9 272 * anyway. 273 */ 274 /* 275 * XXX fredette - possible security hole here. 276 * What happens if the user hands us a stack 277 * that points to nowhere, or to data that they 278 * should not be reading? 279 */ 280 stw %arg0, 1*4(%sr1, %t3) /* XXX can use ,bc */ 281 stw %arg1, 2*4(%sr1, %t3) 282 stw %arg2, 3*4(%sr1, %t3) 283 stw %arg3, 4*4(%sr1, %t3) 284 ldw HPPA_FRAME_ARG( 4)(%t4), %arg0 285 ldw HPPA_FRAME_ARG( 5)(%t4), %arg1 286 ldw HPPA_FRAME_ARG( 6)(%t4), %arg2 287 ldw HPPA_FRAME_ARG( 7)(%t4), %arg3 288 stw %arg0, 5*4(%sr1, %t3) 289 stw %arg1, 6*4(%sr1, %t3) 290 stw %arg2, 7*4(%sr1, %t3) 291 stw %arg3, 8*4(%sr1, %t3) 292 ldw HPPA_FRAME_ARG( 8)(%t4), %arg0 293 ldw HPPA_FRAME_ARG( 9)(%t4), %arg1 294 stw %arg0, 9*4(%sr1, %t3) 295 stw %arg1,10*4(%sr1, %t3) 296 297 /* 298 * Save the rest of the CPU context 299 */ 300 301 /* XXXNH: Should do a be 0(%sr1, %r31) instead of rfi when possible */ 302 ldo 4(%r31), %arg1 303 stw %r31, TF_IIOQH-TRAPFRAME_SIZEOF(%sr1, %t3) 304 stw %arg1, TF_IIOQT-TRAPFRAME_SIZEOF(%sr1, %t3) 305 306 mfsp %sr0, %arg0 307 stw %arg0, TF_IISQH-TRAPFRAME_SIZEOF(%sr1, %t3) 308 stw %arg0, TF_IISQT-TRAPFRAME_SIZEOF(%sr1, %t3) 309 310 stw %arg0, TF_CR20-TRAPFRAME_SIZEOF(%sr1, %t3) 311 stw %r31, TF_CR21-TRAPFRAME_SIZEOF(%sr1, %t3) 312 313 ldil L%(TFF_LAST|TFF_SYS), %arg1 314 stw %r0, TF_CR19-TRAPFRAME_SIZEOF(%sr1, %t3) /* iir */ 315 stw %arg1, TF_FLAGS-TRAPFRAME_SIZEOF(%sr1, %t3) 316 317 /* Already done above: mfsp %sr0, %arg0 */ 318 mfsp %sr2, %arg2 319 mfsp %sr4, %arg3 320 stw %arg0, TF_SR0-TRAPFRAME_SIZEOF(%sr1, %t3) 321 stw %arg0, TF_SR1-TRAPFRAME_SIZEOF(%sr1, %t3) 322 /* we overwrote sr1 earlier */ 323 stw %arg2, TF_SR2-TRAPFRAME_SIZEOF(%sr1, %t3) 324 stw %arg3, TF_SR4-TRAPFRAME_SIZEOF(%sr1, %t3) 325 326 mfsp %sr5, %arg0 327 mfsp %sr6, %arg1 328 mfsp %sr7, %arg2 329 mfctl %pidr2, %arg3 330 stw %arg0, TF_SR5-TRAPFRAME_SIZEOF(%sr1, %t3) 331 stw %arg1, TF_SR6-TRAPFRAME_SIZEOF(%sr1, %t3) 332 stw %arg2, TF_SR7-TRAPFRAME_SIZEOF(%sr1, %t3) 333 stw %arg3, TF_CR9-TRAPFRAME_SIZEOF(%sr1, %t3) 334 335#if pbably_not_worth_it 336 mfctl %pidr3, %arg2 337 mfctl %pidr4, %arg3 338 stw %arg2, TF_CR12-TRAPFRAME_SIZEOF(%sr1, %t3) 339 stw %arg3, TF_CR13-TRAPFRAME_SIZEOF(%sr1, %t3) 340#endif 341 342 mfctl CR_TLS, %arg0 343 stw %arg0, TF_CR27-TRAPFRAME_SIZEOF(%sr1, %t3) 344 345#if defined(DDB) || defined(KGDB) 346 /* 347 * Save v2p translation table pointer 348 */ 349 mfctl %eirr, %arg0 350 mfctl CR_VTOP, %arg1 351 stw %arg0, TF_CR23-TRAPFRAME_SIZEOF(%sr1, %t3) 352 stw %arg1, TF_CR25-TRAPFRAME_SIZEOF(%sr1, %t3) 353 354 mfctl %cr24, %arg0 355 mfctl %cr28, %arg1 356 stw %arg0, TF_CR24-TRAPFRAME_SIZEOF(%sr1, %t3) 357 stw %arg1, TF_CR28-TRAPFRAME_SIZEOF(%sr1, %t3) 358#endif 359 360 /* setup kernel context */ 361 mtsp %r0, %sr0 362 mtsp %r0, %sr1 363 mtsp %r0, %sr2 364 mtsp %r0, %sr3 365 mtsp %r0, %sr4 366 mtsp %r0, %sr5 367 mtsp %r0, %sr6 368 mtsp %r0, %sr7 369 370 ldo -TRAPFRAME_SIZEOF(%t3), %arg0 371 ldo 4(%t3), %arg1 372 373 ldil L%$global$,%dp 374 ldo R%$global$(%dp),%dp 375 376 GET_CURLWP(%r3) 377 ldw L_PROC(%r3), %r1 378 ldw P_MD_SYSCALL(%r1), %r1 379 380 .call 381 blr %r0, %rp 382 bv,n %r0(%r1) 383 nop 384 385 /* load curlwp's trapframe pointer */ 386 ldw L_MD(%r3), %t3 387 388 .exit 389 .procend 390 /* FALLTHROUGH */ 391 392 .export syscall_return, entry 393 .proc 394 .callinfo no_calls 395 .entry 396syscall_return: 397 /* t3 == VA trapframe */ 398 399 /* disable interrupts, just in case */ 400 mtctl %r0, %eiem 401 402 /* 403 * Copy the `phys' part of the frame into CPU local temporary store (see 404 * a note for trapall). Hopefully no page fault would happen on or after 405 * the copy, and interrupts are disabled. 406 */ 407 GET_CURCPU(%t2) 408 ldo CI_TRAPSAVE(%t2), %t2 409 410 ldw 0(%t3), %r1 ! ldw 4(%t3), %t1 ! stw %r1, 0(%t2) ! stw %t1, 4(%t2) 411 ldw 8(%t3), %r1 ! ldw 12(%t3), %t1 ! stw %r1, 8(%t2) ! stw %t1, 12(%t2) 412 ldw 16(%t3), %r1 ! ldw 20(%t3), %t1 ! stw %r1, 16(%t2) ! stw %t1, 20(%t2) 413 ldw 24(%t3), %r1 ! ldw 28(%t3), %t1 ! stw %r1, 24(%t2) ! stw %t1, 28(%t2) 414 ldw 32(%t3), %r1 ! ldw 36(%t3), %t1 ! stw %r1, 32(%t2) ! stw %t1, 36(%t2) 415 ldw 40(%t3), %r1 ! ldw 44(%t3), %t1 ! stw %r1, 40(%t2) ! stw %t1, 44(%t2) 416 ldw 48(%t3), %r1 ! ldw 52(%t3), %t1 ! stw %r1, 48(%t2) ! stw %t1, 52(%t2) 417 ldw 56(%t3), %r1 ! ldw 60(%t3), %t1 ! stw %r1, 56(%t2) ! stw %t1, 60(%t2) 418 419 /* 1b. restore most of the general registers */ 420 ldw TF_CR11(%t3), %t1 421 mtctl %t1, %sar 422 ldw TF_R1(%t3), %r1 423 ldw TF_R2(%t3), %r2 424 ldw TF_R3(%t3), %r3 425 426 /* 427 * See the comment in the trap handling code below about why we need to 428 * save and restore all general registers under these cases. 429 */ 430 ldw TF_R4(%t3), %r4 431 ldw TF_R5(%t3), %r5 432 ldw TF_R6(%t3), %r6 433 ldw TF_R7(%t3), %r7 434 ldw TF_R8(%t3), %r8 435 ldw TF_R9(%t3), %r9 436 ldw TF_R10(%t3), %r10 437 ldw TF_R11(%t3), %r11 438 ldw TF_R12(%t3), %r12 439 ldw TF_R13(%t3), %r13 440 ldw TF_R14(%t3), %r14 441 ldw TF_R15(%t3), %r15 442 ldw TF_R16(%t3), %r16 443 ldw TF_R17(%t3), %r17 444 ldw TF_R18(%t3), %r18 445 446 ldw TF_R19(%t3), %t4 447 /* %r20(%t3) is used as a temporary and will be restored later */ 448 /* %r21(%t2) is used as a temporary and will be restored later */ 449 /* %r22(%t1) is used as a temporary and will be restored later */ 450 ldw TF_R23(%t3), %r23 451 ldw TF_R24(%t3), %r24 452 ldw TF_R25(%t3), %r25 453 ldw TF_R26(%t3), %r26 454 ldw TF_R27(%t3), %r27 455 ldw TF_R28(%t3), %r28 456 ldw TF_R29(%t3), %r29 457 /* %r30 (%sp) will be restored later */ 458 ldw TF_R31(%t3), %r31 459 460 /* 2. restore all the space regs and pid regs, except sr3, pidr1 */ 461 ldw TF_SR0(%t3), %t1 462 ldw TF_SR1(%t3), %t2 463 mtsp %t1, %sr0 464 mtsp %t2, %sr1 465 466 ldw TF_SR2(%sr3, %t3), %t1 467 ldw TF_SR4(%sr3, %t3), %t2 468 mtsp %t1, %sr2 469 mtsp %t2, %sr4 470 471 ldw TF_SR5(%sr3, %t3), %t1 472 ldw TF_SR6(%sr3, %t3), %t2 473 mtsp %t1, %sr5 474 mtsp %t2, %sr6 475 476 ldw TF_SR7(%sr3, %t3), %t1 477 ldw TF_CR9(%sr3, %t3), %t2 478 mtsp %t1, %sr7 479 mtctl %t2, %pidr2 480 481#if pbably_not_worth_it 482 ldw TF_CR12(%sr3, %t3), %t1 483 ldw TF_CR13(%sr3, %t3), %t2 484 mtctl %t1, %pidr3 485 mtctl %t2, %pidr4 486#endif 487 ldw TF_CR27(%sr3, %t3), %t1 488 ldw TF_CR30(%sr3, %t3), %t2 489 mtctl %t1, CR_TLS 490 mtctl %t2, CR_FPPADDR 491 492 ldw TF_CR0(%sr3, %t3), %t1 493 mtctl %t1, CR_RCTR 494 495 GET_CURCPU_SPACE(%sr3, %t3) 496 497 /* 498 * Clear the system mask, this puts us back into physical mode. Reload 499 * the trapframe pointer with the correspondent PA value. %sp will be 500 * left in virtual until restored from trapframe, since we don't use it 501 * anyway. 502 */ 503 ssm 0, %r0 504 ldo CI_TRAPSAVE(%t3), %t3 505 nop ! nop ! nop ! nop ! nop ! nop 506 rsm RESET_PSW, %r0 507 508 /* finally we can restore the space and offset queues and the ipsw */ 509 ldw TF_IISQH(%t3), %t1 510 ldw TF_IISQT(%t3), %t2 511 mtctl %t1, %pcsq 512 mtctl %t2, %pcsq 513 514 ldw TF_IIOQH(%t3), %t1 515 ldw TF_IIOQT(%t3), %t2 516 mtctl %t1, %pcoq 517 mtctl %t2, %pcoq 518 519 ldw TF_CR15(%t3), %t1 520 ldw TF_CR22(%t3), %t2 521 mtctl %t1, %eiem 522 mtctl %t2, %ipsw 523 524 ldw TF_SR3(%t3), %t1 525 ldw TF_CR8(%t3), %t2 526 mtsp %t1, %sr3 527 mtctl %t2, %pidr1 528 529 ldw TF_R22(%t3), %t1 530 ldw TF_R21(%t3), %t2 531 ldw TF_R30(%t3), %sp 532 ldw TF_R20(%t3), %t3 533 534 rfi 535 nop 536 .exit 537 .procend 538 .size syscall_entry, .- syscall_entry 539 540/* 541 * interrupt vector table 542 */ 543#define TLABEL(name) __CONCAT(trap_,name) 544#define TRAPLABEL(name,num) __CONCAT(TLABEL(name),num) 545#define TELABEL(num) __CONCAT(trap_ep_,num) 546 547#define TRAP(name,num) \ 548 mtctl %r1, %tr7 ! \ 549 .call ! \ 550 .import TLABEL(name), code ! \ 551 b TLABEL(name) ! \ 552 ldi num, %r1 ! \ 553 .align 32 554 555#define ATRAP(name,num) \ 556 .export TRAPLABEL(name,num), entry ! \ 557 .label TRAPLABEL(name,num) ! \ 558 TRAP(all,num) ! \ 559 .size TRAPLABEL(name,num), .-TRAPLABEL(name,num) 560 561#define CTRAP(name,num,pre) \ 562 .export TRAPLABEL(name,num), entry ! \ 563 .label TRAPLABEL(name,num) ! \ 564 pre ! \ 565 TRAP(name,num) ! \ 566 .size TRAPLABEL(name,num), .-TRAPLABEL(name,num) 567 568#define STRAP(name,num,pre) \ 569 .export TRAPLABEL(name,num), entry ! \ 570 .label TRAPLABEL(name,num) ! \ 571 pre ! \ 572 mtctl %r1, %tr7 ! \ 573 .export TELABEL(num), entry ! \ 574 .label TELABEL(num) ! \ 575 ldil 0,%r1 ! \ 576 ldo 0(%r1), %r1 ! \ 577 .call ! \ 578 bv 0(%r1) ! \ 579 ldi num, %r1 ! \ 580 .align 32 ! \ 581 .size TRAPLABEL(name,num), .-TRAPLABEL(name,num) 582 583#define LDILDO(name) ! \ 584 .export name, entry ! \ 585 .label name ! \ 586 ldil L%TLABEL(name),%r1 ! \ 587 ldo R%TLABEL(name)(%r1), %r1 588 589#ifdef HP7000_CPU 590LDILDO(itlb_x) 591LDILDO(itlbna_x) 592LDILDO(dtlb_x) 593LDILDO(dtlbna_x) 594LDILDO(tlbd_x) 595 596LDILDO(itlb_s) 597LDILDO(itlbna_s) 598LDILDO(dtlb_s) 599LDILDO(dtlbna_s) 600LDILDO(tlbd_s) 601#endif 602 603#if defined(HP7100_CPU) || defined(HP7200_CPU) 604LDILDO(itlb_t) 605LDILDO(itlbna_t) 606LDILDO(dtlb_t) 607LDILDO(dtlbna_t) 608LDILDO(tlbd_t) 609#endif 610 611#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU) 612LDILDO(itlb_l) 613LDILDO(itlbna_l) 614LDILDO(dtlb_l) 615LDILDO(dtlbna_l) 616LDILDO(tlbd_l) 617#endif 618 619#if defined(HP8000_CPU) || defined(HP8200_CPU) || \ 620 defined(HP8500_CPU) || defined(HP8600_CPU) || \ 621 defined(HP8700_CPU) 622LDILDO(itlb_u) 623LDILDO(itlbna_u) 624LDILDO(dtlb_u) 625LDILDO(dtlbna_u) 626LDILDO(tlbd_u) 627#endif 628 629#define ITLBPRE \ 630 mfctl %pcoq,%r9 /* Offset */ ! \ 631 mfctl %pcsq,%r8 /* Space */ 632 633#define DTLBPRE \ 634 mfctl %ior, %r9 /* Offset */ ! \ 635 mfctl %isr, %r8 /* Space */ 636 637#define HPMCPRE \ 638 nop 639 640 .align NBPG 641 .export ivaaddr, entry 642 .export os_hpmc, entry 643ivaaddr: 644 ATRAP(null,T_NONEXIST) /* 0. invalid interrupt vector */ 645os_hpmc: 646 CTRAP(hpmc,T_HPMC,HPMCPRE) /* 1. high priority machine check */ 647 ATRAP(power,T_POWERFAIL) /* 2. power failure */ 648 ATRAP(recnt,T_RECOVERY) /* 3. recovery counter trap */ 649 ATRAP(intr,T_INTERRUPT) /* 4. external interrupt */ 650 ATRAP(lpmc,T_LPMC) /* 5. low-priority machine check */ 651 STRAP(itlb,T_ITLBMISS,ITLBPRE) /* 6. instruction TLB miss fault */ 652 ATRAP(iprot,T_IPROT) /* 7. instruction protection trap */ 653 ATRAP(ill,T_ILLEGAL) /* 8. Illegal instruction trap */ 654 CTRAP(ibrk,T_IBREAK,) /* 9. break instruction trap */ 655 ATRAP(privop,T_PRIV_OP) /* 10. privileged operation trap */ 656 ATRAP(privr,T_PRIV_REG) /* 11. privileged register trap */ 657 ATRAP(ovrfl,T_OVERFLOW) /* 12. overflow trap */ 658 ATRAP(cond,T_CONDITION) /* 13. conditional trap */ 659 ATRAP(excpt,T_EXCEPTION) /* 14. assist exception trap */ 660 STRAP(dtlb,T_DTLBMISS,DTLBPRE) /* 15. data TLB miss fault */ 661 STRAP(itlbna,T_ITLBMISSNA,DTLBPRE)/* 16. ITLB non-access miss fault */ 662 STRAP(dtlbna,T_DTLBMISSNA,DTLBPRE)/* 17. DTLB non-access miss fault */ 663 ATRAP(dprot,T_DPROT) /* 18. data protection trap 664 unaligned data reference trap */ 665 ATRAP(dbrk,T_DBREAK) /* 19. data break trap */ 666 STRAP(tlbd,T_TLB_DIRTY,DTLBPRE) /* 20. TLB dirty bit trap */ 667 ATRAP(pgref,T_PAGEREF) /* 21. page reference trap */ 668 CTRAP(emu,T_EMULATION,) /* 22. assist emulation trap */ 669 ATRAP(hpl,T_HIGHERPL) /* 23. higher-privilege transfer trap*/ 670 ATRAP(lpl,T_LOWERPL) /* 24. lower-privilege transfer trap */ 671 ATRAP(tknbr,T_TAKENBR) /* 25. taken branch trap */ 672 ATRAP(dacc,T_DATACC) /* 26. data access rights trap */ 673 ATRAP(dpid,T_DATAPID) /* 27. data protection ID trap */ 674 ATRAP(dalgn,T_DATALIGN) /* 28. unaligned data ref trap */ 675 ATRAP(unk,29) 676 ATRAP(unk,30) 677 ATRAP(unk,31) 678 ATRAP(unk,32) 679 ATRAP(unk,33) 680 ATRAP(unk,34) 681 ATRAP(unk,35) 682 ATRAP(unk,36) 683 ATRAP(unk,37) 684 ATRAP(unk,38) 685 ATRAP(unk,39) 686 ATRAP(unk,40) 687 ATRAP(unk,41) 688 ATRAP(unk,42) 689 ATRAP(unk,43) 690 ATRAP(unk,44) 691 ATRAP(unk,45) 692 ATRAP(unk,46) 693 ATRAP(unk,47) 694 ATRAP(unk,48) 695 ATRAP(unk,49) 696 ATRAP(unk,50) 697 ATRAP(unk,51) 698 ATRAP(unk,52) 699 ATRAP(unk,53) 700 ATRAP(unk,54) 701 ATRAP(unk,55) 702 ATRAP(unk,56) 703 ATRAP(unk,57) 704 ATRAP(unk,58) 705 ATRAP(unk,59) 706 ATRAP(unk,60) 707 ATRAP(unk,61) 708 ATRAP(unk,62) 709 ATRAP(unk,63) 710 /* 64 */ 711 .size ivaaddr, .-ivaaddr 712 713/* 714 * This is the locore support for HPMC and TOC machine checks. In the HPMC 715 * case, this is a continuation of the HPMC handler that begins in the interrupt 716 * vector table. In the TOC case, this is the handler installed in page zero. 717 * 718 * Notable points about the CPU state for the OS_TOC handler: 719 * 720 * - The PSW Q bit is 1, all other PSW bits are 0. 721 * - CR14 (IVA) does not point to our vector table. 722 * - CR22 (IPSW) is valid. 723 * - All other control registers HVERSION dependent. 724 * - The TLB is initialized and invalid. 725 * 726 * Notable points about the CPU state for the OS_HPMC handler: 727 * 728 * - The PSW M bit is 1, all other PSW bits are 0. 729 * - CR14 (IVA) does point to our vector table. 730 * - CR22 (IPSW) is valid. 731 * - All other control registers HVERSION dependent. 732 * - The TLB is unchanged. 733 * 734 * The TOC CPU state is actually trickier. Whereas in the HPMC case, we can 735 * return to virtual mode right away, in the TOC case we can't return to virtual 736 * mode until the kernel mapping is reloaded into the BTLB. 737 * 738 * Otherwise, we set up the kernel context, move onto the emergency stack, and 739 * call hppa_machine_check. 740 */ 741ENTRY_NOPROFILE(os_toc, 0) 742 /* This loads %arg0 and nullifies the next instruction. */ 743 addi,tr T_INTERRUPT, %r0, %arg0 744EXIT(os_toc) 745ENTRY_NOPROFILE(TLABEL(hpmc),0) 746ALTENTRY(os_hpmc_cont) 747 ldi T_HPMC, %arg0 748 749 /* Disable interrupts. */ 750 mtctl %r0, %eiem 751 752 /* Load protection and space registers for the kernel. */ 753 ldi HPPA_PID_KERNEL, %r1 754 mtctl %r1, %pidr1 755 ldi HPPA_SID_KERNEL, %r1 756 mtsp %r1, %sr0 757 mtsp %r1, %sr1 758 mtsp %r1, %sr2 759 mtsp %r1, %sr3 760 mtsp %r1, %sr4 761 mtsp %r1, %sr5 762 mtsp %r1, %sr6 763 mtsp %r1, %sr7 764 765 /* Reload the Interruption Vector Address. */ 766 ldil L%ivaaddr, %r1 767 ldo R%ivaaddr(%r1), %r1 768 mtctl %r1, %iva 769 770 /* Reload the HPT base and mask. */ 771 ldil L%hppa_vtop, %r1 772 ldw R%hppa_vtop(%r1), %r1 773 mtctl %r1, CR_VTOP 774 775 /* Disable interrupts for the long haul. */ 776 GET_CURCPU(%t1) 777 ldw CI_PSW(%t1), %r1 778 depi 0, PSW_I_POS, 1, %r1 779 stw %r1, CI_PSW(%t1) 780 781 /* Reload the global data pointer. */ 782 ldil L%$global$, %dp 783 ldo R%$global$(%dp), %dp 784 785 /* Move onto the emergency stack. */ 786 ldil L%emergency_stack_start, %sp 787 ldo R%emergency_stack_start(%sp), %sp 788 stwm %r0, HPPA_FRAME_SIZE(%sp) 789 copy %sp, %r3 790 791 /* Start stack calling convention. */ 792 stw %r0, HPPA_FRAME_CRP(%sp) 793 stw %r0, HPPA_FRAME_PSP(%sp) 794 copy %r3, %r1 795 copy %sp, %r3 796 stwm %r1, HPPA_FRAME_SIZE(%sp) 797 798 /* If this is a TOC, remap the kernel. */ 799 comib,<>,n T_INTERRUPT, %arg0, L$check_do_rfi 800 801 /* Clear kernelmapped. */ 802 ldil L%kernelmapped, %r1 803 stw %r0, R%kernelmapped(%r1) 804 805 /* Call hppa_btlb_reload. */ 806 ldil L%hppa_btlb_reload, %r1 807 ldo R%hppa_btlb_reload(%r1), %r1 808 blr 0, %rp 809 bv %r0(%r1) 810 nop 811 812 /* Set kernelmapped. */ 813 ldil L%kernelmapped, %r1 814 stw %r1, R%kernelmapped(%r1) 815 816 /* Reload %arg0 (it may have been destroyed). */ 817 ldi T_INTERRUPT, %arg0 818 819 /* Disable the interrupt queues. */ 820 rsm RESET_PSW, %r0 821 822L$check_do_rfi: 823 824 /* Load IPSW. */ 825 GET_CURCPU(%r1) 826 ldw CI_PSW(%r1), %r1 827 mtctl %r1, %ipsw 828 829 /* Get the address of hppa_machine_check. */ 830 ldil L%hppa_machine_check, %r1 831 ldo R%hppa_machine_check(%r1), %r1 832 833 /* Load the instruction address queues. */ 834 mtctl %r1, %pcoq 835 ldo 4(%r1), %r1 836 mtctl %r1, %pcoq 837 ldi HPPA_SID_KERNEL, %r1 838 mtctl %r1, %pcsq 839 mtctl %r1, %pcsq 840 841 blr 0, %rp 842 rfi 843 nop 844 nop 845 nop 846 nop 847 nop 848 849ALTENTRY(os_hpmc_checksum) 850 nop 851ALTENTRY(os_hpmc_cont_end) 852ALTENTRY(os_toc_checksum) 853 nop 854ALTENTRY(os_toc_end) 855EXIT(TLABEL(hpmc)) 856 857/* 858 * This handles all assist emulation traps. We break these down into three 859 * categories and dispatch accordingly. The categories are: 860 * 861 * - emulate special function unit, 862 * - emulate non-FPU coprocessor, and 863 * - emulate FPU coprocessor. 864 * 865 */ 866 .export TLABEL(emu), entry 867LEAF_ENTRY_NOPROFILE(TLABEL(emu)) 868 869 /* 870 * Save %arg0 and load it with the instruction that caused the emulation 871 * trap. 872 */ 873 mtctl %arg0, %tr2 874 mfctl %iir, %arg0 875 876 /* 877 * If the opcode field in the instruction is 4, indicating a special 878 * function unit SPOP instruction, branch to emulate an sfu. If the 879 * opcode field is 0xe, then it's an FPU instruction. 880 */ 881 extru %arg0, 5, 6, %r1 882 comib,=,n 4, %r1, L$emulate_sfu 883 comib,=,n 0xe, %r1, hppa_fpu_emulate 884 885 /* 886 * If the uid field in the instruction is not zero or one, indicating a 887 * coprocessor other than an FPU, branch to emulate a non-FPU 888 * coprocessor. 889 */ 890 extru %arg0, 25, 3, %r1 891 comib,<<,n 1, %r1, L$emulate_coproc 892 893 /* 894 * If we're still here, this is a FPU coprocessor instruction. That we 895 * trapped to emulate it means one of two things. 896 * 897 * If we do have a hardware FPU but it is disabled, we trapped because 898 * the current process' state is not loaded into the FPU. We load that 899 * state in, possibly swapping out another process' state first. 900 * 901 * If we do have a hardware FPU and it is enabled, we trapped because of 902 * an instruction that isn't supported by this FPU, and so we need to 903 * emulate it. 904 */ 905 906hppa_fpu_emulate: 907 908 /* 909 * We have a hardware FPU. If it is enabled, branch to emulate the 910 * instruction. 911 */ 912 mfctl CR_CCR, %arg0 913 extru,= %arg0, 25, 2, %r1 914 b,n L$emulate_fpu 915 916 /* 917 * The hardware FPU is disabled, so we need to swap in the FPU state of 918 * the LWP whose uspace physical address in CR_FPPADDR. We may also 919 * need to swap out the FPU state of any LWP whose uspace physical 920 * address is in curcpu()->ci_fpu_state. 921 */ 922 923 /* 924 * So far, the CTRAP() macro has saved %r1 in %tr7, and the dispatching 925 * above has saved %arg0 in tr2. Save the other registers that we want 926 * to use. hppa_fpu_swap deliberately uses only these registers and %r1 927 * and %arg0. 928 */ 929 mtctl %arg1, %tr4 930 mtctl %rp, %tr5 931 932 /* Call hppa_fpu_swap. */ 933 GET_CURCPU(%arg0) 934 ldw CI_FPU_STATE(%arg0), %arg0 935 mfctl CR_FPPADDR, %arg1 936 blr 0, %rp 937 b hppa_fpu_swap 938 nop 939 940 /* Restore registers and rfi. */ 941 mfctl %tr5, %rp 942 mfctl %tr4, %arg1 943 mfctl %tr2, %arg0 944 mfctl %tr7, %r1 945 rfi 946 nop 947 948 /* 949 * We branch here to emulate a special function unit instruction. On 950 * entry, %r1 is saved in %tr7 (courtesy of CTRAP), and %arg0 is saved 951 * in %tr2 (courtesy of the sfu/coprocessor dispatcher). 952 */ 953L$emulate_sfu: 954 /* 955 * Currently we just restore %arg0 and trap with an illegal instruction. 956 */ 957 mfctl %tr2, %arg0 958 b TLABEL(all) 959 ldi T_ILLEGAL, %r1 960 961 /* 962 * We branch here to emulate a non-FPU coprocessor instruction. On 963 * entry, %r1 is saved in %tr7 (courtesy of CTRAP), and %t1 is saved in 964 * %tr2 (courtesy of the sfu/coprocessor dispatcher). 965 */ 966L$emulate_coproc: 967 /* 968 * Currently we just restore %arg0 and trap with an illegal instruction. 969 */ 970 mfctl %tr2, %arg0 971 b TLABEL(all) 972 ldi T_ILLEGAL, %r1 973 974 /* 975 * We branch here to emulate an FPU coprocessor instruction. On entry, 976 * %r1 is saved in %tr7 (courtesy of CTRAP), and %t1 is saved in %tr2 977 * (courtesy of the sfu/coprocessor dispatcher). 978 */ 979L$emulate_fpu: 980 /* 981 * We get back to C via the normal generic trap mechanism, as opposed to 982 * switching to a special stack, setting up a trapframe, etc. ourselves, 983 * for three reasons. 984 * 985 * One, I want to turn interrupts back on, since the emulation code 986 * might not be fast. Two, because the instruction to emulate might be 987 * a load or a store, I need to turn address translation back on (i.e., 988 * return to virtual mode.) Third, doing both of those plus setting up 989 * a trapframe is a pain, and the generic trap handling already does it 990 * all. 991 * 992 * To relieve trap() from having to check for sfu and non-FPU inst- 993 * ructions again, it assumes that these kinds of instructions have 994 * already been translated into some other trap type (as they have, by 995 * the above L$emulate_sfu and L$emulate_coproc), and all 996 * T_EMULATION | T_USER traps are FPU instructions that need emulating. 997 * 998 * So we just restore %arg0 and trap with T_EMULATION. 999 */ 1000 mfctl %tr2, %arg0 1001 b TLABEL(all) 1002 ldi T_EMULATION, %r1 1003EXIT(TLABEL(emu)) 1004 1005/* 1006 * void hppa_fpu_swapout(struct pcb *out); 1007 * void hppa_fpu_swap(struct fpreg *out, struct fpreg *in); 1008 */ 1009LEAF_ENTRY_NOPROFILE(hppa_fpu_swapout) 1010 ldw PCB_FPREGS(%arg0), %arg0 1011 copy %r0, %arg1 1012 1013ALTENTRY(hppa_fpu_swap) 1014 1015 /* 1016 * Note that this function must work in physical mode as well as virtual 1017 * mode, because it can be called by a trap handler. This also further 1018 * restricts the registers we can use. We can only use %arg0, %arg1, 1019 * and %r1. 1020 */ 1021 1022 /* 1023 * Assuming that out and in aren't both NULL, we will have to run co- 1024 * processor instructions, so we'd better enable it. 1025 * 1026 * Also, branch if there's no FPU state to swap out. 1027 */ 1028 mfctl CR_CCR, %r1 1029 depi 3, 25, 2, %r1 1030 comb,= %r0, %arg0, L$fpu_swap_in 1031 mtctl %r1, CR_CCR 1032 1033 /* 1034 * Swap out the current FPU state. 1035 */ 1036 fstds,ma %fr0 , 8(%arg0) /* fr0 must be saved first */ 1037 fstds,ma %fr1 , 8(%arg0) 1038 fstds,ma %fr2 , 8(%arg0) 1039 fstds,ma %fr3 , 8(%arg0) 1040 fstds,ma %fr4 , 8(%arg0) 1041 fstds,ma %fr5 , 8(%arg0) 1042 fstds,ma %fr6 , 8(%arg0) 1043 fstds,ma %fr7 , 8(%arg0) 1044 fstds,ma %fr8 , 8(%arg0) 1045 fstds,ma %fr9 , 8(%arg0) 1046 fstds,ma %fr10, 8(%arg0) 1047 fstds,ma %fr11, 8(%arg0) 1048 fstds,ma %fr12, 8(%arg0) 1049 fstds,ma %fr13, 8(%arg0) 1050 fstds,ma %fr14, 8(%arg0) 1051 fstds,ma %fr15, 8(%arg0) 1052 fstds,ma %fr16, 8(%arg0) 1053 fstds,ma %fr17, 8(%arg0) 1054 fstds,ma %fr18, 8(%arg0) 1055 fstds,ma %fr19, 8(%arg0) 1056 fstds,ma %fr20, 8(%arg0) 1057 fstds,ma %fr21, 8(%arg0) 1058 fstds,ma %fr22, 8(%arg0) 1059 fstds,ma %fr23, 8(%arg0) 1060 fstds,ma %fr24, 8(%arg0) 1061 fstds,ma %fr25, 8(%arg0) 1062 fstds,ma %fr26, 8(%arg0) 1063 fstds,ma %fr27, 8(%arg0) 1064 fstds,ma %fr28, 8(%arg0) 1065 fstds,ma %fr29, 8(%arg0) 1066 fstds,ma %fr30, 8(%arg0) 1067 fstds %fr31, 0(%arg0) 1068 1069L$fpu_swap_in: 1070 1071 /* 1072 * Stash the incoming user structure in curcpu->ci_fpu_state. Because 1073 * this variable holds a physical address, this means that hppa_fpu_swap 1074 * can only be called with a non-zero user_in from physical mode (i.e., 1075 * from the emulation assist trap handler). And that's exactly what 1076 * happens now. 1077 * 1078 * So stash ci->ci_fpu_state, branching past the swap-in code if it is 1079 * zero. 1080 */ 1081 GET_CURCPU(%r1) 1082 comb,= %r0, %arg1, L$fpu_no_swap_in 1083 stw %arg1, CI_FPU_STATE(%r1) 1084 1085 /* 1086 * Swap in the new FPU state. 1087 */ 1088 ldo 31*8(%arg1), %arg1 1089 fldds,ma -8(%arg1), %fr31 1090 fldds,ma -8(%arg1), %fr30 1091 fldds,ma -8(%arg1), %fr29 1092 fldds,ma -8(%arg1), %fr28 1093 fldds,ma -8(%arg1), %fr27 1094 fldds,ma -8(%arg1), %fr26 1095 fldds,ma -8(%arg1), %fr25 1096 fldds,ma -8(%arg1), %fr24 1097 fldds,ma -8(%arg1), %fr23 1098 fldds,ma -8(%arg1), %fr22 1099 fldds,ma -8(%arg1), %fr21 1100 fldds,ma -8(%arg1), %fr20 1101 fldds,ma -8(%arg1), %fr19 1102 fldds,ma -8(%arg1), %fr18 1103 fldds,ma -8(%arg1), %fr17 1104 fldds,ma -8(%arg1), %fr16 1105 fldds,ma -8(%arg1), %fr15 1106 fldds,ma -8(%arg1), %fr14 1107 fldds,ma -8(%arg1), %fr13 1108 fldds,ma -8(%arg1), %fr12 1109 fldds,ma -8(%arg1), %fr11 1110 fldds,ma -8(%arg1), %fr10 1111 fldds,ma -8(%arg1), %fr9 1112 fldds,ma -8(%arg1), %fr8 1113 fldds,ma -8(%arg1), %fr7 1114 fldds,ma -8(%arg1), %fr6 1115 fldds,ma -8(%arg1), %fr5 1116 fldds,ma -8(%arg1), %fr4 1117 fldds,ma -8(%arg1), %fr3 1118 fldds,ma -8(%arg1), %fr2 1119 fldds,ma -8(%arg1), %fr1 1120 fldds 0(%arg1), %fr0 /* fr0 must be restored last */ 1121 1122L$fpu_swap_done: 1123 1124 /* Increment the switch count and return. */ 1125 ldil L%fpu_csw, %r1 1126 ldw R%fpu_csw(%r1), %arg0 1127 ldo 1(%arg0), %arg0 1128 bv %r0(%rp) 1129 stw %arg0, R%fpu_csw(%r1) 1130 1131L$fpu_no_swap_in: 1132 1133 /* We didn't swap any FPU state in, so disable the FPU. */ 1134 mfctl CR_CCR, %r1 1135 depi 0, 25, 2, %r1 1136 b L$fpu_swap_done 1137 mtctl %r1, CR_CCR 1138EXIT(hppa_fpu_swapout) 1139 1140 /* Construct the virtual address tag. */ 1141 /* NB: it is legal for off and t to be the same. */ 1142#define VTAG(sp,off,t) \ 1143 shd %r0, off, 1, t /* t[1..15] = off[0..14] */ ! \ 1144 dep sp, 31, 16, t /* put in the space id */ ! \ 1145 depi 1, 0, 1, t /* and set the valid bit */ 1146 1147#if 0 1148 BSS(dtlb_c, 8) 1149 BSS(tlbd_c, 8) 1150 BSS(itlb_c, 8) 1151 1152 /* XXX this touches tr5, which it should not, perhaps */ 1153#define TLB_STATS_PRE(t) \ 1154 mfctl CR_ITMR, %r17 ! \ 1155 mtctl %r17, %tr5 1156 1157#define TLB_STATS_AFT(t) \ 1158 mfctl CR_ITMR, %r16 ! \ 1159 mfctl %tr5, %r17 ! \ 1160 ldil L%__CONCAT(t,_c), %r25 ! \ 1161 ldo R%__CONCAT(t,_c)(%r25), %r25 ! \ 1162 sub %r16, %r17, %r16 ! \ 1163 ldw 0(%r25), %r24 ! \ 1164 ldw 4(%r25), %r17 ! \ 1165 ldo 1(%r24), %r24 ! \ 1166 ldo -2(%r16), %r16 /* for mtctl */ ! \ 1167 add %r16, %r17, %r17 ! \ 1168 stw %r24, 0(%r25) ! \ 1169 stw %r17, 4(%r25) 1170 1171#else 1172#define TLB_STATS_PRE(t) /**/ 1173#define TLB_STATS_AFT(t) /**/ 1174#endif 1175 1176#define TLB_PULL(bits,lbl) ! \ 1177 /* space:pgaddr -- %r8:%r9 */ ! \ 1178 mfctl CR_VTOP, %r16 ! \ 1179 ldwax,s %r8(%r16), %r17 /* space -> page directory */ ! \ 1180 extru %r9, 9, 10, %r25 /* r25 = r9[31..22] */ ! \ 1181 combt,=,n %r0, %r17, lbl ! \ 1182 ldwax,s %r25(%r17), %r24 /* page -> page table */ ! \ 1183 extru %r9, 19, 10, %r16 /* r16 = r9[22..12] */ ! \ 1184 combt,=,n %r0, %r24, lbl ! \ 1185 ldwax,s %r16(%r24), %r17 /* va -> pa:prot */ ! \ 1186 sh2addl %r16, %r24, %r25 /* r25 = r16 << 2 + r24 */ ! \ 1187 combt,=,n %r0, %r17, lbl ! \ 1188 copy %r17, %r16 ! \ 1189 depi (bits), 21+bits, 1+bits, %r17 ! \ 1190 sub,= %r16, %r17, %r0 /* do not store if unchanged */ ! \ 1191 stwas %r17, 0(%r25) /* store back w/ the bits */ ! \ 1192 shd %r17, %r0, 13, %r25 ! \ 1193 dep %r8, 30, 15, %r25 /* mix0r the pid from the sid */! \ 1194 dep %r0, 31, 12, %r17 /* needed ? */ ! \ 1195 addi 2, %r25, %r25 ! \ 1196 extru %r17, 24, 25, %r17 1197 1198/* 1199 * possible optimizations: 1200 * change pte to reduce number of shifts 1201 * reorder to reduce stalls 1202 */ 1203#define TLB_PULL_L(bits,lbl) ! \ 1204 /* space:pgaddr -- %r8:%r9 */ ! \ 1205 mfctl CR_VTOP, %r16 ! \ 1206 ldwx,s %r8(%r16), %r17 /* space -> page directory */ ! \ 1207 extru %r9, 9, 10, %r25 ! \ 1208 combt,=,n %r0, %r17, lbl ! \ 1209 ldwx,s %r25(%r17), %r24 /* page -> page table */ ! \ 1210 extru %r9, 19, 10, %r16 ! \ 1211 combt,=,n %r0, %r24, lbl ! \ 1212 ldwx,s %r16(%r24), %r17 /* va -> pa:prot */ ! \ 1213 sh2addl %r16, %r24, %r25 ! \ 1214 combt,=,n %r0, %r17, lbl ! \ 1215 copy %r17, %r16 ! \ 1216 depi (bits), 21+bits, 1+bits, %r17 ! \ 1217 sub,= %r16, %r17, %r0 /* do not store if unchanged */ ! \ 1218 stws %r17, 0(%r25) /* store back w/ the bits */ ! \ 1219 shd %r17, %r0, 13, %r25 ! \ 1220 dep %r8, 30, 15, %r25 /* mix0r the pid from the sid */! \ 1221 dep %r0, 31, 12, %r17 /* needed ? */ ! \ 1222 addi 2, %r25, %r25 ! \ 1223 extru %r17, 24, 25, %r17 /* tlbbtop(%r17) */ ! \ 1224 sync 1225 1226#if defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU) 1227 1228 .align 32 1229 1230/* 1231 * This is a handler for interruption 20, "TLB dirty bit trap". It is used on 1232 * the PA7000 (PCX), PA7000 (PCX-S), and PA7100 (PCX-T). 1233 * Only shadowed registers are available, and they are: 1234 * 1235 * %r1 = C trap number 1236 * %r8 = data address space identifier. Copied from %isr. 1237 * %r9 = data address offset. Copied from %ior. 1238 * %r16 = undefined 1239 * %r17 = undefined 1240 * %r24 = undefined 1241 * %r25 = undefined 1242 */ 1243LEAF_ENTRY_NOPROFILE(TLABEL(tlbd_s)) 1244ALTENTRY(TLABEL(tlbd_t)) 1245ALTENTRY(TLABEL(tlbd_x)) 1246 TLB_STATS_PRE(tlbd) 1247 TLB_PULL(1, TLABEL(all)) 1248 mfsp %sr1, %r16 1249 mtsp %r8, %sr1 1250 idtlba %r17,(%sr1, %r9) 1251 idtlbp %r25,(%sr1, %r9) 1252 mtsp %r16, %sr1 1253 TLB_STATS_AFT(tlbd) 1254 rfir 1255 nop 1256EXIT(TLABEL(tlbd_s)) 1257 1258/* 1259 * This is a handler for interruption 6, "Instruction TLB miss fault". It is 1260 * used on the PA7000 (PCX), PA7000 (PCX-S), PA7100 (PCX-T) and PA7200 (PCX-T') 1261 * Only shadowed registers are available, and they are: 1262 * 1263 * %r1 = C trap number 1264 * %r8 = instruction address space identifier. Copied from %pcsq. 1265 * %r9 = instruction address offset. Copied from %pcoq. 1266 * %r16 = undefined 1267 * %r17 = undefined 1268 * %r24 = undefined 1269 * %r25 = undefined 1270 */ 1271LEAF_ENTRY_NOPROFILE(TLABEL(itlb_s)) 1272ALTENTRY(TLABEL(itlb_t)) 1273ALTENTRY(TLABEL(itlb_x)) 1274 TLB_STATS_PRE(itlb) 1275 TLB_PULL(0, TLABEL(all)) 1276 extru,= %r25, 5, 1, %r0 /* gate needs a kernel pid */ 1277 depi 0, 30, 15, %r25 1278 mfsp %sr1, %r16 1279 mtsp %r8, %sr1 1280 iitlba %r17,(%sr1, %r9) 1281 iitlbp %r25,(%sr1, %r9) 1282 mtsp %r16, %sr1 1283 TLB_STATS_AFT(itlb) 1284 rfir 1285 nop 1286EXIT(TLABEL(itlb_s)) 1287 1288/* 1289 * This is a handler for interruption 15, "Data TLB miss fault". It is used on 1290 * the PA7000 (PCX), PA7000 (PCX-S), PA7100 (PCX-T) and PA7200 (PCX-T'). 1291 * Only shadowed registers are available, and they are: 1292 * 1293 * %r1 = C trap number 1294 * %r8 = data address space identifier. Copied from %isr. 1295 * %r9 = data address offset. Copied from %ior. 1296 * %r16 = undefined 1297 * %r17 = undefined 1298 * %r24 = undefined 1299 * %r25 = undefined 1300 */ 1301LEAF_ENTRY_NOPROFILE(TLABEL(dtlb_s)) 1302ALTENTRY(TLABEL(dtlb_t)) 1303ALTENTRY(TLABEL(dtlb_x)) 1304 TLB_STATS_PRE(dtlb) 1305 TLB_PULL(0, TLABEL(all)) 1306 mfsp %sr1, %r16 1307 mtsp %r8, %sr1 1308 idtlba %r17,(%sr1, %r9) 1309 idtlbp %r25,(%sr1, %r9) 1310 mtsp %r16, %sr1 1311 TLB_STATS_AFT(dtlb) 1312 rfir 1313 nop 1314EXIT(TLABEL(dtlb_s)) 1315 1316/* 1317 * This is a handler for interruption 16, "Non-access instruction TLB miss 1318 * fault", and interrupt 17, "Non-access data TLB miss fault / Non-access data 1319 * page fault". It is used on the PA7000 (PCX), PA7000 (PCX-S), PA7100 (PCX-T) 1320 * and PA7200 (PCX-T'). 1321 * 1322 * Only shadowed registers are available, and they are: 1323 * 1324 * %r1 = C trap number 1325 * %r8 = instruction address space identifier. Copied from %isr. 1326 * %r9 = instruction address offset. Copied from %ior. 1327 * %r16 = undefined 1328 * %r17 = undefined 1329 * %r24 = undefined 1330 * %r25 = undefined 1331 */ 1332LEAF_ENTRY_NOPROFILE(TLABEL(dtlbna_s)) 1333ALTENTRY(TLABEL(itlbna_s)) 1334ALTENTRY(TLABEL(dtlbna_t)) 1335ALTENTRY(TLABEL(itlbna_t)) 1336ALTENTRY(TLABEL(dtlbna_x)) 1337ALTENTRY(TLABEL(itlbna_x)) 1338 TLB_STATS_PRE(dtlb) 1339 TLB_PULL(0, L$dtlbna_t_fake) 1340 mfsp %sr1, %r16 1341 mtsp %r8, %sr1 1342 idtlba %r17,(%sr1, %r9) 1343 idtlbp %r25,(%sr1, %r9) 1344 mtsp %r16, %sr1 1345 TLB_STATS_AFT(dtlb) 1346 rfir 1347 nop 1348L$dtlbna_s_fake: 1349L$dtlbna_t_fake: 1350 /* parse prober/w insns, have to decent to trap() to set regs proper */ 1351 mfctl %iir, %r16 1352 extru %r16, 6, 6, %r24 1353 comib,=,n 1, %r24, TLABEL(all) 1354 extru %r16, 24, 6, %r24 1355 subi,<> 0x23, %r24, %r0 1356 b TLABEL(all) 1357 /* otherwise generate a flush-only tlb entry */ 1358 copy %r0, %r17 1359 zdep %r8, 30, 15, %r25 1360 depi -13, 11, 7, %r25 1361 ldo 2(%r25), %r25 /* 3? */ 1362 mfsp %sr1, %r16 1363 mtsp %r8, %sr1 1364 idtlba %r17,(%sr1, %r9) 1365 idtlbp %r25,(%sr1, %r9) 1366 mtsp %r16, %sr1 1367 TLB_STATS_AFT(dtlb) 1368 rfir 1369 nop 1370EXIT(TLABEL(dtlbna_s)) 1371 1372#endif /* defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU) */ 1373 1374 1375#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU) 1376 1377#define IITLBAF(r) .word 0x04000440 | ((r) << 16) 1378#define IITLBPF(r) .word 0x04000400 | ((r) << 16) 1379#define IDTLBAF(r) .word 0x04001440 | ((r) << 16) 1380#define IDTLBPF(r) .word 0x04001400 | ((r) << 16) 1381 1382 .align 32 1383 1384/* 1385 * This is a handler for interruption 20, "TLB dirty bit trap". It is used on 1386 * the PA7100LC (PCX-L), PA7300LC (PCX-L2). 1387 * Only shadowed registers are available, and they are: 1388 * 1389 * %r1 = C trap number 1390 * %r8 = data address space identifier. Copied from %ior. 1391 * %r9 = data address offset. Copied from %isr. 1392 * %r16 = undefined 1393 * %r17 = undefined 1394 * %r24 = undefined 1395 * %r25 = undefined 1396 */ 1397 1398LEAF_ENTRY_NOPROFILE(TLABEL(tlbd_l)) 1399 TLB_STATS_PRE(tlbd) 1400 TLB_PULL_L(1, TLABEL(all)) 1401 IDTLBAF(17) 1402 IDTLBPF(25) 1403#ifdef USE_HPT 1404 /* invalidate instead of update */ 1405 mfctl %cr28, %r17 1406 ldw 0(%r17), %r24 1407 VTAG(%r8, %r9, %r16) 1408 sub,<> %r16, %r24, %r0 1409 stw %r0, 0(%r17) 1410#endif 1411 TLB_STATS_AFT(tlbd) 1412 rfir 1413 nop 1414EXIT(TLABEL(tlbd_l)) 1415 1416/* 1417 * This is a handler for interruption 6, "Instruction TLB miss fault". It is 1418 * used on the PA7100LC (PCX-L), PA7300LC (PCX-L2). 1419 * Only shadowed registers are available, and they are: 1420 * 1421 * %r1 = C trap number 1422 * %r8 = instruction address space identifier. Copied from %pcsq. 1423 * %r9 = instruction address offset. Copied from %pcoq. 1424 * %r16 = undefined 1425 * %r17 = undefined 1426 * %r24 = undefined 1427 * %r25 = undefined 1428 */ 1429 1430/* 1431 * from 7100lc ers, pg.6: 1432 * we found a post-silicon bug that makes cr28 1433 * unreliable for the itlb miss handler 1434 */ 1435LEAF_ENTRY_NOPROFILE(TLABEL(itlb_l)) 1436 TLB_STATS_PRE(itlb) 1437 TLB_PULL_L(0, TLABEL(all)) 1438 extru,= %r25, 5, 1, %r0 /* gate needs a kernel pid */ 1439 depi 0, 30, 15, %r25 1440 IITLBAF(17) 1441 IITLBPF(25) 1442 TLB_STATS_AFT(itlb) 1443 rfir 1444 nop 1445EXIT(TLABEL(itlb_l)) 1446 1447/* 1448 * This is a handler for interruption 16, "Non-access instruction TLB miss 1449 * fault", and interrupt 17, "Non-access data TLB miss fault / Non-access data 1450 * page fault". It is used on the PA7100LC (PCX-L), PA7300LC (PCX-L2). 1451 * Only shadowed registers are available, and they are: 1452 * 1453 * %r1 = C trap number 1454 * %r8 = instruction address space identifier. Copied from %isr. 1455 * %r9 = instruction address offset. Copied from %ior. 1456 * %r16 = undefined 1457 * %r17 = undefined 1458 * %r24 = undefined 1459 * %r25 = undefined 1460 */ 1461LEAF_ENTRY_NOPROFILE(TLABEL(dtlbna_l)) 1462ALTENTRY(TLABEL(itlbna_l)) 1463 TLB_STATS_PRE(dtlb) 1464 TLB_PULL_L(0, L$dtlbna_l_fake) 1465 IDTLBAF(17) 1466 IDTLBPF(25) 1467 TLB_STATS_AFT(dtlb) 1468 rfir 1469 nop 1470L$dtlbna_l_fake: 1471 /* parse prober/w insns, have to decent to trap() to set regs proper */ 1472 mfctl %iir, %r16 1473 extru %r16, 6, 6, %r24 1474 comib,=,n 1, %r24, TLABEL(all) 1475 extru %r16, 24, 6, %r24 1476 subi,<> 0x23, %r24, %r0 1477 b TLABEL(all) 1478 /* otherwise generate a flush-only tlb entry */ 1479 copy %r0, %r17 1480 zdep %r8, 30, 15, %r25 1481 depi -13, 11, 7, %r25 1482 ldo 2(%r25), %r25 /* 3? */ 1483 IDTLBAF(17) 1484 IDTLBPF(25) 1485 TLB_STATS_AFT(dtlb) 1486 rfir 1487 nop 1488EXIT(TLABEL(dtlbna_l)) 1489 1490/* 1491 * This is a handler for interruption 15, "Data TLB miss fault". It is used on 1492 * the PA7100LC (PCX-L), PA7300LC (PCX-L2). 1493 * Only shadowed registers are available, and they are: 1494 * 1495 * %r1 = C trap number 1496 * %r8 = instruction address space identifier. Copied from %isr. 1497 * %r9 = instruction address offset. Copied from %ior. 1498 * %r16 = undefined 1499 * %r17 = undefined 1500 * %r24 = undefined 1501 * %r25 = undefined 1502 */ 1503LEAF_ENTRY_NOPROFILE(TLABEL(dtlb_l)) 1504 TLB_STATS_PRE(dtlb) 1505 TLB_PULL_L(0, TLABEL(all)) 1506 IDTLBAF(17) 1507 IDTLBPF(25) 1508#ifdef USE_HPT 1509 /* 1510 * cache the next page mapping in the hpt. 1511 * 1512 * mapping for a page at the end of each 128k is uncachable 1513 * in the hvt since it'd be in the tlb itself and thus there 1514 * is no reason to cache it! 1515 * as a side effect this avoids recomputing hpt entry and 1516 * retraversing the whole page table each time. 1517 */ 1518 1519 ldo PAGE_SIZE(%r9), %r9 1520 extru,<> %r9, 20, 5, %r0 1521 b,n L$dtlb_done_l /* skip if no simple advance */ 1522 /* do not check the PT overlap since the above 1523 * check already guaranties that */ 1524 1525 /* ripped from TLB_PULL_L(0) */ 1526 extru %r9, 19, 10, %r16 /* %r24 was loaded in the TLB_PULL_L */ 1527 ldwx,s %r16(%r24), %r17 /* va -> pa:prot */ 1528 sh2addl %r16, %r24, %r25 1529 combt,=,n %r0, %r17, L$dtlb_done_l 1530 copy %r17, %r16 1531 depi 0, 21, 1, %r17 1532 sub,= %r16, %r17, %r0 /* do not store if unchanged */ 1533 stws %r17, 0(%r25) /* store back w/ the bits */ 1534 shd %r17, %r0, 13, %r25 1535 dep %r8, 30, 15, %r25 /* mix0r the pid from the sid */ 1536 dep %r0, 31, 12, %r17 /* needed ? */ 1537 addi 2, %r25, %r25 1538 extru %r17, 24, 25, %r17 1539 sync 1540 1541 mfctl %cr28, %r24 1542 VTAG(%r8, %r9, %r16) 1543 ldo 16(%r24), %r24 1544 stw %r16, 0(%r24) 1545 stw %r25, 4(%r24) 1546 stw %r17, 8(%r24) 1547L$dtlb_done_l: 1548#endif 1549 TLB_STATS_AFT(dtlb) 1550 rfir 1551 nop 1552EXIT(TLABEL(dtlb_l)) 1553#endif /* defined(HP7100LC_CPU) || defined(HP7300LC_CPU) */ 1554 1555#if defined(HP8000_CPU) || defined(HP8200_CPU) || \ 1556 defined(HP8500_CPU) || defined(HP8600_CPU) || \ 1557 defined(HP8700_CPU) 1558 1559 .level 2.0w 1560 1561 /* xlate 32bit->64bit pte */ 1562#define TLB_PCX2PCXU \ 1563 extrw,u %r25, 14, 13, %r16 ! \ 1564 depdi 0, 31, 32, %r17 ! \ 1565 /* fix io mappings */ ! \ 1566 extrd,s %r17, 42, 4, %r1 ! \ 1567 addi,<> 1, %r1, %r0 ! \ 1568 depdi -1, 38, 32, %r17 ! \ 1569 /* fix prom mappings */ ! \ 1570 extrd,s %r17, 46, 8, %r1 ! \ 1571 addi,<> 0x10, %r1, %r0 ! \ 1572 depdi 0, 38, 4, %r17 ! \ 1573 /* weak ordering, dyn bp */ ! \ 1574 depwi 1, 31, 2, %r16 ! \ 1575 depdi 0, 44, 30, %r25 ! \ 1576 depd %r16, 14, 15, %r25 1577 1578/* 1579 * This is a handler for interruption 20, "TLB dirty bit trap". It is used by 1580 * the PA8000 (PCX-U), PA8200 (PCX-W), PA8500 (PCX-W), and PA8600 (PCX-W+). 1581 * Only shadowed registers are available, and they are: 1582 * 1583 * %r1 = C trap number 1584 * %r8 = data address space identifier. Copied from %isr. 1585 * %r9 = data address offset. Copied from %ior. 1586 * %r16 = undefined 1587 * %r17 = undefined 1588 * %r24 = undefined 1589 * %r25 = undefined 1590 */ 1591LEAF_ENTRY_NOPROFILE(TLABEL(tlbd_u)) 1592 TLB_STATS_PRE(tlbd) 1593 TLB_PULL_L(1, TLABEL(all)) 1594 TLB_PCX2PCXU 1595 idtlbt %r17, %r25 1596 TLB_STATS_AFT(tlbd) 1597 rfir 1598 nop 1599EXIT(TLABEL(tlbd_u)) 1600 1601/* 1602 * This is a handler for interruption 6, "Instruction TLB miss fault". It is 1603 * the PA8000 (PCX-U), PA8200 (PCX-W), PA8500 (PCX-W), and PA8600 (PCX-W+). 1604 * Only shadowed registers are available, and they are: 1605 * 1606 * %r1 = C trap number 1607 * %r8 = data address space identifier. Copied from %isr. 1608 * %r9 = data address offset. Copied from %ior. 1609 * %r16 = undefined 1610 * %r17 = undefined 1611 * %r24 = undefined 1612 * %r25 = undefined 1613 */ 1614LEAF_ENTRY_NOPROFILE(TLABEL(itlb_u)) 1615 TLB_STATS_PRE(itlb) 1616 TLB_PULL_L(0, TLABEL(all)) 1617 extru,= %r25, 5, 1, %r0 /* gate needs a kernel pid */ 1618 depi 0, 30, 15, %r25 1619 TLB_PCX2PCXU 1620 iitlbt %r17, %r25 1621 TLB_STATS_AFT(itlb) 1622 rfir 1623 nop 1624EXIT(TLABEL(itlb_u)) 1625 1626 1627/* 1628 * This is a handler for interruption 16, "Non-access instruction TLB miss 1629 * fault", and interrupt 17, "Non-access data TLB miss fault / Non-access data 1630 * page fault". It is the PA8000 (PCX-U), PA8200 (PCX-W), PA8500 (PCX-W), 1631 * and PA8600 (PCX-W+). 1632 * Only shadowed registers are available, and they are: 1633 * 1634 * %r1 = C trap number 1635 * %r8 = instruction address space identifier. Copied from %isr. 1636 * %r9 = instruction address offset. Copied from %ior. 1637 * %r16 = undefined 1638 * %r17 = undefined 1639 * %r24 = undefined 1640 * %r25 = undefined 1641 */ 1642LEAF_ENTRY_NOPROFILE(TLABEL(dtlbna_u)) 1643ALTENTRY(TLABEL(itlbna_u)) 1644 TLB_STATS_PRE(dtlb) 1645 TLB_PULL_L(0, L$dtlbna_u_fake) 1646 TLB_PCX2PCXU 1647 idtlbt %r17, %r25 1648 TLB_STATS_AFT(dtlb) 1649 rfir 1650 nop 1651L$dtlbna_u_fake: 1652 /* parse prober/w insns, have to decent to trap() to set regs proper */ 1653 mfctl %iir, %r16 1654 extru %r16, 6, 6, %r24 1655 comib,=,n 1, %r24, TLABEL(all) 1656 extru %r16, 24, 6, %r24 1657 subi,<> 0x23, %r24, %r0 1658 b TLABEL(all) 1659 /* otherwise generate a flush-only tlb entry */ 1660 copy %r0, %r17 1661 zdep %r8, 30, 15, %r25 1662 depi -13, 11, 7, %r25 1663 ldo 2(%r25), %r25 /* 3? */ 1664 idtlbt %r17, %r25 1665 TLB_STATS_AFT(dtlb) 1666 rfir 1667 nop 1668EXIT(TLABEL(dtlbna_u)) 1669 1670/* 1671 * This is a handler for interruption 15, "Data TLB miss fault". It is the 1672 * PA8000 (PCX-U), PA8200 (PCX-W), PA8500 (PCX-W), and PA8600 (PCX-W+). 1673 * Only shadowed registers are available, and they are: 1674 * 1675 * %r1 = C trap number 1676 * %r8 = instruction address space identifier. Copied from %isr. 1677 * %r9 = instruction address offset. Copied from %ior. 1678 * %r16 = undefined 1679 * %r17 = undefined 1680 * %r24 = undefined 1681 * %r25 = undefined 1682 */ 1683LEAF_ENTRY_NOPROFILE(TLABEL(dtlb_u)) 1684 TLB_STATS_PRE(dtlb) 1685 TLB_PULL_L(0, TLABEL(all)) 1686 TLB_PCX2PCXU 1687 idtlbt %r17, %r25 1688 TLB_STATS_AFT(dtlb) 1689 rfir 1690 nop 1691EXIT(TLABEL(dtlb_u)) 1692 1693 .level 1.1 1694#endif /* HP8000_CPU */ 1695 1696#if defined(HP7000_CPU) 1697/* 1698 * int desidhash_s(void) 1699 * int desidhash_x(void) 1700 */ 1701LEAF_ENTRY_NOPROFILE(desidhash_s) 1702ALTENTRY(desidhash_x) 1703 sync 1704 MFCPU_T(DR_CPUCFG,22) /* %t1 */ 1705 MFCPU_T(DR_CPUCFG,22) 1706 nop 1707 nop 1708 depi 0, DR0_PCXS_DHE, 3, %t1 /* 3 4 DR0_PCXS_DOMAIN|DR0_PCXS_IHE */ 1709 depi 1, DR0_PCXS_EQWSTO, 1, %t1 1710 depi 0, DR0_PCXS_DHPMC, 1, %t1 1711 depi 0, DR0_PCXS_ILPMC, 1, %t1 1712 sync 1713 MTCPU_T(22,DR_CPUCFG) 1714 MTCPU_T(22,DR_CPUCFG) 1715 nop 1716 nop 1717 bv 0(%rp) 1718 extru %t1, 4, 5, %ret0 /* return chip revision */ 1719EXIT(desidhash_s) 1720#endif /* defined(HP7000_CPU) */ 1721 1722#if defined(HP7100_CPU) || defined(HP7200_CPU) 1723/* 1724 * void desidhash_t(void) 1725 */ 1726LEAF_ENTRY_NOPROFILE(desidhash_t) 1727 sync 1728 MFCPU_T(DR_CPUCFG,22) /* %t1 */ 1729 MFCPU_T(DR_CPUCFG,22) 1730 nop 1731 nop 1732 depi 0, DR0_PCXT_IHE, 1, %t1 1733 depi 0, DR0_PCXT_DHE, 1, %t1 1734 depi 0, DR0_PCXT_DHPMC, 1, %t1 1735 depi 0, DR0_PCXT_ILPMC, 1, %t1 1736 sync 1737 MTCPU_T(22,DR_CPUCFG) 1738 MTCPU_T(22,DR_CPUCFG) 1739 nop 1740 nop 1741 bv 0(%rp) 1742 extru %t1, 4, 5, %ret0 /* return chip revision */ 1743EXIT(desidhash_t) 1744#endif /* defined(HP7100_CPU) || defined(HP7200_CPU) */ 1745 1746#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU) 1747/* 1748 * int 1749 * ibtlb_l(int i, pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz, 1750 * u_int prot) 1751 */ 1752LEAF_ENTRY_NOPROFILE(ibtlb_l) 1753 rsm (PSW_R|PSW_I), %t4 1754 nop ! nop ! nop ! nop ! nop ! nop ! nop /* XXXNH why? */ 1755 1756 bv 0(%rp) 1757 mtsm %t4 1758EXIT(ibtlb_l) 1759 1760/* 1761 * void 1762 * hpti_l(addr,size) 1763*/ 1764LEAF_ENTRY_NOPROFILE(hpti_l) 1765 ldo -1(%arg1), %arg1 1766 depi 0, 31, 12, %arg1 1767 ldi 0x1c0, %t1 /* cache size assumed 128k XXX */ 1768 or %arg0, %t1, %arg0 1769 sync 1770 MTCPU_C(26,DR0_PCXL2_HTLB_ADDR) 1771 MTCPU_C(25,DR0_PCXL2_HTLB_CFG) 1772 nop 1773 nop 1774 bv,n %r0(%rp) 1775 nop 1776EXIT(hpti_l) 1777 1778/* 1779 * int 1780 * pbtlb_l(int i) 1781 */ 1782LEAF_ENTRY_NOPROFILE(pbtlb_l) 1783 ; DR_PAGE0 1784 rsm (PSW_R|PSW_I), %t4 1785 nop ! nop ! nop ! nop 1786 ldil L%0xc041, %t1 1787 ldo R%0xc041(%t1), %t1 1788 dep %arg0, 30, 3, %t1 1789 sync 1790 MTCPU_T(22,DR_DTLB) /* t1 */ 1791 nop 1792 nop 1793 mtsp %r0, %sr1 1794 idtlba %r0,(%sr1,%r0) 1795 idtlbp %r0,(%sr1,%r0) 1796 zdepi -1, 18, 1, %t1 1797 nop 1798 sync 1799 MTCPU_T(22,DR_DTLB) 1800 nop 1801 nop 1802 bv 0(%rp) 1803 mtsm %t4 1804EXIT(pbtlb_l) 1805 1806/* 1807 * int desidhash_l(void) 1808 */ 1809LEAF_ENTRY_NOPROFILE(desidhash_l) 1810 MFCPU_C(DR_CPUCFG,22) /* t1 */ 1811 nop 1812 nop 1813 depi 0, DR0_PCXL_L2IHASH_EN, 2, %t1 /* + DR0_PCXL_L2DHASH_EN */ 1814 depi 0, DR0_PCXL_L2IHPMC, 1, %t1 /* don't reset */ 1815 depi 0, DR0_PCXL_L2DHPMC, 1, %t1 /* don't reset */ 1816 depi 0, DR0_PCXL_L1IHPMC, 1, %t1 /* don't reset */ 1817 depi 0, DR0_PCXL_L2PARERR,1, %t1 /* don't reset */ 1818 sync 1819 /* set DR0_PCXL_L1ICACHE_EN ??? */ 1820 MTCPU_C(22,DR_CPUCFG) 1821 nop 1822 nop 1823 bv 0(%rp) 1824 extru %t1, 4, 5, %ret0 /* return chip revision */ 1825EXIT(desidhash_l) 1826 1827#endif /* defined(HP7100LC_CPU) || defined(HP7300LC_CPU) */ 1828 1829#if defined(HP8000_CPU) || defined(HP8200_CPU) || \ 1830 defined(HP8500_CPU) || defined(HP8600_CPU) || \ 1831 defined(HP8700_CPU) 1832 1833 .level 2.0w 1834LEAF_ENTRY_NOPROFILE(desidhash_u) 1835 MFCPU_U(2,28) 1836 depdi 0, 54, 1, %r28 1837 MTCPU_U(28,2) 1838 bv %r0(%rp) 1839 copy %r0, %ret0 /* XXX dunno how to get chip rev */ 1840EXIT(desidhash_u) 1841 1842LEAF_ENTRY_NOPROFILE(ibtlb_u) 1843 /* TODO insert a locked large tlb entry */ 1844 bv 0(%rp) 1845 nop 1846EXIT(ibtlb_u) 1847 1848LEAF_ENTRY_NOPROFILE(pbtlb_u) 1849 /* TODO purge a locked tlb entry */ 1850 bv 0(%rp) 1851 nop 1852EXIT(pbtlb_u) 1853 .level 1.1 1854#endif /* HP8000_CPU || HP8200_CPU || HP8500_CPU || HP8600_CPU || HP8700_CPU */ 1855 1856 .align 64 1857 .export TLABEL(all), entry 1858ENTRY_NOPROFILE(TLABEL(all),0) 1859 /* 1860 * at this point we have: 1861 * - psw copied into ipsw 1862 * - psw E(default), M(1 if HPMC, else 0), all others 0, i.e. 1863 * interrupts masked, absolute accesses are enabled, etc. 1864 * - PL 0 (highest privilege) 1865 * - r1, r8, r9, r16, r17, r24, r25 shadowed (maybe) 1866 * - r1: trap number 1867 * - tr7: old r1 1868 */ 1869 1870 mtctl %t3, %tr2 1871 1872 GET_CURCPU(%t3) 1873 1874 stw %t1, CI_TRAPSAVE + TF_R22(%t3) /* use ,bc */ 1875 stw %t2, CI_TRAPSAVE + TF_R21(%t3) 1876 1877 mfctl %tr2, %t1 1878 stw %sp, CI_TRAPSAVE + TF_R30(%t3) /* sp */ 1879 stw %t1, CI_TRAPSAVE + TF_R20(%t3) /* t3 */ 1880 1881 /* 1882 * Now, save away other volatile state that prevents us from turning 1883 * the PC queue back on, namely, the pc queue and ipsw, and the 1884 * interrupt information. 1885 */ 1886 1887 mfctl %eiem, %t1 1888 mfctl %ipsw, %t2 1889 stw %t1, CI_TRAPSAVE + TF_CR15(%t3) /* use ,bc */ 1890 stw %t2, CI_TRAPSAVE + TF_CR22(%t3) 1891 1892 mfsp %sr3, %t1 1893 mfctl %pidr1, %t2 1894 stw %t1, CI_TRAPSAVE + TF_SR3(%t3) 1895 stw %t2, CI_TRAPSAVE + TF_CR8(%t3) 1896 1897 /* Setup kernel context */ 1898 ldi HPPA_PID_KERNEL,%t1 1899 mtctl %t1, %pidr1 1900 mtsp %r0, %sr3 1901 1902 /* this will enable interrupts after `cold' */ 1903 GET_CURCPU(%t1) 1904 ldw CI_PSW(%t1), %t2 1905 mtctl %r0, %eiem 1906 mtctl %t2, %ipsw 1907 1908 /* save interruption instruction address space queue */ 1909 mfctl %pcsq, %t1 1910 mtctl %r0, %pcsq 1911 mfctl %pcsq, %t2 1912 stw %t1, CI_TRAPSAVE + TF_IISQH(%t3) /* use ,bc */ 1913 stw %t2, CI_TRAPSAVE + TF_IISQT(%t3) 1914 mtctl %r0, %pcsq 1915 1916 /* 1917 * Set up the kernel stack pointer. If the trap happened while we were 1918 * in unprivileged code, or in privileged code in the SYSCALLGATE page, 1919 * move to the kernel stack in curlwp's PCB; otherwise, start a new 1920 * stack frame on whatever kernel stack we're already on. 1921 * 1922 * This used to check only for a trap while we were in unprivileged 1923 * code, but this ignored the possibility that a trap could come in 1924 * during the period between a gateway instruction to raise privilege 1925 * and the disabling of interrupts. During this period we're still on 1926 * the user's stack, and we must move to the kernel stack. 1927 */ 1928 mfctl %pcoq, %t1 1929 ldil L%SYSCALLGATE, %t2 /* t2 = SYSCALLGATE */ 1930 ldo HPPA_FRAME_SIZE-1(%sp), %sp /* Assumed stack align step 1 */ 1931 dep %t1, 31, PGSHIFT, %t2 /* t2 |= (pcoqh & PAGE_MASK) */ 1932 dep,<> %t1, 31, 2, %r0 /* Nullify if user mode (!0) */ 1933 comb,<> %t1, %t2, L$trap_from_kernel /* if %t1 != %t2 => kernel */ 1934 dep %r0, 31, 6, %sp /* Assumed stack align step 2 */ 1935 1936 GET_CURLWP(%t2) 1937 depi 1, T_USER_POS, 1, %r1 1938 depi 1, TFF_LAST_POS, 1, %r1 1939 ldw L_PCB(%t2), %sp 1940#ifdef DIAGNOSTIC 1941 b L$trap_have_stack 1942#endif 1943 ldo NBPG(%sp), %sp 1944 1945L$trap_from_kernel: 1946#ifdef DIAGNOSTIC 1947 /* 1948 * Use the emergency stack if we have taken some kind 1949 * of TLB or protection fault on the kernel stack. 1950 */ 1951 mtctl %t1, %tr2 1952 ldw CI_TRAPSAVE + TF_R30(%t3), %t1 1953 mfctl %ior, %t2 1954 dep %r0, 31, PGSHIFT, %t1 1955 dep %r0, 31, PGSHIFT, %t2 1956 comb,=,n %t1, %t2, 0 1957 ldo NBPG(%t1), %t1 1958 comb,<> %t1, %t2, L$trap_have_stack 1959 mfctl %tr2, %t1 1960 mfctl %isr, %t2 1961 comib,<>,n HPPA_SID_KERNEL, %t2, L$trap_have_stack 1962#define _CHECK_TRAP_TYPE(tt) ldi tt, %t2 ! comb,= %r1, %t2, L$trap_kstack_fault 1963 _CHECK_TRAP_TYPE(T_ITLBMISS) 1964 _CHECK_TRAP_TYPE(T_DTLBMISS) 1965 _CHECK_TRAP_TYPE(T_ITLBMISSNA) 1966 _CHECK_TRAP_TYPE(T_DTLBMISSNA) 1967 _CHECK_TRAP_TYPE(T_DPROT) 1968 _CHECK_TRAP_TYPE(T_DATACC) 1969 _CHECK_TRAP_TYPE(T_DATAPID) 1970 ldi T_DATALIGN, %t2 1971 comb,<>,n %r1, %t2, L$trap_have_stack 1972#undef _CHECK_TRAP_TYPE 1973L$trap_kstack_fault: 1974 ldil L%emergency_stack_start, %sp 1975 ldo R%emergency_stack_start(%sp), %sp 1976L$trap_have_stack: 1977#endif 1978 ldil L%trapnowvirt, %t2 1979 ldo R%trapnowvirt(%t2), %t2 1980 mtctl %t2, %pcoq 1981 stw %t1, CI_TRAPSAVE + TF_IIOQH(%t3) 1982 ldo 4(%t2), %t2 1983 mfctl %pcoq, %t1 1984 stw %t1, CI_TRAPSAVE + TF_IIOQT(%t3) 1985 mtctl %t2, %pcoq 1986 1987 /* save the interruption space and offset registers */ 1988 mfctl %isr, %t1 1989 mfctl %ior, %t2 1990 stw %t1, CI_TRAPSAVE + TF_CR20(%t3) /* use ,bc */ 1991 stw %t2, CI_TRAPSAVE + TF_CR21(%t3) 1992 1993 /* save the interruption instruction register */ 1994 mfctl %iir, %t2 1995 stw %t2, CI_TRAPSAVE + TF_CR19(%t3) 1996 1997 /* save the trap type and flags */ 1998 stw %r1, CI_TRAPSAVE + TF_FLAGS(%t3) 1999 2000 /* gotta get it before R is up */ 2001 mfctl CR_RCTR, %t1 2002 2003 copy %sp, %t3 2004 ldo HPPA_FRAME_SIZE+TRAPFRAME_SIZEOF(%sp), %sp 2005 2006#if defined(DDB) || defined(KGDB) 2007 /* 2008 * Match the offset from %sp for the trapframe with syscall_entry 2009 */ 2010 ldo HPPA_FRAME_MAXARGS+HPPA_FRAME_SIZE-1(%sp),%sp 2011 depi 0, 31, 6, %sp 2012#endif 2013 rfir 2014 nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop 2015trapnowvirt: 2016 /* 2017 * %t3 contains the virtual address of the trapframe 2018 * %sp is loaded w/ the right VA (we did not need it being physical) 2019 */ 2020 2021 mfctl CR_CCR, %t2 2022 stw %t1, TF_CR0(%sr3, %t3) 2023 stw %t2, TF_CR10(%sr3, %t3) 2024 2025 mfsp %sr0, %t1 2026 mfsp %sr1, %t2 2027 stw %t1, TF_SR0(%sr3, %t3) 2028 stw %t2, TF_SR1(%sr3, %t3) 2029 2030 mfsp %sr2, %t1 2031 mfsp %sr4, %t2 2032 stw %t1, TF_SR2(%sr3, %t3) 2033 stw %t2, TF_SR4(%sr3, %t3) 2034 2035 mfsp %sr5, %t2 2036 mfsp %sr6, %t1 2037 stw %t2, TF_SR5(%sr3, %t3) 2038 stw %t1, TF_SR6(%sr3, %t3) 2039 2040 mfsp %sr7, %t1 2041 mfctl %pidr2, %t2 2042 stw %t1, TF_SR7(%sr3, %t3) 2043 stw %t2, TF_CR9(%sr3, %t3) 2044 2045 mtsp %r0, %sr0 2046 mtsp %r0, %sr1 2047 mtsp %r0, %sr2 2048 mtsp %r0, %sr4 2049 mtsp %r0, %sr5 2050 mtsp %r0, %sr6 2051 mtsp %r0, %sr7 2052 2053#if pbably_not_worth_it 2054 mfctl %pidr3, %t1 2055 mfctl %pidr4, %t2 2056 stw %t1, TF_CR12(%t3) 2057 stw %t2, TF_CR13(%t3) 2058#endif 2059 2060 /* 2061 * Save all general registers that we haven't saved already 2062 */ 2063 2064 /* XXXNH check this!!! */ 2065#if defined(DDB) || defined(KGDB) 2066 stw %rp, HPPA_FRAME_CRP(%sp) 2067 stw %r0, -HPPA_FRAME_SIZE(%sp) 2068#endif 2069 stw %t3, -HPPA_FRAME_SIZE+4(%sp) 2070 2071 mfctl %sar, %t1 /* use ,bc each cache line */ 2072 stw %t1, TF_CR11(%t3) 2073 stw %r1, TF_R1(%t3) 2074 stw %r2, TF_R2(%t3) 2075 stw %r3, TF_R3(%t3) 2076 2077 /* 2078 * Copy partially saved state from the store into the frame 2079 */ 2080 GET_CURCPU(%t2) 2081 ldo CI_TRAPSAVE(%t2), %t2 2082 2083 /* use ,bc each line */ 2084 ldw 0(%t2), %r1 ! ldw 4(%t2), %t1 ! stw %r1, 0(%t3) ! stw %t1, 4(%t3) 2085 ldw 8(%t2), %r1 ! ldw 12(%t2), %t1 ! stw %r1, 8(%t3) ! stw %t1, 12(%t3) 2086 ldw 16(%t2), %r1 ! ldw 20(%t2), %t1 ! stw %r1, 16(%t3) ! stw %t1, 20(%t3) 2087 ldw 24(%t2), %r1 ! ldw 28(%t2), %t1 ! stw %r1, 24(%t3) ! stw %t1, 28(%t3) 2088 ldw 32(%t2), %r1 ! ldw 36(%t2), %t1 ! stw %r1, 32(%t3) ! stw %t1, 36(%t3) 2089 ldw 40(%t2), %r1 ! ldw 44(%t2), %t1 ! stw %r1, 40(%t3) ! stw %t1, 44(%t3) 2090 ldw 48(%t2), %r1 ! ldw 52(%t2), %t1 ! stw %r1, 48(%t3) ! stw %t1, 52(%t3) 2091 ldw 56(%t2), %r1 ! ldw 60(%t2), %t1 ! stw %r1, 56(%t3) ! stw %t1, 60(%t3) 2092 2093 /* 2094 * Normally, we'd only have to save and restore the caller-save 2095 * registers, because the callee-save registers will be saved and 2096 * restored automatically by our callee(s). 2097 * 2098 * However, in two cases we need to save and restore all of the general 2099 * registers in the trapframe. One, if we're running a debugger, we 2100 * want the debugging person to be able to see and change any and all 2101 * general register values at the trap site. Two, if we have an FPU 2102 * emulator, this trap may be to emulate an instruction that needs to 2103 * read and write any and all general registers (for example, a load 2104 * or store instruction with a modify completer). 2105 * 2106 * See similar #ifdefs in the syscall entry and exit code. 2107 */ 2108 stw %r4, TF_R4(%t3) 2109 stw %r5, TF_R5(%t3) 2110 stw %r6, TF_R6(%t3) 2111 stw %r7, TF_R7(%t3) 2112 stw %r8, TF_R8(%t3) 2113 stw %r9, TF_R9(%t3) 2114 stw %r10, TF_R10(%t3) 2115 stw %r11, TF_R11(%t3) 2116 stw %r12, TF_R12(%t3) 2117 stw %r13, TF_R13(%t3) 2118 stw %r14, TF_R14(%t3) 2119 stw %r15, TF_R15(%t3) 2120 stw %r16, TF_R16(%t3) 2121 stw %r17, TF_R17(%t3) 2122 stw %r18, TF_R18(%t3) 2123 2124 stw %t4, TF_R19(%t3) 2125 stw %r23,TF_R23(%t3) 2126 stw %r24,TF_R24(%t3) 2127 stw %r25,TF_R25(%t3) 2128 stw %r26,TF_R26(%t3) 2129 stw %r27,TF_R27(%t3) 2130 stw %r28,TF_R28(%t3) 2131 stw %r29,TF_R29(%t3) 2132 stw %r31,TF_R31(%t3) 2133 2134 /* 2135 * Save the necessary control registers that have not already saved. 2136 */ 2137#if defined(DDB) || defined(KGDB) 2138 /* 2139 * Save v2p translation table pointer 2140 */ 2141 mfctl %eirr, %t1 2142 mfctl CR_VTOP, %t2 2143 stw %t1, TF_CR23(%t3) 2144 stw %t2, TF_CR25(%t3) 2145 2146 mfctl %cr24, %t1 2147 mfctl %cr28, %t2 2148 stw %t1, TF_CR24(%t3) 2149 stw %t2, TF_CR28(%t3) 2150 2151#endif 2152 mfctl CR_TLS, %t1 2153 mfctl CR_FPPADDR, %t2 2154 stw %t1, TF_CR27(%t3) 2155 stw %t2, TF_CR30(%t3) 2156 2157 /* 2158 * load the global pointer for the kernel 2159 */ 2160 2161 ldil L%$global$, %dp 2162 ldo R%$global$(%dp), %dp 2163 2164 /* 2165 * call the C routine trap(). 2166 * form trap type in the first argument to trap() 2167 */ 2168 ldw TF_FLAGS(%t3), %arg0 2169 dep %r0, 24, 25, %arg0 2170 copy %t3, %arg1 2171 2172#if defined(DDB) || defined(KGDB) 2173 /* Mark frame pointer as NULL to indicate syscall/trap */ 2174 copy %r0, %r3 2175#endif 2176 2177 .import trap, code 2178 CALL(trap, %t1) 2179 2180 ldw -HPPA_FRAME_SIZE+4(%sp), %t3 2181 /* see if curlwp has changed */ 2182 ldw TF_FLAGS(%t3), %arg0 2183 bb,>=,n %arg0, TFF_LAST_POS, L$trap_return 2184 nop 2185 2186 /* load curlwp's trapframe pointer */ 2187 GET_CURLWP(%t2) 2188 ldw L_MD(%t2), %t3 2189 2190L$trap_return: 2191 ldil L%syscall_return, %t1 2192 ldo R%syscall_return(%t1), %t1 2193 bv,n %r0(%t1) 2194 nop 2195 2196EXIT(TLABEL(all)) 2197 2198 .align 32 2199ENTRY_NOPROFILE(TLABEL(ibrk),0) 2200 /* If called by a user process then always pass it to trap() */ 2201 mfctl %pcoq, %r8 2202 extru,= %r8, 31, 2, %r0 2203 b,n L$ibrk_bad 2204 2205 /* don't accept breaks from data segments */ 2206 .import etext 2207 ldil L%etext, %r9 2208 ldo R%etext(%r9), %r9 2209 comb,>>=,n %r8, %r9, L$ibrk_bad 2210 2211 mfctl %iir, %r8 2212 extru %r8, 31, 5, %r9 2213 comib,<>,n HPPA_BREAK_KERNEL, %r9, L$ibrk_bad 2214 2215 /* now process all those `break' calls we make */ 2216 extru %r8, 18, 13, %r9 2217 comib,=,n HPPA_BREAK_GET_PSW, %r9, L$ibrk_getpsw 2218 comib,=,n HPPA_BREAK_SET_PSW, %r9, L$ibrk_setpsw 2219 2220L$ibrk_bad: 2221 /* illegal (unimplemented) break entry point */ 2222 b TLABEL(all) 2223 nop 2224 2225L$ibrk_getpsw: 2226 b L$ibrk_exit 2227 mfctl %ipsw, %ret0 2228 2229L$ibrk_setpsw: 2230 mfctl %ipsw, %ret0 2231 b L$ibrk_exit 2232 mtctl %arg0, %ipsw 2233 2234 /* insert other fast breaks here */ 2235 nop ! nop 2236 2237L$ibrk_exit: 2238 /* skip the break */ 2239 mtctl %r0, %pcoq 2240 mfctl %pcoq, %r9 2241 mtctl %r9, %pcoq 2242 ldo 4(%r9), %r9 2243 mtctl %r9, %pcoq 2244 rfir 2245 nop 2246EXIT(TLABEL(ibrk)) 2247