summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/apbootstrap.s
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/pc/apbootstrap.s
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/pc/apbootstrap.s')
-rwxr-xr-xsys/src/9/pc/apbootstrap.s110
1 files changed, 110 insertions, 0 deletions
diff --git a/sys/src/9/pc/apbootstrap.s b/sys/src/9/pc/apbootstrap.s
new file mode 100755
index 000000000..5407530f0
--- /dev/null
+++ b/sys/src/9/pc/apbootstrap.s
@@ -0,0 +1,110 @@
+/*
+ * 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 LGDT(gdtptr) BYTE $0x0F; /* LGDT */ \
+ BYTE $0x01; BYTE $0x16; \
+ WORD $gdtptr
+#define FARJUMP16(s, o) BYTE $0xEA; /* far jump to ptr16:16 */ \
+ WORD $o; WORD $s; \
+ NOP; NOP; NOP
+#define FARJUMP32(s, o) BYTE $0x66; /* far jump to ptr32:16 */ \
+ BYTE $0xEA; LONG $o; WORD $s
+
+#define DELAY BYTE $0xEB; /* JMP .+2 */ \
+ BYTE $0x00
+#define INVD BYTE $0x0F; BYTE $0x08
+#define WBINVD BYTE $0x0F; BYTE $0x09
+
+/*
+ * Macros for calculating offsets within the page directory base
+ * and page tables. Note that these are assembler-specific hence
+ * the '<<2'.
+ */
+#define PDO(a) (((((a))>>22) & 0x03FF)<<2)
+#define PTO(a) (((((a))>>12) & 0x03FF)<<2)
+
+TEXT apbootstrap(SB), $0
+ FARJUMP16(0, _apbootstrap(SB))
+TEXT _apvector(SB), $0 /* address APBOOTSTRAP+0x08 */
+ LONG $0
+TEXT _appdb(SB), $0 /* address APBOOTSTRAP+0x0C */
+ LONG $0
+TEXT _apapic(SB), $0 /* address APBOOTSTRAP+0x10 */
+ LONG $0
+TEXT _apbootstrap(SB), $0 /* address APBOOTSTRAP+0x14 */
+ MOVW CS, AX
+ MOVW AX, DS /* initialise DS */
+
+ LGDT(gdtptr(SB)) /* load a basic gdt */
+
+ MOVL CR0, AX
+ ORL $1, AX
+ MOVL AX, CR0 /* turn on protected mode */
+ DELAY /* JMP .+2 */
+
+ BYTE $0xB8; WORD $SELECTOR(1, SELGDT, 0)/* MOVW $SELECTOR(1, SELGDT, 0), AX */
+ MOVW AX, DS
+ MOVW AX, ES
+ MOVW AX, FS
+ MOVW AX, GS
+ MOVW AX, SS
+
+ FARJUMP32(SELECTOR(2, SELGDT, 0), _ap32-KZERO(SB))
+
+/*
+ * For Pentiums and higher, the code that enables paging must come from
+ * pages that are identity mapped.
+ * To this end double map KZERO at virtual 0 and undo the mapping once virtual
+ * nirvana has been obtained.
+ */
+TEXT _ap32(SB), $0
+ MOVL _appdb-KZERO(SB), CX /* physical address of PDB */
+ MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */
+ MOVL DX, (PDO(0))(CX)
+ MOVL CX, CR3 /* load and flush the mmu */
+
+ MOVL CR0, DX
+ ORL $0x80010000, DX /* PG|WP */
+ ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */
+
+ MOVL $_appg(SB), AX
+ MOVL DX, CR0 /* turn on paging */
+ JMP* AX
+
+TEXT _appg(SB), $0
+ MOVL CX, AX /* physical address of PDB */
+ ORL $KZERO, AX
+ MOVL $0, (PDO(0))(AX) /* undo double-map of KZERO at 0 */
+ MOVL CX, CR3 /* load and flush the mmu */
+
+ MOVL $(MACHADDR+MACHSIZE-4), SP
+
+ MOVL $0, AX
+ PUSHL AX
+ POPFL
+
+ MOVL _apapic(SB), AX
+ MOVL AX, (SP)
+ MOVL _apvector(SB), AX
+ CALL* AX
+_aphalt:
+ HLT
+ JMP _aphalt
+
+TEXT gdt(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 gdtptr(SB), $0
+ WORD $(3*8-1)
+ LONG $gdt-KZERO(SB)