Commit b536b4b9623084d86f2b1f19cb44a2d6d74f00bf
Committed by
Jeremy Fitzhardinge
1 parent
8b84ad942b
Exists in
master
and in
7 other branches
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>
Showing 7 changed files with 182 additions and 1 deletions Side-by-side Diff
arch/i386/xen/events.c
... | ... | @@ -244,7 +244,7 @@ |
244 | 244 | return irq; |
245 | 245 | } |
246 | 246 | |
247 | -static int bind_evtchn_to_irq(unsigned int evtchn) | |
247 | +int bind_evtchn_to_irq(unsigned int evtchn) | |
248 | 248 | { |
249 | 249 | int irq; |
250 | 250 | |
... | ... | @@ -269,6 +269,7 @@ |
269 | 269 | |
270 | 270 | return irq; |
271 | 271 | } |
272 | +EXPORT_SYMBOL_GPL(bind_evtchn_to_irq); | |
272 | 273 | |
273 | 274 | static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) |
274 | 275 | { |
arch/x86_64/kernel/early_printk.c
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | #include <asm/io.h> |
7 | 7 | #include <asm/processor.h> |
8 | 8 | #include <asm/fcntl.h> |
9 | +#include <xen/hvc-console.h> | |
9 | 10 | |
10 | 11 | /* Simple VGA output */ |
11 | 12 | |
... | ... | @@ -242,6 +243,10 @@ |
242 | 243 | simnow_init(buf + 6); |
243 | 244 | early_console = &simnow_console; |
244 | 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 | 252 | if (keep_early) |
drivers/char/Kconfig
... | ... | @@ -604,6 +604,14 @@ |
604 | 604 | help |
605 | 605 | Toshiba's Cell Reference Set Beat Console device driver |
606 | 606 | |
607 | +config 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 | + | |
607 | 615 | config HVCS |
608 | 616 | tristate "IBM Hypervisor Virtual Console Server support" |
609 | 617 | depends on PPC_PSERIES |
drivers/char/Makefile
... | ... | @@ -48,6 +48,7 @@ |
48 | 48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
49 | 49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o |
50 | 50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o |
51 | +obj-$(CONFIG_HVC_XEN) += hvc_xen.o | |
51 | 52 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
52 | 53 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o |
53 | 54 | obj-$(CONFIG_MSPEC) += mspec.o |
drivers/char/hvc_xen.c
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 | + | |
37 | +static struct hvc_struct *hvc; | |
38 | +static int xencons_irq; | |
39 | + | |
40 | +/* ------------------------------------------------------------------ */ | |
41 | + | |
42 | +static inline struct xencons_interface *xencons_interface(void) | |
43 | +{ | |
44 | + return mfn_to_virt(xen_start_info->console.domU.mfn); | |
45 | +} | |
46 | + | |
47 | +static 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 | + | |
53 | +static 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 | + | |
74 | +static 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 | + | |
95 | +static struct hv_ops hvc_ops = { | |
96 | + .get_chars = read_console, | |
97 | + .put_chars = write_console, | |
98 | +}; | |
99 | + | |
100 | +static 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 | + | |
118 | +static void __exit xen_fini(void) | |
119 | +{ | |
120 | + if (hvc) | |
121 | + hvc_remove(hvc); | |
122 | +} | |
123 | + | |
124 | +static 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 | + | |
133 | +module_init(xen_init); | |
134 | +module_exit(xen_fini); | |
135 | +console_initcall(xen_cons_init); | |
136 | + | |
137 | +static 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 | + | |
155 | +struct console xenboot_console = { | |
156 | + .name = "xenboot", | |
157 | + .write = xenboot_write_console, | |
158 | + .flags = CON_PRINTBUFFER | CON_BOOT, | |
159 | +}; |
include/xen/events.h
include/xen/hvc-console.h