hvc_xen.c revision 4fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06
1b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge/*
2b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * xen console driver interface to hvc_console.c
3b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge *
4b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * (c) 2007 Gerd Hoffmann <kraxel@suse.de>
5b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge *
6b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * This program is free software; you can redistribute it and/or modify
7b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * it under the terms of the GNU General Public License as published by
8b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * the Free Software Foundation; either version 2 of the License, or
9b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * (at your option) any later version.
10b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge *
11b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * This program is distributed in the hope that it will be useful,
12b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * but WITHOUT ANY WARRANTY; without even the implied warranty of
13b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * GNU General Public License for more details.
15b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge *
16b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * You should have received a copy of the GNU General Public License
17b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * along with this program; if not, write to the Free Software
18b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge */
20b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
21b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <linux/console.h>
22b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <linux/delay.h>
23b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <linux/err.h>
24b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <linux/init.h>
25b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <linux/types.h>
26b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
27b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <asm/xen/hypervisor.h>
281ccbf5344c3daef046d2323190cc6807c44f1917Jeremy Fitzhardinge
291ccbf5344c3daef046d2323190cc6807c44f1917Jeremy Fitzhardinge#include <xen/xen.h>
30b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <xen/page.h>
31b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <xen/events.h>
32b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <xen/interface/io/console.h>
33b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include <xen/hvc-console.h>
34b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
35b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#include "hvc_console.h"
36b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
37b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge#define HVC_COOKIE   0x58656e /* "Xen" in hex */
38b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
39b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardingestatic struct hvc_struct *hvc;
40b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardingestatic int xencons_irq;
41b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
42b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge/* ------------------------------------------------------------------ */
43b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
446b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardingestatic unsigned long console_pfn = ~0ul;
456b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge
46b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardingestatic inline struct xencons_interface *xencons_interface(void)
47b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge{
486b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge	if (console_pfn == ~0ul)
496b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge		return mfn_to_virt(xen_start_info->console.domU.mfn);
506b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge	else
516b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge		return __va(console_pfn << PAGE_SHIFT);
52b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge}
53b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
54b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardingestatic inline void notify_daemon(void)
55b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge{
56b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	/* Use evtchn: this is called early, before irq is set up. */
57b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
58b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge}
59b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
607825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardingestatic int __write_console(const char *data, int len)
61b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge{
62b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	struct xencons_interface *intf = xencons_interface();
63b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	XENCONS_RING_IDX cons, prod;
64b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	int sent = 0;
65b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
66b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	cons = intf->out_cons;
67b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	prod = intf->out_prod;
68b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	mb();			/* update queue values before going on */
69b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	BUG_ON((prod - cons) > sizeof(intf->out));
70b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
71b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
72b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
73b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
74b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	wmb();			/* write ring before updating pointer */
75b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	intf->out_prod = prod;
76b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
77b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	notify_daemon();
78b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	return sent;
79b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge}
80b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
814fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingestatic int domU_write_console(uint32_t vtermno, const char *data, int len)
827825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge{
837825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	int ret = len;
847825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge
857825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	/*
867825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	 * Make sure the whole buffer is emitted, polling if
877825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	 * necessary.  We don't ever want to rely on the hvc daemon
887825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	 * because the most interesting console output is when the
897825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	 * kernel is crippled.
907825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	 */
917825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	while (len) {
927825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge		int sent = __write_console(data, len);
937825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge
947825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge		data += sent;
957825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge		len -= sent;
967825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge
977825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge		if (unlikely(len))
987825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge			HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
997825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	}
1007825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge
1017825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge	return ret;
1027825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge}
1037825cf10e31c64ece3cac66fb01a742f1094da51Jeremy Fitzhardinge
1044fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingestatic int domU_read_console(uint32_t vtermno, char *buf, int len)
105b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge{
106b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	struct xencons_interface *intf = xencons_interface();
107b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	XENCONS_RING_IDX cons, prod;
108b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	int recv = 0;
109b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
110b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	cons = intf->in_cons;
111b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	prod = intf->in_prod;
112b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	mb();			/* get pointers before reading ring */
113b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	BUG_ON((prod - cons) > sizeof(intf->in));
114b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
115b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	while (cons != prod && recv < len)
116b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge		buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
117b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
118b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	mb();			/* read ring before consuming */
119b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	intf->in_cons = cons;
120b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
121b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	notify_daemon();
122b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	return recv;
123b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge}
124b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
1254fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingestatic struct hv_ops domU_hvc_ops = {
1264fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	.get_chars = domU_read_console,
1274fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	.put_chars = domU_write_console,
128611e097d7707741a336a0677d9d69bec40f29f3dChristian Borntraeger	.notifier_add = notifier_add_irq,
129611e097d7707741a336a0677d9d69bec40f29f3dChristian Borntraeger	.notifier_del = notifier_del_irq,
130fc362e2e0efd8b652ebfb409a4e43e6189c04f6fHendrik Brueckner	.notifier_hangup = notifier_hangup_irq,
131b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge};
132b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
1334fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingestatic int dom0_read_console(uint32_t vtermno, char *buf, int len)
1344fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge{
1354fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	return HYPERVISOR_console_io(CONSOLEIO_read, len, buf);
1364fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge}
1374fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge
1384fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge/*
1394fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge * Either for a dom0 to write to the system console, or a domU with a
1404fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge * debug version of Xen
1414fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge */
1424fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingestatic int dom0_write_console(uint32_t vtermno, const char *str, int len)
1434fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge{
1444fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
1454fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	if (rc < 0)
1464fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		return 0;
1474fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge
1484fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	return len;
1494fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge}
1504fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge
1514fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingestatic struct hv_ops dom0_hvc_ops = {
1524fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	.get_chars = dom0_read_console,
1534fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	.put_chars = dom0_write_console,
1544fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	.notifier_add = notifier_add_irq,
1554fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	.notifier_del = notifier_del_irq,
1564fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	.notifier_hangup = notifier_hangup_irq,
1574fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge};
1584fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge
1594fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingestatic int __init xen_hvc_init(void)
160b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge{
161b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	struct hvc_struct *hp;
1624fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	struct hv_ops *ops;
163b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
1644fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	if (!xen_pv_domain())
1656b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge		return -ENODEV;
166b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
1674fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	if (xen_initial_domain()) {
1684fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		ops = &dom0_hvc_ops;
1694fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
1704fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	} else {
1714fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		if (!xen_start_info->console.domU.evtchn)
1724fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge			return -ENODEV;
1734fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge
1744fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		ops = &domU_hvc_ops;
1754fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
1764fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	}
177b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	if (xencons_irq < 0)
1786b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge		xencons_irq = 0; /* NO_IRQ */
1796b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge
1804fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
181b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	if (IS_ERR(hp))
182b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge		return PTR_ERR(hp);
183b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
184b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	hvc = hp;
1856b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge
1866b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge	console_pfn = mfn_to_pfn(xen_start_info->console.domU.mfn);
1876b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge
188b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	return 0;
189b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge}
190b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
1916b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardingevoid xen_console_resume(void)
1926b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge{
1936b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge	if (xencons_irq)
1946b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge		rebind_evtchn_irq(xen_start_info->console.domU.evtchn, xencons_irq);
1956b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge}
1966b9b732d0e396a3f1a95977162a8624aafce38a1Jeremy Fitzhardinge
1974fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingestatic void __exit xen_hvc_fini(void)
198b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge{
199b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	if (hvc)
200b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge		hvc_remove(hvc);
201b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge}
202b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
203b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardingestatic int xen_cons_init(void)
204b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge{
2054fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	struct hv_ops *ops;
2064fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge
2076e833587e11ed0dbf12e647127f2650e2f80b26dJeremy Fitzhardinge	if (!xen_pv_domain())
208b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge		return 0;
209b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
2104fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	if (xen_initial_domain())
2114fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		ops = &dom0_hvc_ops;
2124fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	else
2134fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		ops = &domU_hvc_ops;
2144fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge
2154fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	hvc_instantiate(HVC_COOKIE, 0, ops);
216b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	return 0;
217b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge}
218b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
2194fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingemodule_init(xen_hvc_init);
2204fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardingemodule_exit(xen_hvc_fini);
221b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardingeconsole_initcall(xen_cons_init);
222b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
2230922abdc3982ae54cbe1b24ac5aa91a260eca1bbJeremy Fitzhardinge#ifdef CONFIG_EARLY_PRINTK
224b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardingestatic void xenboot_write_console(struct console *console, const char *string,
225b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge				  unsigned len)
226b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge{
227b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	unsigned int linelen, off = 0;
228b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	const char *pos;
229b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
2304fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	dom0_write_console(0, string, len);
2314fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge
2324fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	if (xen_initial_domain())
2334fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		return;
2340922abdc3982ae54cbe1b24ac5aa91a260eca1bbJeremy Fitzhardinge
2354fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	domU_write_console(0, "(early) ", 8);
236b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
237b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge		linelen = pos-string+off;
238b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge		if (off + linelen > len)
239b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge			break;
2404fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		domU_write_console(0, string+off, linelen);
2414fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		domU_write_console(0, "\r\n", 2);
242b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge		off += linelen + 1;
243b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	}
244b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	if (off < len)
2454fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge		domU_write_console(0, string+off, len-off);
246b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge}
247b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge
248b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardingestruct console xenboot_console = {
249b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	.name		= "xenboot",
250b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge	.write		= xenboot_write_console,
2510922abdc3982ae54cbe1b24ac5aa91a260eca1bbJeremy Fitzhardinge	.flags		= CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
252b536b4b9623084d86f2b1f19cb44a2d6d74f00bfJeremy Fitzhardinge};
2530922abdc3982ae54cbe1b24ac5aa91a260eca1bbJeremy Fitzhardinge#endif	/* CONFIG_EARLY_PRINTK */
2540acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge
2550acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardingevoid xen_raw_console_write(const char *str)
2560acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge{
2574fe7d5a708a955b35e3fdc4dea3e0b7a6ae2eb06Jeremy Fitzhardinge	dom0_write_console(0, str, strlen(str));
2580acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge}
2590acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge
2600acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardingevoid xen_raw_printk(const char *fmt, ...)
2610acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge{
2620acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge	static char buf[512];
2630acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge	va_list ap;
2640acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge
2650acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge	va_start(ap, fmt);
2660acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge	vsnprintf(buf, sizeof(buf), fmt, ap);
2670acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge	va_end(ap);
2680acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge
2690acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge	xen_raw_console_write(buf);
2700acf10d8fbd52926217d3933d196b33fe2468f18Jeremy Fitzhardinge}
271