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>