ia64/xen-unstable

changeset 1157:0f65f19b396c

bitkeeper revision 1.777 (404f4cb5WovysmMe80HYkFhXdVbs9A)

Rules.mk, Makefile:
Xen uses TARGET_ARCH instead of ARCH for clarity and to prevent conflict with other uses of ARCH in the environment.
xend_utils.c:
Rename: tools/xend/xend.c -> tools/xend/xend_utils.c
author kaf24@scramble.cl.cam.ac.uk
date Wed Mar 10 17:13:25 2004 +0000 (2004-03-10)
parents 1d090ba93630
children 3a610b209872 386a27cbdb84
files .rootkeys tools/xend/xend.c tools/xend/xend_utils.c xen/Makefile xen/Rules.mk
line diff
     1.1 --- a/.rootkeys	Wed Mar 10 16:17:46 2004 +0000
     1.2 +++ b/.rootkeys	Wed Mar 10 17:13:25 2004 +0000
     1.3 @@ -88,7 +88,7 @@ 3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/
     1.4  3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xc/py/XenoUtil.py
     1.5  3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
     1.6  40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
     1.7 -40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/xend.c
     1.8 +40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/xend_utils.c
     1.9  403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
    1.10  403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
    1.11  403a3edb0lzD0Fojc-NYNoXr3SYrnA tools/xentrace/xentrace_cpusplit.py
     2.1 --- a/tools/xend/xend.c	Wed Mar 10 16:17:46 2004 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,616 +0,0 @@
     2.4 -/******************************************************************************
     2.5 - * xend.c
     2.6 - * 
     2.7 - * The grand Xen daemon. For now it's just a virtual-console concentrator.
     2.8 - * 
     2.9 - * Copyright (c) 2004, K A Fraser
    2.10 - */
    2.11 -
    2.12 -#include <stdio.h>
    2.13 -#include <stdlib.h>
    2.14 -#include <string.h>
    2.15 -#include <sys/ioctl.h>
    2.16 -#include <sys/types.h>
    2.17 -#include <sys/stat.h>
    2.18 -#include <sys/socket.h>
    2.19 -#include <sys/mman.h>
    2.20 -#include <sys/poll.h>
    2.21 -#include <netinet/in.h>
    2.22 -#include <fcntl.h>
    2.23 -#include <unistd.h>
    2.24 -#include <errno.h>
    2.25 -#include <signal.h>
    2.26 -#include <xc.h>
    2.27 -#include <asm-xeno/control_if.h>
    2.28 -
    2.29 -/* NB. The following should be kept in sync with the kernel's evtchn driver. */
    2.30 -#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
    2.31 -#define EVTCHN_DEV_MAJOR 10
    2.32 -#define EVTCHN_DEV_MINOR 200
    2.33 -#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
    2.34 -#define PORT_DISCONNECT 0x8000   /* A port-disconnect notification.     */
    2.35 -#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
    2.36 -#define EVTCHN_RESET _IO('E', 1) /* Clear notification buffer. Clear errors. */
    2.37 -
    2.38 -/* Error macros. */
    2.39 -#define ERROR(_f, _a...)     \
    2.40 -    fprintf ( stderr, "ERROR: " _f "\n" , ## _a );
    2.41 -#define SYS_ERROR(_f, _a...) \
    2.42 -    fprintf ( stderr, "ERROR: " _f " [errno=%d (%s)]\n" , \
    2.43 -              ## _a , errno , strerror(errno) );
    2.44 -#define HINT(_f, _a...)      \
    2.45 -    fprintf ( stderr, "Hint: " _f "\n" , ## _a );
    2.46 -#define ROOT_HINT() HINT("You must execute this daemon as root.")
    2.47 -#define DOM0_HINT() HINT("You must execute this daemon " \
    2.48 -                         "on a privileged Xenolinux instance (e.g., DOM0).")
    2.49 -
    2.50 -#if 0
    2.51 -#define DPRINTF(_f, _a...)  \
    2.52 -    fprintf ( stdout, _f "\n" , ## _a );
    2.53 -#else
    2.54 -#define DPRINTF(_f, _a...) ((void)0)
    2.55 -#endif
    2.56 -
    2.57 -/* Per-port Tx/Rx buffering. */
    2.58 -#define CONBUFSZ 65536
    2.59 -#define MASK_CONBUF_IDX(_i) ((_i)&(CONBUFSZ-1))
    2.60 -
    2.61 -struct portinfo;
    2.62 -typedef struct portinfo {
    2.63 -    u64              dom;
    2.64 -    control_if_t    *interface;
    2.65 -    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
    2.66 -    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
    2.67 -    char            *tx_buf, *rx_buf;
    2.68 -    unsigned int     txp, txc, rxp, rxc;
    2.69 -#define CONSTAT_CLOSED    0
    2.70 -#define CONSTAT_LISTENING 1
    2.71 -#define CONSTAT_CONNECTED 2
    2.72 -    int              con_fd, con_status;
    2.73 -    struct portinfo **pprev, *next; /* links to other active ports */
    2.74 -} portinfo_t;
    2.75 -
    2.76 -#define PORT(_pinfo) ((_pinfo)-portinfo)
    2.77 -#define TX_EMPTY(_pinfo) ((_pinfo)->txp == (_pinfo)->txc)
    2.78 -#define TX_FULL(_pinfo)  (((_pinfo)->txp - (_pinfo)->txc) == CONBUFSZ)
    2.79 -#define RX_EMPTY(_pinfo) ((_pinfo)->rxp == (_pinfo)->rxc)
    2.80 -#define RX_FULL(_pinfo)  (((_pinfo)->rxp - (_pinfo)->rxc) == CONBUFSZ)
    2.81 -
    2.82 -static portinfo_t *active_head;   /* linked list of active ports */
    2.83 -static portinfo_t portinfo[1024]; /* array of all ports */    
    2.84 -static int xc_fd, evt_fd, mem_fd;
    2.85 -
    2.86 -#define PAGE_SIZE           4096 /* size of a machine page frame            */
    2.87 -#define BATCH_SIZE           512 /* maximum notifications to read at a time */
    2.88 -
    2.89 -static int make_consock_listener(portinfo_t *pinfo);
    2.90 -static int make_consock_connected(portinfo_t *pinfo);
    2.91 -static void make_consock_closed(portinfo_t *pinfo);
    2.92 -static void do_consock_read(portinfo_t *pinfo);
    2.93 -static void do_consock_write(portinfo_t *pinfo);
    2.94 -static int process_evtchn_reads(portinfo_t *pinfo);
    2.95 -static int process_evtchn_writes(portinfo_t *pinfo);
    2.96 -
    2.97 -static control_if_t *map_control_interface(int fd, unsigned long pfn)
    2.98 -{
    2.99 -    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
   2.100 -                       MAP_SHARED, fd, pfn * PAGE_SIZE);
   2.101 -    if ( vaddr == MAP_FAILED )
   2.102 -        return NULL;
   2.103 -    return (control_if_t *)(vaddr + 2048);
   2.104 -}
   2.105 -
   2.106 -static void unmap_control_interface(int fd, control_if_t *c)
   2.107 -{
   2.108 -    char *vaddr = (char *)c - 2048;
   2.109 -    (void)munmap(vaddr, PAGE_SIZE);
   2.110 -}
   2.111 -
   2.112 -/* Returns TRUE if the channel is open on exit. */
   2.113 -static int handle_channel_exception(unsigned int port)
   2.114 -{
   2.115 -    xc_dominfo_t info;
   2.116 -    unsigned int remote_port, status;
   2.117 -    u64          remote_dom;
   2.118 -    u16          wbuf;
   2.119 -    portinfo_t  *pinfo = &portinfo[port];
   2.120 -
   2.121 -    if ( xc_evtchn_status(xc_fd, DOMID_SELF, port, 
   2.122 -                          &remote_dom, &remote_port, &status) != 0 )
   2.123 -    {
   2.124 -        SYS_ERROR("Unexpected failure when obtaining port-%d status.", port);
   2.125 -        exit(1);
   2.126 -    }
   2.127 -    
   2.128 -    if ( status != EVTCHNSTAT_connected )
   2.129 -    {
   2.130 -        DPRINTF("Port %d not connected: cleaning up.", port);
   2.131 -        if ( pinfo->interface != NULL )
   2.132 -        {
   2.133 -            unmap_control_interface(mem_fd, pinfo->interface);
   2.134 -            pinfo->interface = NULL;
   2.135 -            *(pinfo->pprev) = pinfo->next;
   2.136 -            if ( pinfo->next != NULL )
   2.137 -                pinfo->next->pprev = pinfo->pprev;
   2.138 -            make_consock_closed(pinfo);
   2.139 -            free(pinfo->tx_buf);
   2.140 -            free(pinfo->rx_buf);
   2.141 -            memset(pinfo, 0, sizeof(*pinfo));
   2.142 -        }
   2.143 -        /* Cleanup sanity: we'll be the grim reaper. */
   2.144 -        wbuf = port | PORT_NORMAL;
   2.145 -        (void)write(evt_fd, &wbuf, sizeof(wbuf));
   2.146 -        wbuf = port | PORT_DISCONNECT;
   2.147 -        (void)write(evt_fd, &wbuf, sizeof(wbuf));
   2.148 -        if ( status == EVTCHNSTAT_disconnected )
   2.149 -            (void)xc_evtchn_close(xc_fd, DOMID_SELF, port);
   2.150 -        return 0;
   2.151 -    }
   2.152 -
   2.153 -    /* We only deal with initial ports (id == 0). */
   2.154 -    if ( remote_port != 0 )
   2.155 -        return 0;
   2.156 -
   2.157 -    if ( pinfo->interface == NULL )
   2.158 -    {
   2.159 -        DPRINTF("New control interface for DOM%llu on port %d.", 
   2.160 -                remote_dom, port);
   2.161 -        if ( xc_domain_getinfo(xc_fd, remote_dom, 1, &info) != 1 )
   2.162 -        {
   2.163 -            SYS_ERROR("Failed to obtain DOM%llu status.", remote_dom);
   2.164 -            exit(1);
   2.165 -        }
   2.166 -        memset(pinfo, 0, sizeof(*pinfo));
   2.167 -        pinfo->interface = 
   2.168 -            map_control_interface(mem_fd, info.shared_info_frame);
   2.169 -        pinfo->tx_buf = malloc(CONBUFSZ);
   2.170 -        pinfo->rx_buf = malloc(CONBUFSZ);
   2.171 -        pinfo->dom = remote_dom;
   2.172 -        pinfo->con_status = CONSTAT_CLOSED;
   2.173 -        if ( !make_consock_listener(pinfo) )
   2.174 -        {
   2.175 -            ERROR("Could not start console %d in listener status.",
   2.176 -                  PORT(pinfo));
   2.177 -            exit(1);
   2.178 -        }
   2.179 -        pinfo->pprev = &active_head;
   2.180 -        if ( (pinfo->next = active_head) != NULL )
   2.181 -            pinfo->next->pprev = &pinfo->next;
   2.182 -        active_head = pinfo;
   2.183 -    }
   2.184 -
   2.185 -    return 1;
   2.186 -}
   2.187 -
   2.188 -static void process_channel(unsigned int port)
   2.189 -{
   2.190 -    portinfo_t      *pinfo = &portinfo[port];
   2.191 -    u16              wbuf = port;
   2.192 -
   2.193 -    /* Acknowledge the notification. */
   2.194 -    (void)write(evt_fd, &wbuf, sizeof(wbuf));
   2.195 -
   2.196 -    /* Process requests; send notification if we updated either ring. */
   2.197 -    if ( process_evtchn_reads(pinfo) || process_evtchn_writes(pinfo) )
   2.198 -        (void)xc_evtchn_send(xc_fd, port);
   2.199 -}
   2.200 -
   2.201 -int main(int argc, char **argv)
   2.202 -{
   2.203 -    struct pollfd polls[1025]; /* one per port, plus /dev/xeno/evtchn */
   2.204 -    portinfo_t *pinfo;
   2.205 -    unsigned int batch, bytes, i, port, fd_idx;
   2.206 -    u16 buf[BATCH_SIZE];
   2.207 -
   2.208 -    /* Ignore writes to disconnected sockets. We clear up later. */
   2.209 -    (void)signal(SIGPIPE, SIG_IGN);
   2.210 -    
   2.211 -    if ( (evt_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR)) == -1 )
   2.212 -    {
   2.213 -        SYS_ERROR("Could not open '%s'", EVTCHN_DEV_NAME);
   2.214 -        ROOT_HINT();
   2.215 -        HINT("On a non-devfs system you must run 'mknod %s c %d %d'.",
   2.216 -             EVTCHN_DEV_NAME, EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR);
   2.217 -        exit(1);
   2.218 -    }
   2.219 -
   2.220 -    if ( (mem_fd = open("/dev/mem", O_RDWR)) == -1 )
   2.221 -    {
   2.222 -        SYS_ERROR("Could not open '/dev/mem'");
   2.223 -        ROOT_HINT();
   2.224 -        exit(1);
   2.225 -    }
   2.226 -
   2.227 -    if ( (xc_fd = xc_interface_open()) == -1 )
   2.228 -    {
   2.229 -        SYS_ERROR("Could not open Xen control interface");
   2.230 -        ROOT_HINT();
   2.231 -        DOM0_HINT();
   2.232 -        exit(1);
   2.233 -    }
   2.234 -
   2.235 -    for ( ; ; )
   2.236 -    {
   2.237 -        polls[0].fd     = evt_fd;
   2.238 -        polls[0].events = POLLIN;
   2.239 -
   2.240 -        fd_idx = 1;
   2.241 -        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
   2.242 -        {
   2.243 -            switch ( pinfo->con_status )
   2.244 -            {
   2.245 -            case CONSTAT_LISTENING:
   2.246 -                polls[fd_idx].fd     = pinfo->con_fd;
   2.247 -                polls[fd_idx].events = POLLIN;
   2.248 -                fd_idx++;
   2.249 -                break;
   2.250 -            case CONSTAT_CONNECTED:
   2.251 -                polls[fd_idx].fd     = pinfo->con_fd;
   2.252 -                polls[fd_idx].events = POLLIN | (RX_EMPTY(pinfo)?0:POLLOUT);
   2.253 -                fd_idx++;
   2.254 -                break;
   2.255 -            }
   2.256 -        }
   2.257 -
   2.258 -        while ( poll(polls, fd_idx, -1) == -1 )
   2.259 -        {
   2.260 -            if ( errno == EINTR )
   2.261 -                continue;
   2.262 -            SYS_ERROR("Unexpected error from poll().");
   2.263 -            exit(1);
   2.264 -        }
   2.265 -
   2.266 -        fd_idx = 1;
   2.267 -        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
   2.268 -        {
   2.269 -            switch ( pinfo->con_status )
   2.270 -            {
   2.271 -            case CONSTAT_LISTENING:
   2.272 -                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
   2.273 -                    (void)make_consock_connected(pinfo);
   2.274 -                break;
   2.275 -            case CONSTAT_CONNECTED:
   2.276 -                if ( ((polls[fd_idx].revents & POLLOUT) != 0) )
   2.277 -                    do_consock_write(pinfo);
   2.278 -                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
   2.279 -                    do_consock_read(pinfo);
   2.280 -                break;
   2.281 -            }
   2.282 -            fd_idx++;
   2.283 -        }
   2.284 -
   2.285 -        while ( (bytes = read(evt_fd, buf, sizeof(buf))) == -1 )
   2.286 -        {
   2.287 -            if ( errno == EINTR )
   2.288 -                continue;
   2.289 -            if ( errno == EAGAIN )
   2.290 -            {
   2.291 -                bytes = 0;
   2.292 -                break;
   2.293 -            }
   2.294 -            SYS_ERROR("Unexpected error while reading '%s'.", EVTCHN_DEV_NAME);
   2.295 -            exit(1);
   2.296 -        }
   2.297 -        
   2.298 -        if ( bytes == 0 )
   2.299 -            continue;
   2.300 -
   2.301 -        if ( (bytes & 1) != 0 )
   2.302 -        {
   2.303 -            ERROR("Bad read length (%d bytes) from '%s'.",
   2.304 -                  bytes, EVTCHN_DEV_NAME);
   2.305 -            exit(1);
   2.306 -        }
   2.307 -        
   2.308 -        batch = bytes / sizeof(u16);
   2.309 -        for ( i = 0; i < batch; i++ )
   2.310 -        {
   2.311 -            port = buf[i] & PORTIDX_MASK;
   2.312 -            
   2.313 -            if ( buf[i] & PORT_DISCONNECT )
   2.314 -            {
   2.315 -                DPRINTF("Disconnect on port %d.", port);
   2.316 -                (void)handle_channel_exception(port);
   2.317 -                continue;
   2.318 -            }
   2.319 -            
   2.320 -            if ( portinfo[port].interface == NULL )
   2.321 -            {
   2.322 -                DPRINTF("Unexpected notification on port %d.", port);
   2.323 -                if ( !handle_channel_exception(port) )
   2.324 -                    continue;
   2.325 -            }
   2.326 -            
   2.327 -            process_channel(port);
   2.328 -        }
   2.329 -    }
   2.330 -
   2.331 -    (void)xc_interface_close(xc_fd);
   2.332 -    (void)close(mem_fd);
   2.333 -    (void)close(evt_fd);
   2.334 -
   2.335 -    return 0;
   2.336 -}
   2.337 -
   2.338 -
   2.339 -/* Returns non-zero if console is listening on exit. */
   2.340 -static int make_consock_listener(portinfo_t *pinfo)
   2.341 -{
   2.342 -    int reuseaddr_flag = 1;
   2.343 -    struct linger linger;
   2.344 -    int tcp_port = 9600 + PORT(pinfo);
   2.345 -    int fd, flags;
   2.346 -    struct sockaddr_in sa;
   2.347 -
   2.348 -    if ( pinfo->con_status == CONSTAT_LISTENING )
   2.349 -        return 1;
   2.350 -
   2.351 -    if ( pinfo->con_status == CONSTAT_CONNECTED )
   2.352 -    {
   2.353 -        (void)close(pinfo->con_fd);
   2.354 -        pinfo->con_status = CONSTAT_CLOSED;
   2.355 -    }
   2.356 -
   2.357 -    if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
   2.358 -    {
   2.359 -        SYS_ERROR("Could not create TCP socket.");
   2.360 -        return 0;
   2.361 -    }
   2.362 -
   2.363 -    linger.l_onoff = 0;
   2.364 -    if ( (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
   2.365 -                     &reuseaddr_flag, sizeof(int)) != 0) ||
   2.366 -         (setsockopt(fd, SOL_SOCKET, SO_LINGER, 
   2.367 -                     &linger, sizeof(linger)) != 0) )
   2.368 -    {
   2.369 -        SYS_ERROR("Could not enable immediate reuse of socket port.");
   2.370 -        close(fd);
   2.371 -        return 0;
   2.372 -    }
   2.373 -
   2.374 -    sa.sin_family      = AF_INET;
   2.375 -    sa.sin_addr.s_addr = htonl(INADDR_ANY);
   2.376 -    sa.sin_port        = htons(tcp_port);
   2.377 -    if ( bind(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 )
   2.378 -    {
   2.379 -        SYS_ERROR("Unable to bind to console port %d.", tcp_port);
   2.380 -        close(fd);
   2.381 -        return 0;
   2.382 -    }
   2.383 -
   2.384 -    if ( listen(fd, 5) != 0 )
   2.385 -    {
   2.386 -        SYS_ERROR("Unable to listen on console port %d.", tcp_port);
   2.387 -        close(fd);
   2.388 -        return 0;
   2.389 -    }
   2.390 -
   2.391 -    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
   2.392 -         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
   2.393 -    {
   2.394 -        SYS_ERROR("Unable to set non-blocking status for console listener.");
   2.395 -        close(fd);
   2.396 -        return 0;
   2.397 -    }
   2.398 -
   2.399 -    pinfo->con_fd     = fd;
   2.400 -    pinfo->con_status = CONSTAT_LISTENING;
   2.401 -    return 1;
   2.402 -}
   2.403 -
   2.404 -/* Returns non-zero if console is connected on exit. */
   2.405 -static int make_consock_connected(portinfo_t *pinfo)
   2.406 -{
   2.407 -    int fd, flags, sa_len;
   2.408 -    struct linger linger;
   2.409 -    struct sockaddr_in sa;
   2.410 -
   2.411 -    if ( pinfo->con_status == CONSTAT_CONNECTED )
   2.412 -        return 1;
   2.413 -
   2.414 -    if ( pinfo->con_status == CONSTAT_CLOSED )
   2.415 -        return 0;
   2.416 -
   2.417 -    if ( (fd = accept(pinfo->con_fd, (struct sockaddr *)&sa, &sa_len)) == -1 )
   2.418 -        return 0;
   2.419 -
   2.420 -    linger.l_onoff = 0;
   2.421 -    if ( setsockopt(fd, SOL_SOCKET, SO_LINGER, 
   2.422 -                    &linger, sizeof(linger)) != 0 )
   2.423 -    {
   2.424 -        SYS_ERROR("Could not enable immediate socket death.");
   2.425 -        close(fd);
   2.426 -        return 0;
   2.427 -    }
   2.428 -
   2.429 -    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
   2.430 -         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
   2.431 -    {
   2.432 -        SYS_ERROR("Unable to set non-blocking status on socket.");
   2.433 -        close(fd);
   2.434 -        return 0;
   2.435 -    }
   2.436 -
   2.437 -    (void)close(pinfo->con_fd);
   2.438 -
   2.439 -    pinfo->con_fd     = fd;
   2.440 -    pinfo->con_status = CONSTAT_CONNECTED;
   2.441 -    return 1;
   2.442 -}
   2.443 -
   2.444 -
   2.445 -static void make_consock_closed(portinfo_t *pinfo)
   2.446 -{
   2.447 -    if ( pinfo->con_status != CONSTAT_CLOSED )
   2.448 -        (void)close(pinfo->con_fd);
   2.449 -    pinfo->con_status = CONSTAT_CLOSED;
   2.450 -}
   2.451 -
   2.452 -
   2.453 -static void do_consock_read(portinfo_t *pinfo)
   2.454 -{
   2.455 -    char buf[1024];
   2.456 -    int  idx, bytes, rc, was_empty = TX_EMPTY(pinfo);
   2.457 -
   2.458 -    while ( (rc = read(pinfo->con_fd, &buf, sizeof(buf))) > 0 )
   2.459 -    {
   2.460 -        idx = 0;
   2.461 -        while ( (rc != 0) && !TX_FULL(pinfo) )
   2.462 -        {
   2.463 -            bytes = rc;
   2.464 -            /* Clip copy to ring-buffer wrap. */
   2.465 -            if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp)) )
   2.466 -                bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp);
   2.467 -            /* Clip copy to ring-buffer overflow. */
   2.468 -            if ( bytes > (CONBUFSZ - (pinfo->txp - pinfo->txc)) )
   2.469 -                bytes = CONBUFSZ - (pinfo->txp - pinfo->txc);
   2.470 -            memcpy(&pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txp)],
   2.471 -                   &buf[idx], bytes);
   2.472 -            pinfo->txp += bytes;
   2.473 -            idx        += bytes;
   2.474 -            rc         -= bytes;
   2.475 -        }
   2.476 -    }
   2.477 -
   2.478 -    if ( (rc == 0) || (errno != EAGAIN) )
   2.479 -    {
   2.480 -        DPRINTF("Console client has disconnected.");
   2.481 -        if ( !make_consock_listener(pinfo) )
   2.482 -        {
   2.483 -            ERROR("Could not revert console %d to listener status.",
   2.484 -                  PORT(pinfo));
   2.485 -            exit(1);
   2.486 -        }
   2.487 -    }
   2.488 -
   2.489 -    if ( was_empty && !TX_EMPTY(pinfo) )
   2.490 -    {
   2.491 -        /* There is now data to transmit to guest. Kickstart the pipeline. */
   2.492 -        if ( process_evtchn_writes(pinfo) )
   2.493 -            (void)xc_evtchn_send(xc_fd, PORT(pinfo));
   2.494 -    }
   2.495 -}
   2.496 -
   2.497 -static void do_consock_write(portinfo_t *pinfo)
   2.498 -{
   2.499 -    int bytes, rc;
   2.500 -
   2.501 -    while ( !RX_EMPTY(pinfo) )
   2.502 -    {
   2.503 -        /* Clip transfer to ring-buffer wrap. */
   2.504 -        bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxc);
   2.505 -        /* Clip transfer to ring-buffer overflow. */
   2.506 -        if ( bytes > (pinfo->rxp - pinfo->rxc) )
   2.507 -            bytes = pinfo->rxp - pinfo->rxc;
   2.508 -        rc = write(pinfo->con_fd, 
   2.509 -                   &pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxc)], 
   2.510 -                   bytes);
   2.511 -        if ( rc <= 0 )
   2.512 -            return; /* Nothing to do. Errors cleaned up in reader code. */
   2.513 -        pinfo->rxc += rc;
   2.514 -    }
   2.515 -}
   2.516 -
   2.517 -static int process_evtchn_reads(portinfo_t *pinfo)
   2.518 -{
   2.519 -    CONTROL_RING_IDX c;
   2.520 -    control_if_t    *cif = pinfo->interface;
   2.521 -    control_msg_t   *cmsg;
   2.522 -    unsigned int     clen, idx, len, bytes;
   2.523 -
   2.524 -    for ( c = pinfo->tx_req_cons; 
   2.525 -          (c != cif->tx_req_prod) && 
   2.526 -              ((c-pinfo->tx_resp_prod) != CONTROL_RING_SIZE);
   2.527 -          c++ )
   2.528 -    {
   2.529 -        cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
   2.530 -
   2.531 -        if ( (clen = cmsg->length) > sizeof(cmsg->msg) )
   2.532 -            clen = sizeof(cmsg->msg);
   2.533 -
   2.534 -        if ( (cmsg->cmd_type == CMD_CONSOLE) &&
   2.535 -             (cmsg->cmd_subtype == CMD_CONSOLE_DATA) )
   2.536 -        {
   2.537 -            idx = 0;
   2.538 -            len = cmsg->length;
   2.539 -            while ( (len != 0) && !RX_FULL(pinfo) )
   2.540 -            {
   2.541 -                bytes = len;
   2.542 -                /* Clip copy to ring-buffer wrap. */
   2.543 -                if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp)) )
   2.544 -                    bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp);
   2.545 -                /* Clip copy to ring-buffer overflow. */
   2.546 -                if ( bytes > (CONBUFSZ - (pinfo->rxp - pinfo->rxc)) )
   2.547 -                    bytes = CONBUFSZ - (pinfo->rxp - pinfo->rxc);
   2.548 -                memcpy(&pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxp)],
   2.549 -                       &cmsg->msg[idx], bytes);
   2.550 -                pinfo->rxp += bytes;
   2.551 -                idx += bytes;
   2.552 -                len -= bytes;
   2.553 -            }
   2.554 -        }
   2.555 -
   2.556 -        /* Prepare response. No payload; msg type and id same as request. */
   2.557 -        cmsg->length = 0;
   2.558 -    }
   2.559 -
   2.560 -    if ( c != pinfo->tx_req_cons )
   2.561 -    {
   2.562 -        /* Update private indexes. */
   2.563 -        pinfo->tx_resp_prod = c;
   2.564 -        pinfo->tx_req_cons  = c;
   2.565 -        /* Queue responses and send a notification to the guest OS. */
   2.566 -        cif->tx_resp_prod   = c;
   2.567 -        return 1;
   2.568 -    }
   2.569 -
   2.570 -    return 0;
   2.571 -}
   2.572 -
   2.573 -static int process_evtchn_writes(portinfo_t *pinfo)
   2.574 -{
   2.575 -    CONTROL_RING_IDX p, rx_resp_prod;
   2.576 -    control_if_t    *cif = pinfo->interface;
   2.577 -    control_msg_t   *cmsg;
   2.578 -    unsigned int     bytes;
   2.579 -
   2.580 -    /* Validate the rx-response producer, an dupdate our consumer if okay. */
   2.581 -    rx_resp_prod = cif->rx_resp_prod;
   2.582 -    if ( (pinfo->rx_resp_cons != rx_resp_prod) &&
   2.583 -         ((pinfo->rx_req_prod - rx_resp_prod) <= CONTROL_RING_SIZE) &&
   2.584 -         ((rx_resp_prod - pinfo->rx_resp_cons) <= CONTROL_RING_SIZE) )
   2.585 -        pinfo->rx_resp_cons = cif->rx_resp_prod;
   2.586 -
   2.587 -    for ( p = pinfo->rx_req_prod;
   2.588 -          (p-pinfo->rx_resp_cons) != CONTROL_RING_SIZE;
   2.589 -          p++ )
   2.590 -    {
   2.591 -        if ( TX_EMPTY(pinfo) )
   2.592 -            break;
   2.593 -        cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
   2.594 -        bytes = sizeof(cmsg->msg);
   2.595 -        /* Clip transfer to ring-buffer wrap. */
   2.596 -        if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc)) )
   2.597 -            bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc);
   2.598 -        /* Clip transfer to ring-buffer overflow. */
   2.599 -        if ( bytes > (pinfo->txp - pinfo->txc) )
   2.600 -            bytes = pinfo->txp - pinfo->txc;
   2.601 -        cmsg->cmd_type    = CMD_CONSOLE;
   2.602 -        cmsg->cmd_subtype = CMD_CONSOLE_DATA;
   2.603 -        cmsg->id          = 0xaa;
   2.604 -        cmsg->length      = bytes;
   2.605 -        memcpy(&cmsg->msg[0], 
   2.606 -               &pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txc)], 
   2.607 -               bytes);
   2.608 -        pinfo->txc += bytes;
   2.609 -    }
   2.610 -
   2.611 -    if ( p != pinfo->rx_req_prod )
   2.612 -    {
   2.613 -        pinfo->rx_req_prod  = p;
   2.614 -        cif->rx_req_prod    = p;
   2.615 -        return 1;
   2.616 -    }
   2.617 -
   2.618 -    return 0;
   2.619 -}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/xend/xend_utils.c	Wed Mar 10 17:13:25 2004 +0000
     3.3 @@ -0,0 +1,616 @@
     3.4 +/******************************************************************************
     3.5 + * xend.c
     3.6 + * 
     3.7 + * The grand Xen daemon. For now it's just a virtual-console concentrator.
     3.8 + * 
     3.9 + * Copyright (c) 2004, K A Fraser
    3.10 + */
    3.11 +
    3.12 +#include <stdio.h>
    3.13 +#include <stdlib.h>
    3.14 +#include <string.h>
    3.15 +#include <sys/ioctl.h>
    3.16 +#include <sys/types.h>
    3.17 +#include <sys/stat.h>
    3.18 +#include <sys/socket.h>
    3.19 +#include <sys/mman.h>
    3.20 +#include <sys/poll.h>
    3.21 +#include <netinet/in.h>
    3.22 +#include <fcntl.h>
    3.23 +#include <unistd.h>
    3.24 +#include <errno.h>
    3.25 +#include <signal.h>
    3.26 +#include <xc.h>
    3.27 +#include <asm-xeno/control_if.h>
    3.28 +
    3.29 +/* NB. The following should be kept in sync with the kernel's evtchn driver. */
    3.30 +#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
    3.31 +#define EVTCHN_DEV_MAJOR 10
    3.32 +#define EVTCHN_DEV_MINOR 200
    3.33 +#define PORT_NORMAL     0x0000   /* A standard event notification.      */ 
    3.34 +#define PORT_DISCONNECT 0x8000   /* A port-disconnect notification.     */
    3.35 +#define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
    3.36 +#define EVTCHN_RESET _IO('E', 1) /* Clear notification buffer. Clear errors. */
    3.37 +
    3.38 +/* Error macros. */
    3.39 +#define ERROR(_f, _a...)     \
    3.40 +    fprintf ( stderr, "ERROR: " _f "\n" , ## _a );
    3.41 +#define SYS_ERROR(_f, _a...) \
    3.42 +    fprintf ( stderr, "ERROR: " _f " [errno=%d (%s)]\n" , \
    3.43 +              ## _a , errno , strerror(errno) );
    3.44 +#define HINT(_f, _a...)      \
    3.45 +    fprintf ( stderr, "Hint: " _f "\n" , ## _a );
    3.46 +#define ROOT_HINT() HINT("You must execute this daemon as root.")
    3.47 +#define DOM0_HINT() HINT("You must execute this daemon " \
    3.48 +                         "on a privileged Xenolinux instance (e.g., DOM0).")
    3.49 +
    3.50 +#if 0
    3.51 +#define DPRINTF(_f, _a...)  \
    3.52 +    fprintf ( stdout, _f "\n" , ## _a );
    3.53 +#else
    3.54 +#define DPRINTF(_f, _a...) ((void)0)
    3.55 +#endif
    3.56 +
    3.57 +/* Per-port Tx/Rx buffering. */
    3.58 +#define CONBUFSZ 65536
    3.59 +#define MASK_CONBUF_IDX(_i) ((_i)&(CONBUFSZ-1))
    3.60 +
    3.61 +struct portinfo;
    3.62 +typedef struct portinfo {
    3.63 +    u64              dom;
    3.64 +    control_if_t    *interface;
    3.65 +    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
    3.66 +    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
    3.67 +    char            *tx_buf, *rx_buf;
    3.68 +    unsigned int     txp, txc, rxp, rxc;
    3.69 +#define CONSTAT_CLOSED    0
    3.70 +#define CONSTAT_LISTENING 1
    3.71 +#define CONSTAT_CONNECTED 2
    3.72 +    int              con_fd, con_status;
    3.73 +    struct portinfo **pprev, *next; /* links to other active ports */
    3.74 +} portinfo_t;
    3.75 +
    3.76 +#define PORT(_pinfo) ((_pinfo)-portinfo)
    3.77 +#define TX_EMPTY(_pinfo) ((_pinfo)->txp == (_pinfo)->txc)
    3.78 +#define TX_FULL(_pinfo)  (((_pinfo)->txp - (_pinfo)->txc) == CONBUFSZ)
    3.79 +#define RX_EMPTY(_pinfo) ((_pinfo)->rxp == (_pinfo)->rxc)
    3.80 +#define RX_FULL(_pinfo)  (((_pinfo)->rxp - (_pinfo)->rxc) == CONBUFSZ)
    3.81 +
    3.82 +static portinfo_t *active_head;   /* linked list of active ports */
    3.83 +static portinfo_t portinfo[1024]; /* array of all ports */    
    3.84 +static int xc_fd, evt_fd, mem_fd;
    3.85 +
    3.86 +#define PAGE_SIZE           4096 /* size of a machine page frame            */
    3.87 +#define BATCH_SIZE           512 /* maximum notifications to read at a time */
    3.88 +
    3.89 +static int make_consock_listener(portinfo_t *pinfo);
    3.90 +static int make_consock_connected(portinfo_t *pinfo);
    3.91 +static void make_consock_closed(portinfo_t *pinfo);
    3.92 +static void do_consock_read(portinfo_t *pinfo);
    3.93 +static void do_consock_write(portinfo_t *pinfo);
    3.94 +static int process_evtchn_reads(portinfo_t *pinfo);
    3.95 +static int process_evtchn_writes(portinfo_t *pinfo);
    3.96 +
    3.97 +static control_if_t *map_control_interface(int fd, unsigned long pfn)
    3.98 +{
    3.99 +    char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
   3.100 +                       MAP_SHARED, fd, pfn * PAGE_SIZE);
   3.101 +    if ( vaddr == MAP_FAILED )
   3.102 +        return NULL;
   3.103 +    return (control_if_t *)(vaddr + 2048);
   3.104 +}
   3.105 +
   3.106 +static void unmap_control_interface(int fd, control_if_t *c)
   3.107 +{
   3.108 +    char *vaddr = (char *)c - 2048;
   3.109 +    (void)munmap(vaddr, PAGE_SIZE);
   3.110 +}
   3.111 +
   3.112 +/* Returns TRUE if the channel is open on exit. */
   3.113 +static int handle_channel_exception(unsigned int port)
   3.114 +{
   3.115 +    xc_dominfo_t info;
   3.116 +    unsigned int remote_port, status;
   3.117 +    u64          remote_dom;
   3.118 +    u16          wbuf;
   3.119 +    portinfo_t  *pinfo = &portinfo[port];
   3.120 +
   3.121 +    if ( xc_evtchn_status(xc_fd, DOMID_SELF, port, 
   3.122 +                          &remote_dom, &remote_port, &status) != 0 )
   3.123 +    {
   3.124 +        SYS_ERROR("Unexpected failure when obtaining port-%d status.", port);
   3.125 +        exit(1);
   3.126 +    }
   3.127 +    
   3.128 +    if ( status != EVTCHNSTAT_connected )
   3.129 +    {
   3.130 +        DPRINTF("Port %d not connected: cleaning up.", port);
   3.131 +        if ( pinfo->interface != NULL )
   3.132 +        {
   3.133 +            unmap_control_interface(mem_fd, pinfo->interface);
   3.134 +            pinfo->interface = NULL;
   3.135 +            *(pinfo->pprev) = pinfo->next;
   3.136 +            if ( pinfo->next != NULL )
   3.137 +                pinfo->next->pprev = pinfo->pprev;
   3.138 +            make_consock_closed(pinfo);
   3.139 +            free(pinfo->tx_buf);
   3.140 +            free(pinfo->rx_buf);
   3.141 +            memset(pinfo, 0, sizeof(*pinfo));
   3.142 +        }
   3.143 +        /* Cleanup sanity: we'll be the grim reaper. */
   3.144 +        wbuf = port | PORT_NORMAL;
   3.145 +        (void)write(evt_fd, &wbuf, sizeof(wbuf));
   3.146 +        wbuf = port | PORT_DISCONNECT;
   3.147 +        (void)write(evt_fd, &wbuf, sizeof(wbuf));
   3.148 +        if ( status == EVTCHNSTAT_disconnected )
   3.149 +            (void)xc_evtchn_close(xc_fd, DOMID_SELF, port);
   3.150 +        return 0;
   3.151 +    }
   3.152 +
   3.153 +    /* We only deal with initial ports (id == 0). */
   3.154 +    if ( remote_port != 0 )
   3.155 +        return 0;
   3.156 +
   3.157 +    if ( pinfo->interface == NULL )
   3.158 +    {
   3.159 +        DPRINTF("New control interface for DOM%llu on port %d.", 
   3.160 +                remote_dom, port);
   3.161 +        if ( xc_domain_getinfo(xc_fd, remote_dom, 1, &info) != 1 )
   3.162 +        {
   3.163 +            SYS_ERROR("Failed to obtain DOM%llu status.", remote_dom);
   3.164 +            exit(1);
   3.165 +        }
   3.166 +        memset(pinfo, 0, sizeof(*pinfo));
   3.167 +        pinfo->interface = 
   3.168 +            map_control_interface(mem_fd, info.shared_info_frame);
   3.169 +        pinfo->tx_buf = malloc(CONBUFSZ);
   3.170 +        pinfo->rx_buf = malloc(CONBUFSZ);
   3.171 +        pinfo->dom = remote_dom;
   3.172 +        pinfo->con_status = CONSTAT_CLOSED;
   3.173 +        if ( !make_consock_listener(pinfo) )
   3.174 +        {
   3.175 +            ERROR("Could not start console %d in listener status.",
   3.176 +                  PORT(pinfo));
   3.177 +            exit(1);
   3.178 +        }
   3.179 +        pinfo->pprev = &active_head;
   3.180 +        if ( (pinfo->next = active_head) != NULL )
   3.181 +            pinfo->next->pprev = &pinfo->next;
   3.182 +        active_head = pinfo;
   3.183 +    }
   3.184 +
   3.185 +    return 1;
   3.186 +}
   3.187 +
   3.188 +static void process_channel(unsigned int port)
   3.189 +{
   3.190 +    portinfo_t      *pinfo = &portinfo[port];
   3.191 +    u16              wbuf = port;
   3.192 +
   3.193 +    /* Acknowledge the notification. */
   3.194 +    (void)write(evt_fd, &wbuf, sizeof(wbuf));
   3.195 +
   3.196 +    /* Process requests; send notification if we updated either ring. */
   3.197 +    if ( process_evtchn_reads(pinfo) || process_evtchn_writes(pinfo) )
   3.198 +        (void)xc_evtchn_send(xc_fd, port);
   3.199 +}
   3.200 +
   3.201 +int main(int argc, char **argv)
   3.202 +{
   3.203 +    struct pollfd polls[1025]; /* one per port, plus /dev/xeno/evtchn */
   3.204 +    portinfo_t *pinfo;
   3.205 +    unsigned int batch, bytes, i, port, fd_idx;
   3.206 +    u16 buf[BATCH_SIZE];
   3.207 +
   3.208 +    /* Ignore writes to disconnected sockets. We clear up later. */
   3.209 +    (void)signal(SIGPIPE, SIG_IGN);
   3.210 +    
   3.211 +    if ( (evt_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR)) == -1 )
   3.212 +    {
   3.213 +        SYS_ERROR("Could not open '%s'", EVTCHN_DEV_NAME);
   3.214 +        ROOT_HINT();
   3.215 +        HINT("On a non-devfs system you must run 'mknod %s c %d %d'.",
   3.216 +             EVTCHN_DEV_NAME, EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR);
   3.217 +        exit(1);
   3.218 +    }
   3.219 +
   3.220 +    if ( (mem_fd = open("/dev/mem", O_RDWR)) == -1 )
   3.221 +    {
   3.222 +        SYS_ERROR("Could not open '/dev/mem'");
   3.223 +        ROOT_HINT();
   3.224 +        exit(1);
   3.225 +    }
   3.226 +
   3.227 +    if ( (xc_fd = xc_interface_open()) == -1 )
   3.228 +    {
   3.229 +        SYS_ERROR("Could not open Xen control interface");
   3.230 +        ROOT_HINT();
   3.231 +        DOM0_HINT();
   3.232 +        exit(1);
   3.233 +    }
   3.234 +
   3.235 +    for ( ; ; )
   3.236 +    {
   3.237 +        polls[0].fd     = evt_fd;
   3.238 +        polls[0].events = POLLIN;
   3.239 +
   3.240 +        fd_idx = 1;
   3.241 +        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
   3.242 +        {
   3.243 +            switch ( pinfo->con_status )
   3.244 +            {
   3.245 +            case CONSTAT_LISTENING:
   3.246 +                polls[fd_idx].fd     = pinfo->con_fd;
   3.247 +                polls[fd_idx].events = POLLIN;
   3.248 +                fd_idx++;
   3.249 +                break;
   3.250 +            case CONSTAT_CONNECTED:
   3.251 +                polls[fd_idx].fd     = pinfo->con_fd;
   3.252 +                polls[fd_idx].events = POLLIN | (RX_EMPTY(pinfo)?0:POLLOUT);
   3.253 +                fd_idx++;
   3.254 +                break;
   3.255 +            }
   3.256 +        }
   3.257 +
   3.258 +        while ( poll(polls, fd_idx, -1) == -1 )
   3.259 +        {
   3.260 +            if ( errno == EINTR )
   3.261 +                continue;
   3.262 +            SYS_ERROR("Unexpected error from poll().");
   3.263 +            exit(1);
   3.264 +        }
   3.265 +
   3.266 +        fd_idx = 1;
   3.267 +        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
   3.268 +        {
   3.269 +            switch ( pinfo->con_status )
   3.270 +            {
   3.271 +            case CONSTAT_LISTENING:
   3.272 +                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
   3.273 +                    (void)make_consock_connected(pinfo);
   3.274 +                break;
   3.275 +            case CONSTAT_CONNECTED:
   3.276 +                if ( ((polls[fd_idx].revents & POLLOUT) != 0) )
   3.277 +                    do_consock_write(pinfo);
   3.278 +                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
   3.279 +                    do_consock_read(pinfo);
   3.280 +                break;
   3.281 +            }
   3.282 +            fd_idx++;
   3.283 +        }
   3.284 +
   3.285 +        while ( (bytes = read(evt_fd, buf, sizeof(buf))) == -1 )
   3.286 +        {
   3.287 +            if ( errno == EINTR )
   3.288 +                continue;
   3.289 +            if ( errno == EAGAIN )
   3.290 +            {
   3.291 +                bytes = 0;
   3.292 +                break;
   3.293 +            }
   3.294 +            SYS_ERROR("Unexpected error while reading '%s'.", EVTCHN_DEV_NAME);
   3.295 +            exit(1);
   3.296 +        }
   3.297 +        
   3.298 +        if ( bytes == 0 )
   3.299 +            continue;
   3.300 +
   3.301 +        if ( (bytes & 1) != 0 )
   3.302 +        {
   3.303 +            ERROR("Bad read length (%d bytes) from '%s'.",
   3.304 +                  bytes, EVTCHN_DEV_NAME);
   3.305 +            exit(1);
   3.306 +        }
   3.307 +        
   3.308 +        batch = bytes / sizeof(u16);
   3.309 +        for ( i = 0; i < batch; i++ )
   3.310 +        {
   3.311 +            port = buf[i] & PORTIDX_MASK;
   3.312 +            
   3.313 +            if ( buf[i] & PORT_DISCONNECT )
   3.314 +            {
   3.315 +                DPRINTF("Disconnect on port %d.", port);
   3.316 +                (void)handle_channel_exception(port);
   3.317 +                continue;
   3.318 +            }
   3.319 +            
   3.320 +            if ( portinfo[port].interface == NULL )
   3.321 +            {
   3.322 +                DPRINTF("Unexpected notification on port %d.", port);
   3.323 +                if ( !handle_channel_exception(port) )
   3.324 +                    continue;
   3.325 +            }
   3.326 +            
   3.327 +            process_channel(port);
   3.328 +        }
   3.329 +    }
   3.330 +
   3.331 +    (void)xc_interface_close(xc_fd);
   3.332 +    (void)close(mem_fd);
   3.333 +    (void)close(evt_fd);
   3.334 +
   3.335 +    return 0;
   3.336 +}
   3.337 +
   3.338 +
   3.339 +/* Returns non-zero if console is listening on exit. */
   3.340 +static int make_consock_listener(portinfo_t *pinfo)
   3.341 +{
   3.342 +    int reuseaddr_flag = 1;
   3.343 +    struct linger linger;
   3.344 +    int tcp_port = 9600 + PORT(pinfo);
   3.345 +    int fd, flags;
   3.346 +    struct sockaddr_in sa;
   3.347 +
   3.348 +    if ( pinfo->con_status == CONSTAT_LISTENING )
   3.349 +        return 1;
   3.350 +
   3.351 +    if ( pinfo->con_status == CONSTAT_CONNECTED )
   3.352 +    {
   3.353 +        (void)close(pinfo->con_fd);
   3.354 +        pinfo->con_status = CONSTAT_CLOSED;
   3.355 +    }
   3.356 +
   3.357 +    if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
   3.358 +    {
   3.359 +        SYS_ERROR("Could not create TCP socket.");
   3.360 +        return 0;
   3.361 +    }
   3.362 +
   3.363 +    linger.l_onoff = 0;
   3.364 +    if ( (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
   3.365 +                     &reuseaddr_flag, sizeof(int)) != 0) ||
   3.366 +         (setsockopt(fd, SOL_SOCKET, SO_LINGER, 
   3.367 +                     &linger, sizeof(linger)) != 0) )
   3.368 +    {
   3.369 +        SYS_ERROR("Could not enable immediate reuse of socket port.");
   3.370 +        close(fd);
   3.371 +        return 0;
   3.372 +    }
   3.373 +
   3.374 +    sa.sin_family      = AF_INET;
   3.375 +    sa.sin_addr.s_addr = htonl(INADDR_ANY);
   3.376 +    sa.sin_port        = htons(tcp_port);
   3.377 +    if ( bind(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 )
   3.378 +    {
   3.379 +        SYS_ERROR("Unable to bind to console port %d.", tcp_port);
   3.380 +        close(fd);
   3.381 +        return 0;
   3.382 +    }
   3.383 +
   3.384 +    if ( listen(fd, 5) != 0 )
   3.385 +    {
   3.386 +        SYS_ERROR("Unable to listen on console port %d.", tcp_port);
   3.387 +        close(fd);
   3.388 +        return 0;
   3.389 +    }
   3.390 +
   3.391 +    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
   3.392 +         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
   3.393 +    {
   3.394 +        SYS_ERROR("Unable to set non-blocking status for console listener.");
   3.395 +        close(fd);
   3.396 +        return 0;
   3.397 +    }
   3.398 +
   3.399 +    pinfo->con_fd     = fd;
   3.400 +    pinfo->con_status = CONSTAT_LISTENING;
   3.401 +    return 1;
   3.402 +}
   3.403 +
   3.404 +/* Returns non-zero if console is connected on exit. */
   3.405 +static int make_consock_connected(portinfo_t *pinfo)
   3.406 +{
   3.407 +    int fd, flags, sa_len;
   3.408 +    struct linger linger;
   3.409 +    struct sockaddr_in sa;
   3.410 +
   3.411 +    if ( pinfo->con_status == CONSTAT_CONNECTED )
   3.412 +        return 1;
   3.413 +
   3.414 +    if ( pinfo->con_status == CONSTAT_CLOSED )
   3.415 +        return 0;
   3.416 +
   3.417 +    if ( (fd = accept(pinfo->con_fd, (struct sockaddr *)&sa, &sa_len)) == -1 )
   3.418 +        return 0;
   3.419 +
   3.420 +    linger.l_onoff = 0;
   3.421 +    if ( setsockopt(fd, SOL_SOCKET, SO_LINGER, 
   3.422 +                    &linger, sizeof(linger)) != 0 )
   3.423 +    {
   3.424 +        SYS_ERROR("Could not enable immediate socket death.");
   3.425 +        close(fd);
   3.426 +        return 0;
   3.427 +    }
   3.428 +
   3.429 +    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
   3.430 +         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
   3.431 +    {
   3.432 +        SYS_ERROR("Unable to set non-blocking status on socket.");
   3.433 +        close(fd);
   3.434 +        return 0;
   3.435 +    }
   3.436 +
   3.437 +    (void)close(pinfo->con_fd);
   3.438 +
   3.439 +    pinfo->con_fd     = fd;
   3.440 +    pinfo->con_status = CONSTAT_CONNECTED;
   3.441 +    return 1;
   3.442 +}
   3.443 +
   3.444 +
   3.445 +static void make_consock_closed(portinfo_t *pinfo)
   3.446 +{
   3.447 +    if ( pinfo->con_status != CONSTAT_CLOSED )
   3.448 +        (void)close(pinfo->con_fd);
   3.449 +    pinfo->con_status = CONSTAT_CLOSED;
   3.450 +}
   3.451 +
   3.452 +
   3.453 +static void do_consock_read(portinfo_t *pinfo)
   3.454 +{
   3.455 +    char buf[1024];
   3.456 +    int  idx, bytes, rc, was_empty = TX_EMPTY(pinfo);
   3.457 +
   3.458 +    while ( (rc = read(pinfo->con_fd, &buf, sizeof(buf))) > 0 )
   3.459 +    {
   3.460 +        idx = 0;
   3.461 +        while ( (rc != 0) && !TX_FULL(pinfo) )
   3.462 +        {
   3.463 +            bytes = rc;
   3.464 +            /* Clip copy to ring-buffer wrap. */
   3.465 +            if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp)) )
   3.466 +                bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp);
   3.467 +            /* Clip copy to ring-buffer overflow. */
   3.468 +            if ( bytes > (CONBUFSZ - (pinfo->txp - pinfo->txc)) )
   3.469 +                bytes = CONBUFSZ - (pinfo->txp - pinfo->txc);
   3.470 +            memcpy(&pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txp)],
   3.471 +                   &buf[idx], bytes);
   3.472 +            pinfo->txp += bytes;
   3.473 +            idx        += bytes;
   3.474 +            rc         -= bytes;
   3.475 +        }
   3.476 +    }
   3.477 +
   3.478 +    if ( (rc == 0) || (errno != EAGAIN) )
   3.479 +    {
   3.480 +        DPRINTF("Console client has disconnected.");
   3.481 +        if ( !make_consock_listener(pinfo) )
   3.482 +        {
   3.483 +            ERROR("Could not revert console %d to listener status.",
   3.484 +                  PORT(pinfo));
   3.485 +            exit(1);
   3.486 +        }
   3.487 +    }
   3.488 +
   3.489 +    if ( was_empty && !TX_EMPTY(pinfo) )
   3.490 +    {
   3.491 +        /* There is now data to transmit to guest. Kickstart the pipeline. */
   3.492 +        if ( process_evtchn_writes(pinfo) )
   3.493 +            (void)xc_evtchn_send(xc_fd, PORT(pinfo));
   3.494 +    }
   3.495 +}
   3.496 +
   3.497 +static void do_consock_write(portinfo_t *pinfo)
   3.498 +{
   3.499 +    int bytes, rc;
   3.500 +
   3.501 +    while ( !RX_EMPTY(pinfo) )
   3.502 +    {
   3.503 +        /* Clip transfer to ring-buffer wrap. */
   3.504 +        bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxc);
   3.505 +        /* Clip transfer to ring-buffer overflow. */
   3.506 +        if ( bytes > (pinfo->rxp - pinfo->rxc) )
   3.507 +            bytes = pinfo->rxp - pinfo->rxc;
   3.508 +        rc = write(pinfo->con_fd, 
   3.509 +                   &pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxc)], 
   3.510 +                   bytes);
   3.511 +        if ( rc <= 0 )
   3.512 +            return; /* Nothing to do. Errors cleaned up in reader code. */
   3.513 +        pinfo->rxc += rc;
   3.514 +    }
   3.515 +}
   3.516 +
   3.517 +static int process_evtchn_reads(portinfo_t *pinfo)
   3.518 +{
   3.519 +    CONTROL_RING_IDX c;
   3.520 +    control_if_t    *cif = pinfo->interface;
   3.521 +    control_msg_t   *cmsg;
   3.522 +    unsigned int     clen, idx, len, bytes;
   3.523 +
   3.524 +    for ( c = pinfo->tx_req_cons; 
   3.525 +          (c != cif->tx_req_prod) && 
   3.526 +              ((c-pinfo->tx_resp_prod) != CONTROL_RING_SIZE);
   3.527 +          c++ )
   3.528 +    {
   3.529 +        cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
   3.530 +
   3.531 +        if ( (clen = cmsg->length) > sizeof(cmsg->msg) )
   3.532 +            clen = sizeof(cmsg->msg);
   3.533 +
   3.534 +        if ( (cmsg->cmd_type == CMD_CONSOLE) &&
   3.535 +             (cmsg->cmd_subtype == CMD_CONSOLE_DATA) )
   3.536 +        {
   3.537 +            idx = 0;
   3.538 +            len = cmsg->length;
   3.539 +            while ( (len != 0) && !RX_FULL(pinfo) )
   3.540 +            {
   3.541 +                bytes = len;
   3.542 +                /* Clip copy to ring-buffer wrap. */
   3.543 +                if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp)) )
   3.544 +                    bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp);
   3.545 +                /* Clip copy to ring-buffer overflow. */
   3.546 +                if ( bytes > (CONBUFSZ - (pinfo->rxp - pinfo->rxc)) )
   3.547 +                    bytes = CONBUFSZ - (pinfo->rxp - pinfo->rxc);
   3.548 +                memcpy(&pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxp)],
   3.549 +                       &cmsg->msg[idx], bytes);
   3.550 +                pinfo->rxp += bytes;
   3.551 +                idx += bytes;
   3.552 +                len -= bytes;
   3.553 +            }
   3.554 +        }
   3.555 +
   3.556 +        /* Prepare response. No payload; msg type and id same as request. */
   3.557 +        cmsg->length = 0;
   3.558 +    }
   3.559 +
   3.560 +    if ( c != pinfo->tx_req_cons )
   3.561 +    {
   3.562 +        /* Update private indexes. */
   3.563 +        pinfo->tx_resp_prod = c;
   3.564 +        pinfo->tx_req_cons  = c;
   3.565 +        /* Queue responses and send a notification to the guest OS. */
   3.566 +        cif->tx_resp_prod   = c;
   3.567 +        return 1;
   3.568 +    }
   3.569 +
   3.570 +    return 0;
   3.571 +}
   3.572 +
   3.573 +static int process_evtchn_writes(portinfo_t *pinfo)
   3.574 +{
   3.575 +    CONTROL_RING_IDX p, rx_resp_prod;
   3.576 +    control_if_t    *cif = pinfo->interface;
   3.577 +    control_msg_t   *cmsg;
   3.578 +    unsigned int     bytes;
   3.579 +
   3.580 +    /* Validate the rx-response producer, an dupdate our consumer if okay. */
   3.581 +    rx_resp_prod = cif->rx_resp_prod;
   3.582 +    if ( (pinfo->rx_resp_cons != rx_resp_prod) &&
   3.583 +         ((pinfo->rx_req_prod - rx_resp_prod) <= CONTROL_RING_SIZE) &&
   3.584 +         ((rx_resp_prod - pinfo->rx_resp_cons) <= CONTROL_RING_SIZE) )
   3.585 +        pinfo->rx_resp_cons = cif->rx_resp_prod;
   3.586 +
   3.587 +    for ( p = pinfo->rx_req_prod;
   3.588 +          (p-pinfo->rx_resp_cons) != CONTROL_RING_SIZE;
   3.589 +          p++ )
   3.590 +    {
   3.591 +        if ( TX_EMPTY(pinfo) )
   3.592 +            break;
   3.593 +        cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
   3.594 +        bytes = sizeof(cmsg->msg);
   3.595 +        /* Clip transfer to ring-buffer wrap. */
   3.596 +        if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc)) )
   3.597 +            bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc);
   3.598 +        /* Clip transfer to ring-buffer overflow. */
   3.599 +        if ( bytes > (pinfo->txp - pinfo->txc) )
   3.600 +            bytes = pinfo->txp - pinfo->txc;
   3.601 +        cmsg->cmd_type    = CMD_CONSOLE;
   3.602 +        cmsg->cmd_subtype = CMD_CONSOLE_DATA;
   3.603 +        cmsg->id          = 0xaa;
   3.604 +        cmsg->length      = bytes;
   3.605 +        memcpy(&cmsg->msg[0], 
   3.606 +               &pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txc)], 
   3.607 +               bytes);
   3.608 +        pinfo->txc += bytes;
   3.609 +    }
   3.610 +
   3.611 +    if ( p != pinfo->rx_req_prod )
   3.612 +    {
   3.613 +        pinfo->rx_req_prod  = p;
   3.614 +        cif->rx_req_prod    = p;
   3.615 +        return 1;
   3.616 +    }
   3.617 +
   3.618 +    return 0;
   3.619 +}
     4.1 --- a/xen/Makefile	Wed Mar 10 16:17:46 2004 +0000
     4.2 +++ b/xen/Makefile	Wed Mar 10 17:13:25 2004 +0000
     4.3 @@ -32,7 +32,7 @@ clean: delete-links
     4.4  	$(MAKE) -C common clean
     4.5  	$(MAKE) -C net clean
     4.6  	$(MAKE) -C drivers clean
     4.7 -	$(MAKE) -C arch/$(ARCH) clean
     4.8 +	$(MAKE) -C arch/$(TARGET_ARCH) clean
     4.9  	rm -f *.o $(TARGET)* *~ core $(GENERATED_FILES)
    4.10  
    4.11  $(TARGET): delete-unfresh-files make-links $(GENERATED_FILES)
    4.12 @@ -40,11 +40,11 @@ clean: delete-links
    4.13  	$(MAKE) -C common
    4.14  	$(MAKE) -C net
    4.15  	$(MAKE) -C drivers
    4.16 -	$(MAKE) -C arch/$(ARCH)
    4.17 +	$(MAKE) -C arch/$(TARGET_ARCH)
    4.18  
    4.19  make-links: delete-links
    4.20 -	ln -sf asm-$(ARCH) include/asm
    4.21 -	ln -sf arch-$(ARCH) include/hypervisor-ifs/arch
    4.22 +	ln -sf asm-$(TARGET_ARCH) include/asm
    4.23 +	ln -sf arch-$(TARGET_ARCH) include/hypervisor-ifs/arch
    4.24  
    4.25  delete-links:
    4.26  	rm -f include/asm include/hypervisor-ifs/arch
    4.27 @@ -77,7 +77,7 @@ include/xeno/compile.h:
    4.28  
    4.29  SUBDIRS = arch common drivers net 
    4.30  TAGS: 
    4.31 -	etags `find include/asm-$(ARCH) -name '*.h'`
    4.32 +	etags `find include/asm-$(TARGET_ARCH) -name '*.h'`
    4.33  	find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a
    4.34  	find $(SUBDIRS) -name '*.[ch]' | xargs etags -a
    4.35  MAP:
     5.1 --- a/xen/Rules.mk	Wed Mar 10 16:17:46 2004 +0000
     5.2 +++ b/xen/Rules.mk	Wed Mar 10 17:13:25 2004 +0000
     5.3 @@ -1,11 +1,11 @@
     5.4 -ARCH    ?= i386
     5.5 -ARCH    := $(ARCH:i%86=i386)
     5.6 +COMPILE_ARCH := $(shell uname -m | sed -e s/i.86/i386/)
     5.7 +TARGET_ARCH  ?= $(COMPILE_ARCH)
     5.8  
     5.9  TARGET  := $(BASEDIR)/xen
    5.10  HDRS    := $(wildcard $(BASEDIR)/include/xeno/*.h)
    5.11  HDRS    += $(wildcard $(BASEDIR)/include/scsi/*.h)
    5.12  HDRS    += $(wildcard $(BASEDIR)/include/hypervisor-ifs/*.h)
    5.13 -HDRS    += $(wildcard $(BASEDIR)/include/asm-$(ARCH)/*.h)
    5.14 +HDRS    += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/*.h)
    5.15  # compile.h is always regenerated, but other files shouldn't be rebuilt
    5.16  HDRS    := $(subst $(BASEDIR)/include/xeno/compile.h,,$(HDRS))
    5.17  
    5.18 @@ -25,12 +25,12 @@ ALL_OBJS += $(BASEDIR)/drivers/cdrom/dri
    5.19  ALL_OBJS += $(BASEDIR)/drivers/ide/driver.o
    5.20  ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o
    5.21  ALL_OBJS += $(BASEDIR)/drivers/message/fusion/driver.o
    5.22 -ALL_OBJS += $(BASEDIR)/arch/$(ARCH)/arch.o
    5.23 +ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o
    5.24  
    5.25  HOSTCC     = gcc
    5.26  HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer 
    5.27  
    5.28 -include $(BASEDIR)/arch/$(ARCH)/Rules.mk
    5.29 +include $(BASEDIR)/arch/$(TARGET_ARCH)/Rules.mk
    5.30  
    5.31  %.o: %.c $(HDRS) Makefile
    5.32  	$(CC) $(CFLAGS) -c $< -o $@