Date: Thu, 30 Oct 2003 19:13:30 -0800 (PST) From: Peter Wemm <peter@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 40926 for review Message-ID: <200310310313.h9V3DUKn008335@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=40926 Change 40926 by peter@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200310310313.h9V3DUKn008335>