Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "mem.h"

#define KB              1024
#define MB              (1024*1024)

/*
 * Some machine instructions not handled by 8[al].
 */
#define DELAY           BYTE $0xEB; BYTE $0x00  /* JMP .+2 */
#define FARJUMP(s, o)   BYTE $0xEA;             /* far jump to ptr32:16 */\
                        LONG $o; WORD $s

#define NOP             BYTE $0x90
#define HLT             BYTE $0xF4

/*
 * Macro for calculating offset within the page directory base.
 * Note that this is assembler-specific hence the '<<2'.
 */
#define PDO(a)          (((((a))>>22) & 0x03FF)<<2)

/*
 * May enter here either from the 16-bit real-mode startup or
 * from other 32-bit protected mode code. For the latter case must
 * make sure the GDT is set as it would be by the 16-bit code:
 *      disable interrupts;
 *      load the GDT with the table in _gdt32p;
 *      load all the data segments
 *      load the code segment via a far jump.
 */
TEXT _start32p(SB), $0
/* if distance to _start32p32 changes, update the offset after 0xEB. */
//      jmp     .+32 (_start32p32).
        BYTE $0xEB; BYTE $(2+3*2*4+2+4)
        NOP; NOP

TEXT _gdt32p(SB), $0
        LONG    $0x0000; LONG $0
        LONG    $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
        LONG    $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)

TEXT _gdtptr32p(SB), $0
        WORD    $(3*8)
        LONG    $_gdt32p-KZERO(SB)

_start32p32:
        CLI

        MOVL    AX, _multibootheader+(48-KZERO)(SB)
        MOVL    BX, _multibootheader+(52-KZERO)(SB)

        MOVL    $_gdtptr32p-KZERO(SB), AX
        MOVL    (AX), GDTR

        MOVL    $KDSEL, AX
        MOVW    AX, DS
        MOVW    AX, ES
        MOVW    AX, FS
        MOVW    AX, GS
        MOVW    AX, SS

        DELAY
        FARJUMP(KESEL, _start32pg-KZERO(SB))

/*
 * Make the basic page tables for processor 0. Eight pages are needed for
 * the basic set:
 * a page directory, 5 pages pf page tables for mapping the first 20MB of
 * physical memory, a single physical and virtual page for the Mach structure,
 * and a page to be used later for the GDT.
 *
 * The remaining PTEs will be allocated later when memory is sized.
 * Could clear BSS here too when clearing the space for the tables,
 * but that would violate the separation of church and state.
 * The first aligned page after end[] was used for passing BIOS parameters
 * by the real-mode startup, now it's BIOSTABLES.
 */
TEXT _start32pg(SB), $0                 /* CHECK alignment (16) */
        DELAY

        MOVL    $end-KZERO(SB), DX      /* clear pages for the tables etc. */
        /* start must be page aligned, skip boot params page */
        ADDL    $(2*BY2PG-1), DX
        ANDL    $~(BY2PG-1), DX

        /*
         * zero mach page & gdt in low memory
         */
        MOVL    $(CPU0MACH-KZERO), DI
        XORL    AX, AX
        MOVL    $(2*BY2PG), CX          /* mach (phys & virt) & gdt */
        SHRL    $2, CX
        CLD
        REP;    STOSL                   /* zero mach & gdt pages */

        /*
         * zero pdb and pte for low memory
         */
        MOVL    DX, DI                  /* first page after end & boot params */
        XORL    AX, AX
        MOVL    $((1+LOWPTEPAGES)*BY2PG), CX /* pdb, n pte */
        SHRL    $2, CX
        CLD
        REP;    STOSL                   /* zero pdb & pte pages */

        /*
         * populate pdb for low memory (20MB)
         */
        MOVL    DX, AX                  /* bootstrap processor PDB (page 0) */
        MOVL    DX, DI                  /* save it for later */
        MOVL    $(PTEWRITE|PTEVALID), BX/* page permissions */

        ADDL    $BY2PG, DX              /* -> PA of first page of page table (page 1)  */
        ADDL    $PDO(KZERO), AX         /* page directory offset for KZERO */
        MOVL    DX, (AX)                /* PTE's for KZERO */
        ORL     BX, (AX)

        /* should be LOWPTEPAGES-1 repetitions of this fragment */
        ADDL    $BY2PG, DX              /* -> PA of second page of page table (page 2)  */
        ADDL    $4, AX                  /* page dir. offset for KZERO+4MB */
        MOVL    DX, (AX)                /* PTE's for KZERO */
        ORL     BX, (AX)

        ADDL    $BY2PG, DX              /* -> PA of third page of page table (page 3)  */
        ADDL    $4, AX                  /* page dir. offset for KZERO+8MB */
        MOVL    DX, (AX)                /* PTE's for KZERO */
        ORL     BX, (AX)

        ADDL    $BY2PG, DX              /* -> PA of fourth page of page table (page 4)  */
        ADDL    $4, AX                  /* page dir. offset for KZERO+12MB */
        MOVL    DX, (AX)                /* PTE's for KZERO */
        ORL     BX, (AX)

        ADDL    $BY2PG, DX              /* -> PA of fifth page of page table (page 5)  */
        ADDL    $4, AX                  /* page dir. offset for KZERO+16MB */
        MOVL    DX, (AX)                /* PTE's for KZERO */
        ORL     BX, (AX)

        /*
         * populate page tables for low memory
         */
        MOVL    DI, AX
        ADDL    $BY2PG, AX              /* PA of first page of page table */
        MOVL    $(MemMin/BY2PG), CX
_setpte:
        MOVL    BX, (AX)
        ADDL    $(1<<PGSHIFT), BX
        ADDL    $4, AX
        LOOP    _setpte

        /*
         * map the Mach page
         */
        MOVL    DI, AX
        ADDL    $BY2PG, AX              /* PA of first page of page table */
        MOVL    $(CPU0MACH-KZERO), DX   /* -> PA of Mach structure */
        MOVL    $CPU0MACH, BX           /* VA of Mach structure */
        SHRL    $10, BX                 /* create offset into PTEs */
        ANDL    $(0x3FF<<2), BX

        ADDL    BX, AX                  /* PTE offset for Mach structure */
        MOVL    DX, (AX)                /* create PTE for Mach */
        MOVL    $(PTEWRITE|PTEVALID), BX/* page permissions */
        ORL     BX, (AX)

/*
 * Now ready to use the new map. Initialise CR0 (assume the BIOS gets
 * it mostly correct for this processor type w.r.t. caches and FPU).
 * It is necessary on some processors to follow mode switching
 * with a JMP instruction to clear the prefetch queues.
 * The instruction to switch modes and the following jump instruction
 * should be identity-mapped; to this end double map KZERO at
 * virtual 0 and undo the mapping once virtual nirvana has been attained.
 * If paging is already on, don't load CR3 before setting CR0, in which
 * case most of this is a NOP and the 2nd load of CR3 actually does
 * the business.
 */
        MOVL    DI, CX                  /* load address of PDB */
        /* double-map first 20 MB, since we are running at 7 or 9 MB */
        /* should be LOWPTEPAGES repetitions */
        MOVL    PDO(KZERO)(CX), DX      /* double-map KZERO at 0 */
        MOVL    DX, PDO(0)(CX)
        MOVL    PDO(KZERO+4*MB)(CX), DX
        MOVL    DX, PDO(4*MB)(CX)
        MOVL    PDO(KZERO+8*MB)(CX), DX
        MOVL    DX, PDO(8*MB)(CX)
        MOVL    PDO(KZERO+12*MB)(CX), DX
        MOVL    DX, PDO(12*MB)(CX)
        MOVL    PDO(KZERO+16*MB)(CX), DX
        MOVL    DX, PDO(16*MB)(CX)

        MOVL    CR0, DX
        MOVL    DX, AX
        ANDL    $PG, AX                 /* check paging not already on */
        JNE     _nocr3load
        MOVL    CX, CR3                 /* paging off, safe to load cr3 */
_nocr3load:
        ORL     $(PG|0x10000), DX       /* PG|WP */
        ANDL    $~0x6000000A, DX        /* ~(CD|NW|TS|MP) */

        MOVL    $_startpg(SB), AX
        TESTL   $KZERO, AX              /* want to run protected or virtual? */
        JEQ     _to32v                  /* protected */
        MOVL    DX, CR0                 /* turn on paging */
        JMP*    AX                      /* headfirst into the new world */

TEXT _startpg(SB), $0
//      MOVL    $0, PDO(0)(CX)          /* undo double-map of KZERO at 0 */
        MOVL    CX, CR3                 /* load and flush the mmu */
_to32v:
        MOVL    $_start32v(SB), AX
        JMP*    AX                      /* into the dorkness */