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
|
#include <linux/config.h>
.section __xen_guest
.ascii "GUEST_OS=linux,GUEST_VER=2.6,XEN_VER=2.0,VIRT_BASE=0xC0000000"
.ascii ",LOADER=generic"
#ifdef CONFIG_XEN_WRITABLE_PAGETABLES
.ascii ",PT_MODE_WRITABLE"
#endif
.byte 0
.text
#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/thread_info.h>
#include <asm/asm_offsets.h>
#include <asm/hypervisor-ifs/arch-x86_32.h>
/*
* References to members of the new_cpu_data structure.
*/
#define X86 new_cpu_data+CPUINFO_x86
#define X86_VENDOR new_cpu_data+CPUINFO_x86_vendor
#define X86_MODEL new_cpu_data+CPUINFO_x86_model
#define X86_MASK new_cpu_data+CPUINFO_x86_mask
#define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math
#define X86_CPUID new_cpu_data+CPUINFO_cpuid_level
#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability
#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id
ENTRY(startup_32)
cld
/* Set up the stack pointer */
lss stack_start,%esp
/* Copy the necessary stuff from xen_start_info structure. */
mov $xen_start_info_union,%edi
mov $128,%ecx
rep movsl
checkCPUtype:
/* get vendor info */
xorl %eax,%eax # call CPUID with 0 -> return vendor ID
cpuid
movl %eax,X86_CPUID # save CPUID level
movl %ebx,X86_VENDOR_ID # lo 4 chars
movl %edx,X86_VENDOR_ID+4 # next 4 chars
movl %ecx,X86_VENDOR_ID+8 # last 4 chars
movl $1,%eax # Use the CPUID instruction to get CPU type
cpuid
movb %al,%cl # save reg for future use
andb $0x0f,%ah # mask processor family
movb %ah,X86
andb $0xf0,%al # mask model
shrb $4,%al
movb %al,X86_MODEL
andb $0x0f,%cl # mask mask revision
movb %cl,X86_MASK
movl %edx,X86_CAPABILITY
xorl %eax,%eax # Clear FS/GS and LDT
movl %eax,%fs
movl %eax,%gs
cld # gcc2 wants the direction flag cleared at all times
call start_kernel
L6:
jmp L6 # main should never return here, but
# just in case, we know what happens.
ENTRY(lgdt_finish)
movl $(__KERNEL_DS),%eax # reload all the segment registers
movw %ax,%ss # after changing gdt.
movl $(__USER_DS),%eax # DS/ES contains default USER segment
movw %ax,%ds
movw %ax,%es
popl %eax # reload CS by intersegment return
pushl $(__KERNEL_CS)
pushl %eax
lret
ENTRY(stack_start)
.long init_thread_union+THREAD_SIZE
.long __BOOT_DS
# XXXcl
.globl idt_descr
.globl cpu_gdt_descr
ALIGN
.word 0 # 32-bit align idt_desc.address
idt_descr:
.word IDT_ENTRIES*8-1 # idt contains 256 entries
.long idt_table
# XXXcl
# boot GDT descriptor (later on used by CPU#0):
.word 0 # 32 bit align gdt_desc.address
cpu_gdt_descr:
.word GDT_SIZE
.long cpu_gdt_table
.fill NR_CPUS-1,8,0 # space for the other GDT descriptors
.org 0x1000
ENTRY(empty_zero_page)
.org 0x2000
ENTRY(swapper_pg_dir)
.org 0x3000
ENTRY(cpu_gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* 0x0b reserved */
.quad 0x0000000000000000 /* 0x13 reserved */
.quad 0x0000000000000000 /* 0x1b reserved */
.quad 0x0000000000000000 /* 0x20 unused */
.quad 0x0000000000000000 /* 0x28 unused */
.quad 0x0000000000000000 /* 0x33 TLS entry 1 */
.quad 0x0000000000000000 /* 0x3b TLS entry 2 */
.quad 0x0000000000000000 /* 0x43 TLS entry 3 */
.quad 0x0000000000000000 /* 0x4b reserved */
.quad 0x0000000000000000 /* 0x53 reserved */
.quad 0x0000000000000000 /* 0x5b reserved */
.quad 0x00cfbb000000c3ff /* 0x60 kernel 4GB code at 0x00000000 */
.quad 0x00cfb3000000c3ff /* 0x68 kernel 4GB data at 0x00000000 */
.quad 0x00cffb000000c3ff /* 0x73 user 4GB code at 0x00000000 */
.quad 0x00cff3000000c3ff /* 0x7b user 4GB data at 0x00000000 */
.quad 0x0000000000000000 /* 0x80 TSS descriptor */
.quad 0x0000000000000000 /* 0x88 LDT descriptor */
/* Segments used for calling PnP BIOS */
.quad 0x0000000000000000 /* 0x90 32-bit code */
.quad 0x0000000000000000 /* 0x98 16-bit code */
.quad 0x0000000000000000 /* 0xa0 16-bit data */
.quad 0x0000000000000000 /* 0xa8 16-bit data */
.quad 0x0000000000000000 /* 0xb0 16-bit data */
/*
* The APM segments have byte granularity and their bases
* and limits are set at run time.
*/
.quad 0x0000000000000000 /* 0xb8 APM CS code */
.quad 0x0000000000000000 /* 0xc0 APM CS 16 code (16 bit) */
.quad 0x0000000000000000 /* 0xc8 APM DS data */
.quad 0x0000000000000000 /* 0xd0 - unused */
.quad 0x0000000000000000 /* 0xd8 - unused */
.quad 0x0000000000000000 /* 0xe0 - unused */
.quad 0x0000000000000000 /* 0xe8 - unused */
.quad 0x0000000000000000 /* 0xf0 - unused */
.quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
.fill GDT_ENTRIES-32,8,0
.org 0x4000
ENTRY(default_ldt)
.org 0x5000
/*
* Real beginning of normal "text" segment
*/
ENTRY(stext)
ENTRY(_stext)
|