aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@xensource.com>2007-07-17 21:37:06 -0400
committerJeremy Fitzhardinge <jeremy@goop.org>2007-07-18 11:47:44 -0400
commitb536b4b9623084d86f2b1f19cb44a2d6d74f00bf (patch)
tree86c1981309dbd8b9bf120d4ddba50abd105af89a
parent8b84ad942b534f8faeb34b68f0f7277ea375fed0 (diff)
xen: use the hvc console infrastructure for Xen console
Implement a Xen back-end for hvc console. * * * Add early printk support via hvc console, enable using "earlyprintk=xen" on the kernel command line. From: Gerd Hoffmann <kraxel@suse.de> Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Chris Wright <chrisw@sous-sol.org> Acked-by: Ingo Molnar <mingo@elte.hu> Acked-by: Olof Johansson <olof@lixom.net>
-rw-r--r--arch/i386/xen/events.c3
-rw-r--r--arch/x86_64/kernel/early_printk.c5
-rw-r--r--drivers/char/Kconfig8
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/hvc_xen.c159
-rw-r--r--include/xen/events.h1
-rw-r--r--include/xen/hvc-console.h6
7 files changed, 182 insertions, 1 deletions
diff --git a/arch/i386/xen/events.c b/arch/i386/xen/events.c
index 4103b8bf22fd..8904acc20f8c 100644
--- a/arch/i386/xen/events.c
+++ b/arch/i386/xen/events.c
@@ -244,7 +244,7 @@ static int find_unbound_irq(void)
244 return irq; 244 return irq;
245} 245}
246 246
247static int bind_evtchn_to_irq(unsigned int evtchn) 247int bind_evtchn_to_irq(unsigned int evtchn)
248{ 248{
249 int irq; 249 int irq;
250 250
@@ -269,6 +269,7 @@ static int bind_evtchn_to_irq(unsigned int evtchn)
269 269
270 return irq; 270 return irq;
271} 271}
272EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
272 273
273static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) 274static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
274{ 275{
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 296d2b0c5d88..fd9aff3f3890 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -6,6 +6,7 @@
6#include <asm/io.h> 6#include <asm/io.h>
7#include <asm/processor.h> 7#include <asm/processor.h>
8#include <asm/fcntl.h> 8#include <asm/fcntl.h>
9#include <xen/hvc-console.h>
9 10
10/* Simple VGA output */ 11/* Simple VGA output */
11 12
@@ -242,6 +243,10 @@ static int __init setup_early_printk(char *buf)
242 simnow_init(buf + 6); 243 simnow_init(buf + 6);
243 early_console = &simnow_console; 244 early_console = &simnow_console;
244 keep_early = 1; 245 keep_early = 1;
246#ifdef CONFIG_HVC_XEN
247 } else if (!strncmp(buf, "xen", 3)) {
248 early_console = &xenboot_console;
249#endif
245 } 250 }
246 251
247 if (keep_early) 252 if (keep_early)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 97bd71bc3aea..9e8f21410d2d 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -604,6 +604,14 @@ config HVC_BEAT
604 help 604 help
605 Toshiba's Cell Reference Set Beat Console device driver 605 Toshiba's Cell Reference Set Beat Console device driver
606 606
607config HVC_XEN
608 bool "Xen Hypervisor Console support"
609 depends on XEN
610 select HVC_DRIVER
611 default y
612 help
613 Xen virtual console device driver
614
607config HVCS 615config HVCS
608 tristate "IBM Hypervisor Virtual Console Server support" 616 tristate "IBM Hypervisor Virtual Console Server support"
609 depends on PPC_PSERIES 617 depends on PPC_PSERIES
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index f2996a95eb07..8852b8d643cf 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o
48obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o 48obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
49obj-$(CONFIG_HVC_BEAT) += hvc_beat.o 49obj-$(CONFIG_HVC_BEAT) += hvc_beat.o
50obj-$(CONFIG_HVC_DRIVER) += hvc_console.o 50obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
51obj-$(CONFIG_HVC_XEN) += hvc_xen.o
51obj-$(CONFIG_RAW_DRIVER) += raw.o 52obj-$(CONFIG_RAW_DRIVER) += raw.o
52obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o 53obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
53obj-$(CONFIG_MSPEC) += mspec.o 54obj-$(CONFIG_MSPEC) += mspec.o
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c
new file mode 100644
index 000000000000..dd68f8541c2d
--- /dev/null
+++ b/drivers/char/hvc_xen.c
@@ -0,0 +1,159 @@
1/*
2 * xen console driver interface to hvc_console.c
3 *
4 * (c) 2007 Gerd Hoffmann <kraxel@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/console.h>
22#include <linux/delay.h>
23#include <linux/err.h>
24#include <linux/init.h>
25#include <linux/types.h>
26
27#include <asm/xen/hypervisor.h>
28#include <xen/page.h>
29#include <xen/events.h>
30#include <xen/interface/io/console.h>
31#include <xen/hvc-console.h>
32
33#include "hvc_console.h"
34
35#define HVC_COOKIE 0x58656e /* "Xen" in hex */
36
37static struct hvc_struct *hvc;
38static int xencons_irq;
39
40/* ------------------------------------------------------------------ */
41
42static inline struct xencons_interface *xencons_interface(void)
43{
44 return mfn_to_virt(xen_start_info->console.domU.mfn);
45}
46
47static inline void notify_daemon(void)
48{
49 /* Use evtchn: this is called early, before irq is set up. */
50 notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
51}
52
53static int write_console(uint32_t vtermno, const char *data, int len)
54{
55 struct xencons_interface *intf = xencons_interface();
56 XENCONS_RING_IDX cons, prod;
57 int sent = 0;
58
59 cons = intf->out_cons;
60 prod = intf->out_prod;
61 mb(); /* update queue values before going on */
62 BUG_ON((prod - cons) > sizeof(intf->out));
63
64 while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
65 intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
66
67 wmb(); /* write ring before updating pointer */
68 intf->out_prod = prod;
69
70 notify_daemon();
71 return sent;
72}
73
74static int read_console(uint32_t vtermno, char *buf, int len)
75{
76 struct xencons_interface *intf = xencons_interface();
77 XENCONS_RING_IDX cons, prod;
78 int recv = 0;
79
80 cons = intf->in_cons;
81 prod = intf->in_prod;
82 mb(); /* get pointers before reading ring */
83 BUG_ON((prod - cons) > sizeof(intf->in));
84
85 while (cons != prod && recv < len)
86 buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
87
88 mb(); /* read ring before consuming */
89 intf->in_cons = cons;
90
91 notify_daemon();
92 return recv;
93}
94
95static struct hv_ops hvc_ops = {
96 .get_chars = read_console,
97 .put_chars = write_console,
98};
99
100static int __init xen_init(void)
101{
102 struct hvc_struct *hp;
103
104 if (!is_running_on_xen())
105 return 0;
106
107 xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
108 if (xencons_irq < 0)
109 xencons_irq = 0 /* NO_IRQ */;
110 hp = hvc_alloc(HVC_COOKIE, xencons_irq, &hvc_ops, 256);
111 if (IS_ERR(hp))
112 return PTR_ERR(hp);
113
114 hvc = hp;
115 return 0;
116}
117
118static void __exit xen_fini(void)
119{
120 if (hvc)
121 hvc_remove(hvc);
122}
123
124static int xen_cons_init(void)
125{
126 if (!is_running_on_xen())
127 return 0;
128
129 hvc_instantiate(HVC_COOKIE, 0, &hvc_ops);
130 return 0;
131}
132
133module_init(xen_init);
134module_exit(xen_fini);
135console_initcall(xen_cons_init);
136
137static void xenboot_write_console(struct console *console, const char *string,
138 unsigned len)
139{
140 unsigned int linelen, off = 0;
141 const char *pos;
142
143 while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
144 linelen = pos-string+off;
145 if (off + linelen > len)
146 break;
147 write_console(0, string+off, linelen);
148 write_console(0, "\r\n", 2);
149 off += linelen + 1;
150 }
151 if (off < len)
152 write_console(0, string+off, len-off);
153}
154
155struct console xenboot_console = {
156 .name = "xenboot",
157 .write = xenboot_write_console,
158 .flags = CON_PRINTBUFFER | CON_BOOT,
159};
diff --git a/include/xen/events.h b/include/xen/events.h
index 7abe4ddfac54..2bde54d29be5 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -13,6 +13,7 @@ enum ipi_vector {
13 XEN_NR_IPIS, 13 XEN_NR_IPIS,
14}; 14};
15 15
16int bind_evtchn_to_irq(unsigned int evtchn);
16int bind_evtchn_to_irqhandler(unsigned int evtchn, 17int bind_evtchn_to_irqhandler(unsigned int evtchn,
17 irq_handler_t handler, 18 irq_handler_t handler,
18 unsigned long irqflags, const char *devname, 19 unsigned long irqflags, const char *devname,
diff --git a/include/xen/hvc-console.h b/include/xen/hvc-console.h
new file mode 100644
index 000000000000..21c0ecfd786d
--- /dev/null
+++ b/include/xen/hvc-console.h
@@ -0,0 +1,6 @@
1#ifndef XEN_HVC_CONSOLE_H
2#define XEN_HVC_CONSOLE_H
3
4extern struct console xenboot_console;
5
6#endif /* XEN_HVC_CONSOLE_H */