direct-io.hg

view tools/firmware/vmxassist/setup.c @ 7477:5a7baecb1c70

Fix an issue for passing arguement from control panel to deivce model
for some arguemnt like 'localtime', 'isa', device model need an argument
"-localtime", instead of "-localtime 1"
Signed-off-by: Xiaofeng Ling <xiaofeng.ling@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Sun Oct 23 16:51:47 2005 +0100 (2005-10-23)
parents 61b3b357d827
children f1b361b05bf3
line source
1 /*
2 * setup.c: Setup the world for vmxassist.
3 *
4 * Leendert van Doorn, leendert@watson.ibm.com
5 * Copyright (c) 2005, International Business Machines Corporation.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 * Place - Suite 330, Boston, MA 02111-1307 USA.
19 */
20 #include "vm86.h"
21 #include "util.h"
22 #include "machine.h"
24 #if (VMXASSIST_BASE != TEXTADDR)
25 #error VMXAssist base mismatch
26 #endif
28 #define NR_PGD (PGSIZE / sizeof(unsigned))
30 #define min(a, b) ((a) > (b) ? (b) : (a))
32 /* Which CPU are we booting, and what is the initial CS segment? */
33 int booting_cpu, booting_vector;
35 unsigned long long gdt[] __attribute__ ((aligned(32))) = {
36 0x0000000000000000ULL, /* 0x00: reserved */
37 0x0000890000000000ULL, /* 0x08: 32-bit TSS */
38 0x00CF9A000000FFFFULL, /* 0x10: CS 32-bit */
39 0x00CF92000000FFFFULL, /* 0x18: DS 32-bit */
40 };
42 struct dtr gdtr = { sizeof(gdt)-1, (unsigned long) &gdt };
44 struct tss tss __attribute__ ((aligned(4)));
46 unsigned long long idt[NR_TRAPS] __attribute__ ((aligned(32)));
48 struct dtr idtr = { sizeof(idt)-1, (unsigned long) &idt };
50 #ifdef TEST
51 unsigned pgd[NR_PGD] __attribute__ ((aligned(PGSIZE))) = { 0 };
53 struct e820entry e820map[] = {
54 { 0x0000000000000000ULL, 0x000000000009F800ULL, E820_RAM },
55 { 0x000000000009F800ULL, 0x0000000000000800ULL, E820_RESERVED },
56 { 0x00000000000A0000ULL, 0x0000000000020000ULL, E820_IO },
57 { 0x00000000000C0000ULL, 0x0000000000040000ULL, E820_RESERVED },
58 { 0x0000000000100000ULL, 0x0000000000000000ULL, E820_RAM },
59 { 0x0000000000000000ULL, 0x0000000000001000ULL, E820_SHARED },
60 { 0x0000000000000000ULL, 0x0000000000003000ULL, E820_NVS },
61 { 0x0000000000003000ULL, 0x000000000000A000ULL, E820_ACPI },
62 { 0x00000000FEC00000ULL, 0x0000000001400000ULL, E820_IO },
63 };
64 #endif /* TEST */
66 struct vmx_assist_context oldctx;
67 struct vmx_assist_context newctx;
69 unsigned long memory_size;
70 int initialize_real_mode;
72 extern char stack[], stack_top[];
73 extern unsigned trap_handlers[];
75 void
76 banner(void)
77 {
78 printf("VMXAssist (%s)\n", __DATE__);
80 /* Bochs its way to convey memory size */
81 memory_size = ((get_cmos(0x35) << 8) | get_cmos(0x34)) << 6;
82 if (memory_size > 0x3bc000)
83 memory_size = 0x3bc000;
84 memory_size = (memory_size << 10) + 0xF00000;
85 if (memory_size <= 0xF00000)
86 memory_size =
87 (((get_cmos(0x31) << 8) | get_cmos(0x30)) + 0x400) << 10;
88 memory_size += 0x400 << 10; /* + 1MB */
90 #ifdef TEST
91 /* Create an SMAP for our debug environment */
92 e820map[4].size = memory_size - e820map[4].addr - PGSIZE;
93 e820map[5].addr = memory_size - PGSIZE;
94 e820map[6].addr = memory_size;
95 e820map[7].addr += memory_size;
97 *LINUX_E820_MAP_NR = sizeof(e820map)/sizeof(e820map[0]);
98 memcpy(LINUX_E820_MAP, e820map, sizeof(e820map));
99 #endif
101 printf("Memory size %ld MB\n", memory_size >> 20);
102 printf("E820 map:\n");
103 print_e820_map(LINUX_E820_MAP, *LINUX_E820_MAP_NR);
104 printf("\n");
105 }
107 #ifdef TEST
108 void
109 setup_paging(void)
110 {
111 unsigned long i;
113 if (((unsigned)pgd & ~PGMASK) != 0)
114 panic("PGD not page aligned");
115 set_cr4(get_cr4() | CR4_PSE);
116 for (i = 0; i < NR_PGD; i++)
117 pgd[i] = (i * LPGSIZE)| PTE_PS | PTE_US | PTE_RW | PTE_P;
118 set_cr3((unsigned) pgd);
119 set_cr0(get_cr0() | (CR0_PE|CR0_PG));
120 }
121 #endif /* TEST */
123 void
124 setup_gdt(void)
125 {
126 /* setup task state segment */
127 memset(&tss, 0, sizeof(tss));
128 tss.ss0 = DATA_SELECTOR;
129 tss.esp0 = (unsigned) stack_top - 4*4;
130 tss.iomap_base = offsetof(struct tss, iomap);
132 /* initialize gdt's tss selector */
133 unsigned long long addr = (unsigned long long) &tss;
134 gdt[TSS_SELECTOR / sizeof(gdt[0])] |=
135 ((addr & 0xFF000000) << (56-24)) |
136 ((addr & 0x00FF0000) << (32-16)) |
137 ((addr & 0x0000FFFF) << (16)) |
138 (sizeof(tss) - 1);
140 /* switch to our own gdt and set current tss */
141 __asm__ __volatile__ ("lgdt %0" : : "m" (gdtr));
142 __asm__ __volatile__ ("movl %%eax,%%ds;"
143 "movl %%eax,%%es;"
144 "movl %%eax,%%fs;"
145 "movl %%eax,%%gs;"
146 "movl %%eax,%%ss" : : "a" (DATA_SELECTOR));
148 __asm__ __volatile__ ("ljmp %0,$1f; 1:" : : "i" (CODE_SELECTOR));
150 __asm__ __volatile__ ("ltr %%ax" : : "a" (TSS_SELECTOR));
151 }
153 void
154 set_intr_gate(int i, unsigned handler)
155 {
156 unsigned long long addr = handler;
158 idt[i] = ((addr & 0xFFFF0000ULL) << 32) | (0x8E00ULL << 32) |
159 (addr & 0xFFFFULL) | (CODE_SELECTOR << 16);
160 }
162 void
163 setup_idt(void)
164 {
165 int i;
167 for (i = 0; i < NR_TRAPS; i++)
168 set_intr_gate(i, trap_handlers[i]);
169 __asm__ __volatile__ ("lidt %0" : : "m" (idtr));
170 }
172 void
173 setup_pic(void)
174 {
175 /* mask all interrupts */
176 outb(PIC_MASTER + PIC_IMR, 0xFF);
177 outb(PIC_SLAVE + PIC_IMR, 0xFF);
179 /* setup master PIC */
180 outb(PIC_MASTER + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */
181 outb(PIC_MASTER + PIC_IMR, NR_EXCEPTION_HANDLER);
182 outb(PIC_MASTER + PIC_IMR, 1 << 2); /* slave on channel 2 */
183 outb(PIC_MASTER + PIC_IMR, 0x01);
185 /* setup slave PIC */
186 outb(PIC_SLAVE + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */
187 outb(PIC_SLAVE + PIC_IMR, NR_EXCEPTION_HANDLER + 8);
188 outb(PIC_SLAVE + PIC_IMR, 0x02); /* slave identity is 2 */
189 outb(PIC_SLAVE + PIC_IMR, 0x01);
191 /* enable all interrupts */
192 outb(PIC_MASTER + PIC_IMR, 0);
193 outb(PIC_SLAVE + PIC_IMR, 0);
194 }
196 void
197 enter_real_mode(struct regs *regs)
198 {
199 /* mask off TSS busy bit */
200 gdt[TSS_SELECTOR / sizeof(gdt[0])] &= ~0x0000020000000000ULL;
202 /* start 8086 emulation of BIOS */
203 if (initialize_real_mode) {
204 initialize_real_mode = 0;
205 regs->eflags |= EFLAGS_VM | 0x02;
206 regs->ves = regs->vds = regs->vfs = regs->vgs = 0xF000;
207 if (booting_cpu == 0) {
208 regs->cs = 0xF000; /* ROM BIOS POST entry point */
209 #ifdef TEST
210 regs->eip = 0xFFE0;
211 #else
212 regs->eip = 0xFFF0;
213 #endif
214 } else {
215 regs->cs = booting_vector << 8; /* AP entry point */
216 regs->eip = 0;
217 }
218 regs->uesp = 0;
219 regs->uss = 0;
220 printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n",
221 regs->cs, regs->eip);
223 mode = VM86_REAL; /* becomes previous mode */
224 set_mode(regs, VM86_REAL);
226 /* this should get us into 16-bit mode */
227 return;
228 } else {
229 /* go from protected to real mode */
230 regs->eflags |= EFLAGS_VM;
232 set_mode(regs, VM86_PROTECTED_TO_REAL);
234 emulate(regs);
235 }
236 }
238 /*
239 * Setup the environment for VMX assist.
240 * This environment consists of flat segments (code and data),
241 * its own gdt, idt, and tr.
242 */
243 void
244 setup_ctx(void)
245 {
246 struct vmx_assist_context *c = &newctx;
248 memset(c, 0, sizeof(*c));
249 c->eip = (unsigned long) switch_to_real_mode;
250 c->esp = (unsigned) stack_top - 4*4;
251 c->eflags = 0x2; /* no interrupts, please */
253 /*
254 * Obviously, vmx assist is not running with CR0_PE disabled.
255 * The reason why the vmx assist cr0 has CR0.PE disabled is
256 * that a transtion to CR0.PE causes a world switch. It seems
257 * more natural to enable CR0.PE to cause a world switch to
258 * protected mode rather than disabling it.
259 */
260 #ifdef TEST
261 c->cr0 = (get_cr0() | CR0_NE | CR0_PG) & ~CR0_PE;
262 c->cr3 = (unsigned long) pgd;
263 #else
264 c->cr0 = (get_cr0() | CR0_NE) & ~CR0_PE;
265 c->cr3 = 0;
266 #endif
267 c->cr4 = get_cr4();
269 c->idtr_limit = sizeof(idt)-1;
270 c->idtr_base = (unsigned long) &idt;
272 c->gdtr_limit = sizeof(gdt)-1;
273 c->gdtr_base = (unsigned long) &gdt;
275 c->cs_sel = CODE_SELECTOR;
276 c->cs_limit = 0xFFFFFFFF;
277 c->cs_base = 0;
278 c->cs_arbytes.fields.seg_type = 0xb;
279 c->cs_arbytes.fields.s = 1;
280 c->cs_arbytes.fields.dpl = 0;
281 c->cs_arbytes.fields.p = 1;
282 c->cs_arbytes.fields.avl = 0;
283 c->cs_arbytes.fields.default_ops_size = 1;
284 c->cs_arbytes.fields.g = 1;
286 c->ds_sel = DATA_SELECTOR;
287 c->ds_limit = 0xFFFFFFFF;
288 c->ds_base = 0;
289 c->ds_arbytes = c->cs_arbytes;
290 c->ds_arbytes.fields.seg_type = 0x3;
292 c->es_sel = DATA_SELECTOR;
293 c->es_limit = 0xFFFFFFFF;
294 c->es_base = 0;
295 c->es_arbytes = c->ds_arbytes;
297 c->ss_sel = DATA_SELECTOR;
298 c->ss_limit = 0xFFFFFFFF;
299 c->ss_base = 0;
300 c->ss_arbytes = c->ds_arbytes;
302 c->fs_sel = DATA_SELECTOR;
303 c->fs_limit = 0xFFFFFFFF;
304 c->fs_base = 0;
305 c->fs_arbytes = c->ds_arbytes;
307 c->gs_sel = DATA_SELECTOR;
308 c->gs_limit = 0xFFFFFFFF;
309 c->gs_base = 0;
310 c->gs_arbytes = c->ds_arbytes;
312 c->tr_sel = TSS_SELECTOR;
313 c->tr_limit = sizeof(tss) - 1;
314 c->tr_base = (unsigned long) &tss;
315 c->tr_arbytes.fields.seg_type = 0xb; /* 0x9 | 0x2 (busy) */
316 c->tr_arbytes.fields.s = 0;
317 c->tr_arbytes.fields.dpl = 0;
318 c->tr_arbytes.fields.p = 1;
319 c->tr_arbytes.fields.avl = 0;
320 c->tr_arbytes.fields.default_ops_size = 0;
321 c->tr_arbytes.fields.g = 0;
323 c->ldtr_sel = 0;
324 c->ldtr_limit = 0;
325 c->ldtr_base = 0;
326 c->ldtr_arbytes = c->ds_arbytes;
327 c->ldtr_arbytes.fields.seg_type = 0x2;
328 c->ldtr_arbytes.fields.s = 0;
329 c->ldtr_arbytes.fields.dpl = 0;
330 c->ldtr_arbytes.fields.p = 1;
331 c->ldtr_arbytes.fields.avl = 0;
332 c->ldtr_arbytes.fields.default_ops_size = 0;
333 c->ldtr_arbytes.fields.g = 0;
334 }
336 /*
337 * Start BIOS by causing a world switch to vmxassist, which causes
338 * VM8086 to be enabled and control is transfered to F000:FFF0.
339 */
340 void
341 start_bios(void)
342 {
343 unsigned long cr0;
345 if (booting_cpu == 0)
346 printf("Start BIOS ...\n");
347 else
348 printf("Start AP %d from %08x ...\n",
349 booting_cpu, booting_vector << 12);
351 initialize_real_mode = 1;
352 cr0 = get_cr0();
353 #ifndef TEST
354 set_cr0(cr0 | CR0_PE);
355 #endif
356 set_cr0(cr0 & ~CR0_PE);
357 panic("vmxassist returned"); /* "cannot happen" */
358 }
360 int
361 main(void)
362 {
363 if (booting_cpu == 0)
364 banner();
366 #ifdef TEST
367 setup_paging();
368 #endif
370 setup_gdt();
371 setup_idt();
373 #ifndef TEST
374 set_cr4(get_cr4() | CR4_VME);
375 #endif
377 setup_ctx();
379 if (booting_cpu == 0)
380 setup_pic();
382 start_bios();
384 return 0;
385 }