vm86bios.s revision 39046
134840Sjlemon/*-
234840Sjlemon * Copyright (c) 1998 Jonathan Lemon
334840Sjlemon * All rights reserved.
434840Sjlemon *
534840Sjlemon * Redistribution and use in source and binary forms, with or without
634840Sjlemon * modification, are permitted provided that the following conditions
734840Sjlemon * are met:
834840Sjlemon * 1. Redistributions of source code must retain the above copyright
934840Sjlemon *    notice, this list of conditions and the following disclaimer.
1034840Sjlemon * 2. Redistributions in binary form must reproduce the above copyright
1134840Sjlemon *    notice, this list of conditions and the following disclaimer in the
1234840Sjlemon *    documentation and/or other materials provided with the distribution.
1334840Sjlemon *
1434840Sjlemon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1534840Sjlemon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1634840Sjlemon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1734840Sjlemon * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1834840Sjlemon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1934840Sjlemon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2034840Sjlemon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2134840Sjlemon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2234840Sjlemon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2334840Sjlemon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2434840Sjlemon * SUCH DAMAGE.
2534840Sjlemon *
2639046Syokota *	$Id: vm86bios.s,v 1.3 1998/07/27 16:45:05 jlemon Exp $
2734840Sjlemon */
2834840Sjlemon
2934840Sjlemon#include "opt_vm86.h"
3034840Sjlemon
3134840Sjlemon#include <machine/asmacros.h>		/* miscellaneous asm macros */
3234840Sjlemon#include <machine/trap.h>
3334840Sjlemon
3434840Sjlemon#include "assym.s"
3534840Sjlemon
3637889Sjlemon#define SCR_NEWPTD	PCB_ESI		/* readability macros */
3737889Sjlemon#define SCR_VMFRAME	PCB_EBP		/* see vm86.c for explanation */
3837889Sjlemon#define SCR_STACK	PCB_ESP
3937889Sjlemon#define SCR_PGTABLE	PCB_EBX
4037889Sjlemon#define SCR_ARGFRAME	PCB_EIP
4137889Sjlemon#define SCR_TSS0	PCB_FS
4237889Sjlemon#define SCR_TSS1	PCB_GS
4337889Sjlemon
4434840Sjlemon	.data
4534840Sjlemon	ALIGN_DATA
4634840Sjlemon
4734840Sjlemon	.globl	_in_vm86call, _vm86pcb
4834840Sjlemon
4934840Sjlemon_in_vm86call:		.long	0
5034840Sjlemon_vm86pcb:		.long	0
5134840Sjlemon
5234840Sjlemon	.text
5334840Sjlemon
5434840Sjlemon/*
5534840Sjlemon * vm86_bioscall(struct trapframe_vm86 *vm86)
5634840Sjlemon */
5734840SjlemonENTRY(vm86_bioscall)
5837889Sjlemon	movl	_vm86pcb,%edx		/* scratch data area */
5934840Sjlemon	movl	4(%esp),%eax
6037889Sjlemon	movl	%eax,SCR_ARGFRAME(%edx)	/* save argument pointer */
6134840Sjlemon	pushl	%ebx
6234840Sjlemon	pushl	%ebp
6334840Sjlemon	pushl	%esi
6434840Sjlemon	pushl	%edi
6534840Sjlemon	pushl	%fs
6634840Sjlemon	pushl	%gs
6734840Sjlemon
6834840Sjlemon#ifdef SMP
6934840Sjlemon	pushl	%edx
7034840Sjlemon	ALIGN_LOCK			/* Get global lock */
7134840Sjlemon	popl	%edx
7234840Sjlemon#endif
7334840Sjlemon	movl	_curproc,%ecx
7434840Sjlemon	pushl	%ecx			/* save _curproc value */
7534840Sjlemon	testl	%ecx,%ecx
7634840Sjlemon	je	1f			/* no process to save */
7734840Sjlemon
7834840Sjlemon#if NNPX > 0
7934840Sjlemon	cmpl	%ecx,_npxproc		/* do we need to save fp? */
8034840Sjlemon	jne	1f
8139046Syokota	pushl	%edx
8234840Sjlemon	movl	P_ADDR(%ecx),%ecx
8334840Sjlemon	addl	$PCB_SAVEFPU,%ecx
8439046Syokota	pushl	%ecx
8534840Sjlemon	call	_npxsave
8639046Syokota	popl	%ecx
8734840Sjlemon	popl	%edx			/* recover our pcb */
8834840Sjlemon#endif
8934840Sjlemon
9034840Sjlemon1:
9137889Sjlemon	movl	SCR_VMFRAME(%edx),%ebx	/* target frame location */
9234840Sjlemon	movl	%ebx,%edi		/* destination */
9337889Sjlemon	movl    SCR_ARGFRAME(%edx),%esi	/* source (set on entry) */
9434840Sjlemon	movl	$21,%ecx		/* sizeof(struct vm86frame)/4 */
9534840Sjlemon	cld
9634840Sjlemon	rep
9734840Sjlemon	movsl				/* copy frame to new stack */
9834840Sjlemon
9934840Sjlemon	movl	TF_TRAPNO(%ebx),%ebx
10034840Sjlemon	cmpl	$256,%ebx
10134840Sjlemon	jb	1f			/* no page frame to map */
10234840Sjlemon
10334840Sjlemon	andl	$~PAGE_MASK,%ebx
10434840Sjlemon#if 0
10534840Sjlemon	orl	$PG_V|PG_RW|PG_U,%ebx	/* XXX assembler error?? */
10634840Sjlemon#endif
10734840Sjlemon	orl	$0x7,%ebx
10837889Sjlemon	movl	SCR_PGTABLE(%edx),%eax	/* va of vm86 page table */
10934840Sjlemon	movl	%ebx,4(%eax)		/* set vm86 PTE entry 1 */
11034840Sjlemon1:
11134840Sjlemon	movl	_curpcb,%eax
11234840Sjlemon	pushl	%eax			/* save curpcb */
11334840Sjlemon	movl	%edx,_curpcb		/* set curpcb to vm86pcb */
11434840Sjlemon	movl	$0,_curproc		/* erase curproc */
11534840Sjlemon
11634840Sjlemon	movl	_my_tr,%esi
11734840Sjlemon	leal	_gdt(,%esi,8),%ebx	/* entry in GDT */
11834840Sjlemon	movl	0(%ebx),%eax
11937889Sjlemon	movl	%eax,SCR_TSS0(%edx)	/* save first word */
12034840Sjlemon	movl	4(%ebx),%eax
12134840Sjlemon	andl    $~0x200, %eax		/* flip 386BSY -> 386TSS */
12237889Sjlemon	movl	%eax,SCR_TSS1(%edx)	/* save second word */
12334840Sjlemon
12434840Sjlemon	movl	PCB_EXT(%edx),%edi	/* vm86 tssd entry */
12534840Sjlemon	movl	0(%edi),%eax
12634840Sjlemon	movl	%eax,0(%ebx)
12734840Sjlemon	movl	4(%edi),%eax
12834840Sjlemon	movl	%eax,4(%ebx)
12934840Sjlemon	shll	$3,%esi			/* GSEL(entry, SEL_KPL) */
13034840Sjlemon	ltr	%si
13134840Sjlemon
13234840Sjlemon	movl	%cr3,%eax
13334840Sjlemon	pushl	%eax			/* save address space */
13434840Sjlemon#ifdef SMP
13534840Sjlemon	movl	_my_idlePTD,%ecx
13634840Sjlemon#else
13734840Sjlemon	movl	_IdlePTD,%ecx
13834840Sjlemon#endif
13934840Sjlemon	movl	%ecx,%ebx
14034840Sjlemon	addl	$KERNBASE,%ebx		/* va of Idle PTD */
14134840Sjlemon	movl	0(%ebx),%eax
14234840Sjlemon	pushl	%eax			/* old ptde != 0 when booting */
14334840Sjlemon	pushl	%ebx			/* keep for reuse */
14434840Sjlemon
14537889Sjlemon	movl	%esp,SCR_STACK(%edx)	/* save current stack location */
14634840Sjlemon
14737889Sjlemon	movl	SCR_NEWPTD(%edx),%eax	/* mapping for vm86 page table */
14834840Sjlemon	movl	%eax,0(%ebx)		/* ... install as PTD entry 0 */
14934840Sjlemon
15034840Sjlemon	movl	%ecx,%cr3		/* new page tables */
15137889Sjlemon	movl	SCR_VMFRAME(%edx),%esp	/* switch to new stack */
15234840Sjlemon
15334840Sjlemon	call	_vm86_prepcall		/* finish setup */
15434840Sjlemon
15534840Sjlemon	movl	$1,_in_vm86call		/* set flag for trap() */
15634840Sjlemon
15734840Sjlemon	/*
15834840Sjlemon	 * Return via _doreti
15934840Sjlemon	 */
16034840Sjlemon#ifdef SMP
16134840Sjlemon	ECPL_LOCK
16234840Sjlemon#ifdef CPL_AND_CML
16334840Sjlemon#error Not ready for CPL_AND_CML
16434840Sjlemon#endif
16534840Sjlemon	pushl	_cpl			/* cpl to restore */
16634840Sjlemon	ECPL_UNLOCK
16734840Sjlemon#else
16834840Sjlemon	pushl	_cpl			/* cpl to restore */
16934840Sjlemon#endif
17034840Sjlemon	subl	$4,%esp			/* dummy unit */
17134840Sjlemon	MPLOCKED incb _intr_nesting_level
17234840Sjlemon	MEXITCOUNT
17334840Sjlemon	jmp	_doreti
17434840Sjlemon
17534840Sjlemon
17634840Sjlemon/*
17734840Sjlemon * vm86_biosret(struct trapframe_vm86 *vm86)
17834840Sjlemon */
17934840SjlemonENTRY(vm86_biosret)
18034840Sjlemon	movl	_vm86pcb,%edx		/* data area */
18134840Sjlemon
18234840Sjlemon	movl	4(%esp),%esi		/* source */
18337889Sjlemon	movl	SCR_ARGFRAME(%edx),%edi	/* destination */
18434840Sjlemon	movl	$21,%ecx		/* size */
18534840Sjlemon	cld
18634840Sjlemon	rep
18734840Sjlemon	movsl				/* copy frame to original frame */
18834840Sjlemon
18937889Sjlemon	movl	SCR_STACK(%edx),%esp	/* back to old stack */
19034840Sjlemon	popl	%ebx			/* saved va of Idle PTD */
19134840Sjlemon	popl	%eax
19234840Sjlemon	movl	%eax,0(%ebx)		/* restore old pte */
19334840Sjlemon	popl	%eax
19434840Sjlemon	movl	%eax,%cr3		/* install old page table */
19534840Sjlemon
19634840Sjlemon	movl	$0,_in_vm86call		/* reset trapflag */
19737889Sjlemon	movl	SCR_PGTABLE(%edx),%ebx	/* va of vm86 page table */
19834840Sjlemon	movl	$0,4(%ebx)		/* ...clear entry 1 */
19934840Sjlemon
20034840Sjlemon	movl	_my_tr,%esi
20134840Sjlemon	leal	_gdt(,%esi,8),%ebx	/* entry in GDT */
20237889Sjlemon	movl	SCR_TSS0(%edx),%eax
20334840Sjlemon	movl	%eax,0(%ebx)		/* restore first word */
20437889Sjlemon	movl	SCR_TSS1(%edx),%eax
20534840Sjlemon	movl	%eax,4(%ebx)		/* restore second word */
20634840Sjlemon	shll	$3,%esi			/* GSEL(entry, SEL_KPL) */
20734840Sjlemon	ltr	%si
20834840Sjlemon
20934840Sjlemon	popl	_curpcb			/* restore curpcb/curproc */
21034840Sjlemon	popl	_curproc
21137889Sjlemon	movl	SCR_ARGFRAME(%edx),%edx	/* original stack frame */
21234840Sjlemon	movl	TF_TRAPNO(%edx),%eax	/* return (trapno) */
21334840Sjlemon
21434840Sjlemon	popl	%gs
21534840Sjlemon	popl	%fs
21634840Sjlemon	popl	%edi
21734840Sjlemon	popl	%esi
21834840Sjlemon	popl	%ebp
21934840Sjlemon	popl	%ebx
22034840Sjlemon	ret				/* back to our normal program */
221