1/* $NetBSD: locore.s,v 1.143 2022/08/07 10:12:19 andvar Exp $ */ 2 3/*- 4 * Copyright (c) 1999, 2000, 2019 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 35 * All rights reserved. 36 * 37 * Author: Chris G. Demetriou 38 * 39 * Permission to use, copy, modify and distribute this software and 40 * its documentation is hereby granted, provided that both the copyright 41 * notice and this permission notice appear in all copies of the 42 * software, derivative works or modified versions, and any portions 43 * thereof, and that both notices appear in supporting documentation. 44 * 45 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 46 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 47 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 48 * 49 * Carnegie Mellon requests users of this software to return to 50 * 51 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 52 * School of Computer Science 53 * Carnegie Mellon University 54 * Pittsburgh PA 15213-3890 55 * 56 * any improvements or extensions that they make and grant Carnegie the 57 * rights to redistribute these changes. 58 */ 59 60.stabs __FILE__,100,0,0,kernel_text 61 62#include "opt_ddb.h" 63#include "opt_kgdb.h" 64#include "opt_multiprocessor.h" 65#include "opt_lockdebug.h" 66#include "opt_compat_netbsd.h" 67 68#include <machine/asm.h> 69 70__KERNEL_RCSID(0, "$NetBSD: locore.s,v 1.143 2022/08/07 10:12:19 andvar Exp $"); 71 72#include "assym.h" 73 74.stabs __FILE__,132,0,0,kernel_text 75 76 /* don't reorder instructions; paranoia. */ 77 .set noreorder 78 .text 79 80 .macro bfalse reg, dst 81 beq \reg, \dst 82 .endm 83 84 .macro btrue reg, dst 85 bne \reg, \dst 86 .endm 87 88/* 89 * This is for kvm_mkdb, and should be the address of the beginning 90 * of the kernel text segment (not necessarily the same as kernbase). 91 */ 92 EXPORT(kernel_text) 93.loc 1 __LINE__ 94kernel_text: 95 96/* 97 * bootstack: a temporary stack, for booting. 98 * 99 * Extends from 'start' down. 100 */ 101bootstack: 102 103/* 104 * locorestart: Kernel start. This is no longer the actual entry 105 * point, although jumping to here (the first kernel address) will 106 * in fact work just fine. 107 * 108 * Arguments: 109 * a0 is the first free page frame number (PFN) 110 * a1 is the page table base register (PTBR) 111 * a2 is the bootinfo magic number 112 * a3 is the pointer to the bootinfo structure 113 * 114 * All arguments are passed to alpha_init(). 115 */ 116IMPORT(prom_mapped, 4) 117NESTED_NOPROFILE(locorestart,1,0,ra,0,0) 118 br pv,1f 1191: LDGP(pv) 120 121 /* Switch to the boot stack. */ 122 lda sp,bootstack 123 124 /* Load KGP with current GP. */ 125 mov a0, s0 /* save pfn */ 126 mov gp, a0 127 call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */ 128 mov s0, a0 /* restore pfn */ 129 130 /* 131 * Call alpha_init() to do pre-main initialization. 132 * alpha_init() gets the arguments we were called with, 133 * which are already in a0, a1, a2, a3, and a4. 134 */ 135 CALL(alpha_init) 136 137 /* Set up the virtual page table pointer. */ 138 ldiq a0, VPTBASE 139 call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */ 140 141 /* 142 * Switch to lwp0's PCB. 143 */ 144 lda a0, lwp0 145 ldq a0, L_MD_PCBPADDR(a0) /* phys addr of PCB */ 146 call_pal PAL_OSF1_swpctx /* clobbers a0, t0, t8-t11, a0 */ 147 148 /* PROM is no longer mapped. */ 149 lda t0, prom_mapped 150 stl zero, 0(t0) 151 152 /* 153 * We've switched to a new page table base, so invalidate the TLB 154 * and I-stream. This happens automatically everywhere but here. 155 */ 156 ldiq a0, -2 /* TBIA */ 157 call_pal PAL_OSF1_tbi 158 call_pal PAL_imb 159 160 /* 161 * All ready to go! Call main()! 162 * 163 * We're going to play a little trick there, though. We are 164 * going to fake our return address as the kthread backstop. 165 * Hitting the backstop will trigger a panic, and we want lwp0 166 * to work like other kthreads in that regard. We will still 167 * keep the "main returned" backstop here in case something 168 * goes horribly wrong. 169 */ 170 lda ra, alpha_kthread_backstop 171 jsr s0, main 172 ldgp gp, 0(s0) 173 174 /* This should never happen. */ 175 PANIC("main() returned",Lmain_returned_pmsg) 176 END(locorestart) 177 178/**************************************************************************/ 179 180/* 181 * Pull in the PROM interface routines; these are needed for 182 * prom printf (while bootstrapping), and for determining the 183 * boot device, etc. 184 */ 185#include <alpha/alpha/prom_disp.s> 186 187/**************************************************************************/ 188 189/* 190 * Pull in the PALcode function stubs. 191 */ 192#include <alpha/alpha/pal.s> 193 194/**************************************************************************/ 195 196/**************************************************************************/ 197 198#if defined(MULTIPROCESSOR) 199/* 200 * Pull in the multiprocssor glue. 201 */ 202#include <alpha/alpha/multiproc.s> 203#endif /* MULTIPROCESSOR */ 204 205/**************************************************************************/ 206 207/**************************************************************************/ 208 209#if defined(DDB) || defined(KGDB) 210/* 211 * Pull in debugger glue. 212 */ 213#include <alpha/alpha/debug.s> 214#endif /* DDB || KGDB */ 215 216/**************************************************************************/ 217 218/**************************************************************************/ 219 220/* 221 * Pull in optimized pmap subroutines. 222 */ 223#include <alpha/alpha/pmap_subr.s> 224 225/**************************************************************************/ 226 227/**************************************************************************/ 228 229 .text 230.stabs __FILE__,132,0,0,backtolocore1 /* done with includes */ 231.loc 1 __LINE__ 232backtolocore1: 233/**************************************************************************/ 234 235#ifdef COMPAT_16 236/* 237 * Signal "trampoline" code. 238 * 239 * The kernel arranges for the handler to be invoked directly. This 240 * trampoline is used only to return from the signal. 241 * 242 * The stack pointer points to the saved sigcontext. 243 */ 244 245NESTED_NOPROFILE(sigcode,0,0,ra,0,0) 246 mov sp, a0 /* get pointer to sigcontext */ 247 CALLSYS_NOERROR(compat_16___sigreturn14) /* and call sigreturn() with it. */ 248 mov v0, a0 /* if that failed, get error code */ 249 CALLSYS_NOERROR(exit) /* and call exit() with it. */ 250XNESTED(esigcode,0) 251 END(sigcode) 252#endif /* COMPAT_16 */ 253 254/**************************************************************************/ 255 256/* 257 * exception_return: return from trap, exception, or syscall 258 */ 259 260LEAF(exception_return, 1) /* XXX should be NESTED */ 261 br pv, 1f 2621: LDGP(pv) 263 264 ldq s1, (FRAME_PS * 8)(sp) /* s1 = new PSL */ 265 and s1, ALPHA_PSL_IPL_MASK, s3 /* s3 = new ipl */ 266 267 /* --- BEGIN inline spllower() --- */ 268 269 cmpult s3, ALPHA_PSL_IPL_SOFT_HI, t1 /* new IPL < SOFT_HI? */ 270 beq t1, 5f /* no, can't do AST or SI */ 271 /* yes */ 272 273 /* GET_CURLWP clobbers v0, t0, t8...t11. */ 274 GET_CURLWP 275 mov v0, s0 /* s0 = curlwp */ 276 2772: /* 278 * Check to see if a soft interrupt is pending. We need to only 279 * check for soft ints eligible to run at the new IPL. We generate 280 * the mask of eligible soft ints to run by masking the ssir with: 281 * 282 * (ALPHA_ALL_SOFTINTS << ((ipl) << 1)) 283 * 284 * See alpha_softint_dispatch(). 285 */ 286 ldq t1, L_CPU(s0) /* t1 = curlwp->l_cpu */ 287 ldiq t2, ALPHA_ALL_SOFTINTS /* t2 = ALPHA_ALL_SOFTINTS */ 288 ldq t1, CPU_INFO_SSIR(t1) /* t1 = t1->ci_ssir */ 289 sll s3, 1, t3 /* t3 = ipl << 1 */ 290 sll t2, t3, t2 /* t2 <<= t3 */ 291 and t1, t2, t1 /* t1 &= t2 */ 292 bne t1, 6f /* yes */ 293 /* no */ 294 295 /* --- END inline spllower() --- */ 296 297 and s1, ALPHA_PSL_USERMODE, t0 /* are we returning to user? */ 298 beq t0, 5f /* no: just return */ 299 /* yes */ 300 301 /* check for AST */ 3023: ldl t3, L_MD_ASTPENDING(s0) /* AST pending? */ 303 bne t3, 7f /* yes */ 304 /* no: headed back to user space */ 305 306 /* Enable the FPU based on whether MDLWP_FPACTIVE is set. */ 3074: ldq t2, L_MD_FLAGS(s0) 308 cmplt t2, zero, a0 309 call_pal PAL_OSF1_wrfen 310 311 /* restore the registers, and return */ 3125: bsr ra, exception_restore_regs /* jmp/CALL trashes pv/t12 */ 313 ldq ra,(FRAME_RA*8)(sp) 314 .set noat 315 ldq at_reg,(FRAME_AT*8)(sp) 316 317 lda sp,(FRAME_SW_SIZE*8)(sp) 318 call_pal PAL_OSF1_rti 319 .set at 320 /* NOTREACHED */ 321 322 /* We've got a softint */ 3236: ldiq a0, ALPHA_PSL_IPL_HIGH 324 call_pal PAL_OSF1_swpipl 325 mov v0, s2 /* remember old IPL */ 326 mov s3, a0 /* pass new ipl */ 327 CALL(alpha_softint_dispatch) 328 329 /* SI handled; restore IPL and check again */ 330 mov s2, a0 331 call_pal PAL_OSF1_swpipl 332 br 2b 333 334 /* We've got an AST */ 3357: stl zero, L_MD_ASTPENDING(s0) /* no AST pending */ 336 337 ldiq a0, ALPHA_PSL_IPL_0 /* drop IPL to zero */ 338 call_pal PAL_OSF1_swpipl 339 mov v0, s2 /* remember old IPL */ 340 341 mov sp, a0 /* only arg is frame */ 342 CALL(ast) 343 344 /* AST handled; restore IPL and check again */ 345 mov s2, a0 346 call_pal PAL_OSF1_swpipl 347 br 3b 348 349 END(exception_return) 350 351LEAF(exception_save_regs, 0) 352 stq v0,(FRAME_V0*8)(sp) 353 stq a3,(FRAME_A3*8)(sp) 354 stq a4,(FRAME_A4*8)(sp) 355 stq a5,(FRAME_A5*8)(sp) 356 stq s0,(FRAME_S0*8)(sp) 357 stq s1,(FRAME_S1*8)(sp) 358 stq s2,(FRAME_S2*8)(sp) 359 stq s3,(FRAME_S3*8)(sp) 360 stq s4,(FRAME_S4*8)(sp) 361 stq s5,(FRAME_S5*8)(sp) 362 stq s6,(FRAME_S6*8)(sp) 363 stq t0,(FRAME_T0*8)(sp) 364 stq t1,(FRAME_T1*8)(sp) 365 stq t2,(FRAME_T2*8)(sp) 366 stq t3,(FRAME_T3*8)(sp) 367 stq t4,(FRAME_T4*8)(sp) 368 stq t5,(FRAME_T5*8)(sp) 369 stq t6,(FRAME_T6*8)(sp) 370 stq t7,(FRAME_T7*8)(sp) 371 stq t8,(FRAME_T8*8)(sp) 372 stq t9,(FRAME_T9*8)(sp) 373 stq t10,(FRAME_T10*8)(sp) 374 stq t11,(FRAME_T11*8)(sp) 375 stq t12,(FRAME_T12*8)(sp) 376 RET 377 END(exception_save_regs) 378 379LEAF(exception_restore_regs, 0) 380 ldq v0,(FRAME_V0*8)(sp) 381 ldq a3,(FRAME_A3*8)(sp) 382 ldq a4,(FRAME_A4*8)(sp) 383 ldq a5,(FRAME_A5*8)(sp) 384 ldq s0,(FRAME_S0*8)(sp) 385 ldq s1,(FRAME_S1*8)(sp) 386 ldq s2,(FRAME_S2*8)(sp) 387 ldq s3,(FRAME_S3*8)(sp) 388 ldq s4,(FRAME_S4*8)(sp) 389 ldq s5,(FRAME_S5*8)(sp) 390 ldq s6,(FRAME_S6*8)(sp) 391 ldq t0,(FRAME_T0*8)(sp) 392 ldq t1,(FRAME_T1*8)(sp) 393 ldq t2,(FRAME_T2*8)(sp) 394 ldq t3,(FRAME_T3*8)(sp) 395 ldq t4,(FRAME_T4*8)(sp) 396 ldq t5,(FRAME_T5*8)(sp) 397 ldq t6,(FRAME_T6*8)(sp) 398 ldq t7,(FRAME_T7*8)(sp) 399 ldq t8,(FRAME_T8*8)(sp) 400 ldq t9,(FRAME_T9*8)(sp) 401 ldq t10,(FRAME_T10*8)(sp) 402 ldq t11,(FRAME_T11*8)(sp) 403 ldq t12,(FRAME_T12*8)(sp) 404 RET 405 END(exception_restore_regs) 406 407/**************************************************************************/ 408 409/* 410 * XentArith: 411 * System arithmetic trap entry point. 412 */ 413 414 PALVECT(XentArith) /* setup frame, save registers */ 415 416 /* a0, a1, & a2 already set up */ 417 ldiq a3, ALPHA_KENTRY_ARITH 418 mov sp, a4 ; .loc 1 __LINE__ 419 CALL(trap) 420 421 jmp zero, exception_return 422 END(XentArith) 423 424/**************************************************************************/ 425 426/* 427 * XentIF: 428 * System instruction fault trap entry point. 429 */ 430 431 PALVECT(XentIF) /* setup frame, save registers */ 432 433 /* a0, a1, & a2 already set up */ 434 ldiq a3, ALPHA_KENTRY_IF 435 mov sp, a4 ; .loc 1 __LINE__ 436 CALL(trap) 437 jmp zero, exception_return 438 END(XentIF) 439 440/**************************************************************************/ 441 442/* 443 * XentInt: 444 * System interrupt entry point. 445 */ 446 447 PALVECT(XentInt) /* setup frame, save registers */ 448 449 /* a0, a1, & a2 already set up */ 450 mov sp, a3 ; .loc 1 __LINE__ 451 CALL(interrupt) 452 jmp zero, exception_return 453 END(XentInt) 454 455/**************************************************************************/ 456 457/* 458 * XentMM: 459 * System memory management fault entry point. 460 */ 461 462 PALVECT(XentMM) /* setup frame, save registers */ 463 464 /* a0, a1, & a2 already set up */ 465 ldiq a3, ALPHA_KENTRY_MM 466 mov sp, a4 ; .loc 1 __LINE__ 467 CALL(trap) 468 469 jmp zero, exception_return 470 END(XentMM) 471 472/**************************************************************************/ 473 474/* 475 * XentSys: 476 * System call entry point. 477 */ 478 479 ESETUP(XentSys) ; .loc 1 __LINE__ 480 481 stq v0,(FRAME_V0*8)(sp) /* in case we need to restart */ 482 stq s0,(FRAME_S0*8)(sp) 483 stq s1,(FRAME_S1*8)(sp) 484 stq s2,(FRAME_S2*8)(sp) 485 stq s3,(FRAME_S3*8)(sp) 486 stq s4,(FRAME_S4*8)(sp) 487 stq s5,(FRAME_S5*8)(sp) 488 stq s6,(FRAME_S6*8)(sp) 489 stq a0,(FRAME_A0*8)(sp) 490 stq a1,(FRAME_A1*8)(sp) 491 stq a2,(FRAME_A2*8)(sp) 492 stq a3,(FRAME_A3*8)(sp) 493 stq a4,(FRAME_A4*8)(sp) 494 stq a5,(FRAME_A5*8)(sp) 495 stq ra,(FRAME_RA*8)(sp) 496 497 /* syscall number, passed in v0, is first arg, frame pointer second */ 498 mov v0,a1 499 GET_CURLWP 500 mov v0,a0 501 mov sp,a2 ; .loc 1 __LINE__ 502 ldq t11,L_PROC(a0) 503 ldq t12,P_MD_SYSCALL(t11) 504 CALL((t12)) 505 506 jmp zero, exception_return 507 END(XentSys) 508 509/**************************************************************************/ 510 511/* 512 * XentUna: 513 * System unaligned access entry point. 514 */ 515 516LEAF(XentUna, 3) /* XXX should be NESTED */ 517 .set noat 518 lda sp,-(FRAME_SW_SIZE*8)(sp) 519 stq at_reg,(FRAME_AT*8)(sp) 520 .set at 521 stq ra,(FRAME_RA*8)(sp) 522 bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */ 523 524 /* a0, a1, & a2 already set up */ 525 ldiq a3, ALPHA_KENTRY_UNA 526 mov sp, a4 ; .loc 1 __LINE__ 527 CALL(trap) 528 529 jmp zero, exception_return 530 END(XentUna) 531 532/**************************************************************************/ 533 534/* 535 * savefpstate: Save a process's floating point state. 536 * 537 * Arguments: 538 * a0 'struct fpstate *' to save into 539 */ 540 541LEAF(savefpstate, 1) 542 LDGP(pv) 543 /* save all of the FP registers */ 544 lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */ 545 stt $f0, (0 * 8)(t1) /* save first register, using hw name */ 546 stt $f1, (1 * 8)(t1) /* etc. */ 547 stt $f2, (2 * 8)(t1) 548 stt $f3, (3 * 8)(t1) 549 stt $f4, (4 * 8)(t1) 550 stt $f5, (5 * 8)(t1) 551 stt $f6, (6 * 8)(t1) 552 stt $f7, (7 * 8)(t1) 553 stt $f8, (8 * 8)(t1) 554 stt $f9, (9 * 8)(t1) 555 stt $f10, (10 * 8)(t1) 556 stt $f11, (11 * 8)(t1) 557 stt $f12, (12 * 8)(t1) 558 stt $f13, (13 * 8)(t1) 559 stt $f14, (14 * 8)(t1) 560 stt $f15, (15 * 8)(t1) 561 stt $f16, (16 * 8)(t1) 562 stt $f17, (17 * 8)(t1) 563 stt $f18, (18 * 8)(t1) 564 stt $f19, (19 * 8)(t1) 565 stt $f20, (20 * 8)(t1) 566 stt $f21, (21 * 8)(t1) 567 stt $f22, (22 * 8)(t1) 568 stt $f23, (23 * 8)(t1) 569 stt $f24, (24 * 8)(t1) 570 stt $f25, (25 * 8)(t1) 571 stt $f26, (26 * 8)(t1) 572 stt $f27, (27 * 8)(t1) 573 .set noat 574 stt $f28, (28 * 8)(t1) 575 .set at 576 stt $f29, (29 * 8)(t1) 577 stt $f30, (30 * 8)(t1) 578 579 /* 580 * Then save the FPCR; note that the necessary 'trapb's are taken 581 * care of on kernel entry and exit. 582 */ 583 mf_fpcr ft0 584 stt ft0, FPREG_FPR_CR(a0) /* store to FPCR save area */ 585 586 RET 587 END(savefpstate) 588 589/**************************************************************************/ 590 591/* 592 * restorefpstate: Restore a process's floating point state. 593 * 594 * Arguments: 595 * a0 'struct fpstate *' to restore from 596 */ 597 598LEAF(restorefpstate, 1) 599 LDGP(pv) 600 /* 601 * Restore the FPCR; note that the necessary 'trapb's are taken care of 602 * on kernel entry and exit. 603 */ 604 ldt ft0, FPREG_FPR_CR(a0) /* load from FPCR save area */ 605 mt_fpcr ft0 606 607 /* Restore all of the FP registers. */ 608 lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */ 609 ldt $f0, (0 * 8)(t1) /* restore first reg., using hw name */ 610 ldt $f1, (1 * 8)(t1) /* etc. */ 611 ldt $f2, (2 * 8)(t1) 612 ldt $f3, (3 * 8)(t1) 613 ldt $f4, (4 * 8)(t1) 614 ldt $f5, (5 * 8)(t1) 615 ldt $f6, (6 * 8)(t1) 616 ldt $f7, (7 * 8)(t1) 617 ldt $f8, (8 * 8)(t1) 618 ldt $f9, (9 * 8)(t1) 619 ldt $f10, (10 * 8)(t1) 620 ldt $f11, (11 * 8)(t1) 621 ldt $f12, (12 * 8)(t1) 622 ldt $f13, (13 * 8)(t1) 623 ldt $f14, (14 * 8)(t1) 624 ldt $f15, (15 * 8)(t1) 625 ldt $f16, (16 * 8)(t1) 626 ldt $f17, (17 * 8)(t1) 627 ldt $f18, (18 * 8)(t1) 628 ldt $f19, (19 * 8)(t1) 629 ldt $f20, (20 * 8)(t1) 630 ldt $f21, (21 * 8)(t1) 631 ldt $f22, (22 * 8)(t1) 632 ldt $f23, (23 * 8)(t1) 633 ldt $f24, (24 * 8)(t1) 634 ldt $f25, (25 * 8)(t1) 635 ldt $f26, (26 * 8)(t1) 636 ldt $f27, (27 * 8)(t1) 637 ldt $f28, (28 * 8)(t1) 638 ldt $f29, (29 * 8)(t1) 639 ldt $f30, (30 * 8)(t1) 640 641 RET 642 END(restorefpstate) 643 644/**************************************************************************/ 645 646/* 647 * savectx: save process context, i.e. callee-saved registers 648 * 649 * Note that savectx() only works for processes other than curlwp, 650 * since cpu_switchto will copy over the info saved here. (It _can_ 651 * sanely be used for curlwp iff cpu_switchto won't be called again, e.g. 652 * if called from boot().) 653 * 654 * N.B. this is actually only used by dumpsys(). 655 * 656 * Arguments: 657 * a0 'struct pcb *' of the process that needs its context saved 658 */ 659 660LEAF(savectx, 1) 661 br pv, 1f 6621: LDGP(pv) 663 stq sp, PCB_HWPCB_KSP(a0) /* store sp */ 664 stq s0, PCB_CONTEXT+(0 * 8)(a0) /* store s0 - s6 */ 665 stq s1, PCB_CONTEXT+(1 * 8)(a0) 666 stq s2, PCB_CONTEXT+(2 * 8)(a0) 667 stq s3, PCB_CONTEXT+(3 * 8)(a0) 668 stq s4, PCB_CONTEXT+(4 * 8)(a0) 669 stq s5, PCB_CONTEXT+(5 * 8)(a0) 670 stq s6, PCB_CONTEXT+(6 * 8)(a0) 671 stq ra, PCB_CONTEXT+(7 * 8)(a0) /* store ra */ 672 RET 673 END(savectx) 674 675/**************************************************************************/ 676 677/* 678 * void alpha_softint_switchto(struct lwp *current, int ipl, struct lwp *next) 679 * Switch away from the current LWP to the specified softint LWP, and 680 * dispatch to softint processing. 681 * Aguments: 682 * a0 'struct lwp *' of the LWP to switch from 683 * a1 IPL that the softint will run at 684 * a2 'struct lwp *' of the LWP to switch to 685 * 686 * N.B. We have arranged that a0 and a1 are already set up correctly 687 * for the call to softint_dispatch(). 688 */ 689NESTED_NOPROFILE(alpha_softint_switchto, 3, 16, ra, IM_RA, 0) 690 LDGP(pv) 691 692 ldq a3, L_PCB(a0) /* a3 = from->l_pcb */ 693 694 lda sp, -16(sp) /* set up stack frame */ 695 stq ra, 0(sp) /* save ra */ 696 697 /* 698 * Step 1: Save the current LWP's context. We don't 699 * save the return address directly; instead, we arrange 700 * for it to bounce through a trampoline that fixes up 701 * the state in case the softint LWP blocks. 702 */ 703 stq sp, PCB_HWPCB_KSP(a3) /* store sp */ 704 stq s0, PCB_CONTEXT+(0 * 8)(a3) /* store s0 - s6 */ 705 stq s1, PCB_CONTEXT+(1 * 8)(a3) 706 stq s2, PCB_CONTEXT+(2 * 8)(a3) 707 stq s3, PCB_CONTEXT+(3 * 8)(a3) 708 stq s4, PCB_CONTEXT+(4 * 8)(a3) 709 stq s5, PCB_CONTEXT+(5 * 8)(a3) 710 stq s6, PCB_CONTEXT+(6 * 8)(a3) 711 712 /* Set the trampoline address in saved context. */ 713 lda v0, alpha_softint_return 714 stq v0, PCB_CONTEXT+(7 * 8)(a3) /* store ra */ 715 716 /* 717 * Step 2: Switch to the softint LWP's stack. 718 * We always start at the top of the stack (i.e. 719 * just below the trapframe). 720 * 721 * N.B. There is no need to restore any other registers 722 * from the softint LWP's context; we are starting from 723 * the root of the call graph. 724 */ 725 ldq sp, L_MD_TF(a2) 726 727 /* 728 * Step 3: Update curlwp. 729 * 730 * N.B. We save off the from-LWP argument that will be passed 731 * to softint_dispatch() in s0, which we'll need to restore 732 * before returning. If we bounce through the trampoline, the 733 * context switch will restore it for us. 734 */ 735 mov a0, s0 /* s0 = from LWP */ 736 SET_CURLWP(a2) /* clobbers a0, v0, t0, t8..t11 */ 737 738 /* 739 * Step 4: Call softint_dispatch(). 740 * 741 * N.B. a1 already has the IPL argument. 742 */ 743 mov s0, a0 /* a0 = from LWP */ 744 CALL(softint_dispatch) 745 746 /* 747 * Step 5: Restore everything and return. 748 */ 749 ldq a3, L_PCB(s0) /* a3 = from->l_pcb */ 750 SET_CURLWP(s0) /* clobbers a0, v0, t0, t8..t11 */ 751 ldq sp, PCB_HWPCB_KSP(a3) /* restore sp */ 752 ldq s0, PCB_CONTEXT+(0 * 8)(a3) /* restore s0 */ 753 ldq ra, 0(sp) /* restore ra */ 754 lda sp, 16(sp) /* pop stack frame */ 755 RET 756 END(alpha_softint_switchto) 757 758LEAF_NOPROFILE(alpha_softint_return, 0) 759 /* 760 * Step 1: Go to IPL_HIGH, which is what the alpha_softint_dispatch() 761 * expects. We will have arrived here at IPL_SCHED. 762 */ 763 ldiq a0, ALPHA_PSL_IPL_HIGH 764 call_pal PAL_OSF1_swpipl 765 766 /* 767 * Step 2: Re-adjust the mutex count after mi_switch(). 768 */ 769 GET_CURLWP 770 ldq v0, L_CPU(v0) 771 ldl t0, CPU_INFO_MTX_COUNT(v0) 772 addl t0, 1, t0 773 stl t0, CPU_INFO_MTX_COUNT(v0) 774 775 /* 776 * Step 3: Pop alpha_softint_switchto()'s stack frame 777 * and return. 778 */ 779 ldq ra, 0(sp) /* restore ra */ 780 lda sp, 16(sp) /* pop stack frame */ 781 RET 782 END(alpha_softint_return) 783 784/* 785 * struct lwp *cpu_switchto(struct lwp *current, struct lwp *next, 786 * bool returning) 787 * Switch to the specified next LWP 788 * Arguments: 789 * a0 'struct lwp *' of the LWP to switch from 790 * a1 'struct lwp *' of the LWP to switch to 791 * a2 non-zero if we're returning to an interrupted LWP 792 * from a soft interrupt 793 */ 794LEAF(cpu_switchto, 0) 795 LDGP(pv) 796 797 /* 798 * do an inline savectx(), to save old context 799 */ 800 ldq a3, L_PCB(a0) 801 /* NOTE: ksp is stored by the swpctx */ 802 stq s0, PCB_CONTEXT+(0 * 8)(a3) /* store s0 - s6 */ 803 stq s1, PCB_CONTEXT+(1 * 8)(a3) 804 stq s2, PCB_CONTEXT+(2 * 8)(a3) 805 stq s3, PCB_CONTEXT+(3 * 8)(a3) 806 stq s4, PCB_CONTEXT+(4 * 8)(a3) 807 stq s5, PCB_CONTEXT+(5 * 8)(a3) 808 stq s6, PCB_CONTEXT+(6 * 8)(a3) 809 stq ra, PCB_CONTEXT+(7 * 8)(a3) /* store ra */ 810 811 mov a0, s4 /* save old curlwp */ 812 mov a1, s2 /* save new lwp */ 813 814 /* 815 * Check to see if we're doing a light-weight switch back to 816 * an interrupted LWP (referred to as the "pinned" LWP) from 817 * a softint LWP. In this case we have been running on the 818 * pinned LWP's context -- swpctx was not used to get here -- 819 * so we won't be using swpctx to go back, either. 820 */ 821 bne a2, 3f /* yes, go handle it */ 822 /* no, normal context switch */ 823 824 /* Switch to the new PCB. */ 825 ldq a0, L_MD_PCBPADDR(s2) 826 call_pal PAL_OSF1_swpctx /* clobbers a0, t0, t8-t11, v0 */ 827 8281: SET_CURLWP(s2) /* curlwp = l */ 829 830 /* 831 * Now running on the new PCB. 832 */ 833 ldq s0, L_PCB(s2) 834 835 /* 836 * Check for restartable atomic sequences (RAS). 837 */ 838 ldq a0, L_PROC(s2) /* first ras_lookup() arg */ 839 ldq t0, P_RASLIST(a0) /* any RAS entries? */ 840 bne t0, 4f /* yes, go deal with it */ 8412: 842 mov s4, v0 /* return the old lwp */ 843 /* 844 * Restore registers and return. 845 * NOTE: ksp is restored by the swpctx. 846 */ 847 ldq s1, PCB_CONTEXT+(1 * 8)(s0) /* restore s1-s6 */ 848 ldq s2, PCB_CONTEXT+(2 * 8)(s0) 849 ldq s3, PCB_CONTEXT+(3 * 8)(s0) 850 ldq s4, PCB_CONTEXT+(4 * 8)(s0) 851 ldq s5, PCB_CONTEXT+(5 * 8)(s0) 852 ldq s6, PCB_CONTEXT+(6 * 8)(s0) 853 ldq ra, PCB_CONTEXT+(7 * 8)(s0) /* restore ra */ 854 ldq s0, PCB_CONTEXT+(0 * 8)(s0) /* restore s0 */ 855 856 RET 857 8583: /* 859 * Registers right now: 860 * 861 * a0 old LWP 862 * a1 new LWP 863 * a3 old PCB 864 * 865 * What we need to do here is swap the stack, since we won't 866 * be getting that from swpctx. 867 */ 868 ldq a2, L_PCB(a1) /* a2 = new PCB */ 869 stq sp, PCB_HWPCB_KSP(a3) /* save old SP */ 870 ldq sp, PCB_HWPCB_KSP(a2) /* restore new SP */ 871 br 1b /* finish up */ 872 8734: 874 ldq s1, L_MD_TF(s2) /* s1 = l->l_md.md_tf */ 875 ldq a1, (FRAME_PC*8)(s1) /* second ras_lookup() arg */ 876 CALL(ras_lookup) /* ras_lookup(p, PC) */ 877 addq v0, 1, t0 /* -1 means "not in ras" */ 878 beq t0, 2b /* not in ras? return */ 879 stq v0, (FRAME_PC*8)(s1) /* in ras? fix up PC */ 880 br 2b /* finish up */ 881 882 END(cpu_switchto) 883 884/* 885 * lwp_trampoline() 886 * 887 * Arrange for a function to be invoked neatly, after a cpu_lwp_fork(), 888 * which has set up our pcb_context for us. But we actually *get here* 889 * via cpu_switchto(), which returns the LWP we switched away from in v0. 890 * 891 * Invokes the function specified by the s0 register with the return 892 * address specified by the s1 register and with one argument specified 893 * by the s2 register. 894 */ 895LEAF_NOPROFILE(lwp_trampoline, 0) 896 mov v0, a0 /* a0 = prev_lwp (from cpu_switchto()) */ 897 mov s3, a1 /* a1 = new_lwp (that's us!) */ 898 CALL(lwp_startup) /* lwp_startup(prev_lwp, new_lwp); */ 899 mov s0, pv /* pv = func */ 900 mov s1, ra /* ra = (probably exception_return()) */ 901 mov s2, a0 /* a0 = arg */ 902 jmp zero, (pv) /* func(arg) */ 903 END(lwp_trampoline) 904 905/**************************************************************************/ 906 907/* 908 * alpha_copystr(const void *from, void *to, size_t len, size_t *donep) 909 */ 910 .arch ev56 911LEAF(alpha_copystr_bwx, 4) 912 LDGP(pv) 913 914 mov a2, t0 /* t0 = i = len */ 915 beq a2, 5f /* if (len == 0), bail */ 916 9171: ldbu t1, 0(a0) /* t1 = *from */ 918 subl a2, 1, a2 /* len-- */ 919 addq a0, 1, a0 /* from++ */ 920 stb t1, 0(a1) /* *to = t1 */ 921 beq t1, 2f /* if (t1 == '\0'), bail out */ 922 addq a1, 1, a1 /* to++ */ 923 bne a2, 1b /* if (len != 0), copy more */ 924 9252: beq a3, 3f /* if (lenp != NULL) */ 926 subl t0, a2, t0 /* *lenp = (i - len) */ 927 stq t0, 0(a3) 9283: bne t1, 4f /* *from != '\0'; leave in a huff */ 929 930 mov zero, v0 /* return 0. */ 931 RET 932 9334: ldiq v0, ENAMETOOLONG 934 RET 935 9365: ldiq t1, 1 /* fool the test above... */ 937 br zero, 2b 938 939 nop /* pad to same length as... */ 940 nop /* non-BWX version. */ 941 nop 942 nop 943 nop 944 EXPORT(alpha_copystr_bwx_end) 945 END(alpha_copystr_bwx) 946 .arch ev4 947 948LEAF(alpha_copystr, 4) 949 LDGP(pv) 950 951 mov a2, t0 /* t0 = i = len */ 952 beq a2, 5f /* if (len == 0), bail */ 953 9541: ldq_u t1, 0(a0) /* t1 = *from */ 955 extbl t1, a0, t1 956 ldq_u t3, 0(a1) /* set up t2 with quad around *to */ 957 insbl t1, a1, t2 958 mskbl t3, a1, t3 959 or t3, t2, t3 /* add *from to quad around *to */ 960 stq_u t3, 0(a1) /* write out that quad */ 961 962 subl a2, 1, a2 /* len-- */ 963 beq t1, 2f /* if (*from == 0), bail out */ 964 addq a1, 1, a1 /* to++ */ 965 addq a0, 1, a0 /* from++ */ 966 bne a2, 1b /* if (len != 0) copy more */ 967 9682: beq a3, 3f /* if (lenp != NULL) */ 969 subl t0, a2, t0 /* *lenp = (i - len) */ 970 stq t0, 0(a3) 9713: bne t1, 4f /* *from != '\0'; leave in a huff */ 972 973 mov zero, v0 /* return 0. */ 974 RET 975 9764: ldiq v0, ENAMETOOLONG 977 RET 978 9795: ldiq t1, 1 /* fool the test above... */ 980 br zero, 2b 981 EXPORT(alpha_copystr_end) 982 END(alpha_copystr) 983 984NESTED(copyinstr, 4, 16, ra, IM_RA|IM_S0, 0) 985 LDGP(pv) 986 lda sp, -16(sp) /* set up stack frame */ 987 stq ra, (16-8)(sp) /* save ra */ 988 stq s0, (16-16)(sp) /* save s0 */ 989 ldiq t0, VM_MAX_ADDRESS /* make sure that src addr */ 990 cmpult a0, t0, t1 /* is in user space. */ 991 beq t1, copyerr_efault /* if it's not, error out. */ 992 /* Note: GET_CURLWP clobbers v0, t0, t8...t11. */ 993 GET_CURLWP 994 ldq s0, L_PCB(v0) /* s0 = pcb */ 995 lda v0, copyerr /* set up fault handler. */ 996 stq v0, PCB_ONFAULT(s0) 997 CALL(alpha_copystr) /* do the copy. */ 998 stq zero, PCB_ONFAULT(s0) /* kill the fault handler. */ 999 ldq ra, (16-8)(sp) /* restore ra. */ 1000 ldq s0, (16-16)(sp) /* restore s0. */ 1001 lda sp, 16(sp) /* kill stack frame. */ 1002 RET /* v0 left over from copystr */ 1003 END(copyinstr) 1004 1005NESTED(copyoutstr, 4, 16, ra, IM_RA|IM_S0, 0) 1006 LDGP(pv) 1007 lda sp, -16(sp) /* set up stack frame */ 1008 stq ra, (16-8)(sp) /* save ra */ 1009 stq s0, (16-16)(sp) /* save s0 */ 1010 ldiq t0, VM_MAX_ADDRESS /* make sure that dest addr */ 1011 cmpult a1, t0, t1 /* is in user space. */ 1012 beq t1, copyerr_efault /* if it's not, error out. */ 1013 /* Note: GET_CURLWP clobbers v0, t0, t8...t11. */ 1014 GET_CURLWP 1015 ldq s0, L_PCB(v0) /* s0 = pcb */ 1016 lda v0, copyerr /* set up fault handler. */ 1017 stq v0, PCB_ONFAULT(s0) 1018 CALL(alpha_copystr) /* do the copy. */ 1019 stq zero, PCB_ONFAULT(s0) /* kill the fault handler. */ 1020 ldq ra, (16-8)(sp) /* restore ra. */ 1021 ldq s0, (16-16)(sp) /* restore s0. */ 1022 lda sp, 16(sp) /* kill stack frame. */ 1023 RET /* v0 left over from copystr */ 1024 END(copyoutstr) 1025 1026/* 1027 * kcopy(const void *src, void *dst, size_t len); 1028 * 1029 * Copy len bytes from src to dst, aborting if we encounter a fatal 1030 * page fault. 1031 * 1032 * kcopy() _must_ save and restore the old fault handler since it is 1033 * called by uiomove(), which may be in the path of servicing a non-fatal 1034 * page fault. 1035 * 1036 * N.B. This implementation is a wrapper around memcpy(), which is 1037 * implemented in src/common/lib/libc/arch/alpha/string/bcopy.S. 1038 * This is safe ONLY because we know that, as implemented, it is 1039 * a LEAF function (and thus does not use any callee-saved registers). 1040 */ 1041NESTED(kcopy, 3, 32, ra, IM_RA|IM_S0|IM_S1, 0) 1042 LDGP(pv) 1043 lda sp, -32(sp) /* set up stack frame */ 1044 stq ra, (32-8)(sp) /* save ra */ 1045 stq s0, (32-16)(sp) /* save s0 */ 1046 stq s1, (32-24)(sp) /* save s1 */ 1047 /* Swap a0, a1, for call to memcpy(). */ 1048 mov a1, v0 1049 mov a0, a1 1050 mov v0, a0 1051 /* Note: GET_CURLWP clobbers v0, t0, t8...t11. */ 1052 GET_CURLWP 1053 ldq s1, L_PCB(v0) /* s1 = pcb */ 1054 lda v0, kcopyerr /* set up fault handler. */ 1055 ldq s0, PCB_ONFAULT(s1) /* save old handler. */ 1056 stq v0, PCB_ONFAULT(s1) 1057 CALL(memcpy) /* do the copy. */ 1058 stq s0, PCB_ONFAULT(s1) /* restore the old handler. */ 1059 ldq ra, (32-8)(sp) /* restore ra. */ 1060 ldq s0, (32-16)(sp) /* restore s0. */ 1061 ldq s1, (32-24)(sp) /* restore s1. */ 1062 lda sp, 32(sp) /* kill stack frame. */ 1063 mov zero, v0 /* return 0. */ 1064 RET 1065 END(kcopy) 1066 1067LEAF(kcopyerr, 0) 1068 LDGP(pv) 1069 stq s0, PCB_ONFAULT(s1) /* s1 == pcb (from above) */ 1070 ldq ra, (32-8)(sp) /* restore ra. */ 1071 ldq s0, (32-16)(sp) /* restore s0. */ 1072 ldq s1, (32-24)(sp) /* restore s1. */ 1073 lda sp, 32(sp) /* kill stack frame. */ 1074 RET 1075END(kcopyerr) 1076 1077NESTED(copyin, 3, 16, ra, IM_RA|IM_S0, 0) 1078 LDGP(pv) 1079 lda sp, -16(sp) /* set up stack frame */ 1080 stq ra, (16-8)(sp) /* save ra */ 1081 stq s0, (16-16)(sp) /* save s0 */ 1082 ldiq t0, VM_MAX_ADDRESS /* make sure that src addr */ 1083 cmpult a0, t0, t1 /* is in user space. */ 1084 beq t1, copyerr_efault /* if it's not, error out. */ 1085 /* Swap a0, a1, for call to memcpy(). */ 1086 mov a1, v0 1087 mov a0, a1 1088 mov v0, a0 1089 /* Note: GET_CURLWP clobbers v0, t0, t8...t11. */ 1090 GET_CURLWP 1091 ldq s0, L_PCB(v0) /* s = pcb */ 1092 lda v0, copyerr /* set up fault handler. */ 1093 stq v0, PCB_ONFAULT(s0) 1094 CALL(memcpy) /* do the copy. */ 1095 stq zero, PCB_ONFAULT(s0) /* kill the fault handler. */ 1096 ldq ra, (16-8)(sp) /* restore ra. */ 1097 ldq s0, (16-16)(sp) /* restore s0. */ 1098 lda sp, 16(sp) /* kill stack frame. */ 1099 mov zero, v0 /* return 0. */ 1100 RET 1101 END(copyin) 1102 1103NESTED(copyout, 3, 16, ra, IM_RA|IM_S0, 0) 1104 LDGP(pv) 1105 lda sp, -16(sp) /* set up stack frame */ 1106 stq ra, (16-8)(sp) /* save ra */ 1107 stq s0, (16-16)(sp) /* save s0 */ 1108 ldiq t0, VM_MAX_ADDRESS /* make sure that dest addr */ 1109 cmpult a1, t0, t1 /* is in user space. */ 1110 beq t1, copyerr_efault /* if it's not, error out. */ 1111 /* Swap a0, a1, for call to memcpy(). */ 1112 mov a1, v0 1113 mov a0, a1 1114 mov v0, a0 1115 /* Note: GET_CURLWP clobbers v0, t0, t8...t11. */ 1116 GET_CURLWP 1117 ldq s0, L_PCB(v0) /* s0 = pcb */ 1118 lda v0, copyerr /* set up fault handler. */ 1119 stq v0, PCB_ONFAULT(s0) 1120 CALL(memcpy) /* do the copy. */ 1121 stq zero, PCB_ONFAULT(s0) /* kill the fault handler. */ 1122 ldq ra, (16-8)(sp) /* restore ra. */ 1123 ldq s0, (16-16)(sp) /* restore s0. */ 1124 lda sp, 16(sp) /* kill stack frame. */ 1125 mov zero, v0 /* return 0. */ 1126 RET 1127 END(copyout) 1128 1129LEAF(copyerr_efault, 0) 1130 ldiq v0, EFAULT /* return EFAULT. */ 1131XLEAF(copyerr, 0) 1132 LDGP(pv) 1133 ldq ra, (16-8)(sp) /* restore ra. */ 1134 ldq s0, (16-16)(sp) /* restore s0. */ 1135 lda sp, 16(sp) /* kill stack frame. */ 1136 RET 1137END(copyerr) 1138 1139/**************************************************************************/ 1140 1141#define UFETCHSTORE_PROLOGUE \ 1142 br pv, 1f ;\ 11431: LDGP(pv) ;\ 1144 ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ ;\ 1145 cmpult a0, t0, t1 /* is in user space. */ ;\ 1146 beq t1, ufetchstoreerr_efault /* if it's not, error out. */ 1147 1148/* LINTSTUB: int _ufetch_8(const uint8_t *uaddr, uint8_t *valp); */ 1149LEAF_NOPROFILE(_ufetch_8, 2) 1150 UFETCHSTORE_PROLOGUE 1151.L_ufetch_8_start: 1152 ldq_u t0, 0(a0) /* load quad containing byte */ 1153.L_ufetch_8_end: 1154 extbl t0, a0, a0 /* a0 = extracted byte */ 1155 ldq_u t0, 0(a1) /* load dest quad */ 1156 insbl a0, a1, a0 /* a0 = byte in target position */ 1157 mskbl t0, a1, t0 /* clear target byte in destination */ 1158 or a0, t0, a0 /* or in byte to destination */ 1159 stq_u a0, 0(a1) /* *a1 = fetched byte! */ 1160 mov zero, v0 1161 RET 1162 END(_ufetch_8) 1163 1164/* LINTSTUB: int _ufetch_16(const uint16_t *uaddr, uint16_t *valp); */ 1165LEAF_NOPROFILE(_ufetch_16, 2) 1166 UFETCHSTORE_PROLOGUE 1167.L_ufetch_16_start: 1168 ldq_u t0, 0(a0) /* load quad containing short */ 1169.L_ufetch_16_end: 1170 extwl t0, a0, a0 /* a0 = extracted short */ 1171 ldq_u t0, 0(a1) /* load dest quad */ 1172 inswl a0, a1, a0 /* a0 = short in target position */ 1173 mskwl t0, a1, t0 /* clear target short in destination */ 1174 or a0, t0, a0 /* or in short to destination */ 1175 stq_u a0, 0(a1) /* *a1 = fetched short! */ 1176 mov zero, v0 1177 RET 1178 END(_ufetch_16) 1179 1180/* LINTSTUB: int _ufetch_32(const uint32_t *uaddr, uint32_t *valp); */ 1181LEAF_NOPROFILE(_ufetch_32, 2) 1182 UFETCHSTORE_PROLOGUE 1183.L_ufetch_32_start: 1184 ldl v0, 0(a0) 1185.L_ufetch_32_end: 1186 stl v0, 0(a1) 1187 mov zero, v0 1188 RET 1189 END(_ufetch_32) 1190 1191/* LINTSTUB: int _ufetch_64(const uint64_t *uaddr, uint64_t *valp); */ 1192LEAF_NOPROFILE(_ufetch_64, 2) 1193 UFETCHSTORE_PROLOGUE 1194.L_ufetch_64_start: 1195 ldq v0, 0(a0) 1196.L_ufetch_64_end: 1197 stq v0, 0(a1) 1198 mov zero, v0 1199 RET 1200 END(_ufetch_64) 1201 1202/* LINTSTUB: int _ustore_8(uint8_t *uaddr, uint8_t val); */ 1203LEAF_NOPROFILE(_ustore_8, 2) 1204 UFETCHSTORE_PROLOGUE 1205 zap a1, 0xfe, a1 /* kill arg's high bytes */ 1206 insbl a1, a0, a1 /* move it to the right spot */ 1207.L_ustore_8_start: 1208 ldq_u t0, 0(a0) /* load quad around byte */ 1209 mskbl t0, a0, t0 /* kill the target byte */ 1210 or t0, a1, a1 /* put the result together */ 1211 stq_u a1, 0(a0) /* and store it. */ 1212.L_ustore_8_end: 1213 mov zero, v0 1214 RET 1215 END(_ustore_8) 1216 1217/* LINTSTUB: int _ustore_16(uint16_t *uaddr, uint16_t val); */ 1218LEAF_NOPROFILE(_ustore_16, 2) 1219 UFETCHSTORE_PROLOGUE 1220 zap a1, 0xfc, a1 /* kill arg's high bytes */ 1221 inswl a1, a0, a1 /* move it to the right spot */ 1222.L_ustore_16_start: 1223 ldq_u t0, 0(a0) /* load quad around short */ 1224 mskwl t0, a0, t0 /* kill the target short */ 1225 or t0, a1, a1 /* put the result together */ 1226 stq_u a1, 0(a0) /* and store it. */ 1227.L_ustore_16_end: 1228 mov zero, v0 1229 RET 1230 END(_ustore_16) 1231 1232/* LINTSTUB: int _ustore_32(uint32_t *uaddr, uint32_t val); */ 1233LEAF_NOPROFILE(_ustore_32, 2) 1234 UFETCHSTORE_PROLOGUE 1235.L_ustore_32_start: 1236 stl a1, 0(a0) 1237.L_ustore_32_end: 1238 mov zero, v0 1239 RET 1240 END(_ustore_32) 1241 1242/* LINTSTUB: int _ustore_64(uint64_t *uaddr, uint64_t val); */ 1243LEAF_NOPROFILE(_ustore_64, 2) 1244 UFETCHSTORE_PROLOGUE 1245.L_ustore_64_start: 1246 stq a1, 0(a0) 1247.L_ustore_64_end: 1248 mov zero, v0 1249 RET 1250 END(_ustore_64) 1251 1252LEAF_NOPROFILE(ufetchstoreerr_efault, 0) 1253 ldiq v0, EFAULT /* return EFAULT. */ 1254XLEAF(ufetchstoreerr, 0) 1255 LDGP(pv) 1256 RET 1257 END(ufetchstoreerr_efault) 1258 1259/**************************************************************************/ 1260 1261/* 1262 * int _ucas_32(volatile uint32_t *uptr, uint32_t old, uint32_t new, 1263 * uint32_t *ret); 1264 */ 1265LEAF_NOPROFILE(_ucas_32, 4) 1266 UFETCHSTORE_PROLOGUE 12673: 1268.Lucas_32_start: 1269 mov a2, t2 1270 ldl_l t0, 0(a0) /* t0 = *uptr */ 1271 cmpeq t0, a1, t1 /* does t0 = old? */ 1272 beq t1, 1f /* if not, skip */ 1273 stl_c t2, 0(a0) /* *uptr ~= new */ 1274.Lucas_32_end: 1275 beq t1, 2f /* did it work? */ 12761: 1277 stl t0, 0(a3) /* *ret = t0 */ 1278 mov zero, v0 1279 RET 12802: 1281 br 3b 1282END(_ucas_32) 1283 1284/* 1285 * int _ucas_64(volatile uint64_t *uptr, uint64_t old, uint64_t new, 1286 * uint64_t *ret); 1287 */ 1288LEAF_NOPROFILE(_ucas_64, 4) 1289 UFETCHSTORE_PROLOGUE 12903: 1291.Lucas_64_start: 1292 mov a2, t2 1293 ldq_l t0, 0(a0) /* t0 = *uptr */ 1294 cmpeq t0, a1, t1 /* does t0 = old? */ 1295 beq t1, 1f /* if not, skip */ 1296 stq_c t2, 0(a0) /* *uptr ~= new */ 1297.Lucas_64_end: 1298 beq t1, 2f /* did it work? */ 12991: 1300 stq t0, 0(a3) /* *ret = t0 */ 1301 mov zero, v0 1302 RET 13032: 1304 br 3b 1305END(_ucas_64) 1306 1307/**************************************************************************/ 1308 1309/* 1310 * Fault table of user access functions for trap(). 1311 */ 1312 .section ".rodata" 1313 .globl onfault_table 1314onfault_table: 1315 .quad .L_ufetch_8_start 1316 .quad .L_ufetch_8_end 1317 .quad ufetchstoreerr 1318 1319 .quad .L_ufetch_16_start 1320 .quad .L_ufetch_16_end 1321 .quad ufetchstoreerr 1322 1323 .quad .L_ufetch_32_start 1324 .quad .L_ufetch_32_end 1325 .quad ufetchstoreerr 1326 1327 .quad .L_ufetch_64_start 1328 .quad .L_ufetch_64_end 1329 .quad ufetchstoreerr 1330 1331 .quad .L_ustore_8_start 1332 .quad .L_ustore_8_end 1333 .quad ufetchstoreerr 1334 1335 .quad .L_ustore_16_start 1336 .quad .L_ustore_16_end 1337 .quad ufetchstoreerr 1338 1339 .quad .L_ustore_32_start 1340 .quad .L_ustore_32_end 1341 .quad ufetchstoreerr 1342 1343 .quad .L_ustore_64_start 1344 .quad .L_ustore_64_end 1345 .quad ufetchstoreerr 1346 1347 .quad .Lucas_32_start 1348 .quad .Lucas_32_end 1349 .quad ufetchstoreerr 1350 1351 .quad .Lucas_64_start 1352 .quad .Lucas_64_end 1353 .quad ufetchstoreerr 1354 1355 .quad 0 1356 1357 .text 1358 1359/**************************************************************************/ 1360 1361/* 1362 * console 'restart' routine to be placed in HWRPB. 1363 */ 1364LEAF(XentRestart, 1) /* XXX should be NESTED */ 1365 .set noat 1366 lda sp,-(FRAME_SIZE*8)(sp) 1367 stq at_reg,(FRAME_AT*8)(sp) 1368 .set at 1369 stq v0,(FRAME_V0*8)(sp) 1370 stq a0,(FRAME_A0*8)(sp) 1371 stq a1,(FRAME_A1*8)(sp) 1372 stq a2,(FRAME_A2*8)(sp) 1373 stq a3,(FRAME_A3*8)(sp) 1374 stq a4,(FRAME_A4*8)(sp) 1375 stq a5,(FRAME_A5*8)(sp) 1376 stq s0,(FRAME_S0*8)(sp) 1377 stq s1,(FRAME_S1*8)(sp) 1378 stq s2,(FRAME_S2*8)(sp) 1379 stq s3,(FRAME_S3*8)(sp) 1380 stq s4,(FRAME_S4*8)(sp) 1381 stq s5,(FRAME_S5*8)(sp) 1382 stq s6,(FRAME_S6*8)(sp) 1383 stq t0,(FRAME_T0*8)(sp) 1384 stq t1,(FRAME_T1*8)(sp) 1385 stq t2,(FRAME_T2*8)(sp) 1386 stq t3,(FRAME_T3*8)(sp) 1387 stq t4,(FRAME_T4*8)(sp) 1388 stq t5,(FRAME_T5*8)(sp) 1389 stq t6,(FRAME_T6*8)(sp) 1390 stq t7,(FRAME_T7*8)(sp) 1391 stq t8,(FRAME_T8*8)(sp) 1392 stq t9,(FRAME_T9*8)(sp) 1393 stq t10,(FRAME_T10*8)(sp) 1394 stq t11,(FRAME_T11*8)(sp) 1395 stq t12,(FRAME_T12*8)(sp) 1396 stq ra,(FRAME_RA*8)(sp) 1397 1398 br pv,1f 13991: LDGP(pv) 1400 1401 mov sp,a0 1402 CALL(console_restart) 1403 1404 call_pal PAL_halt 1405 END(XentRestart) 1406 1407/**************************************************************************/ 1408 1409/* 1410 * Kernel setjmp and longjmp. Rather minimalist. 1411 * 1412 * longjmp(label_t *a) 1413 * will generate a "return (1)" from the last call to 1414 * setjmp(label_t *a) 1415 * by restoring registers from the stack, 1416 */ 1417 1418 .set noreorder 1419 1420LEAF(setjmp, 1) 1421 LDGP(pv) 1422 1423 stq ra, (0 * 8)(a0) /* return address */ 1424 stq s0, (1 * 8)(a0) /* callee-saved registers */ 1425 stq s1, (2 * 8)(a0) 1426 stq s2, (3 * 8)(a0) 1427 stq s3, (4 * 8)(a0) 1428 stq s4, (5 * 8)(a0) 1429 stq s5, (6 * 8)(a0) 1430 stq s6, (7 * 8)(a0) 1431 stq sp, (8 * 8)(a0) 1432 1433 ldiq t0, 0xbeeffedadeadbabe /* set magic number */ 1434 stq t0, (9 * 8)(a0) 1435 1436 mov zero, v0 /* return zero */ 1437 RET 1438END(setjmp) 1439 1440LEAF(longjmp, 1) 1441 LDGP(pv) 1442 1443 ldiq t0, 0xbeeffedadeadbabe /* check magic number */ 1444 ldq t1, (9 * 8)(a0) 1445 cmpeq t0, t1, t0 1446 beq t0, longjmp_botch /* if bad, punt */ 1447 1448 ldq ra, (0 * 8)(a0) /* return address */ 1449 ldq s0, (1 * 8)(a0) /* callee-saved registers */ 1450 ldq s1, (2 * 8)(a0) 1451 ldq s2, (3 * 8)(a0) 1452 ldq s3, (4 * 8)(a0) 1453 ldq s4, (5 * 8)(a0) 1454 ldq s5, (6 * 8)(a0) 1455 ldq s6, (7 * 8)(a0) 1456 ldq sp, (8 * 8)(a0) 1457 1458 ldiq v0, 1 1459 RET 1460 1461longjmp_botch: 1462 lda a0, longjmp_botchmsg 1463 mov ra, a1 1464 CALL(panic) 1465 call_pal PAL_bugchk 1466 1467 .data 1468longjmp_botchmsg: 1469 .asciz "longjmp botch from %p" 1470 .text 1471END(longjmp) 1472 1473/* 1474 * void sts(int rn, u_int32_t *rval); 1475 * void stt(int rn, u_int64_t *rval); 1476 * void lds(int rn, u_int32_t *rval); 1477 * void ldt(int rn, u_int64_t *rval); 1478 */ 1479 1480.macro make_freg_util name, op 1481 LEAF(alpha_\name, 2) 1482 and a0, 0x1f, a0 1483 s8addq a0, pv, pv 1484 addq pv, 1f - alpha_\name, pv 1485 jmp (pv) 14861: 1487 rn = 0 1488 .rept 32 1489 \op $f0 + rn, 0(a1) 1490 RET 1491 rn = rn + 1 1492 .endr 1493 END(alpha_\name) 1494.endm 1495/* 1496LEAF(alpha_sts, 2) 1497LEAF(alpha_stt, 2) 1498LEAF(alpha_lds, 2) 1499LEAF(alpha_ldt, 2) 1500 */ 1501 make_freg_util sts, sts 1502 make_freg_util stt, stt 1503 make_freg_util lds, lds 1504 make_freg_util ldt, ldt 1505 1506LEAF(alpha_read_fpcr, 0); f30save = 0; rettmp = 8; framesz = 16 1507 lda sp, -framesz(sp) 1508 stt $f30, f30save(sp) 1509 mf_fpcr $f30 1510 stt $f30, rettmp(sp) 1511 ldt $f30, f30save(sp) 1512 ldq v0, rettmp(sp) 1513 lda sp, framesz(sp) 1514 RET 1515END(alpha_read_fpcr) 1516 1517LEAF(alpha_write_fpcr, 1); f30save = 0; fpcrtmp = 8; framesz = 16 1518 lda sp, -framesz(sp) 1519 stq a0, fpcrtmp(sp) 1520 stt $f30, f30save(sp) 1521 ldt $f30, fpcrtmp(sp) 1522 mt_fpcr $f30 1523 ldt $f30, f30save(sp) 1524 lda sp, framesz(sp) 1525 RET 1526END(alpha_write_fpcr) 1527