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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
/**
* @file boot/head.S
* @author matthewj
* @author de0u
*/
/* N.B. This is NOT to be construed as style guidance!! */
/* N.B. This is NOT to be construed as style guidance!! */
/* N.B. This is NOT to be construed as style guidance!! */
#include <simics.h>
#include <x86/video_defines.h>
#include <x86/seg.h>
/** @brief Entry point from the bootloader */
.global _start
/** @brief Start of the kernel image */
.global __kimg_start
/** @brief Start of the init GDT */
.global init_gdt
/** @brief Start of the init IDT */
.global init_idt
/** @brief Start of the init TSS */
.global init_tss
.global init_tss_size
.text
__kimg_start:
mb_header:
/* Not a complete Multiboot header, but GRUB can live with it. */
.long 0x1BADB002 /**< Multiboot magic word */
.long 0x00000000 /**< Flags field */
.long (0 - 0x1BADB002 - 0x00000000) /**< Checksum */
.space 244
init_idt: /* 0x100100 */
.space 64
.long 0x001009b8
.long 0x00108e00
.space 1976
init_gdt: /* 0x100900 */
.long 0x00000000
.long 0x00000000
/* Next two lines need to be kept in sync with smp/smp.c */
.long 0x09500067
.long 0x00008910
.long 0x0000ffff
.long 0x00cf9b00
.long 0x0000ffff
.long 0x00cf9300
.long 0x0000ffff
.long 0x00cffb00
.long 0x0000ffff
.long 0x00cff200
/* Spare segment descriptors follow, see x86/seg.h */
.long 0x00000000 /**< SEGSEL_SPARE0 word 0 */
.long 0x00000000
.long 0x00000000 /**< SEGSEL_SPARE1 word 0 */
.long 0x00000000
.long 0x00000000 /**< SEGSEL_SPARE2 word 0 */
.long 0x00000000
.long 0x00000000 /**< SEGSEL_SPARE3 word 0 */
.long 0x00000000
init_tss: /* 0x100950 */
.space 8
.word 0x0018
.space 92 /* fills with 0's */
.word 0x0068
init_tss_end:
df_handler: /* 0x1009b8 */
cli
/* Get something "out there" first thing */
leal fmsg, %ecx
movl $SIM_PUTS, %ebx
xchg %ebx, %ebx
/* We got here because we were in trouble, so be conservative */
movl $SEGSEL_KERNEL_DS, %eax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
leal istack, %esp
subl $2048, %esp /* try to avoid wiping state */
/* Now we probably have a runtime environment */
leal fbytes, %eax
pushl %eax
call blat
df_handler_loop:
jmp df_handler_loop
_start:
cmpl $0x15410DE0, %eax
je _guest_start
cli /* I sure HOPE this is superfluous */
leal istack, %esp /* Load initial stack pointer */
movl $init_tss, %eax
subl $init_gdt, %eax
subl $1, %eax
pushl %eax /* gdt limit == sizeof(gdt)-1 */
pushl $init_gdt
call lgdt
addl $8, %esp
movl $init_gdt, %eax
subl $init_idt, %eax
subl $1, %eax
pushl %eax /* idt limit == sizeof(idt)-1 */
pushl $init_idt
call lidt
addl $8, %esp
movl $SEGSEL_TSS, %eax
ltr %ax
pushl %esp /* Pass in the top of the initial stack */
pushl %ebx /* Pass in the multiboot structure */
call mb_entry /* Call the C entry point */
/* "should not get here" */
pushl $pbytes
call blat
stuck:
jmp stuck
_guest_start:
leal istack, %esp /* Load initial stack pointer */
pushl %ecx /* Max legal vaddr */
pushl %ebx /* Number of max legal vframe */
call hv_guest_entry
addl $8,%esp /* In case anybody's keeping score */
jmp stuck
# void blat(uint8_t *bytes)
blat:
pushl %ebp
movl %esp, %ebp
pushl %ebx
pushl %esi
pushl %edi
movl 8(%ebp), %eax # bytes
pushl %eax
call strlen
movl %eax, %edx # EDX: strlen(bytes)
add $4, %esp
movl $CONSOLE_MEM_BASE, %edi # EDI: dest
movl $CONSOLE_WIDTH, %ebx
imull $CONSOLE_HEIGHT, %ebx
sall $1, %ebx # 2*width*height
addl %edi, %ebx # EBX: limit
subl %edx, %ebx # EBX: limit (round down)
movl %es, %eax
pushl %eax # save ES
movl %ds, %eax
movl %eax, %es # force ES to match DS
movs:
movl %edx, %ecx # ECX: count
movl 8(%ebp), %esi # ESI: source
rep movsb # ECX bytes from DS:ESI to ES:EDI
cmpl %edi, %ebx
jg movs
popl %eax
movl %eax, %es # restore ES
popl %edi
popl %esi
popl %ebx
popl %ebp
ret
init_tss_size:
.long (init_tss_end - init_tss)
.data
fmsg:
.asciz "\n***** Double fault!\n"
fbytes:
.asciz "D\ro\ru\rb\rl\re\r \rf\ra\ru\rl\rt\r!\r \r"
pmsg:
.asciz "Kernel cannot return()!"
pbytes:
.asciz "K\re\rr\rn\re\rl\r \rc\ra\rn\rn\ro\rt\r \rr\re\rt\ru\rr\rn\r(\r)\r!\r \r"
/* Initial stack */
.align 4
.space 4096
istack:
|