support.S revision 115084
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 115084 2003-05-16 21:26:42Z marcel $ 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 rsm psr.i | psr.ic 73 mov r19=ar.rsc // save rsc while we change mode 74 tbit.nz p6,p7=r14,17 // physical or virtual ? 75 ;; 76 mov ar.rsc=0 // turn off RSE 77(p6) mov r15=7 // RR base for virtual addresses 78(p7) mov r15=0 // RR base for physical addresses 79 flushrs // no dirty registers please 80 srlz.i 81 ;; 82 mov r16=ar.bsp 83 mov r17=rp 84 mov r18=ar.rnat 85 ;; 86 dep r16=r15,r16,61,3 // new address of ar.bsp 87 dep r17=r15,r17,61,3 // new address of rp 88 dep sp=r15,sp,61,3 // new address of sp 89 ;; 90 mov ar.bspstore=r16 91 mov rp=r17 92 ;; 931: mov r16=ip 94 mov ar.rnat=r18 95 mov cr.ipsr=r14 // psr for new mode 96 ;; 97 add r16=2f-1b,r16 // address to rfi to 98 ;; 99 dep r16=r15,r16,61,3 // new mode address for rfi 100 ;; 101 mov cr.iip=r16 // setup for rfi 102 mov cr.ifs=r0 103 ;; 104 rfi 105 1062: mov ar.rsc=r19 // restore ar.rsc 107 br.ret.sptk.few rp // now in new mode 108END(ia64_change_mode) 109 110/* 111 * ia64_physical_mode: change mode to physical mode 112 * 113 * Return: 114 * ret0 psr to restore 115 * 116 * Modifies: 117 * r15-r18 scratch 118 * ar.bsp tranlated to physical mode 119 * psr.i cleared 120 */ 121ENTRY(ia64_physical_mode, 0) 122 mov r14=psr 123 mov ret0=psr 124 movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH) 125 movl r16=IA64_PSR_BN 126 ;; 127 andcm r14=r14,r15 // clear various xT bits 128 ;; 129 or r14=r14,r16 // make sure BN=1 130 or ret0=ret0,r16 // make sure BN=1 131 132 br.cond.sptk.many ia64_change_mode 133END(ia64_physical_mode) 134 135/* 136 * ia64_call_efi_physical: call an EFI procedure in physical mode 137 * 138 * Arguments: 139 * in0 Address of EFI procedure descriptor 140 * in1-in5 Arguments to EFI procedure 141 * 142 * Return: 143 * ret0-ret3 return values from EFI 144 * 145 */ 146ENTRY(ia64_call_efi_physical, 6) 147 .prologue 148 .regstk 6,4,5,0 149 .save ar.pfs,loc0 150 alloc loc0=ar.pfs,6,4,5,0 151 ;; 152 .save rp,loc1 153 mov loc1=rp 154 ;; 155 .body 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 181END(ia64_call_efi_physical) 182 183/**************************************************************************/ 184 185/* 186 * fu{byte,word} : fetch a byte (word) from user memory 187 */ 188 189ENTRY(suword64, 2) 190XENTRY(suword) 191 movl r14=VM_MAX_ADDRESS;; // make sure address is ok 192 cmp.geu p6,p0=in0,r14 193(p6) br.dpnt.few fusufault 194 195 movl r14=fusufault // set up fault handler. 196 add r15=PC_CURTHREAD,r13 // find curthread 197 ;; 198 ld8 r15=[r15] 199 ;; 200 add r15=TD_PCB,r15 // find pcb 201 ;; 202 ld8 r15=[r15] 203 ;; 204 add r15=PCB_ONFAULT,r15 205 ;; 206 st8 [r15]=r14 207 ;; 208 st8.rel [in0]=in1 // try the store 209 ;; 210 st8 [r15]=r0 // clean up 211 212 mov ret0=r0 213 br.ret.sptk.few rp 214END(suword64) 215 216ENTRY(suword32, 2) 217 movl r14=VM_MAX_ADDRESS;; // make sure address is ok 218 cmp.geu p6,p0=in0,r14 219(p6) br.dpnt.few fusufault 220 221 movl r14=fusufault // set up fault handler. 222 add r15=PC_CURTHREAD,r13 // find curthread 223 ;; 224 ld8 r15=[r15] 225 ;; 226 add r15=TD_PCB,r15 // find pcb 227 ;; 228 ld8 r15=[r15] 229 ;; 230 add r15=PCB_ONFAULT,r15 231 ;; 232 st8 [r15]=r14 233 ;; 234 st4.rel [in0]=in1 // try the store 235 ;; 236 st8 [r15]=r0 // clean up 237 238 mov ret0=r0 239 br.ret.sptk.few rp 240END(suword32) 241 242ENTRY(subyte, 2) 243 movl r14=VM_MAX_ADDRESS;; // make sure address is ok 244 cmp.geu p6,p0=in0,r14 245(p6) br.dpnt.few fusufault 246 247 movl r14=fusufault // set up fault handler. 248 add r15=PC_CURTHREAD,r13 // find curthread 249 ;; 250 ld8 r15=[r15] 251 ;; 252 add r15=TD_PCB,r15 // find pcb 253 ;; 254 ld8 r15=[r15] 255 ;; 256 add r15=PCB_ONFAULT,r15 257 ;; 258 st8 [r15]=r14 259 ;; 260 st1.rel [in0]=in1 // try the store 261 ;; 262 st8 [r15]=r0 // clean up 263 264 mov ret0=r0 265 br.ret.sptk.few rp 266END(subyte) 267 268ENTRY(fuword64, 1) 269XENTRY(fuword) 270 movl r14=VM_MAX_ADDRESS;; // make sure address is ok 271 cmp.geu p6,p0=in0,r14 272(p6) br.dpnt.few fusufault 273 274 movl r14=fusufault // set up fault handler. 275 add r15=PC_CURTHREAD,r13 // find curthread 276 ;; 277 ld8 r15=[r15] 278 ;; 279 add r15=TD_PCB,r15 // find pcb 280 ;; 281 ld8 r15=[r15] 282 ;; 283 add r15=PCB_ONFAULT,r15 284 ;; 285 st8 [r15]=r14 286 ;; 287 ld8.acq ret0=[in0] // try the fetch 288 ;; 289 st8 [r15]=r0 // clean up 290 291 br.ret.sptk.few rp 292END(fuword64) 293 294ENTRY(fuword32, 1) 295 movl r14=VM_MAX_ADDRESS;; // make sure address is ok 296 cmp.geu p6,p0=in0,r14 297(p6) br.dpnt.few fusufault 298 299 movl r14=fusufault // set up fault handler. 300 add r15=PC_CURTHREAD,r13 // find curthread 301 ;; 302 ld8 r15=[r15] 303 ;; 304 add r15=TD_PCB,r15 // find pcb 305 ;; 306 ld8 r15=[r15] 307 ;; 308 add r15=PCB_ONFAULT,r15 309 ;; 310 st8 [r15]=r14 311 ;; 312 ld4.acq ret0=[in0] // try the fetch 313 ;; 314 st8 [r15]=r0 // clean up 315 316 br.ret.sptk.few rp 317END(fuword32) 318 319ENTRY(fubyte, 1) 320 movl r14=VM_MAX_ADDRESS;; // make sure address is ok 321 cmp.geu p6,p0=in0,r14 322(p6) br.dpnt.few fusufault 323 324 movl r14=fusufault // set up fault handler. 325 add r15=PC_CURTHREAD,r13 // find curthread 326 ;; 327 ld8 r15=[r15] 328 ;; 329 add r15=TD_PCB,r15 // find pcb 330 ;; 331 ld8 r15=[r15] 332 ;; 333 add r15=PCB_ONFAULT,r15 334 ;; 335 st8 [r15]=r14 336 ;; 337 ld1.acq ret0=[in0] // try the fetch 338 ;; 339 st8 [r15]=r0 // clean up 340 341 br.ret.sptk.few rp 342END(fubyte) 343 344ENTRY(fusufault, 0) 345 st8 [r15]=r0 ;; // r15 points at onfault 346 mov ret0=r0 347 br.ret.sptk.few rp 348END(fusufault) 349 350ENTRY(fswintrberr, 0) 351XENTRY(fuswintr) /* XXX 16 bit short for profiling */ 352XENTRY(suswintr) /* XXX 16 bit short for profiling */ 353 mov ret0=-1 354 br.ret.sptk.few rp 355END(fswintrberr) 356 357/**************************************************************************/ 358 359/* 360 * Copy a null-terminated string within the kernel's address space. 361 * If lenp is not NULL, store the number of chars copied in *lenp 362 * 363 * int copystr(char *from, char *to, size_t len, size_t *lenp); 364 */ 365ENTRY(copystr, 4) 366 mov r14=in2 // r14 = i = len 367 cmp.eq p6,p0=r0,in2 368(p6) br.cond.spnt.few 2f // if (len == 0), bail out 369 3701: ld1 r15=[in0],1 // read one byte 371 ;; 372 st1 [in1]=r15,1 // write that byte 373 add in2=-1,in2 // len-- 374 ;; 375 cmp.eq p6,p0=r0,r15 376 cmp.ne p7,p0=r0,in2 377 ;; 378(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 379(p7) br.cond.sptk.few 1b // if (len != 0) copy more 380 3812: cmp.eq p6,p0=r0,in3 382(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 383 sub r14=r14,in2 // *lenp = (i - len) 384 ;; 385 st8 [in3]=r14 386 3873: cmp.eq p6,p0=r0,r15 388(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 389 390 mov ret0=ENAMETOOLONG // *from != '\0'; error. 391 br.ret.sptk.few rp 392 3934: mov ret0=0 // return 0. 394 br.ret.sptk.few rp 395END(copystr) 396 397ENTRY(copyinstr, 4) 398 .prologue 399 .regstk 4, 3, 4, 0 400 .save ar.pfs,loc0 401 alloc loc0=ar.pfs,4,3,4,0 402 .save rp,loc1 403 mov loc1=rp 404 .body 405 406 movl loc2=VM_MAX_ADDRESS // make sure that src addr 407 ;; 408 cmp.geu p6,p0=in0,loc2 // is in user space. 409 ;; 410(p6) br.cond.spnt.few copyerr // if it's not, error out. 411 movl r14=copyerr // set up fault handler. 412 add r15=PC_CURTHREAD,r13 // find curthread 413 ;; 414 ld8 r15=[r15] 415 ;; 416 add r15=TD_PCB,r15 // find pcb 417 ;; 418 ld8 r15=[r15] 419 ;; 420 add loc2=PCB_ONFAULT,r15 421 ;; 422 st8 [loc2]=r14 423 ;; 424 mov out0=in0 425 mov out1=in1 426 mov out2=in2 427 mov out3=in3 428 ;; 429 br.call.sptk.few rp=copystr // do the copy. 430 st8 [loc2]=r0 // kill the fault handler. 431 mov ar.pfs=loc0 // restore ar.pfs 432 mov rp=loc1 // restore ra. 433 br.ret.sptk.few rp // ret0 left over from copystr 434END(copyinstr) 435 436/* 437 * Not the fastest bcopy in the world. 438 */ 439ENTRY(bcopy, 3) 440 mov ret0=r0 // return zero for copy{in,out} 441 ;; 442 cmp.le p6,p0=in2,r0 // bail if len <= 0 443(p6) br.ret.spnt.few rp 444 445 sub r14=in1,in0 ;; // check for overlap 446 cmp.ltu p6,p0=r14,in2 // dst-src < len 447(p6) br.cond.spnt.few 5f 448 449 extr.u r14=in0,0,3 // src & 7 450 extr.u r15=in1,0,3 ;; // dst & 7 451 cmp.eq p6,p0=r14,r15 // different alignment? 452(p6) br.cond.spnt.few 2f // branch if same alignment 453 4541: ld1 r14=[in0],1 ;; // copy bytewise 455 st1 [in1]=r14,1 456 add in2=-1,in2 ;; // len-- 457 cmp.ne p6,p0=r0,in2 458(p6) br.cond.dptk.few 1b // loop 459 br.ret.sptk.few rp // done 460 4612: cmp.eq p6,p0=r14,r0 // aligned? 462(p6) br.cond.sptk.few 4f 463 4643: ld1 r14=[in0],1 ;; // copy bytewise 465 st1 [in1]=r14,1 466 extr.u r15=in0,0,3 // src & 7 467 add in2=-1,in2 ;; // len-- 468 cmp.eq p6,p0=r0,in2 // done? 469 cmp.eq p7,p0=r0,r15 ;; // aligned now? 470(p6) br.ret.spnt.few rp // return if done 471(p7) br.cond.spnt.few 4f // go to main copy 472 br.cond.sptk.few 3b // more bytes to copy 473 474 // At this point, in2 is non-zero 475 4764: mov r14=8 ;; 477 cmp.ltu p6,p0=in2,r14 ;; // len < 8? 478(p6) br.cond.spnt.few 1b // byte copy the end 479 ld8 r15=[in0],8 ;; // copy word 480 st8 [in1]=r15,8 481 add in2=-8,in2 ;; // len -= 8 482 cmp.ne p6,p0=r0,in2 // done? 483(p6) br.cond.spnt.few 4b // again 484 485 br.ret.sptk.few rp // return 486 487 // Don't bother optimising overlap case 488 4895: add in0=in0,in2 490 add in1=in1,in2 ;; 491 add in0=-1,in0 492 add in1=-1,in1 ;; 493 4946: ld1 r14=[in0],-1 ;; 495 st1 [in1]=r14,-1 496 add in2=-1,in2 ;; 497 cmp.ne p6,p0=r0,in2 498(p6) br.cond.spnt.few 6b 499 500 br.ret.sptk.few rp 501END(bcopy) 502 503ENTRY(memcpy,3) 504 mov r14=in0 ;; 505 mov in0=in1 ;; 506 mov in1=r14 507 br.cond.sptk.few bcopy 508END(memcpy) 509 510ENTRY(copyin, 3) 511 .prologue 512 .regstk 3, 3, 3, 0 513 .save ar.pfs,loc0 514 alloc loc0=ar.pfs,3,3,3,0 515 .save rp,loc1 516 mov loc1=rp 517 .body 518 519 movl loc2=VM_MAX_ADDRESS // make sure that src addr 520 ;; 521 cmp.geu p6,p0=in0,loc2 // is in user space. 522 ;; 523(p6) br.cond.spnt.few copyerr // if it's not, error out. 524 movl r14=copyerr // set up fault handler. 525 add r15=PC_CURTHREAD,r13 // find curthread 526 ;; 527 ld8 r15=[r15] 528 ;; 529 add r15=TD_PCB,r15 // find pcb 530 ;; 531 ld8 r15=[r15] 532 ;; 533 add loc2=PCB_ONFAULT,r15 534 ;; 535 st8 [loc2]=r14 536 ;; 537 mov out0=in0 538 mov out1=in1 539 mov out2=in2 540 ;; 541 br.call.sptk.few rp=bcopy // do the copy. 542 st8 [loc2]=r0 // kill the fault handler. 543 mov ar.pfs=loc0 // restore ar.pfs 544 mov rp=loc1 // restore ra. 545 br.ret.sptk.few rp // ret0 left over from bcopy 546END(copyin) 547 548ENTRY(copyout, 3) 549 .prologue 550 .regstk 3, 3, 3, 0 551 .save ar.pfs,loc0 552 alloc loc0=ar.pfs,3,3,3,0 553 .save rp,loc1 554 mov loc1=rp 555 .body 556 557 movl loc2=VM_MAX_ADDRESS // make sure that dest addr 558 ;; 559 cmp.geu p6,p0=in1,loc2 // is in user space. 560 ;; 561(p6) br.cond.spnt.few copyerr // if it's not, error out. 562 movl r14=copyerr // set up fault handler. 563 add r15=PC_CURTHREAD,r13 // find curthread 564 ;; 565 ld8 r15=[r15] 566 ;; 567 add r15=TD_PCB,r15 // find pcb 568 ;; 569 ld8 r15=[r15] 570 ;; 571 add loc2=PCB_ONFAULT,r15 572 ;; 573 st8 [loc2]=r14 574 ;; 575 mov out0=in0 576 mov out1=in1 577 mov out2=in2 578 ;; 579 br.call.sptk.few rp=bcopy // do the copy. 580 st8 [loc2]=r0 // kill the fault handler. 581 mov ar.pfs=loc0 // restore ar.pfs 582 mov rp=loc1 // restore ra. 583 br.ret.sptk.few rp // ret0 left over from bcopy 584END(copyout) 585 586ENTRY(copyerr, 0) 587 add r14=PC_CURTHREAD,r13 ;; // find curthread 588 ld8 r14=[r14] ;; 589 add r14=TD_PCB,r14 ;; // curthread->td_addr 590 ld8 r14=[r14] ;; 591 add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault 592 st8 [r14]=r0 // reset fault handler 593 594 mov ret0=EFAULT // return EFAULT 595 br.ret.sptk.few rp 596END(copyerr) 597