Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Mar 2014 10:09:23 +0000 (UTC)
From:      Roger Pau Monné <royger@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r263004 - in head/sys: conf dev/xen/console i386/include/xen i386/xen x86/xen xen
Message-ID:  <201403111009.s2BA9NZp015193@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: royger
Date: Tue Mar 11 10:09:23 2014
New Revision: 263004
URL: http://svnweb.freebsd.org/changeset/base/263004

Log:
  xen: add and enable Xen console for PVH guests
  
  This adds and enables the PV console used on XEN kernels to
  GENERIC/XENHVM kernels in order for it to be used on PVH.
  
  Approved by: gibbs
  Sponsored by: Citrix Systems R&D
  
  dev/xen/console/console.c:
   - Define console_page.
   - Move xc_printf debug function from i386 XEN code to generic console
     code.
   - Rework xc_printf.
   - Use xen_initial_domain instead of open-coded checks for Dom0.
   - Gate the attach of the PV console to PV(H) guests.
  
  dev/xen/console/xencons_ring.c:
   - Allow the PV Xen console to output earlier by directly signaling
     the event channel in start_info if the event channel is not yet
     initialized.
   - Use HYPERVISOR_start_info instead of xen_start_info.
  
  i386/include/xen/xen-os.h:
   - Remove prototype for xc_printf since it's now declared in global
     xen-os.h
  
  i386/xen/xen_machdep.c:
   - Remove previous version of xc_printf.
   - Remove definition of console_page (now it's defined in the console
     itself).
   - Fix some printf formatting errors.
  
  x86/xen/pv.c:
   - Add some early boot debug messages using xc_printf.
   - Set console_page based on the value passed in start_info.
  
  xen/xen-os.h:
   - Declare console_page and add prototype for xc_printf.

Modified:
  head/sys/conf/files
  head/sys/dev/xen/console/console.c
  head/sys/dev/xen/console/xencons_ring.c
  head/sys/i386/include/xen/xen-os.h
  head/sys/i386/xen/xen_machdep.c
  head/sys/x86/xen/pv.c
  head/sys/xen/xen-os.h

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Tue Mar 11 10:07:55 2014	(r263003)
+++ head/sys/conf/files	Tue Mar 11 10:09:23 2014	(r263004)
@@ -2527,8 +2527,8 @@ dev/xe/if_xe_pccard.c		optional xe pccar
 dev/xen/balloon/balloon.c	optional xen | xenhvm
 dev/xen/blkfront/blkfront.c	optional xen | xenhvm
 dev/xen/blkback/blkback.c	optional xen | xenhvm
-dev/xen/console/console.c	optional xen
-dev/xen/console/xencons_ring.c	optional xen
+dev/xen/console/console.c	optional xen | xenhvm
+dev/xen/console/xencons_ring.c	optional xen | xenhvm
 dev/xen/control/control.c	optional xen | xenhvm
 dev/xen/netback/netback.c	optional xen | xenhvm
 dev/xen/netfront/netfront.c	optional xen | xenhvm

Modified: head/sys/dev/xen/console/console.c
==============================================================================
--- head/sys/dev/xen/console/console.c	Tue Mar 11 10:07:55 2014	(r263003)
+++ head/sys/dev/xen/console/console.c	Tue Mar 11 10:09:23 2014	(r263004)
@@ -27,6 +27,8 @@ __FBSDID("$FreeBSD$");
 
 
 #include "opt_ddb.h"
+#include "opt_printf.h"
+
 #ifdef DDB
 #include <ddb/ddb.h>
 #endif
@@ -69,11 +71,14 @@ struct mtx              cn_mtx;
 static char wbuf[WBUF_SIZE];
 static char rbuf[RBUF_SIZE];
 static int rc, rp;
-static unsigned int cnsl_evt_reg;
+bool cnsl_evt_reg;
 static unsigned int wc, wp; /* write_cons, write_prod */
 xen_intr_handle_t xen_intr_handle;
 device_t xencons_dev;
 
+/* Virtual address of the shared console page */
+char *console_page;
+
 #ifdef KDB
 static int	xc_altbrk;
 #endif
@@ -110,9 +115,70 @@ static struct ttydevsw xc_ttydevsw = {
         .tsw_outwakeup	= xcoutwakeup,
 };
 
+/*----------------------------- Debug function -------------------------------*/
+struct putchar_arg {
+	char	*buf;
+	size_t	size;
+	size_t	n_next;
+};
+
+static void
+putchar(int c, void *arg)
+{
+	struct putchar_arg *pca;
+
+	pca = (struct putchar_arg *)arg;
+
+	if (pca->buf == NULL) {
+		/*
+		 * We have no buffer, output directly to the
+		 * console char by char.
+		 */
+		HYPERVISOR_console_write((char *)&c, 1);
+	} else {
+		pca->buf[pca->n_next++] = c;
+		if ((pca->size == pca->n_next) || (c = '\0')) {
+			/* Flush the buffer */
+			HYPERVISOR_console_write(pca->buf, pca->n_next);
+			pca->n_next = 0;
+		}
+	}
+}
+
+void
+xc_printf(const char *fmt, ...)
+{
+	va_list ap;
+	struct putchar_arg pca;
+#ifdef PRINTF_BUFR_SIZE
+	char buf[PRINTF_BUFR_SIZE];
+
+	pca.buf = buf;
+	pca.size = sizeof(buf);
+	pca.n_next = 0;
+#else
+	pca.buf = NULL;
+	pca.size = 0;
+#endif
+
+	KASSERT((xen_domain()), ("call to xc_printf from non Xen guest"));
+
+	va_start(ap, fmt);
+	kvprintf(fmt, putchar, &pca, 10, ap);
+	va_end(ap);
+
+#ifdef PRINTF_BUFR_SIZE
+	if (pca.n_next != 0)
+		HYPERVISOR_console_write(buf, pca.n_next);
+#endif
+}
+
 static void
 xc_cnprobe(struct consdev *cp)
 {
+	if (!xen_pv_domain())
+		return;
+
 	cp->cn_pri = CN_REMOTE;
 	sprintf(cp->cn_name, "%s0", driver_name);
 }
@@ -175,7 +241,7 @@ static void
 xc_cnputc(struct consdev *dev, int c)
 {
 
-	if (xen_start_info->flags & SIF_INITDOMAIN)
+	if (xen_initial_domain())
 		xc_cnputc_dom0(dev, c);
 	else
 		xc_cnputc_domu(dev, c);
@@ -206,8 +272,7 @@ xcons_putc(int c)
 		xcons_force_flush();
 #endif	    	
 	}
-	if (cnsl_evt_reg)
-		__xencons_tx_flush();
+	__xencons_tx_flush();
 	
 	/* inform start path that we're pretty full */
 	return ((wp - wc) >= WBUF_SIZE - 100) ? TRUE : FALSE;
@@ -217,6 +282,10 @@ static void
 xc_identify(driver_t *driver, device_t parent)
 {
 	device_t child;
+
+	if (!xen_pv_domain())
+		return;
+
 	child = BUS_ADD_CHILD(parent, 0, driver_name, 0);
 	device_set_driver(child, driver);
 	device_set_desc(child, "Xen Console");
@@ -242,10 +311,10 @@ xc_attach(device_t dev) 
 
 	xencons_ring_init();
 
-	cnsl_evt_reg = 1;
+	cnsl_evt_reg = true;
 	callout_reset(&xc_callout, XC_POLLTIME, xc_timeout, xccons);
     
-	if (xen_start_info->flags & SIF_INITDOMAIN) {
+	if (xen_initial_domain()) {
 		error = xen_intr_bind_virq(dev, VIRQ_CONSOLE, 0, NULL,
 		                           xencons_priv_interrupt, NULL,
 		                           INTR_TYPE_TTY, &xen_intr_handle);
@@ -309,7 +378,7 @@ __xencons_tx_flush(void)
 		sz = wp - wc;
 		if (sz > (WBUF_SIZE - WBUF_MASK(wc)))
 			sz = WBUF_SIZE - WBUF_MASK(wc);
-		if (xen_start_info->flags & SIF_INITDOMAIN) {
+		if (xen_initial_domain()) {
 			HYPERVISOR_console_io(CONSOLEIO_write, sz, &wbuf[WBUF_MASK(wc)]);
 			wc += sz;
 		} else {
@@ -426,7 +495,7 @@ xcons_force_flush(void)
 {
 	int        sz;
 
-	if (xen_start_info->flags & SIF_INITDOMAIN)
+	if (xen_initial_domain())
 		return;
 
 	/* Spin until console data is flushed through to the domain controller. */

Modified: head/sys/dev/xen/console/xencons_ring.c
==============================================================================
--- head/sys/dev/xen/console/xencons_ring.c	Tue Mar 11 10:07:55 2014	(r263003)
+++ head/sys/dev/xen/console/xencons_ring.c	Tue Mar 11 10:09:23 2014	(r263004)
@@ -32,9 +32,9 @@ __FBSDID("$FreeBSD$");
 
 #define console_evtchn	console.domU.evtchn
 xen_intr_handle_t console_handle;
-extern char *console_page;
 extern struct mtx              cn_mtx;
 extern device_t xencons_dev;
+extern bool cnsl_evt_reg;
 
 static inline struct xencons_interface *
 xencons_interface(void)
@@ -60,6 +60,9 @@ xencons_ring_send(const char *data, unsi
 	struct xencons_interface *intf; 
 	XENCONS_RING_IDX cons, prod;
 	int sent;
+	struct evtchn_send send = {
+		.port = HYPERVISOR_start_info->console_evtchn
+	};
 
 	intf = xencons_interface();
 	cons = intf->out_cons;
@@ -76,7 +79,10 @@ xencons_ring_send(const char *data, unsi
 	wmb();
 	intf->out_prod = prod;
 
-	xen_intr_signal(console_handle);
+	if (cnsl_evt_reg)
+		xen_intr_signal(console_handle);
+	else
+		HYPERVISOR_event_channel_op(EVTCHNOP_send, &send);
 
 	return sent;
 
@@ -125,11 +131,11 @@ xencons_ring_init(void)
 {
 	int err;
 
-	if (!xen_start_info->console_evtchn)
+	if (HYPERVISOR_start_info->console_evtchn == 0)
 		return 0;
 
 	err = xen_intr_bind_local_port(xencons_dev,
-	    xen_start_info->console_evtchn, NULL, xencons_handle_input, NULL,
+	    HYPERVISOR_start_info->console_evtchn, NULL, xencons_handle_input, NULL,
 	    INTR_TYPE_MISC | INTR_MPSAFE, &console_handle);
 	if (err) {
 		return err;
@@ -145,7 +151,7 @@ void 
 xencons_suspend(void)
 {
 
-	if (!xen_start_info->console_evtchn)
+	if (HYPERVISOR_start_info->console_evtchn == 0)
 		return;
 
 	xen_intr_unbind(&console_handle);

Modified: head/sys/i386/include/xen/xen-os.h
==============================================================================
--- head/sys/i386/include/xen/xen-os.h	Tue Mar 11 10:07:55 2014	(r263003)
+++ head/sys/i386/include/xen/xen-os.h	Tue Mar 11 10:09:23 2014	(r263004)
@@ -45,7 +45,6 @@ static inline void rep_nop(void)
 #define cpu_relax() rep_nop()
 
 #ifndef XENHVM
-void xc_printf(const char *fmt, ...);
 
 #ifdef SMP
 extern int gdtset;

Modified: head/sys/i386/xen/xen_machdep.c
==============================================================================
--- head/sys/i386/xen/xen_machdep.c	Tue Mar 11 10:07:55 2014	(r263003)
+++ head/sys/i386/xen/xen_machdep.c	Tue Mar 11 10:09:23 2014	(r263004)
@@ -186,21 +186,6 @@ xen_boothowto(char *envp)
 	return howto;
 }
 
-#define XC_PRINTF_BUFSIZE 1024
-void
-xc_printf(const char *fmt, ...)
-{
-        __va_list ap;
-        int retval;
-        static char buf[XC_PRINTF_BUFSIZE];
-
-        va_start(ap, fmt);
-        retval = vsnprintf(buf, XC_PRINTF_BUFSIZE - 1, fmt, ap);
-        va_end(ap);
-        buf[retval] = 0;
-        (void)HYPERVISOR_console_write(buf, retval);
-}
-
 
 #define XPQUEUE_SIZE 128
 
@@ -745,8 +730,6 @@ void initvalues(start_info_t *startinfo)
 struct xenstore_domain_interface;
 extern struct xenstore_domain_interface *xen_store;
 
-char *console_page;
-
 void *
 bootmem_alloc(unsigned int size) 
 {
@@ -969,7 +952,7 @@ initvalues(start_info_t *startinfo)
 	xc_printf("initvalues(): wooh - availmem=%x,%x\n", avail_space,
 	    cur_space);
 
-	xc_printf("KERNBASE=%x,pt_base=%x, VTOPFN(base)=%x, nr_pt_frames=%x\n",
+	xc_printf("KERNBASE=%x,pt_base=%lx, VTOPFN(base)=%x, nr_pt_frames=%lx\n",
 	    KERNBASE,xen_start_info->pt_base, VTOPFN(xen_start_info->pt_base),
 	    xen_start_info->nr_pt_frames);
 	xendebug_flags = 0; /* 0xffffffff; */
@@ -978,7 +961,7 @@ initvalues(start_info_t *startinfo)
 	shift_phys_machine(xen_phys_machine, xen_start_info->nr_pages);
 #endif
 	XENPRINTF("IdlePTD %p\n", IdlePTD);
-	XENPRINTF("nr_pages: %ld shared_info: 0x%lx flags: 0x%lx pt_base: 0x%lx "
+	XENPRINTF("nr_pages: %ld shared_info: 0x%lx flags: 0x%x pt_base: 0x%lx "
 		  "mod_start: 0x%lx mod_len: 0x%lx\n",
 		  xen_start_info->nr_pages, xen_start_info->shared_info, 
 		  xen_start_info->flags, xen_start_info->pt_base, 

Modified: head/sys/x86/xen/pv.c
==============================================================================
--- head/sys/x86/xen/pv.c	Tue Mar 11 10:07:55 2014	(r263003)
+++ head/sys/x86/xen/pv.c	Tue Mar 11 10:09:23 2014	(r263004)
@@ -73,9 +73,12 @@ hammer_time_xen(start_info_t *si, uint64
 	vm_guest = VM_GUEST_XEN;
 
 	if ((si == NULL) || (xenstack == 0)) {
+		xc_printf("ERROR: invalid start_info or xen stack, halting\n");
 		HYPERVISOR_shutdown(SHUTDOWN_crash);
 	}
 
+	xc_printf("FreeBSD PVH running on %s\n", si->magic);
+
 	/* We use 3 pages of xen stack for the boot pagetables */
 	physfree = xenstack + 3 * PAGE_SIZE - KERNBASE;
 
@@ -93,6 +96,7 @@ hammer_time_xen(start_info_t *si, uint64
 	 */
 	xen_store = (struct xenstore_domain_interface *)
 	    (ptoa(si->store_mfn) + KERNBASE);
+	console_page = (char *)(ptoa(si->console.domU.mfn) + KERNBASE);
 
 	/*
 	 * Use the stack Xen gives us to build the page tables

Modified: head/sys/xen/xen-os.h
==============================================================================
--- head/sys/xen/xen-os.h	Tue Mar 11 10:07:55 2014	(r263003)
+++ head/sys/xen/xen-os.h	Tue Mar 11 10:09:23 2014	(r263004)
@@ -55,6 +55,7 @@ extern start_info_t *HYPERVISOR_start_in
 
 /* XXX: we need to get rid of this and use HYPERVISOR_start_info directly */
 extern struct xenstore_domain_interface *xen_store;
+extern char *console_page;
 
 enum xen_domain_type {
 	XEN_NATIVE,             /* running on bare hardware    */
@@ -89,6 +90,9 @@ xen_initial_domain(void)
 	    (HYPERVISOR_start_info->flags & SIF_INITDOMAIN) != 0);
 }
 
+/* Debug/emergency function, prints directly to hypervisor console */
+void xc_printf(const char *, ...) __printflike(1, 2);
+
 #ifndef xen_mb
 #define xen_mb() mb()
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403111009.s2BA9NZp015193>