debuggers.hg

view xen/common/kernel.c @ 665:a74ec9013abb

bitkeeper revision 1.349 (3f132695Orgv2nzuhXag1iNmNOy53Q)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into labyrinth.cl.cam.ac.uk:/auto/anfs/scratch/labyrinth/iap10/xeno-clone/xeno.bk
author iap10@labyrinth.cl.cam.ac.uk
date Mon Jul 14 21:54:29 2003 +0000 (2003-07-14)
parents cda951fc1bef 384fbe1ed716
children 8ae2c6bc95ea
line source
1 #include <stdarg.h>
2 #include <xeno/lib.h>
3 #include <xeno/errno.h>
4 #include <xeno/spinlock.h>
5 #include <xeno/multiboot.h>
6 #include <xeno/sched.h>
7 #include <xeno/mm.h>
8 #include <xeno/delay.h>
9 #include <xeno/skbuff.h>
10 #include <xeno/interrupt.h>
11 #include <xeno/compile.h>
12 #include <xeno/version.h>
13 #include <asm/io.h>
14 #include <asm/msr.h>
15 #include <asm/uaccess.h>
16 #include <hypervisor-ifs/dom0_ops.h>
17 #include <asm/byteorder.h>
18 #include <linux/if_ether.h>
19 #include <asm/domain_page.h>
20 #include <xeno/console.h>
21 #include <xeno/net_headers.h>
23 static int xpos, ypos;
24 static volatile unsigned char *video;
26 spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
28 struct e820entry {
29 unsigned long addr_lo, addr_hi; /* start of memory segment */
30 unsigned long size_lo, size_hi; /* size of memory segment */
31 unsigned long type; /* type of memory segment */
32 };
34 void init_vga(void);
35 void init_serial(void);
36 void start_of_day(void);
38 /* Command line options and variables. */
39 unsigned int opt_console = 1;
40 unsigned int opt_ser_baud = 9600; /* default baud for COM1 */
41 unsigned int opt_dom0_mem = 16000; /* default kbytes for DOM0 */
42 unsigned int opt_ne_base = 0; /* NE2k NICs cannot be probed */
43 unsigned char opt_ifname[10] = "eth0";
44 int opt_noht=0, opt_noacpi=0, opt_nosmp=0, opt_watchdog=0;
45 enum { OPT_IP, OPT_STR, OPT_UINT, OPT_BOOL };
46 static struct {
47 unsigned char *name;
48 int type;
49 void *var;
50 } opts[] = {
51 { "console", OPT_UINT, &opt_console },
52 { "ser_baud", OPT_UINT, &opt_ser_baud },
53 { "dom0_mem", OPT_UINT, &opt_dom0_mem },
54 { "ne_base", OPT_UINT, &opt_ne_base },
55 { "ifname", OPT_STR, &opt_ifname },
56 { "noht", OPT_BOOL, &opt_noht },
57 { "noacpi", OPT_BOOL, &opt_noacpi },
58 { "nosmp", OPT_BOOL, &opt_nosmp },
59 { "watchdog", OPT_BOOL, &opt_watchdog },
60 { NULL, 0, NULL }
61 };
64 void cmain (unsigned long magic, multiboot_info_t *mbi)
65 {
66 struct task_struct *new_dom;
67 dom0_newdomain_t dom0_params;
68 unsigned long max_page;
69 unsigned char *cmdline;
70 module_t *mod;
71 int i;
73 /*
74 * Note that serial output cannot be done properly until
75 * after command-line arguments have been parsed, and the required baud
76 * rate is known. Any messages before that will be output using the
77 * settings of the bootloader, for example. Maybe okay for error msgs...
78 */
79 #define early_error(args...) opt_console=1; init_vga(); cls(); printk(args)
81 if ( magic != MULTIBOOT_BOOTLOADER_MAGIC )
82 {
83 early_error("Invalid magic number: 0x%x\n", (unsigned)magic);
84 return;
85 }
87 /*
88 * We require some kind of memory and module information.
89 * The rest we can fake!
90 */
91 if ( (mbi->flags & 9) != 9 )
92 {
93 early_error("Bad flags passed by bootloader: 0x%x\n", (unsigned)mbi->flags);
94 return;
95 }
97 if ( mbi->mods_count == 0 )
98 {
99 early_error("Require at least one module!\n");
100 return;
101 }
103 /* Are mmap_* valid? */
104 #if 0
105 if ( (mbi->flags & (1<<6)) )
106 {
107 memory_map_t *mmap = (memory_map_t *)mbi->mmap_addr;
108 struct e820entry *e820 = E820_MAP;
110 while ( (unsigned long)mmap < (mbi->mmap_addr + mbi->mmap_length) )
111 {
112 e820->addr_lo = mmap->base_addr_low;
113 e820->addr_hi = mmap->base_addr_high;
114 e820->size_lo = mmap->length_low;
115 e820->size_hi = mmap->length_high;
116 e820->type = mmap->type;
117 e820++;
118 mmap = (memory_map_t *)
119 ((unsigned long)mmap + mmap->size + sizeof (mmap->size));
120 }
121 }
122 #endif
124 mod = (module_t *)__va(mbi->mods_addr);
126 /* Parse the command line. */
127 cmdline = (unsigned char *)(mbi->cmdline ? __va(mbi->cmdline) : NULL);
128 if ( cmdline != NULL )
129 {
130 unsigned char *opt_end, *opt;
131 while ( *cmdline == ' ' ) cmdline++;
132 cmdline = strchr(cmdline, ' ');
133 while ( cmdline != NULL )
134 {
135 while ( *cmdline == ' ' ) cmdline++;
136 if ( *cmdline == '\0' ) break;
137 opt_end = strchr(cmdline, ' ');
138 if ( opt_end != NULL ) *opt_end++ = '\0';
139 opt = strchr(cmdline, '=');
140 if ( opt != NULL ) *opt++ = '\0';
141 for ( i = 0; opts[i].name != NULL; i++ )
142 {
143 if ( strcmp(opts[i].name, cmdline ) != 0 ) continue;
144 switch ( opts[i].type )
145 {
146 case OPT_IP:
147 if ( opt != NULL )
148 *(unsigned long *)opts[i].var = str_to_quad(opt);
149 break;
150 case OPT_STR:
151 if ( opt != NULL )
152 strcpy(opts[i].var, opt);
153 break;
154 case OPT_UINT:
155 if ( opt != NULL )
156 *(unsigned int *)opts[i].var =
157 simple_strtol(opt, (char **)&opt, 0);
158 break;
159 case OPT_BOOL:
160 *(int *)opts[i].var = 1;
161 break;
162 }
163 }
164 cmdline = opt_end;
165 }
166 }
168 #undef early_error
170 init_vga();
171 cls();
173 /* INITIALISE SERIAL LINE (printk will work okay from here on). */
174 init_serial();
176 printk(XEN_BANNER);
177 printk(" http://www.cl.cam.ac.uk/xeno\n");
178 printk(" University of Cambridge Computer Laboratory\n\n");
179 printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n\n",
180 XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
181 XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
182 XEN_COMPILER, XEN_COMPILE_DATE);
184 memcpy(&idle0_task_union, &first_task_struct, sizeof(first_task_struct));
186 max_page = (mbi->mem_upper+1024) >> (PAGE_SHIFT - 10);
187 init_frametable(max_page);
188 printk("Initialised all memory on a %luMB machine\n",
189 max_page >> (20-PAGE_SHIFT));
191 init_page_allocator(__pa(&_end), MAX_MONITOR_ADDRESS);
193 /* These things will get done by do_newdomain() for all other tasks. */
194 current->shared_info = (void *)get_free_page(GFP_KERNEL);
195 memset(current->shared_info, 0, sizeof(shared_info_t));
196 set_fs(USER_DS);
198 start_of_day();
200 /* Create initial domain 0. */
201 dom0_params.memory_kb = opt_dom0_mem;
202 new_dom = do_newdomain(0, 0);
203 if ( new_dom == NULL ) panic("Error creating domain 0\n");
205 /*
206 * We're going to setup domain0 using the module(s) that we stashed safely
207 * above our MAX_DIRECTMAP_ADDRESS in boot/Boot.S The second module, if
208 * present, is an initrd ramdisk
209 */
210 if ( setup_guestos(new_dom,
211 &dom0_params, 1,
212 (char *)MAX_DIRECTMAP_ADDRESS,
213 mod[mbi->mods_count-1].mod_end - mod[0].mod_start,
214 __va(mod[0].string),
215 (mbi->mods_count == 2) ?
216 (mod[1].mod_end - mod[1].mod_start):0)
217 != 0 ) panic("Could not set up DOM0 guest OS\n");
219 update_dom_time(new_dom->shared_info);
220 wake_up(new_dom);
222 cpu_idle();
223 }
226 #define SERIAL_BASE 0x3f8
227 #define RX_BUF 0
228 #define TX_HOLD 0
229 #define INT_ENABLE 1
230 #define INT_IDENT 2
231 #define DATA_FORMAT 3
232 #define LINE_CTL 4
233 #define LINE_STATUS 5
234 #define LINE_IN 6
235 #define DIVISOR_LO 0
236 #define DIVISOR_HI 1
238 void init_serial(void)
239 {
240 #ifdef CONFIG_OUTPUT_SERIAL
241 /* 'opt_ser_baud' baud, no parity, 1 stop bit, 8 data bits. */
242 outb(0x83, SERIAL_BASE+DATA_FORMAT);
243 outb(115200/opt_ser_baud, SERIAL_BASE+DIVISOR_LO);
244 outb(0, SERIAL_BASE+DIVISOR_HI);
245 outb(0x03, SERIAL_BASE+DATA_FORMAT);
247 /* No interrupts. */
248 outb(0x00, SERIAL_BASE+INT_ENABLE);
249 #endif
250 }
253 void putchar_serial(unsigned char c)
254 {
255 #ifdef CONFIG_OUTPUT_SERIAL
256 if ( c == '\n' ) putchar_serial('\r');
257 while ( !(inb(SERIAL_BASE+LINE_STATUS)&(1<<5)) ) barrier();
258 outb(c, SERIAL_BASE+TX_HOLD);
259 #endif
260 }
263 /* VGA text (mode 3) definitions. */
264 #define COLUMNS 80
265 #define LINES 25
266 #define ATTRIBUTE 7
267 #define VIDEO __va(0xB8000)
269 /* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
270 void init_vga(void)
271 {
272 #ifdef CONFIG_OUTPUT_CONSOLE
273 /* The following VGA state was saved from a chip in text mode 3. */
274 static unsigned char regs[] = {
275 /* Sequencer registers */
276 0x03, 0x00, 0x03, 0x00, 0x02,
277 /* CRTC registers */
278 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
279 0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
280 0xb9, 0xa3, 0xff,
281 /* Graphic registers */
282 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
283 /* Attribute registers */
284 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
285 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
286 };
288 int i, j = 0;
289 volatile unsigned char tmp;
291 if(opt_console) {
292 tmp = inb(0x3da);
293 outb(0x00, 0x3c0);
295 for ( i = 0; i < 5; i++ )
296 outw((regs[j++] << 8) | i, 0x3c4);
298 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
299 outw(((regs[5+17] & 0x7F) << 8) | 17, 0x3d4);
301 for ( i = 0; i < 25; i++ )
302 outw((regs[j++] << 8) | i, 0x3d4);
304 for ( i = 0; i < 9; i++ )
305 outw((regs[j++] << 8) | i, 0x3ce);
307 for ( i = 0; i < 21; i++ )
308 {
309 tmp = inb(0x3da);
310 outb(i, 0x3c0);
311 outb(regs[j++], 0x3c0);
312 }
314 tmp = inb(0x3da);
315 outb(0x20, 0x3c0);
316 }
317 #endif
318 }
321 /* Clear the screen and initialize VIDEO, XPOS and YPOS. */
322 void cls(void)
323 {
324 #ifdef CONFIG_OUTPUT_CONSOLE
325 int i;
327 if(opt_console) {
328 video = (unsigned char *) VIDEO;
330 for (i = 0; i < COLUMNS * LINES * 2; i++)
331 *(video + i) = 0;
333 xpos = 0;
334 ypos = 0;
336 outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
337 }
338 #endif
339 }
342 /* Put the character C on the screen. */
343 static void putchar (int c)
344 {
345 if ( (c != '\n') && ((c < 32) || (c > 126)) ) return;
346 putchar_serial(c);
348 #ifdef CONFIG_OUTPUT_CONSOLE
349 if(opt_console) {
350 if (c == '\n')
351 {
352 newline:
353 xpos = 0;
354 ypos++;
355 if (ypos >= LINES)
356 {
357 static char zeroarr[2*COLUMNS] = { 0 };
358 ypos = LINES-1;
359 memcpy((char*)video,
360 (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
361 memcpy((char*)video + (LINES-1)*2*COLUMNS,
362 zeroarr, 2*COLUMNS);
363 }
364 return;
365 }
367 *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
368 *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
370 xpos++;
371 if (xpos >= COLUMNS)
372 goto newline;
373 }
374 #endif
375 }
377 static inline void __putstr(const char *str)
378 {
379 while ( *str ) putchar(*str++);
380 }
382 void printf (const char *fmt, ...)
383 {
384 va_list args;
385 char buf[128];
386 const char *p = fmt;
387 unsigned long flags;
389 /*
390 * If the format string contains '%' descriptors then we have to parse it
391 * before printing it. We parse it into a fixed-length buffer. Long
392 * strings should therefore _not_ contain '%' characters!
393 */
394 if ( strchr(fmt, '%') != NULL )
395 {
396 va_start(args, fmt);
397 (void)vsnprintf(buf, sizeof(buf), fmt, args);
398 va_end(args);
399 p = buf;
400 }
402 spin_lock_irqsave(&console_lock, flags);
403 while ( *p ) putchar(*p++);
404 spin_unlock_irqrestore(&console_lock, flags);
405 }
407 void panic(const char *fmt, ...)
408 {
409 va_list args;
410 char buf[128];
411 unsigned long flags;
412 extern void machine_restart(char *);
414 va_start(args, fmt);
415 (void)vsnprintf(buf, sizeof(buf), fmt, args);
416 va_end(args);
418 /* Spit out multiline message in one go. */
419 spin_lock_irqsave(&console_lock, flags);
420 __putstr("\n****************************************\n");
421 __putstr(buf);
422 __putstr("Aieee! CPU");
423 sprintf(buf, "%d", smp_processor_id());
424 __putstr(buf);
425 __putstr(" is toast...\n");
426 __putstr("****************************************\n\n");
427 __putstr("Reboot in five seconds...\n");
428 spin_unlock_irqrestore(&console_lock, flags);
430 mdelay(5000);
431 machine_restart(0);
432 }
434 /* No-op syscall. */
435 asmlinkage long sys_ni_syscall(void)
436 {
437 return -ENOSYS;
438 }
441 unsigned short compute_cksum(unsigned short *buf, int count)
442 {
443 /* Function written by ek247
444 * Computes IP and UDP checksum.
445 * To be used for the fake console packets
446 * created in console_export
447 */
449 unsigned long sum=0;
451 while (count--)
452 {
453 sum+=*buf++;
454 if (sum & 0xFFFF0000)
455 {
456 //carry occured, so wrap around
457 sum &=0xFFFF;
458 sum++;
459 }
460 }
461 return ~(sum & 0xFFFF);
462 }
466 /* XXX SMH: below is rather vile; pulled in to allow network console */
468 extern int netif_rx(struct sk_buff *);
470 /*
471 * Function written by ek247. Exports console output from all domains upwards
472 * to domain0, by stuffing it into a fake network packet.
473 */
474 int console_export(char *str, int len)
475 {
476 struct sk_buff *skb;
477 struct iphdr *iph = NULL;
478 struct udphdr *udph = NULL;
479 struct ethhdr *ethh = NULL;
480 int hdr_size = sizeof(struct iphdr) + sizeof(struct udphdr);
481 u8 *skb_data;
483 skb = dev_alloc_skb(sizeof(struct ethhdr) +
484 hdr_size + len + 20);
485 if ( skb == NULL ) return 0;
487 skb->dev = the_dev;
488 skb_data = (u8 *)map_domain_mem((skb->pf - frame_table) << PAGE_SHIFT);
489 skb_reserve(skb, 2);
491 /* Get a pointer to each header. */
492 ethh = (struct ethhdr *)
493 (skb_data + (skb->data - skb->head));
494 iph = (struct iphdr *)(ethh + 1);
495 udph = (struct udphdr *)(iph + 1);
497 skb_reserve(skb, sizeof(struct ethhdr));
498 skb_put(skb, hdr_size + len);
500 /* Build IP header. */
501 iph->version = 4;
502 iph->ihl = 5;
503 iph->frag_off= 0;
504 iph->id = 0xdead;
505 iph->ttl = 255;
506 iph->protocol= 17;
507 iph->daddr = htonl(0xa9fe0100); /* 169.254.1.0 */
508 iph->saddr = htonl(0xa9fefeff); /* 169.254.254.255 */
509 iph->tot_len = htons(hdr_size + len);
510 iph->check = 0;
511 iph->check = compute_cksum((__u16 *)iph, sizeof(struct iphdr)/2);
513 /* Build UDP header. */
514 udph->source = htons(current->domain);
515 udph->dest = htons(666);
516 udph->len = htons(sizeof(struct udphdr) + len);
517 udph->check = 0;
519 /* Build the UDP payload. */
520 memcpy((char *)(udph + 1), str, len);
522 /* Fix Ethernet header. */
523 memset(ethh->h_source, 0, ETH_ALEN);
524 memset(ethh->h_dest, 0, ETH_ALEN);
525 ethh->h_proto = htons(ETH_P_IP);
526 skb->mac.ethernet= (struct ethhdr *)ethh;
528 unmap_domain_mem(skb_data);
530 skb->dst_vif = find_vif_by_id(0);
531 (void)netif_rx(skb);
533 return 1;
534 }
537 long do_console_write(char *str, unsigned int count)
538 {
539 #define SIZEOF_BUF 256
540 unsigned char safe_str[SIZEOF_BUF];
541 unsigned char exported_str[SIZEOF_BUF+1];
542 unsigned char dom_id[5];
543 unsigned long flags;
544 int i=0;
545 int j=0;
546 unsigned char prev = '\n';
548 if ( count > SIZEOF_BUF ) count = SIZEOF_BUF;
550 if ( copy_from_user(safe_str, str, count) )
551 return -EFAULT;
553 spin_lock_irqsave(&console_lock, flags);
555 __putstr("DOM");
556 sprintf(dom_id, "%d", current->domain);
557 __putstr(dom_id);
558 __putstr(": ");
560 for ( i = 0; i < count; i++ )
561 {
562 exported_str[j++]=safe_str[i];
564 if ( !safe_str[i] ) break;
565 putchar(prev = safe_str[i]);
566 }
568 if ( prev != '\n' ) putchar('\n');
570 spin_unlock_irqrestore(&console_lock, flags);
572 exported_str[j++]='\0';
573 console_export(exported_str, j);
575 return(0);
576 }
578 void __out_of_line_bug(int line)
579 {
580 printk("kernel BUG in header file at line %d\n", line);
581 BUG();
582 for ( ; ; ) continue;
583 }