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 ld8.acq r15=[r13] // r15 = curthread
77 movl r14=VM_MAXUSER_ADDRESS
87 ld8 r15=[r15] // r15 = PCB
93 add r15=PCB_ONFAULT,r15
98 st8 [r15]=r14 // Set onfault
100 cmpxchg8.rel ret0=[in0],in2,ar.ccv
105 st8.rel [r15]=r0 // Clear onfault
120 * casuword32(uint32_t *p, uint32_t old, uint32_t new)
121 * Perform a 32-bit compare-exchange in user space.
125 movl r14=VM_MAXUSER_ADDRESS
129 ld8.acq r15=[r13] // r15 = curthread
130 cmp.geu p6,p0=in0,r14
140 ld8 r15=[r15] // r15 = PCB
143 add r15=PCB_ONFAULT,r15
147 st8 [r15]=r14 // Set onfault
149 cmpxchg4.rel ret0=[in0],in2,ar.ccv
154 st8.rel [r15]=r0 // Clear onfault
169 * subyte(void *addr, int byte)
170 * suword16(void *addr, int word)
171 * suword32(void *addr, int word)
172 * suword64|suword(void *addr, long word)
173 * Store in user space
178 movl r14=VM_MAXUSER_ADDRESS
182 ld8.acq r15=[r13] // r15 = curthread
183 cmp.geu p6,p0=in0,r14
193 ld8 r15=[r15] // r15 = PCB
196 add r15=PCB_ONFAULT,r15
200 st8 [r15]=r14 // Set onfault
207 st8.rel [r15]=r0 // Clear onfault
223 movl r14=VM_MAXUSER_ADDRESS
227 ld8.acq r15=[r13] // r15 = curthread
228 cmp.geu p6,p0=in0,r14
238 ld8 r15=[r15] // r15 = PCB
241 add r15=PCB_ONFAULT,r15
245 st8 [r15]=r14 // Set onfault
252 st8.rel [r15]=r0 // Clear onfault
268 movl r14=VM_MAXUSER_ADDRESS
272 ld8.acq r15=[r13] // r15 = curthread
273 cmp.geu p6,p0=in0,r14
283 ld8 r15=[r15] // r15 = PCB
286 add r15=PCB_ONFAULT,r15
290 st8 [r15]=r14 // Set onfault
297 st8.rel [r15]=r0 // Clear onfault
314 movl r14=VM_MAXUSER_ADDRESS
318 ld8.acq r15=[r13] // r15 = curthread
319 cmp.geu p6,p0=in0,r14
329 ld8 r15=[r15] // r15 = PCB
332 add r15=PCB_ONFAULT,r15
336 st8 [r15]=r14 // Set onfault
343 st8.rel [r15]=r0 // Clear onfault
358 * fubyte(void *addr, int byte)
359 * fuword16(void *addr, int word)
360 * fuword32(void *addr, int word)
361 * fuword64|fuword(void *addr, long word)
362 * Fetch from user space
367 movl r14=VM_MAXUSER_ADDRESS
371 ld8.acq r15=[r13] // r15 = curthread
372 cmp.geu p6,p0=in0,r14
382 ld8 r15=[r15] // r15 = PCB
385 add r15=PCB_ONFAULT,r15
389 st8 [r15]=r14 // Set onfault
397 st8.rel [r15]=r0 // Clear onfault
412 movl r14=VM_MAXUSER_ADDRESS
416 ld8.acq r15=[r13] // r15 = curthread
417 cmp.geu p6,p0=in0,r14
427 ld8 r15=[r15] // r15 = PCB
430 add r15=PCB_ONFAULT,r15
434 st8 [r15]=r14 // Set onfault
442 st8.rel [r15]=r0 // Clear onfault
457 movl r14=VM_MAXUSER_ADDRESS
461 ld8.acq r15=[r13] // r15 = curthread
462 cmp.geu p6,p0=in0,r14
472 ld8 r15=[r15] // r15 = PCB
475 add r15=PCB_ONFAULT,r15
479 st8 [r15]=r14 // Set onfault
487 st8.rel [r15]=r0 // Clear onfault
503 movl r14=VM_MAXUSER_ADDRESS
507 ld8.acq r15=[r13] // r15 = curthread
508 cmp.geu p6,p0=in0,r14
518 ld8 r15=[r15] // r15 = PCB
521 add r15=PCB_ONFAULT,r15
525 st8 [r15]=r14 // Set onfault
533 st8.rel [r15]=r0 // Clear onfault
547 * fuswintr(void *addr)
548 * suswintr(void *addr)
569 /**************************************************************************/
572 * Copy a null-terminated string within the kernel's address space.
573 * If lenp is not NULL, store the number of chars copied in *lenp
575 * int copystr(char *from, char *to, size_t len, size_t *lenp);
578 mov r14=in2 // r14 = i = len
580 (p6) br.cond.spnt.few 2f // if (len == 0), bail out
582 1: ld1 r15=[in0],1 // read one byte
584 st1 [in1]=r15,1 // write that byte
585 add in2=-1,in2 // len--
590 (p6) br.cond.spnt.few 2f // if (*from == 0), bail out
591 (p7) br.cond.sptk.few 1b // if (len != 0) copy more
593 2: cmp.eq p6,p0=r0,in3
594 (p6) br.cond.dpnt.few 3f // if (lenp != NULL)
595 sub r14=r14,in2 // *lenp = (i - len)
599 3: cmp.eq p6,p0=r0,r15
600 (p6) br.cond.spnt.few 4f // *from == '\0'; leave quietly
602 mov ret0=ENAMETOOLONG // *from != '\0'; error.
605 4: mov ret0=0 // return 0.
613 alloc loc0=ar.pfs,4,3,4,0
618 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
620 cmp.geu p6,p0=in0,loc2 // is in user space.
622 (p6) br.cond.spnt.few copyerr // if it's not, error out.
624 movl r14=copyerr // set up fault handler.
626 add r15=TD_PCB,r15 // find pcb
630 add loc2=PCB_ONFAULT,r15
639 br.call.sptk.few rp=copystr // do the copy.
640 st8 [loc2]=r0 // kill the fault handler.
641 mov ar.pfs=loc0 // restore ar.pfs
642 mov rp=loc1 // restore ra.
643 br.ret.sptk.few rp // ret0 left over from copystr
647 * Not the fastest bcopy in the world.
650 mov ret0=r0 // return zero for copy{in,out}
652 cmp.le p6,p0=in2,r0 // bail if len <= 0
653 (p6) br.ret.spnt.few rp
655 sub r14=in1,in0 ;; // check for overlap
656 cmp.ltu p6,p0=r14,in2 // dst-src < len
657 (p6) br.cond.spnt.few 5f
659 extr.u r14=in0,0,3 // src & 7
660 extr.u r15=in1,0,3 ;; // dst & 7
661 cmp.eq p6,p0=r14,r15 // different alignment?
662 (p6) br.cond.spnt.few 2f // branch if same alignment
664 1: ld1 r14=[in0],1 ;; // copy bytewise
666 add in2=-1,in2 ;; // len--
668 (p6) br.cond.dptk.few 1b // loop
669 br.ret.sptk.few rp // done
671 2: cmp.eq p6,p0=r14,r0 // aligned?
672 (p6) br.cond.sptk.few 4f
674 3: ld1 r14=[in0],1 ;; // copy bytewise
676 extr.u r15=in0,0,3 // src & 7
677 add in2=-1,in2 ;; // len--
678 cmp.eq p6,p0=r0,in2 // done?
679 cmp.eq p7,p0=r0,r15 ;; // aligned now?
680 (p6) br.ret.spnt.few rp // return if done
681 (p7) br.cond.spnt.few 4f // go to main copy
682 br.cond.sptk.few 3b // more bytes to copy
684 // At this point, in2 is non-zero
687 cmp.ltu p6,p0=in2,r14 ;; // len < 8?
688 (p6) br.cond.spnt.few 1b // byte copy the end
689 ld8 r15=[in0],8 ;; // copy word
691 add in2=-8,in2 ;; // len -= 8
692 cmp.ne p6,p0=r0,in2 // done?
693 (p6) br.cond.spnt.few 4b // again
695 br.ret.sptk.few rp // return
697 // Don't bother optimising overlap case
704 6: ld1 r14=[in0],-1 ;;
708 (p6) br.cond.spnt.few 6b
717 br.cond.sptk.few bcopy
724 alloc loc0=ar.pfs,3,3,3,0
729 movl loc2=VM_MAXUSER_ADDRESS // make sure that src addr
731 cmp.geu p6,p0=in0,loc2 // is in user space.
733 (p6) br.cond.spnt.few copyerr // if it's not, error out.
735 movl r14=copyerr // set up fault handler.
737 add r15=TD_PCB,r15 // find pcb
741 add loc2=PCB_ONFAULT,r15
749 br.call.sptk.few rp=bcopy // do the copy.
750 st8 [loc2]=r0 // kill the fault handler.
751 mov ar.pfs=loc0 // restore ar.pfs
752 mov rp=loc1 // restore ra.
753 br.ret.sptk.few rp // ret0 left over from bcopy
760 alloc loc0=ar.pfs,3,3,3,0
765 movl loc2=VM_MAXUSER_ADDRESS // make sure that dest addr
767 cmp.geu p6,p0=in1,loc2 // is in user space.
769 (p6) br.cond.spnt.few copyerr // if it's not, error out.
771 movl r14=copyerr // set up fault handler.
773 add r15=TD_PCB,r15 // find pcb
777 add loc2=PCB_ONFAULT,r15
785 br.call.sptk.few rp=bcopy // do the copy.
786 st8 [loc2]=r0 // kill the fault handler.
787 mov ar.pfs=loc0 // restore ar.pfs
788 mov rp=loc1 // restore ra.
789 br.ret.sptk.few rp // ret0 left over from bcopy
794 add r14=TD_PCB,r14 ;; // curthread->td_addr
796 add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault
797 st8 [r14]=r0 // reset fault handler
799 mov ret0=EFAULT // return EFAULT
805 * Important registers:
806 * r8 structure return address
807 * rp our return address
808 * in0 caller's ar.pfs
814 ENTRY_NOPROFILE(_mcount, 4)
815 alloc loc0 = ar.pfs, 4, 3, 2, 0
821 br.call.sptk rp = __mcount
828 add r14 = 2f - 1b, r14