ia64/xen-unstable

annotate xen/drivers/char/console.c @ 6339:f51fe43c5d1c

Merge libxenstat and xentop.
author cl349@firebug.cl.cam.ac.uk
date Mon Aug 22 21:54:28 2005 +0000 (2005-08-22)
parents 47d49e8b8042 f294acb25858
children d13f5c7daddf d760699356fd 6783e59e1c45
rev   line source
kaf24@1150 1 /******************************************************************************
kaf24@1150 2 * console.c
kaf24@1150 3 *
kaf24@1150 4 * Emergency console I/O for Xen and the domain-0 guest OS.
kaf24@1150 5 *
kaf24@1150 6 * Copyright (c) 2002-2004, K A Fraser.
kaf24@1150 7 */
kaf24@1150 8
kaf24@1150 9 #include <stdarg.h>
kaf24@1210 10 #include <xen/config.h>
kaf24@3338 11 #include <xen/compile.h>
kaf24@3334 12 #include <xen/init.h>
kaf24@1210 13 #include <xen/lib.h>
kaf24@1210 14 #include <xen/errno.h>
kaf24@1210 15 #include <xen/event.h>
kaf24@1210 16 #include <xen/spinlock.h>
kaf24@1210 17 #include <xen/console.h>
kaf24@1210 18 #include <xen/serial.h>
kaf24@5327 19 #include <xen/softirq.h>
kaf24@1210 20 #include <xen/keyhandler.h>
kaf24@4839 21 #include <xen/mm.h>
cl349@5286 22 #include <xen/delay.h>
cl349@5291 23 #include <asm/current.h>
kaf24@1150 24 #include <asm/uaccess.h>
sos22@3763 25 #include <asm/debugger.h>
kaf24@4253 26 #include <asm/io.h>
kaf24@1150 27
kaf24@5322 28 /* console: comma-separated list of console outputs. */
riel@3992 29 static char opt_console[30] = OPT_CONSOLE_STR;
kaf24@3334 30 string_param("console", opt_console);
kaf24@3334 31
kaf24@5322 32 /* conswitch: a character pair controlling console switching. */
kaf24@3334 33 /* Char 1: CTRL+<char1> is used to switch console input between Xen and DOM0 */
kaf24@3334 34 /* Char 2: If this character is 'x', then do not auto-switch to DOM0 when it */
kaf24@3334 35 /* boots. Any other value, or omitting the char, enables auto-switch */
kaf24@3334 36 static unsigned char opt_conswitch[5] = "a";
kaf24@3334 37 string_param("conswitch", opt_conswitch);
kaf24@1769 38
kaf24@5322 39 /* sync_console: force synchronous console output (useful for debugging). */
kaf24@5322 40 static int opt_sync_console;
kaf24@5322 41 boolean_param("sync_console", opt_sync_console);
kaf24@5322 42
kaf24@1150 43 static int xpos, ypos;
kaf24@3477 44 static unsigned char *video;
kaf24@1150 45
kaf24@5327 46 #define CONRING_SIZE 16384
kaf24@5327 47 #define CONRING_IDX_MASK(i) ((i)&(CONRING_SIZE-1))
kaf24@5327 48 static char conring[CONRING_SIZE];
kaf24@5327 49 static unsigned int conringc, conringp;
kaf24@1150 50
kaf24@1150 51 static char printk_prefix[16] = "";
kaf24@1150 52
kaf24@1150 53 static int sercon_handle = -1;
kaf24@1150 54 static int vgacon_enabled = 0;
kaf24@1150 55
kaf24@1150 56 spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
kaf24@1150 57
kaf24@1150 58 /*
kaf24@1150 59 * *******************************************************
kaf24@1150 60 * *************** OUTPUT TO VGA CONSOLE *****************
kaf24@1150 61 * *******************************************************
kaf24@1150 62 */
kaf24@1150 63
kaf24@1150 64 /* VGA text (mode 3) definitions. */
kaf24@1426 65 #define COLUMNS 80
kaf24@1426 66 #define LINES 25
kaf24@1150 67 #define ATTRIBUTE 7
kaf24@1150 68
kaf24@1150 69 /* Clear the screen and initialize VIDEO, XPOS and YPOS. */
kaf24@1150 70 static void cls(void)
kaf24@1150 71 {
kaf24@1150 72 memset(video, 0, COLUMNS * LINES * 2);
kaf24@1150 73 xpos = ypos = 0;
kaf24@1150 74 outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
kaf24@1150 75 }
kaf24@1150 76
kaf24@1150 77 static int detect_video(void *video_base)
kaf24@1150 78 {
kaf24@1150 79 volatile u16 *p = (volatile u16 *)video_base;
kaf24@1150 80 u16 saved1 = p[0], saved2 = p[1];
kaf24@1150 81 int video_found = 1;
kaf24@1150 82
kaf24@1150 83 p[0] = 0xAA55;
kaf24@1150 84 p[1] = 0x55AA;
kaf24@1150 85 if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
kaf24@1150 86 video_found = 0;
kaf24@1150 87
kaf24@1150 88 p[0] = 0x55AA;
kaf24@1150 89 p[1] = 0xAA55;
kaf24@1150 90 if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
kaf24@1150 91 video_found = 0;
kaf24@1150 92
kaf24@1150 93 p[0] = saved1;
kaf24@1150 94 p[1] = saved2;
kaf24@1150 95
kaf24@1150 96 return video_found;
kaf24@1150 97 }
kaf24@1150 98
kaf24@1150 99 static int detect_vga(void)
kaf24@1150 100 {
kaf24@1150 101 /*
kaf24@1150 102 * Look at a number of well-known locations. Even if video is not at
kaf24@1150 103 * 0xB8000 right now, it will appear there when we set up text mode 3.
kaf24@1150 104 *
kaf24@1150 105 * We assume if there is any sign of a video adaptor then it is at least
kaf24@1150 106 * VGA-compatible (surely noone runs CGA, EGA, .... these days?).
kaf24@1150 107 *
kaf24@1150 108 * These checks are basically to detect headless server boxes.
kaf24@1150 109 */
kaf24@1150 110 return (detect_video(__va(0xA0000)) ||
kaf24@1150 111 detect_video(__va(0xB0000)) ||
kaf24@1150 112 detect_video(__va(0xB8000)));
kaf24@1150 113 }
kaf24@1150 114
kaf24@1150 115 /* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
kaf24@1150 116 static void init_vga(void)
kaf24@1150 117 {
kaf24@1150 118 /* The following VGA state was saved from a chip in text mode 3. */
kaf24@1150 119 static unsigned char regs[] = {
kaf24@1150 120 /* Sequencer registers */
kaf24@1150 121 0x03, 0x00, 0x03, 0x00, 0x02,
kaf24@1150 122 /* CRTC registers */
kaf24@1150 123 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
kaf24@1150 124 0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
kaf24@1150 125 0xb9, 0xa3, 0xff,
kaf24@1150 126 /* Graphic registers */
kaf24@1150 127 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
kaf24@1150 128 /* Attribute registers */
kaf24@1150 129 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
kaf24@1150 130 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
kaf24@1150 131 };
kaf24@1150 132
kaf24@1150 133 int i, j = 0;
kaf24@1150 134 volatile unsigned char tmp;
kaf24@1150 135
kaf24@1150 136 if ( !vgacon_enabled )
kaf24@1150 137 return;
kaf24@1150 138
kaf24@1150 139 if ( !detect_vga() )
kaf24@1150 140 {
kaf24@1150 141 printk("No VGA adaptor detected!\n");
kaf24@1150 142 vgacon_enabled = 0;
kaf24@1150 143 return;
kaf24@1150 144 }
kaf24@1150 145
kaf24@3477 146 video = __va(0xB8000);
kaf24@3477 147
kaf24@1150 148 tmp = inb(0x3da);
kaf24@1150 149 outb(0x00, 0x3c0);
kaf24@1150 150
kaf24@1150 151 for ( i = 0; i < 5; i++ )
kaf24@1150 152 outw((regs[j++] << 8) | i, 0x3c4);
kaf24@1150 153
kaf24@1150 154 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
kaf24@1150 155 outw(((regs[5+17] & 0x7F) << 8) | 17, 0x3d4);
kaf24@1150 156
kaf24@1150 157 for ( i = 0; i < 25; i++ )
kaf24@1150 158 outw((regs[j++] << 8) | i, 0x3d4);
kaf24@1150 159
kaf24@1150 160 for ( i = 0; i < 9; i++ )
kaf24@1150 161 outw((regs[j++] << 8) | i, 0x3ce);
kaf24@1150 162
kaf24@1150 163 for ( i = 0; i < 21; i++ )
kaf24@1150 164 {
kaf24@1150 165 tmp = inb(0x3da);
kaf24@1150 166 outb(i, 0x3c0);
kaf24@1150 167 outb(regs[j++], 0x3c0);
kaf24@1150 168 }
kaf24@1150 169
kaf24@1150 170 tmp = inb(0x3da);
kaf24@1150 171 outb(0x20, 0x3c0);
kaf24@1150 172
kaf24@1150 173 cls();
kaf24@1150 174 }
kaf24@1150 175
kaf24@1150 176 static void put_newline(void)
kaf24@1150 177 {
kaf24@1150 178 xpos = 0;
kaf24@1150 179 ypos++;
kaf24@1150 180
kaf24@1150 181 if (ypos >= LINES)
kaf24@1150 182 {
kaf24@1150 183 static char zeroarr[2*COLUMNS] = { 0 };
kaf24@1150 184 ypos = LINES-1;
kaf24@1150 185 memcpy((char*)video,
kaf24@1150 186 (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
kaf24@1150 187 memcpy((char*)video + (LINES-1)*2*COLUMNS,
kaf24@1150 188 zeroarr, 2*COLUMNS);
kaf24@1150 189 }
kaf24@1150 190 }
kaf24@1150 191
kaf24@1150 192 static void putchar_console(int c)
kaf24@1150 193 {
kaf24@1150 194 if ( !vgacon_enabled )
kaf24@1150 195 return;
kaf24@1150 196
kaf24@1150 197 if ( c == '\n' )
kaf24@1150 198 {
kaf24@1150 199 put_newline();
kaf24@1150 200 }
kaf24@1150 201 else
kaf24@1150 202 {
kaf24@1150 203 video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF;
kaf24@1150 204 video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
kaf24@1150 205 if ( ++xpos >= COLUMNS )
kaf24@1150 206 put_newline();
kaf24@1150 207 }
kaf24@1150 208 }
kaf24@1150 209
kaf24@1150 210
kaf24@1150 211 /*
kaf24@1150 212 * ********************************************************
kaf24@1150 213 * *************** ACCESS TO CONSOLE RING *****************
kaf24@1150 214 * ********************************************************
kaf24@1150 215 */
kaf24@1150 216
kaf24@1150 217 static void putchar_console_ring(int c)
kaf24@1150 218 {
kaf24@5327 219 conring[CONRING_IDX_MASK(conringp++)] = c;
kaf24@5327 220 if ( (conringp - conringc) > CONRING_SIZE )
kaf24@5327 221 conringc = conringp - CONRING_SIZE;
kaf24@1150 222 }
kaf24@1150 223
kaf24@5327 224 long read_console_ring(char **pstr, u32 *pcount, int clear)
kaf24@1150 225 {
kaf24@5327 226 char *str = *pstr;
kaf24@5327 227 u32 count = *pcount;
kaf24@5327 228 unsigned int p, q;
kaf24@5327 229 unsigned long flags;
kaf24@5327 230
kaf24@5327 231 /* Start of buffer may get overwritten during copy. So copy backwards. */
kaf24@5327 232 for ( p = conringp, q = count; (p > conringc) && (q > 0); p--, q-- )
kaf24@5327 233 if ( put_user(conring[CONRING_IDX_MASK(p-1)], (char *)str+q-1) )
kaf24@5327 234 return -EFAULT;
kaf24@1150 235
kaf24@5327 236 if ( clear )
kaf24@5327 237 {
kaf24@5327 238 spin_lock_irqsave(&console_lock, flags);
kaf24@5327 239 conringc = conringp;
kaf24@5327 240 spin_unlock_irqrestore(&console_lock, flags);
kaf24@5327 241 }
kaf24@5327 242
kaf24@5327 243 *pstr = str + q;
kaf24@5327 244 *pcount = count - q;
kaf24@5327 245 return 0;
kaf24@1150 246 }
kaf24@1150 247
kaf24@1150 248
kaf24@1150 249 /*
kaf24@1150 250 * *******************************************************
kaf24@1150 251 * *************** ACCESS TO SERIAL LINE *****************
kaf24@1150 252 * *******************************************************
kaf24@1150 253 */
kaf24@1150 254
kaf24@1150 255 /* Characters received over the serial line are buffered for domain 0. */
kaf24@1150 256 #define SERIAL_RX_SIZE 128
kaf24@1150 257 #define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
kaf24@1150 258 static char serial_rx_ring[SERIAL_RX_SIZE];
kaf24@1150 259 static unsigned int serial_rx_cons, serial_rx_prod;
kaf24@1150 260
kaf24@1769 261 /* CTRL-<switch_char> switches input direction between Xen and DOM0. */
kaf24@1769 262 #define SWITCH_CODE (opt_conswitch[0]-'a'+1)
kaf24@1175 263 static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */
kaf24@1175 264
kaf24@1175 265 static void switch_serial_input(void)
kaf24@1175 266 {
kaf24@1175 267 static char *input_str[2] = { "DOM0", "Xen" };
kaf24@1175 268 xen_rx = !xen_rx;
kaf24@1769 269 if ( SWITCH_CODE != 0 )
mafetter@3816 270 {
kaf24@1769 271 printk("*** Serial input -> %s "
kaf24@1769 272 "(type 'CTRL-%c' three times to switch input to %s).\n",
kaf24@1769 273 input_str[xen_rx], opt_conswitch[0], input_str[!xen_rx]);
mafetter@3816 274 }
kaf24@1175 275 }
kaf24@1150 276
kaf24@5195 277 static void __serial_rx(char c, struct cpu_user_regs *regs)
kaf24@1150 278 {
kaf24@1175 279 if ( xen_rx )
kaf24@4988 280 return handle_keypress(c, regs);
kaf24@4988 281
kaf24@4988 282 /* Deliver input to guest buffer, unless it is already full. */
kaf24@4988 283 if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
kaf24@4988 284 serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
kaf24@4988 285 /* Always notify the guest: prevents receive path from getting stuck. */
kaf24@5289 286 send_guest_virq(dom0->vcpu[0], VIRQ_CONSOLE);
kaf24@1150 287 }
kaf24@1150 288
kaf24@5195 289 static void serial_rx(char c, struct cpu_user_regs *regs)
kaf24@1176 290 {
kaf24@1769 291 static int switch_code_count = 0;
kaf24@1176 292
kaf24@1769 293 if ( (SWITCH_CODE != 0) && (c == SWITCH_CODE) )
kaf24@1176 294 {
kaf24@1769 295 /* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
kaf24@1769 296 if ( ++switch_code_count == 3 )
kaf24@1176 297 {
kaf24@1176 298 switch_serial_input();
kaf24@1769 299 switch_code_count = 0;
iap10@5060 300 return;
kaf24@1176 301 }
kaf24@1176 302 }
kaf24@1176 303 else
kaf24@1176 304 {
kaf24@1769 305 switch_code_count = 0;
kaf24@1176 306 }
kaf24@1248 307
kaf24@1248 308 /* Finally process the just-received character. */
kaf24@1248 309 __serial_rx(c, regs);
kaf24@1176 310 }
kaf24@1176 311
kaf24@5327 312 long guest_console_write(char *buffer, int count)
kaf24@5327 313 {
kaf24@5327 314 char kbuf[128];
kaf24@5327 315 int kcount;
kaf24@5327 316
kaf24@5327 317 while ( count > 0 )
kaf24@5327 318 {
kaf24@5327 319 while ( serial_tx_space(sercon_handle) < (SERIAL_TXBUFSZ / 2) )
kaf24@5327 320 {
kaf24@5327 321 if ( hypercall_preempt_check() )
kaf24@5327 322 break;
kaf24@5327 323 cpu_relax();
kaf24@5327 324 }
kaf24@5327 325
kaf24@5327 326 if ( hypercall_preempt_check() )
kaf24@5327 327 return hypercall3_create_continuation(
kaf24@5327 328 __HYPERVISOR_console_io, CONSOLEIO_write, count, buffer);
kaf24@5327 329
kaf24@5327 330 kcount = min_t(int, count, sizeof(kbuf)-1);
kaf24@5327 331 if ( copy_from_user(kbuf, buffer, kcount) )
kaf24@5327 332 return -EFAULT;
kaf24@5327 333 kbuf[kcount] = '\0';
kaf24@5327 334
kaf24@5327 335 serial_puts(sercon_handle, kbuf);
kaf24@5327 336
kaf24@5327 337 buffer += kcount;
kaf24@5327 338 count -= kcount;
kaf24@5327 339 }
kaf24@5327 340
kaf24@5327 341 return 0;
kaf24@5327 342 }
kaf24@5327 343
kaf24@1171 344 long do_console_io(int cmd, int count, char *buffer)
kaf24@1150 345 {
kaf24@5327 346 long rc;
kaf24@1150 347
cl349@2210 348 #ifndef VERBOSE
kaf24@5327 349 /* Only domain 0 may access the emergency console. */
kaf24@4877 350 if ( current->domain->domain_id != 0 )
kaf24@1150 351 return -EPERM;
iap10@1358 352 #endif
kaf24@1150 353
kaf24@1150 354 switch ( cmd )
kaf24@1150 355 {
kaf24@1171 356 case CONSOLEIO_write:
kaf24@5327 357 rc = guest_console_write(buffer, count);
kaf24@1150 358 break;
kaf24@1171 359 case CONSOLEIO_read:
kaf24@1150 360 rc = 0;
kaf24@1150 361 while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
kaf24@1150 362 {
kaf24@1150 363 if ( put_user(serial_rx_ring[SERIAL_RX_MASK(serial_rx_cons)],
kaf24@1150 364 &buffer[rc]) )
kaf24@1150 365 {
kaf24@1150 366 rc = -EFAULT;
kaf24@1150 367 break;
kaf24@1150 368 }
kaf24@1150 369 rc++;
kaf24@1150 370 serial_rx_cons++;
kaf24@1150 371 }
kaf24@1150 372 break;
kaf24@1150 373 default:
kaf24@1150 374 rc = -ENOSYS;
kaf24@1150 375 break;
kaf24@1150 376 }
kaf24@1150 377
kaf24@1150 378 return rc;
kaf24@1150 379 }
kaf24@1150 380
kaf24@1150 381
kaf24@1150 382 /*
kaf24@1150 383 * *****************************************************
kaf24@1150 384 * *************** GENERIC CONSOLE I/O *****************
kaf24@1150 385 * *****************************************************
kaf24@1150 386 */
kaf24@1150 387
kaf24@1150 388 static inline void __putstr(const char *str)
kaf24@1150 389 {
kaf24@1150 390 int c;
mafetter@3816 391
kaf24@1150 392 serial_puts(sercon_handle, str);
mafetter@3816 393
kaf24@1150 394 while ( (c = *str++) != '\0' )
kaf24@1150 395 {
kaf24@1150 396 putchar_console(c);
kaf24@1150 397 putchar_console_ring(c);
kaf24@1150 398 }
kaf24@1150 399 }
kaf24@1150 400
kaf24@1150 401 void printf(const char *fmt, ...)
kaf24@1150 402 {
kaf24@1150 403 static char buf[1024];
kaf24@1150 404 static int start_of_line = 1;
kaf24@1150 405
kaf24@1150 406 va_list args;
kaf24@1150 407 char *p, *q;
kaf24@1150 408 unsigned long flags;
kaf24@1150 409
kaf24@1150 410 spin_lock_irqsave(&console_lock, flags);
kaf24@1150 411
kaf24@1150 412 va_start(args, fmt);
kaf24@1150 413 (void)vsnprintf(buf, sizeof(buf), fmt, args);
kaf24@1150 414 va_end(args);
kaf24@1150 415
kaf24@1150 416 p = buf;
kaf24@1150 417 while ( (q = strchr(p, '\n')) != NULL )
kaf24@1150 418 {
kaf24@1150 419 *q = '\0';
kaf24@1150 420 if ( start_of_line )
kaf24@1150 421 __putstr(printk_prefix);
kaf24@1150 422 __putstr(p);
kaf24@1150 423 __putstr("\n");
kaf24@1150 424 start_of_line = 1;
kaf24@1150 425 p = q + 1;
kaf24@1150 426 }
kaf24@1150 427
kaf24@1150 428 if ( *p != '\0' )
kaf24@1150 429 {
kaf24@1150 430 if ( start_of_line )
kaf24@1150 431 __putstr(printk_prefix);
kaf24@1150 432 __putstr(p);
kaf24@1150 433 start_of_line = 0;
kaf24@1150 434 }
kaf24@1150 435
kaf24@1150 436 spin_unlock_irqrestore(&console_lock, flags);
kaf24@1150 437 }
kaf24@1150 438
kaf24@1150 439 void set_printk_prefix(const char *prefix)
kaf24@1150 440 {
kaf24@1150 441 strcpy(printk_prefix, prefix);
kaf24@1150 442 }
kaf24@1150 443
kaf24@1150 444 void init_console(void)
kaf24@1150 445 {
riel@3992 446 char *p;
kaf24@1150 447
kaf24@1150 448 /* Where should console output go? */
kaf24@1150 449 for ( p = opt_console; p != NULL; p = strchr(p, ',') )
kaf24@1150 450 {
kaf24@1150 451 if ( *p == ',' )
kaf24@1150 452 p++;
kaf24@1150 453 if ( strncmp(p, "com", 3) == 0 )
kaf24@5195 454 sercon_handle = serial_parse_handle(p);
kaf24@1150 455 else if ( strncmp(p, "vga", 3) == 0 )
kaf24@1150 456 vgacon_enabled = 1;
kaf24@1150 457 }
kaf24@1150 458
kaf24@1150 459 init_vga();
kaf24@1150 460
kaf24@1150 461 serial_set_rx_handler(sercon_handle, serial_rx);
kaf24@3338 462
kaf24@3338 463 /* HELLO WORLD --- start-of-day banner text. */
kaf24@3338 464 printk(XEN_BANNER);
kaf24@3338 465 printk(" http://www.cl.cam.ac.uk/netos/xen\n");
kaf24@3338 466 printk(" University of Cambridge Computer Laboratory\n\n");
kaf24@3338 467 printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n",
kaf24@3338 468 XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
kaf24@3338 469 XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
kaf24@3338 470 XEN_COMPILER, XEN_COMPILE_DATE);
kaf24@3338 471 printk(" Latest ChangeSet: %s\n\n", XEN_CHANGESET);
kaf24@3338 472 set_printk_prefix("(XEN) ");
kaf24@5322 473
kaf24@5322 474 if ( opt_sync_console )
kaf24@5322 475 {
kaf24@5322 476 serial_start_sync(sercon_handle);
kaf24@5322 477 printk("Console output is synchronous.\n");
kaf24@5322 478 }
kaf24@1150 479 }
kaf24@1150 480
kaf24@1150 481 void console_endboot(int disable_vga)
kaf24@1150 482 {
kaf24@1150 483 if ( disable_vga )
kaf24@1150 484 vgacon_enabled = 0;
kaf24@1769 485
kaf24@1769 486 /*
kaf24@1769 487 * If user specifies so, we fool the switch routine to redirect input
kaf24@1769 488 * straight back to Xen. I use this convoluted method so we still print
kaf24@1769 489 * a useful 'how to switch' message.
kaf24@1769 490 */
kaf24@1769 491 if ( opt_conswitch[1] == 'x' )
kaf24@1769 492 xen_rx = !xen_rx;
kaf24@1769 493
kaf24@1150 494 /* Serial input is directed to DOM0 by default. */
kaf24@1175 495 switch_serial_input();
kaf24@1150 496 }
kaf24@1150 497
kaf24@2041 498 void console_force_unlock(void)
kaf24@2041 499 {
kaf24@2041 500 console_lock = SPIN_LOCK_UNLOCKED;
kaf24@2041 501 serial_force_unlock(sercon_handle);
kaf24@2041 502 }
kaf24@2041 503
kaf24@2041 504 void console_force_lock(void)
kaf24@2041 505 {
kaf24@2041 506 spin_lock(&console_lock);
kaf24@2041 507 }
kaf24@2041 508
kaf24@5321 509 void console_start_sync(void)
kaf24@5321 510 {
kaf24@5321 511 serial_start_sync(sercon_handle);
kaf24@5321 512 }
kaf24@5321 513
kaf24@5321 514 void console_end_sync(void)
kaf24@5321 515 {
kaf24@5321 516 serial_end_sync(sercon_handle);
kaf24@5321 517 }
kaf24@5321 518
cl349@5204 519 void console_putc(char c)
cl349@5204 520 {
cl349@5204 521 serial_putc(sercon_handle, c);
cl349@5204 522 }
cl349@5204 523
cl349@5204 524 int console_getc(void)
cl349@5204 525 {
cl349@5204 526 return serial_getc(sercon_handle);
cl349@5204 527 }
cl349@5204 528
kaf24@1150 529
kaf24@1150 530 /*
kaf24@1150 531 * **************************************************************
kaf24@3827 532 * *************** Serial console ring buffer *******************
mafetter@3816 533 * **************************************************************
mafetter@3816 534 */
mafetter@3816 535
mafetter@3816 536 #ifndef NDEBUG
kaf24@3827 537
kaf24@3875 538 /* Send output direct to console, or buffer it? */
kaf24@3875 539 int debugtrace_send_to_console;
kaf24@3875 540
kaf24@4653 541 static char *debugtrace_buf; /* Debug-trace buffer */
kaf24@4653 542 static unsigned int debugtrace_prd; /* Producer index */
kaf24@4653 543 static unsigned int debugtrace_kilobytes = 128, debugtrace_bytes;
kaf24@4923 544 static unsigned int debugtrace_used;
kaf24@4653 545 static spinlock_t debugtrace_lock = SPIN_LOCK_UNLOCKED;
kaf24@3827 546 integer_param("debugtrace", debugtrace_kilobytes);
kaf24@3827 547
kaf24@3875 548 void debugtrace_dump(void)
kaf24@3827 549 {
kaf24@3875 550 unsigned long flags;
kaf24@3827 551
kaf24@4923 552 if ( (debugtrace_bytes == 0) || !debugtrace_used )
mafetter@3816 553 return;
mafetter@3816 554
kaf24@4926 555 watchdog_disable();
kaf24@3827 556
kaf24@3875 557 spin_lock_irqsave(&debugtrace_lock, flags);
maf46@3864 558
mafetter@4139 559 printk("debugtrace_dump() starting\n");
mafetter@4139 560
kaf24@3827 561 /* Print oldest portion of the ring. */
mafetter@4139 562 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
maf46@3864 563 serial_puts(sercon_handle, &debugtrace_buf[debugtrace_prd]);
mafetter@3816 564
kaf24@3827 565 /* Print youngest portion of the ring. */
maf46@3864 566 debugtrace_buf[debugtrace_prd] = '\0';
maf46@3864 567 serial_puts(sercon_handle, &debugtrace_buf[0]);
mafetter@3816 568
kaf24@3875 569 memset(debugtrace_buf, '\0', debugtrace_bytes);
maf46@3864 570
mafetter@4139 571 printk("debugtrace_dump() finished\n");
mafetter@4139 572
kaf24@3875 573 spin_unlock_irqrestore(&debugtrace_lock, flags);
mafetter@3816 574
kaf24@4926 575 watchdog_enable();
mafetter@3816 576 }
mafetter@3816 577
kaf24@3827 578 void debugtrace_printk(const char *fmt, ...)
mafetter@3816 579 {
kaf24@3875 580 static char buf[1024];
kaf24@3827 581
kaf24@4653 582 va_list args;
kaf24@4653 583 char *p;
kaf24@4653 584 unsigned long flags;
kaf24@3827 585
kaf24@3827 586 if ( debugtrace_bytes == 0 )
mafetter@3816 587 return;
kaf24@3827 588
kaf24@4923 589 debugtrace_used = 1;
kaf24@4923 590
maf46@3864 591 spin_lock_irqsave(&debugtrace_lock, flags);
mafetter@3816 592
mafetter@4139 593 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
mafetter@4139 594
kaf24@3827 595 va_start(args, fmt);
kaf24@3827 596 (void)vsnprintf(buf, sizeof(buf), fmt, args);
maf46@3865 597 va_end(args);
kaf24@3827 598
kaf24@3875 599 if ( debugtrace_send_to_console )
maf46@3865 600 {
maf46@3865 601 serial_puts(sercon_handle, buf);
maf46@3865 602 }
maf46@3865 603 else
maf46@3864 604 {
maf46@3865 605 for ( p = buf; *p != '\0'; p++ )
maf46@3865 606 {
kaf24@3875 607 debugtrace_buf[debugtrace_prd++] = *p;
kaf24@3875 608 /* Always leave a nul byte at the end of the buffer. */
kaf24@3875 609 if ( debugtrace_prd == (debugtrace_bytes - 1) )
maf46@3865 610 debugtrace_prd = 0;
maf46@3865 611 }
maf46@3864 612 }
maf46@3864 613
maf46@3864 614 spin_unlock_irqrestore(&debugtrace_lock, flags);
mafetter@3816 615 }
mafetter@3816 616
kaf24@3827 617 static int __init debugtrace_init(void)
mafetter@3816 618 {
mafetter@3816 619 int order;
mafetter@4139 620 unsigned int kbytes, bytes;
mafetter@3816 621
kaf24@3827 622 /* Round size down to next power of two. */
kaf24@3827 623 while ( (kbytes = (debugtrace_kilobytes & (debugtrace_kilobytes-1))) != 0 )
kaf24@3827 624 debugtrace_kilobytes = kbytes;
kaf24@3827 625
mafetter@4139 626 bytes = debugtrace_kilobytes << 10;
mafetter@4139 627 if ( bytes == 0 )
mafetter@3816 628 return 0;
mafetter@3816 629
mafetter@4139 630 order = get_order(bytes);
kaf24@5398 631 debugtrace_buf = alloc_xenheap_pages(order);
kaf24@3827 632 ASSERT(debugtrace_buf != NULL);
mafetter@3816 633
mafetter@4139 634 memset(debugtrace_buf, '\0', bytes);
mafetter@4139 635
mafetter@4139 636 debugtrace_bytes = bytes;
mafetter@4139 637
mafetter@3816 638 return 0;
mafetter@3816 639 }
kaf24@3827 640 __initcall(debugtrace_init);
mafetter@3816 641
kaf24@3827 642 #endif /* !NDEBUG */
kaf24@3827 643
mafetter@3816 644
mafetter@3816 645
mafetter@3816 646 /*
mafetter@3816 647 * **************************************************************
kaf24@1150 648 * *************** Debugging/tracing/error-report ***************
kaf24@1150 649 * **************************************************************
kaf24@1150 650 */
kaf24@1150 651
kaf24@1150 652 void panic(const char *fmt, ...)
kaf24@1150 653 {
kaf24@1150 654 va_list args;
kaf24@6247 655 char buf[128];
kaf24@1150 656 unsigned long flags;
kaf24@6247 657 static spinlock_t lock = SPIN_LOCK_UNLOCKED;
kaf24@1150 658 extern void machine_restart(char *);
kaf24@1150 659
kaf24@3875 660 debugtrace_dump();
maf46@3865 661
kaf24@1150 662 va_start(args, fmt);
kaf24@1150 663 (void)vsnprintf(buf, sizeof(buf), fmt, args);
kaf24@1150 664 va_end(args);
sos22@1951 665
sos22@3763 666 debugger_trap_immediate();
sos22@1951 667
kaf24@1150 668 /* Spit out multiline message in one go. */
kaf24@6247 669 spin_lock_irqsave(&lock, flags);
kaf24@6247 670 printk("\n****************************************\n");
kaf24@6247 671 printk("Panic on CPU %d:\n", smp_processor_id());
kaf24@6247 672 printk(buf);
kaf24@6247 673 printk("****************************************\n\n");
kaf24@6247 674 printk("Reboot in five seconds...\n");
kaf24@6247 675 spin_unlock_irqrestore(&lock, flags);
kaf24@1150 676
kaf24@4926 677 watchdog_disable();
kaf24@1150 678 mdelay(5000);
kaf24@1150 679 machine_restart(0);
kaf24@1150 680 }
kaf24@1150 681
kaf24@3914 682 /*
kaf24@3914 683 * Local variables:
kaf24@3914 684 * mode: C
kaf24@3914 685 * c-set-style: "BSD"
kaf24@3914 686 * c-basic-offset: 4
kaf24@3914 687 * tab-width: 4
kaf24@3914 688 * indent-tabs-mode: nil
kaf24@3988 689 * End:
kaf24@3914 690 */
kaf24@1150 691