Skip to content

Commit eb5ef07

Browse files
Stefano Stabellinikonradwilk
authored andcommitted
hvc_xen: support PV on HVM consoles
Signed-off-by: Stefano Stabellini <[email protected]> Signed-off-by: Konrad Rzeszutek Wilk <[email protected]>
1 parent bd0d5aa commit eb5ef07

File tree

2 files changed

+73
-17
lines changed

2 files changed

+73
-17
lines changed

drivers/tty/hvc/hvc_xen.c

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424
#include <linux/init.h>
2525
#include <linux/types.h>
2626

27+
#include <asm/io.h>
2728
#include <asm/xen/hypervisor.h>
2829

2930
#include <xen/xen.h>
31+
#include <xen/interface/xen.h>
32+
#include <xen/hvm.h>
3033
#include <xen/page.h>
3134
#include <xen/events.h>
3235
#include <xen/interface/io/console.h>
@@ -42,9 +45,13 @@ static int xencons_irq;
4245
/* ------------------------------------------------------------------ */
4346

4447
static unsigned long console_pfn = ~0ul;
48+
static unsigned int console_evtchn = ~0ul;
49+
static struct xencons_interface *xencons_if = NULL;
4550

4651
static inline struct xencons_interface *xencons_interface(void)
4752
{
53+
if (xencons_if != NULL)
54+
return xencons_if;
4855
if (console_pfn == ~0ul)
4956
return mfn_to_virt(xen_start_info->console.domU.mfn);
5057
else
@@ -54,7 +61,10 @@ static inline struct xencons_interface *xencons_interface(void)
5461
static inline void notify_daemon(void)
5562
{
5663
/* 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);
5868
}
5969

6070
static int __write_console(const char *data, int len)
@@ -157,44 +167,77 @@ static struct hv_ops dom0_hvc_ops = {
157167
.notifier_hangup = notifier_hangup_irq,
158168
};
159169

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+
160197
static int __init xen_hvc_init(void)
161198
{
162199
struct hvc_struct *hp;
163200
struct hv_ops *ops;
201+
int r;
164202

165-
if (!xen_pv_domain())
203+
if (!xen_domain())
166204
return -ENODEV;
167205

168206
if (xen_initial_domain()) {
169207
ops = &dom0_hvc_ops;
170208
xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
171209
} else {
172-
if (!xen_start_info->console.domU.evtchn)
173-
return -ENODEV;
174-
175210
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);
177226
}
178-
if (xencons_irq < 0)
179-
xencons_irq = 0; /* NO_IRQ */
180-
else
181-
irq_set_noprobe(xencons_irq);
182227

183228
hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
184229
if (IS_ERR(hp))
185230
return PTR_ERR(hp);
186231

187232
hvc = hp;
188233

189-
console_pfn = mfn_to_pfn(xen_start_info->console.domU.mfn);
190-
191234
return 0;
192235
}
193236

194237
void xen_console_resume(void)
195238
{
196239
if (xencons_irq)
197-
rebind_evtchn_irq(xen_start_info->console.domU.evtchn, xencons_irq);
240+
rebind_evtchn_irq(console_evtchn, xencons_irq);
198241
}
199242

200243
static void __exit xen_hvc_fini(void)
@@ -205,16 +248,22 @@ static void __exit xen_hvc_fini(void)
205248

206249
static int xen_cons_init(void)
207250
{
208-
struct hv_ops *ops;
251+
const struct hv_ops *ops;
209252

210-
if (!xen_pv_domain())
253+
if (!xen_domain())
211254
return 0;
212255

213256
if (xen_initial_domain())
214257
ops = &dom0_hvc_ops;
215-
else
258+
else {
216259
ops = &domU_hvc_ops;
217260

261+
if (xen_pv_domain())
262+
console_evtchn = xen_start_info->console.domU.evtchn;
263+
else
264+
xen_hvm_console_init();
265+
}
266+
218267
hvc_instantiate(HVC_COOKIE, 0, ops);
219268
return 0;
220269
}
@@ -230,6 +279,9 @@ static void xenboot_write_console(struct console *console, const char *string,
230279
unsigned int linelen, off = 0;
231280
const char *pos;
232281

282+
if (!xen_pv_domain())
283+
return;
284+
233285
dom0_write_console(0, string, len);
234286

235287
if (xen_initial_domain())

include/xen/interface/hvm/params.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@
9090
/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
9191
#define HVM_PARAM_VPT_ALIGN 16
9292

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
9498

9599
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */

0 commit comments

Comments
 (0)