2 * Copyright (c) 1998 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
30 * All rights reserved.
32 * Author: Chris G. Demetriou
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.
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.
44 * Carnegie Mellon requests users of this software to return to
46 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
47 * School of Computer Science
48 * Carnegie Mellon University
49 * Pittsburgh PA 15213-3890
51 * any improvements or extensions that they make and grant Carnegie the
52 * rights to redistribute these changes.
55 #include <machine/asm.h>
56 #include <machine/ia64_cpu.h>
62 * ia64_change_mode: change mode to/from physical mode
65 * r14 psr for desired mode
69 * ar.bsp tranlated to new mode
71 ENTRY_NOPROFILE(ia64_change_mode, 0)
73 mov r19=ar.rsc // save rsc while we change mode
74 tbit.nz p6,p7=r14,17 // physical or virtual ?
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
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
95 mov cr.ipsr=r14 // psr for new mode
97 add r16=2f-1b,r16 // address to rfi to
99 dep r16=r15,r16,61,3 // new mode address for rfi
101 mov cr.iip=r16 // setup for rfi
106 2: mov ar.rsc=r19 // restore ar.rsc
107 br.ret.sptk.few rp // now in new mode
108 END(ia64_change_mode)
111 * ia64_physical_mode: change mode to physical mode
114 * ret0 psr to restore
118 * ar.bsp tranlated to physical mode
121 ENTRY(ia64_physical_mode, 0)
124 movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH)
127 andcm r14=r14,r15 // clear various xT bits
129 or r14=r14,r16 // make sure BN=1
130 or ret0=ret0,r16 // make sure BN=1
132 br.cond.sptk.many ia64_change_mode
133 END(ia64_physical_mode)
136 * ia64_call_efi_physical: call an EFI procedure in physical mode
139 * in0 Address of EFI procedure descriptor
140 * in1-in5 Arguments to EFI procedure
143 * ret0-ret3 return values from EFI
146 ENTRY(ia64_call_efi_physical, 6)
150 alloc loc0=ar.pfs,6,4,5,0
156 br.call.sptk.many rp=ia64_physical_mode
158 mov loc2=r8 // psr to restore mode
159 mov loc3=gp // save kernel gp
160 ld8 r14=[in0],8 // function address
167 ld8 gp=[in0] // function gp value
171 br.call.sptk.many rp=b6 // call EFI procedure
172 mov gp=loc3 // restore kernel gp
174 mov r14=loc2 // psr to restore mode
175 br.call.sptk.many rp=ia64_change_mode
181 END(ia64_call_efi_physical)
183 /**************************************************************************/
187 st8.rel [r15]=r0 // Clear onfault.
195 * casuword(u_long *p, u_long old, u_long new)
196 * Perform a compare-exchange in user space.
200 add r15=PC_CURTHREAD,r13
201 movl r14=VM_MAX_ADDRESS
205 ld8 r15=[r15] // r15 = curthread
206 cmp.geu p6,p0=in0,r14
216 ld8 r15=[r15] // r15 = PCB
219 add r15=PCB_ONFAULT,r15
223 st8 [r15]=r14 // Set onfault
225 cmpxchg8.rel ret0=[in0],in2,ar.ccv
230 st8.rel [r15]=r0 // Clear onfault
245 * casuword32(uint32_t *p, uint32_t old, uint32_t new)
246 * Perform a 32-bit compare-exchange in user space.
250 add r15=PC_CURTHREAD,r13
251 movl r14=VM_MAX_ADDRESS
255 ld8 r15=[r15] // r15 = curthread
256 cmp.geu p6,p0=in0,r14
266 ld8 r15=[r15] // r15 = PCB
269 add r15=PCB_ONFAULT,r15
273 st8 [r15]=r14 // Set onfault
275 cmpxchg4.rel ret0=[in0],in2,ar.ccv
280 st8.rel [r15]=r0 // Clear onfault
295 * subyte(void *addr, int byte)
296 * suword16(void *addr, int word)
297 * suword32(void *addr, int word)
298 * suword64|suword(void *addr, long word)
299 * Store in user space
304 add r15=PC_CURTHREAD,r13
305 movl r14=VM_MAX_ADDRESS
309 ld8 r15=[r15] // r15 = curthread
310 cmp.geu p6,p0=in0,r14
320 ld8 r15=[r15] // r15 = PCB
323 add r15=PCB_ONFAULT,r15
327 st8 [r15]=r14 // Set onfault
334 st8.rel [r15]=r0 // Clear onfault
350 add r15=PC_CURTHREAD,r13
351 movl r14=VM_MAX_ADDRESS
355 ld8 r15=[r15] // r15 = curthread
356 cmp.geu p6,p0=in0,r14
366 ld8 r15=[r15] // r15 = PCB
369 add r15=PCB_ONFAULT,r15
373 st8 [r15]=r14 // Set onfault
380 st8.rel [r15]=r0 // Clear onfault
396 add r15=PC_CURTHREAD,r13
397 movl r14=VM_MAX_ADDRESS
401 ld8 r15=[r15] // r15 = curthread
402 cmp.geu p6,p0=in0,r14
412 ld8 r15=[r15] // r15 = PCB
415 add r15=PCB_ONFAULT,r15
419 st8 [r15]=r14 // Set onfault
426 st8.rel [r15]=r0 // Clear onfault
443 add r15=PC_CURTHREAD,r13
444 movl r14=VM_MAX_ADDRESS
448 ld8 r15=[r15] // r15 = curthread
449 cmp.geu p6,p0=in0,r14
459 ld8 r15=[r15] // r15 = PCB
462 add r15=PCB_ONFAULT,r15
466 st8 [r15]=r14 // Set onfault
473 st8.rel [r15]=r0 // Clear onfault
488 * fubyte(void *addr, int byte)
489 * fuword16(void *addr, int word)
490 * fuword32(void *addr, int word)
491 * fuword64|fuword(void *addr, long word)
492 * Fetch from user space
497 add r15=PC_CURTHREAD,r13
498 movl r14=VM_MAX_ADDRESS
502 ld8 r15=[r15] // r15 = curthread
503 cmp.geu p6,p0=in0,r14
513 ld8 r15=[r15] // r15 = PCB
516 add r15=PCB_ONFAULT,r15
520 st8 [r15]=r14 // Set onfault
528 st8.rel [r15]=r0 // Clear onfault
543 add r15=PC_CURTHREAD,r13
544 movl r14=VM_MAX_ADDRESS
548 ld8 r15=[r15] // r15 = curthread
549 cmp.geu p6,p0=in0,r14
559 ld8 r15=[r15] // r15 = PCB
562 add r15=PCB_ONFAULT,r15
566 st8 [r15]=r14 // Set onfault
574 st8.rel [r15]=r0 // Clear onfault
589 add r15=PC_CURTHREAD,r13
590 movl r14=VM_MAX_ADDRESS
594 ld8 r15=[r15] // r15 = curthread
595 cmp.geu p6,p0=in0,r14
605 ld8 r15=[r15] // r15 = PCB
608 add r15=PCB_ONFAULT,r15
612 st8 [r15]=r14 // Set onfault
620 st8.rel [r15]=r0 // Clear onfault
636 add r15=PC_CURTHREAD,r13
637 movl r14=VM_MAX_ADDRESS
641 ld8 r15=[r15] // r15 = curthread
642 cmp.geu p6,p0=in0,r14
652 ld8 r15=[r15] // r15 = PCB
655 add r15=PCB_ONFAULT,r15
659 st8 [r15]=r14 // Set onfault
667 st8.rel [r15]=r0 // Clear onfault
681 * fuswintr(void *addr)
682 * suswintr(void *addr)
703 /**************************************************************************/
706 * Copy a null-terminated string within the kernel's address space.
707 * If lenp is not NULL, store the number of chars copied in *lenp
709 * int copystr(char *from, char *to, size_t len, size_t *lenp);
712 mov r14=in2 // r14 = i = len
714 (p6) br.cond.spnt.few 2f // if (len == 0), bail out
716 1: ld1 r15=[in0],1 // read one byte
718 st1 [in1]=r15,1 // write that byte
719 add in2=-1,in2 // len--
724 (p6) br.cond.spnt.few 2f // if (*from == 0), bail out
725 (p7) br.cond.sptk.few 1b // if (len != 0) copy more
727 2: cmp.eq p6,p0=r0,in3
728 (p6) br.cond.dpnt.few 3f // if (lenp != NULL)
729 sub r14=r14,in2 // *lenp = (i - len)
733 3: cmp.eq p6,p0=r0,r15
734 (p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly
736 mov ret0=ENAMETOOLONG // *from != '\0'; error.
739 4: mov ret0=0 // return 0.
747 alloc loc0=ar.pfs,4,3,4,0
752 movl loc2=VM_MAX_ADDRESS // make sure that src addr
754 cmp.geu p6,p0=in0,loc2 // is in user space.
756 (p6) br.cond.spnt.few copyerr // if it's not, error out.
757 movl r14=copyerr // set up fault handler.
758 add r15=PC_CURTHREAD,r13 // find curthread
762 add r15=TD_PCB,r15 // find pcb
766 add loc2=PCB_ONFAULT,r15
775 br.call.sptk.few rp=copystr // do the copy.
776 st8 [loc2]=r0 // kill the fault handler.
777 mov ar.pfs=loc0 // restore ar.pfs
778 mov rp=loc1 // restore ra.
779 br.ret.sptk.few rp // ret0 left over from copystr
783 * Not the fastest bcopy in the world.
786 mov ret0=r0 // return zero for copy{in,out}
788 cmp.le p6,p0=in2,r0 // bail if len <= 0
789 (p6) br.ret.spnt.few rp
791 sub r14=in1,in0 ;; // check for overlap
792 cmp.ltu p6,p0=r14,in2 // dst-src < len
793 (p6) br.cond.spnt.few 5f
795 extr.u r14=in0,0,3 // src & 7
796 extr.u r15=in1,0,3 ;; // dst & 7
797 cmp.eq p6,p0=r14,r15 // different alignment?
798 (p6) br.cond.spnt.few 2f // branch if same alignment
800 1: ld1 r14=[in0],1 ;; // copy bytewise
802 add in2=-1,in2 ;; // len--
804 (p6) br.cond.dptk.few 1b // loop
805 br.ret.sptk.few rp // done
807 2: cmp.eq p6,p0=r14,r0 // aligned?
808 (p6) br.cond.sptk.few 4f
810 3: ld1 r14=[in0],1 ;; // copy bytewise
812 extr.u r15=in0,0,3 // src & 7
813 add in2=-1,in2 ;; // len--
814 cmp.eq p6,p0=r0,in2 // done?
815 cmp.eq p7,p0=r0,r15 ;; // aligned now?
816 (p6) br.ret.spnt.few rp // return if done
817 (p7) br.cond.spnt.few 4f // go to main copy
818 br.cond.sptk.few 3b // more bytes to copy
820 // At this point, in2 is non-zero
823 cmp.ltu p6,p0=in2,r14 ;; // len < 8?
824 (p6) br.cond.spnt.few 1b // byte copy the end
825 ld8 r15=[in0],8 ;; // copy word
827 add in2=-8,in2 ;; // len -= 8
828 cmp.ne p6,p0=r0,in2 // done?
829 (p6) br.cond.spnt.few 4b // again
831 br.ret.sptk.few rp // return
833 // Don't bother optimising overlap case
840 6: ld1 r14=[in0],-1 ;;
844 (p6) br.cond.spnt.few 6b
853 br.cond.sptk.few bcopy
860 alloc loc0=ar.pfs,3,3,3,0
865 movl loc2=VM_MAX_ADDRESS // make sure that src addr
867 cmp.geu p6,p0=in0,loc2 // is in user space.
869 (p6) br.cond.spnt.few copyerr // if it's not, error out.
870 movl r14=copyerr // set up fault handler.
871 add r15=PC_CURTHREAD,r13 // find curthread
875 add r15=TD_PCB,r15 // find pcb
879 add loc2=PCB_ONFAULT,r15
887 br.call.sptk.few rp=bcopy // do the copy.
888 st8 [loc2]=r0 // kill the fault handler.
889 mov ar.pfs=loc0 // restore ar.pfs
890 mov rp=loc1 // restore ra.
891 br.ret.sptk.few rp // ret0 left over from bcopy
898 alloc loc0=ar.pfs,3,3,3,0
903 movl loc2=VM_MAX_ADDRESS // make sure that dest addr
905 cmp.geu p6,p0=in1,loc2 // is in user space.
907 (p6) br.cond.spnt.few copyerr // if it's not, error out.
908 movl r14=copyerr // set up fault handler.
909 add r15=PC_CURTHREAD,r13 // find curthread
913 add r15=TD_PCB,r15 // find pcb
917 add loc2=PCB_ONFAULT,r15
925 br.call.sptk.few rp=bcopy // do the copy.
926 st8 [loc2]=r0 // kill the fault handler.
927 mov ar.pfs=loc0 // restore ar.pfs
928 mov rp=loc1 // restore ra.
929 br.ret.sptk.few rp // ret0 left over from bcopy
933 add r14=PC_CURTHREAD,r13 ;; // find curthread
935 add r14=TD_PCB,r14 ;; // curthread->td_addr
937 add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault
938 st8 [r14]=r0 // reset fault handler
940 mov ret0=EFAULT // return EFAULT
946 * Important registers:
947 * r8 structure return address
948 * rp our return address
949 * in0 caller's ar.pfs
955 ENTRY_NOPROFILE(_mcount, 4)
956 alloc loc0 = ar.pfs, 4, 3, 2, 0
962 br.call.sptk rp = __mcount
969 add r14 = 2f - 1b, r14