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>
63 st8.rel [r15]=r0 // Clear onfault.
71 * casuword(u_long *p, u_long old, u_long new)
72 * Perform a compare-exchange in user space.
76 add r15=PC_CURTHREAD,r13
77 movl r14=VM_MAXUSER_ADDRESS
81 ld8 r15=[r15] // r15 = curthread
92 ld8 r15=[r15] // r15 = PCB
95 add r15=PCB_ONFAULT,r15
99 st8 [r15]=r14 // Set onfault
101 cmpxchg8.rel ret0=[in0],in2,ar.ccv
106 st8.rel [r15]=r0 // Clear onfault
121 * casuword32(uint32_t *p, uint32_t old, uint32_t new)
122 * Perform a 32-bit compare-exchange in user space.
126 add r15=PC_CURTHREAD,r13
127 movl r14=VM_MAXUSER_ADDRESS
131 ld8 r15=[r15] // r15 = curthread
132 cmp.geu p6,p0=in0,r14
142 ld8 r15=[r15] // r15 = PCB
145 add r15=PCB_ONFAULT,r15
149 st8 [r15]=r14 // Set onfault
151 cmpxchg4.rel ret0=[in0],in2,ar.ccv
156 st8.rel [r15]=r0 // Clear onfault
171 * subyte(void *addr, int byte)
172 * suword16(void *addr, int word)
173 * suword32(void *addr, int word)
174 * suword64|suword(void *addr, long word)
175 * Store in user space
180 add r15=PC_CURTHREAD,r13
181 movl r14=VM_MAXUSER_ADDRESS
185 ld8 r15=[r15] // r15 = curthread
186 cmp.geu p6,p0=in0,r14
196 ld8 r15=[r15] // r15 = PCB
199 add r15=PCB_ONFAULT,r15
203 st8 [r15]=r14 // Set onfault
210 st8.rel [r15]=r0 // Clear onfault
226 add r15=PC_CURTHREAD,r13
227 movl r14=VM_MAXUSER_ADDRESS
231 ld8 r15=[r15] // r15 = curthread
232 cmp.geu p6,p0=in0,r14
242 ld8 r15=[r15] // r15 = PCB
245 add r15=PCB_ONFAULT,r15
249 st8 [r15]=r14 // Set onfault
256 st8.rel [r15]=r0 // Clear onfault
272 add r15=PC_CURTHREAD,r13
273 movl r14=VM_MAXUSER_ADDRESS
277 ld8 r15=[r15] // r15 = curthread
278 cmp.geu p6,p0=in0,r14
288 ld8 r15=[r15] // r15 = PCB
291 add r15=PCB_ONFAULT,r15
295 st8 [r15]=r14 // Set onfault
302 st8.rel [r15]=r0 // Clear onfault
319 add r15=PC_CURTHREAD,r13
320 movl r14=VM_MAXUSER_ADDRESS
324 ld8 r15=[r15] // r15 = curthread
325 cmp.geu p6,p0=in0,r14
335 ld8 r15=[r15] // r15 = PCB
338 add r15=PCB_ONFAULT,r15
342 st8 [r15]=r14 // Set onfault
349 st8.rel [r15]=r0 // Clear onfault
364 * fubyte(void *addr, int byte)
365 * fuword16(void *addr, int word)
366 * fuword32(void *addr, int word)
367 * fuword64|fuword(void *addr, long word)
368 * Fetch from user space
373 add r15=PC_CURTHREAD,r13
374 movl r14=VM_MAXUSER_ADDRESS
378 ld8 r15=[r15] // r15 = curthread
379 cmp.geu p6,p0=in0,r14
389 ld8 r15=[r15] // r15 = PCB
392 add r15=PCB_ONFAULT,r15
396 st8 [r15]=r14 // Set onfault
404 st8.rel [r15]=r0 // Clear onfault
419 add r15=PC_CURTHREAD,r13
420 movl r14=VM_MAXUSER_ADDRESS
424 ld8 r15=[r15] // r15 = curthread
425 cmp.geu p6,p0=in0,r14
435 ld8 r15=[r15] // r15 = PCB
438 add r15=PCB_ONFAULT,r15
442 st8 [r15]=r14 // Set onfault
450 st8.rel [r15]=r0 // Clear onfault
465 add r15=PC_CURTHREAD,r13
466 movl r14=VM_MAXUSER_ADDRESS
470 ld8 r15=[r15] // r15 = curthread
471 cmp.geu p6,p0=in0,r14
481 ld8 r15=[r15] // r15 = PCB
484 add r15=PCB_ONFAULT,r15
488 st8 [r15]=r14 // Set onfault
496 st8.rel [r15]=r0 // Clear onfault
512 add r15=PC_CURTHREAD,r13
513 movl r14=VM_MAXUSER_ADDRESS
517 ld8 r15=[r15] // r15 = curthread
518 cmp.geu p6,p0=in0,r14
528 ld8 r15=[r15] // r15 = PCB
531 add r15=PCB_ONFAULT,r15
535 st8 [r15]=r14 // Set onfault
543 st8.rel [r15]=r0 // Clear onfault
557 * fuswintr(void *addr)
558 * suswintr(void *addr)
579 /**************************************************************************/
582 * Copy a null-terminated string within the kernel's address space.
583 * If lenp is not NULL, store the number of chars copied in *lenp
585 * int copystr(char *from, char *to, size_t len, size_t *lenp);
588 mov r14=in2 // r14 = i = len
590 (p6) br.cond.spnt.few 2f // if (len == 0), bail out
592 1: ld1 r15=[in0],1 // read one byte
594 st1 [in1]=r15,1 // write that byte
595 add in2=-1,in2 // len--
600 (p6) br.cond.spnt.few 2f // if (*from == 0), bail out
601 (p7) br.cond.sptk.few 1b // if (len != 0) copy more
603 2: cmp.eq p6,p0=r0,in3
604 (p6) br.cond.dpnt.few 3f // if (lenp != NULL)
605 sub r14=r14,in2 // *lenp = (i - len)
609 3: cmp.eq p6,p0=r0,r15
610 (p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly
612 mov ret0=ENAMETOOLONG // *from != '\0'; error.
615 4: mov ret0=0 // return 0.
623 alloc loc0=ar.pfs,4,3,4,0
628 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
630 cmp.geu p6,p0=in0,loc2 // is in user space.
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
638 add r15=TD_PCB,r15 // find pcb
642 add loc2=PCB_ONFAULT,r15
651 br.call.sptk.few rp=copystr // do the copy.
652 st8 [loc2]=r0 // kill the fault handler.
653 mov ar.pfs=loc0 // restore ar.pfs
654 mov rp=loc1 // restore ra.
655 br.ret.sptk.few rp // ret0 left over from copystr
659 * Not the fastest bcopy in the world.
662 mov ret0=r0 // return zero for copy{in,out}
664 cmp.le p6,p0=in2,r0 // bail if len <= 0
665 (p6) br.ret.spnt.few rp
667 sub r14=in1,in0 ;; // check for overlap
668 cmp.ltu p6,p0=r14,in2 // dst-src < len
669 (p6) br.cond.spnt.few 5f
671 extr.u r14=in0,0,3 // src & 7
672 extr.u r15=in1,0,3 ;; // dst & 7
673 cmp.eq p6,p0=r14,r15 // different alignment?
674 (p6) br.cond.spnt.few 2f // branch if same alignment
676 1: ld1 r14=[in0],1 ;; // copy bytewise
678 add in2=-1,in2 ;; // len--
680 (p6) br.cond.dptk.few 1b // loop
681 br.ret.sptk.few rp // done
683 2: cmp.eq p6,p0=r14,r0 // aligned?
684 (p6) br.cond.sptk.few 4f
686 3: ld1 r14=[in0],1 ;; // copy bytewise
688 extr.u r15=in0,0,3 // src & 7
689 add in2=-1,in2 ;; // len--
690 cmp.eq p6,p0=r0,in2 // done?
691 cmp.eq p7,p0=r0,r15 ;; // aligned now?
692 (p6) br.ret.spnt.few rp // return if done
693 (p7) br.cond.spnt.few 4f // go to main copy
694 br.cond.sptk.few 3b // more bytes to copy
696 // At this point, in2 is non-zero
699 cmp.ltu p6,p0=in2,r14 ;; // len < 8?
700 (p6) br.cond.spnt.few 1b // byte copy the end
701 ld8 r15=[in0],8 ;; // copy word
703 add in2=-8,in2 ;; // len -= 8
704 cmp.ne p6,p0=r0,in2 // done?
705 (p6) br.cond.spnt.few 4b // again
707 br.ret.sptk.few rp // return
709 // Don't bother optimising overlap case
716 6: ld1 r14=[in0],-1 ;;
720 (p6) br.cond.spnt.few 6b
729 br.cond.sptk.few bcopy
736 alloc loc0=ar.pfs,3,3,3,0
741 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
743 cmp.geu p6,p0=in0,loc2 // is in user space.
745 (p6) br.cond.spnt.few copyerr // if it's not, error out.
746 movl r14=copyerr // set up fault handler.
747 add r15=PC_CURTHREAD,r13 // find curthread
751 add r15=TD_PCB,r15 // find pcb
755 add loc2=PCB_ONFAULT,r15
763 br.call.sptk.few rp=bcopy // do the copy.
764 st8 [loc2]=r0 // kill the fault handler.
765 mov ar.pfs=loc0 // restore ar.pfs
766 mov rp=loc1 // restore ra.
767 br.ret.sptk.few rp // ret0 left over from bcopy
774 alloc loc0=ar.pfs,3,3,3,0
779 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr
781 cmp.geu p6,p0=in1,loc2 // is in user space.
783 (p6) br.cond.spnt.few copyerr // if it's not, error out.
784 movl r14=copyerr // set up fault handler.
785 add r15=PC_CURTHREAD,r13 // find curthread
789 add r15=TD_PCB,r15 // find pcb
793 add loc2=PCB_ONFAULT,r15
801 br.call.sptk.few rp=bcopy // do the copy.
802 st8 [loc2]=r0 // kill the fault handler.
803 mov ar.pfs=loc0 // restore ar.pfs
804 mov rp=loc1 // restore ra.
805 br.ret.sptk.few rp // ret0 left over from bcopy
809 add r14=PC_CURTHREAD,r13 ;; // find curthread
811 add r14=TD_PCB,r14 ;; // curthread->td_addr
813 add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault
814 st8 [r14]=r0 // reset fault handler
816 mov ret0=EFAULT // return EFAULT
822 * Important registers:
823 * r8 structure return address
824 * rp our return address
825 * in0 caller's ar.pfs
831 ENTRY_NOPROFILE(_mcount, 4)
832 alloc loc0 = ar.pfs, 4, 3, 2, 0
838 br.call.sptk rp = __mcount
845 add r14 = 2f - 1b, r14