ia64/xen-unstable

view xen/drivers/char/console.c @ 11430:0419253c81de

Fix inverted sense of getRequiredAvailableMemory and
getRequiredInitialReservation on x86 HVM.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Sep 05 16:23:11 2006 +0100 (2006-09-05)
parents ca9f3a7b1b03
children 19b126974c1f
line source
1 /******************************************************************************
2 * console.c
3 *
4 * Emergency console I/O for Xen and the domain-0 guest OS.
5 *
6 * Copyright (c) 2002-2004, K A Fraser.
7 */
9 #include <stdarg.h>
10 #include <xen/config.h>
11 #include <xen/version.h>
12 #include <xen/init.h>
13 #include <xen/lib.h>
14 #include <xen/errno.h>
15 #include <xen/event.h>
16 #include <xen/spinlock.h>
17 #include <xen/console.h>
18 #include <xen/serial.h>
19 #include <xen/softirq.h>
20 #include <xen/keyhandler.h>
21 #include <xen/mm.h>
22 #include <xen/delay.h>
23 #include <xen/guest_access.h>
24 #include <xen/shutdown.h>
25 #include <xen/vga.h>
26 #include <asm/current.h>
27 #include <asm/debugger.h>
28 #include <asm/io.h>
30 /* console: comma-separated list of console outputs. */
31 static char opt_console[30] = OPT_CONSOLE_STR;
32 string_param("console", opt_console);
34 /* conswitch: a character pair controlling console switching. */
35 /* Char 1: CTRL+<char1> is used to switch console input between Xen and DOM0 */
36 /* Char 2: If this character is 'x', then do not auto-switch to DOM0 when it */
37 /* boots. Any other value, or omitting the char, enables auto-switch */
38 static unsigned char opt_conswitch[5] = "a";
39 string_param("conswitch", opt_conswitch);
41 /* sync_console: force synchronous console output (useful for debugging). */
42 static int opt_sync_console;
43 boolean_param("sync_console", opt_sync_console);
45 #define CONRING_SIZE 16384
46 #define CONRING_IDX_MASK(i) ((i)&(CONRING_SIZE-1))
47 static char conring[CONRING_SIZE];
48 static unsigned int conringc, conringp;
50 static char printk_prefix[16] = "";
52 static int sercon_handle = -1;
54 static DEFINE_SPINLOCK(console_lock);
56 /*
57 * ********************************************************
58 * *************** ACCESS TO CONSOLE RING *****************
59 * ********************************************************
60 */
62 static void putchar_console_ring(int c)
63 {
64 conring[CONRING_IDX_MASK(conringp++)] = c;
65 if ( (conringp - conringc) > CONRING_SIZE )
66 conringc = conringp - CONRING_SIZE;
67 }
69 long read_console_ring(XEN_GUEST_HANDLE(char) str, u32 *pcount, int clear)
70 {
71 unsigned int idx, len, max, sofar, c;
72 unsigned long flags;
74 max = *pcount;
75 sofar = 0;
77 c = conringc;
78 while ( (c != conringp) && (sofar < max) )
79 {
80 idx = CONRING_IDX_MASK(c);
81 len = conringp - c;
82 if ( (idx + len) > CONRING_SIZE )
83 len = CONRING_SIZE - idx;
84 if ( (sofar + len) > max )
85 len = max - sofar;
86 if ( copy_to_guest_offset(str, sofar, &conring[idx], len) )
87 return -EFAULT;
88 sofar += len;
89 c += len;
90 }
92 if ( clear )
93 {
94 spin_lock_irqsave(&console_lock, flags);
95 if ( (conringp - c) > CONRING_SIZE )
96 conringc = conringp - CONRING_SIZE;
97 else
98 conringc = c;
99 spin_unlock_irqrestore(&console_lock, flags);
100 }
102 *pcount = sofar;
103 return 0;
104 }
107 /*
108 * *******************************************************
109 * *************** ACCESS TO SERIAL LINE *****************
110 * *******************************************************
111 */
113 /* Characters received over the serial line are buffered for domain 0. */
114 #define SERIAL_RX_SIZE 128
115 #define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
116 static char serial_rx_ring[SERIAL_RX_SIZE];
117 static unsigned int serial_rx_cons, serial_rx_prod;
119 /* CTRL-<switch_char> switches input direction between Xen and DOM0. */
120 #define SWITCH_CODE (opt_conswitch[0]-'a'+1)
121 static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */
123 static void switch_serial_input(void)
124 {
125 static char *input_str[2] = { "DOM0", "Xen" };
126 xen_rx = !xen_rx;
127 if ( (SWITCH_CODE != 0) && (dom0 != NULL) )
128 {
129 printk("*** Serial input -> %s "
130 "(type 'CTRL-%c' three times to switch input to %s).\n",
131 input_str[xen_rx], opt_conswitch[0], input_str[!xen_rx]);
132 }
133 }
135 static void __serial_rx(char c, struct cpu_user_regs *regs)
136 {
137 if ( xen_rx )
138 return handle_keypress(c, regs);
140 /* Deliver input to guest buffer, unless it is already full. */
141 if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
142 serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
143 /* Always notify the guest: prevents receive path from getting stuck. */
144 send_guest_global_virq(dom0, VIRQ_CONSOLE);
145 }
147 static void serial_rx(char c, struct cpu_user_regs *regs)
148 {
149 static int switch_code_count = 0;
151 if ( (SWITCH_CODE != 0) && (c == SWITCH_CODE) )
152 {
153 /* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
154 if ( ++switch_code_count == 3 )
155 {
156 switch_serial_input();
157 switch_code_count = 0;
158 return;
159 }
160 }
161 else
162 {
163 switch_code_count = 0;
164 }
166 /* Finally process the just-received character. */
167 __serial_rx(c, regs);
168 }
170 static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count)
171 {
172 char kbuf[128], *kptr;
173 int kcount;
175 while ( count > 0 )
176 {
177 while ( serial_tx_space(sercon_handle) < (SERIAL_TXBUFSZ / 2) )
178 {
179 if ( hypercall_preempt_check() )
180 break;
181 cpu_relax();
182 }
184 if ( hypercall_preempt_check() )
185 return hypercall_create_continuation(
186 __HYPERVISOR_console_io, "iih",
187 CONSOLEIO_write, count, buffer);
189 kcount = min_t(int, count, sizeof(kbuf)-1);
190 if ( copy_from_guest((char *)kbuf, buffer, kcount) )
191 return -EFAULT;
192 kbuf[kcount] = '\0';
194 serial_puts(sercon_handle, kbuf);
196 for ( kptr = kbuf; *kptr != '\0'; kptr++ )
197 vga_putchar(*kptr);
199 guest_handle_add_offset(buffer, kcount);
200 count -= kcount;
201 }
203 return 0;
204 }
206 long do_console_io(int cmd, int count, XEN_GUEST_HANDLE(char) buffer)
207 {
208 long rc;
209 unsigned int idx, len;
211 #ifndef VERBOSE
212 /* Only domain 0 may access the emergency console. */
213 if ( current->domain->domain_id != 0 )
214 return -EPERM;
215 #endif
217 switch ( cmd )
218 {
219 case CONSOLEIO_write:
220 rc = guest_console_write(buffer, count);
221 break;
222 case CONSOLEIO_read:
223 rc = 0;
224 while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
225 {
226 idx = SERIAL_RX_MASK(serial_rx_cons);
227 len = serial_rx_prod - serial_rx_cons;
228 if ( (idx + len) > SERIAL_RX_SIZE )
229 len = SERIAL_RX_SIZE - idx;
230 if ( (rc + len) > count )
231 len = count - rc;
232 if ( copy_to_guest_offset(buffer, rc, &serial_rx_ring[idx], len) )
233 {
234 rc = -EFAULT;
235 break;
236 }
237 rc += len;
238 serial_rx_cons += len;
239 }
240 break;
241 default:
242 rc = -ENOSYS;
243 break;
244 }
246 return rc;
247 }
250 /*
251 * *****************************************************
252 * *************** GENERIC CONSOLE I/O *****************
253 * *****************************************************
254 */
256 static inline void __putstr(const char *str)
257 {
258 int c;
260 serial_puts(sercon_handle, str);
262 while ( (c = *str++) != '\0' )
263 {
264 vga_putchar(c);
265 putchar_console_ring(c);
266 }
267 }
269 void printf(const char *fmt, ...)
270 {
271 static char buf[1024];
272 static int start_of_line = 1;
274 va_list args;
275 char *p, *q;
276 unsigned long flags;
278 spin_lock_irqsave(&console_lock, flags);
280 va_start(args, fmt);
281 (void)vsnprintf(buf, sizeof(buf), fmt, args);
282 va_end(args);
284 p = buf;
285 while ( (q = strchr(p, '\n')) != NULL )
286 {
287 *q = '\0';
288 if ( start_of_line )
289 __putstr(printk_prefix);
290 __putstr(p);
291 __putstr("\n");
292 start_of_line = 1;
293 p = q + 1;
294 }
296 if ( *p != '\0' )
297 {
298 if ( start_of_line )
299 __putstr(printk_prefix);
300 __putstr(p);
301 start_of_line = 0;
302 }
304 spin_unlock_irqrestore(&console_lock, flags);
305 }
307 void set_printk_prefix(const char *prefix)
308 {
309 strcpy(printk_prefix, prefix);
310 }
312 void init_console(void)
313 {
314 char *p;
316 /* Where should console output go? */
317 for ( p = opt_console; p != NULL; p = strchr(p, ',') )
318 {
319 if ( *p == ',' )
320 p++;
321 if ( strncmp(p, "com", 3) == 0 )
322 sercon_handle = serial_parse_handle(p);
323 else if ( strncmp(p, "vga", 3) == 0 )
324 vga_init();
325 }
327 serial_set_rx_handler(sercon_handle, serial_rx);
329 /* HELLO WORLD --- start-of-day banner text. */
330 printk(xen_banner());
331 printk(" http://www.cl.cam.ac.uk/netos/xen\n");
332 printk(" University of Cambridge Computer Laboratory\n\n");
333 printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n",
334 xen_major_version(), xen_minor_version(), xen_extra_version(),
335 xen_compile_by(), xen_compile_domain(),
336 xen_compiler(), xen_compile_date());
337 printk(" Latest ChangeSet: %s\n\n", xen_changeset());
338 set_printk_prefix("(XEN) ");
340 if ( opt_sync_console )
341 {
342 serial_start_sync(sercon_handle);
343 add_taint(TAINT_SYNC_CONSOLE);
344 printk("Console output is synchronous.\n");
345 }
346 }
348 void console_endboot(void)
349 {
350 int i, j;
352 if ( opt_sync_console )
353 {
354 printk("**********************************************\n");
355 printk("******* WARNING: CONSOLE OUTPUT IS SYCHRONOUS\n");
356 printk("******* This option is intended to aid debugging "
357 "of Xen by ensuring\n");
358 printk("******* that all output is synchronously delivered "
359 "on the serial line.\n");
360 printk("******* However it can introduce SIGNIFICANT latencies "
361 "and affect\n");
362 printk("******* timekeeping. It is NOT recommended for "
363 "production use!\n");
364 printk("**********************************************\n");
365 for ( i = 0; i < 3; i++ )
366 {
367 printk("%d... ", 3-i);
368 for ( j = 0; j < 100; j++ )
369 {
370 process_pending_timers();
371 mdelay(10);
372 }
373 }
374 printk("\n");
375 }
377 vga_endboot();
379 /*
380 * If user specifies so, we fool the switch routine to redirect input
381 * straight back to Xen. I use this convoluted method so we still print
382 * a useful 'how to switch' message.
383 */
384 if ( opt_conswitch[1] == 'x' )
385 xen_rx = !xen_rx;
387 /* Serial input is directed to DOM0 by default. */
388 switch_serial_input();
389 }
391 void console_force_unlock(void)
392 {
393 console_lock = SPIN_LOCK_UNLOCKED;
394 serial_force_unlock(sercon_handle);
395 console_start_sync();
396 }
398 void console_force_lock(void)
399 {
400 spin_lock(&console_lock);
401 }
403 void console_start_sync(void)
404 {
405 serial_start_sync(sercon_handle);
406 }
408 void console_end_sync(void)
409 {
410 serial_end_sync(sercon_handle);
411 }
413 void console_putc(char c)
414 {
415 serial_putc(sercon_handle, c);
416 }
418 int console_getc(void)
419 {
420 return serial_getc(sercon_handle);
421 }
424 /*
425 * **************************************************************
426 * *************** Serial console ring buffer *******************
427 * **************************************************************
428 */
430 #ifdef DEBUG_TRACE_DUMP
432 /* Send output direct to console, or buffer it? */
433 static volatile int debugtrace_send_to_console;
435 static char *debugtrace_buf; /* Debug-trace buffer */
436 static unsigned int debugtrace_prd; /* Producer index */
437 static unsigned int debugtrace_kilobytes = 128, debugtrace_bytes;
438 static unsigned int debugtrace_used;
439 static DEFINE_SPINLOCK(debugtrace_lock);
440 integer_param("debugtrace", debugtrace_kilobytes);
442 static void debugtrace_dump_worker(void)
443 {
444 if ( (debugtrace_bytes == 0) || !debugtrace_used )
445 return;
447 printk("debugtrace_dump() starting\n");
449 /* Print oldest portion of the ring. */
450 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
451 serial_puts(sercon_handle, &debugtrace_buf[debugtrace_prd]);
453 /* Print youngest portion of the ring. */
454 debugtrace_buf[debugtrace_prd] = '\0';
455 serial_puts(sercon_handle, &debugtrace_buf[0]);
457 memset(debugtrace_buf, '\0', debugtrace_bytes);
459 printk("debugtrace_dump() finished\n");
460 }
462 static void debugtrace_toggle(void)
463 {
464 unsigned long flags;
466 watchdog_disable();
467 spin_lock_irqsave(&debugtrace_lock, flags);
469 // dump the buffer *before* toggling, in case the act of dumping the
470 // buffer itself causes more printk's...
471 //
472 printk("debugtrace_printk now writing to %s.\n",
473 !debugtrace_send_to_console ? "console": "buffer");
474 if ( !debugtrace_send_to_console )
475 debugtrace_dump_worker();
477 debugtrace_send_to_console = !debugtrace_send_to_console;
479 spin_unlock_irqrestore(&debugtrace_lock, flags);
480 watchdog_enable();
482 }
484 void debugtrace_dump(void)
485 {
486 unsigned long flags;
488 watchdog_disable();
489 spin_lock_irqsave(&debugtrace_lock, flags);
491 debugtrace_dump_worker();
493 spin_unlock_irqrestore(&debugtrace_lock, flags);
494 watchdog_enable();
495 }
497 void debugtrace_printk(const char *fmt, ...)
498 {
499 static char buf[1024];
500 static u32 count;
502 va_list args;
503 char *p;
504 unsigned long flags;
506 if ( debugtrace_bytes == 0 )
507 return;
509 debugtrace_used = 1;
511 spin_lock_irqsave(&debugtrace_lock, flags);
513 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
515 sprintf(buf, "%u ", ++count);
517 va_start(args, fmt);
518 (void)vsnprintf(buf + strlen(buf), sizeof(buf), fmt, args);
519 va_end(args);
521 if ( debugtrace_send_to_console )
522 {
523 serial_puts(sercon_handle, buf);
524 }
525 else
526 {
527 for ( p = buf; *p != '\0'; p++ )
528 {
529 debugtrace_buf[debugtrace_prd++] = *p;
530 /* Always leave a nul byte at the end of the buffer. */
531 if ( debugtrace_prd == (debugtrace_bytes - 1) )
532 debugtrace_prd = 0;
533 }
534 }
536 spin_unlock_irqrestore(&debugtrace_lock, flags);
537 }
539 static void debugtrace_key(unsigned char key)
540 {
541 debugtrace_toggle();
542 }
544 static int __init debugtrace_init(void)
545 {
546 int order;
547 unsigned int kbytes, bytes;
549 /* Round size down to next power of two. */
550 while ( (kbytes = (debugtrace_kilobytes & (debugtrace_kilobytes-1))) != 0 )
551 debugtrace_kilobytes = kbytes;
553 bytes = debugtrace_kilobytes << 10;
554 if ( bytes == 0 )
555 return 0;
557 order = get_order_from_bytes(bytes);
558 debugtrace_buf = alloc_xenheap_pages(order);
559 ASSERT(debugtrace_buf != NULL);
561 memset(debugtrace_buf, '\0', bytes);
563 debugtrace_bytes = bytes;
565 register_keyhandler(
566 'T', debugtrace_key, "toggle debugtrace to console/buffer");
568 return 0;
569 }
570 __initcall(debugtrace_init);
572 #endif /* !NDEBUG */
576 /*
577 * **************************************************************
578 * *************** Debugging/tracing/error-report ***************
579 * **************************************************************
580 */
582 void panic(const char *fmt, ...)
583 {
584 va_list args;
585 char buf[128];
586 unsigned long flags;
587 static DEFINE_SPINLOCK(lock);
589 debugtrace_dump();
591 va_start(args, fmt);
592 (void)vsnprintf(buf, sizeof(buf), fmt, args);
593 va_end(args);
595 /* Spit out multiline message in one go. */
596 console_start_sync();
597 spin_lock_irqsave(&lock, flags);
598 printk("\n****************************************\n");
599 printk("Panic on CPU %d:\n", smp_processor_id());
600 printk(buf);
601 printk("****************************************\n\n");
602 if ( opt_noreboot )
603 printk("Manual reset required ('noreboot' specified)\n");
604 else
605 printk("Reboot in five seconds...\n");
606 spin_unlock_irqrestore(&lock, flags);
608 debugger_trap_immediate();
610 if ( opt_noreboot )
611 {
612 machine_halt();
613 }
614 else
615 {
616 watchdog_disable();
617 mdelay(5000);
618 machine_restart(NULL);
619 }
620 }
622 void __bug(char *file, int line)
623 {
624 console_start_sync();
625 debugtrace_dump();
626 printk("BUG at %s:%d\n", file, line);
627 FORCE_CRASH();
628 for ( ; ; ) ;
629 }
631 /*
632 * Local variables:
633 * mode: C
634 * c-set-style: "BSD"
635 * c-basic-offset: 4
636 * tab-width: 4
637 * indent-tabs-mode: nil
638 * End:
639 */