support.S revision 84114
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 84114 2001-09-29 09:54:42Z 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 alloc loc0=ar.pfs,6,4,5,0 153 ;; 154 mov loc1=rp 155 ;; 156 br.call.sptk.many rp=ia64_physical_mode 157 ;; 158 mov loc2=r8 // psr to restore mode 159 mov loc3=gp // save kernel gp 160 ld8 r14=[in0],8 // function address 161 ;; 162 mov out0=in1 163 mov out1=in2 164 mov out2=in3 165 mov out3=in4 166 mov out4=in5 167 ld8 gp=[in0] // function gp value 168 ;; 169 mov b6=r14 170 ;; 171 br.call.sptk.many rp=b6 // call EFI procedure 172 mov gp=loc3 // restore kernel gp 173 ;; 174 mov r14=loc2 // psr to restore mode 175 br.call.sptk.many rp=ia64_change_mode 176 ;; 177 mov rp=loc1 178 mov ar.pfs=loc0 179 ;; 180 br.ret.sptk.many rp 181 182END(ia64_call_efi_physical) 183 184/**************************************************************************/ 185 186/* 187 * fu{byte,word} : fetch a byte (word) from user memory 188 */ 189 190ENTRY(suword, 2) 191 192 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 193 cmp.geu p6,p0=in0,r14 194(p6) br.dpnt.few fusufault 195 196 movl r14=fusufault // set up fault handler. 197 add r15=GD_CURTHREAD,r13 // find curthread 198 ;; 199 ld8 r15=[r15] 200 ;; 201 add r15=TD_PCB,r15 // find pcb 202 ;; 203 ld8 r15=[r15] 204 ;; 205 add r15=PCB_ONFAULT,r15 206 ;; 207 st8 [r15]=r14 208 ;; 209 st8.rel [in0]=in1 // try the store 210 ;; 211 st8 [r15]=r0 // clean up 212 213 mov ret0=r0 214 br.ret.sptk.few rp 215 216END(suword) 217 218ENTRY(subyte, 2) 219 220 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 221 cmp.geu p6,p0=in0,r14 222(p6) br.dpnt.few fusufault 223 224 movl r14=fusufault // set up fault handler. 225 add r15=GD_CURTHREAD,r13 // find curthread 226 ;; 227 ld8 r15=[r15] 228 ;; 229 add r15=TD_PCB,r15 // find pcb 230 ;; 231 ld8 r15=[r15] 232 ;; 233 add r15=PCB_ONFAULT,r15 234 ;; 235 st8 [r15]=r14 236 ;; 237 st1.rel [in0]=in1 // try the store 238 ;; 239 st8 [r15]=r0 // clean up 240 241 mov ret0=r0 242 br.ret.sptk.few rp 243 244END(subyte) 245 246ENTRY(fuword, 1) 247 248 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 249 cmp.geu p6,p0=in0,r14 250(p6) br.dpnt.few fusufault 251 252 movl r14=fusufault // set up fault handler. 253 add r15=GD_CURTHREAD,r13 // find curthread 254 ;; 255 ld8 r15=[r15] 256 ;; 257 add r15=TD_PCB,r15 // find pcb 258 ;; 259 ld8 r15=[r15] 260 ;; 261 add r15=PCB_ONFAULT,r15 262 ;; 263 st8 [r15]=r14 264 ;; 265 ld8.acq ret0=[in0] // try the fetch 266 ;; 267 st8 [r15]=r0 // clean up 268 269 br.ret.sptk.few rp 270 271END(fuword) 272 273ENTRY(fubyte, 1) 274 275 movl r14=VM_MAXUSER_ADDRESS;; // make sure address is ok 276 cmp.geu p6,p0=in0,r14 277(p6) br.dpnt.few fusufault 278 279 movl r14=fusufault // set up fault handler. 280 add r15=GD_CURTHREAD,r13 // find curthread 281 ;; 282 ld8 r15=[r15] 283 ;; 284 add r15=TD_PCB,r15 // find pcb 285 ;; 286 ld8 r15=[r15] 287 ;; 288 add r15=PCB_ONFAULT,r15 289 ;; 290 st8 [r15]=r14 291 ;; 292 ld1.acq ret0=[in0] // try the fetch 293 ;; 294 st8 [r15]=r0 // clean up 295 296 br.ret.sptk.few rp 297 298END(fubyte) 299 300ENTRY(suibyte, 2) 301 mov ret0=-1 302 br.ret.sptk.few rp 303END(suibyte) 304 305ENTRY(fusufault, 0) 306 st8 [r15]=r0 ;; // r15 points at onfault 307 mov ret0=r0 308 br.ret.sptk.few rp 309END(fusufault) 310 311ENTRY(fswintrberr, 0) 312XENTRY(fuswintr) /* XXX what is a 'word'? */ 313XENTRY(suswintr) /* XXX what is a 'word'? */ 314 mov ret0=-1 315 br.ret.sptk.few rp 316END(fswintrberr) 317 318/**************************************************************************/ 319 320/* 321 * Copy a null-terminated string within the kernel's address space. 322 * If lenp is not NULL, store the number of chars copied in *lenp 323 * 324 * int copystr(char *from, char *to, size_t len, size_t *lenp); 325 */ 326ENTRY(copystr, 4) 327 mov r14=in2 // r14 = i = len 328 cmp.eq p6,p0=r0,in2 329(p6) br.cond.spnt.few 2f // if (len == 0), bail out 330 3311: ld1 r15=[in0],1 // read one byte 332 ;; 333 st1 [in1]=r15,1 // write that byte 334 add in2=-1,in2 // len-- 335 ;; 336 cmp.eq p6,p0=r0,r15 337 cmp.ne p7,p0=r0,in2 338 ;; 339(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 340(p7) br.cond.sptk.few 1b // if (len != 0) copy more 341 3422: cmp.eq p6,p0=r0,in3 343(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 344 sub r14=r14,in2 // *lenp = (i - len) 345 ;; 346 st8 [in3]=r14 347 3483: cmp.eq p6,p0=r0,r15 349(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 350 351 mov ret0=ENAMETOOLONG // *from != '\0'; error. 352 br.ret.sptk.few rp 353 3544: mov ret0=0 // return 0. 355 br.ret.sptk.few rp 356 357END(copystr) 358 359ENTRY(copyinstr, 4) 360 alloc loc0=ar.pfs,4,3,4,0 361 mov loc1=rp 362 363 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 364 ;; 365 cmp.geu p6,p0=in0,loc2 // is in user space. 366 ;; 367(p6) br.cond.spnt.few copyerr // if it's not, error out. 368 movl r14=copyerr // set up fault handler. 369 add r15=GD_CURTHREAD,r13 // find curthread 370 ;; 371 ld8 r15=[r15] 372 ;; 373 add r15=TD_PCB,r15 // find pcb 374 ;; 375 ld8 r15=[r15] 376 ;; 377 add loc2=PCB_ONFAULT,r15 378 ;; 379 st8 [loc2]=r14 380 ;; 381 mov out0=in0 382 mov out1=in1 383 mov out2=in2 384 mov out3=in3 385 ;; 386 br.call.sptk.few rp=copystr // do the copy. 387 st8 [loc2]=r0 // kill the fault handler. 388 mov ar.pfs=loc0 // restore ar.pfs 389 mov rp=loc1 // restore ra. 390 br.ret.sptk.few rp // ret0 left over from copystr 391 392END(copyinstr) 393 394ENTRY(copyoutstr, 4) 395 alloc loc0=ar.pfs,4,3,4,0 396 mov loc1=rp 397 398 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 399 ;; 400 cmp.geu p6,p0=in1,loc2 // is in user space. 401 ;; 402(p6) br.cond.spnt.few copyerr // if it's not, error out. 403 movl r14=copyerr // set up fault handler. 404 add r15=GD_CURTHREAD,r13 // find curthread 405 ;; 406 ld8 r15=[r15] 407 ;; 408 add r15=TD_PCB,r15 // find pcb 409 ;; 410 ld8 r15=[r15] 411 ;; 412 add loc2=PCB_ONFAULT,r15 413 ;; 414 st8 [loc2]=r14 415 ;; 416 mov out0=in0 417 mov out1=in1 418 mov out2=in2 419 mov out3=in3 420 ;; 421 br.call.sptk.few rp=copystr // do the copy. 422 st8 [loc2]=r0 // kill the fault handler. 423 mov ar.pfs=loc0 // restore ar.pfs 424 mov rp=loc1 // restore ra. 425 br.ret.sptk.few rp // ret0 left over from copystr 426 427END(copyoutstr) 428 429/* 430 * Not the fastest bcopy in the world. 431 */ 432ENTRY(bcopy, 3) 433XENTRY(ovbcopy) 434 435 mov ret0=r0 // return zero for copy{in,out} 436 ;; 437 cmp.le p6,p0=in2,r0 // bail if len <= 0 438(p6) br.ret.spnt.few rp 439 440 sub r14=in1,in0 ;; // check for overlap 441 cmp.ltu p6,p0=r14,in2 // dst-src < len 442(p6) br.cond.spnt.few 5f 443 444 extr.u r14=in0,0,3 // src & 7 445 extr.u r15=in1,0,3 ;; // dst & 7 446 cmp.eq p6,p0=r14,r15 // different alignment? 447(p6) br.cond.spnt.few 2f // branch if same alignment 448 4491: ld1 r14=[in0],1 ;; // copy bytewise 450 st1 [in1]=r14,1 451 add in2=-1,in2 ;; // len-- 452 cmp.ne p6,p0=r0,in2 453(p6) br.cond.dptk.few 1b // loop 454 br.ret.sptk.few rp // done 455 4562: cmp.eq p6,p0=r14,r0 // aligned? 457(p6) br.cond.sptk.few 4f 458 4593: ld1 r14=[in0],1 ;; // copy bytewise 460 st1 [in1]=r14,1 461 extr.u r15=in0,0,3 // src & 7 462 add in2=-1,in2 ;; // len-- 463 cmp.eq p6,p0=r0,in2 // done? 464 cmp.eq p7,p0=r0,r15 ;; // aligned now? 465(p6) br.ret.spnt.few rp // return if done 466(p7) br.cond.spnt.few 4f // go to main copy 467 br.cond.sptk.few 3b // more bytes to copy 468 469 // At this point, in2 is non-zero 470 4714: mov r14=8 ;; 472 cmp.ltu p6,p0=in2,r14 ;; // len < 8? 473(p6) br.cond.spnt.few 1b // byte copy the end 474 ld8 r15=[in0],8 ;; // copy word 475 st8 [in1]=r15,8 476 add in2=-8,in2 ;; // len -= 8 477 cmp.ne p6,p0=r0,in2 // done? 478(p6) br.cond.spnt.few 4b // again 479 480 br.ret.sptk.few rp // return 481 482 // Don't bother optimising overlap case 483 4845: add in0=in0,in2 485 add in1=in1,in2 ;; 486 add in0=-1,in0 487 add in1=-1,in1 ;; 488 4896: ld1 r14=[in0],-1 ;; 490 st1 [in1]=r14,-1 491 add in2=-1,in2 ;; 492 cmp.ne p6,p0=r0,in2 493(p6) br.cond.spnt.few 6b 494 495 br.ret.sptk.few rp 496 497END(bcopy) 498 499ENTRY(memcpy,3) 500 501 mov r14=in0 ;; 502 mov in0=in1 ;; 503 mov in1=r14 504 br.cond.sptk.few bcopy 505 506END(memcpy) 507 508ENTRY(copyin, 3) 509 510 alloc loc0=ar.pfs,3,3,3,0 511 mov loc1=rp 512 513 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr 514 ;; 515 cmp.geu p6,p0=in0,loc2 // is in user space. 516 ;; 517(p6) br.cond.spnt.few copyerr // if it's not, error out. 518 movl r14=copyerr // set up fault handler. 519 add r15=GD_CURTHREAD,r13 // find curthread 520 ;; 521 ld8 r15=[r15] 522 ;; 523 add r15=TD_PCB,r15 // find pcb 524 ;; 525 ld8 r15=[r15] 526 ;; 527 add loc2=PCB_ONFAULT,r15 528 ;; 529 st8 [loc2]=r14 530 ;; 531 mov out0=in0 532 mov out1=in1 533 mov out2=in2 534 ;; 535 br.call.sptk.few rp=bcopy // do the copy. 536 st8 [loc2]=r0 // kill the fault handler. 537 mov ar.pfs=loc0 // restore ar.pfs 538 mov rp=loc1 // restore ra. 539 br.ret.sptk.few rp // ret0 left over from bcopy 540 541END(copyin) 542 543ENTRY(copyout, 3) 544 545 alloc loc0=ar.pfs,3,3,3,0 546 mov loc1=rp 547 548 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr 549 ;; 550 cmp.geu p6,p0=in1,loc2 // is in user space. 551 ;; 552(p6) br.cond.spnt.few copyerr // if it's not, error out. 553 movl r14=copyerr // set up fault handler. 554 add r15=GD_CURTHREAD,r13 // find curthread 555 ;; 556 ld8 r15=[r15] 557 ;; 558 add r15=TD_PCB,r15 // find pcb 559 ;; 560 ld8 r15=[r15] 561 ;; 562 add loc2=PCB_ONFAULT,r15 563 ;; 564 st8 [loc2]=r14 565 ;; 566 mov out0=in0 567 mov out1=in1 568 mov out2=in2 569 ;; 570 br.call.sptk.few rp=bcopy // do the copy. 571 st8 [loc2]=r0 // kill the fault handler. 572 mov ar.pfs=loc0 // restore ar.pfs 573 mov rp=loc1 // restore ra. 574 br.ret.sptk.few rp // ret0 left over from bcopy 575 576END(copyout) 577 578ENTRY(copyerr, 0) 579 580 add r14=GD_CURTHREAD,r13 ;; // find curthread 581 ld8 r14=[r14] ;; 582 add r14=TD_PCB,r14 ;; // curthread->td_addr 583 ld8 r14=[r14] ;; 584 add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault 585 st8 [r14]=r0 // reset fault handler 586 587 mov ret0=EFAULT // return EFAULT 588 br.ret.sptk.few rp 589 590END(copyerr) 591