ia64/xen-unstable

changeset 1138:5b6243a7571b

bitkeeper revision 1.760 (40436d00pAWlfO-5kOcLlyUpl-Vl0Q)

event_channel.c, xend.c, Makefile, xc_domain.c, xc.h:
Another point on the way to shared comms rings. The console concentrator is coming along.
author kaf24@scramble.cl.cam.ac.uk
date Mon Mar 01 17:04:00 2004 +0000 (2004-03-01)
parents 4d18dbf45e16
children 65aadb3d7e55 f8e976295167
files tools/xc/lib/xc.h tools/xc/lib/xc_domain.c tools/xend/Makefile tools/xend/xend.c xen/common/event_channel.c
line diff
     1.1 --- a/tools/xc/lib/xc.h	Mon Mar 01 11:13:22 2004 +0000
     1.2 +++ b/tools/xc/lib/xc.h	Mon Mar 01 17:04:00 2004 +0000
     1.3 @@ -28,6 +28,7 @@ typedef struct {
     1.4      int           has_cpu;
     1.5      int           stopped;
     1.6      unsigned long nr_pages;
     1.7 +    unsigned long shared_info_frame;
     1.8      u64           cpu_time;
     1.9  #define XC_DOMINFO_MAXNAME 16
    1.10      char          name[XC_DOMINFO_MAXNAME];
     2.1 --- a/tools/xc/lib/xc_domain.c	Mon Mar 01 11:13:22 2004 +0000
     2.2 +++ b/tools/xc/lib/xc_domain.c	Mon Mar 01 17:04:00 2004 +0000
     2.3 @@ -91,6 +91,7 @@ int xc_domain_getinfo(int xc_handle,
     2.4          info->has_cpu = op.u.getdomaininfo.has_cpu;
     2.5          info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
     2.6          info->nr_pages = op.u.getdomaininfo.tot_pages;
     2.7 +        info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
     2.8          info->cpu_time = op.u.getdomaininfo.cpu_time;
     2.9          strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
    2.10          info->name[XC_DOMINFO_MAXNAME-1] = '\0';
     3.1 --- a/tools/xend/Makefile	Mon Mar 01 11:13:22 2004 +0000
     3.2 +++ b/tools/xend/Makefile	Mon Mar 01 17:04:00 2004 +0000
     3.3 @@ -1,7 +1,7 @@
     3.4  
     3.5  CC       = gcc
     3.6  CFLAGS   = -Wall -O3 
     3.7 -CFLAGS  += -I../../xen/include -I../../xenolinux-sparse/include
     3.8 +CFLAGS  += -I../xc/lib
     3.9  
    3.10  HDRS     = $(wildcard *.h)
    3.11  OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
    3.12 @@ -24,7 +24,7 @@ clean:
    3.13  	$(RM) *.a *.so *.o *.rpm $(BIN)
    3.14  
    3.15  $(BIN): $(OBJS)
    3.16 -	$(CC) $(CFLAGS) -o $@ $^ -L../xc/lib -lxc
    3.17 +	$(CC) -o $@ $^ -L../xc/lib -lxc
    3.18  
    3.19  %.o: %.c $(HDRS) Makefile
    3.20  	$(CC) $(CFLAGS) -c -o $@ $<
     4.1 --- a/tools/xend/xend.c	Mon Mar 01 11:13:22 2004 +0000
     4.2 +++ b/tools/xend/xend.c	Mon Mar 01 17:04:00 2004 +0000
     4.3 @@ -1,12 +1,194 @@
     4.4  /******************************************************************************
     4.5   * xend.c
     4.6   * 
     4.7 - * The grand Xen daemon. For now it's just a console concentrator.
     4.8 + * The grand Xen daemon. For now it's just a virtual-console concentrator.
     4.9   * 
    4.10   * Copyright (c) 2004, K A Fraser
    4.11   */
    4.12  
    4.13 +#include <stdio.h>
    4.14 +#include <stdlib.h>
    4.15 +#include <string.h>
    4.16 +#include <sys/ioctl.h>
    4.17 +#include <sys/types.h>
    4.18 +#include <sys/stat.h>
    4.19 +#include <sys/socket.h>
    4.20 +#include <sys/mman.h>
    4.21 +#include <fcntl.h>
    4.22 +#include <unistd.h>
    4.23 +#include <errno.h>
    4.24 +#include <xc.h>
    4.25 +
    4.26 +/* NB. The following should be kept in sync with the kernel's evtchn driver. */
    4.27 +#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
    4.28 +#define EVTCHN_DEV_MAJOR 10
    4.29 +#define EVTCHN_DEV_MINOR 200
    4.30 +#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
    4.31 +#define PORT_DISCONNECT 0x8000   /* A port-disconnect notification.     */
    4.32 +#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
    4.33 +#define EVTCHN_RESET _IO('E', 1) /* Clear notification buffer. Clear errors. */
    4.34 +
    4.35 +/* Error macros. */
    4.36 +#define ERROR(_f, _a...)     \
    4.37 +    fprintf ( stderr, "ERROR: " _f "\n" , ## _a );
    4.38 +#define SYS_ERROR(_f, _a...) \
    4.39 +    fprintf ( stderr, "ERROR: " _f " [errno=%d (%s)]\n" , \
    4.40 +              ## _a , errno , strerror(errno) );
    4.41 +#define HINT(_f, _a...)      \
    4.42 +    fprintf ( stderr, "Hint: " _f "\n" , ## _a );
    4.43 +#define ROOT_HINT() HINT("You must execute this daemon as root.")
    4.44 +#define DOM0_HINT() HINT("You must execute this daemon " \
    4.45 +                         "on a privileged Xenolinux instance (e.g., DOM0).")
    4.46 +
    4.47 +/* The following is to be shared with guest kernels. */
    4.48 +typedef struct {
    4.49 +    u8 cmd_type;     /* echoed in response */
    4.50 +    u8 cmd_subtype;  /* echoed in response */
    4.51 +    u8 id;           /* echoed in response */
    4.52 +    u8 length;       /* number of bytes in 'msg' */
    4.53 +    unsigned char msg[60]; /* command-specific message data */
    4.54 +} control_msg_t;
    4.55 +#define CONTROL_RING_SIZE 8
    4.56 +typedef unsigned int CONTROL_RING_IDX;
    4.57 +#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
    4.58 +typedef struct {
    4.59 +    control_msg_t tx_ring[CONTROL_RING_SIZE]; /* guest -> DOM0 */
    4.60 +    control_msg_t rx_ring[CONTROL_RING_SIZE]; /* DOM0 -> guest */
    4.61 +    CONTROL_RING_IDX tx_req_prod, tx_resp_prod;
    4.62 +    CONTROL_RING_IDX rx_req_prod, rx_resp_prod;
    4.63 +} control_comms_t;
    4.64 +#define CMD_CONSOLE      0
    4.65 +#define CMD_CONSOLE_DATA 0
    4.66 +
    4.67 +#define PAGE_SHIFT 12
    4.68 +#define PAGE_SIZE  (1<<PAGE_SHIFT)
    4.69 +
    4.70 +typedef struct {
    4.71 +    u64              dom;
    4.72 +    control_comms_t *comms;
    4.73 +    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
    4.74 +    CONTROL_RING_IDX rx_req_cons, rx_resp_prod;
    4.75 +} portinfo_t;
    4.76 +
    4.77 +static portinfo_t portinfo[1024];    
    4.78 +
    4.79 +static control_comms_t *map_comms(int fd, unsigned long pfn)
    4.80 +{
    4.81 +    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
    4.82 +                       MAP_SHARED, fd, pfn << PAGE_SHIFT);
    4.83 +    if ( vaddr == MAP_FAILED )
    4.84 +        return NULL;
    4.85 +    return (control_comms_t *)(vaddr + 2048);
    4.86 +}
    4.87 +
    4.88 +static void unmap_comms(int fd, control_comms_t *c)
    4.89 +{
    4.90 +    char *vaddr = (char *)c - 2048;
    4.91 +    (void)munmap(vaddr, PAGE_SIZE);
    4.92 +}
    4.93 +
    4.94 +#define PORT_CHUNK 4
    4.95  int main(int argc, char **argv)
    4.96  {
    4.97 +    int fd, memfd, xch, chunk;
    4.98 +    unsigned int bytes, i, port, portid, status;
    4.99 +    u64 domid;
   4.100 +    u16 buf[PORT_CHUNK];
   4.101 +
   4.102 +    if ( (fd = open(EVTCHN_DEV_NAME, O_RDWR)) == -1 )
   4.103 +    {
   4.104 +        SYS_ERROR("Could not open '%s'", EVTCHN_DEV_NAME);
   4.105 +        ROOT_HINT();
   4.106 +        HINT("On a non-devfs system you must run 'mknod %s c %d %d'.",
   4.107 +             EVTCHN_DEV_NAME, EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR);
   4.108 +        exit(1);
   4.109 +    }
   4.110 +
   4.111 +    if ( (memfd = open("/dev/mem", O_RDWR)) == -1 )
   4.112 +    {
   4.113 +        SYS_ERROR("Could not open '/dev/mem'");
   4.114 +        ROOT_HINT();
   4.115 +        exit(1);
   4.116 +    }
   4.117 +
   4.118 +    if ( (xch = xc_interface_open()) == -1 )
   4.119 +    {
   4.120 +        SYS_ERROR("Could not open Xen control interface");
   4.121 +        ROOT_HINT();
   4.122 +        DOM0_HINT();
   4.123 +        exit(1);
   4.124 +    }
   4.125 +
   4.126 +    while ( (bytes = read(fd, buf, sizeof(buf))) == -1 )
   4.127 +    {
   4.128 +        if ( errno == EINTR )
   4.129 +            continue;
   4.130 +        SYS_ERROR("Unexpected error reading '%s'.", EVTCHN_DEV_NAME);
   4.131 +        exit(1);
   4.132 +    }
   4.133 +
   4.134 +    if ( (bytes == 0) || ((bytes & 1) != 0) )
   4.135 +    {
   4.136 +        ERROR("Short or bad read length (%d bytes) from '%s'.",
   4.137 +              bytes, EVTCHN_DEV_NAME);
   4.138 +        exit(1);
   4.139 +    }
   4.140 +
   4.141 +    chunk = bytes / 2;
   4.142 +    for ( i = 0; i < chunk; i++ )
   4.143 +    {
   4.144 +        port = buf[i] & PORTIDX_MASK;
   4.145 +        if ( buf[i] & PORT_DISCONNECT )
   4.146 +        {
   4.147 +            if ( portinfo[port].comms == NULL )
   4.148 +                continue;
   4.149 +            unmap_comms(memfd, portinfo[port].comms);
   4.150 +            portinfo[port].comms = NULL;
   4.151 +            (void)write(fd, &buf[i], sizeof(u16));
   4.152 +            (void)xc_evtchn_close(xch, DOMID_SELF, port);
   4.153 +        }
   4.154 +        else
   4.155 +        {
   4.156 +            if ( portinfo[port].comms == NULL )
   4.157 +            {
   4.158 +                xc_dominfo_t info;
   4.159 +                xc_evtchn_status(xch, DOMID_SELF, port, 
   4.160 +                                 &domid, &portid, &status);
   4.161 +
   4.162 +                if ( (status == EVTCHNSTAT_closed) ||
   4.163 +                     ((status == EVTCHNSTAT_disconnected) && (portid == 0)) )
   4.164 +                {
   4.165 +                    /* Cleanup sanity: we'll be the grim reaper. */
   4.166 +                    (void)write(fd, &buf[i], sizeof(u16)); /* PORT_NORMAL */
   4.167 +                    buf[i] |= PORT_DISCONNECT;
   4.168 +                    (void)write(fd, &buf[i], sizeof(u16)); /* PORT_DISCON */
   4.169 +                    continue;
   4.170 +                }
   4.171 +
   4.172 +                /* We only deal with initial ports (id == 0). */
   4.173 +                if ( portid != 0 )
   4.174 +                    continue;
   4.175 +
   4.176 +                xc_domain_getinfo(xch, domid, 1, &info);
   4.177 +                portinfo[port].comms = 
   4.178 +                    map_comms(memfd, info.shared_info_frame);
   4.179 +                portinfo[port].dom = domid;
   4.180 +                portinfo[port].tx_req_cons  = 0;
   4.181 +                portinfo[port].tx_resp_prod = 0;
   4.182 +                portinfo[port].rx_req_cons  = 0;
   4.183 +                portinfo[port].rx_resp_prod = 0;
   4.184 +            }
   4.185 +
   4.186 +            do {
   4.187 +                xc_evtchn_send(xch, port);
   4.188 +                write(fd, &buf[i], sizeof(u16));
   4.189 +            } while ( 0 );
   4.190 +        }
   4.191 +    }
   4.192 +
   4.193 +    (void)xc_interface_close(xch);
   4.194 +    (void)close(memfd);
   4.195 +    (void)close(fd);
   4.196 +
   4.197      return 0;
   4.198  }
     5.1 --- a/xen/common/event_channel.c	Mon Mar 01 11:13:22 2004 +0000
     5.2 +++ b/xen/common/event_channel.c	Mon Mar 01 17:04:00 2004 +0000
     5.3 @@ -138,6 +138,10 @@ static long event_channel_open(evtchn_op
     5.4      p2->event_channel[port2].remote_port = (u16)port1;
     5.5      p2->event_channel[port2].state       = ECS_CONNECTED;
     5.6  
     5.7 +    /* Ensure that the disconnect signal is not asserted. */
     5.8 +    clear_bit(port1, &p1->shared_info->event_channel_disc[0]);
     5.9 +    clear_bit(port2, &p2->shared_info->event_channel_disc[0]);
    5.10 +
    5.11      cpu_mask  = set_event_pending(p1, port1);
    5.12      cpu_mask |= set_event_pending(p2, port2);
    5.13      guest_event_notify(cpu_mask);