ia64/xen-unstable

view xen/common/kernel.c @ 1776:c2f673cea5e4

bitkeeper revision 1.1072.1.1 (40f4e51fLMgcKX4Sn6FNYePX6EqkGA)

Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
author xenbk@gandalf.hpl.hp.com
date Wed Jul 14 07:47:43 2004 +0000 (2004-07-14)
parents cd887a8fa08a a37ede4b5d41
children e91945007886
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 <hypervisor-ifs/dom0_ops.h>
29 unsigned long xenheap_phys_end;
31 kmem_cache_t *domain_struct_cachep;
33 struct e820entry {
34 unsigned long addr_lo, addr_hi; /* start of memory segment */
35 unsigned long size_lo, size_hi; /* size of memory segment */
36 unsigned long type; /* type of memory segment */
37 };
39 void start_of_day(void);
41 /* opt_console: comma-separated list of console outputs. */
42 unsigned char opt_console[30] = "com1,vga";
43 /* opt_conswitch: a character pair controlling console switching. */
44 /* Char 1: CTRL+<char1> is used to switch console input between Xen and DOM0 */
45 /* Char 2: If this character is 'x', then do not auto-switch to DOM0 when it */
46 /* boots. Any other value, or omitting the char, enables auto-switch */
47 unsigned char opt_conswitch[5] = "a"; /* NB. '`' would disable switching. */
48 /* opt_com[12]: Config serial port with a string <baud>,DPS,<io-base>,<irq>. */
49 unsigned char opt_com1[30] = "", opt_com2[30] = "";
50 /* opt_dom0_mem: Kilobytes of memory allocated to domain 0. */
51 unsigned int opt_dom0_mem = 16000;
52 /* opt_noht: If true, Hyperthreading is ignored. */
53 int opt_noht=0;
54 /* opt_noacpi: If true, ACPI tables are not parsed. */
55 int opt_noacpi=0;
56 /* opt_nosmp: If true, secondary processors are ignored. */
57 int opt_nosmp=0;
58 /* opt_noreboot: If true, machine will need manual reset on error. */
59 int opt_noreboot=0;
60 /* opt_ignorebiostables: If true, ACPI and MP tables are ignored. */
61 /* NB. This flag implies 'nosmp' and 'noacpi'. */
62 int opt_ignorebiostables=0;
63 /* opt_watchdog: If true, run a watchdog NMI on each processor. */
64 int opt_watchdog=0;
65 /* opt_pdb: Name of serial port for Xen pervasive debugger (and enable pdb) */
66 unsigned char opt_pdb[10] = "none";
67 /* opt_tbuf_size: trace buffer size (in pages) */
68 unsigned int opt_tbuf_size = 10;
69 /* opt_sched: scheduler - default to Borrowed Virtual Time */
70 char opt_sched[10] = "bvt";
71 /* opt_physdev_dom0_hide: list of PCI slots to hide from domain 0. */
72 /* Format is '(%02x:%02x.%1x)(%02x:%02x.%1x)' and so on. */
73 char opt_physdev_dom0_hide[200] = "";
74 /* opt_leveltrigger, opt_edgetrigger: Force an IO-APIC-routed IRQ to be */
75 /* level- or edge-triggered. */
76 /* Example: 'leveltrigger=4,5,6,20 edgetrigger=21'. */
77 char opt_leveltrigger[30] = "", opt_edgetrigger[30] = "";
78 /*
79 * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
80 * pfn_info table and allocation bitmap.
81 */
82 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
84 static struct {
85 unsigned char *name;
86 enum { OPT_STR, OPT_UINT, OPT_BOOL } type;
87 void *var;
88 } opts[] = {
89 { "console", OPT_STR, &opt_console },
90 { "conswitch", OPT_STR, &opt_conswitch },
91 { "com1", OPT_STR, &opt_com1 },
92 { "com2", OPT_STR, &opt_com2 },
93 { "dom0_mem", OPT_UINT, &opt_dom0_mem },
94 { "noht", OPT_BOOL, &opt_noht },
95 { "noacpi", OPT_BOOL, &opt_noacpi },
96 { "nosmp", OPT_BOOL, &opt_nosmp },
97 { "noreboot", OPT_BOOL, &opt_noreboot },
98 { "ignorebiostables", OPT_BOOL, &opt_ignorebiostables },
99 { "watchdog", OPT_BOOL, &opt_watchdog },
100 { "pdb", OPT_STR, &opt_pdb },
101 { "tbuf_size", OPT_UINT, &opt_tbuf_size },
102 { "sched", OPT_STR, &opt_sched },
103 { "physdev_dom0_hide", OPT_STR, &opt_physdev_dom0_hide },
104 { "leveltrigger", OPT_STR, &opt_leveltrigger },
105 { "edgetrigger", OPT_STR, &opt_edgetrigger },
106 { "xenheap_megabytes", OPT_UINT, &opt_xenheap_megabytes },
107 { NULL, 0, NULL }
108 };
111 void cmain(unsigned long magic, multiboot_info_t *mbi)
112 {
113 struct domain *new_dom;
114 unsigned long max_page;
115 unsigned char *cmdline;
116 module_t *mod = (module_t *)__va(mbi->mods_addr);
117 void *heap_start;
118 int i;
119 unsigned long max_mem;
120 unsigned long dom0_memory_start, dom0_memory_end;
121 unsigned long initial_images_start, initial_images_end;
123 /* Parse the command-line options. */
124 cmdline = (unsigned char *)(mbi->cmdline ? __va(mbi->cmdline) : NULL);
125 if ( cmdline != NULL )
126 {
127 unsigned char *opt_end, *opt;
128 while ( *cmdline == ' ' ) cmdline++;
129 cmdline = strchr(cmdline, ' ');
130 while ( cmdline != NULL )
131 {
132 while ( *cmdline == ' ' ) cmdline++;
133 if ( *cmdline == '\0' ) break;
134 opt_end = strchr(cmdline, ' ');
135 if ( opt_end != NULL ) *opt_end++ = '\0';
136 opt = strchr(cmdline, '=');
137 if ( opt != NULL ) *opt++ = '\0';
138 for ( i = 0; opts[i].name != NULL; i++ )
139 {
140 if ( strcmp(opts[i].name, cmdline ) != 0 ) continue;
141 switch ( opts[i].type )
142 {
143 case OPT_STR:
144 if ( opt != NULL )
145 strcpy(opts[i].var, opt);
146 break;
147 case OPT_UINT:
148 if ( opt != NULL )
149 *(unsigned int *)opts[i].var =
150 simple_strtol(opt, (char **)&opt, 0);
151 break;
152 case OPT_BOOL:
153 *(int *)opts[i].var = 1;
154 break;
155 }
156 }
157 cmdline = opt_end;
158 }
159 }
161 /* We initialise the serial devices very early so we can get debugging. */
162 serial_init_stage1();
164 init_console();
166 /* HELLO WORLD --- start-of-day banner text. */
167 printk(XEN_BANNER);
168 printk(" http://www.cl.cam.ac.uk/netos/xen\n");
169 printk(" University of Cambridge Computer Laboratory\n\n");
170 printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n\n",
171 XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
172 XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
173 XEN_COMPILER, XEN_COMPILE_DATE);
174 set_printk_prefix("(XEN) ");
176 if ( magic != MULTIBOOT_BOOTLOADER_MAGIC )
177 {
178 printk("FATAL ERROR: Invalid magic number: 0x%08lx\n", magic);
179 for ( ; ; ) ;
180 }
182 /* We require memory and module information. */
183 if ( (mbi->flags & 9) != 9 )
184 {
185 printk("FATAL ERROR: Bad flags passed by bootloader: 0x%x\n",
186 (unsigned)mbi->flags);
187 for ( ; ; ) ;
188 }
190 if ( mbi->mods_count == 0 )
191 {
192 printk("Require at least one Multiboot module!\n");
193 for ( ; ; ) ;
194 }
196 if ( opt_xenheap_megabytes < 4 )
197 {
198 printk("Xen heap size is too small to safely continue!\n");
199 for ( ; ; ) ;
200 }
202 set_current(&idle0_task);
204 xenheap_phys_end = opt_xenheap_megabytes << 20;
206 max_mem = max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
208 #if defined(__i386__)
210 initial_images_start = DIRECTMAP_PHYS_END;
211 initial_images_end = initial_images_start +
212 (mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
213 if ( initial_images_end > (max_page << PAGE_SHIFT) )
214 {
215 printk("Not enough memory to stash the DOM0 kernel image.\n");
216 for ( ; ; ) ;
217 }
218 memmove((void *)initial_images_start, /* use low mapping */
219 (void *)mod[0].mod_start, /* use low mapping */
220 mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
222 if ( opt_xenheap_megabytes > XENHEAP_DEFAULT_MB )
223 {
224 printk("Xen heap size is limited to %dMB - you specified %dMB.\n",
225 XENHEAP_DEFAULT_MB, opt_xenheap_megabytes);
226 for ( ; ; ) ;
227 }
229 ASSERT((sizeof(struct pfn_info) << 20) >
230 (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START));
232 init_frametable((void *)FRAMETABLE_VIRT_START, max_page);
234 #elif defined(__x86_64__)
236 init_frametable(__va(xenheap_phys_end), max_page);
238 initial_images_start = __pa(frame_table) + frame_table_size;
239 initial_images_end = initial_images_start +
240 (mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
241 if ( initial_images_end > (max_page << PAGE_SHIFT) )
242 {
243 printk("Not enough memory to stash the DOM0 kernel image.\n");
244 for ( ; ; ) ;
245 }
246 memmove(__va(initial_images_start),
247 __va(mod[0].mod_start),
248 mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
250 #endif
252 dom0_memory_start = (initial_images_end + ((4<<20)-1)) & ~((4<<20)-1);
253 dom0_memory_end = dom0_memory_start + (opt_dom0_mem << 10);
254 dom0_memory_end = (dom0_memory_end + PAGE_SIZE - 1) & PAGE_MASK;
256 /* Cheesy sanity check: enough memory for DOM0 allocation + some slack? */
257 if ( (dom0_memory_end + (8<<20)) > (max_page << PAGE_SHIFT) )
258 {
259 printk("Not enough memory for DOM0 memory reservation.\n");
260 for ( ; ; ) ;
261 }
263 printk("Initialised %luMB memory (%lu pages) on a %luMB machine\n",
264 max_page >> (20-PAGE_SHIFT), max_page,
265 max_mem >> (20-PAGE_SHIFT));
267 add_to_domain_alloc_list(dom0_memory_end, max_page << PAGE_SHIFT);
269 heap_start = memguard_init(&_end);
271 printk("Xen heap size is %luKB\n",
272 (xenheap_phys_end-__pa(heap_start))/1024 );
274 init_page_allocator(__pa(heap_start), xenheap_phys_end);
276 /* Initialise the slab allocator. */
277 kmem_cache_init();
278 kmem_cache_sizes_init(max_page);
280 domain_struct_cachep = kmem_cache_create(
281 "domain_cache", sizeof(struct domain),
282 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
283 if ( domain_struct_cachep == NULL )
284 panic("No slab cache for task structs.");
286 start_of_day();
288 /* Add CPU0 idle task to the task hash list */
289 task_hash[TASK_HASH(IDLE_DOMAIN_ID)] = &idle0_task;
291 /* Create initial domain 0. */
292 new_dom = do_createdomain(0, 0);
293 if ( new_dom == NULL )
294 panic("Error creating domain 0\n");
296 set_bit(DF_PRIVILEGED, &new_dom->flags);
298 shadow_mode_init();
300 /*
301 * We're going to setup domain0 using the module(s) that we stashed safely
302 * above our heap. The second module, if present, is an initrd ramdisk.
303 */
304 if ( construct_dom0(new_dom, dom0_memory_start, dom0_memory_end,
305 (char *)initial_images_start,
306 mod[0].mod_end-mod[0].mod_start,
307 (mbi->mods_count == 1) ? 0 :
308 (char *)initial_images_start +
309 (mod[1].mod_start-mod[0].mod_start),
310 (mbi->mods_count == 1) ? 0 :
311 mod[mbi->mods_count-1].mod_end - mod[1].mod_start,
312 __va(mod[0].string)) != 0)
313 panic("Could not set up DOM0 guest OS\n");
315 /* The stash space for the initial kernel image can now be freed up. */
316 add_to_domain_alloc_list(__pa(frame_table) + frame_table_size,
317 dom0_memory_start);
319 init_trace_bufs();
321 domain_unpause_by_systemcontroller(current);
322 domain_unpause_by_systemcontroller(new_dom);
323 startup_cpu_idle_loop();
324 }
326 /*
327 * Simple hypercalls.
328 */
330 long do_xen_version(int cmd)
331 {
332 if ( cmd != 0 )
333 return -ENOSYS;
334 return (XEN_VERSION<<16) | (XEN_SUBVERSION);
335 }
337 long do_ni_hypercall(void)
338 {
339 /* No-op hypercall. */
340 return -ENOSYS;
341 }