ia64/xen-unstable

changeset 16264:3bb94bb35dad

Allow incremental access to hypervisor console log.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Mon Oct 29 12:56:27 2007 +0000 (2007-10-29)
parents 23582bcda6e1
children 955ee4fa1345
files tools/console/daemon/io.c tools/libxc/xc_misc.c tools/libxc/xenctrl.h tools/python/xen/lowlevel/xc/xc.c xen/common/sysctl.c xen/drivers/char/console.c xen/include/public/sysctl.h xen/include/xen/console.h
line diff
     1.1 --- a/tools/console/daemon/io.c	Mon Oct 29 09:49:39 2007 +0000
     1.2 +++ b/tools/console/daemon/io.c	Mon Oct 29 12:56:27 2007 +0000
     1.3 @@ -53,7 +53,9 @@ extern int log_hv;
     1.4  extern char *log_dir;
     1.5  
     1.6  static int log_hv_fd = -1;
     1.7 +static evtchn_port_or_error_t log_hv_evtchn = -1;
     1.8  static int xc_handle = -1;
     1.9 +static int xce_handle = -1;
    1.10  
    1.11  struct buffer
    1.12  {
    1.13 @@ -76,8 +78,8 @@ struct domain
    1.14  	char *serialpath;
    1.15  	int use_consolepath;
    1.16  	int ring_ref;
    1.17 -	evtchn_port_t local_port;
    1.18 -	evtchn_port_t remote_port;
    1.19 +	evtchn_port_or_error_t local_port;
    1.20 +	evtchn_port_or_error_t remote_port;
    1.21  	int xce_handle;
    1.22  	struct xencons_interface *interface;
    1.23  };
    1.24 @@ -713,7 +715,7 @@ static void handle_tty_write(struct doma
    1.25  
    1.26  static void handle_ring_read(struct domain *dom)
    1.27  {
    1.28 -	evtchn_port_t port;
    1.29 +	evtchn_port_or_error_t port;
    1.30  
    1.31  	if ((port = xc_evtchn_pending(dom->xce_handle)) == -1)
    1.32  		return;
    1.33 @@ -752,12 +754,20 @@ static void handle_hv_logs(void)
    1.34  	char buffer[1024*16];
    1.35  	char *bufptr = buffer;
    1.36  	unsigned int size = sizeof(buffer);
    1.37 -	if (xc_readconsolering(xc_handle, &bufptr, &size, 1) == 0) {
    1.38 +	static uint32_t index = 0;
    1.39 +	evtchn_port_or_error_t port;
    1.40 +
    1.41 +	if ((port = xc_evtchn_pending(xce_handle)) == -1)
    1.42 +		return;
    1.43 +
    1.44 +	if (xc_readconsolering(xc_handle, &bufptr, &size, 0, 1, &index) == 0) {
    1.45  		int len = write(log_hv_fd, buffer, size);
    1.46  		if (len < 0)
    1.47  			dolog(LOG_ERR, "Failed to write hypervisor log: %d (%s)",
    1.48  			      errno, strerror(errno));
    1.49  	}
    1.50 +
    1.51 +	(void)xc_evtchn_unmask(xce_handle, port);
    1.52  }
    1.53  
    1.54  static void handle_log_reload(void)
    1.55 @@ -785,16 +795,30 @@ void handle_io(void)
    1.56  
    1.57  	if (log_hv) {
    1.58  		xc_handle = xc_interface_open();
    1.59 -		if (xc_handle == -1)
    1.60 +		if (xc_handle == -1) {
    1.61  			dolog(LOG_ERR, "Failed to open xc handle: %d (%s)",
    1.62  			      errno, strerror(errno));
    1.63 -		else
    1.64 -			log_hv_fd = create_hv_log();
    1.65 +			goto out;
    1.66 +		}
    1.67 +		xce_handle = xc_evtchn_open();
    1.68 +		if (xce_handle == -1) {
    1.69 +			dolog(LOG_ERR, "Failed to open xce handle: %d (%s)",
    1.70 +			      errno, strerror(errno));
    1.71 +			goto out;
    1.72 +		}
    1.73 +		log_hv_fd = create_hv_log();
    1.74 +		if (log_hv_fd == -1)
    1.75 +			goto out;
    1.76 +		log_hv_evtchn = xc_evtchn_bind_virq(xce_handle, VIRQ_CON_RING);
    1.77 +		if (log_hv_evtchn == -1) {
    1.78 +			dolog(LOG_ERR, "Failed to bind to VIRQ_CON_RING: "
    1.79 +			      "%d (%s)", errno, strerror(errno));
    1.80 +			goto out;
    1.81 +		}
    1.82  	}
    1.83  
    1.84  	for (;;) {
    1.85  		struct domain *d, *n;
    1.86 -		struct timeval timeout = { 1, 0 }; /* Read HV logs every 1 second */
    1.87  		int max_fd = -1;
    1.88  
    1.89  		FD_ZERO(&readfds);
    1.90 @@ -803,6 +827,11 @@ void handle_io(void)
    1.91  		FD_SET(xs_fileno(xs), &readfds);
    1.92  		max_fd = MAX(xs_fileno(xs), max_fd);
    1.93  
    1.94 +		if (log_hv) {
    1.95 +			FD_SET(xc_evtchn_fd(xce_handle), &readfds);
    1.96 +			max_fd = MAX(xc_evtchn_fd(xce_handle), max_fd);
    1.97 +		}
    1.98 +
    1.99  		for (d = dom_head; d; d = d->next) {
   1.100  			if (d->xce_handle != -1) {
   1.101  				int evtchn_fd = xc_evtchn_fd(d->xce_handle);
   1.102 @@ -820,11 +849,7 @@ void handle_io(void)
   1.103  			}
   1.104  		}
   1.105  
   1.106 -		/* XXX I wish we didn't have to busy wait for hypervisor logs
   1.107 -		 * but there's no obvious way to get event channel notifications
   1.108 -		 * for new HV log data as we can with guest */
   1.109 -		ret = select(max_fd + 1, &readfds, &writefds, 0,
   1.110 -			     log_hv_fd != -1 ? &timeout : NULL);
   1.111 +		ret = select(max_fd + 1, &readfds, &writefds, 0, NULL);
   1.112  
   1.113  		if (log_reload) {
   1.114  			handle_log_reload();
   1.115 @@ -841,12 +866,10 @@ void handle_io(void)
   1.116  			break;
   1.117  		}
   1.118  
   1.119 -		/* Always process HV logs even if not a timeout */
   1.120 -		if (log_hv_fd != -1)
   1.121 +		if (log_hv && FD_ISSET(xc_evtchn_fd(xce_handle), &readfds))
   1.122  			handle_hv_logs();
   1.123  
   1.124 -		/* Must not check returned FDSET if it was a timeout */
   1.125 -		if (ret == 0)
   1.126 +		if (ret <= 0)
   1.127  			continue;
   1.128  
   1.129  		if (FD_ISSET(xs_fileno(xs), &readfds))
   1.130 @@ -869,6 +892,7 @@ void handle_io(void)
   1.131  		}
   1.132  	}
   1.133  
   1.134 + out:
   1.135  	if (log_hv_fd != -1) {
   1.136  		close(log_hv_fd);
   1.137  		log_hv_fd = -1;
   1.138 @@ -877,6 +901,11 @@ void handle_io(void)
   1.139  		xc_interface_close(xc_handle);
   1.140  		xc_handle = -1;
   1.141  	}
   1.142 +	if (xce_handle != -1) {
   1.143 +		xc_evtchn_close(xce_handle);
   1.144 +		xce_handle = -1;
   1.145 +	}
   1.146 +	log_hv_evtchn = -1;
   1.147  }
   1.148  
   1.149  /*
     2.1 --- a/tools/libxc/xc_misc.c	Mon Oct 29 09:49:39 2007 +0000
     2.2 +++ b/tools/libxc/xc_misc.c	Mon Oct 29 12:56:27 2007 +0000
     2.3 @@ -10,7 +10,7 @@
     2.4  int xc_readconsolering(int xc_handle,
     2.5                         char **pbuffer,
     2.6                         unsigned int *pnr_chars,
     2.7 -                       int clear)
     2.8 +                       int clear, int incremental, uint32_t *pindex)
     2.9  {
    2.10      int ret;
    2.11      DECLARE_SYSCTL;
    2.12 @@ -19,14 +19,24 @@ int xc_readconsolering(int xc_handle,
    2.13  
    2.14      sysctl.cmd = XEN_SYSCTL_readconsole;
    2.15      set_xen_guest_handle(sysctl.u.readconsole.buffer, buffer);
    2.16 -    sysctl.u.readconsole.count  = nr_chars;
    2.17 -    sysctl.u.readconsole.clear  = clear;
    2.18 +    sysctl.u.readconsole.count = nr_chars;
    2.19 +    sysctl.u.readconsole.clear = clear;
    2.20 +    sysctl.u.readconsole.incremental = 0;
    2.21 +    if ( pindex )
    2.22 +    {
    2.23 +        sysctl.u.readconsole.index = *pindex;
    2.24 +        sysctl.u.readconsole.incremental = incremental;
    2.25 +    }
    2.26  
    2.27      if ( (ret = lock_pages(buffer, nr_chars)) != 0 )
    2.28          return ret;
    2.29  
    2.30      if ( (ret = do_sysctl(xc_handle, &sysctl)) == 0 )
    2.31 +    {
    2.32          *pnr_chars = sysctl.u.readconsole.count;
    2.33 +        if ( pindex )
    2.34 +            *pindex = sysctl.u.readconsole.index;
    2.35 +    }
    2.36  
    2.37      unlock_pages(buffer, nr_chars);
    2.38  
     3.1 --- a/tools/libxc/xenctrl.h	Mon Oct 29 09:49:39 2007 +0000
     3.2 +++ b/tools/libxc/xenctrl.h	Mon Oct 29 12:56:27 2007 +0000
     3.3 @@ -549,7 +549,7 @@ int xc_physdev_pci_access_modify(int xc_
     3.4  int xc_readconsolering(int xc_handle,
     3.5                         char **pbuffer,
     3.6                         unsigned int *pnr_chars,
     3.7 -                       int clear);
     3.8 +                       int clear, int incremental, uint32_t *pindex);
     3.9  
    3.10  int xc_send_debug_keys(int xc_handle, char *keys);
    3.11  
     4.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Mon Oct 29 09:49:39 2007 +0000
     4.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Mon Oct 29 12:56:27 2007 +0000
     4.3 @@ -716,17 +716,19 @@ static PyObject *pyxc_readconsolering(Xc
     4.4                                        PyObject *args,
     4.5                                        PyObject *kwds)
     4.6  {
     4.7 -    unsigned int clear = 0;
     4.8 +    unsigned int clear = 0, index = 0, incremental = 0;
     4.9      char         _str[32768], *str = _str;
    4.10      unsigned int count = 32768;
    4.11      int          ret;
    4.12  
    4.13 -    static char *kwd_list[] = { "clear", NULL };
    4.14 +    static char *kwd_list[] = { "clear", "index", "incremental", NULL };
    4.15  
    4.16 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
    4.17 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwd_list,
    4.18 +                                      &clear, &index, &incremental) )
    4.19          return NULL;
    4.20  
    4.21 -    ret = xc_readconsolering(self->xc_handle, &str, &count, clear);
    4.22 +    ret = xc_readconsolering(self->xc_handle, &str, &count, clear,
    4.23 +                             incremental, &index);
    4.24      if ( ret < 0 )
    4.25          return pyxc_error_to_exception();
    4.26  
     5.1 --- a/xen/common/sysctl.c	Mon Oct 29 09:49:39 2007 +0000
     5.2 +++ b/xen/common/sysctl.c	Mon Oct 29 12:56:27 2007 +0000
     5.3 @@ -53,10 +53,7 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
     5.4          if ( ret )
     5.5              break;
     5.6  
     5.7 -        ret = read_console_ring(
     5.8 -            guest_handle_cast(op->u.readconsole.buffer, char),
     5.9 -            &op->u.readconsole.count,
    5.10 -            op->u.readconsole.clear);
    5.11 +        ret = read_console_ring(&op->u.readconsole);
    5.12          if ( copy_to_guest(u_sysctl, op, 1) )
    5.13              ret = -EFAULT;
    5.14      }
     6.1 --- a/xen/drivers/char/console.c	Mon Oct 29 09:49:39 2007 +0000
     6.2 +++ b/xen/drivers/char/console.c	Mon Oct 29 12:56:27 2007 +0000
     6.3 @@ -33,6 +33,7 @@
     6.4  #include <asm/io.h>
     6.5  #include <asm/div64.h>
     6.6  #include <xsm/xsm.h>
     6.7 +#include <public/sysctl.h>
     6.8  
     6.9  /* console: comma-separated list of console outputs. */
    6.10  static char opt_console[30] = OPT_CONSOLE_STR;
    6.11 @@ -60,7 +61,7 @@ boolean_param("console_timestamps", opt_
    6.12  #define CONRING_SIZE 16384
    6.13  #define CONRING_IDX_MASK(i) ((i)&(CONRING_SIZE-1))
    6.14  static char conring[CONRING_SIZE];
    6.15 -static unsigned int conringc, conringp;
    6.16 +static uint32_t conringc, conringp;
    6.17  
    6.18  static int sercon_handle = -1;
    6.19  
    6.20 @@ -175,20 +176,25 @@ static char * __init loglvl_str(int lvl)
    6.21  
    6.22  static void putchar_console_ring(int c)
    6.23  {
    6.24 +    ASSERT(spin_is_locked(&console_lock));
    6.25      conring[CONRING_IDX_MASK(conringp++)] = c;
    6.26 -    if ( (conringp - conringc) > CONRING_SIZE )
    6.27 +    if ( (uint32_t)(conringp - conringc) > CONRING_SIZE )
    6.28          conringc = conringp - CONRING_SIZE;
    6.29  }
    6.30  
    6.31 -long read_console_ring(XEN_GUEST_HANDLE(char) str, u32 *pcount, int clear)
    6.32 +long read_console_ring(struct xen_sysctl_readconsole *op)
    6.33  {
    6.34 -    unsigned int idx, len, max, sofar, c;
    6.35 -    unsigned long flags;
    6.36 +    XEN_GUEST_HANDLE(char) str;
    6.37 +    uint32_t idx, len, max, sofar, c;
    6.38  
    6.39 -    max   = *pcount;
    6.40 +    str   = guest_handle_cast(op->buffer, char),
    6.41 +    max   = op->count;
    6.42      sofar = 0;
    6.43  
    6.44      c = conringc;
    6.45 +    if ( op->incremental && ((int32_t)(op->index - c) < 0) )
    6.46 +        c = op->index;
    6.47 +
    6.48      while ( (c != conringp) && (sofar < max) )
    6.49      {
    6.50          idx = CONRING_IDX_MASK(c);
    6.51 @@ -203,17 +209,19 @@ long read_console_ring(XEN_GUEST_HANDLE(
    6.52          c += len;
    6.53      }
    6.54  
    6.55 -    if ( clear )
    6.56 +    if ( op->clear )
    6.57      {
    6.58 -        spin_lock_irqsave(&console_lock, flags);
    6.59 -        if ( (conringp - c) > CONRING_SIZE )
    6.60 +        spin_lock_irq(&console_lock);
    6.61 +        if ( (uint32_t)(conringp - c) > CONRING_SIZE )
    6.62              conringc = conringp - CONRING_SIZE;
    6.63          else
    6.64              conringc = c;
    6.65 -        spin_unlock_irqrestore(&console_lock, flags);
    6.66 +        spin_unlock_irq(&console_lock);
    6.67      }
    6.68  
    6.69 -    *pcount = sofar;
    6.70 +    op->count = sofar;
    6.71 +    op->index = c;
    6.72 +
    6.73      return 0;
    6.74  }
    6.75  
    6.76 @@ -333,15 +341,19 @@ static long guest_console_write(XEN_GUES
    6.77              return -EFAULT;
    6.78          kbuf[kcount] = '\0';
    6.79  
    6.80 +        spin_lock_irq(&console_lock);
    6.81 +
    6.82          sercon_puts(kbuf);
    6.83          vga_puts(kbuf);
    6.84  
    6.85          if ( opt_console_to_ring )
    6.86 +        {
    6.87              for ( kptr = kbuf; *kptr != '\0'; kptr++ )
    6.88                  putchar_console_ring(*kptr);
    6.89 +            send_guest_global_virq(dom0, VIRQ_CON_RING);
    6.90 +        }
    6.91  
    6.92 -        if ( opt_console_to_ring )
    6.93 -            send_guest_global_virq(dom0, VIRQ_CON_RING);
    6.94 +        spin_unlock_irq(&console_lock);
    6.95  
    6.96          guest_handle_add_offset(buffer, kcount);
    6.97          count -= kcount;
    6.98 @@ -408,6 +420,8 @@ static void __putstr(const char *str)
    6.99  {
   6.100      int c;
   6.101  
   6.102 +    ASSERT(spin_is_locked(&console_lock));
   6.103 +
   6.104      sercon_puts(str);
   6.105      vga_puts(str);
   6.106  
   6.107 @@ -540,7 +554,9 @@ void __init init_console(void)
   6.108      serial_set_rx_handler(sercon_handle, serial_rx);
   6.109  
   6.110      /* HELLO WORLD --- start-of-day banner text. */
   6.111 +    spin_lock(&console_lock);
   6.112      __putstr(xen_banner());
   6.113 +    spin_unlock(&console_lock);
   6.114      printk("Xen version %d.%d%s (%s@%s) (%s) %s\n",
   6.115             xen_major_version(), xen_minor_version(), xen_extra_version(),
   6.116             xen_compile_by(), xen_compile_domain(),
     7.1 --- a/xen/include/public/sysctl.h	Mon Oct 29 09:49:39 2007 +0000
     7.2 +++ b/xen/include/public/sysctl.h	Mon Oct 29 12:56:27 2007 +0000
     7.3 @@ -34,18 +34,27 @@
     7.4  #include "xen.h"
     7.5  #include "domctl.h"
     7.6  
     7.7 -#define XEN_SYSCTL_INTERFACE_VERSION 0x00000005
     7.8 +#define XEN_SYSCTL_INTERFACE_VERSION 0x00000006
     7.9  
    7.10  /*
    7.11   * Read console content from Xen buffer ring.
    7.12   */
    7.13  #define XEN_SYSCTL_readconsole       1
    7.14  struct xen_sysctl_readconsole {
    7.15 -    /* IN variables. */
    7.16 -    uint32_t clear;                /* Non-zero -> clear after reading. */
    7.17 -    XEN_GUEST_HANDLE_64(char) buffer; /* Buffer start */
    7.18 -    /* IN/OUT variables. */
    7.19 -    uint32_t count;            /* In: Buffer size;  Out: Used buffer size  */
    7.20 +    /* IN: Non-zero -> clear after reading. */
    7.21 +    uint8_t clear;
    7.22 +    /* IN: Non-zero -> start index specified by @index field. */
    7.23 +    uint8_t incremental;
    7.24 +    uint8_t pad0, pad1;
    7.25 +    /*
    7.26 +     * IN:  Start index for consuming from ring buffer (if @incremental);
    7.27 +     * OUT: End index after consuming from ring buffer.
    7.28 +     */
    7.29 +    uint32_t index; 
    7.30 +    /* IN: Virtual address to write console data. */
    7.31 +    XEN_GUEST_HANDLE_64(char) buffer;
    7.32 +    /* IN: Size of buffer; OUT: Bytes written to buffer. */
    7.33 +    uint32_t count;
    7.34  };
    7.35  typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t;
    7.36  DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t);
     8.1 --- a/xen/include/xen/console.h	Mon Oct 29 09:49:39 2007 +0000
     8.2 +++ b/xen/include/xen/console.h	Mon Oct 29 12:56:27 2007 +0000
     8.3 @@ -11,7 +11,8 @@
     8.4  #include <xen/guest_access.h>
     8.5  #include <public/xen.h>
     8.6  
     8.7 -long read_console_ring(XEN_GUEST_HANDLE(char), u32 *, int);
     8.8 +struct xen_sysctl_readconsole;
     8.9 +long read_console_ring(struct xen_sysctl_readconsole *op);
    8.10  
    8.11  void init_console(void);
    8.12  void console_endboot(void);