1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include "mem.h"
MODE $64
/*
* Turn off MMU, then memmove the new kernel to its correct location
* in physical memory. Then jumps the to start of the kernel.
*/
TEXT main(SB), 1, $-4
MOVL RARG, DI /* destination */
MOVL p2+8(FP), SI /* source */
MOVL n+16(FP), BX /* byte count */
/* load zero length idt */
MOVL $_idtptr64p<>(SB), AX
MOVL (AX), IDTR
/* load temporary gdt */
MOVL $_gdtptr64p<>(SB), AX
MOVL (AX), GDTR
/* move stack below destination */
MOVL DI, SP
/* load CS with 32bit code segment */
PUSHQ $SELECTOR(3, SELGDT, 0)
PUSHQ $_warp32<>(SB)
RETFQ
MODE $32
TEXT _warp32<>(SB), 1, $-4
/* load 32bit data segments */
MOVL $SELECTOR(2, SELGDT, 0), AX
MOVW AX, DS
MOVW AX, ES
MOVW AX, FS
MOVW AX, GS
MOVW AX, SS
/* turn off paging */
MOVL CR0, AX
ANDL $0x7fffffff, AX /* ~(PG) */
MOVL AX, CR0
MOVL $0, AX
MOVL AX, CR3
/* disable long mode */
MOVL $0xc0000080, CX /* Extended Feature Enable */
RDMSR
ANDL $0xfffffeff, AX /* Long Mode Disable */
WRMSR
/* diable pae */
MOVL CR4, AX
ANDL $0xffffff5f, AX /* ~(PAE|PGE) */
MOVL AX, CR4
MOVL BX, CX /* byte count */
MOVL DI, AX /* save entry point */
/*
* the source and destination may overlap.
* determine whether to copy forward or backwards
*/
CMPL SI, DI
JGT _forward
MOVL SI, DX
ADDL CX, DX
CMPL DX, DI
JGT _back
_forward:
CLD
REP; MOVSB
_startkernel:
/* jump to entry point */
JMP* AX
_back:
ADDL CX, DI
ADDL CX, SI
SUBL $1, DI
SUBL $1, SI
STD
REP; MOVSB
JMP _startkernel
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 _gdtptr64p<>(SB), 1, $-4
WORD $(4*8-1)
QUAD $_gdt<>(SB)
TEXT _idtptr64p<>(SB), 1, $-4
WORD $0
QUAD $0
|