aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hvc_xen.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-09-02 11:17:06 -0400
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2010-10-22 16:26:01 -0400
commit4fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06 (patch)
tree43fff2734caa2efa8d7adc8c3439d4c282f29081 /drivers/char/hvc_xen.c
parent4ec5387cc36c6472a2ff2c82e9865abe8cab96c2 (diff)
xen: make hvc_xen console work for dom0.
Use the console hypercalls for dom0 console. [ Impact: Add Xen dom0 console ] Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/char/hvc_xen.c')
-rw-r--r--drivers/char/hvc_xen.c98
1 files changed, 65 insertions, 33 deletions
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c
index 60446f82a3fc..1f7e13a43a88 100644
--- a/drivers/char/hvc_xen.c
+++ b/drivers/char/hvc_xen.c
@@ -78,7 +78,7 @@ static int __write_console(const char *data, int len)
78 return sent; 78 return sent;
79} 79}
80 80
81static int write_console(uint32_t vtermno, const char *data, int len) 81static int domU_write_console(uint32_t vtermno, const char *data, int len)
82{ 82{
83 int ret = len; 83 int ret = len;
84 84
@@ -101,7 +101,7 @@ static int write_console(uint32_t vtermno, const char *data, int len)
101 return ret; 101 return ret;
102} 102}
103 103
104static int read_console(uint32_t vtermno, char *buf, int len) 104static int domU_read_console(uint32_t vtermno, char *buf, int len)
105{ 105{
106 struct xencons_interface *intf = xencons_interface(); 106 struct xencons_interface *intf = xencons_interface();
107 XENCONS_RING_IDX cons, prod; 107 XENCONS_RING_IDX cons, prod;
@@ -122,28 +122,62 @@ static int read_console(uint32_t vtermno, char *buf, int len)
122 return recv; 122 return recv;
123} 123}
124 124
125static const struct hv_ops hvc_ops = { 125static struct hv_ops domU_hvc_ops = {
126 .get_chars = read_console, 126 .get_chars = domU_read_console,
127 .put_chars = write_console, 127 .put_chars = domU_write_console,
128 .notifier_add = notifier_add_irq, 128 .notifier_add = notifier_add_irq,
129 .notifier_del = notifier_del_irq, 129 .notifier_del = notifier_del_irq,
130 .notifier_hangup = notifier_hangup_irq, 130 .notifier_hangup = notifier_hangup_irq,
131}; 131};
132 132
133static int __init xen_init(void) 133static int dom0_read_console(uint32_t vtermno, char *buf, int len)
134{
135 return HYPERVISOR_console_io(CONSOLEIO_read, len, buf);
136}
137
138/*
139 * Either for a dom0 to write to the system console, or a domU with a
140 * debug version of Xen
141 */
142static int dom0_write_console(uint32_t vtermno, const char *str, int len)
143{
144 int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
145 if (rc < 0)
146 return 0;
147
148 return len;
149}
150
151static struct hv_ops dom0_hvc_ops = {
152 .get_chars = dom0_read_console,
153 .put_chars = dom0_write_console,
154 .notifier_add = notifier_add_irq,
155 .notifier_del = notifier_del_irq,
156 .notifier_hangup = notifier_hangup_irq,
157};
158
159static int __init xen_hvc_init(void)
134{ 160{
135 struct hvc_struct *hp; 161 struct hvc_struct *hp;
162 struct hv_ops *ops;
136 163
137 if (!xen_pv_domain() || 164 if (!xen_pv_domain())
138 xen_initial_domain() ||
139 !xen_start_info->console.domU.evtchn)
140 return -ENODEV; 165 return -ENODEV;
141 166
142 xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn); 167 if (xen_initial_domain()) {
168 ops = &dom0_hvc_ops;
169 xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
170 } else {
171 if (!xen_start_info->console.domU.evtchn)
172 return -ENODEV;
173
174 ops = &domU_hvc_ops;
175 xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
176 }
143 if (xencons_irq < 0) 177 if (xencons_irq < 0)
144 xencons_irq = 0; /* NO_IRQ */ 178 xencons_irq = 0; /* NO_IRQ */
145 179
146 hp = hvc_alloc(HVC_COOKIE, xencons_irq, &hvc_ops, 256); 180 hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
147 if (IS_ERR(hp)) 181 if (IS_ERR(hp))
148 return PTR_ERR(hp); 182 return PTR_ERR(hp);
149 183
@@ -160,7 +194,7 @@ void xen_console_resume(void)
160 rebind_evtchn_irq(xen_start_info->console.domU.evtchn, xencons_irq); 194 rebind_evtchn_irq(xen_start_info->console.domU.evtchn, xencons_irq);
161} 195}
162 196
163static void __exit xen_fini(void) 197static void __exit xen_hvc_fini(void)
164{ 198{
165 if (hvc) 199 if (hvc)
166 hvc_remove(hvc); 200 hvc_remove(hvc);
@@ -168,29 +202,24 @@ static void __exit xen_fini(void)
168 202
169static int xen_cons_init(void) 203static int xen_cons_init(void)
170{ 204{
205 struct hv_ops *ops;
206
171 if (!xen_pv_domain()) 207 if (!xen_pv_domain())
172 return 0; 208 return 0;
173 209
174 hvc_instantiate(HVC_COOKIE, 0, &hvc_ops); 210 if (xen_initial_domain())
211 ops = &dom0_hvc_ops;
212 else
213 ops = &domU_hvc_ops;
214
215 hvc_instantiate(HVC_COOKIE, 0, ops);
175 return 0; 216 return 0;
176} 217}
177 218
178module_init(xen_init); 219module_init(xen_hvc_init);
179module_exit(xen_fini); 220module_exit(xen_hvc_fini);
180console_initcall(xen_cons_init); 221console_initcall(xen_cons_init);
181 222
182static void raw_console_write(const char *str, int len)
183{
184 while(len > 0) {
185 int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
186 if (rc <= 0)
187 break;
188
189 str += rc;
190 len -= rc;
191 }
192}
193
194#ifdef CONFIG_EARLY_PRINTK 223#ifdef CONFIG_EARLY_PRINTK
195static void xenboot_write_console(struct console *console, const char *string, 224static void xenboot_write_console(struct console *console, const char *string,
196 unsigned len) 225 unsigned len)
@@ -198,19 +227,22 @@ static void xenboot_write_console(struct console *console, const char *string,
198 unsigned int linelen, off = 0; 227 unsigned int linelen, off = 0;
199 const char *pos; 228 const char *pos;
200 229
201 raw_console_write(string, len); 230 dom0_write_console(0, string, len);
231
232 if (xen_initial_domain())
233 return;
202 234
203 write_console(0, "(early) ", 8); 235 domU_write_console(0, "(early) ", 8);
204 while (off < len && NULL != (pos = strchr(string+off, '\n'))) { 236 while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
205 linelen = pos-string+off; 237 linelen = pos-string+off;
206 if (off + linelen > len) 238 if (off + linelen > len)
207 break; 239 break;
208 write_console(0, string+off, linelen); 240 domU_write_console(0, string+off, linelen);
209 write_console(0, "\r\n", 2); 241 domU_write_console(0, "\r\n", 2);
210 off += linelen + 1; 242 off += linelen + 1;
211 } 243 }
212 if (off < len) 244 if (off < len)
213 write_console(0, string+off, len-off); 245 domU_write_console(0, string+off, len-off);
214} 246}
215 247
216struct console xenboot_console = { 248struct console xenboot_console = {
@@ -222,7 +254,7 @@ struct console xenboot_console = {
222 254
223void xen_raw_console_write(const char *str) 255void xen_raw_console_write(const char *str)
224{ 256{
225 raw_console_write(str, strlen(str)); 257 dom0_write_console(0, str, strlen(str));
226} 258}
227 259
228void xen_raw_printk(const char *fmt, ...) 260void xen_raw_printk(const char *fmt, ...)