2 * Copyright (c) 1993 The Regents of the University of California.
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.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * $FreeBSD: src/sys/i386/i386/support.s,v 1.67.2.5 2001/08/15 01:23:50 peter Exp $
34 * $DragonFly: src/sys/platform/pc32/i386/support.s,v 1.21 2008/05/08 01:21:04 dillon Exp $
39 #include <machine/asmacros.h>
40 #include <machine/cputypes.h>
41 #include <machine/pmap.h>
42 #include <machine/specialreg.h>
52 .long asm_generic_memcpy
56 .long asm_generic_bcopy
60 .long asm_generic_bcopy
64 /* fillw(pat, base, cnt) */
77 * void bcopy(const void *s, void *d, size_t count)
79 * Normal bcopy() vector, an optimized bcopy may be installed in
85 movl
4+8(%esp
),%esi
/* caddr_t from */
86 movl
8+8(%esp
),%edi
/* caddr_t to */
87 movl
12+8(%esp
),%ecx
/* size_t len */
94 * Generic (integer-only) bcopy() vector.
99 movl
4+8(%esp
),%esi
/* caddr_t from */
100 movl
8+8(%esp
),%edi
/* caddr_t to */
101 movl
12+8(%esp
),%ecx
/* size_t len */
102 call asm_generic_bcopy
110 movl
4+8(%esp
),%esi
/* caddr_t from */
111 movl
8+8(%esp
),%edi
/* caddr_t to */
112 movl
12+8(%esp
),%ecx
/* size_t len */
119 * void *memcpy(void *d, const void *s, size_t count)
121 * Note: memcpy does not have to support overlapping copies.
123 * Note: (d, s) arguments reversed from bcopy, and memcpy() returns d
124 * while bcopy() returns void.
139 * A stack-based on-fault routine is used for more complex PCB_ONFAULT
140 * situations (such as memcpy/bcopy/bzero). In this case the on-fault
141 * routine must be pushed on the stack.
146 /*****************************************************************************/
147 /* copyout and fubyte family */
148 /*****************************************************************************/
150 * Access user memory from inside the kernel. These routines and possibly
151 * the math- and DOS emulators should be the only places that do this.
153 * We have to access the memory with user's permissions, so use a segment
154 * selector with RPL 3. For writes to user space we have to additionally
155 * check the PTE for write permission, because the 386 does not check
156 * write permissions when we are executing with EPL 0. The 486 does check
157 * this if the WP bit is set in CR0, so we can use a simpler version here.
159 * These routines set curpcb->onfault for the time they execute. When a
160 * protection violation occurs inside the functions, the trap handler
161 * returns to *curpcb->onfault instead of the function.
165 * copyout(from_kernel, to_user, len) - MP SAFE
168 movl PCPU
(curthread
),%eax
169 movl TD_PCB
(%eax
),%eax
173 pushl $copyout_fault2
174 movl $stack_onfault
,PCB_ONFAULT
(%eax
)
177 movl
12+16(%esp
),%ebx
178 testl
%ebx
,%ebx
/* anything to do? */
182 * Check explicitly for non-user addresses. If 486 write protection
183 * is being used, this check is essential because we are in kernel
184 * mode so the h/w does not provide any protection against writing
189 * First, prevent address wrapping.
195 * XXX STOP USING VM_MAX_USER_ADDRESS.
196 * It is an end address, not a max, so every time it is used correctly it
197 * looks like there is an off by one error, and of course it caused an off
198 * by one error in several places.
200 cmpl $VM_MAX_USER_ADDRESS
,%eax
204 * Convert copyout to memcpy_vector(dest:%edi, src:%esi, count:%ecx)
214 movl PCPU
(curthread
),%edx
216 movl TD_PCB
(%edx
),%edx
220 movl
%eax
,PCB_ONFAULT
(%edx
)
225 addl $
4,%esp
/* skip pushed copyout_fault vector */
230 movl PCPU
(curthread
),%edx
231 movl TD_PCB
(%edx
),%edx
232 movl $
0,PCB_ONFAULT
(%edx
)
237 * copyin(from_user, to_kernel, len) - MP SAFE
241 movl PCPU
(curthread
),%eax
242 movl TD_PCB
(%eax
),%eax
246 movl $stack_onfault
,PCB_ONFAULT
(%eax
)
247 movl
4+12(%esp
),%esi
/* caddr_t from */
248 movl
8+12(%esp
),%edi
/* caddr_t to */
249 movl
12+12(%esp
),%ecx
/* size_t len */
252 * make sure address is valid
257 cmpl $VM_MAX_USER_ADDRESS
,%edx
261 * Call memcpy(destination:%edi, source:%esi, bytes:%ecx)
266 * return 0 (no error)
269 movl PCPU
(curthread
),%edx
271 movl TD_PCB
(%edx
),%edx
274 movl
%eax
,PCB_ONFAULT
(%edx
)
282 addl $
4,%esp
/* skip pushed copyin_fault vector */
286 movl PCPU
(curthread
),%edx
287 movl TD_PCB
(%edx
),%edx
288 movl $
0,PCB_ONFAULT
(%edx
)
293 * fu{byte,sword,word} - MP SAFE
295 * Fetch a byte (sword, word) from user memory
298 movl PCPU
(curthread
),%ecx
299 movl TD_PCB
(%ecx
),%ecx
300 movl $fusufault
,PCB_ONFAULT
(%ecx
)
301 movl
4(%esp
),%edx
/* from */
303 cmpl $VM_MAX_USER_ADDRESS-
4,%edx
/* verify address is valid */
307 movl $
0,PCB_ONFAULT
(%ecx
)
314 movl PCPU
(curthread
),%ecx
315 movl TD_PCB
(%ecx
),%ecx
316 movl $fusufault
,PCB_ONFAULT
(%ecx
)
319 cmpl $VM_MAX_USER_ADDRESS-
2,%edx
323 movl $
0,PCB_ONFAULT
(%ecx
)
330 movl PCPU
(curthread
),%ecx
331 movl TD_PCB
(%ecx
),%ecx
332 movl $fusufault
,PCB_ONFAULT
(%ecx
)
335 cmpl $VM_MAX_USER_ADDRESS-
1,%edx
339 movl $
0,PCB_ONFAULT
(%ecx
)
344 movl PCPU
(curthread
),%ecx
345 movl TD_PCB
(%ecx
),%ecx
347 movl
%eax
,PCB_ONFAULT
(%ecx
)
352 * su{byte,sword,word} - MP SAFE
354 * Write a byte (word, longword) to user memory
357 movl PCPU
(curthread
),%ecx
358 movl TD_PCB
(%ecx
),%ecx
359 movl $fusufault
,PCB_ONFAULT
(%ecx
)
362 cmpl $VM_MAX_USER_ADDRESS-
4,%edx
/* verify address validity */
368 movl PCPU
(curthread
),%ecx
369 movl TD_PCB
(%ecx
),%ecx
370 movl
%eax
,PCB_ONFAULT
(%ecx
)
377 movl PCPU
(curthread
),%ecx
378 movl TD_PCB
(%ecx
),%ecx
379 movl $fusufault
,PCB_ONFAULT
(%ecx
)
382 cmpl $VM_MAX_USER_ADDRESS-
2,%edx
/* verify address validity */
388 movl PCPU
(curthread
),%ecx
/* restore trashed register */
389 movl TD_PCB
(%ecx
),%ecx
390 movl
%eax
,PCB_ONFAULT
(%ecx
)
397 movl PCPU
(curthread
),%ecx
398 movl TD_PCB
(%ecx
),%ecx
399 movl $fusufault
,PCB_ONFAULT
(%ecx
)
402 cmpl $VM_MAX_USER_ADDRESS-
1,%edx
/* verify address validity */
408 movl PCPU
(curthread
),%ecx
/* restore trashed register */
409 movl TD_PCB
(%ecx
),%ecx
410 movl
%eax
,PCB_ONFAULT
(%ecx
)
414 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
416 * copy a string from from to to, stop when a 0 character is reached.
417 * return ENAMETOOLONG if string is longer than maxlen, and
418 * EFAULT on protection violations. If lencopied is non-zero,
419 * return the actual length in *lencopied.
424 movl PCPU
(curthread
),%ecx
425 movl TD_PCB
(%ecx
),%ecx
426 movl $cpystrflt
,PCB_ONFAULT
(%ecx
)
428 movl
12(%esp
),%esi
/* %esi = from */
429 movl
16(%esp
),%edi
/* %edi = to */
430 movl
20(%esp
),%edx
/* %edx = maxlen */
432 movl $VM_MAX_USER_ADDRESS
,%eax
434 /* make sure 'from' is within bounds */
438 /* restrict maxlen to <= VM_MAX_USER_ADDRESS-from */
456 /* Success -- 0 byte reached */
461 /* edx is zero - return ENAMETOOLONG or EFAULT */
462 cmpl $VM_MAX_USER_ADDRESS
,%esi
465 movl $ENAMETOOLONG
,%eax
472 /* set *lencopied and return %eax */
473 movl PCPU
(curthread
),%ecx
474 movl TD_PCB
(%ecx
),%ecx
475 movl $
0,PCB_ONFAULT
(%ecx
)
489 * copystr(from, to, maxlen, int *lencopied) - MP SAFE
495 movl
12(%esp
),%esi
/* %esi = from */
496 movl
16(%esp
),%edi
/* %edi = to */
497 movl
20(%esp
),%edx
/* %edx = maxlen */
508 /* Success -- 0 byte reached */
513 /* edx is zero -- return ENAMETOOLONG */
514 movl $ENAMETOOLONG
,%eax
517 /* set *lencopied and return %eax */
539 cld
/* compare forwards */
558 * Handling of special 386 registers and descriptor tables etc
560 /* void lgdt(struct region_descriptor *rdp); */
562 /* reload the descriptor table */
566 /* flush the prefetch q */
570 /* reload "stale" selectors */
580 /* reload code selector by turning return into intersegmental return */
587 * void lidt(struct region_descriptor *rdp);
595 * void lldt(u_short sel)
602 * void ltr(u_short sel)
608 /* ssdtosd(*ssdp,*sdp) */
645 /* void load_cr3(caddr_t cr3) */
647 #if defined(SWTCH_OPTIM_STATS)
648 incl _tlb_flush_count
659 /* void load_cr4(caddr_t cr4) */
665 /* void reset_dbregs() */
668 movl
%eax
,%dr7
/* disable all breapoints first */
676 /*****************************************************************************/
677 /* setjump, longjump */
678 /*****************************************************************************/
682 movl
%ebx
,(%eax
) /* save ebx */
683 movl
%esp
,4(%eax
) /* save esp */
684 movl
%ebp
,8(%eax
) /* save ebp */
685 movl
%esi
,12(%eax
) /* save esi */
686 movl
%edi
,16(%eax
) /* save edi */
687 movl
(%esp
),%edx
/* get rta */
688 movl
%edx
,20(%eax
) /* save eip */
689 xorl
%eax
,%eax
/* return(0); */
694 movl
(%eax
),%ebx
/* restore ebx */
695 movl
4(%eax
),%esp
/* restore esp */
696 movl
8(%eax
),%ebp
/* restore ebp */
697 movl
12(%eax
),%esi
/* restore esi */
698 movl
16(%eax
),%edi
/* restore edi */
699 movl
20(%eax
),%edx
/* get rta */
700 movl
%edx
,(%esp
) /* put in return frame */
701 xorl
%eax
,%eax
/* return(1); */
706 * Support for BB-profiling (gcc -a). The kernbb program will extract
707 * the data from the kernel.
717 NON_GPROF_ENTRY
(__bb_init_func
)
723 .byte 0xc3 /* avoid macro for `ret' */