From 01e79009d0b962ce5cf9812bdde6fe7680035df0 Mon Sep 17 00:00:00 2001
From: Julien Grall <julien.grall@linaro.org>
Date: Tue, 14 Jan 2014 01:41:17 +0000
Subject: [PATCH 36/48] xen/console: handle console for HVM

ARM guest is an HVM container with PV drivers for the console. Support HVM
in the console and enable it for ARM.
---
 sys/dev/xen/console/console.c      | 19 +++++++++++++++++-
 sys/dev/xen/console/xencons_ring.c | 41 ++++++++++++++++++++++++++++----------
 2 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c
index a26e30c..c0d8e0b 100644
--- a/sys/dev/xen/console/console.c
+++ b/sys/dev/xen/console/console.c
@@ -176,8 +176,13 @@ xc_printf(const char *fmt, ...)
 static void
 xc_cnprobe(struct consdev *cp)
 {
+#if defined(__arm__)
+	if (!xen_domain())
+		return;
+#else
 	if (!xen_pv_domain())
 		return;
+#endif
 
 	cp->cn_pri = CN_REMOTE;
 	sprintf(cp->cn_name, "%s0", driver_name);
@@ -282,8 +287,13 @@ xc_identify(driver_t *driver, device_t parent)
 {
 	device_t child;
 
+#if defined(__arm__)
+	if (!xen_domain())
+		return;
+#else
 	if (!xen_pv_domain())
 		return;
+#endif
 
 	child = BUS_ADD_CHILD(parent, 0, driver_name, 0);
 }
@@ -306,7 +316,13 @@ xc_attach(device_t dev)
 
 	callout_init(&xc_callout, 0);
 
-	xencons_ring_init();
+	error = xencons_ring_init();
+
+	if (error != 0) {
+		printf("xencons: unable to initialize the ring (%d)\n",
+		       error);
+		return error;
+	}
 
 	cnsl_evt_reg = true;
 	callout_reset(&xc_callout, XC_POLLTIME, xc_timeout, xccons);
@@ -323,6 +339,7 @@ xc_attach(device_t dev)
 				   NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
 		printf("xencons: shutdown event registration failed!\n");
 	
+
 	return (0);
 }
 
diff --git a/sys/dev/xen/console/xencons_ring.c b/sys/dev/xen/console/xencons_ring.c
index 65d05ce..54b0ddf 100644
--- a/sys/dev/xen/console/xencons_ring.c
+++ b/sys/dev/xen/console/xencons_ring.c
@@ -15,6 +15,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/bus.h>
 #include <sys/cons.h>
 
+#include <vm/vm.h>
+#include <vm/pmap.h>
 #include <machine/stdarg.h>
 
 #include <xen/xen-os.h>
@@ -29,6 +31,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/xen/console/xencons_ring.h>
 #include <xen/evtchn.h>
 #include <xen/interface/io/console.h>
+#include <xen/hvm.h>
 
 #define console_evtchn	console.domU.evtchn
 xen_intr_handle_t console_handle;
@@ -78,6 +81,10 @@ xencons_ring_send(const char *data, unsigned len)
 	};
 
 	intf = xencons_interface();
+
+	if (!intf)
+		return 0;
+
 	cons = intf->out_cons;
 	prod = intf->out_prod;
 	sent = 0;
@@ -152,20 +159,34 @@ xencons_ring_register_receiver(xencons_receiver_func *f)
 	xencons_receiver = f;
 }
 
+/* HVM code */
 int
 xencons_ring_init(void)
 {
 	int err;
-
-	if (HYPERVISOR_start_info->console_evtchn == 0)
-		return 0;
-
-	err = xen_intr_bind_local_port(xencons_dev,
-	    HYPERVISOR_start_info->console_evtchn, NULL, xencons_handle_input, NULL,
-	    INTR_TYPE_MISC | INTR_MPSAFE, &console_handle);
-	if (err) {
-		return err;
-	}
+	evtchn_port_t evtchn;
+	xen_pfn_t pfn;
+
+	if (xen_hvm_domain()) {
+		evtchn = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN);
+		pfn = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN);
+		if (!pfn)
+			return (ENODEV);
+		console_page = xen_pmap(pfn << PAGE_SHIFT, PAGE_SIZE);
+	} else
+		evtchn = HYPERVISOR_start_info->console_evtchn;
+
+	if (!evtchn)
+		return (ENODEV);
+
+	err = xen_intr_bind_local_port(xencons_dev, evtchn, NULL,
+				       xencons_handle_input, NULL,
+				       INTR_TYPE_MISC | INTR_MPSAFE,
+				       &console_handle);
+	if (err != 0)
+		return (err);
+
+	console_page = xen_pmap(pfn << PAGE_SHIFT, PAGE_SIZE);
 
 	return 0;
 }
-- 
2.1.0

