support.s revision 12702
1/*-
2 * Copyright (c) 1993 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
20 *
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
31 * SUCH DAMAGE.
32 *
33 *	$Id: support.s,v 1.24 1995/10/15 18:03:42 phk Exp $
34 */
35
36#include "assym.s"				/* system definitions */
37#include "errno.h"				/* error return codes */
38#include "machine/asmacros.h"			/* miscellaneous asm macros */
39#include "machine/cputypes.h"			/* types of CPUs */
40
41#define KDSEL		0x10			/* kernel data selector */
42#define IDXSHIFT	10
43
44/*
45 * Support for reading real time clock registers
46 */
47ENTRY(rtcin)					/* rtcin(val) */
48	movl	4(%esp),%eax
49	outb	%al,$0x70
50	NOP
51	xorl	%eax,%eax
52	inb	$0x71,%al
53	NOP
54	ret
55
56/*
57 * bcopy family
58 */
59
60/*
61 * void bzero(void *base, u_int cnt)
62 * Special code for I486 because stosl uses lots
63 * of clocks.  Makes little or no difference on DX2 type
64 * machines, but stosl is about 1/2 as fast as
65 * memory moves on a standard DX !!!!!
66 */
67ALTENTRY(blkclr)
68ENTRY(bzero)
69#if defined(I486_CPU)
70	cmpl	$CPUCLASS_486,_cpu_class
71	jz	1f
72#endif
73
74	pushl	%edi
75	movl	8(%esp),%edi
76	movl	12(%esp),%ecx
77	xorl	%eax,%eax
78	shrl	$2,%ecx
79	cld
80	rep
81	stosl
82	movl	12(%esp),%ecx
83	andl	$3,%ecx
84	rep
85	stosb
86	popl	%edi
87	ret
88
89#if defined(I486_CPU)
90	SUPERALIGN_TEXT
911:
92	movl	4(%esp),%edx
93	movl	8(%esp),%ecx
94	xorl	%eax,%eax
95/
96/ do 64 byte chunks first
97/
98/ XXX this is probably over-unrolled at least for DX2's
99/
1002:
101	cmpl	$64,%ecx
102	jb	3f
103	movl	%eax,(%edx)
104	movl	%eax,4(%edx)
105	movl	%eax,8(%edx)
106	movl	%eax,12(%edx)
107	movl	%eax,16(%edx)
108	movl	%eax,20(%edx)
109	movl	%eax,24(%edx)
110	movl	%eax,28(%edx)
111	movl	%eax,32(%edx)
112	movl	%eax,36(%edx)
113	movl	%eax,40(%edx)
114	movl	%eax,44(%edx)
115	movl	%eax,48(%edx)
116	movl	%eax,52(%edx)
117	movl	%eax,56(%edx)
118	movl	%eax,60(%edx)
119	addl	$64,%edx
120	subl	$64,%ecx
121	jnz	2b
122	ret
123
124/
125/ do 16 byte chunks
126/
127	SUPERALIGN_TEXT
1283:
129	cmpl	$16,%ecx
130	jb	4f
131	movl	%eax,(%edx)
132	movl	%eax,4(%edx)
133	movl	%eax,8(%edx)
134	movl	%eax,12(%edx)
135	addl	$16,%edx
136	subl	$16,%ecx
137	jnz	3b
138	ret
139
140/
141/ do 4 byte chunks
142/
143	SUPERALIGN_TEXT
1444:
145	cmpl	$4,%ecx
146	jb	5f
147	movl	%eax,(%edx)
148	addl	$4,%edx
149	subl	$4,%ecx
150	jnz	4b
151	ret
152
153/
154/ do 1 byte chunks
155/ a jump table seems to be faster than a loop or more range reductions
156/
157/ XXX need a const section for non-text
158/
159	SUPERALIGN_TEXT
160jtab:
161	.long	do0
162	.long	do1
163	.long	do2
164	.long	do3
165
166	SUPERALIGN_TEXT
1675:
168	jmp	jtab(,%ecx,4)
169
170	SUPERALIGN_TEXT
171do3:
172	movw	%ax,(%edx)
173	movb	%al,2(%edx)
174	ret
175
176	SUPERALIGN_TEXT
177do2:
178	movw	%ax,(%edx)
179	ret
180
181	SUPERALIGN_TEXT
182do1:
183	movb	%al,(%edx)
184
185	SUPERALIGN_TEXT
186do0:
187	ret
188#endif /* I486_CPU */
189
190/* fillw(pat, base, cnt) */
191ENTRY(fillw)
192	pushl	%edi
193	movl	8(%esp),%eax
194	movl	12(%esp),%edi
195	movl	16(%esp),%ecx
196	cld
197	rep
198	stosw
199	popl	%edi
200	ret
201
202ENTRY(bcopyb)
203bcopyb:
204	pushl	%esi
205	pushl	%edi
206	movl	12(%esp),%esi
207	movl	16(%esp),%edi
208	movl	20(%esp),%ecx
209	cmpl	%esi,%edi			/* potentially overlapping? */
210	jnb	1f
211	cld					/* nope, copy forwards */
212	rep
213	movsb
214	popl	%edi
215	popl	%esi
216	ret
217
218	ALIGN_TEXT
2191:
220	addl	%ecx,%edi			/* copy backwards. */
221	addl	%ecx,%esi
222	std
223	decl	%edi
224	decl	%esi
225	rep
226	movsb
227	popl	%edi
228	popl	%esi
229	cld
230	ret
231
232/*
233 * (ov)bcopy(src, dst, cnt)
234 *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
235 */
236ALTENTRY(ovbcopy)
237ENTRY(bcopy)
238bcopy:
239	pushl	%esi
240	pushl	%edi
241	movl	12(%esp),%esi
242	movl	16(%esp),%edi
243	movl	20(%esp),%ecx
244	cmpl	%esi,%edi			/* potentially overlapping? */
245	jnb	1f
246	shrl	$2,%ecx				/* copy by 32-bit words */
247	cld					/* nope, copy forwards */
248	rep
249	movsl
250	movl	20(%esp),%ecx
251	andl	$3,%ecx				/* any bytes left? */
252	rep
253	movsb
254	popl	%edi
255	popl	%esi
256	ret
257
258	ALIGN_TEXT
2591:
260	addl	%ecx,%edi			/* copy backwards */
261	addl	%ecx,%esi
262	andl	$3,%ecx				/* any fractional bytes? */
263	decl	%edi
264	decl	%esi
265	std
266	rep
267	movsb
268	movl	20(%esp),%ecx			/* copy remainder by 32-bit words */
269	shrl	$2,%ecx
270	subl	$3,%esi
271	subl	$3,%edi
272	rep
273	movsl
274	popl	%edi
275	popl	%esi
276	cld
277	ret
278
279
280/*
281 * Note: memcpy does not support overlapping copies
282 */
283ENTRY(memcpy)
284	pushl	%edi
285	pushl	%esi
286	movl	12(%esp),%edi
287	movl	16(%esp),%esi
288	movl	20(%esp),%ecx
289	movl	%edi,%eax
290	shrl	$2,%ecx				/* copy by 32-bit words */
291	cld					/* nope, copy forwards */
292	rep
293	movsl
294	movl	20(%esp),%ecx
295	andl	$3,%ecx				/* any bytes left? */
296	rep
297	movsb
298	popl	%esi
299	popl	%edi
300	ret
301
302
303/*****************************************************************************/
304/* copyout and fubyte family                                                 */
305/*****************************************************************************/
306/*
307 * Access user memory from inside the kernel. These routines and possibly
308 * the math- and DOS emulators should be the only places that do this.
309 *
310 * We have to access the memory with user's permissions, so use a segment
311 * selector with RPL 3. For writes to user space we have to additionally
312 * check the PTE for write permission, because the 386 does not check
313 * write permissions when we are executing with EPL 0. The 486 does check
314 * this if the WP bit is set in CR0, so we can use a simpler version here.
315 *
316 * These routines set curpcb->onfault for the time they execute. When a
317 * protection violation occurs inside the functions, the trap handler
318 * returns to *curpcb->onfault instead of the function.
319 */
320
321
322ENTRY(copyout)					/* copyout(from_kernel, to_user, len) */
323	movl	_curpcb,%eax
324	movl	$copyout_fault,PCB_ONFAULT(%eax)
325	pushl	%esi
326	pushl	%edi
327	pushl	%ebx
328	movl	16(%esp),%esi
329	movl	20(%esp),%edi
330	movl	24(%esp),%ebx
331	testl	%ebx,%ebx			/* anything to do? */
332	jz	done_copyout
333
334	/*
335	 * Check explicitly for non-user addresses.  If 486 write protection
336	 * is being used, this check is essential because we are in kernel
337	 * mode so the h/w does not provide any protection against writing
338	 * kernel addresses.
339	 */
340
341	/*
342	 * First, prevent address wrapping.
343	 */
344	movl	%edi,%eax
345	addl	%ebx,%eax
346	jc	copyout_fault
347/*
348 * XXX STOP USING VM_MAXUSER_ADDRESS.
349 * It is an end address, not a max, so every time it is used correctly it
350 * looks like there is an off by one error, and of course it caused an off
351 * by one error in several places.
352 */
353	cmpl	$VM_MAXUSER_ADDRESS,%eax
354	ja	copyout_fault
355
356#if defined(I386_CPU)
357
358#if defined(I486_CPU) || defined(I586_CPU)
359	cmpl	$CPUCLASS_386,_cpu_class
360	jne	3f
361#endif
362/*
363 * We have to check each PTE for user write permission.
364 * The checking may cause a page fault, so it is important to set
365 * up everything for return via copyout_fault before here.
366 */
367	/* compute number of pages */
368	movl	%edi,%ecx
369	andl	$NBPG-1,%ecx
370	addl	%ebx,%ecx
371	decl	%ecx
372	shrl	$IDXSHIFT+2,%ecx
373	incl	%ecx
374
375	/* compute PTE offset for start address */
376	movl	%edi,%edx
377	shrl	$IDXSHIFT,%edx
378	andb	$0xfc,%dl
379
3801:	/* check PTE for each page */
381	movb	_PTmap(%edx),%al
382	andb	$0x07,%al			/* Pages must be VALID + USERACC + WRITABLE */
383	cmpb	$0x07,%al
384	je	2f
385
386	/* simulate a trap */
387	pushl	%edx
388	pushl	%ecx
389	shll	$IDXSHIFT,%edx
390	pushl	%edx
391	call	_trapwrite			/* trapwrite(addr) */
392	popl	%edx
393	popl	%ecx
394	popl	%edx
395
396	testl	%eax,%eax			/* if not ok, return EFAULT */
397	jnz	copyout_fault
398
3992:
400	addl	$4,%edx
401	decl	%ecx
402	jnz	1b				/* check next page */
403#endif /* I386_CPU */
404
405	/* bcopy(%esi, %edi, %ebx) */
4063:
407	movl	%ebx,%ecx
408	shrl	$2,%ecx
409	cld
410	rep
411	movsl
412	movb	%bl,%cl
413	andb	$3,%cl
414	rep
415	movsb
416
417done_copyout:
418	popl	%ebx
419	popl	%edi
420	popl	%esi
421	xorl	%eax,%eax
422	movl	_curpcb,%edx
423	movl	%eax,PCB_ONFAULT(%edx)
424	ret
425
426	ALIGN_TEXT
427copyout_fault:
428	popl	%ebx
429	popl	%edi
430	popl	%esi
431	movl	_curpcb,%edx
432	movl	$0,PCB_ONFAULT(%edx)
433	movl	$EFAULT,%eax
434	ret
435
436/* copyin(from_user, to_kernel, len) */
437ENTRY(copyin)
438	movl	_curpcb,%eax
439	movl	$copyin_fault,PCB_ONFAULT(%eax)
440	pushl	%esi
441	pushl	%edi
442	movl	12(%esp),%esi			/* caddr_t from */
443	movl	16(%esp),%edi			/* caddr_t to */
444	movl	20(%esp),%ecx			/* size_t  len */
445
446	/*
447	 * make sure address is valid
448	 */
449	movl	%esi,%edx
450	addl	%ecx,%edx
451	jc	copyin_fault
452	cmpl	$VM_MAXUSER_ADDRESS,%edx
453	ja	copyin_fault
454
455	movb	%cl,%al
456	shrl	$2,%ecx				/* copy longword-wise */
457	cld
458	rep
459	movsl
460	movb	%al,%cl
461	andb	$3,%cl				/* copy remaining bytes */
462	rep
463	movsb
464
465	popl	%edi
466	popl	%esi
467	xorl	%eax,%eax
468	movl	_curpcb,%edx
469	movl	%eax,PCB_ONFAULT(%edx)
470	ret
471
472	ALIGN_TEXT
473copyin_fault:
474	popl	%edi
475	popl	%esi
476	movl	_curpcb,%edx
477	movl	$0,PCB_ONFAULT(%edx)
478	movl	$EFAULT,%eax
479	ret
480
481/*
482 * fu{byte,sword,word} : fetch a byte (sword, word) from user memory
483 */
484ENTRY(fuword)
485	movl	_curpcb,%ecx
486	movl	$fusufault,PCB_ONFAULT(%ecx)
487	movl	4(%esp),%edx			/* from */
488
489	cmpl	$VM_MAXUSER_ADDRESS-4,%edx	/* verify address is valid */
490	ja	fusufault
491
492	movl	(%edx),%eax
493	movl	$0,PCB_ONFAULT(%ecx)
494	ret
495
496/*
497 * These two routines are called from the profiling code, potentially
498 * at interrupt time. If they fail, that's okay, good things will
499 * happen later. Fail all the time for now - until the trap code is
500 * able to deal with this.
501 */
502ALTENTRY(suswintr)
503ENTRY(fuswintr)
504	movl	$-1,%eax
505	ret
506
507ENTRY(fubyte)
508	movl	_curpcb,%ecx
509	movl	$fusufault,PCB_ONFAULT(%ecx)
510	movl	4(%esp),%edx
511
512	cmpl	$VM_MAXUSER_ADDRESS-1,%edx
513	ja	fusufault
514
515	movzbl	(%edx),%eax
516	movl	$0,PCB_ONFAULT(%ecx)
517	ret
518
519	ALIGN_TEXT
520fusufault:
521	movl	_curpcb,%ecx
522	xorl	%eax,%eax
523	movl	%eax,PCB_ONFAULT(%ecx)
524	decl	%eax
525	ret
526
527/*
528 * su{byte,sword,word}: write a byte (word, longword) to user memory
529 */
530ENTRY(suword)
531	movl	_curpcb,%ecx
532	movl	$fusufault,PCB_ONFAULT(%ecx)
533	movl	4(%esp),%edx
534
535#if defined(I386_CPU)
536
537#if defined(I486_CPU) || defined(I586_CPU)
538	cmpl	$CPUCLASS_386,_cpu_class
539	jne	2f				/* we only have to set the right segment selector */
540#endif /* I486_CPU || I586_CPU */
541
542	/* XXX - page boundary crossing is still not handled */
543	movl	%edx,%eax
544	shrl	$IDXSHIFT,%edx
545	andb	$0xfc,%dl
546	movb	_PTmap(%edx),%dl
547	andb	$0x7,%dl			/* must be VALID + USERACC + WRITE */
548	cmpb	$0x7,%dl
549	je	1f
550
551	/* simulate a trap */
552	pushl	%eax
553	call	_trapwrite
554	popl	%edx				/* remove junk parameter from stack */
555	movl	_curpcb,%ecx			/* restore trashed register */
556	testl	%eax,%eax
557	jnz	fusufault
5581:
559	movl	4(%esp),%edx
560#endif
561
5622:
563	cmpl	$VM_MAXUSER_ADDRESS-4,%edx	/* verify address validity */
564	ja	fusufault
565
566	movl	8(%esp),%eax
567	movl	%eax,(%edx)
568	xorl	%eax,%eax
569	movl	%eax,PCB_ONFAULT(%ecx)
570	ret
571
572ENTRY(susword)
573	movl	_curpcb,%ecx
574	movl	$fusufault,PCB_ONFAULT(%ecx)
575	movl	4(%esp),%edx
576
577#if defined(I386_CPU)
578
579#if defined(I486_CPU) || defined(I586_CPU)
580	cmpl	$CPUCLASS_386,_cpu_class
581	jne	2f
582#endif /* I486_CPU || I586_CPU */
583
584	/* XXX - page boundary crossing is still not handled */
585	movl	%edx,%eax
586	shrl	$IDXSHIFT,%edx
587	andb	$0xfc,%dl
588	movb	_PTmap(%edx),%dl
589	andb	$0x7,%dl			/* must be VALID + USERACC + WRITE */
590	cmpb	$0x7,%dl
591	je	1f
592
593	/* simulate a trap */
594	pushl	%eax
595	call	_trapwrite
596	popl	%edx				/* remove junk parameter from stack */
597	movl	_curpcb,%ecx			/* restore trashed register */
598	testl	%eax,%eax
599	jnz	fusufault
6001:
601	movl	4(%esp),%edx
602#endif
603
6042:
605	cmpl	$VM_MAXUSER_ADDRESS-2,%edx	/* verify address validity */
606	ja	fusufault
607
608	movw	8(%esp),%ax
609	movw	%ax,(%edx)
610	xorl	%eax,%eax
611	movl	%eax,PCB_ONFAULT(%ecx)
612	ret
613
614ALTENTRY(suibyte)
615ENTRY(subyte)
616	movl	_curpcb,%ecx
617	movl	$fusufault,PCB_ONFAULT(%ecx)
618	movl	4(%esp),%edx
619
620#if defined(I386_CPU)
621
622#if defined(I486_CPU) || defined(I586_CPU)
623	cmpl	$CPUCLASS_386,_cpu_class
624	jne	2f
625#endif /* I486_CPU || I586_CPU */
626
627	movl	%edx,%eax
628	shrl	$IDXSHIFT,%edx
629	andb	$0xfc,%dl
630	movb	_PTmap(%edx),%dl
631	andb	$0x7,%dl			/* must be VALID + USERACC + WRITE */
632	cmpb	$0x7,%dl
633	je	1f
634
635	/* simulate a trap */
636	pushl	%eax
637	call	_trapwrite
638	popl	%edx				/* remove junk parameter from stack */
639	movl	_curpcb,%ecx			/* restore trashed register */
640	testl	%eax,%eax
641	jnz	fusufault
6421:
643	movl	4(%esp),%edx
644#endif
645
6462:
647	cmpl	$VM_MAXUSER_ADDRESS-1,%edx	/* verify address validity */
648	ja	fusufault
649
650	movb	8(%esp),%al
651	movb	%al,(%edx)
652	xorl	%eax,%eax
653	movl	%eax,PCB_ONFAULT(%ecx)
654	ret
655
656/*
657 * copyinstr(from, to, maxlen, int *lencopied)
658 *	copy a string from from to to, stop when a 0 character is reached.
659 *	return ENAMETOOLONG if string is longer than maxlen, and
660 *	EFAULT on protection violations. If lencopied is non-zero,
661 *	return the actual length in *lencopied.
662 */
663ENTRY(copyinstr)
664	pushl	%esi
665	pushl	%edi
666	movl	_curpcb,%ecx
667	movl	$cpystrflt,PCB_ONFAULT(%ecx)
668
669	movl	12(%esp),%esi			/* %esi = from */
670	movl	16(%esp),%edi			/* %edi = to */
671	movl	20(%esp),%edx			/* %edx = maxlen */
672
673	movl	$VM_MAXUSER_ADDRESS,%eax
674
675	/* make sure 'from' is within bounds */
676	subl	%esi,%eax
677	jbe	cpystrflt
678
679	/* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
680	cmpl	%edx,%eax
681	jae	1f
682	movl	%eax,%edx
683	movl	%eax,20(%esp)
6841:
685	incl	%edx
686	cld
687
6882:
689	decl	%edx
690	jz	3f
691
692	lodsb
693	stosb
694	orb	%al,%al
695	jnz	2b
696
697	/* Success -- 0 byte reached */
698	decl	%edx
699	xorl	%eax,%eax
700	jmp	cpystrflt_x
7013:
702	/* edx is zero - return ENAMETOOLONG or EFAULT */
703	cmpl	$VM_MAXUSER_ADDRESS,%esi
704	jae	cpystrflt
7054:
706	movl	$ENAMETOOLONG,%eax
707	jmp	cpystrflt_x
708
709cpystrflt:
710	movl	$EFAULT,%eax
711
712cpystrflt_x:
713	/* set *lencopied and return %eax */
714	movl	_curpcb,%ecx
715	movl	$0,PCB_ONFAULT(%ecx)
716	movl	20(%esp),%ecx
717	subl	%edx,%ecx
718	movl	24(%esp),%edx
719	testl	%edx,%edx
720	jz	1f
721	movl	%ecx,(%edx)
7221:
723	popl	%edi
724	popl	%esi
725	ret
726
727
728/*
729 * copystr(from, to, maxlen, int *lencopied)
730 */
731ENTRY(copystr)
732	pushl	%esi
733	pushl	%edi
734
735	movl	12(%esp),%esi			/* %esi = from */
736	movl	16(%esp),%edi			/* %edi = to */
737	movl	20(%esp),%edx			/* %edx = maxlen */
738	incl	%edx
739	cld
7401:
741	decl	%edx
742	jz	4f
743	lodsb
744	stosb
745	orb	%al,%al
746	jnz	1b
747
748	/* Success -- 0 byte reached */
749	decl	%edx
750	xorl	%eax,%eax
751	jmp	6f
7524:
753	/* edx is zero -- return ENAMETOOLONG */
754	movl	$ENAMETOOLONG,%eax
755
7566:
757	/* set *lencopied and return %eax */
758	movl	20(%esp),%ecx
759	subl	%edx,%ecx
760	movl	24(%esp),%edx
761	testl	%edx,%edx
762	jz	7f
763	movl	%ecx,(%edx)
7647:
765	popl	%edi
766	popl	%esi
767	ret
768
769ENTRY(bcmp)
770	pushl	%edi
771	pushl	%esi
772	movl	12(%esp),%edi
773	movl	16(%esp),%esi
774	movl	20(%esp),%edx
775	xorl	%eax,%eax
776
777	movl	%edx,%ecx
778	shrl	$2,%ecx
779	cld					/* compare forwards */
780	repe
781	cmpsl
782	jne	1f
783
784	movl	%edx,%ecx
785	andl	$3,%ecx
786	repe
787	cmpsb
788	je	2f
7891:
790	incl	%eax
7912:
792	popl	%esi
793	popl	%edi
794	ret
795
796
797/*
798 * Handling of special 386 registers and descriptor tables etc
799 */
800/* void lgdt(struct region_descriptor *rdp); */
801ENTRY(lgdt)
802	/* reload the descriptor table */
803	movl	4(%esp),%eax
804	lgdt	(%eax)
805
806	/* flush the prefetch q */
807	jmp	1f
808	nop
8091:
810	/* reload "stale" selectors */
811	movl	$KDSEL,%eax
812	movl	%ax,%ds
813	movl	%ax,%es
814	movl	%ax,%ss
815
816	/* reload code selector by turning return into intersegmental return */
817	movl	(%esp),%eax
818	pushl	%eax
819#	movl	$KCSEL,4(%esp)
820	movl	$8,4(%esp)
821	lret
822
823/*
824 * void lidt(struct region_descriptor *rdp);
825 */
826ENTRY(lidt)
827	movl	4(%esp),%eax
828	lidt	(%eax)
829	ret
830
831/*
832 * void lldt(u_short sel)
833 */
834ENTRY(lldt)
835	lldt	4(%esp)
836	ret
837
838/*
839 * void ltr(u_short sel)
840 */
841ENTRY(ltr)
842	ltr	4(%esp)
843	ret
844
845/* ssdtosd(*ssdp,*sdp) */
846ENTRY(ssdtosd)
847	pushl	%ebx
848	movl	8(%esp),%ecx
849	movl	8(%ecx),%ebx
850	shll	$16,%ebx
851	movl	(%ecx),%edx
852	roll	$16,%edx
853	movb	%dh,%bl
854	movb	%dl,%bh
855	rorl	$8,%ebx
856	movl	4(%ecx),%eax
857	movw	%ax,%dx
858	andl	$0xf0000,%eax
859	orl	%eax,%ebx
860	movl	12(%esp),%ecx
861	movl	%edx,(%ecx)
862	movl	%ebx,4(%ecx)
863	popl	%ebx
864	ret
865
866/* load_cr0(cr0) */
867ENTRY(load_cr0)
868	movl	4(%esp),%eax
869	movl	%eax,%cr0
870	ret
871
872/* rcr0() */
873ENTRY(rcr0)
874	movl	%cr0,%eax
875	ret
876
877/* rcr3() */
878ENTRY(rcr3)
879	movl	%cr3,%eax
880	ret
881
882/* void load_cr3(caddr_t cr3) */
883ENTRY(load_cr3)
884	movl	4(%esp),%eax
885	movl	%eax,%cr3
886	ret
887
888
889/*****************************************************************************/
890/* setjump, longjump                                                         */
891/*****************************************************************************/
892
893ENTRY(setjmp)
894	movl	4(%esp),%eax
895	movl	%ebx,(%eax)			/* save ebx */
896	movl	%esp,4(%eax)			/* save esp */
897	movl	%ebp,8(%eax)			/* save ebp */
898	movl	%esi,12(%eax)			/* save esi */
899	movl	%edi,16(%eax)			/* save edi */
900	movl	(%esp),%edx			/* get rta */
901	movl	%edx,20(%eax)			/* save eip */
902	xorl	%eax,%eax			/* return(0); */
903	ret
904
905ENTRY(longjmp)
906	movl	4(%esp),%eax
907	movl	(%eax),%ebx			/* restore ebx */
908	movl	4(%eax),%esp			/* restore esp */
909	movl	8(%eax),%ebp			/* restore ebp */
910	movl	12(%eax),%esi			/* restore esi */
911	movl	16(%eax),%edi			/* restore edi */
912	movl	20(%eax),%edx			/* get rta */
913	movl	%edx,(%esp)			/* put in return frame */
914	xorl	%eax,%eax			/* return(1); */
915	incl	%eax
916	ret
917
918/*
919 * Here for doing BB-profiling (gcc -a).
920 * We rely on the "bbset" instead, but need a dummy function.
921 */
922	.text
923	.align 2
924.globl	___bb_init_func
925___bb_init_func:
926        movl 4(%esp),%eax
927        movl $1,(%eax)
928        ret
929
930/*
931 * Pull in everything in libkern for LKM's
932 */
933
934.globl	___umoddi3
935.globl	___moddi3
936.globl	___udivdi3
937.globl	___divdi3
938.globl	_inet_ntoa
939.globl	_random
940.globl	_scanc
941.globl	_skpc
942.globl	_strcat
943.globl	_strncmp
944.globl	_strncpy
945.globl	_strcmp
946.globl	_strcpy
947.globl	___qdivrem
948