1*4de34a7eSDavid du Colombier/* 2*4de34a7eSDavid du Colombier * Start an Application Processor. This must be placed on a 4KB boundary 3*4de34a7eSDavid du Colombier * somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However, 4*4de34a7eSDavid du Colombier * due to some shortcuts below it's restricted further to within the 1st 5*4de34a7eSDavid du Colombier * 64KB. The AP starts in real-mode, with 6*4de34a7eSDavid du Colombier * CS selector set to the startup memory address/16; 7*4de34a7eSDavid du Colombier * CS base set to startup memory address; 8*4de34a7eSDavid du Colombier * CS limit set to 64KB; 9*4de34a7eSDavid du Colombier * CPL and IP set to 0. 10*4de34a7eSDavid du Colombier */ 117dd7cddfSDavid du Colombier#include "mem.h" 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier#define NOP BYTE $0x90 /* NOP */ 147dd7cddfSDavid du Colombier#define LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \ 157dd7cddfSDavid du Colombier BYTE $0x01; BYTE $0x16; \ 167dd7cddfSDavid du Colombier WORD $gdtptr 177dd7cddfSDavid du Colombier#define FARJUMP16(s, o) BYTE $0xEA; /* far jump to ptr16:16 */ \ 187dd7cddfSDavid du Colombier WORD $o; WORD $s; \ 197dd7cddfSDavid du Colombier NOP; NOP; NOP 207dd7cddfSDavid du Colombier#define FARJUMP32(s, o) BYTE $0x66; /* far jump to ptr32:16 */ \ 217dd7cddfSDavid du Colombier BYTE $0xEA; LONG $o; WORD $s 227dd7cddfSDavid du Colombier 237dd7cddfSDavid du Colombier#define DELAY BYTE $0xEB; /* JMP .+2 */ \ 247dd7cddfSDavid du Colombier BYTE $0x00 257dd7cddfSDavid du Colombier#define INVD BYTE $0x0F; BYTE $0x08 267dd7cddfSDavid du Colombier#define WBINVD BYTE $0x0F; BYTE $0x09 277dd7cddfSDavid du Colombier 287dd7cddfSDavid du Colombier/* 297dd7cddfSDavid du Colombier * Macros for calculating offsets within the page directory base 307dd7cddfSDavid du Colombier * and page tables. Note that these are assembler-specific hence 317dd7cddfSDavid du Colombier * the '<<2'. 327dd7cddfSDavid du Colombier */ 337dd7cddfSDavid du Colombier#define PDO(a) (((((a))>>22) & 0x03FF)<<2) 347dd7cddfSDavid du Colombier#define PTO(a) (((((a))>>12) & 0x03FF)<<2) 357dd7cddfSDavid du Colombier 367dd7cddfSDavid du ColombierTEXT apbootstrap(SB), $0 377dd7cddfSDavid du Colombier FARJUMP16(0, _apbootstrap(SB)) 387dd7cddfSDavid du ColombierTEXT _apvector(SB), $0 /* address APBOOTSTRAP+0x08 */ 397dd7cddfSDavid du Colombier LONG $0 407dd7cddfSDavid du ColombierTEXT _appdb(SB), $0 /* address APBOOTSTRAP+0x0C */ 417dd7cddfSDavid du Colombier LONG $0 427dd7cddfSDavid du ColombierTEXT _apapic(SB), $0 /* address APBOOTSTRAP+0x10 */ 437dd7cddfSDavid du Colombier LONG $0 447dd7cddfSDavid du ColombierTEXT _apbootstrap(SB), $0 /* address APBOOTSTRAP+0x14 */ 457dd7cddfSDavid du Colombier MOVW CS, AX 467dd7cddfSDavid du Colombier MOVW AX, DS /* initialise DS */ 477dd7cddfSDavid du Colombier 487dd7cddfSDavid du Colombier LGDT(gdtptr(SB)) /* load a basic gdt */ 497dd7cddfSDavid du Colombier 507dd7cddfSDavid du Colombier MOVL CR0, AX 517dd7cddfSDavid du Colombier ORL $1, AX 527dd7cddfSDavid du Colombier MOVL AX, CR0 /* turn on protected mode */ 537dd7cddfSDavid du Colombier DELAY /* JMP .+2 */ 547dd7cddfSDavid du Colombier 557dd7cddfSDavid du Colombier BYTE $0xB8; WORD $SELECTOR(1, SELGDT, 0)/* MOVW $SELECTOR(1, SELGDT, 0), AX */ 567dd7cddfSDavid du Colombier MOVW AX, DS 577dd7cddfSDavid du Colombier MOVW AX, ES 587dd7cddfSDavid du Colombier MOVW AX, FS 597dd7cddfSDavid du Colombier MOVW AX, GS 607dd7cddfSDavid du Colombier MOVW AX, SS 617dd7cddfSDavid du Colombier 627dd7cddfSDavid du Colombier FARJUMP32(SELECTOR(2, SELGDT, 0), _ap32-KZERO(SB)) 637dd7cddfSDavid du Colombier 647dd7cddfSDavid du Colombier/* 659a747e4fSDavid du Colombier * For Pentiums and higher, the code that enables paging must come from 669a747e4fSDavid du Colombier * pages that are identity mapped. 677dd7cddfSDavid du Colombier * To this end double map KZERO at virtual 0 and undo the mapping once virtual 687dd7cddfSDavid du Colombier * nirvana has been obtained. 697dd7cddfSDavid du Colombier */ 707dd7cddfSDavid du ColombierTEXT _ap32(SB), $0 717dd7cddfSDavid du Colombier MOVL _appdb-KZERO(SB), CX /* physical address of PDB */ 727dd7cddfSDavid du Colombier MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */ 737dd7cddfSDavid du Colombier MOVL DX, (PDO(0))(CX) 747dd7cddfSDavid du Colombier MOVL CX, CR3 /* load and flush the mmu */ 757dd7cddfSDavid du Colombier 767dd7cddfSDavid du Colombier MOVL CR0, DX 777dd7cddfSDavid du Colombier ORL $0x80010000, DX /* PG|WP */ 787dd7cddfSDavid du Colombier ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */ 797dd7cddfSDavid du Colombier 807dd7cddfSDavid du Colombier MOVL $_appg(SB), AX 817dd7cddfSDavid du Colombier MOVL DX, CR0 /* turn on paging */ 827dd7cddfSDavid du Colombier JMP* AX 837dd7cddfSDavid du Colombier 847dd7cddfSDavid du ColombierTEXT _appg(SB), $0 857dd7cddfSDavid du Colombier MOVL CX, AX /* physical address of PDB */ 867dd7cddfSDavid du Colombier ORL $KZERO, AX 877dd7cddfSDavid du Colombier MOVL $0, (PDO(0))(AX) /* undo double-map of KZERO at 0 */ 887dd7cddfSDavid du Colombier MOVL CX, CR3 /* load and flush the mmu */ 897dd7cddfSDavid du Colombier 907dd7cddfSDavid du Colombier MOVL $(MACHADDR+MACHSIZE-4), SP 917dd7cddfSDavid du Colombier 927dd7cddfSDavid du Colombier MOVL $0, AX 937dd7cddfSDavid du Colombier PUSHL AX 947dd7cddfSDavid du Colombier POPFL 957dd7cddfSDavid du Colombier 967dd7cddfSDavid du Colombier MOVL _apapic(SB), AX 977dd7cddfSDavid du Colombier MOVL AX, (SP) 987dd7cddfSDavid du Colombier MOVL _apvector(SB), AX 997dd7cddfSDavid du Colombier CALL* AX 1007dd7cddfSDavid du Colombier_aphalt: 1017dd7cddfSDavid du Colombier HLT 1027dd7cddfSDavid du Colombier JMP _aphalt 1037dd7cddfSDavid du Colombier 1047dd7cddfSDavid du ColombierTEXT gdt(SB), $0 1057dd7cddfSDavid du Colombier LONG $0x0000; LONG $0 1067dd7cddfSDavid du Colombier LONG $0xFFFF; LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) 1077dd7cddfSDavid du Colombier LONG $0xFFFF; LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) 1087dd7cddfSDavid du ColombierTEXT gdtptr(SB), $0 1099a747e4fSDavid du Colombier WORD $(3*8-1) 1107dd7cddfSDavid du Colombier LONG $gdt-KZERO(SB) 111