/* $OpenBSD: kvm86call.S,v 1.4 2006/12/11 23:45:13 gwk Exp $ */ /* $NetBSD: kvm86call.S,v 1.7 2006/04/11 17:14:07 drochner Exp $ */ /*- * Copyright (c) 1998 Jonathan Lemon * All rights reserved. * Copyright (c) 2002 * Matthias Drochner. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/vm86bios.s,v 1.28 2001/12/11 23:33:40 jhb Exp $ */ #include #include #include "assym.h" .data .align 4 /* flag for trap() */ .globl kvm86_incall kvm86_incall: .long 0 /* XXX arguments for kvm86call() */ .globl vm86pcb, vm86newptd, vm86frame, vm86pgtableva .globl vm86tssd0, vm86tssd1 /* locals */ SCRARGFRAME: .long 0 SCRSTACK: .long 0 SCRTSS0: .long 0 SCRTSS1: .long 0 .text #if defined MULTIPROCESSOR #include #endif /* int kvm86_call(struct trapframe *) */ ENTRY(kvm86_call) pushl %ebp movl %esp,%ebp /* set up frame ptr */ pushl %esi pushl %edi pushl %ebx pushl %fs pushl %gs movl 8(%ebp),%eax movl %eax,SCRARGFRAME /* save argument pointer */ movl vm86frame,%edi /* target frame location */ movl SCRARGFRAME,%esi /* source (set on entry) */ movl $FRAMESIZE/4,%ecx /* sizeof(struct trapframe)/4 */ cld rep movsl /* copy frame to new stack */ #ifdef MULTIPROCESSOR movl _C_LABEL(local_apic)+LAPIC_ID,%ecx shrl $LAPIC_ID_SHIFT,%ecx leal 0(,%ecx,4),%ecx movl _C_LABEL(cpu_info)(%ecx),%edx movl %edx,%ecx #else leal _C_LABEL(cpu_info_primary),%ecx #endif movl CPU_INFO_CURPCB(%ecx),%eax pushl %eax /* save curpcb */ movl vm86pcb,%eax movl %eax,CPU_INFO_CURPCB(%ecx) /* set curpcb to vm86pcb */ movl CPU_INFO_CURPROC(%ecx),%ecx movl P_MD_TSS_SEL(%ecx),%edi #ifdef MULTIPROCESSOR movl CPU_INFO_GDT(%edx),%eax #else movl _C_LABEL(gdt),%eax #endif andl $~0x0200,4(%eax,%edi,1) /* reset "task busy" */ movl 0(%eax,%edi,1),%edx movl %edx,SCRTSS0 /* save first word */ movl 4(%eax,%edi,1),%edx movl %edx,SCRTSS1 /* save second word */ movl vm86tssd0,%edx /* vm86 tssd entry */ movl %edx,0(%eax,%edi,1) movl vm86tssd1,%edx /* vm86 tssd entry */ movl %edx,4(%eax,%edi,1) ltr %di movl %cr3,%eax pushl %eax /* save address space */ movl PTDpaddr,%ecx movl %ecx,%ebx addl $KERNBASE,%ebx /* va of Idle PDP */ movl 0(%ebx),%eax pushl %eax /* old pde */ pushl %ebx /* keep address for reuse */ movl %esp,SCRSTACK /* save current stack location */ movl vm86newptd,%eax /* mapping for vm86 page table */ movl %eax,0(%ebx) /* ... install as PDP entry 0 */ movl %ecx,%cr3 /* new page tables */ movl vm86frame,%esp /* switch to new stack */ movl $1,kvm86_incall /* set flag for trap() */ /* INTRFASTEXIT */ popl %gs popl %fs popl %es popl %ds popl %edi popl %esi popl %ebp popl %ebx popl %edx popl %ecx popl %eax addl $8,%esp iret /* void kvm86_ret(struct trapframe *, int) */ ENTRY(kvm86_ret) pushl %ebp movl %esp,%ebp /* set up frame ptr */ movl 8(%ebp),%esi /* source */ movl SCRARGFRAME,%edi /* destination */ movl $FRAMESIZE/4,%ecx /* size */ cld rep movsl /* copy frame to original frame */ movl SCRSTACK,%esp /* back to old stack */ popl %ebx /* saved va of Idle PDP */ popl %eax movl %eax,0(%ebx) /* restore old pde */ popl %eax movl %eax,%cr3 /* install old page table */ movl $0,kvm86_incall /* reset trapflag */ #ifdef MULTIPROCESSOR movl _C_LABEL(local_apic)+LAPIC_ID,%ecx shrl $LAPIC_ID_SHIFT,%ecx leal 0(,%ecx,4),%ecx movl _C_LABEL(cpu_info)(%ecx),%ecx movl CPU_INFO_GDT(%ecx),%eax #else leal _C_LABEL(cpu_info_primary),%ecx movl _C_LABEL(gdt),%eax #endif movl CPU_INFO_CURPROC(%ecx),%ecx movl P_MD_TSS_SEL(%ecx),%edi movl SCRTSS0, %edx movl %edx, 0(%eax,%edi,1) /* restore first word */ movl SCRTSS1, %edx movl %edx, 4(%eax,%edi,1) /* restore second word */ ltr %di #ifdef MULTIPROCESSOR movl _C_LABEL(local_apic)+LAPIC_ID,%ecx shrl $LAPIC_ID_SHIFT,%ecx leal 0(,%ecx,4),%ecx movl _C_LABEL(cpu_info)(%ecx),%ecx #else leal _C_LABEL(cpu_info_primary),%ecx #endif popl %eax /* restore curpcb */ movl %eax,CPU_INFO_CURPCB(%ecx) movl 12(%ebp), %eax /* will be kvm86_call()'s retval */ popl %gs popl %fs popl %ebx popl %edi popl %esi popl %ebp ret /* back to kvm86_call()'s caller */