aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-01-27 13:31:36 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-03-13 19:23:32 -0400
commiteb5ef07151ba3c3cb4bcef0c8f146ff1115eaa55 (patch)
tree57544730b6e17030af01092cf68c972acc1c55ad /drivers/tty
parentbd0d5aa417d40d6b996fb7b5c926bcecd56c8984 (diff)
hvc_xen: support PV on HVM consoles
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/hvc/hvc_xen.c84
1 files changed, 68 insertions, 16 deletions
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 52fdf60bdbe2..d5000aa02864 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -24,9 +24,12 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/types.h> 25#include <linux/types.h>
26 26
27#include <asm/io.h>
27#include <asm/xen/hypervisor.h> 28#include <asm/xen/hypervisor.h>
28 29
29#include <xen/xen.h> 30#include <xen/xen.h>
31#include <xen/interface/xen.h>
32#include <xen/hvm.h>
30#include <xen/page.h> 33#include <xen/page.h>
31#include <xen/events.h> 34#include <xen/events.h>
32#include <xen/interface/io/console.h> 35#include <xen/interface/io/console.h>
@@ -42,9 +45,13 @@ static int xencons_irq;
42/* ------------------------------------------------------------------ */ 45/* ------------------------------------------------------------------ */
43 46
44static unsigned long console_pfn = ~0ul; 47static unsigned long console_pfn = ~0ul;
48static unsigned int console_evtchn = ~0ul;
49static struct xencons_interface *xencons_if = NULL;
45 50
46static inline struct xencons_interface *xencons_interface(void) 51static inline struct xencons_interface *xencons_interface(void)
47{ 52{
53 if (xencons_if != NULL)
54 return xencons_if;
48 if (console_pfn == ~0ul) 55 if (console_pfn == ~0ul)
49 return mfn_to_virt(xen_start_info->console.domU.mfn); 56 return mfn_to_virt(xen_start_info->console.domU.mfn);
50 else 57 else
@@ -54,7 +61,10 @@ static inline struct xencons_interface *xencons_interface(void)
54static inline void notify_daemon(void) 61static inline void notify_daemon(void)
55{ 62{
56 /* Use evtchn: this is called early, before irq is set up. */ 63 /* Use evtchn: this is called early, before irq is set up. */
57 notify_remote_via_evtchn(xen_start_info->console.domU.evtchn); 64 if (console_evtchn == ~0ul)
65 notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
66 else
67 notify_remote_via_evtchn(console_evtchn);
58} 68}
59 69
60static int __write_console(const char *data, int len) 70static int __write_console(const char *data, int len)
@@ -157,28 +167,63 @@ static struct hv_ops dom0_hvc_ops = {
157 .notifier_hangup = notifier_hangup_irq, 167 .notifier_hangup = notifier_hangup_irq,
158}; 168};
159 169
170static int xen_hvm_console_init(void)
171{
172 int r;
173 uint64_t v = 0;
174 unsigned long mfn;
175
176 if (!xen_hvm_domain())
177 return -ENODEV;
178
179 if (xencons_if != NULL)
180 return -EBUSY;
181
182 r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
183 if (r < 0)
184 return -ENODEV;
185 console_evtchn = v;
186 hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
187 if (r < 0)
188 return -ENODEV;
189 mfn = v;
190 xencons_if = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE);
191 if (xencons_if == NULL)
192 return -ENODEV;
193
194 return 0;
195}
196
160static int __init xen_hvc_init(void) 197static int __init xen_hvc_init(void)
161{ 198{
162 struct hvc_struct *hp; 199 struct hvc_struct *hp;
163 struct hv_ops *ops; 200 struct hv_ops *ops;
201 int r;
164 202
165 if (!xen_pv_domain()) 203 if (!xen_domain())
166 return -ENODEV; 204 return -ENODEV;
167 205
168 if (xen_initial_domain()) { 206 if (xen_initial_domain()) {
169 ops = &dom0_hvc_ops; 207 ops = &dom0_hvc_ops;
170 xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0); 208 xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
171 } else { 209 } else {
172 if (!xen_start_info->console.domU.evtchn)
173 return -ENODEV;
174
175 ops = &domU_hvc_ops; 210 ops = &domU_hvc_ops;
176 xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn); 211 if (xen_pv_domain()) {
212 if (!xen_start_info->console.domU.evtchn)
213 return -ENODEV;
214 console_pfn = mfn_to_pfn(xen_start_info->console.domU.mfn);
215 console_evtchn = xen_start_info->console.domU.evtchn;
216 } else {
217 r = xen_hvm_console_init();
218 if (r < 0)
219 return r;
220 }
221 xencons_irq = bind_evtchn_to_irq(console_evtchn);
222 if (xencons_irq < 0)
223 xencons_irq = 0; /* NO_IRQ */
224 else
225 irq_set_noprobe(xencons_irq);
177 } 226 }
178 if (xencons_irq < 0)
179 xencons_irq = 0; /* NO_IRQ */
180 else
181 irq_set_noprobe(xencons_irq);
182 227
183 hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256); 228 hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
184 if (IS_ERR(hp)) 229 if (IS_ERR(hp))
@@ -186,15 +231,13 @@ static int __init xen_hvc_init(void)
186 231
187 hvc = hp; 232 hvc = hp;
188 233
189 console_pfn = mfn_to_pfn(xen_start_info->console.domU.mfn);
190
191 return 0; 234 return 0;
192} 235}
193 236
194void xen_console_resume(void) 237void xen_console_resume(void)
195{ 238{
196 if (xencons_irq) 239 if (xencons_irq)
197 rebind_evtchn_irq(xen_start_info->console.domU.evtchn, xencons_irq); 240 rebind_evtchn_irq(console_evtchn, xencons_irq);
198} 241}
199 242
200static void __exit xen_hvc_fini(void) 243static void __exit xen_hvc_fini(void)
@@ -205,16 +248,22 @@ static void __exit xen_hvc_fini(void)
205 248
206static int xen_cons_init(void) 249static int xen_cons_init(void)
207{ 250{
208 struct hv_ops *ops; 251 const struct hv_ops *ops;
209 252
210 if (!xen_pv_domain()) 253 if (!xen_domain())
211 return 0; 254 return 0;
212 255
213 if (xen_initial_domain()) 256 if (xen_initial_domain())
214 ops = &dom0_hvc_ops; 257 ops = &dom0_hvc_ops;
215 else 258 else {
216 ops = &domU_hvc_ops; 259 ops = &domU_hvc_ops;
217 260
261 if (xen_pv_domain())
262 console_evtchn = xen_start_info->console.domU.evtchn;
263 else
264 xen_hvm_console_init();
265 }
266
218 hvc_instantiate(HVC_COOKIE, 0, ops); 267 hvc_instantiate(HVC_COOKIE, 0, ops);
219 return 0; 268 return 0;
220} 269}
@@ -230,6 +279,9 @@ static void xenboot_write_console(struct console *console, const char *string,
230 unsigned int linelen, off = 0; 279 unsigned int linelen, off = 0;
231 const char *pos; 280 const char *pos;
232 281
282 if (!xen_pv_domain())
283 return;
284
233 dom0_write_console(0, string, len); 285 dom0_write_console(0, string, len);
234 286
235 if (xen_initial_domain()) 287 if (xen_initial_domain())