plan9fox/sys/src/9/pc64/apbootstrap.s

172 lines
3.9 KiB
ArmAsm
Raw Normal View History

2014-02-01 09:25:10 +00:00
/*
* Start an Application Processor. This must be placed on a 4KB boundary
* somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However,
* due to some shortcuts below it's restricted further to within the 1st
* 64KB. The AP starts in real-mode, with
* CS selector set to the startup memory address/16;
* CS base set to startup memory address;
* CS limit set to 64KB;
* CPL and IP set to 0.
*/
#include "mem.h"
#define NOP BYTE $0x90 /* NOP */
#define pFARJMP32(s, o) BYTE $0xea; /* far jmp ptr32:16 */ \
LONG $o; WORD $s
#define rFARJMP16(s, o) BYTE $0xea; /* far jump ptr16:16 */ \
WORD $o; WORD $s;
#define rFARJMP32(s, o) BYTE $0x66; /* far jump ptr32:16 */ \
pFARJMP32(s, o)
#define rLGDT(gdtptr) BYTE $0x0f; /* LGDT */ \
BYTE $0x01; BYTE $0x16; \
WORD $gdtptr
#define rMOVAX(i) BYTE $0xb8; /* i -> AX */ \
WORD $i;
#define DELAY BYTE $0xEB; /* JMP .+2 */ \
BYTE $0x00
MODE $16
TEXT apbootstrap(SB), 1, $-4
rFARJMP16(0, _apbootstrap-KZERO(SB))
NOP; NOP; NOP;
TEXT _apvector(SB), 1, $-4 /* address APBOOTSTRAP+0x08 */
QUAD $0
TEXT _appml4(SB), 1, $-4 /* address APBOOTSTRAP+0x10 */
QUAD $0
TEXT _apapic(SB), 1, $-4 /* address APBOOTSTRAP+0x18 */
QUAD $0
TEXT _apmach(SB), 1, $-4 /* address APBOOTSTRAP+0x20 */
QUAD $0
TEXT _apefer(SB), 1, $-4
QUAD $0x100 /* Long Mode Enable */
2014-02-01 09:25:10 +00:00
TEXT _apbootstrap(SB), 1, $-4
MOVW CS, AX
MOVW AX, DS /* initialise DS */
rLGDT(_gdtptr32p<>-KZERO(SB)) /* load a basic gdt */
MOVL CR0, AX
ORL $1, AX
MOVL AX, CR0 /* turn on protected mode */
DELAY /* JMP .+2 */
rFARJMP16(SELECTOR(3, SELGDT, 0), _ap32-KZERO(SB))
/*
* Enable and activate Long Mode. From the manual:
* make sure Page Size Extentions are off, and Page Global
* Extensions and Physical Address Extensions are on in CR4;
* set Long Mode Enable in the Extended Feature Enable MSR;
* set Paging Enable in CR0;
* make an inter-segment jump to the Long Mode code.
* It's all in 32-bit mode until the jump is made.
*/
MODE $32
TEXT _ap32(SB), 1, $-4
MOVW $SELECTOR(2, SELGDT, 0), AX
MOVW AX, DS
MOVW AX, ES
MOVW AX, FS
MOVW AX, GS
MOVW AX, SS
MOVL _appml4-KZERO(SB), AX /* physical address of PML4 */
MOVL AX, CR3 /* load the mmu */
DELAY
MOVL CR4, AX
ANDL $~0x00000010, AX /* Page Size */
ORL $0x000000A0, AX /* Page Global, Phys. Address */
MOVL AX, CR4
MOVL $0xc0000080, CX /* Extended Feature Enable */
RDMSR
ORL _apefer-KZERO(SB), AX
2014-02-01 09:25:10 +00:00
WRMSR
MOVL CR0, DX
ANDL $~0x6000000a, DX
ORL $0x80010000, DX /* Paging Enable, Write Protect */
MOVL DX, CR0
pFARJMP32(SELECTOR(KESEG, SELGDT, 0), _ap64-KZERO(SB))
/*
* Long mode. Welcome to 2003.
* Jump out of the identity map space;
* load a proper long mode GDT;
* initialise the stack and call the
* C startup code in m->splpc.
*/
MODE $64
TEXT _ap64(SB), 1, $-4
MOVQ $_gdtptr64v<>(SB), AX
MOVL (AX), GDTR
XORQ AX, AX
MOVW AX, DS /* not used in long mode */
MOVW AX, ES /* not used in long mode */
MOVW AX, FS
MOVW AX, GS
MOVW AX, SS /* not used in long mode */
MOVW AX, LDTR
MOVQ _apmach(SB), SP
MOVQ AX, RUSER /* up = 0; */
MOVQ SP, RMACH /* m = apmach */
ADDQ $MACHSIZE, SP
PUSHQ AX /* clear flags */
POPFQ
MOVQ _apvector(SB), AX
MOVQ _apapic(SB), RARG
PUSHQ RARG
CALL *AX
_halt:
HLT
JMP _halt
TEXT _gdt<>(SB), 1, $-4
/* null descriptor */
LONG $0
LONG $0
/* (KESEG) 64 bit long mode exec segment */
LONG $(0xFFFF)
LONG $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR)
/* 32 bit data segment descriptor for 4 gigabytes (PL 0) */
LONG $(0xFFFF)
LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
/* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */
LONG $(0xFFFF)
LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
TEXT _gdtptr32p<>(SB), 1, $-4
WORD $(4*8-1)
LONG $_gdt<>-KZERO(SB)
TEXT _gdtptr64p<>(SB), 1, $-4
WORD $(4*8-1)
QUAD $_gdt<>-KZERO(SB)
TEXT _gdtptr64v<>(SB), 1, $-4
WORD $(4*8-1)
QUAD $_gdt<>(SB)