diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2012-01-27 13:31:36 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-03-13 19:23:32 -0400 |
commit | eb5ef07151ba3c3cb4bcef0c8f146ff1115eaa55 (patch) | |
tree | 57544730b6e17030af01092cf68c972acc1c55ad | |
parent | bd0d5aa417d40d6b996fb7b5c926bcecd56c8984 (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>
-rw-r--r-- | drivers/tty/hvc/hvc_xen.c | 84 | ||||
-rw-r--r-- | include/xen/interface/hvm/params.h | 6 |
2 files changed, 73 insertions, 17 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 | ||
44 | static unsigned long console_pfn = ~0ul; | 47 | static unsigned long console_pfn = ~0ul; |
48 | static unsigned int console_evtchn = ~0ul; | ||
49 | static struct xencons_interface *xencons_if = NULL; | ||
45 | 50 | ||
46 | static inline struct xencons_interface *xencons_interface(void) | 51 | static 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) | |||
54 | static inline void notify_daemon(void) | 61 | static 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 | ||
60 | static int __write_console(const char *data, int len) | 70 | static 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 | ||
170 | static 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 | |||
160 | static int __init xen_hvc_init(void) | 197 | static 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 | ||
194 | void xen_console_resume(void) | 237 | void 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 | ||
200 | static void __exit xen_hvc_fini(void) | 243 | static void __exit xen_hvc_fini(void) |
@@ -205,16 +248,22 @@ static void __exit xen_hvc_fini(void) | |||
205 | 248 | ||
206 | static int xen_cons_init(void) | 249 | static 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()) |
diff --git a/include/xen/interface/hvm/params.h b/include/xen/interface/hvm/params.h index 1888d8c157e6..1b4f923d7086 100644 --- a/include/xen/interface/hvm/params.h +++ b/include/xen/interface/hvm/params.h | |||
@@ -90,6 +90,10 @@ | |||
90 | /* Boolean: Enable aligning all periodic vpts to reduce interrupts */ | 90 | /* Boolean: Enable aligning all periodic vpts to reduce interrupts */ |
91 | #define HVM_PARAM_VPT_ALIGN 16 | 91 | #define HVM_PARAM_VPT_ALIGN 16 |
92 | 92 | ||
93 | #define HVM_NR_PARAMS 17 | 93 | /* Console debug shared memory ring and event channel */ |
94 | #define HVM_PARAM_CONSOLE_PFN 17 | ||
95 | #define HVM_PARAM_CONSOLE_EVTCHN 18 | ||
96 | |||
97 | #define HVM_NR_PARAMS 19 | ||
94 | 98 | ||
95 | #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */ | 99 | #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */ |