biosint.s revision a0130b69c3952b827264ca8cb19bcbeecb67b463
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/asm_linkage.h>
/*
* biosint.s - installed by kernel to make bios calls
*
* The kernel jumps here from protected mode to make a bios service call.
* Calling syntax: bios_doint(int intnum, struct int_pb *ic)
*/
/
/
/
/
/
/
/
/
movl call_esp, %eax
pushl 12(%eax)
call copyout_args
addl $4, %esp
xorl %eax, %eax / initialize return to zero
popw %ax / get eflags
/ Interrupt descriptor table
lidt kernIDTptr
/ Returned from BIOS call, restore cr0 here
movl call_cr0, %edx
movl %edx, %cr0
movl call_edx, %edx
movl call_ecx, %ecx
movl call_ebx, %ebx
movl call_edi, %edi
movl call_esi, %esi
/ switch back to caller's stack
/ ----------------------------------------------------
/
/
ljmp $0x18, $set16cs
set16cs:
/ need to have all segment regs sane
/ before we can enter real mode
D16 movl $0x20, %eax
movw %ax, %es
movw %ax, %ds
movw %ax, %fs
movw %ax, %gs
/ clear the protection and paging bits
/ jump should clear prefetch q
mov %cr0, %eax
D16 and $0x7ffffffe, %eax
mov %eax, %cr0
/ Do a long jump here to establish %cs in real mode.
/ It appears that this has to be a ljmp as opposed to
/ a lret probably due to the way Intel fixed errata #25
/ on the A2 step. This leads to self modifying code.
ljmp $0x0, $restorecs
restorecs:
/ flush tlb
mov %cr3, %eax
mov %eax, %cr3
/ we are loading in first 64K, so all segment reg should be zero
movw %cs, %ax
movw %ax, %ss
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
D16 ret
/ ----------------------------------------------------
/ Enter protected mode.
/
.globl goprot
goprot:
/ Workaround for BIOSes that mess with GDT during INT call without
/ restoring original value on the way back. Hence restore it here.
D16 A16 lgdt kernGDTptr
D16 popl %ebx / get return %eip, for later use
/ set protect mode and page mode
mov %cr0, %eax
D16 A16 orl $0x80000001, %eax
mov %eax, %cr0
jmp qflush2 / flush the prefetch queue
qflush2:
.align 4
.value 0x3ff
.long 0
.value 0
.long 0
.value 0
.long 0
.long 0
.value 0
.value 0
.value 0
.value 0
.value 0
.value 0
.value 0
.value 0
.value 0
/ Caller's registers
.globl call_cs
call_cs:
.value 0
call_ds:
.value 0
call_es:
.value 0
call_fs:
.value 0
call_gs:
.value 0
.globl call_ss
call_ss:
.value 0
.globl call_cr0
call_cr0:
.long 0
.globl call_esp
call_esp:
.long 0
call_ebp:
.long 0
call_esi:
.long 0
call_edi:
.long 0
call_ebx:
.long 0
call_ecx:
.long 0
call_edx:
.long 0