PERFORCE change 40926 for review
Peter Wemm
peter at FreeBSD.org
Thu Oct 30 19:13:32 PST 2003
http://perforce.freebsd.org/chv.cgi?CH=40926
Change 40926 by peter at peter_daintree on 2003/10/30 19:13:27
rewrite mpboot.s. There are still a couple of loose ends yet.
TODO:
* set the segment base for %cs/%ds so we can remain relocatable
* hook up the pagetables
* make it compile (yeah, this would be useful)
Affected files ...
.. //depot/projects/hammer/sys/amd64/amd64/mpboot.s#11 edit
Differences ...
==== //depot/projects/hammer/sys/amd64/amd64/mpboot.s#11 (text+ko) ====
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 1995, Jack F. Vogel
+/*-
+ * Copyright (c) 2003 Peter Wemm
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,16 +10,11 @@
* 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 Jack F. Vogel
- * 4. The name of the developer may be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* 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 REGENTS OR CONTRIBUTORS BE LIABLE
+ * 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)
@@ -28,188 +23,160 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * mpboot.s: FreeBSD machine support for the Intel MP Spec
- * multiprocessor systems.
- *
* $FreeBSD: src/sys/i386/i386/mpboot.s,v 1.22 2003/10/30 21:42:44 jhb Exp $
*/
#include <machine/asmacros.h> /* miscellaneous asm macros */
-#include <machine/apicreg.h>
#include <machine/specialreg.h>
#include "assym.s"
-/*
- * the APs enter here from their trampoline code (bootMP, below)
- */
- .section .data32
+ .section .bootcode
.p2align 4
- .code32
- .globl MPentry
-MPentry:
- movl %cr4,%eax
- orl $CR4_PSE|CR4_PGE|CR4_PAE,%eax /* Enable features */
- movl %eax,%cr4
-
- /* Now enable paging mode */
- movl IdlePTD32, %eax
- movl %eax, %cr3
- movl %cr0,%eax
- orl $CR0_PE|CR0_PG,%eax /* enable paging */
- movl %eax,%cr0 /* let the games begin! */
- movl bootSTK32,%esp /* boot stack end loc. */
-
-#ifdef SMP_ME_HARDER /* 64 bit reference in 32 bit code */
- pushl $init_secondary /* jump to high mem */
-#endif
- ret
-
- .p2align 4
-
-BOOTMP_start:
-
+ .globl mptramp_start
+mptramp_start:
.code16
- .globl bootMP
-bootMP:
- cli
- /* First guarantee a 'clean slate' */
- xorl %eax, %eax
- movl %eax, %ebx
- movl %eax, %ecx
- movl %eax, %edx
- movl %eax, %esi
- movl %eax, %edi
-
- /* set up data segments */
- mov %cs, %ax
- mov %ax, %ds
- mov %ax, %es
- mov %ax, %fs
- mov %ax, %gs
+ /*
+ * The AP enters here in response to the startup IPI.
+ * We are in real mode. %cs is the only segment register set.
+ */
+ cli /* make sure no interrupts */
+ mov %cs, %ax /* copy %cs to %ds. Remember these */
+ mov %ax, %ds /* are offsets rather than selectors */
mov %ax, %ss
- mov $(boot_stk-bootMP), %esp
- /* Now load the global descriptor table */
- lgdt MP_GDTptr-bootMP
+ /*
+ * Load the descriptor table pointer. We'll need it when running
+ * in 16 bit protected mode.
+ */
+ lgdt lgdt_desc-mptramp_start
/* Enable protected mode */
- movl %cr0, %eax
- orl $CR0_PE, %eax
+ movl $CR0_PE, %eax
movl %eax, %cr0
/*
- * make intrasegment jump to flush the processor pipeline and
- * reload CS register
+ * Now execute a far jump to turn on protected mode. This
+ * causes the segment registers to turn into selectors and causes
+ * %cs to be loaded from the gdt.
*/
- pushl $0x18
- pushl $(protmode-bootMP)
- lretl
+ .byte 0xea /* opcode for far jump */
+ .word protmode-mptramp_start /* offset in segment */
+ .word bootcode-gdt /* index in gdt for 16 bit code */
- .code32
+ /*
+ * At this point, we are running in 32 bit legacy protected mode.
+ * However, we have a non-zero base address in our segment registers
+ * so that we can remain relocatable.
+ */
+ .code32
protmode:
+ mov $bootdata-gdt, %eax
+ mov %ax, %ds
+ mov %ax, %ss
+
+ /* Turn on the PAE, PSE and PGE bits for when paging is enabled */
+ mov %cr4, %eax
+ orl $(CR4_PAE | CR4_PSE | CR4_PGE), %eax
+ mov %eax, %cr4
/*
- * we are NOW running for the first time with %eip
- * having the full physical address, BUT we still
- * are using a segment descriptor with the origin
- * not matching the booting kernel.
- *
- * SO NOW... for the BIG Jump into kernel's segment
- * and physical text above 1 Meg.
+ * Point to the embedded page tables for startup. Note that this
+ * only gets accessed after we're actually in 64 bit mode, however
+ * we can only set the bottom 32 bits of %cr3 in this state. This
+ * means we are required to use a temporary page table that is below
+ * the 4GB limit.
*/
- mov $0x10, %ebx
- movw %bx, %ds
- movw %bx, %es
- movw %bx, %fs
- movw %bx, %gs
- movw %bx, %ss
+ movl $pagetables, %eax XXX
+ mov %eax, %cr3
- .globl bigJump
-bigJump:
- /* this will be modified by mpInstallTramp() */
- ljmp $0x08, $0 /* far jmp to MPentry() */
-
-/*
- * MP boot strap Global Descriptor Table
- */
- .p2align 4
- .globl MP_GDT
- .globl bootCodeSeg
- .globl bootDataSeg
-MP_GDT:
+ /*
+ * Enable EFER.LME so that we get long mode when all the prereqs are
+ * in place. In this case, it turns on when CR0_PG is finally enabled.
+ */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ orl $EFER_LME, %eax
+ wrmsr
-nulldesc: /* offset = 0x0 */
+ /*
+ * Finally, switch to 64 bit mode by enabling paging. We have
+ * to be very careful here because all the segmentation disappears
+ * out from underneath us. The spec says we can depend on the
+ * subsequent pipelined long jump to execute. This is Magic.
+ */
+ mov %cr0, %eax
+ orl $CR0_PG, %eax
+ mov %eax, %cr3
- .word 0x0
- .word 0x0
- .byte 0x0
- .byte 0x0
- .byte 0x0
- .byte 0x0
+ .byte 0xea /* opcode for far jump */
+ .long entry_64 /* 64 bit flat address */
+ .word kernelcode-gdt /* selector offset */
-kernelcode: /* offset = 0x08 */
+ .p2align 4,0
+gdt:
+ /*
+ * All segment descriptor tables start with a null descriptor */
+ */
+ .long 0x00000000
+ .long 0x00000000
- .word 0xffff /* segment limit 0..15 */
- .word 0x0000 /* segment base 0..15 */
- .byte 0x0 /* segment base 16..23; set for 0K */
- .byte 0x9f /* flags; Type */
- .byte 0xcf /* flags; Limit */
- .byte 0x0 /* segment base 24..32 */
+ /*
+ * This is the 64 bit long mode code descriptor. There is no
+ * 64 bit data descriptor.
+ */
+kernelcode:
+ .long 0x00000000
+ .long 0x00209800
-kerneldata: /* offset = 0x10 */
+ /*
+ * This is the descriptor for the 32 bit boot code.
+ * %cs: +A, +R, -C, DPL=0, +P, +D, +G
+ * Accessed, Readable, Present, 32 bit, 4G granularity
+ */
+bootcode:
+ .long 0x0000ffff
+ .long 0x00cf9b00
- .word 0xffff /* segment limit 0..15 */
- .word 0x0000 /* segment base 0..15 */
- .byte 0x0 /* segment base 16..23; set for 0k */
- .byte 0x93 /* flags; Type */
- .byte 0xcf /* flags; Limit */
- .byte 0x0 /* segment base 24..32 */
+ /*
+ * This is the descriptor for the 32 bit boot data.
+ * We load it into %ds and %ss. The bits for each selector
+ * are interpreted slightly differently.
+ * %ds: +A, +W, -E, DPL=0, +P, +D, +G
+ * %ss: +A, +W, -E, DPL=0, +P, +B, +G
+ * Accessed, Writeable, Expand up, Present, 32 bit, 4GB
+ * For %ds, +D means 'default operand size is 32 bit'.
+ * For %ss, +B means the stack register is %esp rather than %sp.
+ */
+bootdata:
+ .long 0x0000ffff
+ .long 0x00cf9300
-bootcode: /* offset = 0x18 */
+gdtend:
- .word 0xffff /* segment limit 0..15 */
-bootCodeSeg: /* this will be modified by mpInstallTramp() */
- .word 0x0000 /* segment base 0..15 */
- .byte 0x00 /* segment base 16...23; set for 0x000xx000 */
- .byte 0x9e /* flags; Type */
- .byte 0xcf /* flags; Limit */
- .byte 0x0 /*segment base 24..32 */
+ /*
+ * The pseudo descriptor for lgdt to use.
+ */
+lgdt_desc:
+ .word gdtend - gdt /* Length */
+ .long gdt - mptramp_start /* Offset plus %ds << 4 */
-bootdata: /* offset = 0x20 */
+ .globl mptramp_end
+mptramp_end:
- .word 0xffff
-bootDataSeg: /* this will be modified by mpInstallTramp() */
- .word 0x0000 /* segment base 0..15 */
- .byte 0x00 /* segment base 16...23; set for 0x000xx000 */
- .byte 0x92
- .byte 0xcf
- .byte 0x0
-/*
- * GDT pointer for the lgdt call
- */
-
-MP_GDTptr:
-mp_gdtlimit:
- .word 0x0028
- .globl mp_gdtbase
-mp_gdtbase: /* this will be modified by mpInstallTramp() */
- .long 0
-
- .space 0x100 /* space for boot_stk - 1st temporary stack */
-boot_stk:
-
- .globl bootSTK32
-bootSTK32:
- .long 0
- .globl IdlePTD32
-IdlePTD32:
- .long 0
-
-BOOTMP_end:
-
- .globl bootMP_size
-bootMP_size:
- .long BOOTMP_end - BOOTMP_start
+ /*
+ * Yeehar! We're running in 64 bit mode! We can mostly ignore our
+ * segment registers, and get on with it.
+ * Load a basic stack pointer and jump into the kernel.
+ * Note that we are running at the correct virtual address, but with
+ * a 1:1 1GB mirrored mapping over entire address space. We had better
+ * switch to a real %cr3 promptly.
+ */
+ .text
+ .code64
+entry_64:
+ movq $bootSTK, %rsp
+ pushq $init_secondary
+ ret
More information about the p4-projects
mailing list