Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/i386/stand/lib Routines to switch between 16bit rea...
details: https://anonhg.NetBSD.org/src/rev/f4046a3a1d57
branches: trunk
changeset: 545810:f4046a3a1d57
user: dsl <dsl%NetBSD.org@localhost>
date: Wed Apr 16 17:38:43 2003 +0000
description:
Routines to switch between 16bit real and 32bit protected modes
diffstat:
sys/arch/i386/stand/lib/realprot.S | 271 +++++++++++++++++++++++++++++++++++++
1 files changed, 271 insertions(+), 0 deletions(-)
diffs (275 lines):
diff -r 25e7f59ca37e -r f4046a3a1d57 sys/arch/i386/stand/lib/realprot.S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/i386/stand/lib/realprot.S Wed Apr 16 17:38:43 2003 +0000
@@ -0,0 +1,271 @@
+/* $NetBSD: realprot.S,v 1.1 2003/04/16 17:38:43 dsl Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Loosely based on code from stand/lib/libcrt/bootsect/start_bootsect.S
+ */
+
+#include <machine/asm.h>
+
+#define CR0_PE 1
+
+ .text
+ .align 16
+gdt:
+ .word 0, 0
+ .byte 0, 0x00, 0x00, 0
+
+ /* kernel code segment */
+ .globl flatcodeseg
+flatcodeseg = . - gdt
+ .word 0xffff, 0
+ .byte 0, 0x9f, 0xcf, 0
+
+ /* kernel data segment */
+ .globl flatdataseg
+flatdataseg = . - gdt
+ .word 0xffff, 0
+ .byte 0, 0x93, 0xcf, 0
+
+ /* boot code segment, base will be patched */
+bootcodeseg = . - gdt
+ .word 0xffff, 0
+ .byte 0, 0x9e, 0x4f, 0
+
+ /* boot data segment, base will be patched */
+bootdataseg = . - gdt
+ .word 0xffff, 0
+ .byte 0, 0x92, 0x4f, 0
+
+ /* 16 bit real mode, base will be patched */
+bootrealseg = . - gdt
+ .word 0xffff, 0
+ .byte 0, 0x9e, 0x00, 0
+
+ /* limits (etc) for data segment in real mode */
+bootrealdata = . - gdt
+ .word 0xffff, 0
+ .byte 0, 0x92, 0x00, 0
+gdtlen = . - gdt
+
+ .align 16
+gdtarg:
+ .word gdtlen-1 /* limit */
+ .long 0 /* physical addr, will be inserted */
+
+toreal: .word xreal /* off:seg address for indirect jump */
+ourseg: .word 0 /* real mode code and data segment */
+
+stkseg: .word 0 /* real mode stack segment */
+stkdif: .long 0 /* diff. between real and prot sp */
+
+ .global gdt_fixup
+gdt_fixup:
+ .code16
+ push %ax
+ push %dx
+
+ xorl %eax, %eax
+ mov %cs, %ax
+ mov %ax, ourseg
+ /* sort out stuff for %ss != %ds */
+ movw %ss, %dx
+ movw %dx, stkseg
+ subw %ax, %dx
+ shll $16, %edx
+ shrl $12, %edx
+ movl %edx, stkdif
+
+ /* fix up GDT entries for bootstrap */
+ mov %ax, %dx
+ shll $4, %eax
+ shr $12, %dx
+
+#define FIXUP(gdt_index) \
+ movw %ax, gdt+gdt_index+2; \
+ movb %dl, gdt+gdt_index+4
+
+ FIXUP(bootcodeseg)
+ FIXUP(bootrealseg)
+ FIXUP(bootdataseg)
+
+ /* fix up GDT pointer */
+ addl $gdt, %eax
+ movl %eax, gdtarg+2
+
+ pop %dx
+ pop %ax
+ ret
+
+/*
+ * real_to_prot()
+ *
+ * Switch cpu to 32bit protected mode to execute C.
+ *
+ * NB: Call with the 32bit calll instruction so that a 32 bit
+ * return address is pushed.
+ *
+ * All registers are preserved, %ss:%esp will point to the same
+ * place as %ss:%sp did, although the actual value of %esp might
+ * be changed.
+ *
+ * Interrupts are disabled while we are in 32bit mode to save us
+ * having to setup a different IDT. This code is only used during
+ * the boot process and it doesn't use any interrupts.
+ */
+ENTRY(real_to_prot)
+ .code16
+ pushl %eax
+ cli
+
+ lgdt %cs:gdtarg /* Global descriptor table */
+
+ movl %cr0, %eax
+ or $CR0_PE, %ax
+ movl %eax, %cr0 /* Enter 'protected mode'
+
+ ljmp $bootcodeseg, $1f /* Jump into a 32bit segment */
+1:
+
+ .code32
+ /* Set all the segment registers to map the same area as the code */
+ mov $bootdataseg, %eax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %ss
+ addl stkdif, %esp /* Allow for real %ss != %ds */
+
+ popl %eax
+ ret
+
+/*
+ * prot_to_real()
+ *
+ * Switch cpu back to 16bit real mode in order to call system bios functions.
+ *
+ * All registers are preserved, except that %sp may be changed so that
+ * %ss:%sp points to the same memory.
+ * Note that %ebp is preserved and will not reference the correct part
+ * of the stack.
+ *
+ * Interrupts are enabled while in real mode.
+ *
+ * Based on the descripton in section 14.5 of the 80386 Programmer's
+ * reference book.
+ */
+ENTRY(prot_to_real)
+ .code32
+ pushl %eax
+
+ /*
+ * Load the segment registers while still in protected mode.
+ * Otherwise the control bits don't get changed.
+ * The correct base addresses are loaded later.
+ */
+ movw $bootrealdata, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+
+ /*
+ * Load %cs with a segment that has the correct attributes for
+ * 16bit operation.
+ */
+ ljmp $bootrealseg, $1f
+1:
+
+ .code16
+ movl %cr0, %eax
+ and $~CR0_PE, %eax
+ movl %eax, %cr0 /* Disable potected mode */
+
+ /* Jump far indirect to load real mode %cs */
+ ljmp *%cs:toreal
+xreal:
+ /*
+ * Cpu is now in real mode, load the other segment registers
+ * with their correct base addresses.
+ */
+ mov %cs, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ /*
+ * If stack was above 64k, 16bit %ss needs to be different from
+ * 32bit %ss (and the other segment registers).
+ */
+ mov stkseg, %ax
+ mov %ax, %ss
+ subl stkdif, %esp
+
+ /* Check we are returning to an address below 64k */
+ push %bp
+ movw %sp, %bp
+ movw 2/*bp*/ + 4/*eax*/ + 2(%bp), %ax /* high bits ret addr */
+ test %ax, %ax
+ jne 1f
+ pop %bp
+
+ sti
+ popl %eax
+ retl
+
+1: movw $3f, %si
+ call message
+ movl 2/*bp*/ + 4/*eax*/(%bp), %eax /* return address */
+ call dump_eax
+ int $0x18
+2: sti
+ hlt
+ jmp 2b
+3: .asciz "prot_to_real can't return to "
+
+ .global dump_eax_buff
+dump_eax_buff:
+ . = . + 16
+
+/* vtophys(void *)
+ * convert boot time 'linear' address to a physical one
+ */
+
+ENTRY(vtophys)
+ .code32
+ xorl %eax, %eax
+ movw ourseg, %ax
+ shll $4, %eax
+ addl 4(%esp), %eax
+ ret
Home |
Main Index |
Thread Index |
Old Index