support.S revision 94377
1/*- 2 * Copyright (c) 1998 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/ia64/ia64/support.S 94377 2002-04-10 19:26:49Z dfr $ 27 */ 28/* 29 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 30 * All rights reserved. 31 * 32 * Author: Chris G. Demetriou 33 * 34 * Permission to use, copy, modify and distribute this software and 35 * its documentation is hereby granted, provided that both the copyright 36 * notice and this permission notice appear in all copies of the 37 * software, derivative works or modified versions, and any portions 38 * thereof, and that both notices appear in supporting documentation. 39 * 40 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 41 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 42 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 43 * 44 * Carnegie Mellon requests users of this software to return to 45 * 46 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 47 * School of Computer Science 48 * Carnegie Mellon University 49 * Pittsburgh PA 15213-3890 50 * 51 * any improvements or extensions that they make and grant Carnegie the 52 * rights to redistribute these changes. 53 */ 54 55#include <machine/asm.h> 56#include <machine/ia64_cpu.h> 57#include <assym.s> 58 59 .text 60 61/* 62 * ia64_change_mode: change mode to/from physical mode 63 * 64 * Arguments: 65 * r14 psr for desired mode 66 * 67 * Modifies: 68 * r15-r19 scratch 69 * ar.bsp tranlated to new mode 70 */ 71ENTRY(ia64_change_mode, 0) 72 73 rsm psr.i | psr.ic 74 mov r19=ar.rsc // save rsc while we change mode 75 tbit.nz p6,p7=r14,17 // physical or virtual ? 76 ;; 77 mov ar.rsc=0 // turn off RSE 78(p6) mov r15=7 // RR base for virtual addresses 79(p7) mov r15=0 // RR base for physical addresses 80 flushrs // no dirty registers please 81 srlz.i 82 ;; 83 mov r16=ar.bsp 84 mov r17=rp 85 mov r18=ar.rnat 86 ;; 87 dep r16=r15,r16,61,3 // new address of ar.bsp 88 dep r17=r15,r17,61,3 // new address of rp 89 dep sp=r15,sp,61,3 // new address of sp 90 ;; 91 mov ar.bspstore=r16 92 mov rp=r17 93 ;; 941: mov r16=ip 95 mov ar.rnat=r18 96 mov cr.ipsr=r14 // psr for new mode 97 ;; 98 add r16=2f-1b,r16 // address to rfi to 99 ;; 100 dep r16=r15,r16,61,3 // new mode address for rfi 101 ;; 102 mov cr.iip=r16 // setup for rfi 103 mov cr.ifs=r0 104 ;; 105 rfi 106 1072: mov ar.rsc=r19 // restore ar.rsc 108 br.ret.sptk.few rp // now in new mode 109 110END(ia64_change_mode) 111 112/* 113 * ia64_physical_mode: change mode to physical mode 114 * 115 * Return: 116 * ret0 psr to restore 117 * 118 * Modifies: 119 * r15-r18 scratch 120 * ar.bsp tranlated to physical mode 121 * psr.i cleared 122 */ 123ENTRY(ia64_physical_mode, 0) 124 125 mov r14=psr 126 mov ret0=psr 127 movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH) 128 movl r16=IA64_PSR_BN 129 ;; 130 andcm r14=r14,r15 // clear various xT bits 131 ;; 132 or r14=r14,r16 // make sure BN=1 133 or ret0=ret0,r16 // make sure BN=1 134 135 br.cond.sptk.many ia64_change_mode 136 137END(ia64_physical_mode) 138 139/* 140 * ia64_call_efi_physical: call an EFI procedure in physical mode 141 * 142 * Arguments: 143 * in0 Address of EFI procedure descriptor 144 * in1-in5 Arguments to EFI procedure 145 * 146 * Return: 147 * ret0-ret3 return values from EFI 148 * 149 */ 150ENTRY(ia64_call_efi_physical, 6) 151 152 .prologue 153 .regstk 6,4,5,0 154 .save ar.pfs,loc0 155 alloc loc0=ar.pfs,6,4,5,0 156 ;; 157 .save rp,loc1 158 mov loc1=rp 159 ;; 160 .body 161 br.call.sptk.many rp=ia64_physical_mode 162 ;; 163 mov loc2=r8 // psr to restore mode 164 mov loc3=gp // save kernel gp 165 ld8 r14=[in0],8 // function address 166 ;; 167 mov out0=in1 168 mov out1=in2 169 mov out2=in3 170 mov out3=in4 171 mov out4=in5 172 ld8 gp=[in0] // function gp value 173 ;; 174 mov b6=r14 175 ;; 176 br.call.sptk.many rp=b6 // call EFI procedure 177 mov gp=loc3 // restore kernel gp 178 ;; 179 mov r14=loc2 // psr to restore mode 180 br.call.sptk.many rp=ia64_change_mode 181 ;; 182 mov rp=loc1 183 mov ar.pfs=loc0 184 ;; 185 br.ret.sptk.many rp 186 187END(ia64_call_efi_physical) 188 189/**************************************************************************/ 190 191/* 192 * fu{byte,word} : fetch a byte (word) from user memory 193 */ 194 195ENTRY(suword, 2) 196 197 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 198 cmp.geu p6,p0=in0,r14 199(p6) br.dpnt.few fusufault 200 201 movl r14=fusufault // set up fault handler. 202 add r15=PC_CURTHREAD,r13 // find curthread 203 ;; 204 ld8 r15=[r15] 205 ;; 206 add r15=TD_PCB,r15 // find pcb 207 ;; 208 ld8 r15=[r15] 209 ;; 210 add r15=PCB_ONFAULT,r15 211 ;; 212 st8 [r15]=r14 213 ;; 214 st8.rel [in0]=in1 // try the store 215 ;; 216 st8 [r15]=r0 // clean up 217 218 mov ret0=r0 219 br.ret.sptk.few rp 220 221END(suword) 222 223ENTRY(suhword, 2) 224 225 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 226 cmp.geu p6,p0=in0,r14 227(p6) br.dpnt.few fusufault 228 229 movl r14=fusufault // set up fault handler. 230 add r15=PC_CURTHREAD,r13 // find curthread 231 ;; 232 ld8 r15=[r15] 233 ;; 234 add r15=TD_PCB,r15 // find pcb 235 ;; 236 ld8 r15=[r15] 237 ;; 238 add r15=PCB_ONFAULT,r15 239 ;; 240 st8 [r15]=r14 241 ;; 242 st4.rel [in0]=in1 // try the store 243 ;; 244 st8 [r15]=r0 // clean up 245 246 mov ret0=r0 247 br.ret.sptk.few rp 248 249END(suhword) 250 251ENTRY(subyte, 2) 252 253 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 254 cmp.geu p6,p0=in0,r14 255(p6) br.dpnt.few fusufault 256 257 movl r14=fusufault // set up fault handler. 258 add r15=PC_CURTHREAD,r13 // find curthread 259 ;; 260 ld8 r15=[r15] 261 ;; 262 add r15=TD_PCB,r15 // find pcb 263 ;; 264 ld8 r15=[r15] 265 ;; 266 add r15=PCB_ONFAULT,r15 267 ;; 268 st8 [r15]=r14 269 ;; 270 st1.rel [in0]=in1 // try the store 271 ;; 272 st8 [r15]=r0 // clean up 273 274 mov ret0=r0 275 br.ret.sptk.few rp 276 277END(subyte) 278 279ENTRY(fuword, 1) 280 281 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 282 cmp.geu p6,p0=in0,r14 283(p6) br.dpnt.few fusufault 284 285 movl r14=fusufault // set up fault handler. 286 add r15=PC_CURTHREAD,r13 // find curthread 287 ;; 288 ld8 r15=[r15] 289 ;; 290 add r15=TD_PCB,r15 // find pcb 291 ;; 292 ld8 r15=[r15] 293 ;; 294 add r15=PCB_ONFAULT,r15 295 ;; 296 st8 [r15]=r14 297 ;; 298 ld8.acq ret0=[in0] // try the fetch 299 ;; 300 st8 [r15]=r0 // clean up 301 302 br.ret.sptk.few rp 303 304END(fuword) 305 306ENTRY(fuhword, 1) 307 308 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 309 cmp.geu p6,p0=in0,r14 310(p6) br.dpnt.few fusufault 311 312 movl r14=fusufault // set up fault handler. 313 add r15=PC_CURTHREAD,r13 // find curthread 314 ;; 315 ld8 r15=[r15] 316 ;; 317 add r15=TD_PCB,r15 // find pcb 318 ;; 319 ld8 r15=[r15] 320 ;; 321 add r15=PCB_ONFAULT,r15 322 ;; 323 st8 [r15]=r14 324 ;; 325 ld4.acq ret0=[in0] // try the fetch 326 ;; 327 st8 [r15]=r0 // clean up 328 329 br.ret.sptk.few rp 330 331END(fuhword) 332 333ENTRY(fubyte, 1) 334 335 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 336 cmp.geu p6,p0=in0,r14 337(p6) br.dpnt.few fusufault 338 339 movl r14=fusufault // set up fault handler. 340 add r15=PC_CURTHREAD,r13 // find curthread 341 ;; 342 ld8 r15=[r15] 343 ;; 344 add r15=TD_PCB,r15 // find pcb 345 ;; 346 ld8 r15=[r15] 347 ;; 348 add r15=PCB_ONFAULT,r15 349 ;; 350 st8 [r15]=r14 351 ;; 352 ld1.acq ret0=[in0] // try the fetch 353 ;; 354 st8 [r15]=r0 // clean up 355 356 br.ret.sptk.few rp 357 358END(fubyte) 359 360ENTRY(suibyte, 2) 361 mov ret0=-1 362 br.ret.sptk.few rp 363END(suibyte) 364 365ENTRY(fusufault, 0) 366 st8 [r15]=r0 ;; // r15 points at onfault 367 mov ret0=r0 368 br.ret.sptk.few rp 369END(fusufault) 370 371ENTRY(fswintrberr, 0) 372XENTRY(fuswintr) /* XXX what is a 'word'? */ 373XENTRY(suswintr) /* XXX what is a 'word'? */ 374 mov ret0=-1 375 br.ret.sptk.few rp 376END(fswintrberr) 377 378/**************************************************************************/ 379 380/* 381 * Copy a null-terminated string within the kernel's address space. 382 * If lenp is not NULL, store the number of chars copied in *lenp 383 * 384 * int copystr(char *from, char *to, size_t len, size_t *lenp); 385 */ 386ENTRY(copystr, 4) 387 mov r14=in2 // r14 = i = len 388 cmp.eq p6,p0=r0,in2 389(p6) br.cond.spnt.few 2f // if (len == 0), bail out 390 3911: ld1 r15=[in0],1 // read one byte 392 ;; 393 st1 [in1]=r15,1 // write that byte 394 add in2=-1,in2 // len-- 395 ;; 396 cmp.eq p6,p0=r0,r15 397 cmp.ne p7,p0=r0,in2 398 ;; 399(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 400(p7) br.cond.sptk.few 1b // if (len != 0) copy more 401 4022: cmp.eq p6,p0=r0,in3 403(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 404 sub r14=r14,in2 // *lenp = (i - len) 405 ;; 406 st8 [in3]=r14 407 4083: cmp.eq p6,p0=r0,r15 409(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 410 411 mov ret0=ENAMETOOLONG // *from != '\0'; error. 412 br.ret.sptk.few rp 413 4144: mov ret0=0 // return 0. 415 br.ret.sptk.few rp 416 417END(copystr) 418 419ENTRY(copyinstr, 4) 420 .prologue 421 .regstk 4, 3, 4, 0 422 .save ar.pfs,loc0 423 alloc loc0=ar.pfs,4,3,4,0 424 .save rp,loc1 425 mov loc1=rp 426 .body 427 428 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 429 ;; 430 cmp.geu p6,p0=in0,loc2 // is in user space. 431 ;; 432(p6) br.cond.spnt.few copyerr // if it's not, error out. 433 movl r14=copyerr // set up fault handler. 434 add r15=PC_CURTHREAD,r13 // find curthread 435 ;; 436 ld8 r15=[r15] 437 ;; 438 add r15=TD_PCB,r15 // find pcb 439 ;; 440 ld8 r15=[r15] 441 ;; 442 add loc2=PCB_ONFAULT,r15 443 ;; 444 st8 [loc2]=r14 445 ;; 446 mov out0=in0 447 mov out1=in1 448 mov out2=in2 449 mov out3=in3 450 ;; 451 br.call.sptk.few rp=copystr // do the copy. 452 st8 [loc2]=r0 // kill the fault handler. 453 mov ar.pfs=loc0 // restore ar.pfs 454 mov rp=loc1 // restore ra. 455 br.ret.sptk.few rp // ret0 left over from copystr 456 457END(copyinstr) 458 459ENTRY(copyoutstr, 4) 460 .prologue 461 .regstk 4, 3, 4, 0 462 .save ar.pfs,loc0 463 alloc loc0=ar.pfs,4,3,4,0 464 .save rp,loc1 465 mov loc1=rp 466 .body 467 468 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 469 ;; 470 cmp.geu p6,p0=in1,loc2 // is in user space. 471 ;; 472(p6) br.cond.spnt.few copyerr // if it's not, error out. 473 movl r14=copyerr // set up fault handler. 474 add r15=PC_CURTHREAD,r13 // find curthread 475 ;; 476 ld8 r15=[r15] 477 ;; 478 add r15=TD_PCB,r15 // find pcb 479 ;; 480 ld8 r15=[r15] 481 ;; 482 add loc2=PCB_ONFAULT,r15 483 ;; 484 st8 [loc2]=r14 485 ;; 486 mov out0=in0 487 mov out1=in1 488 mov out2=in2 489 mov out3=in3 490 ;; 491 br.call.sptk.few rp=copystr // do the copy. 492 st8 [loc2]=r0 // kill the fault handler. 493 mov ar.pfs=loc0 // restore ar.pfs 494 mov rp=loc1 // restore ra. 495 br.ret.sptk.few rp // ret0 left over from copystr 496 497END(copyoutstr) 498 499/* 500 * Not the fastest bcopy in the world. 501 */ 502ENTRY(bcopy, 3) 503XENTRY(ovbcopy) 504 505 mov ret0=r0 // return zero for copy{in,out} 506 ;; 507 cmp.le p6,p0=in2,r0 // bail if len <= 0 508(p6) br.ret.spnt.few rp 509 510 sub r14=in1,in0 ;; // check for overlap 511 cmp.ltu p6,p0=r14,in2 // dst-src < len 512(p6) br.cond.spnt.few 5f 513 514 extr.u r14=in0,0,3 // src & 7 515 extr.u r15=in1,0,3 ;; // dst & 7 516 cmp.eq p6,p0=r14,r15 // different alignment? 517(p6) br.cond.spnt.few 2f // branch if same alignment 518 5191: ld1 r14=[in0],1 ;; // copy bytewise 520 st1 [in1]=r14,1 521 add in2=-1,in2 ;; // len-- 522 cmp.ne p6,p0=r0,in2 523(p6) br.cond.dptk.few 1b // loop 524 br.ret.sptk.few rp // done 525 5262: cmp.eq p6,p0=r14,r0 // aligned? 527(p6) br.cond.sptk.few 4f 528 5293: ld1 r14=[in0],1 ;; // copy bytewise 530 st1 [in1]=r14,1 531 extr.u r15=in0,0,3 // src & 7 532 add in2=-1,in2 ;; // len-- 533 cmp.eq p6,p0=r0,in2 // done? 534 cmp.eq p7,p0=r0,r15 ;; // aligned now? 535(p6) br.ret.spnt.few rp // return if done 536(p7) br.cond.spnt.few 4f // go to main copy 537 br.cond.sptk.few 3b // more bytes to copy 538 539 // At this point, in2 is non-zero 540 5414: mov r14=8 ;; 542 cmp.ltu p6,p0=in2,r14 ;; // len < 8? 543(p6) br.cond.spnt.few 1b // byte copy the end 544 ld8 r15=[in0],8 ;; // copy word 545 st8 [in1]=r15,8 546 add in2=-8,in2 ;; // len -= 8 547 cmp.ne p6,p0=r0,in2 // done? 548(p6) br.cond.spnt.few 4b // again 549 550 br.ret.sptk.few rp // return 551 552 // Don't bother optimising overlap case 553 5545: add in0=in0,in2 555 add in1=in1,in2 ;; 556 add in0=-1,in0 557 add in1=-1,in1 ;; 558 5596: ld1 r14=[in0],-1 ;; 560 st1 [in1]=r14,-1 561 add in2=-1,in2 ;; 562 cmp.ne p6,p0=r0,in2 563(p6) br.cond.spnt.few 6b 564 565 br.ret.sptk.few rp 566 567END(bcopy) 568 569ENTRY(memcpy,3) 570 571 mov r14=in0 ;; 572 mov in0=in1 ;; 573 mov in1=r14 574 br.cond.sptk.few bcopy 575 576END(memcpy) 577 578ENTRY(copyin, 3) 579 580 .prologue 581 .regstk 4, 3, 4, 0 582 .save ar.pfs,loc0 583 alloc loc0=ar.pfs,4,3,4,0 584 .save rp,loc1 585 mov loc1=rp 586 .body 587 588 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 589 ;; 590 cmp.geu p6,p0=in0,loc2 // is in user space. 591 ;; 592(p6) br.cond.spnt.few copyerr // if it's not, error out. 593 movl r14=copyerr // set up fault handler. 594 add r15=PC_CURTHREAD,r13 // find curthread 595 ;; 596 ld8 r15=[r15] 597 ;; 598 add r15=TD_PCB,r15 // find pcb 599 ;; 600 ld8 r15=[r15] 601 ;; 602 add loc2=PCB_ONFAULT,r15 603 ;; 604 st8 [loc2]=r14 605 ;; 606 mov out0=in0 607 mov out1=in1 608 mov out2=in2 609 ;; 610 br.call.sptk.few rp=bcopy // do the copy. 611 st8 [loc2]=r0 // kill the fault handler. 612 mov ar.pfs=loc0 // restore ar.pfs 613 mov rp=loc1 // restore ra. 614 br.ret.sptk.few rp // ret0 left over from bcopy 615 616END(copyin) 617 618ENTRY(copyout, 3) 619 620 .prologue 621 .regstk 4, 3, 4, 0 622 .save ar.pfs,loc0 623 alloc loc0=ar.pfs,4,3,4,0 624 .save rp,loc1 625 mov loc1=rp 626 .body 627 628 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 629 ;; 630 cmp.geu p6,p0=in1,loc2 // is in user space. 631 ;; 632(p6) br.cond.spnt.few copyerr // if it's not, error out. 633 movl r14=copyerr // set up fault handler. 634 add r15=PC_CURTHREAD,r13 // find curthread 635 ;; 636 ld8 r15=[r15] 637 ;; 638 add r15=TD_PCB,r15 // find pcb 639 ;; 640 ld8 r15=[r15] 641 ;; 642 add loc2=PCB_ONFAULT,r15 643 ;; 644 st8 [loc2]=r14 645 ;; 646 mov out0=in0 647 mov out1=in1 648 mov out2=in2 649 ;; 650 br.call.sptk.few rp=bcopy // do the copy. 651 st8 [loc2]=r0 // kill the fault handler. 652 mov ar.pfs=loc0 // restore ar.pfs 653 mov rp=loc1 // restore ra. 654 br.ret.sptk.few rp // ret0 left over from bcopy 655 656END(copyout) 657 658ENTRY(copyerr, 0) 659 660 add r14=PC_CURTHREAD,r13 ;; // find curthread 661 ld8 r14=[r14] ;; 662 add r14=TD_PCB,r14 ;; // curthread->td_addr 663 ld8 r14=[r14] ;; 664 add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault 665 st8 [r14]=r0 // reset fault handler 666 667 mov ret0=EFAULT // return EFAULT 668 br.ret.sptk.few rp 669 670END(copyerr) 671