vm86bios.s revision 87702
1121572Sume/*-
262583Sitojun * Copyright (c) 1998 Jonathan Lemon
355505Sshin * All rights reserved.
455505Sshin *
555505Sshin * Redistribution and use in source and binary forms, with or without
655505Sshin * modification, are permitted provided that the following conditions
755505Sshin * are met:
855505Sshin * 1. Redistributions of source code must retain the above copyright
955505Sshin *    notice, this list of conditions and the following disclaimer.
1055505Sshin * 2. Redistributions in binary form must reproduce the above copyright
1155505Sshin *    notice, this list of conditions and the following disclaimer in the
1255505Sshin *    documentation and/or other materials provided with the distribution.
1355505Sshin *
1455505Sshin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1555505Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1655505Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1755505Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1855505Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1955505Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2055505Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2155505Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2255505Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2355505Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2455505Sshin * SUCH DAMAGE.
2555505Sshin *
2655505Sshin * $FreeBSD: head/sys/i386/i386/vm86bios.s 87702 2001-12-11 23:33:44Z jhb $
2755505Sshin */
2855505Sshin
2955505Sshin#include "opt_npx.h"
3055505Sshin
3155505Sshin#include <machine/asmacros.h>		/* miscellaneous asm macros */
3284208Sdillon#include <machine/trap.h>
3384208Sdillon
3484208Sdillon#include "assym.s"
3555505Sshin
3655505Sshin#define SCR_NEWPTD	PCB_ESI		/* readability macros */
3755505Sshin#define SCR_VMFRAME	PCB_EBP		/* see vm86.c for explanation */
3855505Sshin#define SCR_STACK	PCB_ESP
3955505Sshin#define SCR_PGTABLE	PCB_EBX
4057855Sshin#define SCR_ARGFRAME	PCB_EIP
41171135Sgnn#define SCR_TSS0	PCB_SPARE
42171135Sgnn#define SCR_TSS1	(PCB_SPARE+4)
4355505Sshin
4455505Sshin	.data
4555505Sshin	ALIGN_DATA
4655505Sshin
4755505Sshin	.globl	in_vm86call, vm86pcb
4862583Sitojun
4955505Sshinin_vm86call:		.long	0
5055505Sshinvm86pcb:		.long	0
5178064Sume
5278064Sume	.text
5362583Sitojun
5462583Sitojun/*
5562583Sitojun * vm86_bioscall(struct trapframe_vm86 *vm86)
5662583Sitojun */
5762583SitojunENTRY(vm86_bioscall)
5862583Sitojun	movl	vm86pcb,%edx		/* scratch data area */
5962583Sitojun	movl	4(%esp),%eax
6062583Sitojun	movl	%eax,SCR_ARGFRAME(%edx)	/* save argument pointer */
6162583Sitojun	pushl	%ebx
6262583Sitojun	pushl	%ebp
6362583Sitojun	pushl	%esi
6462583Sitojun	pushl	%edi
6562583Sitojun	pushl	%gs
6662583Sitojun
6762583Sitojun#ifdef DEV_NPX
6862583Sitojun	pushfl
6962583Sitojun	cli
7062583Sitojun	movl	PCPU(CURTHREAD),%ecx
7162583Sitojun	cmpl	%ecx,PCPU(FPCURTHREAD)	/* do we need to save fp? */
7262583Sitojun	jne	1f
7362583Sitojun	testl	%ecx,%ecx
7462583Sitojun	je 	1f			/* no curproc/npxproc */
7562583Sitojun	pushl	%edx
7662583Sitojun	movl	TD_PCB(%ecx),%ecx
7762583Sitojun	addl	$PCB_SAVEFPU,%ecx
78248314Sglebius	pushl	%ecx
79248314Sglebius	call	npxsave
80248314Sglebius	popl	%ecx
81248314Sglebius	popl	%edx			/* recover our pcb */
82248314Sglebius1:
83248314Sglebius	popfl
84248314Sglebius#endif
8562583Sitojun
8655505Sshin	movl	SCR_VMFRAME(%edx),%ebx	/* target frame location */
8755505Sshin	movl	%ebx,%edi		/* destination */
8892917Sobrien	movl    SCR_ARGFRAME(%edx),%esi	/* source (set on entry) */
8992917Sobrien	movl	$VM86_FRAMESIZE/4,%ecx	/* sizeof(struct vm86frame)/4 */
9092917Sobrien	cld
9192917Sobrien	rep
9292917Sobrien	movsl				/* copy frame to new stack */
9355505Sshin
9455505Sshin	movl	PCPU(CURPCB),%eax
9555505Sshin	pushl	%eax			/* save curpcb */
9655505Sshin	movl	%edx,PCPU(CURPCB)	/* set curpcb to vm86pcb */
9755505Sshin
9855505Sshin	movl	PCPU(TSS_GDT),%ebx	/* entry in GDT */
9962583Sitojun	movl	0(%ebx),%eax
10062583Sitojun	movl	%eax,SCR_TSS0(%edx)	/* save first word */
10162583Sitojun	movl	4(%ebx),%eax
10262583Sitojun	andl    $~0x200, %eax		/* flip 386BSY -> 386TSS */
10362583Sitojun	movl	%eax,SCR_TSS1(%edx)	/* save second word */
10462583Sitojun
10562583Sitojun	movl	PCB_EXT(%edx),%edi	/* vm86 tssd entry */
10662583Sitojun	movl	0(%edi),%eax
10762583Sitojun	movl	%eax,0(%ebx)
10855505Sshin	movl	4(%edi),%eax
10962583Sitojun	movl	%eax,4(%ebx)
11055505Sshin	movl	$GPROC0_SEL*8,%esi	/* GSEL(entry, SEL_KPL) */
11162583Sitojun	ltr	%si
11262583Sitojun
11362583Sitojun	movl	%cr3,%eax
11455505Sshin	pushl	%eax			/* save address space */
11562583Sitojun	movl	IdlePTD,%ecx
11662583Sitojun	movl	%ecx,%ebx
117121572Sume	addl	$KERNBASE,%ebx		/* va of Idle PTD */
11862583Sitojun	movl	0(%ebx),%eax
119121572Sume	pushl	%eax			/* old ptde != 0 when booting */
12055505Sshin	pushl	%ebx			/* keep for reuse */
12162583Sitojun
12255505Sshin	movl	%esp,SCR_STACK(%edx)	/* save current stack location */
12362583Sitojun
12462583Sitojun	movl	SCR_NEWPTD(%edx),%eax	/* mapping for vm86 page table */
12555505Sshin	movl	%eax,0(%ebx)		/* ... install as PTD entry 0 */
12662583Sitojun
12762583Sitojun	movl	%ecx,%cr3		/* new page tables */
12862583Sitojun	movl	SCR_VMFRAME(%edx),%esp	/* switch to new stack */
12962583Sitojun
13062583Sitojun	call	vm86_prepcall		/* finish setup */
13155505Sshin
13262583Sitojun	movl	$1,in_vm86call		/* set flag for trap() */
13362583Sitojun
13462583Sitojun	/*
13562583Sitojun	 * Return via doreti
13662583Sitojun	 */
13762583Sitojun	MEXITCOUNT
13862583Sitojun	jmp	doreti
13962583Sitojun
14055505Sshin
14162583Sitojun/*
14255505Sshin * vm86_biosret(struct trapframe_vm86 *vm86)
14362583Sitojun */
14462583SitojunENTRY(vm86_biosret)
14562583Sitojun	movl	vm86pcb,%edx		/* data area */
14655505Sshin
14762583Sitojun	movl	4(%esp),%esi		/* source */
14855505Sshin	movl	SCR_ARGFRAME(%edx),%edi	/* destination */
14955505Sshin	movl	$VM86_FRAMESIZE/4,%ecx	/* size */
15055505Sshin	cld
15155505Sshin	rep
15262583Sitojun	movsl				/* copy frame to original frame */
15355505Sshin
15455505Sshin	movl	SCR_STACK(%edx),%esp	/* back to old stack */
15555505Sshin	popl	%ebx			/* saved va of Idle PTD */
15662583Sitojun	popl	%eax
15762583Sitojun	movl	%eax,0(%ebx)		/* restore old pte */
15855505Sshin	popl	%eax
15955505Sshin	movl	%eax,%cr3		/* install old page table */
16055505Sshin
16155505Sshin	movl	$0,in_vm86call		/* reset trapflag */
16255505Sshin
16355505Sshin	movl	PCPU(TSS_GDT),%ebx		/* entry in GDT */
16455505Sshin	movl	SCR_TSS0(%edx),%eax
16555505Sshin	movl	%eax,0(%ebx)		/* restore first word */
16655505Sshin	movl	SCR_TSS1(%edx),%eax
16755505Sshin	movl	%eax,4(%ebx)		/* restore second word */
16855505Sshin	movl	$GPROC0_SEL*8,%esi	/* GSEL(entry, SEL_KPL) */
16955505Sshin	ltr	%si
17055505Sshin
17155505Sshin	popl	PCPU(CURPCB)		/* restore curpcb/curproc */
17255505Sshin	movl	SCR_ARGFRAME(%edx),%edx	/* original stack frame */
17355505Sshin	movl	TF_TRAPNO(%edx),%eax	/* return (trapno) */
17455505Sshin
17555505Sshin	popl	%gs
17662583Sitojun	popl	%edi
17762583Sitojun	popl	%esi
17862583Sitojun	popl	%ebp
17962583Sitojun	popl	%ebx
18055505Sshin	ret				/* back to our normal program */
18162583Sitojun