locore.s revision 134
14Srgrimes/*-
24Srgrimes * Copyright (c) 1990 The Regents of the University of California.
34Srgrimes * All rights reserved.
44Srgrimes *
54Srgrimes * This code is derived from software contributed to Berkeley by
64Srgrimes * William Jolitz.
74Srgrimes *
84Srgrimes * Redistribution and use in source and binary forms, with or without
94Srgrimes * modification, are permitted provided that the following conditions
104Srgrimes * are met:
114Srgrimes * 1. Redistributions of source code must retain the above copyright
124Srgrimes *    notice, this list of conditions and the following disclaimer.
134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
144Srgrimes *    notice, this list of conditions and the following disclaimer in the
154Srgrimes *    documentation and/or other materials provided with the distribution.
164Srgrimes * 3. All advertising materials mentioning features or use of this software
174Srgrimes *    must display the following acknowledgement:
184Srgrimes *	This product includes software developed by the University of
194Srgrimes *	California, Berkeley and its contributors.
204Srgrimes * 4. Neither the name of the University nor the names of its contributors
214Srgrimes *    may be used to endorse or promote products derived from this software
224Srgrimes *    without specific prior written permission.
234Srgrimes *
244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
274Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344Srgrimes * SUCH DAMAGE.
354Srgrimes *
364Srgrimes *	@(#)locore.s	7.3 (Berkeley) 5/13/91
374Srgrimes *
384Srgrimes * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
394Srgrimes * --------------------         -----   ----------------------
404Srgrimes * CURRENT PATCH LEVEL:         5       00158
414Srgrimes * --------------------         -----   ----------------------
424Srgrimes *
434Srgrimes * 06 Aug 92	Pace Willisson		Allow VGA memory to be mapped
444Srgrimes * 28 Nov 92	Frank MacLachlan	Aligned addresses and data
454Srgrimes *					on 32bit boundaries.
464Srgrimes * 25 Mar 93	Kevin Lahey		Add syscall counter for vmstat
474Srgrimes * 20 Apr 93	Bruce Evans		New npx-0.5 code
484Srgrimes * 25 Apr 93	Bruce Evans		Support new interrupt code (intr-0.1)
494Srgrimes */
504Srgrimes
514Srgrimes
524Srgrimes/*
534Srgrimes * locore.s:	4BSD machine support for the Intel 386
544Srgrimes *		Preliminary version
554Srgrimes *		Written by William F. Jolitz, 386BSD Project
564Srgrimes */
574Srgrimes
584Srgrimes#include "assym.s"
594Srgrimes#include "machine/psl.h"
604Srgrimes#include "machine/pte.h"
614Srgrimes
624Srgrimes#include "errno.h"
634Srgrimes
644Srgrimes#include "machine/trap.h"
654Srgrimes
664Srgrimes#include "machine/specialreg.h"
674Srgrimes#include "i386/isa/debug.h"
684Srgrimes
694Srgrimes#define	KDSEL		0x10
704Srgrimes#define	SEL_RPL_MASK	0x0003
714Srgrimes#define	TRAPF_CS_OFF	(13 * 4)
724Srgrimes
734Srgrimes/*
744Srgrimes * Note: This version greatly munged to avoid various assembler errors
754Srgrimes * that may be fixed in newer versions of gas. Perhaps newer versions
764Srgrimes * will have more pleasant appearance.
774Srgrimes */
784Srgrimes
794Srgrimes	.set	IDXSHIFT,10
804Srgrimes	.set	SYSTEM,0xFE000000	# virtual address of system start
814Srgrimes	/*note: gas copys sign bit (e.g. arithmetic >>), can't do SYSTEM>>22! */
824Srgrimes	.set	SYSPDROFF,0x3F8		# Page dir index of System Base
834Srgrimes
84134Sdg
85134Sdg/*
86134Sdg * Macros
87134Sdg */
884Srgrimes#define	ALIGN_DATA	.align	2
894Srgrimes#define	ALIGN_TEXT	.align	2,0x90	/* 4-byte boundaries, NOP-filled */
904Srgrimes#define	SUPERALIGN_TEXT	.align	4,0x90	/* 16-byte boundaries better for 486 */
914Srgrimes
92134Sdg#define	LENTRY(name)		ALIGN_TEXT; .globl name; name:
93134Sdg#define	ENTRY(name)		ALIGN_TEXT; .globl _/**/name; _/**/name:
94134Sdg#define	ALTENTRY(name)		.globl _/**/name; _/**/name:
95134Sdg
964Srgrimes/* NB: NOP now preserves registers so NOPs can be inserted anywhere */
974Srgrimes/* XXX: NOP and FASTER_NOP are misleadingly named */
984Srgrimes#ifdef BROKEN_HARDWARE_AND_OR_SOFTWARE /* XXX - rarely necessary */
994Srgrimes#define	FASTER_NOP	pushl %eax ; inb $0x84,%al ; popl %eax
1004Srgrimes#define	NOP	pushl %eax ; inb $0x84,%al ; inb $0x84,%al ; popl %eax
1014Srgrimes#else
1024Srgrimes#define	FASTER_NOP
1034Srgrimes#define	NOP
1044Srgrimes#endif
1054Srgrimes
1064Srgrimes/*
1074Srgrimes * PTmap is recursive pagemap at top of virtual address space.
1084Srgrimes * Within PTmap, the page directory can be found (third indirection).
1094Srgrimes */
1104Srgrimes	.set	PDRPDROFF,0x3F7		# Page dir index of Page dir
1114Srgrimes	.globl	_PTmap, _PTD, _PTDpde, _Sysmap
1124Srgrimes	.set	_PTmap,0xFDC00000
1134Srgrimes	.set	_PTD,0xFDFF7000
1144Srgrimes	.set	_Sysmap,0xFDFF8000
1154Srgrimes	.set	_PTDpde,0xFDFF7000+4*PDRPDROFF
1164Srgrimes
1174Srgrimes/*
1184Srgrimes * APTmap, APTD is the alternate recursive pagemap.
1194Srgrimes * It's used when modifying another process's page tables.
1204Srgrimes */
1214Srgrimes	.set	APDRPDROFF,0x3FE		# Page dir index of Page dir
1224Srgrimes	.globl	_APTmap, _APTD, _APTDpde
1234Srgrimes	.set	_APTmap,0xFF800000
1244Srgrimes	.set	_APTD,0xFFBFE000
1254Srgrimes	.set	_APTDpde,0xFDFF7000+4*APDRPDROFF
1264Srgrimes
1274Srgrimes/*
1284Srgrimes * Access to each processes kernel stack is via a region of
1294Srgrimes * per-process address space (at the beginning), immediatly above
1304Srgrimes * the user process stack.
1314Srgrimes */
132134Sdg	.globl	_kstack
1334Srgrimes	.set	_kstack, USRSTACK
1344Srgrimes	.set	PPDROFF,0x3F6
1354Srgrimes	.set	PPTEOFF,0x400-UPAGES	# 0x3FE
1364Srgrimes
1374Srgrimes
138134Sdg/*****************************************************************************/
139134Sdg/* Globals                                                                   */
140134Sdg/*****************************************************************************/
141134Sdg
1424Srgrimes	.data
143134Sdg	.globl	_boothowto, _bootdev, _curpcb
144134Sdg	.globl	__ucodesel,__udatasel
145134Sdg
146134Sdg	.globl	_cpu, _cold, _atdevbase, _atdevphys
1474Srgrimes_cpu:	.long	0		# are we 386, 386sx, or 486
1484Srgrimes_cold:	.long	1		# cold till we are not
1494Srgrimes_atdevbase:	.long	0	# location of start of iomem in virtual
1504Srgrimes_atdevphys:	.long	0	# location of device mapping ptes (phys)
1514Srgrimes
1524Srgrimes	.globl	_IdlePTD, _KPTphys
1534Srgrimes_IdlePTD:	.long	0
1544Srgrimes_KPTphys:	.long	0
1554Srgrimes
156134Sdg	.globl	_cyloffset, _proc0paddr
157134Sdg_cyloffset:	.long	0
158134Sdg_proc0paddr:	.long	0
159134Sdg
160134Sdg#ifdef SHOW_A_LOT
161134Sdgbit_colors:	.byte	GREEN,RED,0,0
162134Sdg#endif
163134Sdg
1644Srgrimes	.space 512
1654Srgrimestmpstk:
166134Sdg
167134Sdg
1684Srgrimes	.text
169134Sdg/*****************************************************************************/
170134Sdg/* System Initialisation                                                     */
171134Sdg/*****************************************************************************/
172134Sdg
173134Sdg/*
174134Sdg * start: jumped to directly from the boot blocks
175134Sdg */
176134SdgLENTRY(start)
177134Sdg	movw	$0x1234,%ax
1784Srgrimes	movw	%ax,0x472	# warm boot
1794Srgrimes	jmp	1f
1804Srgrimes	.space	0x500		# skip over warm boot shit
1814Srgrimes
1824Srgrimes	/*
1834Srgrimes	 * pass parameters on stack (howto, bootdev, unit, cyloffset)
1844Srgrimes	 * note: (%esp) is return address of boot
1854Srgrimes	 * ( if we want to hold onto /boot, it's physical %esp up to _end)
1864Srgrimes	 */
1874Srgrimes
1884Srgrimes 1:	movl	4(%esp),%eax
1894Srgrimes	movl	%eax,_boothowto-SYSTEM
1904Srgrimes	movl	8(%esp),%eax
1914Srgrimes	movl	%eax,_bootdev-SYSTEM
1924Srgrimes	movl	12(%esp),%eax
1934Srgrimes	movl	%eax, _cyloffset-SYSTEM
1944Srgrimes
1954Srgrimes	/*
1964Srgrimes	 * Finished with old stack; load new %esp now instead of later so
1974Srgrimes	 * we can trace this code without having to worry about the trace
1984Srgrimes	 * trap clobbering the memory test or the zeroing of the bss+bootstrap
1994Srgrimes	 * page tables.
2004Srgrimes	 *
2014Srgrimes	 * XXX - wdboot clears the bss after testing that this is safe.
2024Srgrimes	 * This is too wasteful - memory below 640K is scarce.  The boot
2034Srgrimes	 * program should check:
2044Srgrimes	 *	text+data <= &stack_variable - more_space_for_stack
2054Srgrimes	 *	text+data+bss+pad+space_for_page_tables <= end_of_memory
2064Srgrimes	 * Oops, the gdt is in the carcass of the boot program so clearing
2074Srgrimes	 * the rest of memory is still not possible.
2084Srgrimes	 */
2094Srgrimes	movl	$ tmpstk-SYSTEM,%esp	# bootstrap stack end location
2104Srgrimes
2114Srgrimes#ifdef garbage
2124Srgrimes	/* count up memory */
2134Srgrimes
2144Srgrimes	xorl	%eax,%eax		# start with base memory at 0x0
2154Srgrimes	#movl	$ 0xA0000/NBPG,%ecx	# look every 4K up to 640K
2164Srgrimes	movl	$ 0xA0,%ecx		# look every 4K up to 640K
2174Srgrimes1:	movl	(%eax),%ebx		# save location to check
2184Srgrimes	movl	$0xa55a5aa5,(%eax)	# write test pattern
2194Srgrimes	/* flush stupid cache here! (with bcopy (0,0,512*1024) ) */
2204Srgrimes	cmpl	$0xa55a5aa5,(%eax)	# does not check yet for rollover
2214Srgrimes	jne	2f
2224Srgrimes	movl	%ebx,(%eax)		# restore memory
2234Srgrimes	addl	$ NBPG,%eax
2244Srgrimes	loop	1b
2254Srgrimes2:	shrl	$12,%eax
2264Srgrimes	movl	%eax,_Maxmem-SYSTEM
2274Srgrimes
2284Srgrimes	movl	$0x100000,%eax		# next, talley remaining memory
2294Srgrimes	#movl	$((0xFFF000-0x100000)/NBPG),%ecx
2304Srgrimes	movl	$(0xFFF-0x100),%ecx
2314Srgrimes1:	movl	(%eax),%ebx		# save location to check
2324Srgrimes	movl	$0xa55a5aa5,(%eax)	# write test pattern
2334Srgrimes	cmpl	$0xa55a5aa5,(%eax)	# does not check yet for rollover
2344Srgrimes	jne	2f
2354Srgrimes	movl	%ebx,(%eax)		# restore memory
2364Srgrimes	addl	$ NBPG,%eax
2374Srgrimes	loop	1b
2384Srgrimes2:	shrl	$12,%eax
2394Srgrimes	movl	%eax,_Maxmem-SYSTEM
2404Srgrimes#endif
2414Srgrimes
2424Srgrimes/* find end of kernel image */
2434Srgrimes	movl	$_end-SYSTEM,%ecx
2444Srgrimes	addl	$ NBPG-1,%ecx
2454Srgrimes	andl	$~(NBPG-1),%ecx
2464Srgrimes	movl	%ecx,%esi
2474Srgrimes
2484Srgrimes/* clear bss and memory for bootstrap pagetables. */
2494Srgrimes	movl	$_edata-SYSTEM,%edi
2504Srgrimes	subl	%edi,%ecx
2514Srgrimes	addl	$(UPAGES+5)*NBPG,%ecx
2524Srgrimes/*
2534Srgrimes * Virtual address space of kernel:
2544Srgrimes *
2554Srgrimes *	text | data | bss | page dir | proc0 kernel stack | usr stk map | Sysmap
2564Srgrimes *			     0               1       2       3             4
2574Srgrimes */
2584Srgrimes	xorl	%eax,%eax	# pattern
2594Srgrimes	cld
2604Srgrimes	rep
2614Srgrimes	stosb
2624Srgrimes
2634Srgrimes	movl	%esi,_IdlePTD-SYSTEM /*physical address of Idle Address space */
2644Srgrimes
2654Srgrimes#define	fillkpt		\
2664Srgrimes1:	movl	%eax,(%ebx)	; \
2674Srgrimes	addl	$ NBPG,%eax	; /* increment physical address */ \
2684Srgrimes	addl	$4,%ebx		; /* next pte */ \
2694Srgrimes	loop	1b		;
2704Srgrimes
2714Srgrimes/*
2724Srgrimes * Map Kernel
2734Srgrimes * N.B. don't bother with making kernel text RO, as 386
2744Srgrimes * ignores R/W AND U/S bits on kernel access (only v works) !
2754Srgrimes *
2764Srgrimes * First step - build page tables
2774Srgrimes */
2784Srgrimes	movl	%esi,%ecx		# this much memory,
2794Srgrimes	shrl	$ PGSHIFT,%ecx		# for this many pte s
2804Srgrimes	addl	$ UPAGES+4,%ecx		# including our early context
2814Srgrimes	movl	$0xa0,%ecx		# XXX - cover debugger pages
2824Srgrimes	movl	$PG_V|PG_KW,%eax	#  having these bits set,
2834Srgrimes	lea	(4*NBPG)(%esi),%ebx	#   physical address of KPT in proc 0,
2844Srgrimes	movl	%ebx,_KPTphys-SYSTEM	#    in the kernel page table,
2854Srgrimes	fillkpt
2864Srgrimes
2874Srgrimes/* map I/O memory map */
2884Srgrimes
2894Srgrimes	movl	$0x100-0xa0,%ecx	# for this many pte s,
2904Srgrimes	movl	$(0xa0000|PG_V|PG_UW),%eax # having these bits set,(perhaps URW?) XXX 06 Aug 92
2914Srgrimes	movl	%ebx,_atdevphys-SYSTEM	#   remember phys addr of ptes
2924Srgrimes	fillkpt
2934Srgrimes
2944Srgrimes /* map proc 0's kernel stack into user page table page */
2954Srgrimes
2964Srgrimes	movl	$ UPAGES,%ecx		# for this many pte s,
2974Srgrimes	lea	(1*NBPG)(%esi),%eax	# physical address in proc 0
2984Srgrimes	lea	(SYSTEM)(%eax),%edx
2994Srgrimes	movl	%edx,_proc0paddr-SYSTEM  # remember VA for 0th process init
3004Srgrimes	orl	$PG_V|PG_KW,%eax	#  having these bits set,
3014Srgrimes	lea	(3*NBPG)(%esi),%ebx	# physical address of stack pt in proc 0
3024Srgrimes	addl	$(PPTEOFF*4),%ebx
3034Srgrimes	fillkpt
3044Srgrimes
3054Srgrimes/*
3064Srgrimes * Construct a page table directory
3074Srgrimes * (of page directory elements - pde's)
3084Srgrimes */
3094Srgrimes	/* install a pde for temporary double map of bottom of VA */
3104Srgrimes	lea	(4*NBPG)(%esi),%eax	# physical address of kernel page table
3114Srgrimes	orl     $ PG_V|PG_UW,%eax	# pde entry is valid XXX 06 Aug 92
3124Srgrimes	movl	%eax,(%esi)		# which is where temp maps!
3134Srgrimes
3144Srgrimes	/* kernel pde's */
3154Srgrimes	movl	$ 3,%ecx		# for this many pde s,
3164Srgrimes	lea	(SYSPDROFF*4)(%esi), %ebx	# offset of pde for kernel
3174Srgrimes	fillkpt
3184Srgrimes
3194Srgrimes	/* install a pde recursively mapping page directory as a page table! */
3204Srgrimes	movl	%esi,%eax		# phys address of ptd in proc 0
3214Srgrimes	orl	$ PG_V|PG_UW,%eax	# pde entry is valid XXX 06 Aug 92
3224Srgrimes	movl	%eax, PDRPDROFF*4(%esi)	# which is where PTmap maps!
3234Srgrimes
3244Srgrimes	/* install a pde to map kernel stack for proc 0 */
3254Srgrimes	lea	(3*NBPG)(%esi),%eax	# physical address of pt in proc 0
3264Srgrimes	orl	$PG_V|PG_KW,%eax	# pde entry is valid
3274Srgrimes	movl	%eax,PPDROFF*4(%esi)	# which is where kernel stack maps!
3284Srgrimes
3294Srgrimes	/* copy and convert stuff from old gdt and idt for debugger */
3304Srgrimes
3314Srgrimes	cmpl	$0x0375c339,0x96104	# XXX - debugger signature
3324Srgrimes	jne	1f
3334Srgrimes	movb	$1,_bdb_exists-SYSTEM
3344Srgrimes1:
3354Srgrimes	pushal
3364Srgrimes	subl	$2*6,%esp
3374Srgrimes
3384Srgrimes	sgdt	(%esp)
3394Srgrimes	movl	2(%esp),%esi		# base address of current gdt
3404Srgrimes	movl	$_gdt-SYSTEM,%edi
3414Srgrimes	movl	%edi,2(%esp)
3424Srgrimes	movl	$8*18/4,%ecx
3434Srgrimes	rep				# copy gdt
3444Srgrimes	movsl
3454Srgrimes	movl	$_gdt-SYSTEM,-8+2(%edi)	# adjust gdt self-ptr
3464Srgrimes	movb	$0x92,-8+5(%edi)
3474Srgrimes
3484Srgrimes	sidt	6(%esp)
3494Srgrimes	movl	6+2(%esp),%esi		# base address of current idt
3504Srgrimes	movl	8+4(%esi),%eax		# convert dbg descriptor to ...
3514Srgrimes	movw	8(%esi),%ax
3524Srgrimes	movl	%eax,bdb_dbg_ljmp+1-SYSTEM	# ... immediate offset ...
3534Srgrimes	movl	8+2(%esi),%eax
3544Srgrimes	movw	%ax,bdb_dbg_ljmp+5-SYSTEM	# ... and selector for ljmp
3554Srgrimes	movl	24+4(%esi),%eax		# same for bpt descriptor
3564Srgrimes	movw	24(%esi),%ax
3574Srgrimes	movl	%eax,bdb_bpt_ljmp+1-SYSTEM
3584Srgrimes	movl	24+2(%esi),%eax
3594Srgrimes	movw	%ax,bdb_bpt_ljmp+5-SYSTEM
3604Srgrimes
3614Srgrimes	movl	$_idt-SYSTEM,%edi
3624Srgrimes	movl	%edi,6+2(%esp)
3634Srgrimes	movl	$8*4/4,%ecx
3644Srgrimes	rep				# copy idt
3654Srgrimes	movsl
3664Srgrimes
3674Srgrimes	lgdt	(%esp)
3684Srgrimes	lidt	6(%esp)
3694Srgrimes
3704Srgrimes	addl	$2*6,%esp
3714Srgrimes	popal
3724Srgrimes
3734Srgrimes	/* load base of page directory, and enable mapping */
3744Srgrimes	movl	%esi,%eax		# phys address of ptd in proc 0
3754Srgrimes 	orl	$ I386_CR3PAT,%eax
3764Srgrimes	movl	%eax,%cr3		# load ptd addr into mmu
3774Srgrimes	movl	%cr0,%eax		# get control word
3784Srgrimes#ifdef USE_486_WRITE_PROTECT
3794Srgrimes	orl	$CR0_PE|CR0_PG|CR0_WP,%eax	# and let s page!
3804Srgrimes#else
3814Srgrimes	orl	$CR0_PE|CR0_PG,%eax	# and let s page!
3824Srgrimes#endif
3834Srgrimes	movl	%eax,%cr0		# NOW!
3844Srgrimes
3854Srgrimes	pushl	$begin				# jump to high mem!
3864Srgrimes	ret
3874Srgrimes
3884Srgrimesbegin: /* now running relocated at SYSTEM where the system is linked to run */
3894Srgrimes
390134Sdg	.globl _Crtat			# XXX - locore should not know about
391134Sdg	movl	_Crtat,%eax		# variables of device drivers (pccons)!
3924Srgrimes	subl	$0xfe0a0000,%eax
3934Srgrimes	movl	_atdevphys,%edx	# get pte PA
3944Srgrimes	subl	_KPTphys,%edx	# remove base of ptes, now have phys offset
3954Srgrimes	shll	$ PGSHIFT-2,%edx  # corresponding to virt offset
3964Srgrimes	addl	$ SYSTEM,%edx	# add virtual base
3974Srgrimes	movl	%edx, _atdevbase
3984Srgrimes	addl	%eax,%edx
3994Srgrimes	movl	%edx,_Crtat
4004Srgrimes
4014Srgrimes	/* set up bootstrap stack */
4024Srgrimes	movl	$ _kstack+UPAGES*NBPG-4*12,%esp	# bootstrap stack end location
4034Srgrimes	xorl	%eax,%eax		# mark end of frames
4044Srgrimes	movl	%eax,%ebp
4054Srgrimes	movl	_proc0paddr, %eax
4064Srgrimes	movl	%esi, PCB_CR3(%eax)
4074Srgrimes
4084Srgrimes	lea	7*NBPG(%esi),%esi	# skip past stack.
4094Srgrimes	pushl	%esi
4104Srgrimes
4114Srgrimes	/* relocate debugger gdt entries */
4124Srgrimes
4134Srgrimes	movl	$_gdt+8*9,%eax		# adjust slots 9-17
4144Srgrimes	movl	$9,%ecx
4154Srgrimesreloc_gdt:
4164Srgrimes	movb	$0xfe,7(%eax)		# top byte of base addresses, was 0,
4174Srgrimes	addl	$8,%eax			# now SYSTEM>>24
4184Srgrimes	loop	reloc_gdt
4194Srgrimes
4204Srgrimes	cmpl	$0,_bdb_exists
4214Srgrimes	je	1f
4224Srgrimes	int	$3
4234Srgrimes1:
4244Srgrimes
4254Srgrimes	call	_init386		# wire 386 chip for unix operation
4264Srgrimes
4274Srgrimes	movl	$0,_PTD
428134Sdg	call 	_main			# autoconfiguration, mountroot etc
4294Srgrimes	popl	%esi
4304Srgrimes
431134Sdg	/*
432134Sdg	 * on return from main(), we are process 1
433134Sdg	 * set up address space and stack so that we can 'return' to user mode
434134Sdg	 */
435134Sdg
4364Srgrimes	movl	__ucodesel,%eax
4374Srgrimes	movl	__udatasel,%ecx
4384Srgrimes	# build outer stack frame
4394Srgrimes	pushl	%ecx		# user ss
4404Srgrimes	pushl	$ USRSTACK	# user esp
4414Srgrimes	pushl	%eax		# user cs
4424Srgrimes	pushl	$0		# user ip
4434Srgrimes	movl	%cx,%ds
4444Srgrimes	movl	%cx,%es
4454Srgrimes	movl	%ax,%fs		# double map cs to fs
4464Srgrimes	movl	%cx,%gs		# and ds to gs
4474Srgrimes	lret	# goto user!
4484Srgrimes
4494Srgrimes	pushl	$lretmsg1	/* "should never get here!" */
4504Srgrimes	call	_panic
4514Srgrimeslretmsg1:
4524Srgrimes	.asciz	"lret: toinit\n"
4534Srgrimes
4544Srgrimes
4554Srgrimes	.set	exec,59
4564Srgrimes	.set	exit,1
4574Srgrimes
4584Srgrimes#define	LCALL(x,y)	.byte 0x9a ; .long y; .word x
4594Srgrimes/*
460134Sdg * Icode is copied out to process 1 and executed in user mode:
461134Sdg *	execve("/sbin/init", argv, envp); exit(0);
462134Sdg * If the exec fails, process 1 exits and the system panics.
4634Srgrimes */
4644SrgrimesENTRY(icode)
4654Srgrimes	# pushl	$argv-_icode	# gas fucks up again
4664Srgrimes	movl	$argv,%eax
4674Srgrimes	subl	$_icode,%eax
4684Srgrimes	pushl	%eax
4694Srgrimes
4704Srgrimes	# pushl	$init-_icode
4714Srgrimes	movl	$init,%eax
4724Srgrimes	subl	$_icode,%eax
4734Srgrimes	pushl	%eax
4744Srgrimes	pushl	%eax	# dummy out rta
4754Srgrimes
4764Srgrimes	movl	%esp,%ebp
4774Srgrimes	movl	$exec,%eax
4784Srgrimes	LCALL(0x7,0x0)
4794Srgrimes	pushl	%eax
4804Srgrimes	movl	$exit,%eax
4814Srgrimes	pushl	%eax	# dummy out rta
4824Srgrimes	LCALL(0x7,0x0)
4834Srgrimes
4844Srgrimesinit:
4854Srgrimes	.asciz	"/sbin/init"
4864Srgrimes	ALIGN_DATA
4874Srgrimesargv:
4884Srgrimes	.long	init+6-_icode		# argv[0] = "init" ("/sbin/init" + 6)
4894Srgrimes	.long	eicode-_icode		# argv[1] follows icode after copyout
4904Srgrimes	.long	0
4914Srgrimeseicode:
4924Srgrimes
4934Srgrimes	.globl	_szicode
4944Srgrimes_szicode:
4954Srgrimes	.long	_szicode-_icode
4964Srgrimes
4974SrgrimesENTRY(sigcode)
4984Srgrimes	call	12(%esp)
4994Srgrimes	lea	28(%esp),%eax	# scp (the call may have clobbered the
5004Srgrimes				# copy at 8(%esp))
5014Srgrimes				# XXX - use genassym
5024Srgrimes	pushl	%eax
5034Srgrimes	pushl	%eax		# junk to fake return address
5044Srgrimes	movl	$103,%eax	# sigreturn()
5054Srgrimes	LCALL(0x7,0)		# enter kernel with args on stack
5064Srgrimes	hlt			# never gets here
5074Srgrimes
5084Srgrimes	.globl	_szsigcode
5094Srgrimes_szsigcode:
5104Srgrimes	.long	_szsigcode-_sigcode
5114Srgrimes
512134Sdg
513134Sdg/*****************************************************************************/
514134Sdg/* support routines for GCC, general C-callable functions                    */
515134Sdg/*****************************************************************************/
516134Sdg
5174SrgrimesENTRY(__udivsi3)
5184Srgrimes	movl 4(%esp),%eax
5194Srgrimes	xorl %edx,%edx
5204Srgrimes	divl 8(%esp)
5214Srgrimes	ret
5224Srgrimes
5234SrgrimesENTRY(__divsi3)
5244Srgrimes	movl 4(%esp),%eax
5254Srgrimes	cltd
5264Srgrimes	idivl 8(%esp)
5274Srgrimes	ret
5284Srgrimes
529134Sdg
5304Srgrimes	/*
5314Srgrimes	 * I/O bus instructions via C
5324Srgrimes	 */
533134SdgENTRY(outb)				# outb (port, val)
5344Srgrimes	movl	4(%esp),%edx
535134Sdg	NOP
536134Sdg	movl	8(%esp),%eax
537134Sdg	outb	%al,%dx
538134Sdg	NOP
539134Sdg	ret
540134Sdg
541134Sdg
542134SdgENTRY(outw)				# outw (port, val)
543134Sdg	movl	4(%esp),%edx
544134Sdg	NOP
545134Sdg	movl	8(%esp),%eax
546134Sdg	outw	%ax,%dx
547134Sdg	NOP
548134Sdg	ret
549134Sdg
550134Sdg
551134SdgENTRY(outsb)			# outsb(port,addr,cnt)
552134Sdg	pushl	%esi
553134Sdg	movw	8(%esp),%dx
554134Sdg	movl	12(%esp),%esi
555134Sdg	movl	16(%esp),%ecx
556134Sdg	cld
557134Sdg	NOP
558134Sdg	rep
559134Sdg	outsb
560134Sdg	NOP
561134Sdg	movl	%esi,%eax
562134Sdg	popl	%esi
563134Sdg	ret
564134Sdg
565134Sdg
566134SdgENTRY(outsw)			# outsw(port,addr,cnt)
567134Sdg	pushl	%esi
568134Sdg	movw	8(%esp),%dx
569134Sdg	movl	12(%esp),%esi
570134Sdg	movl	16(%esp),%ecx
571134Sdg	cld
572134Sdg	NOP
573134Sdg	rep
574134Sdg	outsw
575134Sdg	NOP
576134Sdg	movl	%esi,%eax
577134Sdg	popl	%esi
578134Sdg	ret
579134Sdg
580134Sdg
581134SdgENTRY(inb)			# val = inb (port)
582134Sdg	movl	4(%esp),%edx
5834Srgrimes	subl	%eax,%eax	# clr eax
5844Srgrimes	NOP
5854Srgrimes	inb	%dx,%al
5864Srgrimes	ret
5874Srgrimes
5884Srgrimes
589134SdgENTRY(inw)			# val = inw (port)
5904Srgrimes	movl	4(%esp),%edx
5914Srgrimes	subl	%eax,%eax	# clr eax
5924Srgrimes	NOP
5934Srgrimes	inw	%dx,%ax
5944Srgrimes	ret
5954Srgrimes
5964Srgrimes
597134SdgENTRY(insb)			# insb(port,addr,cnt)
598134Sdg	pushl	%edi
599134Sdg	movw	8(%esp),%dx
600134Sdg	movl	12(%esp),%edi
601134Sdg	movl	16(%esp),%ecx
602134Sdg	cld
603134Sdg	NOP
604134Sdg	rep
605134Sdg	insb
606134Sdg	NOP
607134Sdg	movl	%edi,%eax
608134Sdg	popl	%edi
609134Sdg	ret
610134Sdg
611134Sdg
612134SdgENTRY(insw)			# insw(port,addr,cnt)
613134Sdg	pushl	%edi
614134Sdg	movw	8(%esp),%dx
615134Sdg	movl	12(%esp),%edi
616134Sdg	movl	16(%esp),%ecx
617134Sdg	cld
618134Sdg	NOP
619134Sdg	rep
620134Sdg	insw
621134Sdg	NOP
622134Sdg	movl	%edi,%eax
623134Sdg	popl	%edi
624134Sdg	ret
625134Sdg
626134Sdg
6274SrgrimesENTRY(rtcin)
6284Srgrimes	movl	4(%esp),%eax
6294Srgrimes	outb	%al,$0x70
6304Srgrimes	subl	%eax,%eax	# clr eax
6314Srgrimes	inb	$0x71,%al
6324Srgrimes	ret
6334Srgrimes
6344Srgrimes
6354Srgrimes	/*
636134Sdg	 * bcopy family
6374Srgrimes	 */
638134SdgENTRY(bzero)			# void bzero(void *base, u_int cnt)
6394Srgrimes	pushl	%edi
6404Srgrimes	movl	8(%esp),%edi
6414Srgrimes	movl	12(%esp),%ecx
6424Srgrimes	xorl	%eax,%eax
6434Srgrimes	shrl	$2,%ecx
6444Srgrimes	cld
6454Srgrimes	rep
6464Srgrimes	stosl
6474Srgrimes	movl	12(%esp),%ecx
6484Srgrimes	andl	$3,%ecx
6494Srgrimes	rep
6504Srgrimes	stosb
6514Srgrimes	popl	%edi
6524Srgrimes	ret
6534Srgrimes
6544Srgrimes
655134SdgENTRY(fillw)			# fillw (pat,base,cnt)
6564Srgrimes	pushl	%edi
6574Srgrimes	movl	8(%esp),%eax
6584Srgrimes	movl	12(%esp),%edi
6594Srgrimes	movl	16(%esp),%ecx
6604Srgrimes	cld
6614Srgrimes	rep
6624Srgrimes	stosw
6634Srgrimes	popl	%edi
6644Srgrimes	ret
6654Srgrimes
6664SrgrimesENTRY(bcopyb)
6674Srgrimes	pushl	%esi
6684Srgrimes	pushl	%edi
6694Srgrimes	movl	12(%esp),%esi
6704Srgrimes	movl	16(%esp),%edi
6714Srgrimes	movl	20(%esp),%ecx
6724Srgrimes	cmpl	%esi,%edi	/* potentially overlapping? */
6734Srgrimes	jnb	1f
6744Srgrimes	cld			/* nope, copy forwards */
675134Sdg	rep
6764Srgrimes	movsb
6774Srgrimes	popl	%edi
6784Srgrimes	popl	%esi
6794Srgrimes	ret
6804Srgrimes
6814Srgrimes	ALIGN_TEXT
6824Srgrimes1:
6834Srgrimes	addl	%ecx,%edi	/* copy backwards. */
6844Srgrimes	addl	%ecx,%esi
6854Srgrimes	std
6864Srgrimes	decl	%edi
6874Srgrimes	decl	%esi
6884Srgrimes	rep
6894Srgrimes	movsb
6904Srgrimes	popl	%edi
6914Srgrimes	popl	%esi
6924Srgrimes	cld
6934Srgrimes	ret
6944Srgrimes
6954SrgrimesENTRY(bcopyw)
6964Srgrimes	pushl	%esi
6974Srgrimes	pushl	%edi
6984Srgrimes	movl	12(%esp),%esi
6994Srgrimes	movl	16(%esp),%edi
7004Srgrimes	movl	20(%esp),%ecx
7014Srgrimes	cmpl	%esi,%edi	/* potentially overlapping? */
7024Srgrimes	jnb	1f
7034Srgrimes	cld			/* nope, copy forwards */
7044Srgrimes	shrl	$1,%ecx		/* copy by 16-bit words */
7054Srgrimes	rep
7064Srgrimes	movsw
7074Srgrimes	adc	%ecx,%ecx	/* any bytes left? */
7084Srgrimes	rep
7094Srgrimes	movsb
7104Srgrimes	popl	%edi
7114Srgrimes	popl	%esi
7124Srgrimes	ret
7134Srgrimes
7144Srgrimes	ALIGN_TEXT
7154Srgrimes1:
7164Srgrimes	addl	%ecx,%edi	/* copy backwards */
7174Srgrimes	addl	%ecx,%esi
7184Srgrimes	std
7194Srgrimes	andl	$1,%ecx		/* any fractional bytes? */
7204Srgrimes	decl	%edi
7214Srgrimes	decl	%esi
7224Srgrimes	rep
7234Srgrimes	movsb
7244Srgrimes	movl	20(%esp),%ecx	/* copy remainder by 16-bit words */
7254Srgrimes	shrl	$1,%ecx
7264Srgrimes	decl	%esi
7274Srgrimes	decl	%edi
7284Srgrimes	rep
7294Srgrimes	movsw
7304Srgrimes	popl	%edi
7314Srgrimes	popl	%esi
7324Srgrimes	cld
7334Srgrimes	ret
7344Srgrimes
7354SrgrimesENTRY(bcopyx)
7364Srgrimes	movl	16(%esp),%eax
7374Srgrimes	cmpl	$2,%eax
7384Srgrimes	je	_bcopyw
7394Srgrimes	cmpl	$4,%eax
7404Srgrimes	jne	_bcopyb
7414Srgrimes	/*
7424Srgrimes	 * Fall through to bcopy.  ENTRY() provides harmless fill bytes.
7434Srgrimes	 */
7444Srgrimes
745134Sdg
7464Srgrimes	/*
7474Srgrimes	 * (ov)bcopy (src,dst,cnt)
7484Srgrimes	 *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
7494Srgrimes	 */
7504SrgrimesENTRY(bcopy)
751134SdgALTENTRY(ovbcopy)
7524Srgrimes	pushl	%esi
7534Srgrimes	pushl	%edi
7544Srgrimes	movl	12(%esp),%esi
7554Srgrimes	movl	16(%esp),%edi
7564Srgrimes	movl	20(%esp),%ecx
7574Srgrimes	cmpl	%esi,%edi	/* potentially overlapping? */
7584Srgrimes	jnb	1f
7594Srgrimes	cld			/* nope, copy forwards */
7604Srgrimes	shrl	$2,%ecx		/* copy by 32-bit words */
7614Srgrimes	rep
7624Srgrimes	movsl
7634Srgrimes	movl	20(%esp),%ecx
7644Srgrimes	andl	$3,%ecx		/* any bytes left? */
7654Srgrimes	rep
7664Srgrimes	movsb
7674Srgrimes	popl	%edi
7684Srgrimes	popl	%esi
7694Srgrimes	ret
7704Srgrimes
7714Srgrimes	ALIGN_TEXT
7724Srgrimes1:
7734Srgrimes	addl	%ecx,%edi	/* copy backwards */
7744Srgrimes	addl	%ecx,%esi
7754Srgrimes	std
7764Srgrimes	andl	$3,%ecx		/* any fractional bytes? */
7774Srgrimes	decl	%edi
7784Srgrimes	decl	%esi
7794Srgrimes	rep
7804Srgrimes	movsb
7814Srgrimes	movl	20(%esp),%ecx	/* copy remainder by 32-bit words */
7824Srgrimes	shrl	$2,%ecx
7834Srgrimes	subl	$3,%esi
7844Srgrimes	subl	$3,%edi
7854Srgrimes	rep
7864Srgrimes	movsl
7874Srgrimes	popl	%edi
7884Srgrimes	popl	%esi
7894Srgrimes	cld
7904Srgrimes	ret
7914Srgrimes
792134SdgENTRY(ntohl)
793134SdgALTENTRY(htonl)
794134Sdg	movl	4(%esp),%eax
795134Sdg#ifdef i486
796134Sdg	/* XXX */
797134Sdg	/* Since Gas 1.38 does not grok bswap this has been coded as the
798134Sdg	 * equivalent bytes.  This can be changed back to bswap when we
799134Sdg	 * upgrade to a newer version of Gas */
800134Sdg	/* bswap	%eax */
801134Sdg	.byte 	0x0f
802134Sdg	.byte	0xc8
803134Sdg#else
804134Sdg	xchgb	%al,%ah
805134Sdg	roll	$16,%eax
806134Sdg	xchgb	%al,%ah
807134Sdg#endif
808134Sdg	ret
809134Sdg
810134SdgENTRY(ntohs)
811134SdgALTENTRY(htons)
812134Sdg	movzwl	4(%esp),%eax
813134Sdg	xchgb	%al,%ah
814134Sdg	ret
815134Sdg
816134Sdg
817134Sdg#ifdef SHOW_A_LOT
818134Sdg/*
819134Sdg * 'show_bits' was too big when defined as a macro.  The line length for some
820134Sdg * enclosing macro was too big for gas.  Perhaps the code would have blown
821134Sdg * the cache anyway.
822134Sdg */
823134Sdg	ALIGN_TEXT
824134Sdgshow_bits:
825134Sdg	pushl	%eax
826134Sdg	SHOW_BIT(0)
827134Sdg	SHOW_BIT(1)
828134Sdg	SHOW_BIT(2)
829134Sdg	SHOW_BIT(3)
830134Sdg	SHOW_BIT(4)
831134Sdg	SHOW_BIT(5)
832134Sdg	SHOW_BIT(6)
833134Sdg	SHOW_BIT(7)
834134Sdg	SHOW_BIT(8)
835134Sdg	SHOW_BIT(9)
836134Sdg	SHOW_BIT(10)
837134Sdg	SHOW_BIT(11)
838134Sdg	SHOW_BIT(12)
839134Sdg	SHOW_BIT(13)
840134Sdg	SHOW_BIT(14)
841134Sdg	SHOW_BIT(15)
842134Sdg	popl	%eax
843134Sdg	ret
844134Sdg#endif /* SHOW_A_LOT */
845134Sdg
846134Sdg
847134Sdg/*****************************************************************************/
848134Sdg/* copyout and fubyte family                                                 */
849134Sdg/*****************************************************************************/
850134Sdg/*
851134Sdg * Access user memory from inside the kernel. These routines and possibly
852134Sdg * the math- and DOS emulators should be the only places that do this.
853134Sdg *
854134Sdg * We have to access the memory with user's permissions, so use a segment
855134Sdg * selector with RPL 3. For writes to user space we have to additionally
856134Sdg * check the PTE for write permission, because the 386 does not check
857134Sdg * write permissions when we are executing with EPL 0. The 486 does check
858134Sdg * this if the WP bit is set in CR0, so we can use a simpler version here.
859134Sdg *
860134Sdg * These routines set curpcb->onfault for the time they execute. When a
861134Sdg * protection violation occurs inside the functions, the trap handler
862134Sdg * returns to *curpcb->onfault instead of the function.
863134Sdg */
864134Sdg/*
865134Sdg * XXX These routines load a segment register every time they execute.
866134Sdg * it would be nicer (faster) if they could depend on %gs.
867134Sdg */
868134Sdg
869134Sdg
870134SdgENTRY(copyout)			# copyout (from_kernel, to_user, len)
8714Srgrimes	movl	_curpcb, %eax
872134Sdg	movl	$copyout_fault, PCB_ONFAULT(%eax)
8734Srgrimes	pushl	%esi
8744Srgrimes	pushl	%edi
8754Srgrimes	pushl	%ebx
8764Srgrimes	movl	16(%esp), %esi
8774Srgrimes	movl	20(%esp), %edi
8784Srgrimes	movl	24(%esp), %ebx
879134Sdg	orl	%ebx, %ebx	# nothing to do?
880134Sdg	jz	done_copyout
8814Srgrimes
882134Sdg#ifdef USE_486_WRITE_PROTECT
883134Sdg	/* if WP bit in CR0 is set (n/a on 386), the hardware does the */
884134Sdg	/* write check. We just have to load the right segment selector */
885134Sdg	pushl	%es
886134Sdg	movl	__udatasel, %eax
887134Sdg	movl	%ax, %es
888134Sdg#else /* USE_486_WRITE_PROTECT */
889134Sdg	/* we have to check each PTE for (write) permission */
8904Srgrimes
891134Sdg			/* compute number of pages */
892134Sdg	movl	%edi, %ecx
893134Sdg	andl	$0x0fff, %ecx
894134Sdg	addl	%ebx, %ecx
895134Sdg	decl	%ecx
896134Sdg	shrl	$IDXSHIFT+2, %ecx
897134Sdg	incl	%ecx
898134Sdg
899134Sdg			/* compute PTE offset for start address */
900134Sdg	movl	%edi, %edx
901134Sdg	shrl	$IDXSHIFT, %edx
902134Sdg	andb	$0xfc, %dl
903134Sdg
904134Sdg1:			/* check PTE for each page */
905134Sdg	movb	_PTmap(%edx), %al
906134Sdg	andb	$0x07, %al	/* Pages must be VALID + USERACC + WRITABLE */
907134Sdg	cmpb	$0x07, %al
908134Sdg	je	2f
909134Sdg
910134Sdg				/* simulate a trap */
911134Sdg	pushl	%edx
912134Sdg	pushl	%ecx
913134Sdg	shll	$IDXSHIFT, %edx
914134Sdg	pushl	%edx
915134Sdg	call	_trapwrite	/* XXX trapwrite(addr) */
9164Srgrimes	popl	%edx
917134Sdg	popl	%ecx
918134Sdg	popl	%edx
9194Srgrimes
920134Sdg	orl	%eax, %eax	/* if not ok, return EFAULT */
921134Sdg	jnz	copyout_fault
922134Sdg
9234Srgrimes2:
924134Sdg	addl	$4, %edx
925134Sdg	decl	%ecx
926134Sdg	jnz	1b		/* check next page */
9274Srgrimes
928134Sdg#endif /* USE_486_WRITE_PROTECT */
929134Sdg
930134Sdg			/* now copy it over */
931134Sdg			/* bcopy (%esi, %edi, %ebx) */
9324Srgrimes	cld
933134Sdg	movl	%ebx, %ecx
934134Sdg	shrl	$2, %ecx
9354Srgrimes	rep
9364Srgrimes	movsl
937134Sdg	movb	%bl, %cl
938134Sdg	andb	$3, %cl
9394Srgrimes	rep
9404Srgrimes	movsb
941134Sdg#ifdef USE_486_WRITE_PROTECT
942134Sdg	popl	%es
9434Srgrimes#endif
9444Srgrimes
945134Sdgdone_copyout:
9464Srgrimes	popl	%ebx
9474Srgrimes	popl	%edi
9484Srgrimes	popl	%esi
9494Srgrimes	xorl	%eax,%eax
9504Srgrimes	movl	_curpcb,%edx
9514Srgrimes	movl	%eax,PCB_ONFAULT(%edx)
9524Srgrimes	ret
9534Srgrimes
954134Sdgcopyout_fault:
955134Sdg#ifdef	USE_486_WRITE_PROTECT
956134Sdg	popl	%es
957134Sdg#endif
9584Srgrimes	popl	%ebx
9594Srgrimes	popl	%edi
9604Srgrimes	popl	%esi
961134Sdg	movl	_curpcb, %edx
962134Sdg	movl	$0, PCB_ONFAULT(%edx)
963134Sdg	movl	$EFAULT, %eax
9644Srgrimes	ret
9654Srgrimes
966134Sdg
967134SdgENTRY(copyin)			# copyin (from_user, to_kernel, len)
9684Srgrimes	movl	_curpcb,%eax
969134Sdg	movl	$copyin_fault, PCB_ONFAULT(%eax)
9704Srgrimes	pushl	%esi
9714Srgrimes	pushl	%edi
972134Sdg	movl	12(%esp),%esi		# caddr_t from
973134Sdg	movl	16(%esp),%edi		# caddr_t to
974134Sdg	movl	20(%esp),%ecx		# size_t  len
975134Sdg	movl	%ecx,%edx
976134Sdg	pushl	%ds
977134Sdg	movl	__udatasel,%ax		# access 'from' via user data segment
978134Sdg	movl	%ax,%ds
979134Sdg
980134Sdg	movb	%cl,%al
981134Sdg	shrl	$2,%ecx			# copy longword-wise
9824Srgrimes	cld
9834Srgrimes	rep
9844Srgrimes	movsl
985134Sdg	movb	%al,%cl
986134Sdg	andb	$3,%cl			# copy remaining bytes
9874Srgrimes	rep
9884Srgrimes	movsb
989134Sdg
990134Sdg	popl	%ds
9914Srgrimes	popl	%edi
9924Srgrimes	popl	%esi
993134Sdg	xorl	%eax, %eax
994134Sdg	movl	_curpcb, %edx
995134Sdg	movl	%eax, PCB_ONFAULT(%edx)
9964Srgrimes	ret
9974Srgrimes
998134Sdgcopyin_fault:
999134Sdg	popl	%ds
10004Srgrimes	popl	%edi
10014Srgrimes	popl	%esi
1002134Sdg	movl	_curpcb, %edx
1003134Sdg	movl	$0, PCB_ONFAULT(%edx)
1004134Sdg	movl	$EFAULT, %eax
1005134Sdg	ret
1006134Sdg
1007134Sdg	/*
1008134Sdg	 * fu{byte,sword,word} : fetch a byte (sword, word) from user memory
1009134Sdg	 */
1010134SdgENTRY(fuword)
1011134SdgALTENTRY(fuiword)
1012134Sdg	movl	__udatasel,%eax
1013134Sdg	movl	%ax,%gs
1014134Sdg	movl	_curpcb,%ecx
1015134Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
1016134Sdg	movl	4(%esp),%edx
1017134Sdg	gs
1018134Sdg	movl	(%edx),%eax
1019134Sdg	movl	$0,PCB_ONFAULT(%ecx)
1020134Sdg	ret
1021134Sdg
1022134SdgENTRY(fusword)
1023134Sdg	movl	__udatasel,%eax
1024134Sdg	movl	%ax,%gs
1025134Sdg	movl	_curpcb,%ecx
1026134Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
1027134Sdg	movl	4(%esp),%edx
1028134Sdg	gs
1029134Sdg	movzwl	(%edx),%eax
1030134Sdg	movl	$0,PCB_ONFAULT(%ecx)
1031134Sdg	ret
1032134Sdg
1033134SdgENTRY(fubyte)
1034134SdgALTENTRY(fuibyte)
1035134Sdg	movl	__udatasel,%eax
1036134Sdg	movl	%ax,%gs
1037134Sdg	movl	_curpcb,%ecx
1038134Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
1039134Sdg	movl	4(%esp),%edx
1040134Sdg	gs
1041134Sdg	movzbl	(%edx),%eax
1042134Sdg	movl	$0,PCB_ONFAULT(%ecx)
1043134Sdg	ret
1044134Sdg
1045134Sdgfusufault:
1046134Sdg	movl	_curpcb,%ecx
10474Srgrimes	xorl	%eax,%eax
1048134Sdg	movl	%eax,PCB_ONFAULT(%ecx)
1049134Sdg	decl	%eax
10504Srgrimes	ret
10514Srgrimes
1052134Sdg	/*
1053134Sdg	 * su{byte,sword,word}: write a byte (word, longword) to user memory
1054134Sdg	 */
1055134Sdg#ifdef USE_486_WRITE_PROTECT
1056134Sdg	/*
1057134Sdg	 * we only have to set the right segment selector.
1058134Sdg	 */
1059134SdgENTRY(suword)
1060134SdgALTENTRY(suiword)
1061134Sdg	movl	__udatasel,%eax
1062134Sdg	movl	%ax,%gs
1063134Sdg	movl	_curpcb,%ecx
1064134Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
1065134Sdg	movl	4(%esp),%edx
1066134Sdg	movl	8(%esp),%eax
1067134Sdg	gs
1068134Sdg	movl	%eax,(%edx)
1069134Sdg	movl	$0,PCB_ONFAULT(%ecx)
10704Srgrimes	ret
1071134Sdg
1072134SdgENTRY(susword)
1073134Sdg	movl	__udatasel,%eax
1074134Sdg	movl	%ax,%gs
1075134Sdg	movl	_curpcb,%ecx
1076134Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
1077134Sdg	movl	4(%esp),%edx
1078134Sdg	movw	8(%esp),%ax
1079134Sdg	gs
1080134Sdg	movw	%ax,(%edx)
1081134Sdg	movl	$0,PCB_ONFAULT(%ecx)
1082134Sdg	ret
1083134Sdg
1084134SdgENTRY(subyte)
1085134SdgALTENTRY(suibyte)
1086134Sdg	movl	__udatasel,%eax
1087134Sdg	movl	%ax,%gs
1088134Sdg	movl	_curpcb,%ecx
1089134Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
1090134Sdg	movl	4(%esp),%edx
1091134Sdg	movb	8(%esp),%al
1092134Sdg	gs
1093134Sdg	movb	%al,(%edx)
1094134Sdg	movl	$0,PCB_ONFAULT(%ecx)
1095134Sdg	ret
10964Srgrimes
10974Srgrimes
1098134Sdg#else /* USE_486_WRITE_PROTECT */
1099134Sdg	/*
1100134Sdg	 * here starts the trouble again: check PTE, twice if word crosses
1101134Sdg	 * a page boundary.
1102134Sdg	 */
1103134Sdg	# XXX - page boundary crossing is not handled yet
1104134Sdg
1105134SdgENTRY(subyte)
1106134SdgENTRY(suibyte)
1107134Sdg	movl	_curpcb, %ecx
1108134Sdg	movl	$fusufault, PCB_ONFAULT(%ecx)
1109134Sdg	movl	4(%esp), %edx
1110134Sdg	movl	%edx, %eax
1111134Sdg	shrl	$IDXSHIFT, %edx
1112134Sdg	andb	$0xfc, %dl
1113134Sdg	movb	_PTmap(%edx), %dl
1114134Sdg	andb	$0x7, %dl		/* must be VALID + USERACC + WRITE */
1115134Sdg	cmpb	$0x7, %dl
1116134Sdg	je	1f
1117134Sdg					/* simulate a trap */
1118134Sdg	pushl	%eax
1119134Sdg	call	_trapwrite
1120134Sdg	popl	%edx
1121134Sdg	orl	%eax, %eax
1122134Sdg	jnz	fusufault
1123134Sdg1:
1124134Sdg	movl	4(%esp), %edx
1125134Sdg	movl	8(%esp), %eax
1126134Sdg	movb	%al, (%edx)
1127134Sdg	xorl	%eax, %eax
1128134Sdg	movl	_curpcb, %ecx
1129134Sdg	movl	%eax, PCB_ONFAULT(%ecx)
11304Srgrimes	ret
11314Srgrimes
1132134SdgENTRY(susword)
1133134Sdg	movl	_curpcb, %ecx
1134134Sdg	movl	$fusufault, PCB_ONFAULT(%ecx)
1135134Sdg	movl	4(%esp), %edx
1136134Sdg	movl	%edx, %eax
1137134Sdg	shrl	$IDXSHIFT, %edx
1138134Sdg	andb	$0xfc, %dl
1139134Sdg	movb	_PTmap(%edx), %dl
1140134Sdg	andb	$0x7, %dl		/* must be VALID + USERACC + WRITE */
1141134Sdg	cmpb	$0x7, %dl
1142134Sdg	je	1f
1143134Sdg					/* simulate a trap */
1144134Sdg	pushl	%eax
1145134Sdg	call	_trapwrite
1146134Sdg	popl	%edx
1147134Sdg	orl	%eax, %eax
1148134Sdg	jnz	fusufault
1149134Sdg1:
1150134Sdg	movl	4(%esp), %edx
1151134Sdg	movl	8(%esp), %eax
1152134Sdg	movw	%ax, (%edx)
1153134Sdg	xorl	%eax, %eax
1154134Sdg	movl	_curpcb, %ecx
1155134Sdg	movl	%eax, PCB_ONFAULT(%ecx)
1156134Sdg	ret
1157134Sdg
1158134SdgENTRY(suword)
1159134SdgENTRY(suiword)
1160134Sdg	movl	_curpcb, %ecx
1161134Sdg	movl	$fusufault, PCB_ONFAULT(%ecx)
1162134Sdg	movl	4(%esp), %edx
1163134Sdg	movl	%edx, %eax
1164134Sdg	shrl	$IDXSHIFT, %edx
1165134Sdg	andb	$0xfc, %dl
1166134Sdg	movb	_PTmap(%edx), %dl
1167134Sdg	andb	$0x7, %dl		/* must be VALID + USERACC + WRITE */
1168134Sdg	cmpb	$0x7, %dl
1169134Sdg	je	1f
1170134Sdg					/* simulate a trap */
1171134Sdg	pushl	%eax
1172134Sdg	call	_trapwrite
1173134Sdg	popl	%edx
1174134Sdg	orl	%eax, %eax
1175134Sdg	jnz	fusufault
1176134Sdg1:
1177134Sdg	movl	4(%esp), %edx
1178134Sdg	movl	8(%esp), %eax
1179134Sdg	movl	%eax, 0(%edx)
1180134Sdg	xorl	%eax, %eax
1181134Sdg	movl	_curpcb, %ecx
1182134Sdg	movl	%eax, PCB_ONFAULT(%ecx)
1183134Sdg	ret
1184134Sdg
1185134Sdg#endif /* USE_486_WRITE_PROTECT */
1186134Sdg/*
1187134Sdg * copyoutstr(from, to, maxlen, int *lencopied)
1188134Sdg *	copy a string from from to to, stop when a 0 character is reached.
1189134Sdg *	return ENAMETOOLONG if string is longer than maxlen, and
1190134Sdg *	EFAULT on protection violations. If lencopied is non-zero,
1191134Sdg *	return the actual length in *lencopied.
1192134Sdg */
1193134Sdg#ifdef USE_486_WRITE_PROTECT
1194134Sdg
1195134SdgENTRY(copyoutstr)
1196134Sdg	pushl	%esi
11974Srgrimes	pushl	%edi
1198134Sdg	movl	_curpcb, %ecx
1199134Sdg	movl	$cpystrflt, PCB_ONFAULT(%ecx)
1200134Sdg
1201134Sdg	movl	12(%esp), %esi			# %esi = from
1202134Sdg	movl	16(%esp), %edi			# %edi = to
1203134Sdg	movl	20(%esp), %edx			# %edx = maxlen
1204134Sdg	movl	__udatasel,%eax
1205134Sdg	movl	%ax,%gs
1206134Sdg	incl	%edx
1207134Sdg
1208134Sdg1:
1209134Sdg	decl	%edx
1210134Sdg	jz	4f
1211134Sdg	lodsb
1212134Sdg	gs
1213134Sdg	stosb
1214134Sdg	orb	%al,%al
1215134Sdg	jnz	1b
1216134Sdg			/* Success -- 0 byte reached */
1217134Sdg	decl	%edx
1218134Sdg	xorl	%eax, %eax
1219134Sdg	jmp	6f
1220134Sdg4:
1221134Sdg			/* edx is zero -- return ENAMETOOLONG */
1222134Sdg	movl	$ENAMETOOLONG, %eax
1223134Sdg	jmp	6f
1224134Sdg
1225134Sdg#else	/* USE_486_WRITE_PROTECT */
1226134Sdg
1227134SdgENTRY(copyoutstr)
1228134Sdg	pushl	%esi
1229134Sdg	pushl	%edi
1230134Sdg	movl	_curpcb, %ecx
1231134Sdg	movl	$cpystrflt, PCB_ONFAULT(%ecx)
1232134Sdg
1233134Sdg	movl	12(%esp), %esi			# %esi = from
1234134Sdg	movl	16(%esp), %edi			# %edi = to
1235134Sdg	movl	20(%esp), %edx			# %edx = maxlen
1236134Sdg1:
1237134Sdg	movl	%edi, %eax
1238134Sdg	shrl	$IDXSHIFT, %eax
1239134Sdg	andb	$0xfc, %al
1240134Sdg	movb	_PTmap(%eax), %al
1241134Sdg	andb	$7, %al
1242134Sdg	cmpb	$7, %al
1243134Sdg	je	2f
1244134Sdg
1245134Sdg			/* simulate trap */
1246134Sdg	pushl	%edx
1247134Sdg	pushl	%edi
1248134Sdg	call	_trapwrite
12494Srgrimes	popl	%edi
1250134Sdg	popl	%edx
1251134Sdg	orl	%eax, %eax
1252134Sdg	jnz	cpystrflt
12534Srgrimes
1254134Sdg2:			/* copy up to end of this page */
1255134Sdg	movl	%edi, %eax
1256134Sdg	andl	$0x0fff, %eax
1257134Sdg	movl	$NBPG, %ecx
1258134Sdg	subl	%eax, %ecx	/* ecx = NBPG - (src % NBPG) */
1259134Sdg	cmpl	%ecx, %edx
1260134Sdg	jge	3f
1261134Sdg	movl	%edx, %ecx	/* ecx = min (ecx, edx) */
1262134Sdg3:
1263134Sdg	orl	%ecx, %ecx
1264134Sdg	jz	4f
1265134Sdg	decl	%ecx
1266134Sdg	decl	%edx
1267134Sdg	lodsb
1268134Sdg	stosb
1269134Sdg	orb	%al, %al
1270134Sdg	jnz	3b
1271134Sdg
1272134Sdg			/* Success -- 0 byte reached */
1273134Sdg	decl	%edx
1274134Sdg	xorl	%eax, %eax
1275134Sdg	jmp	6f
1276134Sdg
1277134Sdg4:			/* next page */
1278134Sdg	orl	%edx, %edx
1279134Sdg	jnz	1b
1280134Sdg			/* edx is zero -- return ENAMETOOLONG */
1281134Sdg	movl	$ENAMETOOLONG, %eax
1282134Sdg	jmp	6f
1283134Sdg#endif /* USE_486_WRITE_PROTECT */
1284134Sdg
1285134Sdg/*
1286134Sdg * copyinstr(from, to, maxlen, int *lencopied)
1287134Sdg *	copy a string from from to to, stop when a 0 character is reached.
1288134Sdg *	return ENAMETOOLONG if string is longer than maxlen, and
1289134Sdg *	EFAULT on protection violations. If lencopied is non-zero,
1290134Sdg *	return the actual length in *lencopied.
1291134Sdg */
1292134SdgENTRY(copyinstr)
12934Srgrimes	pushl	%esi
1294134Sdg	pushl	%edi
1295134Sdg	movl	_curpcb, %ecx
1296134Sdg	movl	$cpystrflt, PCB_ONFAULT(%ecx)
1297134Sdg
1298134Sdg	movl	12(%esp), %esi			# %esi = from
1299134Sdg	movl	16(%esp), %edi			# %edi = to
1300134Sdg	movl	20(%esp), %edx			# %edx = maxlen
1301134Sdg	movl	__udatasel,%eax
1302134Sdg	movl	%ax,%gs
1303134Sdg	incl	%edx
1304134Sdg
1305134Sdg1:
1306134Sdg	decl	%edx
1307134Sdg	jz	4f
1308134Sdg	gs
1309134Sdg	lodsb
1310134Sdg	stosb
1311134Sdg	orb	%al,%al
1312134Sdg	jnz	1b
1313134Sdg			/* Success -- 0 byte reached */
1314134Sdg	decl	%edx
1315134Sdg	xorl	%eax, %eax
1316134Sdg	jmp	6f
1317134Sdg4:
1318134Sdg			/* edx is zero -- return ENAMETOOLONG */
1319134Sdg	movl	$ENAMETOOLONG, %eax
1320134Sdg	jmp	6f
1321134Sdg
1322134Sdgcpystrflt:
1323134Sdg	movl	$EFAULT, %eax
1324134Sdg6:			/* set *lencopied and return %eax */
1325134Sdg	movl	_curpcb, %ecx
1326134Sdg	movl	$0, PCB_ONFAULT(%ecx)
1327134Sdg	movl	20(%esp), %ecx
1328134Sdg	subl	%edx, %ecx
1329134Sdg	movl	24(%esp), %edx
1330134Sdg	orl	%edx, %edx
1331134Sdg	jz	7f
1332134Sdg	movl	%ecx, (%edx)
1333134Sdg7:
1334134Sdg	popl	%edi
13354Srgrimes	popl	%esi
13364Srgrimes	ret
13374Srgrimes
1338134Sdg
1339134Sdg/*
1340134Sdg * copystr(from, to, maxlen, int *lencopied)
1341134Sdg */
1342134SdgENTRY(copystr)
13434Srgrimes	pushl	%esi
1344134Sdg	pushl	%edi
1345134Sdg
1346134Sdg	movl	12(%esp), %esi			# %esi = from
1347134Sdg	movl	16(%esp), %edi			# %edi = to
1348134Sdg	movl	20(%esp), %edx			# %edx = maxlen
1349134Sdg	incl	%edx
1350134Sdg
1351134Sdg1:
1352134Sdg	decl	%edx
1353134Sdg	jz	4f
1354134Sdg	lodsb
1355134Sdg	stosb
1356134Sdg	orb	%al,%al
1357134Sdg	jnz	1b
1358134Sdg			/* Success -- 0 byte reached */
1359134Sdg	decl	%edx
1360134Sdg	xorl	%eax, %eax
1361134Sdg	jmp	6f
1362134Sdg4:
1363134Sdg			/* edx is zero -- return ENAMETOOLONG */
1364134Sdg	movl	$ENAMETOOLONG, %eax
1365134Sdg
1366134Sdg6:			/* set *lencopied and return %eax */
1367134Sdg	movl	20(%esp), %ecx
1368134Sdg	subl	%edx, %ecx
1369134Sdg	movl	24(%esp), %edx
1370134Sdg	orl	%edx, %edx
1371134Sdg	jz	7f
1372134Sdg	movl	%ecx, (%edx)
1373134Sdg7:
1374134Sdg	popl	%edi
13754Srgrimes	popl	%esi
13764Srgrimes	ret
13774Srgrimes
1378134Sdg/*****************************************************************************/
1379134Sdg/* Handling of special 386 registers and descriptor tables etc               */
1380134Sdg/*****************************************************************************/
13814Srgrimes	/*
13824Srgrimes	 * void lgdt(struct region_descriptor *rdp);
13834Srgrimes	 */
13844SrgrimesENTRY(lgdt)
13854Srgrimes	/* reload the descriptor table */
13864Srgrimes	movl	4(%esp),%eax
13874Srgrimes	lgdt	(%eax)
13884Srgrimes	/* flush the prefetch q */
13894Srgrimes	jmp	1f
13904Srgrimes	nop
13914Srgrimes1:
13924Srgrimes	/* reload "stale" selectors */
13934Srgrimes	movl	$KDSEL,%eax
13944Srgrimes	movl	%ax,%ds
13954Srgrimes	movl	%ax,%es
13964Srgrimes	movl	%ax,%ss
13974Srgrimes
13984Srgrimes	/* reload code selector by turning return into intersegmental return */
13994Srgrimes	movl	(%esp),%eax
14004Srgrimes	pushl	%eax
14014Srgrimes	# movl	$KCSEL,4(%esp)
14024Srgrimes	movl	$8,4(%esp)
14034Srgrimes	lret
14044Srgrimes
14054Srgrimes	/*
14064Srgrimes	 * void lidt(struct region_descriptor *rdp);
14074Srgrimes	 */
14084SrgrimesENTRY(lidt)
14094Srgrimes	movl	4(%esp),%eax
14104Srgrimes	lidt	(%eax)
14114Srgrimes	ret
14124Srgrimes
14134Srgrimes	/*
14144Srgrimes	 * void lldt(u_short sel)
14154Srgrimes	 */
14164SrgrimesENTRY(lldt)
14174Srgrimes	lldt	4(%esp)
14184Srgrimes	ret
14194Srgrimes
14204Srgrimes	/*
14214Srgrimes	 * void ltr(u_short sel)
14224Srgrimes	 */
14234SrgrimesENTRY(ltr)
14244Srgrimes	ltr	4(%esp)
14254Srgrimes	ret
14264Srgrimes
1427134SdgENTRY(ssdtosd)				# ssdtosd(*ssdp,*sdp)
14284Srgrimes	pushl	%ebx
14294Srgrimes	movl	8(%esp),%ecx
14304Srgrimes	movl	8(%ecx),%ebx
14314Srgrimes	shll	$16,%ebx
14324Srgrimes	movl	(%ecx),%edx
14334Srgrimes	roll	$16,%edx
14344Srgrimes	movb	%dh,%bl
14354Srgrimes	movb	%dl,%bh
14364Srgrimes	rorl	$8,%ebx
14374Srgrimes	movl	4(%ecx),%eax
14384Srgrimes	movw	%ax,%dx
14394Srgrimes	andl	$0xf0000,%eax
14404Srgrimes	orl	%eax,%ebx
14414Srgrimes	movl	12(%esp),%ecx
14424Srgrimes	movl	%edx,(%ecx)
14434Srgrimes	movl	%ebx,4(%ecx)
14444Srgrimes	popl	%ebx
14454Srgrimes	ret
14464Srgrimes
1447134Sdg
1448134SdgENTRY(tlbflush)				# tlbflush()
1449134Sdg	movl	%cr3,%eax
1450134Sdg 	orl	$ I386_CR3PAT,%eax
1451134Sdg	movl	%eax,%cr3
14524Srgrimes	ret
1453134Sdg
1454134Sdg
1455134SdgENTRY(lcr0)				# lcr0(cr0)
1456134SdgALTENTRY(load_cr0)
1457134Sdg	movl	4(%esp),%eax
1458134Sdg	movl	%eax,%cr0
14594Srgrimes	ret
1460134Sdg
1461134Sdg
1462134SdgENTRY(rcr0)				# rcr0()
1463134Sdg	movl	%cr0,%eax
14644Srgrimes	ret
14654Srgrimes
1466134Sdg
1467134SdgENTRY(rcr2)				# rcr2()
1468134Sdg	movl	%cr2,%eax
14694Srgrimes	ret
14704Srgrimes
14714Srgrimes
1472134SdgENTRY(rcr3)				# rcr3()
1473134SdgALTENTRY(_cr3)
1474134Sdg	movl	%cr3,%eax
14754Srgrimes	ret
14764Srgrimes
1477134Sdg
1478134Sdg	/*
1479134Sdg	 * void lcr3(caddr_t cr3)
1480134Sdg	 */
1481134SdgENTRY(lcr3)
1482134SdgALTENTRY(load_cr3)
1483134Sdg	movl	4(%esp),%eax
1484134Sdg 	orl	$ I386_CR3PAT,%eax
1485134Sdg	movl	%eax,%cr3
14864Srgrimes	ret
14874Srgrimes
1488134Sdg
1489134Sdg/*****************************************************************************/
1490134Sdg/* setjump, longjump                                                         */
1491134Sdg/*****************************************************************************/
1492134Sdg
14934SrgrimesENTRY(setjmp)
14944Srgrimes	movl	4(%esp),%eax
14954Srgrimes	movl	%ebx,  (%eax)		# save ebx
14964Srgrimes	movl	%esp, 4(%eax)		# save esp
14974Srgrimes	movl	%ebp, 8(%eax)		# save ebp
14984Srgrimes	movl	%esi,12(%eax)		# save esi
14994Srgrimes	movl	%edi,16(%eax)		# save edi
15004Srgrimes	movl	(%esp),%edx		# get rta
15014Srgrimes	movl	%edx,20(%eax)		# save eip
15024Srgrimes	xorl	%eax,%eax		# return (0);
15034Srgrimes	ret
15044Srgrimes
15054SrgrimesENTRY(longjmp)
15064Srgrimes	movl	4(%esp),%eax
15074Srgrimes	movl	  (%eax),%ebx		# restore ebx
15084Srgrimes	movl	 4(%eax),%esp		# restore esp
15094Srgrimes	movl	 8(%eax),%ebp		# restore ebp
15104Srgrimes	movl	12(%eax),%esi		# restore esi
15114Srgrimes	movl	16(%eax),%edi		# restore edi
15124Srgrimes	movl	20(%eax),%edx		# get rta
15134Srgrimes	movl	%edx,(%esp)		# put in return frame
15144Srgrimes	xorl	%eax,%eax		# return (1);
15154Srgrimes	incl	%eax
15164Srgrimes	ret
1517134Sdg
1518134Sdg
1519134Sdg/*****************************************************************************/
1520134Sdg/* Scheduling                                                                */
1521134Sdg/*****************************************************************************/
1522134Sdg
15234Srgrimes/*
15244Srgrimes * The following primitives manipulate the run queues.
15254Srgrimes * _whichqs tells which of the 32 queues _qs
15264Srgrimes * have processes in them.  Setrq puts processes into queues, Remrq
15274Srgrimes * removes them from queues.  The running process is on no queue,
15284Srgrimes * other processes are on a queue related to p->p_pri, divided by 4
15294Srgrimes * actually to shrink the 0-127 range of priorities into the 32 available
15304Srgrimes * queues.
15314Srgrimes */
15324Srgrimes
15334Srgrimes	.globl	_whichqs,_qs,_cnt,_panic
15344Srgrimes	.comm	_noproc,4
15354Srgrimes	.comm	_runrun,4
15364Srgrimes
15374Srgrimes/*
15384Srgrimes * Setrq(p)
15394Srgrimes *
15404Srgrimes * Call should be made at spl6(), and p->p_stat should be SRUN
15414Srgrimes */
15424SrgrimesENTRY(setrq)
15434Srgrimes	movl	4(%esp),%eax
15444Srgrimes	cmpl	$0,P_RLINK(%eax)	# should not be on q already
15454Srgrimes	je	set1
15464Srgrimes	pushl	$set2
15474Srgrimes	call	_panic
15484Srgrimesset1:
15494Srgrimes	movzbl	P_PRI(%eax),%edx
15504Srgrimes	shrl	$2,%edx
15514Srgrimes	btsl	%edx,_whichqs		# set q full bit
15524Srgrimes	shll	$3,%edx
15534Srgrimes	addl	$_qs,%edx		# locate q hdr
15544Srgrimes	movl	%edx,P_LINK(%eax)	# link process on tail of q
15554Srgrimes	movl	P_RLINK(%edx),%ecx
15564Srgrimes	movl	%ecx,P_RLINK(%eax)
15574Srgrimes	movl	%eax,P_RLINK(%edx)
15584Srgrimes	movl	%eax,P_LINK(%ecx)
15594Srgrimes	ret
15604Srgrimes
15614Srgrimesset2:	.asciz	"setrq"
15624Srgrimes
15634Srgrimes/*
15644Srgrimes * Remrq(p)
15654Srgrimes *
15664Srgrimes * Call should be made at spl6().
15674Srgrimes */
15684SrgrimesENTRY(remrq)
15694Srgrimes	movl	4(%esp),%eax
15704Srgrimes	movzbl	P_PRI(%eax),%edx
15714Srgrimes	shrl	$2,%edx
15724Srgrimes	btrl	%edx,_whichqs		# clear full bit, panic if clear already
15734Srgrimes	jb	rem1
15744Srgrimes	pushl	$rem3
15754Srgrimes	call	_panic
15764Srgrimesrem1:
15774Srgrimes	pushl	%edx
15784Srgrimes	movl	P_LINK(%eax),%ecx	# unlink process
15794Srgrimes	movl	P_RLINK(%eax),%edx
15804Srgrimes	movl	%edx,P_RLINK(%ecx)
15814Srgrimes	movl	P_RLINK(%eax),%ecx
15824Srgrimes	movl	P_LINK(%eax),%edx
15834Srgrimes	movl	%edx,P_LINK(%ecx)
15844Srgrimes	popl	%edx
15854Srgrimes	movl	$_qs,%ecx
15864Srgrimes	shll	$3,%edx
15874Srgrimes	addl	%edx,%ecx
15884Srgrimes	cmpl	P_LINK(%ecx),%ecx	# q still has something?
15894Srgrimes	je	rem2
15904Srgrimes	shrl	$3,%edx			# yes, set bit as still full
15914Srgrimes	btsl	%edx,_whichqs
15924Srgrimesrem2:
15934Srgrimes	movl	$0,P_RLINK(%eax)	# zap reverse link to indicate off list
15944Srgrimes	ret
15954Srgrimes
15964Srgrimesrem3:	.asciz	"remrq"
15974Srgrimessw0:	.asciz	"swtch"
15984Srgrimes
15994Srgrimes/*
16004Srgrimes * When no processes are on the runq, Swtch branches to idle
16014Srgrimes * to wait for something to come ready.
16024Srgrimes */
1603134SdgLENTRY(Idle)
16044Srgrimes	sti
16054Srgrimes	SHOW_STI
1606134Sdgidle_loop:
16074Srgrimes	call	_spl0
16084Srgrimes	cmpl	$0,_whichqs
16094Srgrimes	jne	sw1
1610134Sdg	hlt		# wait for interrupt
1611134Sdg	jmp	idle_loop
16124Srgrimes
16134Srgrimes	SUPERALIGN_TEXT	/* so profiling doesn't lump Idle with swtch().. */
16144Srgrimesbadsw:
16154Srgrimes	pushl	$sw0
16164Srgrimes	call	_panic
16174Srgrimes	/*NOTREACHED*/
16184Srgrimes
16194Srgrimes/*
16204Srgrimes * Swtch()
16214Srgrimes */
16224SrgrimesENTRY(swtch)
16234Srgrimes
16244Srgrimes	incl	_cnt+V_SWTCH
16254Srgrimes
16264Srgrimes	/* switch to new process. first, save context as needed */
16274Srgrimes
16284Srgrimes	movl	_curproc,%ecx
16294Srgrimes
16304Srgrimes	/* if no process to save, don't bother */
16314Srgrimes	testl	%ecx,%ecx
16324Srgrimes	je	sw1
16334Srgrimes
16344Srgrimes	movl	P_ADDR(%ecx),%ecx
16354Srgrimes
16364Srgrimes	movl	(%esp),%eax		# Hardware registers
16374Srgrimes	movl	%eax, PCB_EIP(%ecx)
16384Srgrimes	movl	%ebx, PCB_EBX(%ecx)
16394Srgrimes	movl	%esp, PCB_ESP(%ecx)
16404Srgrimes	movl	%ebp, PCB_EBP(%ecx)
16414Srgrimes	movl	%esi, PCB_ESI(%ecx)
16424Srgrimes	movl	%edi, PCB_EDI(%ecx)
16434Srgrimes
16444Srgrimes#ifdef NPX
16454Srgrimes	/* have we used fp, and need a save? */
16464Srgrimes	mov	_curproc,%eax
16474Srgrimes	cmp	%eax,_npxproc
16484Srgrimes	jne	1f
16494Srgrimes	pushl	%ecx			/* h/w bugs make saving complicated */
16504Srgrimes	leal	PCB_SAVEFPU(%ecx),%eax
16514Srgrimes	pushl	%eax
16524Srgrimes	call	_npxsave		/* do it in a big C function */
16534Srgrimes	popl	%eax
16544Srgrimes	popl	%ecx
16554Srgrimes1:
16564Srgrimes#endif
16574Srgrimes
16584Srgrimes	movl	_CMAP2,%eax		# save temporary map PTE
16594Srgrimes	movl	%eax,PCB_CMAP2(%ecx)	# in our context
16604Srgrimes	movl	$0,_curproc		#  out of process
16614Srgrimes
16624Srgrimes	# movw	_cpl, %ax
16634Srgrimes	# movw	%ax, PCB_IML(%ecx)	# save ipl
16644Srgrimes
16654Srgrimes	/* save is done, now choose a new process or idle */
16664Srgrimessw1:
16674Srgrimes	cli
16684Srgrimes	SHOW_CLI
16694Srgrimes	movl	_whichqs,%edi
16704Srgrimes2:
16714Srgrimes	# XXX - bsf is sloow
16724Srgrimes	bsfl	%edi,%eax		# find a full q
1673134Sdg	je	Idle			# if none, idle
16744Srgrimes	# XX update whichqs?
16754Srgrimesswfnd:
16764Srgrimes	btrl	%eax,%edi		# clear q full status
16774Srgrimes	jnb	2b		# if it was clear, look for another
16784Srgrimes	movl	%eax,%ebx		# save which one we are using
16794Srgrimes
16804Srgrimes	shll	$3,%eax
16814Srgrimes	addl	$_qs,%eax		# select q
16824Srgrimes	movl	%eax,%esi
16834Srgrimes
16844Srgrimes#ifdef	DIAGNOSTIC
16854Srgrimes	cmpl	P_LINK(%eax),%eax # linked to self? (e.g. not on list)
16864Srgrimes	je	badsw			# not possible
16874Srgrimes#endif
16884Srgrimes
16894Srgrimes	movl	P_LINK(%eax),%ecx	# unlink from front of process q
16904Srgrimes	movl	P_LINK(%ecx),%edx
16914Srgrimes	movl	%edx,P_LINK(%eax)
16924Srgrimes	movl	P_RLINK(%ecx),%eax
16934Srgrimes	movl	%eax,P_RLINK(%edx)
16944Srgrimes
16954Srgrimes	cmpl	P_LINK(%ecx),%esi	# q empty
16964Srgrimes	je	3f
16974Srgrimes	btsl	%ebx,%edi		# nope, set to indicate full
16984Srgrimes3:
16994Srgrimes	movl	%edi,_whichqs		# update q status
17004Srgrimes
17014Srgrimes	movl	$0,%eax
17024Srgrimes	movl	%eax,_want_resched
17034Srgrimes
17044Srgrimes#ifdef	DIAGNOSTIC
17054Srgrimes	cmpl	%eax,P_WCHAN(%ecx)
17064Srgrimes	jne	badsw
17074Srgrimes	cmpb	$ SRUN,P_STAT(%ecx)
17084Srgrimes	jne	badsw
17094Srgrimes#endif
17104Srgrimes
17114Srgrimes	movl	%eax,P_RLINK(%ecx) /* isolate process to run */
17124Srgrimes	movl	P_ADDR(%ecx),%edx
17134Srgrimes	movl	PCB_CR3(%edx),%ebx
17144Srgrimes
17154Srgrimes	/* switch address space */
17164Srgrimes	movl	%ebx,%cr3
17174Srgrimes
17184Srgrimes	/* restore context */
17194Srgrimes	movl	PCB_EBX(%edx), %ebx
17204Srgrimes	movl	PCB_ESP(%edx), %esp
17214Srgrimes	movl	PCB_EBP(%edx), %ebp
17224Srgrimes	movl	PCB_ESI(%edx), %esi
17234Srgrimes	movl	PCB_EDI(%edx), %edi
17244Srgrimes	movl	PCB_EIP(%edx), %eax
17254Srgrimes	movl	%eax, (%esp)
17264Srgrimes
17274Srgrimes	movl	PCB_CMAP2(%edx),%eax	# get temporary map
17284Srgrimes	movl	%eax,_CMAP2		# reload temporary map PTE
17294Srgrimes
17304Srgrimes	movl	%ecx,_curproc		# into next process
17314Srgrimes	movl	%edx,_curpcb
17324Srgrimes
17334Srgrimes	pushl	%edx			# save p to return
17344Srgrimes/*
17354Srgrimes * XXX - 0.0 forgot to save it - is that why this was commented out in 0.1?
17364Srgrimes * I think restoring the cpl is unnecessary, but we must turn off the cli
17374Srgrimes * now that spl*() don't do it as a side affect.
17384Srgrimes */
17394Srgrimes	pushl	PCB_IML(%edx)
17404Srgrimes	sti
17414Srgrimes	SHOW_STI
17424Srgrimes#if 0
17434Srgrimes	call	_splx
17444Srgrimes#endif
17454Srgrimes	addl	$4,%esp
17464Srgrimes/*
17474Srgrimes * XXX - 0.0 gets here via swtch_to_inactive().  I think 0.1 gets here in the
17484Srgrimes * same way.  Better return a value.
17494Srgrimes */
17504Srgrimes	popl	%eax			# return (p);
17514Srgrimes	ret
17524Srgrimes
17534SrgrimesENTRY(mvesp)
17544Srgrimes	movl	%esp,%eax
17554Srgrimes	ret
17564Srgrimes/*
17574Srgrimes * struct proc *swtch_to_inactive(p) ; struct proc *p;
17584Srgrimes *
17594Srgrimes * At exit of a process, move off the address space of the
17604Srgrimes * process and onto a "safe" one. Then, on a temporary stack
17614Srgrimes * return and run code that disposes of the old state.
17624Srgrimes * Since this code requires a parameter from the "old" stack,
17634Srgrimes * pass it back as a return value.
17644Srgrimes */
17654SrgrimesENTRY(swtch_to_inactive)
17664Srgrimes	popl	%edx			# old pc
17674Srgrimes	popl	%eax			# arg, our return value
17684Srgrimes	movl	_IdlePTD,%ecx
17694Srgrimes	movl	%ecx,%cr3		# good bye address space
17704Srgrimes #write buffer?
17714Srgrimes	movl	$tmpstk-4,%esp		# temporary stack, compensated for call
17724Srgrimes	jmp	%edx			# return, execute remainder of cleanup
17734Srgrimes
17744Srgrimes/*
17754Srgrimes * savectx(pcb, altreturn)
17764Srgrimes * Update pcb, saving current processor state and arranging
17774Srgrimes * for alternate return ala longjmp in swtch if altreturn is true.
17784Srgrimes */
17794SrgrimesENTRY(savectx)
17804Srgrimes	movl	4(%esp), %ecx
17814Srgrimes	movw	_cpl, %ax
17824Srgrimes	movw	%ax,  PCB_IML(%ecx)
17834Srgrimes	movl	(%esp), %eax
17844Srgrimes	movl	%eax, PCB_EIP(%ecx)
17854Srgrimes	movl	%ebx, PCB_EBX(%ecx)
17864Srgrimes	movl	%esp, PCB_ESP(%ecx)
17874Srgrimes	movl	%ebp, PCB_EBP(%ecx)
17884Srgrimes	movl	%esi, PCB_ESI(%ecx)
17894Srgrimes	movl	%edi, PCB_EDI(%ecx)
17904Srgrimes
17914Srgrimes#ifdef NPX
17924Srgrimes	/*
17934Srgrimes	 * If npxproc == NULL, then the npx h/w state is irrelevant and the
17944Srgrimes	 * state had better already be in the pcb.  This is true for forks
17954Srgrimes	 * but not for dumps (the old book-keeping with FP flags in the pcb
17964Srgrimes	 * always lost for dumps because the dump pcb has 0 flags).
17974Srgrimes	 *
17984Srgrimes	 * If npxproc != NULL, then we have to save the npx h/w state to
17994Srgrimes	 * npxproc's pcb and copy it to the requested pcb, or save to the
18004Srgrimes	 * requested pcb and reload.  Copying is easier because we would
18014Srgrimes	 * have to handle h/w bugs for reloading.  We used to lose the
18024Srgrimes	 * parent's npx state for forks by forgetting to reload.
18034Srgrimes	 */
18044Srgrimes	mov	_npxproc,%eax
18054Srgrimes	testl	%eax,%eax
18064Srgrimes	je	1f
18074Srgrimes
18084Srgrimes	pushl	%ecx
18094Srgrimes	movl	P_ADDR(%eax),%eax
18104Srgrimes	leal	PCB_SAVEFPU(%eax),%eax
18114Srgrimes	pushl	%eax
18124Srgrimes	pushl	%eax
18134Srgrimes	call	_npxsave
18144Srgrimes	popl	%eax
18154Srgrimes	popl	%eax
18164Srgrimes	popl	%ecx
18174Srgrimes
18184Srgrimes	pushl	%ecx
18194Srgrimes	pushl	$108+8*2	/* XXX h/w state size + padding */
18204Srgrimes	leal	PCB_SAVEFPU(%ecx),%ecx
18214Srgrimes	pushl	%ecx
18224Srgrimes	pushl	%eax
18234Srgrimes	call	_bcopy
18244Srgrimes	addl	$12,%esp
18254Srgrimes	popl	%ecx
18264Srgrimes1:
18274Srgrimes#endif
18284Srgrimes
18294Srgrimes	movl	_CMAP2, %edx		# save temporary map PTE
18304Srgrimes	movl	%edx, PCB_CMAP2(%ecx)	# in our context
18314Srgrimes
18324Srgrimes	cmpl	$0, 8(%esp)
18334Srgrimes	je	1f
18344Srgrimes	movl	%esp, %edx		# relocate current sp relative to pcb
18354Srgrimes	subl	$_kstack, %edx		#   (sp is relative to kstack):
18364Srgrimes	addl	%edx, %ecx		#   pcb += sp - kstack;
18374Srgrimes	movl	%eax, (%ecx)		# write return pc at (relocated) sp@
18384Srgrimes	# this mess deals with replicating register state gcc hides
18394Srgrimes	movl	12(%esp),%eax
18404Srgrimes	movl	%eax,12(%ecx)
18414Srgrimes	movl	16(%esp),%eax
18424Srgrimes	movl	%eax,16(%ecx)
18434Srgrimes	movl	20(%esp),%eax
18444Srgrimes	movl	%eax,20(%ecx)
18454Srgrimes	movl	24(%esp),%eax
18464Srgrimes	movl	%eax,24(%ecx)
18474Srgrimes1:
18484Srgrimes	xorl	%eax, %eax		# return 0
18494Srgrimes	ret
18504Srgrimes
18514Srgrimes/*
18524Srgrimes * addupc(int pc, struct uprof *up, int ticks):
18534Srgrimes * update profiling information for the user process.
18544Srgrimes */
18554SrgrimesENTRY(addupc)
18564Srgrimes	pushl %ebp
18574Srgrimes	movl %esp,%ebp
18584Srgrimes	movl 12(%ebp),%edx		/* up */
18594Srgrimes	movl 8(%ebp),%eax		/* pc */
18604Srgrimes
18614Srgrimes	subl PR_OFF(%edx),%eax		/* pc -= up->pr_off */
18624Srgrimes	jl L1				/* if (pc < 0) return */
18634Srgrimes
18644Srgrimes	shrl $1,%eax			/* praddr = pc >> 1 */
18654Srgrimes	imull PR_SCALE(%edx),%eax	/* praddr *= up->pr_scale */
18664Srgrimes	shrl $15,%eax			/* praddr = praddr << 15 */
18674Srgrimes	andl $-2,%eax			/* praddr &= ~1 */
18684Srgrimes
18694Srgrimes	cmpl PR_SIZE(%edx),%eax		/* if (praddr > up->pr_size) return */
18704Srgrimes	ja L1
18714Srgrimes
18724Srgrimes/*	addl %eax,%eax			/* praddr -> word offset */
18734Srgrimes	addl PR_BASE(%edx),%eax		/* praddr += up-> pr_base */
18744Srgrimes	movl 16(%ebp),%ecx		/* ticks */
18754Srgrimes
18764Srgrimes	movl _curpcb,%edx
18774Srgrimes	movl $proffault,PCB_ONFAULT(%edx)
18784Srgrimes	addl %ecx,(%eax)		/* storage location += ticks */
18794Srgrimes	movl $0,PCB_ONFAULT(%edx)
18804SrgrimesL1:
18814Srgrimes	leave
18824Srgrimes	ret
18834Srgrimes
18844Srgrimes	ALIGN_TEXT
18854Srgrimesproffault:
18864Srgrimes	/* if we get a fault, then kill profiling all together */
18874Srgrimes	movl $0,PCB_ONFAULT(%edx)	/* squish the fault handler */
18884Srgrimes 	movl 12(%ebp),%ecx
18894Srgrimes	movl $0,PR_SCALE(%ecx)		/* up->pr_scale = 0 */
18904Srgrimes	leave
18914Srgrimes	ret
18924Srgrimes
1893134Sdg# To be done:
1894134SdgENTRY(astoff)
18954Srgrimes	ret
18964Srgrimes
18974Srgrimes
1898134Sdg/*****************************************************************************/
1899134Sdg/* Trap handling                                                             */
1900134Sdg/*****************************************************************************/
19014Srgrimes/*
19024Srgrimes * Trap and fault vector routines
19034Srgrimes *
19044Srgrimes * XXX - debugger traps are now interrupt gates so at least bdb doesn't lose
19054Srgrimes * control.  The sti's give the standard losing behaviour for ddb and kgdb.
19064Srgrimes */
19074Srgrimes#define	IDTVEC(name)	ALIGN_TEXT; .globl _X/**/name; _X/**/name:
19084Srgrimes#define	TRAP(a)		pushl $(a) ; jmp alltraps
19094Srgrimes#ifdef KGDB
1910134Sdg#  define BPTTRAP(a)	sti; pushl $(a) ; jmp bpttraps
19114Srgrimes#else
1912134Sdg#  define BPTTRAP(a)	sti; TRAP(a)
19134Srgrimes#endif
19144Srgrimes
19154SrgrimesIDTVEC(div)
19164Srgrimes	pushl $0; TRAP(T_DIVIDE)
19174SrgrimesIDTVEC(dbg)
19184Srgrimes#ifdef BDBTRAP
19194Srgrimes	BDBTRAP(dbg)
19204Srgrimes#endif
19214Srgrimes	pushl $0; BPTTRAP(T_TRCTRAP)
19224SrgrimesIDTVEC(nmi)
19234Srgrimes	pushl $0; TRAP(T_NMI)
19244SrgrimesIDTVEC(bpt)
19254Srgrimes#ifdef BDBTRAP
19264Srgrimes	BDBTRAP(bpt)
19274Srgrimes#endif
19284Srgrimes	pushl $0; BPTTRAP(T_BPTFLT)
19294SrgrimesIDTVEC(ofl)
19304Srgrimes	pushl $0; TRAP(T_OFLOW)
19314SrgrimesIDTVEC(bnd)
19324Srgrimes	pushl $0; TRAP(T_BOUND)
19334SrgrimesIDTVEC(ill)
19344Srgrimes	pushl $0; TRAP(T_PRIVINFLT)
19354SrgrimesIDTVEC(dna)
19364Srgrimes	pushl $0; TRAP(T_DNA)
19374SrgrimesIDTVEC(dble)
19384Srgrimes	TRAP(T_DOUBLEFLT)
19394Srgrimes	/*PANIC("Double Fault");*/
19404SrgrimesIDTVEC(fpusegm)
19414Srgrimes	pushl $0; TRAP(T_FPOPFLT)
19424SrgrimesIDTVEC(tss)
19434Srgrimes	TRAP(T_TSSFLT)
19444Srgrimes	/*PANIC("TSS not valid");*/
19454SrgrimesIDTVEC(missing)
19464Srgrimes	TRAP(T_SEGNPFLT)
19474SrgrimesIDTVEC(stk)
19484Srgrimes	TRAP(T_STKFLT)
19494SrgrimesIDTVEC(prot)
19504Srgrimes	TRAP(T_PROTFLT)
19514SrgrimesIDTVEC(page)
19524Srgrimes	TRAP(T_PAGEFLT)
19534SrgrimesIDTVEC(rsvd)
19544Srgrimes	pushl $0; TRAP(T_RESERVED)
19554SrgrimesIDTVEC(fpu)
19564Srgrimes#ifdef NPX
19574Srgrimes	/*
19584Srgrimes	 * Handle like an interrupt so that we can call npxintr to clear the
19594Srgrimes	 * error.  It would be better to handle npx interrupts as traps but
19604Srgrimes	 * this is difficult for nested interrupts.
19614Srgrimes	 */
19624Srgrimes	pushl	$0		/* dummy error code */
19634Srgrimes	pushl	$T_ASTFLT
19644Srgrimes	pushal
19654Srgrimes	nop			/* silly, the bug is for popal and it only
19664Srgrimes				 * bites when the next instruction has a
19674Srgrimes				 * complicated address mode */
19684Srgrimes	pushl	%ds
19694Srgrimes	pushl	%es		/* now the stack frame is a trap frame */
19704Srgrimes	movl	$KDSEL,%eax
19714Srgrimes	movl	%ax,%ds
19724Srgrimes	movl	%ax,%es
19734Srgrimes	pushl	_cpl
19744Srgrimes	pushl	$0		/* dummy unit to finish building intr frame */
19754Srgrimes	incl	_cnt+V_TRAP
19764Srgrimes	call	_npxintr
19774Srgrimes	jmp	doreti
19784Srgrimes#else
19794Srgrimes	pushl $0; TRAP(T_ARITHTRAP)
19804Srgrimes#endif
19814Srgrimes	/* 17 - 31 reserved for future exp */
19824SrgrimesIDTVEC(rsvd0)
19834Srgrimes	pushl $0; TRAP(17)
19844SrgrimesIDTVEC(rsvd1)
19854Srgrimes	pushl $0; TRAP(18)
19864SrgrimesIDTVEC(rsvd2)
19874Srgrimes	pushl $0; TRAP(19)
19884SrgrimesIDTVEC(rsvd3)
19894Srgrimes	pushl $0; TRAP(20)
19904SrgrimesIDTVEC(rsvd4)
19914Srgrimes	pushl $0; TRAP(21)
19924SrgrimesIDTVEC(rsvd5)
19934Srgrimes	pushl $0; TRAP(22)
19944SrgrimesIDTVEC(rsvd6)
19954Srgrimes	pushl $0; TRAP(23)
19964SrgrimesIDTVEC(rsvd7)
19974Srgrimes	pushl $0; TRAP(24)
19984SrgrimesIDTVEC(rsvd8)
19994Srgrimes	pushl $0; TRAP(25)
20004SrgrimesIDTVEC(rsvd9)
20014Srgrimes	pushl $0; TRAP(26)
20024SrgrimesIDTVEC(rsvd10)
20034Srgrimes	pushl $0; TRAP(27)
20044SrgrimesIDTVEC(rsvd11)
20054Srgrimes	pushl $0; TRAP(28)
20064SrgrimesIDTVEC(rsvd12)
20074Srgrimes	pushl $0; TRAP(29)
20084SrgrimesIDTVEC(rsvd13)
20094Srgrimes	pushl $0; TRAP(30)
20104SrgrimesIDTVEC(rsvd14)
20114Srgrimes	pushl $0; TRAP(31)
20124Srgrimes
20134Srgrimes	SUPERALIGN_TEXT
20144Srgrimesalltraps:
20154Srgrimes	pushal
20164Srgrimes	nop
20174Srgrimes	pushl	%ds
20184Srgrimes	pushl	%es
20194Srgrimes	movl	$KDSEL,%eax
20204Srgrimes	movl	%ax,%ds
20214Srgrimes	movl	%ax,%es
20224Srgrimescalltrap:
20234Srgrimes	incl	_cnt+V_TRAP
20244Srgrimes	call	_trap
20254Srgrimes	/*
20264Srgrimes	 * Return through doreti to handle ASTs.  Have to change trap frame
20274Srgrimes	 * to interrupt frame.
20284Srgrimes	 */
20294Srgrimes	movl	$T_ASTFLT,4+4+32(%esp)	/* new trap type (err code not used) */
20304Srgrimes	pushl	_cpl
20314Srgrimes	pushl	$0			/* dummy unit */
20324Srgrimes	jmp	doreti
20334Srgrimes
20344Srgrimes#ifdef KGDB
20354Srgrimes/*
20364Srgrimes * This code checks for a kgdb trap, then falls through
20374Srgrimes * to the regular trap code.
20384Srgrimes */
2039134Sdg	SUPERALIGN_TEXT
20404Srgrimesbpttraps:
20414Srgrimes	pushal
20424Srgrimes	nop
20434Srgrimes	pushl	%es
20444Srgrimes	pushl	%ds
20454Srgrimes	movl	$KDSEL,%eax
20464Srgrimes	movl	%ax,%ds
20474Srgrimes	movl	%ax,%es
20484Srgrimes	testb	$SEL_RPL_MASK,TRAPF_CS_OFF(%esp)
20494Srgrimes					# non-kernel mode?
20504Srgrimes	jne	calltrap		# yes
20514Srgrimes	call	_kgdb_trap_glue
20524Srgrimes	jmp	calltrap
20534Srgrimes#endif
20544Srgrimes
20554Srgrimes/*
20564Srgrimes * Call gate entry for syscall
20574Srgrimes */
2058134Sdg 	SUPERALIGN_TEXT
20594SrgrimesIDTVEC(syscall)
20604Srgrimes	pushfl	# only for stupid carry bit and more stupid wait3 cc kludge
20614Srgrimes		# XXX - also for direction flag (bzero, etc. clear it)
20624Srgrimes	pushal	# only need eax,ecx,edx - trap resaves others
20634Srgrimes	nop
20644Srgrimes	movl	$KDSEL,%eax		# switch to kernel segments
20654Srgrimes	movl	%ax,%ds
20664Srgrimes	movl	%ax,%es
2067134Sdg	incl	_cnt+V_SYSCALL	# kml 3/25/93
20684Srgrimes	call	_syscall
20694Srgrimes	/*
20704Srgrimes	 * Return through doreti to handle ASTs.  Have to change syscall frame
20714Srgrimes	 * to interrupt frame.
20724Srgrimes	 *
20734Srgrimes	 * XXX - we should have set up the frame earlier to avoid the
20744Srgrimes	 * following popal/pushal (not much can be done to avoid shuffling
20754Srgrimes	 * the flags).  Consistent frames would simplify things all over.
20764Srgrimes	 */
20774Srgrimes	movl	32+0(%esp),%eax	/* old flags, shuffle to above cs:eip */
20784Srgrimes	movl	32+4(%esp),%ebx	/* `int' frame should have been ef, eip, cs */
20794Srgrimes	movl	32+8(%esp),%ecx
20804Srgrimes	movl	%ebx,32+0(%esp)
20814Srgrimes	movl	%ecx,32+4(%esp)
20824Srgrimes	movl	%eax,32+8(%esp)
20834Srgrimes	popal
20844Srgrimes	nop
20854Srgrimes	pushl	$0		/* dummy error code */
20864Srgrimes	pushl	$T_ASTFLT
20874Srgrimes	pushal
20884Srgrimes	nop
20894Srgrimes	movl	__udatasel,%eax	/* switch back to user segments */
2090134Sdg	pushl	%eax		/* XXX - better to preserve originals? */
2091134Sdg	pushl	%eax
20924Srgrimes	pushl	_cpl
20934Srgrimes	pushl	$0
20944Srgrimes	jmp	doreti
20954Srgrimes
20964Srgrimes
2097134Sdg/*****************************************************************************/
2098134Sdg/* include generated interrupt vectors and ISA intr code                     */
2099134Sdg/*****************************************************************************/
21004Srgrimes
21014Srgrimes#include "i386/isa/vector.s"
21024Srgrimes#include "i386/isa/icu.s"
2103