1/* 2 * Start an Application Processor. This must be placed on a 4KB boundary 3 * somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However, 4 * due to some shortcuts below it's restricted further to within the 1st 5 * 64KB. The AP starts in real-mode, with 6 * CS selector set to the startup memory address/16; 7 * CS base set to startup memory address; 8 * CS limit set to 64KB; 9 * CPL and IP set to 0. 10 */ 11#include "mem.h" 12 13#define NOP BYTE $0x90 /* NOP */ 14#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \ 15 BYTE $0x01; BYTE $0x16; \ 16 WORD $gdtptr 17#define FARJUMP16(s, o) BYTE $0xEA; /* far jump to ptr16:16 */ \ 18 WORD $o; WORD $s; \ 19 NOP; NOP; NOP 20#define FARJUMP32(s, o) BYTE $0x66; /* far jump to ptr32:16 */ \ 21 BYTE $0xEA; LONG $o; WORD $s 22 23#define DELAY BYTE $0xEB; /* JMP .+2 */ \ 24 BYTE $0x00 25#define INVD BYTE $0x0F; BYTE $0x08 26#define WBINVD BYTE $0x0F; BYTE $0x09 27 28/* 29 * Macros for calculating offsets within the page directory base 30 * and page tables. Note that these are assembler-specific hence 31 * the '<<2'. 32 */ 33#define PDO(a) (((((a))>>22) & 0x03FF)<<2) 34#define PTO(a) (((((a))>>12) & 0x03FF)<<2) 35 36TEXT apbootstrap(SB), $0 37 FARJUMP16(0, _apbootstrap(SB)) 38TEXT _apvector(SB), $0 /* address APBOOTSTRAP+0x08 */ 39 LONG $0 40TEXT _appdb(SB), $0 /* address APBOOTSTRAP+0x0C */ 41 LONG $0 42TEXT _apapic(SB), $0 /* address APBOOTSTRAP+0x10 */ 43 LONG $0 44TEXT _apbootstrap(SB), $0 /* address APBOOTSTRAP+0x14 */ 45 MOVW CS, AX 46 MOVW AX, DS /* initialise DS */ 47 48 LGDT(gdtptr(SB)) /* load a basic gdt */ 49 50 MOVL CR0, AX 51 ORL $1, AX 52 MOVL AX, CR0 /* turn on protected mode */ 53 DELAY /* JMP .+2 */ 54 55 BYTE $0xB8; WORD $SELECTOR(1, SELGDT, 0)/* MOVW $SELECTOR(1, SELGDT, 0), AX */ 56 MOVW AX, DS 57 MOVW AX, ES 58 MOVW AX, FS 59 MOVW AX, GS 60 MOVW AX, SS 61 62 FARJUMP32(SELECTOR(2, SELGDT, 0), _ap32-KZERO(SB)) 63 64/* 65 * For Pentiums and higher, the code that enables paging must come from 66 * pages that are identity mapped. 67 * To this end double map KZERO at virtual 0 and undo the mapping once virtual 68 * nirvana has been obtained. 69 */ 70TEXT _ap32(SB), $0 71 MOVL _appdb-KZERO(SB), CX /* physical address of PDB */ 72 MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */ 73 MOVL DX, (PDO(0))(CX) 74 MOVL CX, CR3 /* load and flush the mmu */ 75 76 MOVL CR0, DX 77 ORL $0x80010000, DX /* PG|WP */ 78 ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */ 79 80 MOVL $_appg(SB), AX 81 MOVL DX, CR0 /* turn on paging */ 82 JMP* AX 83 84TEXT _appg(SB), $0 85 MOVL CX, AX /* physical address of PDB */ 86 ORL $KZERO, AX 87 MOVL $0, (PDO(0))(AX) /* undo double-map of KZERO at 0 */ 88 MOVL CX, CR3 /* load and flush the mmu */ 89 90 MOVL $(MACHADDR+MACHSIZE-4), SP 91 92 MOVL $0, AX 93 PUSHL AX 94 POPFL 95 96 MOVL _apapic(SB), AX 97 MOVL AX, (SP) 98 MOVL _apvector(SB), AX 99 CALL* AX 100_aphalt: 101 HLT 102 JMP _aphalt 103 104TEXT gdt(SB), $0 105 LONG $0x0000; LONG $0 106 LONG $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) 107 LONG $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) 108TEXT gdtptr(SB), $0 109 WORD $(3*8-1) 110 LONG $gdt-KZERO(SB) 111