ia64/xen-unstable

view xen/common/kernel.c @ 2912:1c0b0d49f291

bitkeeper revision 1.1159.169.1 (418e9fbcYPjvgCp5hHW29dMCpCsuDA)

Disable Xen VGA output later in the boot, so we get more start-of-day
messages. Most importantly, users get a visual cue on VGA console when
whole of main memory is scrubbed immediately before starting dom0.
author kaf24@freefall.cl.cam.ac.uk
date Sun Nov 07 22:20:44 2004 +0000 (2004-11-07)
parents 9813d8e70a3b
children 79d8674c230f
line source
1 /******************************************************************************
2 * kernel.c
3 *
4 * This file should contain architecture-independent bootstrap and low-level
5 * help routines. It's a bit x86/PC specific right now!
6 *
7 * Copyright (c) 2002-2003 K A Fraser
8 */
10 #include <stdarg.h>
11 #include <xen/config.h>
12 #include <xen/lib.h>
13 #include <xen/errno.h>
14 #include <xen/spinlock.h>
15 #include <xen/multiboot.h>
16 #include <xen/sched.h>
17 #include <xen/mm.h>
18 #include <xen/delay.h>
19 #include <xen/compile.h>
20 #include <xen/console.h>
21 #include <xen/serial.h>
22 #include <xen/trace.h>
23 #include <asm/shadow.h>
24 #include <asm/io.h>
25 #include <asm/uaccess.h>
26 #include <asm/domain_page.h>
27 #include <public/dom0_ops.h>
29 unsigned long xenheap_phys_end;
31 xmem_cache_t *domain_struct_cachep;
32 struct domain *dom0;
34 vm_assist_info_t vm_assist_info[MAX_VMASST_TYPE + 1];
36 struct e820entry {
37 unsigned long addr_lo, addr_hi; /* start of memory segment */
38 unsigned long size_lo, size_hi; /* size of memory segment */
39 unsigned long type; /* type of memory segment */
40 };
42 void start_of_day(void);
44 /* opt_console: comma-separated list of console outputs. */
45 unsigned char opt_console[30] = "com1,vga";
46 /* opt_conswitch: a character pair controlling console switching. */
47 /* Char 1: CTRL+<char1> is used to switch console input between Xen and DOM0 */
48 /* Char 2: If this character is 'x', then do not auto-switch to DOM0 when it */
49 /* boots. Any other value, or omitting the char, enables auto-switch */
50 unsigned char opt_conswitch[5] = "a"; /* NB. '`' would disable switching. */
51 /* opt_com[12]: Config serial port with a string <baud>,DPS,<io-base>,<irq>. */
52 unsigned char opt_com1[30] = "", opt_com2[30] = "";
53 /* opt_dom0_mem: Kilobytes of memory allocated to domain 0. */
54 unsigned int opt_dom0_mem = 16000;
55 /* opt_noht: If true, Hyperthreading is ignored. */
56 int opt_noht=0;
57 /* opt_noacpi: If true, ACPI tables are not parsed. */
58 int opt_noacpi=0;
59 /* opt_nosmp: If true, secondary processors are ignored. */
60 int opt_nosmp=0;
61 /* opt_noreboot: If true, machine will need manual reset on error. */
62 int opt_noreboot=0;
63 /* opt_ignorebiostables: If true, ACPI and MP tables are ignored. */
64 /* NB. This flag implies 'nosmp' and 'noacpi'. */
65 int opt_ignorebiostables=0;
66 /* opt_watchdog: If true, run a watchdog NMI on each processor. */
67 int opt_watchdog=0;
68 /* opt_pdb: Name of serial port for Xen pervasive debugger (and enable pdb) */
69 unsigned char opt_pdb[10] = "none";
70 /* opt_tbuf_size: trace buffer size (in pages) */
71 unsigned int opt_tbuf_size = 10;
72 /* opt_sched: scheduler - default to Borrowed Virtual Time */
73 char opt_sched[10] = "bvt";
74 /* opt_physdev_dom0_hide: list of PCI slots to hide from domain 0. */
75 /* Format is '(%02x:%02x.%1x)(%02x:%02x.%1x)' and so on. */
76 char opt_physdev_dom0_hide[200] = "";
77 /* opt_leveltrigger, opt_edgetrigger: Force an IO-APIC-routed IRQ to be */
78 /* level- or edge-triggered. */
79 /* Example: 'leveltrigger=4,5,6,20 edgetrigger=21'. */
80 char opt_leveltrigger[30] = "", opt_edgetrigger[30] = "";
81 /*
82 * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
83 * pfn_info table and allocation bitmap.
84 */
85 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
86 /*
87 * opt_nmi: one of 'ignore', 'dom0', or 'fatal'.
88 * fatal: Xen prints diagnostic message and then hangs.
89 * dom0: The NMI is virtualised to DOM0.
90 * ignore: The NMI error is cleared and ignored.
91 */
92 #ifdef NDEBUG
93 char opt_nmi[10] = "dom0";
94 #else
95 char opt_nmi[10] = "fatal";
96 #endif
97 /*
98 * Comma-separated list of hexadecimal page numbers containing bad bytes.
99 * e.g. 'badpage=0x3f45,0x8a321'.
100 */
101 char opt_badpage[100] = "";
103 static struct {
104 unsigned char *name;
105 enum { OPT_STR, OPT_UINT, OPT_BOOL } type;
106 void *var;
107 unsigned int len;
108 } opts[] = {
109 #define V(_x) &_x, sizeof(_x)
110 { "console", OPT_STR, V(opt_console) },
111 { "conswitch", OPT_STR, V(opt_conswitch) },
112 { "com1", OPT_STR, V(opt_com1) },
113 { "com2", OPT_STR, V(opt_com2) },
114 { "dom0_mem", OPT_UINT, V(opt_dom0_mem) },
115 { "noht", OPT_BOOL, V(opt_noht) },
116 { "noacpi", OPT_BOOL, V(opt_noacpi) },
117 { "nosmp", OPT_BOOL, V(opt_nosmp) },
118 { "noreboot", OPT_BOOL, V(opt_noreboot) },
119 { "ignorebiostables", OPT_BOOL, V(opt_ignorebiostables) },
120 { "watchdog", OPT_BOOL, V(opt_watchdog) },
121 { "pdb", OPT_STR, V(opt_pdb) },
122 { "tbuf_size", OPT_UINT, V(opt_tbuf_size) },
123 { "sched", OPT_STR, V(opt_sched) },
124 { "physdev_dom0_hide", OPT_STR, V(opt_physdev_dom0_hide) },
125 { "leveltrigger", OPT_STR, V(opt_leveltrigger) },
126 { "edgetrigger", OPT_STR, V(opt_edgetrigger) },
127 { "xenheap_megabytes", OPT_UINT, V(opt_xenheap_megabytes) },
128 { "nmi", OPT_STR, V(opt_nmi) },
129 { "badpage", OPT_STR, V(opt_badpage) },
130 { NULL, 0, NULL, 0 }
131 };
134 void cmain(multiboot_info_t *mbi)
135 {
136 unsigned long max_page;
137 unsigned char *cmdline;
138 module_t *mod = (module_t *)__va(mbi->mods_addr);
139 void *heap_start;
140 int i;
141 unsigned long max_mem;
142 unsigned long dom0_memory_start, dom0_memory_end;
143 unsigned long initial_images_start, initial_images_end;
145 /* Parse the command-line options. */
146 cmdline = (unsigned char *)(mbi->cmdline ? __va(mbi->cmdline) : NULL);
147 if ( cmdline != NULL )
148 {
149 unsigned char *opt_end, *opt;
150 while ( *cmdline == ' ' ) cmdline++;
151 cmdline = strchr(cmdline, ' '); /* skip the image name */
152 while ( cmdline != NULL )
153 {
154 while ( *cmdline == ' ' ) cmdline++;
155 if ( *cmdline == '\0' ) break;
156 opt_end = strchr(cmdline, ' ');
157 if ( opt_end != NULL ) *opt_end++ = '\0';
158 opt = strchr(cmdline, '=');
159 if ( opt != NULL ) *opt++ = '\0';
160 for ( i = 0; opts[i].name != NULL; i++ )
161 {
162 if ( strcmp(opts[i].name, cmdline ) != 0 ) continue;
163 switch ( opts[i].type )
164 {
165 case OPT_STR:
166 if ( opt != NULL )
167 {
168 strncpy(opts[i].var, opt, opts[i].len);
169 ((char *)opts[i].var)[opts[i].len-1] = '\0';
170 }
171 break;
172 case OPT_UINT:
173 if ( opt != NULL )
174 *(unsigned int *)opts[i].var =
175 simple_strtol(opt, (char **)&opt, 0);
176 break;
177 case OPT_BOOL:
178 *(int *)opts[i].var = 1;
179 break;
180 }
181 }
182 cmdline = opt_end;
183 }
184 }
186 /* Must do this early -- e.g., spinlocks rely on get_current(). */
187 set_current(&idle0_task);
189 /* We initialise the serial devices very early so we can get debugging. */
190 serial_init_stage1();
192 init_console();
194 /* HELLO WORLD --- start-of-day banner text. */
195 printk(XEN_BANNER);
196 printk(" http://www.cl.cam.ac.uk/netos/xen\n");
197 printk(" University of Cambridge Computer Laboratory\n\n");
198 printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n",
199 XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
200 XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
201 XEN_COMPILER, XEN_COMPILE_DATE);
202 printk(" Latest ChangeSet: %s\n\n", XEN_CHANGESET);
203 set_printk_prefix("(XEN) ");
205 /* We require memory and module information. */
206 if ( (mbi->flags & 9) != 9 )
207 {
208 printk("FATAL ERROR: Bad flags passed by bootloader: 0x%x\n",
209 (unsigned)mbi->flags);
210 for ( ; ; ) ;
211 }
213 if ( mbi->mods_count == 0 )
214 {
215 printk("Require at least one Multiboot module!\n");
216 for ( ; ; ) ;
217 }
219 if ( opt_xenheap_megabytes < 4 )
220 {
221 printk("Xen heap size is too small to safely continue!\n");
222 for ( ; ; ) ;
223 }
225 xenheap_phys_end = opt_xenheap_megabytes << 20;
227 max_mem = max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
229 #if defined(__i386__)
231 initial_images_start = DIRECTMAP_PHYS_END;
232 initial_images_end = initial_images_start +
233 (mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
234 if ( initial_images_end > (max_page << PAGE_SHIFT) )
235 {
236 printk("Not enough memory to stash the DOM0 kernel image.\n");
237 for ( ; ; ) ;
238 }
239 memmove((void *)initial_images_start, /* use low mapping */
240 (void *)mod[0].mod_start, /* use low mapping */
241 mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
243 if ( opt_xenheap_megabytes > XENHEAP_DEFAULT_MB )
244 {
245 printk("Xen heap size is limited to %dMB - you specified %dMB.\n",
246 XENHEAP_DEFAULT_MB, opt_xenheap_megabytes);
247 for ( ; ; ) ;
248 }
250 ASSERT((sizeof(struct pfn_info) << 20) <=
251 (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START));
253 init_frametable((void *)FRAMETABLE_VIRT_START, max_page);
255 #elif defined(__x86_64__)
257 init_frametable(__va(xenheap_phys_end), max_page);
259 initial_images_start = __pa(frame_table) + frame_table_size;
260 initial_images_end = initial_images_start +
261 (mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
262 if ( initial_images_end > (max_page << PAGE_SHIFT) )
263 {
264 printk("Not enough memory to stash the DOM0 kernel image.\n");
265 for ( ; ; ) ;
266 }
267 memmove(__va(initial_images_start),
268 __va(mod[0].mod_start),
269 mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
271 #endif
273 dom0_memory_start = (initial_images_end + ((4<<20)-1)) & ~((4<<20)-1);
274 dom0_memory_end = dom0_memory_start + (opt_dom0_mem << 10);
275 dom0_memory_end = (dom0_memory_end + PAGE_SIZE - 1) & PAGE_MASK;
277 /* Cheesy sanity check: enough memory for DOM0 allocation + some slack? */
278 if ( (dom0_memory_end + (8<<20)) > (max_page << PAGE_SHIFT) )
279 {
280 printk("Not enough memory for DOM0 memory reservation.\n");
281 for ( ; ; ) ;
282 }
284 printk("Initialised %luMB memory (%lu pages) on a %luMB machine\n",
285 max_page >> (20-PAGE_SHIFT), max_page,
286 max_mem >> (20-PAGE_SHIFT));
288 heap_start = memguard_init(&_end);
289 heap_start = __va(init_heap_allocator(__pa(heap_start), max_page));
291 init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
292 printk("Xen heap size is %luKB\n",
293 (xenheap_phys_end-__pa(heap_start))/1024 );
295 init_domheap_pages(dom0_memory_end, max_page << PAGE_SHIFT);
297 /* Initialise the slab allocator. */
298 xmem_cache_init();
299 xmem_cache_sizes_init(max_page);
301 domain_struct_cachep = xmem_cache_create(
302 "domain_cache", sizeof(struct domain),
303 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
304 if ( domain_struct_cachep == NULL )
305 panic("No slab cache for task structs.");
307 start_of_day();
309 grant_table_init();
311 /* Create initial domain 0. */
312 dom0 = do_createdomain(0, 0);
313 if ( dom0 == NULL )
314 panic("Error creating domain 0\n");
316 set_bit(DF_PRIVILEGED, &dom0->flags);
318 shadow_mode_init();
320 /* Grab the DOM0 command line. Skip past the image name. */
321 cmdline = (unsigned char *)(mod[0].string ? __va(mod[0].string) : NULL);
322 if ( cmdline != NULL )
323 {
324 while ( *cmdline == ' ' ) cmdline++;
325 if ( (cmdline = strchr(cmdline, ' ')) != NULL )
326 while ( *cmdline == ' ' ) cmdline++;
327 }
329 /*
330 * We're going to setup domain0 using the module(s) that we stashed safely
331 * above our heap. The second module, if present, is an initrd ramdisk.
332 */
333 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_end,
334 (char *)initial_images_start,
335 mod[0].mod_end-mod[0].mod_start,
336 (mbi->mods_count == 1) ? 0 :
337 (char *)initial_images_start +
338 (mod[1].mod_start-mod[0].mod_start),
339 (mbi->mods_count == 1) ? 0 :
340 mod[mbi->mods_count-1].mod_end - mod[1].mod_start,
341 cmdline) != 0)
342 panic("Could not set up DOM0 guest OS\n");
344 /* The stash space for the initial kernel image can now be freed up. */
345 init_domheap_pages(__pa(frame_table) + frame_table_size,
346 dom0_memory_start);
348 scrub_heap_pages();
350 init_trace_bufs();
352 /* Give up the VGA console if DOM0 is configured to grab it. */
353 console_endboot(cmdline && strstr(cmdline, "tty0"));
355 domain_unpause_by_systemcontroller(current);
356 domain_unpause_by_systemcontroller(dom0);
357 startup_cpu_idle_loop();
358 }
360 /*
361 * Simple hypercalls.
362 */
364 long do_xen_version(int cmd)
365 {
366 if ( cmd != 0 )
367 return -ENOSYS;
368 return (XEN_VERSION<<16) | (XEN_SUBVERSION);
369 }
371 long do_vm_assist(unsigned int cmd, unsigned int type)
372 {
373 return vm_assist(current, cmd, type);
374 }
376 long do_ni_hypercall(void)
377 {
378 /* No-op hypercall. */
379 return -ENOSYS;
380 }