support.S revision 121410
166458Sdfr/*- 266458Sdfr * Copyright (c) 1998 Doug Rabson 366458Sdfr * All rights reserved. 466458Sdfr * 566458Sdfr * Redistribution and use in source and binary forms, with or without 666458Sdfr * modification, are permitted provided that the following conditions 766458Sdfr * are met: 866458Sdfr * 1. Redistributions of source code must retain the above copyright 966458Sdfr * notice, this list of conditions and the following disclaimer. 1066458Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1166458Sdfr * notice, this list of conditions and the following disclaimer in the 1266458Sdfr * documentation and/or other materials provided with the distribution. 1366458Sdfr * 1466458Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1566458Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1666458Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1766458Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1866458Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1966458Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2066458Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2166458Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2266458Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2366458Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2466458Sdfr * SUCH DAMAGE. 2566458Sdfr * 2666458Sdfr * $FreeBSD: head/sys/ia64/ia64/support.S 121410 2003-10-23 06:19:06Z marcel $ 2766458Sdfr */ 2866458Sdfr/* 2966458Sdfr * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 3066458Sdfr * All rights reserved. 3166458Sdfr * 3266458Sdfr * Author: Chris G. Demetriou 3366458Sdfr * 3466458Sdfr * Permission to use, copy, modify and distribute this software and 3566458Sdfr * its documentation is hereby granted, provided that both the copyright 3666458Sdfr * notice and this permission notice appear in all copies of the 3766458Sdfr * software, derivative works or modified versions, and any portions 3866458Sdfr * thereof, and that both notices appear in supporting documentation. 3966458Sdfr * 4066458Sdfr * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 4166458Sdfr * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 4266458Sdfr * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 4366458Sdfr * 4466458Sdfr * Carnegie Mellon requests users of this software to return to 4566458Sdfr * 4666458Sdfr * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 4766458Sdfr * School of Computer Science 4866458Sdfr * Carnegie Mellon University 4966458Sdfr * Pittsburgh PA 15213-3890 5066458Sdfr * 5166458Sdfr * any improvements or extensions that they make and grant Carnegie the 5266458Sdfr * rights to redistribute these changes. 5366458Sdfr */ 5466458Sdfr 5566458Sdfr#include <machine/asm.h> 5683893Sdfr#include <machine/ia64_cpu.h> 5766458Sdfr#include <assym.s> 5866458Sdfr 5966458Sdfr .text 6066458Sdfr 6183893Sdfr/* 6283893Sdfr * ia64_change_mode: change mode to/from physical mode 6383893Sdfr * 6483893Sdfr * Arguments: 6583893Sdfr * r14 psr for desired mode 6684114Sdfr * 6784114Sdfr * Modifies: 6884114Sdfr * r15-r19 scratch 6984114Sdfr * ar.bsp tranlated to new mode 7083893Sdfr */ 7183893SdfrENTRY(ia64_change_mode, 0) 7283893Sdfr rsm psr.i | psr.ic 7384114Sdfr mov r19=ar.rsc // save rsc while we change mode 7483893Sdfr tbit.nz p6,p7=r14,17 // physical or virtual ? 7583893Sdfr ;; 7684114Sdfr mov ar.rsc=0 // turn off RSE 7783893Sdfr(p6) mov r15=7 // RR base for virtual addresses 7883893Sdfr(p7) mov r15=0 // RR base for physical addresses 7983893Sdfr flushrs // no dirty registers please 8083893Sdfr srlz.i 8183893Sdfr ;; 8283893Sdfr mov r16=ar.bsp 8383893Sdfr mov r17=rp 8483893Sdfr mov r18=ar.rnat 8583893Sdfr ;; 8683893Sdfr dep r16=r15,r16,61,3 // new address of ar.bsp 8783893Sdfr dep r17=r15,r17,61,3 // new address of rp 8884114Sdfr dep sp=r15,sp,61,3 // new address of sp 8983893Sdfr ;; 9083893Sdfr mov ar.bspstore=r16 9183893Sdfr mov rp=r17 9283893Sdfr ;; 9383893Sdfr1: mov r16=ip 9483893Sdfr mov ar.rnat=r18 9583895Sdfr mov cr.ipsr=r14 // psr for new mode 9683893Sdfr ;; 9783893Sdfr add r16=2f-1b,r16 // address to rfi to 9883893Sdfr ;; 9983895Sdfr dep r16=r15,r16,61,3 // new mode address for rfi 10083893Sdfr ;; 10183893Sdfr mov cr.iip=r16 // setup for rfi 10283893Sdfr mov cr.ifs=r0 10383893Sdfr ;; 10483893Sdfr rfi 10583893Sdfr 10684114Sdfr2: mov ar.rsc=r19 // restore ar.rsc 10784114Sdfr br.ret.sptk.few rp // now in new mode 10883893SdfrEND(ia64_change_mode) 10983893Sdfr 11083893Sdfr/* 11183893Sdfr * ia64_physical_mode: change mode to physical mode 11283893Sdfr * 11383893Sdfr * Return: 11483893Sdfr * ret0 psr to restore 11584114Sdfr * 11684114Sdfr * Modifies: 11784114Sdfr * r15-r18 scratch 11884114Sdfr * ar.bsp tranlated to physical mode 11984114Sdfr * psr.i cleared 12083893Sdfr */ 12183893SdfrENTRY(ia64_physical_mode, 0) 12283893Sdfr mov r14=psr 12383893Sdfr mov ret0=psr 12484114Sdfr movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH) 12583893Sdfr movl r16=IA64_PSR_BN 12683893Sdfr ;; 12783893Sdfr andcm r14=r14,r15 // clear various xT bits 12883893Sdfr ;; 12983893Sdfr or r14=r14,r16 // make sure BN=1 13083893Sdfr or ret0=ret0,r16 // make sure BN=1 13183893Sdfr 13283893Sdfr br.cond.sptk.many ia64_change_mode 13383893SdfrEND(ia64_physical_mode) 13483893Sdfr 13584114Sdfr/* 13684114Sdfr * ia64_call_efi_physical: call an EFI procedure in physical mode 13784114Sdfr * 13884114Sdfr * Arguments: 13984114Sdfr * in0 Address of EFI procedure descriptor 14084114Sdfr * in1-in5 Arguments to EFI procedure 14184114Sdfr * 14284114Sdfr * Return: 14384114Sdfr * ret0-ret3 return values from EFI 14484114Sdfr * 14584114Sdfr */ 14684114SdfrENTRY(ia64_call_efi_physical, 6) 14785682Sdfr .prologue 14885682Sdfr .regstk 6,4,5,0 14985682Sdfr .save ar.pfs,loc0 15084114Sdfr alloc loc0=ar.pfs,6,4,5,0 15184114Sdfr ;; 15285682Sdfr .save rp,loc1 15384114Sdfr mov loc1=rp 15484114Sdfr ;; 15585682Sdfr .body 15684114Sdfr br.call.sptk.many rp=ia64_physical_mode 15784114Sdfr ;; 15884114Sdfr mov loc2=r8 // psr to restore mode 15984114Sdfr mov loc3=gp // save kernel gp 16084114Sdfr ld8 r14=[in0],8 // function address 16184114Sdfr ;; 16284114Sdfr mov out0=in1 16384114Sdfr mov out1=in2 16484114Sdfr mov out2=in3 16584114Sdfr mov out3=in4 16684114Sdfr mov out4=in5 16784114Sdfr ld8 gp=[in0] // function gp value 16884114Sdfr ;; 16984114Sdfr mov b6=r14 17084114Sdfr ;; 17184114Sdfr br.call.sptk.many rp=b6 // call EFI procedure 17284114Sdfr mov gp=loc3 // restore kernel gp 17384114Sdfr ;; 17484114Sdfr mov r14=loc2 // psr to restore mode 17584114Sdfr br.call.sptk.many rp=ia64_change_mode 17684114Sdfr ;; 17784114Sdfr mov rp=loc1 17884114Sdfr mov ar.pfs=loc0 17984114Sdfr ;; 18084114Sdfr br.ret.sptk.many rp 18184114SdfrEND(ia64_call_efi_physical) 18284114Sdfr 18366458Sdfr/**************************************************************************/ 184115341Smarcel 185115341SmarcelENTRY(fusufault, 0) 186115341Smarcel{ .mib 187115341Smarcel st8.rel [r15]=r0 // Clear onfault. 188115341Smarcel add ret0=-1,r0 189115341Smarcel br.ret.sptk rp 190115341Smarcel ;; 191115341Smarcel} 192115341SmarcelEND(fusufault) 193115341Smarcel 19466458Sdfr/* 195115341Smarcel * casuptr(intptr_t *p, intptr_t old, intptr_t new) 196115341Smarcel * Perform a compare-exchange in user space. 19766458Sdfr */ 198115341SmarcelENTRY(casuptr, 3) 199115341Smarcel{ .mlx 200115341Smarcel add r15=PC_CURTHREAD,r13 201115341Smarcel movl r14=VM_MAX_ADDRESS 202115341Smarcel ;; 203115341Smarcel} 204115341Smarcel{ .mib 205115341Smarcel ld8 r15=[r15] // r15 = curthread 206115341Smarcel cmp.geu p6,p0=in0,r14 207115341Smarcel(p6) br.dpnt.few 1f 208115341Smarcel ;; 209115341Smarcel} 210115341Smarcel{ .mlx 211115341Smarcel add r15=TD_PCB,r15 212115341Smarcel movl r14=fusufault 213115341Smarcel ;; 214115341Smarcel} 215115341Smarcel{ .mmi 216115341Smarcel ld8 r15=[r15] // r15 = PCB 217115341Smarcel ;; 218115341Smarcel mov ar.ccv=in1 219115341Smarcel add r15=PCB_ONFAULT,r15 220115341Smarcel ;; 221115341Smarcel} 222115341Smarcel{ .mmi 223115341Smarcel st8 [r15]=r14 // Set onfault 224115341Smarcel ;; 225115341Smarcel cmpxchg8.rel ret0=[in0],in2,ar.ccv 226115341Smarcel nop 0 227115341Smarcel ;; 228115341Smarcel} 229115341Smarcel{ .mfb 230115341Smarcel st8.rel [r15]=r0 // Clear onfault 231115341Smarcel nop 0 232115341Smarcel br.ret.sptk rp 233115341Smarcel ;; 234115341Smarcel} 235115341Smarcel1: 236115341Smarcel{ .mfb 237115341Smarcel add ret0=-1,r0 238115341Smarcel nop 0 239115341Smarcel br.ret.sptk rp 240115341Smarcel ;; 241115341Smarcel} 242115341SmarcelEND(casuptr) 24366458Sdfr 244115341Smarcel/* 245115341Smarcel * subyte(void *addr, int byte) 246115341Smarcel * suword16(void *addr, int word) 247115341Smarcel * suword32(void *addr, int word) 248115341Smarcel * suword64|suword(void *addr, long word) 249115341Smarcel * Store in user space 250115341Smarcel */ 251115341Smarcel 252115341SmarcelENTRY(subyte, 2) 253115341Smarcel{ .mlx 254115341Smarcel add r15=PC_CURTHREAD,r13 255115341Smarcel movl r14=VM_MAX_ADDRESS 25666633Sdfr ;; 257115341Smarcel} 258115341Smarcel{ .mib 259115341Smarcel ld8 r15=[r15] // r15 = curthread 260115341Smarcel cmp.geu p6,p0=in0,r14 261115341Smarcel(p6) br.dpnt.few 1f 26266633Sdfr ;; 263115341Smarcel} 264115341Smarcel{ .mlx 265115341Smarcel add r15=TD_PCB,r15 266115341Smarcel movl r14=fusufault 26766633Sdfr ;; 268115341Smarcel} 269115341Smarcel{ .mmi 270115341Smarcel ld8 r15=[r15] // r15 = PCB 27166633Sdfr ;; 272115341Smarcel nop 0 273115341Smarcel add r15=PCB_ONFAULT,r15 27466633Sdfr ;; 275115341Smarcel} 276115341Smarcel{ .mmi 277115341Smarcel st8 [r15]=r14 // Set onfault 27866633Sdfr ;; 279115341Smarcel st1.rel [in0]=in1 280115341Smarcel nop 0 28166633Sdfr ;; 282115341Smarcel} 283115341Smarcel{ .mib 284115341Smarcel st8.rel [r15]=r0 // Clear onfault 285115341Smarcel mov ret0=r0 286115341Smarcel br.ret.sptk rp 287115341Smarcel ;; 288115341Smarcel} 289115341Smarcel1: 290115341Smarcel{ .mfb 291115341Smarcel add ret0=-1,r0 292115341Smarcel nop 0 293115341Smarcel br.ret.sptk rp 294115341Smarcel ;; 295115341Smarcel} 296115341SmarcelEND(subyte) 29766458Sdfr 298115341SmarcelENTRY(suword16, 2) 299115341Smarcel{ .mlx 300115341Smarcel add r15=PC_CURTHREAD,r13 301115341Smarcel movl r14=VM_MAX_ADDRESS 302115341Smarcel ;; 303115341Smarcel} 304115341Smarcel{ .mib 305115341Smarcel ld8 r15=[r15] // r15 = curthread 306115341Smarcel cmp.geu p6,p0=in0,r14 307115341Smarcel(p6) br.dpnt.few 1f 308115341Smarcel ;; 309115341Smarcel} 310115341Smarcel{ .mlx 311115341Smarcel add r15=TD_PCB,r15 312115341Smarcel movl r14=fusufault 313115341Smarcel ;; 314115341Smarcel} 315115341Smarcel{ .mmi 316115341Smarcel ld8 r15=[r15] // r15 = PCB 317115341Smarcel ;; 318115341Smarcel nop 0 319115341Smarcel add r15=PCB_ONFAULT,r15 320115341Smarcel ;; 321115341Smarcel} 322115341Smarcel{ .mmi 323115341Smarcel st8 [r15]=r14 // Set onfault 324115341Smarcel ;; 325115341Smarcel st2.rel [in0]=in1 326115341Smarcel nop 0 327115341Smarcel ;; 328115341Smarcel} 329115341Smarcel{ .mib 330115341Smarcel st8.rel [r15]=r0 // Clear onfault 331115341Smarcel mov ret0=r0 332115341Smarcel br.ret.sptk rp 333115341Smarcel ;; 334115341Smarcel} 335115341Smarcel1: 336115341Smarcel{ .mfb 337115341Smarcel add ret0=-1,r0 338115341Smarcel nop 0 339115341Smarcel br.ret.sptk rp 340115341Smarcel ;; 341115341Smarcel} 342115341SmarcelEND(suword16) 343115341Smarcel 34498473SpeterENTRY(suword32, 2) 345115341Smarcel{ .mlx 346115341Smarcel add r15=PC_CURTHREAD,r13 347115341Smarcel movl r14=VM_MAX_ADDRESS 34894377Sdfr ;; 349115341Smarcel} 350115341Smarcel{ .mib 351115341Smarcel ld8 r15=[r15] // r15 = curthread 352115341Smarcel cmp.geu p6,p0=in0,r14 353115341Smarcel(p6) br.dpnt.few 1f 35494377Sdfr ;; 355115341Smarcel} 356115341Smarcel{ .mlx 357115341Smarcel add r15=TD_PCB,r15 358115341Smarcel movl r14=fusufault 35994377Sdfr ;; 360115341Smarcel} 361115341Smarcel{ .mmi 362115341Smarcel ld8 r15=[r15] // r15 = PCB 36394377Sdfr ;; 364115341Smarcel nop 0 365115341Smarcel add r15=PCB_ONFAULT,r15 36694377Sdfr ;; 367115341Smarcel} 368115341Smarcel{ .mmi 369115341Smarcel st8 [r15]=r14 // Set onfault 37094377Sdfr ;; 371115341Smarcel st4.rel [in0]=in1 372115341Smarcel nop 0 37394377Sdfr ;; 374115341Smarcel} 375115341Smarcel{ .mib 376115341Smarcel st8.rel [r15]=r0 // Clear onfault 377115341Smarcel mov ret0=r0 378115341Smarcel br.ret.sptk rp 379115341Smarcel ;; 380115341Smarcel} 381115341Smarcel1: 382115341Smarcel{ .mfb 383115341Smarcel add ret0=-1,r0 384115341Smarcel nop 0 385115341Smarcel br.ret.sptk rp 386115341Smarcel ;; 387115341Smarcel} 38898473SpeterEND(suword32) 38966458Sdfr 390115341SmarcelENTRY(suword64, 2) 391115341SmarcelXENTRY(suword) 392115341Smarcel{ .mlx 393115341Smarcel add r15=PC_CURTHREAD,r13 394115341Smarcel movl r14=VM_MAX_ADDRESS 39566633Sdfr ;; 396115341Smarcel} 397115341Smarcel{ .mib 398115341Smarcel ld8 r15=[r15] // r15 = curthread 399115341Smarcel cmp.geu p6,p0=in0,r14 400115341Smarcel(p6) br.dpnt.few 1f 40166633Sdfr ;; 402115341Smarcel} 403115341Smarcel{ .mlx 404115341Smarcel add r15=TD_PCB,r15 405115341Smarcel movl r14=fusufault 40666633Sdfr ;; 407115341Smarcel} 408115341Smarcel{ .mmi 409115341Smarcel ld8 r15=[r15] // r15 = PCB 41066633Sdfr ;; 411115341Smarcel nop 0 412115341Smarcel add r15=PCB_ONFAULT,r15 41366633Sdfr ;; 414115341Smarcel} 415115341Smarcel{ .mmi 416115341Smarcel st8 [r15]=r14 // Set onfault 41766633Sdfr ;; 418115341Smarcel st8.rel [in0]=in1 419115341Smarcel nop 0 42066633Sdfr ;; 421115341Smarcel} 422115341Smarcel{ .mib 423115341Smarcel st8.rel [r15]=r0 // Clear onfault 424115341Smarcel mov ret0=r0 425115341Smarcel br.ret.sptk rp 426115341Smarcel ;; 427115341Smarcel} 428115341Smarcel1: 429115341Smarcel{ .mfb 430115341Smarcel add ret0=-1,r0 431115341Smarcel nop 0 432115341Smarcel br.ret.sptk rp 433115341Smarcel ;; 434115341Smarcel} 435115341SmarcelEND(suword64) 43666458Sdfr 437115341Smarcel/* 438115341Smarcel * fubyte(void *addr, int byte) 439115341Smarcel * fuword16(void *addr, int word) 440115341Smarcel * fuword32(void *addr, int word) 441115341Smarcel * fuword64|fuword(void *addr, long word) 442115341Smarcel * Fetch from user space 443115341Smarcel */ 44466458Sdfr 445115341SmarcelENTRY(fubyte, 1) 446115341Smarcel{ .mlx 447115341Smarcel add r15=PC_CURTHREAD,r13 448115341Smarcel movl r14=VM_MAX_ADDRESS 449115341Smarcel ;; 450115341Smarcel} 451115341Smarcel{ .mib 452115341Smarcel ld8 r15=[r15] // r15 = curthread 453115341Smarcel cmp.geu p6,p0=in0,r14 454115341Smarcel(p6) br.dpnt.few 1f 455115341Smarcel ;; 456115341Smarcel} 457115341Smarcel{ .mlx 458115341Smarcel add r15=TD_PCB,r15 459115341Smarcel movl r14=fusufault 460115341Smarcel ;; 461115341Smarcel} 462115341Smarcel{ .mmi 463115341Smarcel ld8 r15=[r15] // r15 = PCB 464115341Smarcel ;; 465115341Smarcel nop 0 466115341Smarcel add r15=PCB_ONFAULT,r15 467115341Smarcel ;; 468115341Smarcel} 469115341Smarcel{ .mmi 470115341Smarcel st8 [r15]=r14 // Set onfault 471115341Smarcel ;; 472115341Smarcel mf 473115341Smarcel nop 0 474115341Smarcel ;; 475115341Smarcel} 476115341Smarcel{ .mmb 477115341Smarcel ld1 ret0=[in0] 478115341Smarcel st8.rel [r15]=r0 // Clear onfault 479115341Smarcel br.ret.sptk rp 480115341Smarcel ;; 481115341Smarcel} 482115341Smarcel1: 483115341Smarcel{ .mfb 484115341Smarcel add ret0=-1,r0 485115341Smarcel nop 0 486115341Smarcel br.ret.sptk rp 487115341Smarcel ;; 488115341Smarcel} 489115341SmarcelEND(fubyte) 49066458Sdfr 491115341SmarcelENTRY(fuword16, 2) 492115341Smarcel{ .mlx 493115341Smarcel add r15=PC_CURTHREAD,r13 494115341Smarcel movl r14=VM_MAX_ADDRESS 49566633Sdfr ;; 496115341Smarcel} 497115341Smarcel{ .mib 498115341Smarcel ld8 r15=[r15] // r15 = curthread 499115341Smarcel cmp.geu p6,p0=in0,r14 500115341Smarcel(p6) br.dpnt.few 1f 50166633Sdfr ;; 502115341Smarcel} 503115341Smarcel{ .mlx 504115341Smarcel add r15=TD_PCB,r15 505115341Smarcel movl r14=fusufault 50666633Sdfr ;; 507115341Smarcel} 508115341Smarcel{ .mmi 509115341Smarcel ld8 r15=[r15] // r15 = PCB 51066633Sdfr ;; 511115341Smarcel nop 0 512115341Smarcel add r15=PCB_ONFAULT,r15 51366633Sdfr ;; 514115341Smarcel} 515115341Smarcel{ .mmi 516115341Smarcel st8 [r15]=r14 // Set onfault 51766633Sdfr ;; 518115341Smarcel mf 519115341Smarcel nop 0 52066633Sdfr ;; 521115341Smarcel} 522115341Smarcel{ .mmb 523115341Smarcel ld2 ret0=[in0] 524115341Smarcel st8.rel [r15]=r0 // Clear onfault 525115341Smarcel br.ret.sptk rp 526115341Smarcel ;; 527115341Smarcel} 528115341Smarcel1: 529115341Smarcel{ .mfb 530115341Smarcel add ret0=-1,r0 531115341Smarcel nop 0 532115341Smarcel br.ret.sptk rp 533115341Smarcel ;; 534115341Smarcel} 535115341SmarcelEND(fuword16) 53666458Sdfr 537115341SmarcelENTRY(fuword32, 2) 538115341Smarcel{ .mlx 539115341Smarcel add r15=PC_CURTHREAD,r13 540115341Smarcel movl r14=VM_MAX_ADDRESS 54194377Sdfr ;; 542115341Smarcel} 543115341Smarcel{ .mib 544115341Smarcel ld8 r15=[r15] // r15 = curthread 545115341Smarcel cmp.geu p6,p0=in0,r14 546115341Smarcel(p6) br.dpnt.few 1f 54794377Sdfr ;; 548115341Smarcel} 549115341Smarcel{ .mlx 550115341Smarcel add r15=TD_PCB,r15 551115341Smarcel movl r14=fusufault 55294377Sdfr ;; 553115341Smarcel} 554115341Smarcel{ .mmi 555115341Smarcel ld8 r15=[r15] // r15 = PCB 55694377Sdfr ;; 557115341Smarcel nop 0 558115341Smarcel add r15=PCB_ONFAULT,r15 55994377Sdfr ;; 560115341Smarcel} 561115341Smarcel{ .mmi 562115341Smarcel st8 [r15]=r14 // Set onfault 56394377Sdfr ;; 564115341Smarcel mf 565115341Smarcel nop 0 56694377Sdfr ;; 567115341Smarcel} 568115341Smarcel{ .mmb 569115341Smarcel ld4 ret0=[in0] 570115341Smarcel st8.rel [r15]=r0 // Clear onfault 571115341Smarcel br.ret.sptk rp 572115341Smarcel ;; 573115341Smarcel} 574115341Smarcel1: 575115341Smarcel{ .mfb 576115341Smarcel add ret0=-1,r0 577115341Smarcel nop 0 578115341Smarcel br.ret.sptk rp 579115341Smarcel ;; 580115341Smarcel} 58198473SpeterEND(fuword32) 58294377Sdfr 583115341SmarcelENTRY(fuword64, 2) 584115341SmarcelXENTRY(fuword) 585115341Smarcel{ .mlx 586115341Smarcel add r15=PC_CURTHREAD,r13 587115341Smarcel movl r14=VM_MAX_ADDRESS 58866633Sdfr ;; 589115341Smarcel} 590115341Smarcel{ .mib 591115341Smarcel ld8 r15=[r15] // r15 = curthread 592115341Smarcel cmp.geu p6,p0=in0,r14 593115341Smarcel(p6) br.dpnt.few 1f 59466633Sdfr ;; 595115341Smarcel} 596115341Smarcel{ .mlx 597115341Smarcel add r15=TD_PCB,r15 598115341Smarcel movl r14=fusufault 59966633Sdfr ;; 600115341Smarcel} 601115341Smarcel{ .mmi 602115341Smarcel ld8 r15=[r15] // r15 = PCB 60366633Sdfr ;; 604115341Smarcel nop 0 605115341Smarcel add r15=PCB_ONFAULT,r15 60666633Sdfr ;; 607115341Smarcel} 608115341Smarcel{ .mmi 609115341Smarcel st8 [r15]=r14 // Set onfault 61066633Sdfr ;; 611115341Smarcel mf 612115341Smarcel nop 0 61366633Sdfr ;; 614115341Smarcel} 615115341Smarcel{ .mmb 616115341Smarcel ld8 ret0=[in0] 617115341Smarcel st8.rel [r15]=r0 // Clear onfault 618115341Smarcel br.ret.sptk rp 619115341Smarcel ;; 620115341Smarcel} 621115341Smarcel1: 622115341Smarcel{ .mfb 623115341Smarcel add ret0=-1,r0 624115341Smarcel nop 0 625115341Smarcel br.ret.sptk rp 626115341Smarcel ;; 627115341Smarcel} 628115341SmarcelEND(fuword64) 62966458Sdfr 630115341Smarcel/* 631115341Smarcel * fuswintr(void *addr) 632115341Smarcel * suswintr(void *addr) 633115341Smarcel */ 634115341Smarcel 635115341SmarcelENTRY(fuswintr, 1) 636115341Smarcel{ .mfb 637115341Smarcel add ret0=-1,r0 638115341Smarcel nop 0 639115341Smarcel br.ret.sptk rp 640115341Smarcel ;; 641115341Smarcel} 642115341SmarcelEND(fuswintr) 643115341Smarcel 644115341SmarcelENTRY(suswintr, 0) 645115341Smarcel{ .mfb 646115341Smarcel add ret0=-1,r0 647115341Smarcel nop 0 648115341Smarcel br.ret.sptk rp 649115341Smarcel ;; 650115341Smarcel} 651115341SmarcelEND(suswintr) 652115341Smarcel 65366458Sdfr/**************************************************************************/ 65466458Sdfr 65566458Sdfr/* 65666458Sdfr * Copy a null-terminated string within the kernel's address space. 65766458Sdfr * If lenp is not NULL, store the number of chars copied in *lenp 65866458Sdfr * 65966458Sdfr * int copystr(char *from, char *to, size_t len, size_t *lenp); 66066458Sdfr */ 66166633SdfrENTRY(copystr, 4) 66266486Sdfr mov r14=in2 // r14 = i = len 66366486Sdfr cmp.eq p6,p0=r0,in2 66466486Sdfr(p6) br.cond.spnt.few 2f // if (len == 0), bail out 66566458Sdfr 66666486Sdfr1: ld1 r15=[in0],1 // read one byte 66766486Sdfr ;; 66866486Sdfr st1 [in1]=r15,1 // write that byte 66966486Sdfr add in2=-1,in2 // len-- 67066486Sdfr ;; 67166486Sdfr cmp.eq p6,p0=r0,r15 67266486Sdfr cmp.ne p7,p0=r0,in2 67366486Sdfr ;; 67466486Sdfr(p6) br.cond.spnt.few 2f // if (*from == 0), bail out 67566486Sdfr(p7) br.cond.sptk.few 1b // if (len != 0) copy more 67666458Sdfr 67766486Sdfr2: cmp.eq p6,p0=r0,in3 67866486Sdfr(p6) br.cond.dpnt.few 3f // if (lenp != NULL) 67967020Sdfr sub r14=r14,in2 // *lenp = (i - len) 68066486Sdfr ;; 68166486Sdfr st8 [in3]=r14 68266486Sdfr 68366486Sdfr3: cmp.eq p6,p0=r0,r15 68466486Sdfr(p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly 68566458Sdfr 68666486Sdfr mov ret0=ENAMETOOLONG // *from != '\0'; error. 68766486Sdfr br.ret.sptk.few rp 68866458Sdfr 68966486Sdfr4: mov ret0=0 // return 0. 69066486Sdfr br.ret.sptk.few rp 69166486SdfrEND(copystr) 69266458Sdfr 69366633SdfrENTRY(copyinstr, 4) 69485682Sdfr .prologue 69585682Sdfr .regstk 4, 3, 4, 0 69685682Sdfr .save ar.pfs,loc0 69766486Sdfr alloc loc0=ar.pfs,4,3,4,0 69885682Sdfr .save rp,loc1 69966486Sdfr mov loc1=rp 70085682Sdfr .body 70166458Sdfr 702115084Smarcel movl loc2=VM_MAX_ADDRESS // make sure that src addr 70366486Sdfr ;; 70466633Sdfr cmp.geu p6,p0=in0,loc2 // is in user space. 70566486Sdfr ;; 70666486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 70766486Sdfr movl r14=copyerr // set up fault handler. 70887702Sjhb add r15=PC_CURTHREAD,r13 // find curthread 70966486Sdfr ;; 71066486Sdfr ld8 r15=[r15] 71166486Sdfr ;; 71283366Sjulian add r15=TD_PCB,r15 // find pcb 71366486Sdfr ;; 71466486Sdfr ld8 r15=[r15] 71566486Sdfr ;; 71683366Sjulian add loc2=PCB_ONFAULT,r15 71766486Sdfr ;; 71866486Sdfr st8 [loc2]=r14 71966486Sdfr ;; 72066486Sdfr mov out0=in0 72166486Sdfr mov out1=in1 72266486Sdfr mov out2=in2 72366486Sdfr mov out3=in3 72466486Sdfr ;; 72566486Sdfr br.call.sptk.few rp=copystr // do the copy. 72666486Sdfr st8 [loc2]=r0 // kill the fault handler. 72767020Sdfr mov ar.pfs=loc0 // restore ar.pfs 72866486Sdfr mov rp=loc1 // restore ra. 72966486Sdfr br.ret.sptk.few rp // ret0 left over from copystr 73066486SdfrEND(copyinstr) 73166458Sdfr 73266458Sdfr/* 73366486Sdfr * Not the fastest bcopy in the world. 73466458Sdfr */ 73566633SdfrENTRY(bcopy, 3) 73666486Sdfr mov ret0=r0 // return zero for copy{in,out} 73766486Sdfr ;; 73866486Sdfr cmp.le p6,p0=in2,r0 // bail if len <= 0 73966486Sdfr(p6) br.ret.spnt.few rp 74066458Sdfr 74166486Sdfr sub r14=in1,in0 ;; // check for overlap 74266486Sdfr cmp.ltu p6,p0=r14,in2 // dst-src < len 74366486Sdfr(p6) br.cond.spnt.few 5f 74466458Sdfr 74566486Sdfr extr.u r14=in0,0,3 // src & 7 74666486Sdfr extr.u r15=in1,0,3 ;; // dst & 7 74766486Sdfr cmp.eq p6,p0=r14,r15 // different alignment? 74866486Sdfr(p6) br.cond.spnt.few 2f // branch if same alignment 74966458Sdfr 75066486Sdfr1: ld1 r14=[in0],1 ;; // copy bytewise 75166486Sdfr st1 [in1]=r14,1 75266486Sdfr add in2=-1,in2 ;; // len-- 75366486Sdfr cmp.ne p6,p0=r0,in2 75466486Sdfr(p6) br.cond.dptk.few 1b // loop 75566486Sdfr br.ret.sptk.few rp // done 75666458Sdfr 75766486Sdfr2: cmp.eq p6,p0=r14,r0 // aligned? 75866486Sdfr(p6) br.cond.sptk.few 4f 75966458Sdfr 76066486Sdfr3: ld1 r14=[in0],1 ;; // copy bytewise 76166486Sdfr st1 [in1]=r14,1 76266486Sdfr extr.u r15=in0,0,3 // src & 7 76366486Sdfr add in2=-1,in2 ;; // len-- 76466486Sdfr cmp.eq p6,p0=r0,in2 // done? 76566486Sdfr cmp.eq p7,p0=r0,r15 ;; // aligned now? 76666486Sdfr(p6) br.ret.spnt.few rp // return if done 76766486Sdfr(p7) br.cond.spnt.few 4f // go to main copy 76866486Sdfr br.cond.sptk.few 3b // more bytes to copy 76966458Sdfr 77066486Sdfr // At this point, in2 is non-zero 77166458Sdfr 77266486Sdfr4: mov r14=8 ;; 77366486Sdfr cmp.ltu p6,p0=in2,r14 ;; // len < 8? 77466486Sdfr(p6) br.cond.spnt.few 1b // byte copy the end 77566486Sdfr ld8 r15=[in0],8 ;; // copy word 77666486Sdfr st8 [in1]=r15,8 77766486Sdfr add in2=-8,in2 ;; // len -= 8 77866486Sdfr cmp.ne p6,p0=r0,in2 // done? 77966486Sdfr(p6) br.cond.spnt.few 4b // again 78066458Sdfr 78166486Sdfr br.ret.sptk.few rp // return 78266458Sdfr 78366486Sdfr // Don't bother optimising overlap case 78466458Sdfr 78566486Sdfr5: add in0=in0,in2 78666486Sdfr add in1=in1,in2 ;; 78766486Sdfr add in0=-1,in0 78866486Sdfr add in1=-1,in1 ;; 78966458Sdfr 79066486Sdfr6: ld1 r14=[in0],-1 ;; 79166486Sdfr st1 [in1]=r14,-1 79266486Sdfr add in2=-1,in2 ;; 79366486Sdfr cmp.ne p6,p0=r0,in2 79466486Sdfr(p6) br.cond.spnt.few 6b 79566458Sdfr 79666486Sdfr br.ret.sptk.few rp 79766486SdfrEND(bcopy) 79866458Sdfr 79966633SdfrENTRY(memcpy,3) 80066486Sdfr mov r14=in0 ;; 80166486Sdfr mov in0=in1 ;; 80266486Sdfr mov in1=r14 80366486Sdfr br.cond.sptk.few bcopy 80466486SdfrEND(memcpy) 80566486Sdfr 80666633SdfrENTRY(copyin, 3) 80785682Sdfr .prologue 808115084Smarcel .regstk 3, 3, 3, 0 80985682Sdfr .save ar.pfs,loc0 810115084Smarcel alloc loc0=ar.pfs,3,3,3,0 81185682Sdfr .save rp,loc1 81266486Sdfr mov loc1=rp 81385682Sdfr .body 81466458Sdfr 815115084Smarcel movl loc2=VM_MAX_ADDRESS // make sure that src addr 81666486Sdfr ;; 81767020Sdfr cmp.geu p6,p0=in0,loc2 // is in user space. 81866486Sdfr ;; 81966486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 82066486Sdfr movl r14=copyerr // set up fault handler. 82187702Sjhb add r15=PC_CURTHREAD,r13 // find curthread 82266486Sdfr ;; 82366486Sdfr ld8 r15=[r15] 82466486Sdfr ;; 82583366Sjulian add r15=TD_PCB,r15 // find pcb 82666486Sdfr ;; 82766486Sdfr ld8 r15=[r15] 82866486Sdfr ;; 82983366Sjulian add loc2=PCB_ONFAULT,r15 83066486Sdfr ;; 83166486Sdfr st8 [loc2]=r14 83266486Sdfr ;; 83366486Sdfr mov out0=in0 83466486Sdfr mov out1=in1 83566486Sdfr mov out2=in2 83666486Sdfr ;; 83766486Sdfr br.call.sptk.few rp=bcopy // do the copy. 83866486Sdfr st8 [loc2]=r0 // kill the fault handler. 83967020Sdfr mov ar.pfs=loc0 // restore ar.pfs 84066486Sdfr mov rp=loc1 // restore ra. 84166486Sdfr br.ret.sptk.few rp // ret0 left over from bcopy 84266486SdfrEND(copyin) 84366458Sdfr 84466633SdfrENTRY(copyout, 3) 84585682Sdfr .prologue 846115084Smarcel .regstk 3, 3, 3, 0 84785682Sdfr .save ar.pfs,loc0 848115084Smarcel alloc loc0=ar.pfs,3,3,3,0 84985682Sdfr .save rp,loc1 85066486Sdfr mov loc1=rp 85185682Sdfr .body 85266458Sdfr 853115084Smarcel movl loc2=VM_MAX_ADDRESS // make sure that dest addr 85466486Sdfr ;; 85567020Sdfr cmp.geu p6,p0=in1,loc2 // is in user space. 85666486Sdfr ;; 85766486Sdfr(p6) br.cond.spnt.few copyerr // if it's not, error out. 85866486Sdfr movl r14=copyerr // set up fault handler. 85987702Sjhb add r15=PC_CURTHREAD,r13 // find curthread 86066486Sdfr ;; 86166486Sdfr ld8 r15=[r15] 86266486Sdfr ;; 86383366Sjulian add r15=TD_PCB,r15 // find pcb 86466486Sdfr ;; 86566486Sdfr ld8 r15=[r15] 86666486Sdfr ;; 86783366Sjulian add loc2=PCB_ONFAULT,r15 86866486Sdfr ;; 86966486Sdfr st8 [loc2]=r14 87066486Sdfr ;; 87166486Sdfr mov out0=in0 87266486Sdfr mov out1=in1 87366486Sdfr mov out2=in2 87466486Sdfr ;; 87566486Sdfr br.call.sptk.few rp=bcopy // do the copy. 87666486Sdfr st8 [loc2]=r0 // kill the fault handler. 87767020Sdfr mov ar.pfs=loc0 // restore ar.pfs 87866486Sdfr mov rp=loc1 // restore ra. 87966486Sdfr br.ret.sptk.few rp // ret0 left over from bcopy 88066486SdfrEND(copyout) 88166458Sdfr 88266633SdfrENTRY(copyerr, 0) 88387702Sjhb add r14=PC_CURTHREAD,r13 ;; // find curthread 88466486Sdfr ld8 r14=[r14] ;; 88583366Sjulian add r14=TD_PCB,r14 ;; // curthread->td_addr 88666486Sdfr ld8 r14=[r14] ;; 88783366Sjulian add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault 88866486Sdfr st8 [r14]=r0 // reset fault handler 88966458Sdfr 89066486Sdfr mov ret0=EFAULT // return EFAULT 89166486Sdfr br.ret.sptk.few rp 89266486SdfrEND(copyerr) 893121410Smarcel 894121410Smarcel/* 895121410Smarcel * Support functions for handling of unaligned memory accesses. 896121410Smarcel */ 897121410SmarcelENTRY(spillfd, 2) 898121410Smarcel ldfd f6 = [r32] 899121410Smarcel ;; 900121410Smarcel stf.spill [r33] = f6 901121410Smarcel br.ret.sptk rp 902121410SmarcelEND(spillfd) 903