1 /******************************************************************************
4 * Virtual console driver.
6 * Copyright (c) 2002-2004, K A Fraser.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation; or, when distributed
11 * separately from the Linux kernel or incorporated into other
12 * software packages, subject to the following license:
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this source file (the "Software"), to deal in the Software without
16 * restriction, including without limitation the rights to use, copy, modify,
17 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18 * and to permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 #include <linux/module.h>
34 #include <linux/errno.h>
35 #include <linux/signal.h>
36 #include <linux/sched.h>
37 #include <linux/interrupt.h>
38 #include <linux/tty.h>
39 #include <linux/tty_flip.h>
40 #include <linux/serial.h>
41 #include <linux/major.h>
42 #include <linux/ptrace.h>
43 #include <linux/ioport.h>
45 #include <linux/slab.h>
46 #include <linux/init.h>
47 #include <linux/console.h>
48 #include <linux/sysrq.h>
52 #include <asm/uaccess.h>
53 #include <xen/interface/xen.h>
54 #include <xen/interface/event_channel.h>
55 #include <asm/hypervisor.h>
56 #include <xen/evtchn.h>
57 #include <xen/xenbus.h>
58 #include <xen/xencons.h>
62 * 'xencons=off' [XC_OFF]: Console is disabled.
63 * 'xencons=tty' [XC_TTY]: Console attached to '/dev/tty[0-9]+'.
64 * 'xencons=ttyS' [XC_SERIAL]: Console attached to '/dev/ttyS[0-9]+'.
65 * 'xencons=xvc' [XC_XVC]: Console attached to '/dev/xvc0'.
66 * 'xencons=hvc' [XC_HVC]: Console attached to '/dev/hvc0'.
69 * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
70 * warnings from standard distro startup scripts.
73 XC_OFF, XC_TTY, XC_SERIAL, XC_XVC, XC_HVC
75 static int xc_num = -1;
77 /* /dev/xvc0 device number allocated by lanana.org. */
78 #define XEN_XVC_MAJOR 204
79 #define XEN_XVC_MINOR 191
81 /* /dev/hvc0 device number */
82 #define XEN_HVC_MAJOR 229
83 #define XEN_HVC_MINOR 0
85 static int __init xencons_setup(char *str)
91 if (!strncmp(str, "ttyS", 4)) {
94 } else if (!strncmp(str, "tty", 3)) {
98 } else if (!strncmp(str, "xvc", 3)) {
101 } else if (!strncmp(str, "hvc", 3)) {
104 } else if (!strncmp(str, "off", 3)) {
109 n = simple_strtol(str, &q, 10);
115 __setup("xencons=", xencons_setup);
117 /* The kernel and user-land drivers share a common transmit buffer. */
118 static unsigned int wbuf_size = 4096;
119 #define WBUF_MASK(_i) ((_i)&(wbuf_size-1))
121 static unsigned int wc, wp; /* write_cons, write_prod */
123 static int __init xencons_bufsz_setup(char *str)
126 goal = simple_strtoul(str, NULL, 0);
128 goal = roundup_pow_of_two(goal);
129 if (wbuf_size < goal)
134 __setup("xencons_bufsz=", xencons_bufsz_setup);
136 /* This lock protects accesses to the common transmit buffer. */
137 static DEFINE_SPINLOCK(xencons_lock);
139 /* Common transmit-kick routine. */
140 static void __xencons_tx_flush(void);
142 static struct tty_driver *xencons_driver;
144 /******************** Kernel console driver ********************************/
146 static void kcons_write(struct console *c, const char *s, unsigned int count)
151 spin_lock_irqsave(&xencons_lock, flags);
154 for (; i < count; i++) {
155 if ((wp - wc) >= (wbuf_size - 1))
157 if ((wbuf[WBUF_MASK(wp++)] = s[i]) == '\n')
158 wbuf[WBUF_MASK(wp++)] = '\r';
161 __xencons_tx_flush();
164 spin_unlock_irqrestore(&xencons_lock, flags);
167 static void kcons_write_dom0(struct console *c, const char *s, unsigned int count)
172 rc = HYPERVISOR_console_io( CONSOLEIO_write, count, (char *)s);
180 static struct tty_driver *kcons_device(struct console *c, int *index)
183 return xencons_driver;
186 static struct console kcons_info = {
187 .device = kcons_device,
188 .flags = CON_PRINTBUFFER | CON_ENABLED,
192 static int __init xen_console_init(void)
194 if (!is_running_on_xen())
197 if (is_initial_xendomain()) {
198 kcons_info.write = kcons_write_dom0;
200 if (!xen_start_info->console.domU.evtchn)
202 kcons_info.write = kcons_write;
207 strcpy(kcons_info.name, "xvc");
213 strcpy(kcons_info.name, "hvc");
216 if (!is_initial_xendomain())
217 add_preferred_console(kcons_info.name, xc_num, NULL);
221 strcpy(kcons_info.name, "ttyS");
227 strcpy(kcons_info.name, "tty");
236 wbuf = kmalloc(wbuf_size, GFP_KERNEL);
238 register_console(&kcons_info);
243 console_initcall(xen_console_init);
245 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
246 /*** Useful function for console debugging -- goes straight to Xen. ***/
247 asmlinkage int xprintk(const char *fmt, ...)
251 static char printk_buf[1024];
253 /* Emit the output into the temporary buffer */
255 printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
258 /* Send the processed output directly to Xen. */
259 kcons_write_dom0(NULL, printk_buf, printk_len);
265 /*** Forcibly flush console data before dying. ***/
266 void xencons_force_flush(void)
270 /* Emergency console is synchronous, so there's nothing to flush. */
271 if (!is_running_on_xen() ||
272 is_initial_xendomain() ||
273 !xen_start_info->console.domU.evtchn)
276 /* Spin until console data is flushed through to the daemon. */
279 if ((sz = wp - wc) == 0)
281 sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
288 #ifdef CONFIG_XEN_PRIVILEGED_GUEST
289 #include <linux/screen_info.h>
291 void __init dom0_init_screen_info(const struct dom0_vga_console_info *info, size_t size)
293 /* This is drawn from a dump from vgacon:startup in
295 screen_info.orig_video_mode = 3;
296 screen_info.orig_video_isVGA = 1;
297 screen_info.orig_video_lines = 25;
298 screen_info.orig_video_cols = 80;
299 screen_info.orig_video_ega_bx = 3;
300 screen_info.orig_video_points = 16;
301 screen_info.orig_y = screen_info.orig_video_lines - 1;
303 switch (info->video_type) {
304 case XEN_VGATYPE_TEXT_MODE_3:
305 if (size < offsetof(struct dom0_vga_console_info, u.text_mode_3)
306 + sizeof(info->u.text_mode_3))
308 screen_info.orig_video_lines = info->u.text_mode_3.rows;
309 screen_info.orig_video_cols = info->u.text_mode_3.columns;
310 screen_info.orig_x = info->u.text_mode_3.cursor_x;
311 screen_info.orig_y = info->u.text_mode_3.cursor_y;
312 screen_info.orig_video_points =
313 info->u.text_mode_3.font_height;
316 case XEN_VGATYPE_VESA_LFB:
317 case XEN_VGATYPE_EFI_LFB:
318 if (size < offsetof(struct dom0_vga_console_info,
319 u.vesa_lfb.gbl_caps))
321 screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
322 screen_info.lfb_width = info->u.vesa_lfb.width;
323 screen_info.lfb_height = info->u.vesa_lfb.height;
324 screen_info.lfb_depth = info->u.vesa_lfb.bits_per_pixel;
325 screen_info.lfb_base = info->u.vesa_lfb.lfb_base;
326 screen_info.lfb_size = info->u.vesa_lfb.lfb_size;
327 screen_info.lfb_linelength = info->u.vesa_lfb.bytes_per_line;
328 screen_info.red_size = info->u.vesa_lfb.red_size;
329 screen_info.red_pos = info->u.vesa_lfb.red_pos;
330 screen_info.green_size = info->u.vesa_lfb.green_size;
331 screen_info.green_pos = info->u.vesa_lfb.green_pos;
332 screen_info.blue_size = info->u.vesa_lfb.blue_size;
333 screen_info.blue_pos = info->u.vesa_lfb.blue_pos;
334 screen_info.rsvd_size = info->u.vesa_lfb.rsvd_size;
335 screen_info.rsvd_pos = info->u.vesa_lfb.rsvd_pos;
336 if (info->video_type == XEN_VGATYPE_EFI_LFB) {
337 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
340 if (size >= offsetof(struct dom0_vga_console_info,
342 + sizeof(info->u.vesa_lfb.gbl_caps))
343 screen_info.capabilities = info->u.vesa_lfb.gbl_caps;
344 if (size >= offsetof(struct dom0_vga_console_info,
345 u.vesa_lfb.mode_attrs)
346 + sizeof(info->u.vesa_lfb.mode_attrs))
347 screen_info.vesa_attributes = info->u.vesa_lfb.mode_attrs;
354 /******************** User-space console driver (/dev/console) ************/
357 #define DUMMY_TTY(_tty) ((xc_mode == XC_TTY) && \
358 ((_tty)->index != (xc_num - 1)))
360 static struct ktermios *xencons_termios[MAX_NR_CONSOLES];
361 static struct tty_struct *xencons_tty;
362 static int xencons_priv_irq;
365 void xencons_rx(char *buf, unsigned len)
370 spin_lock_irqsave(&xencons_lock, flags);
371 if (xencons_tty == NULL)
374 for (i = 0; i < len; i++) {
375 #ifdef CONFIG_MAGIC_SYSRQ
376 static unsigned long sysrq_requested;
378 if (buf[i] == '\x0f') { /* ^O */
379 if (!sysrq_requested) {
380 sysrq_requested = jiffies;
381 continue; /* don't print sysrq key */
384 } else if (sysrq_requested) {
385 unsigned long sysrq_timeout = sysrq_requested + HZ*2;
388 if (time_before(jiffies, sysrq_timeout)) {
389 spin_unlock_irqrestore(&xencons_lock, flags);
390 handle_sysrq(buf[i]);
391 spin_lock_irqsave(&xencons_lock, flags);
396 tty_insert_flip_char(xencons_tty, buf[i], 0);
398 tty_flip_buffer_push(xencons_tty);
401 spin_unlock_irqrestore(&xencons_lock, flags);
404 static void __xencons_tx_flush(void)
406 int sent, sz, work_done = 0;
409 if (is_initial_xendomain())
410 kcons_write_dom0(NULL, &x_char, 1);
413 if (xencons_ring_send(&x_char, 1) == 1)
421 if (sz > (wbuf_size - WBUF_MASK(wc)))
422 sz = wbuf_size - WBUF_MASK(wc);
423 if (is_initial_xendomain()) {
424 kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
427 sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
435 if (work_done && (xencons_tty != NULL)) {
436 wake_up_interruptible(&xencons_tty->write_wait);
437 tty_wakeup(xencons_tty);
441 void xencons_tx(void)
445 spin_lock_irqsave(&xencons_lock, flags);
446 __xencons_tx_flush();
447 spin_unlock_irqrestore(&xencons_lock, flags);
450 /* Privileged receive callback and transmit kicker. */
451 static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id)
453 static char rbuf[16];
456 while ((l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0)
464 static int xencons_write_room(struct tty_struct *tty)
466 return wbuf_size - (wp - wc);
469 static int xencons_chars_in_buffer(struct tty_struct *tty)
474 static void xencons_send_xchar(struct tty_struct *tty, char ch)
481 spin_lock_irqsave(&xencons_lock, flags);
483 __xencons_tx_flush();
484 spin_unlock_irqrestore(&xencons_lock, flags);
487 static void xencons_throttle(struct tty_struct *tty)
493 xencons_send_xchar(tty, STOP_CHAR(tty));
496 static void xencons_unthrottle(struct tty_struct *tty)
505 xencons_send_xchar(tty, START_CHAR(tty));
509 static void xencons_flush_buffer(struct tty_struct *tty)
516 spin_lock_irqsave(&xencons_lock, flags);
518 spin_unlock_irqrestore(&xencons_lock, flags);
521 static inline int __xencons_put_char(int ch)
524 if ((wp - wc) == wbuf_size)
526 wbuf[WBUF_MASK(wp++)] = _ch;
530 static int xencons_write(
531 struct tty_struct *tty,
532 const unsigned char *buf,
541 spin_lock_irqsave(&xencons_lock, flags);
543 for (i = 0; i < count; i++)
544 if (!__xencons_put_char(buf[i]))
548 __xencons_tx_flush();
550 spin_unlock_irqrestore(&xencons_lock, flags);
555 static int xencons_put_char(struct tty_struct *tty, u_char ch)
563 spin_lock_irqsave(&xencons_lock, flags);
564 ret = __xencons_put_char(ch);
565 spin_unlock_irqrestore(&xencons_lock, flags);
569 static void xencons_flush_chars(struct tty_struct *tty)
576 spin_lock_irqsave(&xencons_lock, flags);
577 __xencons_tx_flush();
578 spin_unlock_irqrestore(&xencons_lock, flags);
581 static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
583 unsigned long orig_jiffies = jiffies;
588 while (tty_chars_in_buffer(tty)) {
589 set_current_state(TASK_INTERRUPTIBLE);
591 if (signal_pending(current))
593 if (timeout && time_after(jiffies, orig_jiffies + timeout))
597 set_current_state(TASK_RUNNING);
600 static int xencons_open(struct tty_struct *tty, struct file *filp)
607 spin_lock_irqsave(&xencons_lock, flags);
608 tty->driver_data = NULL;
609 if (xencons_tty == NULL)
611 __xencons_tx_flush();
612 spin_unlock_irqrestore(&xencons_lock, flags);
617 static void xencons_close(struct tty_struct *tty, struct file *filp)
625 * Must follow lock nesting; callers are prepared for this
626 * (__tty_hangup) or don't care as they drop the lock right after our
627 * return (tty_release) in order to then acquire both in proper order.
630 mutex_lock(&tty_mutex);
633 if (tty->count != 1) {
634 mutex_unlock(&tty_mutex);
638 /* Prevent other threads from re-opening this tty. */
639 set_bit(TTY_CLOSING, &tty->flags);
640 mutex_unlock(&tty_mutex);
643 tty_wait_until_sent(tty, 0);
644 tty_driver_flush_buffer(tty);
645 if (tty->ldisc->ops->flush_buffer)
646 tty->ldisc->ops->flush_buffer(tty);
648 spin_lock_irqsave(&xencons_lock, flags);
650 spin_unlock_irqrestore(&xencons_lock, flags);
653 static const struct tty_operations xencons_ops = {
654 .open = xencons_open,
655 .close = xencons_close,
656 .write = xencons_write,
657 .write_room = xencons_write_room,
658 .put_char = xencons_put_char,
659 .flush_chars = xencons_flush_chars,
660 .chars_in_buffer = xencons_chars_in_buffer,
661 .send_xchar = xencons_send_xchar,
662 .flush_buffer = xencons_flush_buffer,
663 .throttle = xencons_throttle,
664 .unthrottle = xencons_unthrottle,
665 .wait_until_sent = xencons_wait_until_sent,
668 static int __init xencons_init(void)
672 if (!is_running_on_xen())
675 if (xc_mode == XC_OFF)
678 if (!is_initial_xendomain()) {
679 rc = xencons_ring_init();
684 xencons_driver = alloc_tty_driver((xc_mode == XC_TTY) ?
685 MAX_NR_CONSOLES : 1);
686 if (xencons_driver == NULL)
689 DRV(xencons_driver)->name = "xencons";
690 DRV(xencons_driver)->major = TTY_MAJOR;
691 DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL;
692 DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL;
693 DRV(xencons_driver)->init_termios = tty_std_termios;
694 DRV(xencons_driver)->flags =
695 TTY_DRIVER_REAL_RAW |
696 TTY_DRIVER_RESET_TERMIOS;
697 DRV(xencons_driver)->termios = xencons_termios;
701 DRV(xencons_driver)->name = "xvc";
702 DRV(xencons_driver)->major = XEN_XVC_MAJOR;
703 DRV(xencons_driver)->minor_start = XEN_XVC_MINOR;
704 DRV(xencons_driver)->name_base = xc_num;
707 DRV(xencons_driver)->name = "hvc";
708 DRV(xencons_driver)->major = XEN_HVC_MAJOR;
709 DRV(xencons_driver)->minor_start = XEN_HVC_MINOR;
710 DRV(xencons_driver)->name_base = xc_num;
713 DRV(xencons_driver)->name = "ttyS";
714 DRV(xencons_driver)->minor_start = 64 + xc_num;
715 DRV(xencons_driver)->name_base = xc_num;
718 DRV(xencons_driver)->name = "tty";
719 DRV(xencons_driver)->minor_start = 1;
720 DRV(xencons_driver)->name_base = 1;
724 tty_set_operations(xencons_driver, &xencons_ops);
726 if ((rc = tty_register_driver(DRV(xencons_driver))) != 0) {
727 pr_warning("WARNING: Failed to register Xen virtual "
728 "console driver as '%s%d'\n",
729 DRV(xencons_driver)->name,
730 DRV(xencons_driver)->name_base);
731 put_tty_driver(xencons_driver);
732 xencons_driver = NULL;
736 if (is_initial_xendomain()) {
737 xencons_priv_irq = bind_virq_to_irqhandler(
740 xencons_priv_interrupt,
744 BUG_ON(xencons_priv_irq < 0);
747 pr_info("Xen virtual console successfully installed as %s%d\n",
748 DRV(xencons_driver)->name, xc_num);
753 module_init(xencons_init);
755 MODULE_LICENSE("Dual BSD/GPL");