ia64/xen-unstable

changeset 1145:15b958f52da1

bitkeeper revision 1.764.1.1 (4048c0e77koAHUIwNvQFG76iV0Alrg)

evtchn.h, control_if.h:
new file
Many files:
Bidirectional consoles for domains >0. Run 'tools/xend/xend' and telnet to the port printed by xc_dom_create.py. (eg. 'telnet localhost 9600').
.del-xen_read_console.c~2a30ac556d6835c7:
Delete: tools/misc/xen_read_console.c
author kaf24@scramble.cl.cam.ac.uk
date Fri Mar 05 18:03:19 2004 +0000 (2004-03-05)
parents 030038295f0f
children 5c59473e9416
files .rootkeys tools/examples/xc_dom_create.py tools/misc/Makefile tools/misc/xen_read_console.c tools/xc/lib/xc_linux_build.c tools/xend/Makefile tools/xend/xend.c xen/arch/i386/mm.c xen/arch/i386/setup.c xen/arch/i386/smpboot.c xen/arch/i386/traps.c xen/common/event_channel.c xen/common/kernel.c xen/common/page_alloc.c xen/common/schedule.c xen/include/xeno/config.h xen/include/xeno/mm.h xenolinux-2.4.25-sparse/arch/xeno/Makefile xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c xenolinux-2.4.25-sparse/include/asm-xeno/control_if.h xenolinux-2.4.25-sparse/include/asm-xeno/evtchn.h xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h
line diff
     1.1 --- a/.rootkeys	Wed Mar 03 12:59:48 2004 +0000
     1.2 +++ b/.rootkeys	Fri Mar 05 18:03:19 2004 +0000
     1.3 @@ -64,7 +64,6 @@ 401d7e16hWEsgEnMwbPM9sKyInomWw tools/mis
     1.4  3f8bcf29ulZIC9rC4wM70H_q4s6VPg tools/misc/xen_log.c
     1.5  3f13d81eQ9Vz-h-6RDGFkNR9CRP95g tools/misc/xen_nat_enable
     1.6  3f13d81e6Z6806ihYYUw8GVKNkYnuw tools/misc/xen_nat_enable.README
     1.7 -3f1668d4F29Jsw0aC0bJEIkOBiagiQ tools/misc/xen_read_console.c
     1.8  4022a73cEKvrYe_DVZW2JlAxobg9wg tools/nsplitd/Makefile
     1.9  4022a73cKms4Oq030x2JBzUB426lAQ tools/nsplitd/nsplitd.c
    1.10  3fbca441SjQr8vJwTQIgH1laysaWog tools/xc/Makefile
    1.11 @@ -568,7 +567,9 @@ 3f108aeaLcGDgQdFAANLTUEid0a05w xenolinux
    1.12  3e5a4e66rw65CxyolW9PKz4GG42RcA xenolinux-2.4.25-sparse/drivers/char/tty_io.c
    1.13  3e5a4e669uzIE54VwucPYtGwXLAbzA xenolinux-2.4.25-sparse/fs/exec.c
    1.14  3e5a4e66wbeCpsJgVf_U8Jde-CNcsA xenolinux-2.4.25-sparse/include/asm-xeno/bugs.h
    1.15 +4048c0ddxnIa2GpBAVR-mY6mNSdeJg xenolinux-2.4.25-sparse/include/asm-xeno/control_if.h
    1.16  3e5a4e66HdSkvIV6SJ1evG_xmTmXHA xenolinux-2.4.25-sparse/include/asm-xeno/desc.h
    1.17 +4048c0e0_P2wUTiT6UqgPhn0s7yFcA xenolinux-2.4.25-sparse/include/asm-xeno/evtchn.h
    1.18  3e5a4e66SYp_UpAVcF8Lc1wa3Qtgzw xenolinux-2.4.25-sparse/include/asm-xeno/fixmap.h
    1.19  3e5a4e67w_DWgjIJ17Tlossu1LGujQ xenolinux-2.4.25-sparse/include/asm-xeno/highmem.h
    1.20  3e5a4e67YtcyDLQsShhCfQwPSELfvA xenolinux-2.4.25-sparse/include/asm-xeno/hw_irq.h
     2.1 --- a/tools/examples/xc_dom_create.py	Wed Mar 03 12:59:48 2004 +0000
     2.2 +++ b/tools/examples/xc_dom_create.py	Fri Mar 05 18:03:19 2004 +0000
     2.3 @@ -236,6 +236,12 @@ def make_domain():
     2.4              xc.domain_destroy ( dom=id )
     2.5              sys.exit()
     2.6  
     2.7 +    ports = xc.evtchn_open( dom2=id )
     2.8 +    if not ports:
     2.9 +        print "Error creating initial event channel"
    2.10 +        xc.domain_destroy ( dom=id )
    2.11 +        sys.exit()
    2.12 +
    2.13      # setup the virtual block devices
    2.14  
    2.15      # set the expertise level appropriately
    2.16 @@ -277,7 +283,7 @@ def make_domain():
    2.17          xc.domain_destroy ( dom=id )
    2.18          sys.exit()
    2.19  
    2.20 -    return id
    2.21 +    return (id, 9600+ports['port1'])
    2.22  # end of make_domain()
    2.23  
    2.24  def mkpidfile():
    2.25 @@ -305,8 +311,8 @@ def death_handler(dummy1,dummy2):
    2.26  # The starting / monitoring of the domain actually happens here...
    2.27  
    2.28  # start the domain and record its ID number
    2.29 -current_id = make_domain()
    2.30 -output("VM started in domain %d" % current_id)
    2.31 +(current_id, current_port) = make_domain()
    2.32 +output("VM started in domain %d. Console I/O available on TCP port %d." % (current_id,current_port))
    2.33  
    2.34  # if the auto_restart flag is set then keep polling to see if the domain is
    2.35  # alive - restart if it is not by calling make_domain() again (it's necessary
    2.36 @@ -337,6 +343,6 @@ if auto_restart:
    2.37  	    output("Auto-restart daemon: Domain %d has terminated, restarting VM in new domain"
    2.38                                       % current_id)
    2.39              rmpidfile()
    2.40 -	    current_id = make_domain()
    2.41 +	    (current_id, current_port) = make_domain()
    2.42              mkpidfile()
    2.43 -	    output("Auto-restart daemon: VM restarted in domain %d" % current_id)
    2.44 +	    output("Auto-restart daemon: VM restarted in domain %d. Console on port %d." % (current_id,current_port))
     3.1 --- a/tools/misc/Makefile	Wed Mar 03 12:59:48 2004 +0000
     3.2 +++ b/tools/misc/Makefile	Fri Mar 05 18:03:19 2004 +0000
     3.3 @@ -7,7 +7,7 @@ HDRS     = $(wildcard *.h)
     3.4  SRCS     = $(wildcard *.c)
     3.5  OBJS     = $(patsubst %.c,%.o,$(SRCS))
     3.6  
     3.7 -TARGETS  = xen_read_console xen_cpuperf
     3.8 +TARGETS  = xen_cpuperf
     3.9  
    3.10  INSTALL  = $(TARGETS) xen-mkdevnodes xen_nat_enable xen-clone 
    3.11  
     4.1 --- a/tools/misc/xen_read_console.c	Wed Mar 03 12:59:48 2004 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,60 +0,0 @@
     4.4 -/******************************************************************************
     4.5 - * Test program for reading console lines from DOM0 port 666.
     4.6 - */
     4.7 -
     4.8 -#include <arpa/inet.h>
     4.9 -#include <sys/types.h>
    4.10 -#include <sys/socket.h>
    4.11 -#include <stdio.h>
    4.12 -#include <stdlib.h>
    4.13 -#include <string.h>
    4.14 -
    4.15 -int main(void)
    4.16 -{
    4.17 -    unsigned char buf[208], filtered[208];
    4.18 -    struct sockaddr_in addr, from;
    4.19 -    int fromlen = sizeof(from), i, j;
    4.20 -    int len, fd = socket(PF_INET, SOCK_DGRAM, 0);
    4.21 -    
    4.22 -    if ( fd < 0 )
    4.23 -    {
    4.24 -        fprintf(stderr, "could not open datagram socket\n");
    4.25 -        return -1;
    4.26 -    }
    4.27 -
    4.28 -    memset(&addr, 0, sizeof(addr));
    4.29 -    addr.sin_addr.s_addr = htonl(0xa9fe0100); /* 169.254.1.0 */
    4.30 -    addr.sin_port = htons(666);
    4.31 -    addr.sin_family = AF_INET;
    4.32 -    if ( bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 )
    4.33 -    {
    4.34 -        fprintf(stderr, "could not bind to local address and port\n");
    4.35 -        return -1;
    4.36 -    }
    4.37 -
    4.38 -    while ( (len = recvfrom(fd, buf, sizeof(buf), 0, 
    4.39 -                            (struct sockaddr *)&from, &fromlen)) 
    4.40 -            >= 0 )
    4.41 -    {
    4.42 -#if 0
    4.43 -        unsigned char abuf[32];
    4.44 -        printf("%d-byte message from %s:%d --\n", len,
    4.45 -               inet_ntop(AF_INET, &from.sin_addr, abuf, sizeof(abuf)),
    4.46 -               ntohs(from.sin_port));
    4.47 -#endif
    4.48 -        /* For sanity, clean up the string's tail. */
    4.49 -        if ( buf[len-1] != '\n' ) { buf[len] = '\n'; len++; }
    4.50 -        buf[len] = '\0';
    4.51 -
    4.52 -        for ( i = 0, j = 0; i < len; i++ )
    4.53 -            if ( (buf[i] == '\n') || (buf[i] == '\0') ||
    4.54 -                 ((buf[i] >= 32) && (buf[i] <= 126)) )
    4.55 -                filtered[j++] = buf[i];
    4.56 -
    4.57 -        printf("[%d] %s", ntohs(from.sin_port), filtered);
    4.58 -
    4.59 -        fromlen = sizeof(from);
    4.60 -    }
    4.61 -
    4.62 -    return 0;
    4.63 -}
     5.1 --- a/tools/xc/lib/xc_linux_build.c	Wed Mar 03 12:59:48 2004 +0000
     5.2 +++ b/tools/xc/lib/xc_linux_build.c	Fri Mar 05 18:03:19 2004 +0000
     5.3 @@ -322,7 +322,7 @@ int xc_linux_build(int xc_handle,
     5.4          goto error_out;
     5.5      }
     5.6  
     5.7 -    if ( ramdisk_name != NULL )
     5.8 +    if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) )
     5.9      {
    5.10          initrd_fd = open(ramdisk_name, O_RDONLY);
    5.11          if ( initrd_fd < 0 )
     6.1 --- a/tools/xend/Makefile	Wed Mar 03 12:59:48 2004 +0000
     6.2 +++ b/tools/xend/Makefile	Fri Mar 05 18:03:19 2004 +0000
     6.3 @@ -1,7 +1,7 @@
     6.4  
     6.5  CC       = gcc
     6.6  CFLAGS   = -Wall -O3 
     6.7 -CFLAGS  += -I../xc/lib
     6.8 +CFLAGS  += -I../xc/lib -I../../xenolinux-sparse/include
     6.9  
    6.10  HDRS     = $(wildcard *.h)
    6.11  OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
     7.1 --- a/tools/xend/xend.c	Wed Mar 03 12:59:48 2004 +0000
     7.2 +++ b/tools/xend/xend.c	Fri Mar 05 18:03:19 2004 +0000
     7.3 @@ -14,10 +14,14 @@
     7.4  #include <sys/stat.h>
     7.5  #include <sys/socket.h>
     7.6  #include <sys/mman.h>
     7.7 +#include <sys/poll.h>
     7.8 +#include <netinet/in.h>
     7.9  #include <fcntl.h>
    7.10  #include <unistd.h>
    7.11  #include <errno.h>
    7.12 +#include <signal.h>
    7.13  #include <xc.h>
    7.14 +#include <asm-xeno/control_if.h>
    7.15  
    7.16  /* NB. The following should be kept in sync with the kernel's evtchn driver. */
    7.17  #define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
    7.18 @@ -40,62 +44,168 @@
    7.19  #define DOM0_HINT() HINT("You must execute this daemon " \
    7.20                           "on a privileged Xenolinux instance (e.g., DOM0).")
    7.21  
    7.22 -/* The following is to be shared with guest kernels. */
    7.23 -typedef struct {
    7.24 -    u8 cmd_type;     /* echoed in response */
    7.25 -    u8 cmd_subtype;  /* echoed in response */
    7.26 -    u8 id;           /* echoed in response */
    7.27 -    u8 length;       /* number of bytes in 'msg' */
    7.28 -    unsigned char msg[60]; /* command-specific message data */
    7.29 -} control_msg_t;
    7.30 -#define CONTROL_RING_SIZE 8
    7.31 -typedef unsigned int CONTROL_RING_IDX;
    7.32 -#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
    7.33 -typedef struct {
    7.34 -    control_msg_t tx_ring[CONTROL_RING_SIZE]; /* guest -> DOM0 */
    7.35 -    control_msg_t rx_ring[CONTROL_RING_SIZE]; /* DOM0 -> guest */
    7.36 -    CONTROL_RING_IDX tx_req_prod, tx_resp_prod;
    7.37 -    CONTROL_RING_IDX rx_req_prod, rx_resp_prod;
    7.38 -} control_comms_t;
    7.39 -#define CMD_CONSOLE      0
    7.40 -#define CMD_CONSOLE_DATA 0
    7.41 +#if 0
    7.42 +#define DPRINTF(_f, _a...)  \
    7.43 +    fprintf ( stdout, _f "\n" , ## _a );
    7.44 +#else
    7.45 +#define DPRINTF(_f, _a...) ((void)0)
    7.46 +#endif
    7.47 +
    7.48 +/* Per-port Tx/Rx buffering. */
    7.49 +#define CONBUFSZ 65536
    7.50 +#define MASK_CONBUF_IDX(_i) ((_i)&(CONBUFSZ-1))
    7.51  
    7.52 -#define PAGE_SHIFT 12
    7.53 -#define PAGE_SIZE  (1<<PAGE_SHIFT)
    7.54 -
    7.55 -typedef struct {
    7.56 +struct portinfo;
    7.57 +typedef struct portinfo {
    7.58      u64              dom;
    7.59 -    control_comms_t *comms;
    7.60 +    control_if_t    *interface;
    7.61      CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
    7.62 -    CONTROL_RING_IDX rx_req_cons, rx_resp_prod;
    7.63 +    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
    7.64 +    char            *tx_buf, *rx_buf;
    7.65 +    unsigned int     txp, txc, rxp, rxc;
    7.66 +#define CONSTAT_CLOSED    0
    7.67 +#define CONSTAT_LISTENING 1
    7.68 +#define CONSTAT_CONNECTED 2
    7.69 +    int              con_fd, con_status;
    7.70 +    struct portinfo **pprev, *next; /* links to other active ports */
    7.71  } portinfo_t;
    7.72  
    7.73 -static portinfo_t portinfo[1024];    
    7.74 +#define PORT(_pinfo) ((_pinfo)-portinfo)
    7.75 +#define TX_EMPTY(_pinfo) ((_pinfo)->txp == (_pinfo)->txc)
    7.76 +#define TX_FULL(_pinfo)  (((_pinfo)->txp - (_pinfo)->txc) == CONBUFSZ)
    7.77 +#define RX_EMPTY(_pinfo) ((_pinfo)->rxp == (_pinfo)->rxc)
    7.78 +#define RX_FULL(_pinfo)  (((_pinfo)->rxp - (_pinfo)->rxc) == CONBUFSZ)
    7.79 +
    7.80 +static portinfo_t *active_head;   /* linked list of active ports */
    7.81 +static portinfo_t portinfo[1024]; /* array of all ports */    
    7.82 +static int xc_fd, evt_fd, mem_fd;
    7.83  
    7.84 -static control_comms_t *map_comms(int fd, unsigned long pfn)
    7.85 +#define PAGE_SIZE           4096 /* size of a machine page frame            */
    7.86 +#define BATCH_SIZE           512 /* maximum notifications to read at a time */
    7.87 +
    7.88 +static int make_consock_listener(portinfo_t *pinfo);
    7.89 +static int make_consock_connected(portinfo_t *pinfo);
    7.90 +static void make_consock_closed(portinfo_t *pinfo);
    7.91 +static void do_consock_read(portinfo_t *pinfo);
    7.92 +static void do_consock_write(portinfo_t *pinfo);
    7.93 +static int process_evtchn_reads(portinfo_t *pinfo);
    7.94 +static int process_evtchn_writes(portinfo_t *pinfo);
    7.95 +
    7.96 +static control_if_t *map_control_interface(int fd, unsigned long pfn)
    7.97  {
    7.98      char *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
    7.99 -                       MAP_SHARED, fd, pfn << PAGE_SHIFT);
   7.100 +                       MAP_SHARED, fd, pfn * PAGE_SIZE);
   7.101      if ( vaddr == MAP_FAILED )
   7.102          return NULL;
   7.103 -    return (control_comms_t *)(vaddr + 2048);
   7.104 +    return (control_if_t *)(vaddr + 2048);
   7.105  }
   7.106  
   7.107 -static void unmap_comms(int fd, control_comms_t *c)
   7.108 +static void unmap_control_interface(int fd, control_if_t *c)
   7.109  {
   7.110      char *vaddr = (char *)c - 2048;
   7.111      (void)munmap(vaddr, PAGE_SIZE);
   7.112  }
   7.113  
   7.114 -#define PORT_CHUNK 4
   7.115 +/* Returns TRUE if the channel is open on exit. */
   7.116 +static int handle_channel_exception(unsigned int port)
   7.117 +{
   7.118 +    xc_dominfo_t info;
   7.119 +    unsigned int remote_port, status;
   7.120 +    u64          remote_dom;
   7.121 +    u16          wbuf;
   7.122 +    portinfo_t  *pinfo = &portinfo[port];
   7.123 +
   7.124 +    if ( xc_evtchn_status(xc_fd, DOMID_SELF, port, 
   7.125 +                          &remote_dom, &remote_port, &status) != 0 )
   7.126 +    {
   7.127 +        SYS_ERROR("Unexpected failure when obtaining port-%d status.", port);
   7.128 +        exit(1);
   7.129 +    }
   7.130 +    
   7.131 +    if ( status != EVTCHNSTAT_connected )
   7.132 +    {
   7.133 +        DPRINTF("Port %d not connected: cleaning up.", port);
   7.134 +        if ( pinfo->interface != NULL )
   7.135 +        {
   7.136 +            unmap_control_interface(mem_fd, pinfo->interface);
   7.137 +            pinfo->interface = NULL;
   7.138 +            *(pinfo->pprev) = pinfo->next;
   7.139 +            if ( pinfo->next != NULL )
   7.140 +                pinfo->next->pprev = pinfo->pprev;
   7.141 +            make_consock_closed(pinfo);
   7.142 +            free(pinfo->tx_buf);
   7.143 +            free(pinfo->rx_buf);
   7.144 +            memset(pinfo, 0, sizeof(*pinfo));
   7.145 +        }
   7.146 +        /* Cleanup sanity: we'll be the grim reaper. */
   7.147 +        wbuf = port | PORT_NORMAL;
   7.148 +        (void)write(evt_fd, &wbuf, sizeof(wbuf));
   7.149 +        wbuf = port | PORT_DISCONNECT;
   7.150 +        (void)write(evt_fd, &wbuf, sizeof(wbuf));
   7.151 +        if ( status == EVTCHNSTAT_disconnected )
   7.152 +            (void)xc_evtchn_close(xc_fd, DOMID_SELF, port);
   7.153 +        return 0;
   7.154 +    }
   7.155 +
   7.156 +    /* We only deal with initial ports (id == 0). */
   7.157 +    if ( remote_port != 0 )
   7.158 +        return 0;
   7.159 +
   7.160 +    if ( pinfo->interface == NULL )
   7.161 +    {
   7.162 +        DPRINTF("New control interface for DOM%llu on port %d.", 
   7.163 +                remote_dom, port);
   7.164 +        if ( xc_domain_getinfo(xc_fd, remote_dom, 1, &info) != 1 )
   7.165 +        {
   7.166 +            SYS_ERROR("Failed to obtain DOM%llu status.", remote_dom);
   7.167 +            exit(1);
   7.168 +        }
   7.169 +        memset(pinfo, 0, sizeof(*pinfo));
   7.170 +        pinfo->interface = 
   7.171 +            map_control_interface(mem_fd, info.shared_info_frame);
   7.172 +        pinfo->tx_buf = malloc(CONBUFSZ);
   7.173 +        pinfo->rx_buf = malloc(CONBUFSZ);
   7.174 +        pinfo->dom = remote_dom;
   7.175 +        pinfo->con_status = CONSTAT_CLOSED;
   7.176 +        if ( !make_consock_listener(pinfo) )
   7.177 +        {
   7.178 +            ERROR("Could not start console %d in listener status.",
   7.179 +                  PORT(pinfo));
   7.180 +            exit(1);
   7.181 +        }
   7.182 +        pinfo->pprev = &active_head;
   7.183 +        if ( (pinfo->next = active_head) != NULL )
   7.184 +            pinfo->next->pprev = &pinfo->next;
   7.185 +        active_head = pinfo;
   7.186 +    }
   7.187 +
   7.188 +    return 1;
   7.189 +}
   7.190 +
   7.191 +static void process_channel(unsigned int port)
   7.192 +{
   7.193 +    portinfo_t      *pinfo = &portinfo[port];
   7.194 +    u16              wbuf = port;
   7.195 +
   7.196 +    /* Acknowledge the notification. */
   7.197 +    (void)write(evt_fd, &wbuf, sizeof(wbuf));
   7.198 +
   7.199 +    /* Process requests; send notification if we updated either ring. */
   7.200 +    if ( process_evtchn_reads(pinfo) || process_evtchn_writes(pinfo) )
   7.201 +        (void)xc_evtchn_send(xc_fd, port);
   7.202 +}
   7.203 +
   7.204  int main(int argc, char **argv)
   7.205  {
   7.206 -    int fd, memfd, xch, chunk;
   7.207 -    unsigned int bytes, i, port, portid, status;
   7.208 -    u64 domid;
   7.209 -    u16 buf[PORT_CHUNK];
   7.210 +    struct pollfd polls[1025]; /* one per port, plus /dev/xeno/evtchn */
   7.211 +    portinfo_t *pinfo;
   7.212 +    unsigned int batch, bytes, i, port, fd_idx;
   7.213 +    u16 buf[BATCH_SIZE];
   7.214  
   7.215 -    if ( (fd = open(EVTCHN_DEV_NAME, O_RDWR)) == -1 )
   7.216 +    /* Ignore writes to disconnected sockets. We clear up later. */
   7.217 +    (void)signal(SIGPIPE, SIG_IGN);
   7.218 +    
   7.219 +    if ( (evt_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR)) == -1 )
   7.220      {
   7.221          SYS_ERROR("Could not open '%s'", EVTCHN_DEV_NAME);
   7.222          ROOT_HINT();
   7.223 @@ -104,14 +214,14 @@ int main(int argc, char **argv)
   7.224          exit(1);
   7.225      }
   7.226  
   7.227 -    if ( (memfd = open("/dev/mem", O_RDWR)) == -1 )
   7.228 +    if ( (mem_fd = open("/dev/mem", O_RDWR)) == -1 )
   7.229      {
   7.230          SYS_ERROR("Could not open '/dev/mem'");
   7.231          ROOT_HINT();
   7.232          exit(1);
   7.233      }
   7.234  
   7.235 -    if ( (xch = xc_interface_open()) == -1 )
   7.236 +    if ( (xc_fd = xc_interface_open()) == -1 )
   7.237      {
   7.238          SYS_ERROR("Could not open Xen control interface");
   7.239          ROOT_HINT();
   7.240 @@ -119,76 +229,388 @@ int main(int argc, char **argv)
   7.241          exit(1);
   7.242      }
   7.243  
   7.244 -    while ( (bytes = read(fd, buf, sizeof(buf))) == -1 )
   7.245 +    for ( ; ; )
   7.246      {
   7.247 -        if ( errno == EINTR )
   7.248 -            continue;
   7.249 -        SYS_ERROR("Unexpected error reading '%s'.", EVTCHN_DEV_NAME);
   7.250 -        exit(1);
   7.251 -    }
   7.252 -
   7.253 -    if ( (bytes == 0) || ((bytes & 1) != 0) )
   7.254 -    {
   7.255 -        ERROR("Short or bad read length (%d bytes) from '%s'.",
   7.256 -              bytes, EVTCHN_DEV_NAME);
   7.257 -        exit(1);
   7.258 -    }
   7.259 +        polls[0].fd     = evt_fd;
   7.260 +        polls[0].events = POLLIN;
   7.261  
   7.262 -    chunk = bytes / 2;
   7.263 -    for ( i = 0; i < chunk; i++ )
   7.264 -    {
   7.265 -        port = buf[i] & PORTIDX_MASK;
   7.266 -        if ( buf[i] & PORT_DISCONNECT )
   7.267 +        fd_idx = 1;
   7.268 +        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
   7.269          {
   7.270 -            if ( portinfo[port].comms == NULL )
   7.271 +            switch ( pinfo->con_status )
   7.272 +            {
   7.273 +            case CONSTAT_LISTENING:
   7.274 +                polls[fd_idx].fd     = pinfo->con_fd;
   7.275 +                polls[fd_idx].events = POLLIN;
   7.276 +                fd_idx++;
   7.277 +                break;
   7.278 +            case CONSTAT_CONNECTED:
   7.279 +                polls[fd_idx].fd     = pinfo->con_fd;
   7.280 +                polls[fd_idx].events = POLLIN | (RX_EMPTY(pinfo)?0:POLLOUT);
   7.281 +                fd_idx++;
   7.282 +                break;
   7.283 +            }
   7.284 +        }
   7.285 +
   7.286 +        while ( poll(polls, fd_idx, -1) == -1 )
   7.287 +        {
   7.288 +            if ( errno == EINTR )
   7.289                  continue;
   7.290 -            unmap_comms(memfd, portinfo[port].comms);
   7.291 -            portinfo[port].comms = NULL;
   7.292 -            (void)write(fd, &buf[i], sizeof(u16));
   7.293 -            (void)xc_evtchn_close(xch, DOMID_SELF, port);
   7.294 +            SYS_ERROR("Unexpected error from poll().");
   7.295 +            exit(1);
   7.296          }
   7.297 -        else
   7.298 +
   7.299 +        fd_idx = 1;
   7.300 +        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
   7.301          {
   7.302 -            if ( portinfo[port].comms == NULL )
   7.303 +            switch ( pinfo->con_status )
   7.304              {
   7.305 -                xc_dominfo_t info;
   7.306 -                xc_evtchn_status(xch, DOMID_SELF, port, 
   7.307 -                                 &domid, &portid, &status);
   7.308 -
   7.309 -                if ( (status == EVTCHNSTAT_closed) ||
   7.310 -                     ((status == EVTCHNSTAT_disconnected) && (portid == 0)) )
   7.311 -                {
   7.312 -                    /* Cleanup sanity: we'll be the grim reaper. */
   7.313 -                    (void)write(fd, &buf[i], sizeof(u16)); /* PORT_NORMAL */
   7.314 -                    buf[i] |= PORT_DISCONNECT;
   7.315 -                    (void)write(fd, &buf[i], sizeof(u16)); /* PORT_DISCON */
   7.316 -                    continue;
   7.317 -                }
   7.318 +            case CONSTAT_LISTENING:
   7.319 +                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
   7.320 +                    (void)make_consock_connected(pinfo);
   7.321 +                break;
   7.322 +            case CONSTAT_CONNECTED:
   7.323 +                if ( ((polls[fd_idx].revents & POLLOUT) != 0) )
   7.324 +                    do_consock_write(pinfo);
   7.325 +                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
   7.326 +                    do_consock_read(pinfo);
   7.327 +                break;
   7.328 +            }
   7.329 +            fd_idx++;
   7.330 +        }
   7.331  
   7.332 -                /* We only deal with initial ports (id == 0). */
   7.333 -                if ( portid != 0 )
   7.334 -                    continue;
   7.335 +        while ( (bytes = read(evt_fd, buf, sizeof(buf))) == -1 )
   7.336 +        {
   7.337 +            if ( errno == EINTR )
   7.338 +                continue;
   7.339 +            if ( errno == EAGAIN )
   7.340 +            {
   7.341 +                bytes = 0;
   7.342 +                break;
   7.343 +            }
   7.344 +            SYS_ERROR("Unexpected error while reading '%s'.", EVTCHN_DEV_NAME);
   7.345 +            exit(1);
   7.346 +        }
   7.347 +        
   7.348 +        if ( bytes == 0 )
   7.349 +            continue;
   7.350  
   7.351 -                xc_domain_getinfo(xch, domid, 1, &info);
   7.352 -                portinfo[port].comms = 
   7.353 -                    map_comms(memfd, info.shared_info_frame);
   7.354 -                portinfo[port].dom = domid;
   7.355 -                portinfo[port].tx_req_cons  = 0;
   7.356 -                portinfo[port].tx_resp_prod = 0;
   7.357 -                portinfo[port].rx_req_cons  = 0;
   7.358 -                portinfo[port].rx_resp_prod = 0;
   7.359 +        if ( (bytes & 1) != 0 )
   7.360 +        {
   7.361 +            ERROR("Bad read length (%d bytes) from '%s'.",
   7.362 +                  bytes, EVTCHN_DEV_NAME);
   7.363 +            exit(1);
   7.364 +        }
   7.365 +        
   7.366 +        batch = bytes / sizeof(u16);
   7.367 +        for ( i = 0; i < batch; i++ )
   7.368 +        {
   7.369 +            port = buf[i] & PORTIDX_MASK;
   7.370 +            
   7.371 +            if ( buf[i] & PORT_DISCONNECT )
   7.372 +            {
   7.373 +                DPRINTF("Disconnect on port %d.", port);
   7.374 +                (void)handle_channel_exception(port);
   7.375 +                continue;
   7.376              }
   7.377 -
   7.378 -            do {
   7.379 -                xc_evtchn_send(xch, port);
   7.380 -                write(fd, &buf[i], sizeof(u16));
   7.381 -            } while ( 0 );
   7.382 +            
   7.383 +            if ( portinfo[port].interface == NULL )
   7.384 +            {
   7.385 +                DPRINTF("Unexpected notification on port %d.", port);
   7.386 +                if ( !handle_channel_exception(port) )
   7.387 +                    continue;
   7.388 +            }
   7.389 +            
   7.390 +            process_channel(port);
   7.391          }
   7.392      }
   7.393  
   7.394 -    (void)xc_interface_close(xch);
   7.395 -    (void)close(memfd);
   7.396 -    (void)close(fd);
   7.397 +    (void)xc_interface_close(xc_fd);
   7.398 +    (void)close(mem_fd);
   7.399 +    (void)close(evt_fd);
   7.400  
   7.401      return 0;
   7.402  }
   7.403 +
   7.404 +
   7.405 +/* Returns non-zero if console is listening on exit. */
   7.406 +static int make_consock_listener(portinfo_t *pinfo)
   7.407 +{
   7.408 +    int reuseaddr_flag = 1;
   7.409 +    struct linger linger;
   7.410 +    int tcp_port = 9600 + PORT(pinfo);
   7.411 +    int fd, flags;
   7.412 +    struct sockaddr_in sa;
   7.413 +
   7.414 +    if ( pinfo->con_status == CONSTAT_LISTENING )
   7.415 +        return 1;
   7.416 +
   7.417 +    if ( pinfo->con_status == CONSTAT_CONNECTED )
   7.418 +    {
   7.419 +        (void)close(pinfo->con_fd);
   7.420 +        pinfo->con_status = CONSTAT_CLOSED;
   7.421 +    }
   7.422 +
   7.423 +    if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
   7.424 +    {
   7.425 +        SYS_ERROR("Could not create TCP socket.");
   7.426 +        return 0;
   7.427 +    }
   7.428 +
   7.429 +    linger.l_onoff = 0;
   7.430 +    if ( (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
   7.431 +                     &reuseaddr_flag, sizeof(int)) != 0) ||
   7.432 +         (setsockopt(fd, SOL_SOCKET, SO_LINGER, 
   7.433 +                     &linger, sizeof(linger)) != 0) )
   7.434 +    {
   7.435 +        SYS_ERROR("Could not enable immediate reuse of socket port.");
   7.436 +        close(fd);
   7.437 +        return 0;
   7.438 +    }
   7.439 +
   7.440 +    sa.sin_family      = AF_INET;
   7.441 +    sa.sin_addr.s_addr = htonl(INADDR_ANY);
   7.442 +    sa.sin_port        = htons(tcp_port);
   7.443 +    if ( bind(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 )
   7.444 +    {
   7.445 +        SYS_ERROR("Unable to bind to console port %d.", tcp_port);
   7.446 +        close(fd);
   7.447 +        return 0;
   7.448 +    }
   7.449 +
   7.450 +    if ( listen(fd, 5) != 0 )
   7.451 +    {
   7.452 +        SYS_ERROR("Unable to listen on console port %d.", tcp_port);
   7.453 +        close(fd);
   7.454 +        return 0;
   7.455 +    }
   7.456 +
   7.457 +    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
   7.458 +         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
   7.459 +    {
   7.460 +        SYS_ERROR("Unable to set non-blocking status for console listener.");
   7.461 +        close(fd);
   7.462 +        return 0;
   7.463 +    }
   7.464 +
   7.465 +    pinfo->con_fd     = fd;
   7.466 +    pinfo->con_status = CONSTAT_LISTENING;
   7.467 +    return 1;
   7.468 +}
   7.469 +
   7.470 +/* Returns non-zero if console is connected on exit. */
   7.471 +static int make_consock_connected(portinfo_t *pinfo)
   7.472 +{
   7.473 +    int fd, flags, sa_len;
   7.474 +    struct linger linger;
   7.475 +    struct sockaddr_in sa;
   7.476 +
   7.477 +    if ( pinfo->con_status == CONSTAT_CONNECTED )
   7.478 +        return 1;
   7.479 +
   7.480 +    if ( pinfo->con_status == CONSTAT_CLOSED )
   7.481 +        return 0;
   7.482 +
   7.483 +    if ( (fd = accept(pinfo->con_fd, (struct sockaddr *)&sa, &sa_len)) == -1 )
   7.484 +        return 0;
   7.485 +
   7.486 +    linger.l_onoff = 0;
   7.487 +    if ( setsockopt(fd, SOL_SOCKET, SO_LINGER, 
   7.488 +                    &linger, sizeof(linger)) != 0 )
   7.489 +    {
   7.490 +        SYS_ERROR("Could not enable immediate socket death.");
   7.491 +        close(fd);
   7.492 +        return 0;
   7.493 +    }
   7.494 +
   7.495 +    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
   7.496 +         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
   7.497 +    {
   7.498 +        SYS_ERROR("Unable to set non-blocking status on socket.");
   7.499 +        close(fd);
   7.500 +        return 0;
   7.501 +    }
   7.502 +
   7.503 +    (void)close(pinfo->con_fd);
   7.504 +
   7.505 +    pinfo->con_fd     = fd;
   7.506 +    pinfo->con_status = CONSTAT_CONNECTED;
   7.507 +    return 1;
   7.508 +}
   7.509 +
   7.510 +
   7.511 +static void make_consock_closed(portinfo_t *pinfo)
   7.512 +{
   7.513 +    if ( pinfo->con_status != CONSTAT_CLOSED )
   7.514 +        (void)close(pinfo->con_fd);
   7.515 +    pinfo->con_status = CONSTAT_CLOSED;
   7.516 +}
   7.517 +
   7.518 +
   7.519 +static void do_consock_read(portinfo_t *pinfo)
   7.520 +{
   7.521 +    char buf[1024];
   7.522 +    int  idx, bytes, rc, was_empty = TX_EMPTY(pinfo);
   7.523 +
   7.524 +    while ( (rc = read(pinfo->con_fd, &buf, sizeof(buf))) > 0 )
   7.525 +    {
   7.526 +        idx = 0;
   7.527 +        while ( (rc != 0) && !TX_FULL(pinfo) )
   7.528 +        {
   7.529 +            bytes = rc;
   7.530 +            /* Clip copy to ring-buffer wrap. */
   7.531 +            if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp)) )
   7.532 +                bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp);
   7.533 +            /* Clip copy to ring-buffer overflow. */
   7.534 +            if ( bytes > (CONBUFSZ - (pinfo->txp - pinfo->txc)) )
   7.535 +                bytes = CONBUFSZ - (pinfo->txp - pinfo->txc);
   7.536 +            memcpy(&pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txp)],
   7.537 +                   &buf[idx], bytes);
   7.538 +            pinfo->txp += bytes;
   7.539 +            idx        += bytes;
   7.540 +            rc         -= bytes;
   7.541 +        }
   7.542 +    }
   7.543 +
   7.544 +    if ( (rc == 0) || (errno != EAGAIN) )
   7.545 +    {
   7.546 +        DPRINTF("Console client has disconnected.");
   7.547 +        if ( !make_consock_listener(pinfo) )
   7.548 +        {
   7.549 +            ERROR("Could not revert console %d to listener status.",
   7.550 +                  PORT(pinfo));
   7.551 +            exit(1);
   7.552 +        }
   7.553 +    }
   7.554 +
   7.555 +    if ( was_empty && !TX_EMPTY(pinfo) )
   7.556 +    {
   7.557 +        /* There is now data to transmit to guest. Kickstart the pipeline. */
   7.558 +        if ( process_evtchn_writes(pinfo) )
   7.559 +            (void)xc_evtchn_send(xc_fd, PORT(pinfo));
   7.560 +    }
   7.561 +}
   7.562 +
   7.563 +static void do_consock_write(portinfo_t *pinfo)
   7.564 +{
   7.565 +    int bytes, rc;
   7.566 +
   7.567 +    while ( !RX_EMPTY(pinfo) )
   7.568 +    {
   7.569 +        /* Clip transfer to ring-buffer wrap. */
   7.570 +        bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxc);
   7.571 +        /* Clip transfer to ring-buffer overflow. */
   7.572 +        if ( bytes > (pinfo->rxp - pinfo->rxc) )
   7.573 +            bytes = pinfo->rxp - pinfo->rxc;
   7.574 +        rc = write(pinfo->con_fd, 
   7.575 +                   &pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxc)], 
   7.576 +                   bytes);
   7.577 +        if ( rc <= 0 )
   7.578 +            return; /* Nothing to do. Errors cleaned up in reader code. */
   7.579 +        pinfo->rxc += rc;
   7.580 +    }
   7.581 +}
   7.582 +
   7.583 +static int process_evtchn_reads(portinfo_t *pinfo)
   7.584 +{
   7.585 +    CONTROL_RING_IDX c;
   7.586 +    control_if_t    *cif = pinfo->interface;
   7.587 +    control_msg_t   *cmsg;
   7.588 +    unsigned int     clen, idx, len, bytes;
   7.589 +
   7.590 +    for ( c = pinfo->tx_req_cons; 
   7.591 +          (c != cif->tx_req_prod) && 
   7.592 +              ((c-pinfo->tx_resp_prod) != CONTROL_RING_SIZE);
   7.593 +          c++ )
   7.594 +    {
   7.595 +        cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
   7.596 +
   7.597 +        if ( (clen = cmsg->length) > sizeof(cmsg->msg) )
   7.598 +            clen = sizeof(cmsg->msg);
   7.599 +
   7.600 +        if ( (cmsg->cmd_type == CMD_CONSOLE) &&
   7.601 +             (cmsg->cmd_subtype == CMD_CONSOLE_DATA) )
   7.602 +        {
   7.603 +            idx = 0;
   7.604 +            len = cmsg->length;
   7.605 +            while ( (len != 0) && !RX_FULL(pinfo) )
   7.606 +            {
   7.607 +                bytes = len;
   7.608 +                /* Clip copy to ring-buffer wrap. */
   7.609 +                if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp)) )
   7.610 +                    bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp);
   7.611 +                /* Clip copy to ring-buffer overflow. */
   7.612 +                if ( bytes > (CONBUFSZ - (pinfo->rxp - pinfo->rxc)) )
   7.613 +                    bytes = CONBUFSZ - (pinfo->rxp - pinfo->rxc);
   7.614 +                memcpy(&pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxp)],
   7.615 +                       &cmsg->msg[idx], bytes);
   7.616 +                pinfo->rxp += bytes;
   7.617 +                idx += bytes;
   7.618 +                len -= bytes;
   7.619 +            }
   7.620 +        }
   7.621 +
   7.622 +        /* Prepare response. No payload; msg type and id same as request. */
   7.623 +        cmsg->length = 0;
   7.624 +    }
   7.625 +
   7.626 +    if ( c != pinfo->tx_req_cons )
   7.627 +    {
   7.628 +        /* Update private indexes. */
   7.629 +        pinfo->tx_resp_prod = c;
   7.630 +        pinfo->tx_req_cons  = c;
   7.631 +        /* Queue responses and send a notification to the guest OS. */
   7.632 +        cif->tx_resp_prod   = c;
   7.633 +        return 1;
   7.634 +    }
   7.635 +
   7.636 +    return 0;
   7.637 +}
   7.638 +
   7.639 +static int process_evtchn_writes(portinfo_t *pinfo)
   7.640 +{
   7.641 +    CONTROL_RING_IDX p, rx_resp_prod;
   7.642 +    control_if_t    *cif = pinfo->interface;
   7.643 +    control_msg_t   *cmsg;
   7.644 +    unsigned int     bytes;
   7.645 +
   7.646 +    /* Validate the rx-response producer, an dupdate our consumer if okay. */
   7.647 +    rx_resp_prod = cif->rx_resp_prod;
   7.648 +    if ( (pinfo->rx_resp_cons != rx_resp_prod) &&
   7.649 +         ((pinfo->rx_req_prod - rx_resp_prod) <= CONTROL_RING_SIZE) &&
   7.650 +         ((rx_resp_prod - pinfo->rx_resp_cons) <= CONTROL_RING_SIZE) )
   7.651 +        pinfo->rx_resp_cons = cif->rx_resp_prod;
   7.652 +
   7.653 +    for ( p = pinfo->rx_req_prod;
   7.654 +          (p-pinfo->rx_resp_cons) != CONTROL_RING_SIZE;
   7.655 +          p++ )
   7.656 +    {
   7.657 +        if ( TX_EMPTY(pinfo) )
   7.658 +            break;
   7.659 +        cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
   7.660 +        bytes = sizeof(cmsg->msg);
   7.661 +        /* Clip transfer to ring-buffer wrap. */
   7.662 +        if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc)) )
   7.663 +            bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc);
   7.664 +        /* Clip transfer to ring-buffer overflow. */
   7.665 +        if ( bytes > (pinfo->txp - pinfo->txc) )
   7.666 +            bytes = pinfo->txp - pinfo->txc;
   7.667 +        cmsg->cmd_type    = CMD_CONSOLE;
   7.668 +        cmsg->cmd_subtype = CMD_CONSOLE_DATA;
   7.669 +        cmsg->id          = 0xaa;
   7.670 +        cmsg->length      = bytes;
   7.671 +        memcpy(&cmsg->msg[0], 
   7.672 +               &pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txc)], 
   7.673 +               bytes);
   7.674 +        pinfo->txc += bytes;
   7.675 +    }
   7.676 +
   7.677 +    if ( p != pinfo->rx_req_prod )
   7.678 +    {
   7.679 +        pinfo->rx_req_prod  = p;
   7.680 +        cif->rx_req_prod    = p;
   7.681 +        return 1;
   7.682 +    }
   7.683 +
   7.684 +    return 0;
   7.685 +}
     8.1 --- a/xen/arch/i386/mm.c	Wed Mar 03 12:59:48 2004 +0000
     8.2 +++ b/xen/arch/i386/mm.c	Fri Mar 05 18:03:19 2004 +0000
     8.3 @@ -327,3 +327,79 @@ long do_update_descriptor(
     8.4      put_page(page);
     8.5      return ret;
     8.6  }
     8.7 +
     8.8 +#ifdef MEMORY_GUARD
     8.9 +
    8.10 +void *memguard_init(void *heap_start)
    8.11 +{
    8.12 +    l1_pgentry_t *l1;
    8.13 +    int i, j;
    8.14 +
    8.15 +    /* Round the allocation pointer up to a page boundary. */
    8.16 +    heap_start = (void *)(((unsigned long)heap_start + (PAGE_SIZE-1)) & 
    8.17 +                          PAGE_MASK);
    8.18 +
    8.19 +    /* Memory guarding is incompatible with super pages. */
    8.20 +    for ( i = 0; i < (MAX_MONITOR_ADDRESS >> L2_PAGETABLE_SHIFT); i++ )
    8.21 +    {
    8.22 +        l1 = (l1_pgentry_t *)heap_start;
    8.23 +        heap_start = (void *)((unsigned long)heap_start + PAGE_SIZE);
    8.24 +        for ( j = 0; j < ENTRIES_PER_L1_PAGETABLE; j++ )
    8.25 +            l1[j] = mk_l1_pgentry((i << L2_PAGETABLE_SHIFT) |
    8.26 +                                   (j << L1_PAGETABLE_SHIFT) | 
    8.27 +                                  __PAGE_HYPERVISOR);
    8.28 +        idle_pg_table[i] = idle_pg_table[i + l2_table_offset(PAGE_OFFSET)] =
    8.29 +            mk_l2_pgentry(virt_to_phys(l1) | __PAGE_HYPERVISOR);
    8.30 +    }
    8.31 +
    8.32 +    return heap_start;
    8.33 +}
    8.34 +
    8.35 +static void __memguard_change_range(void *p, unsigned long l, int guard)
    8.36 +{
    8.37 +    l1_pgentry_t *l1;
    8.38 +    l2_pgentry_t *l2;
    8.39 +    unsigned long _p = (unsigned long)p;
    8.40 +    unsigned long _l = (unsigned long)l;
    8.41 +
    8.42 +    /* Ensure we are dealing with a page-aligned whole number of pages. */
    8.43 +    ASSERT((_p&PAGE_MASK) != 0);
    8.44 +    ASSERT((_l&PAGE_MASK) != 0);
    8.45 +    ASSERT((_p&~PAGE_MASK) == 0);
    8.46 +    ASSERT((_l&~PAGE_MASK) == 0);
    8.47 +
    8.48 +    while ( _l != 0 )
    8.49 +    {
    8.50 +        l2  = &idle_pg_table[l2_table_offset(_p)];
    8.51 +        l1  = l2_pgentry_to_l1(*l2) + l1_table_offset(_p);
    8.52 +        if ( guard )
    8.53 +            *l1 = mk_l1_pgentry(l1_pgentry_val(*l1) & ~_PAGE_PRESENT);
    8.54 +        else
    8.55 +            *l1 = mk_l1_pgentry(l1_pgentry_val(*l1) | _PAGE_PRESENT);
    8.56 +        _p += PAGE_SIZE;
    8.57 +        _l -= PAGE_SIZE;
    8.58 +    }
    8.59 +}
    8.60 +
    8.61 +void memguard_guard_range(void *p, unsigned long l)
    8.62 +{
    8.63 +    __memguard_change_range(p, l, 1);
    8.64 +    local_flush_tlb();
    8.65 +}
    8.66 +
    8.67 +void memguard_unguard_range(void *p, unsigned long l)
    8.68 +{
    8.69 +    __memguard_change_range(p, l, 0);
    8.70 +}
    8.71 +
    8.72 +int memguard_is_guarded(void *p)
    8.73 +{
    8.74 +    l1_pgentry_t *l1;
    8.75 +    l2_pgentry_t *l2;
    8.76 +    unsigned long _p = (unsigned long)p;
    8.77 +    l2  = &idle_pg_table[l2_table_offset(_p)];
    8.78 +    l1  = l2_pgentry_to_l1(*l2) + l1_table_offset(_p);
    8.79 +    return !(l1_pgentry_val(*l1) & _PAGE_PRESENT);
    8.80 +}
    8.81 +
    8.82 +#endif
     9.1 --- a/xen/arch/i386/setup.c	Wed Mar 03 12:59:48 2004 +0000
     9.2 +++ b/xen/arch/i386/setup.c	Fri Mar 05 18:03:19 2004 +0000
     9.3 @@ -323,29 +323,9 @@ void __init start_of_day(void)
     9.4      extern int do_timer_lists_from_pit;
     9.5      unsigned long low_mem_size;
     9.6      
     9.7 -#ifdef STACK_GUARD
     9.8 +    /* Unmap the first page of CPU0's stack. */
     9.9      extern unsigned long cpu0_stack[];
    9.10 -    l1_pgentry_t *l1;
    9.11 -    l2_pgentry_t *l2;
    9.12 -    int i, j;
    9.13 -
    9.14 -    /* When stack-guarding, Xen's heap cannot be mapped by super pages. */
    9.15 -    for ( i = 0; i < (MAX_MONITOR_ADDRESS >> L2_PAGETABLE_SHIFT); i++ )
    9.16 -    {
    9.17 -        l1 = (l1_pgentry_t *)get_free_page(GFP_KERNEL);
    9.18 -        for ( j = 0; j < ENTRIES_PER_L1_PAGETABLE; j++ )
    9.19 -            l1[j] = mk_l1_pgentry((i << L2_PAGETABLE_SHIFT) |
    9.20 -                                   (j << L1_PAGETABLE_SHIFT) | 
    9.21 -                                   PAGE_HYPERVISOR);
    9.22 -        idle_pg_table[i] = idle_pg_table[i + l2_table_offset(PAGE_OFFSET)] =
    9.23 -            mk_l2_pgentry(virt_to_phys(l1) | PAGE_HYPERVISOR);
    9.24 -    }
    9.25 -
    9.26 -    /* Unmap the first page of CPU0's stack. */
    9.27 -    l2  = &idle_pg_table[l2_table_offset(virt_to_phys(cpu0_stack))];
    9.28 -    l1  = l2_pgentry_to_l1(*l2) + l1_table_offset(virt_to_phys(cpu0_stack));
    9.29 -    *l1 = mk_l1_pgentry(0);
    9.30 -#endif
    9.31 +    memguard_guard_range(cpu0_stack, PAGE_SIZE);
    9.32  
    9.33      if ( opt_watchdog ) 
    9.34          nmi_watchdog = NMI_LOCAL_APIC;
    10.1 --- a/xen/arch/i386/smpboot.c	Wed Mar 03 12:59:48 2004 +0000
    10.2 +++ b/xen/arch/i386/smpboot.c	Fri Mar 05 18:03:19 2004 +0000
    10.3 @@ -691,16 +691,11 @@ static void __init do_boot_cpu (int apic
    10.4      printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
    10.5  
    10.6      stack = __pa(__get_free_pages(GFP_KERNEL, 1));
    10.7 -#ifdef STACK_GUARD
    10.8 -    {
    10.9 -        /* Unmap the first page of the new CPU0's stack. */
   10.10 -        l2_pgentry_t *l2  = &idle_pg_table[l2_table_offset(stack)];
   10.11 -        l1_pgentry_t *l1  = l2_pgentry_to_l1(*l2) + l1_table_offset(stack);
   10.12 -        *l1 = mk_l1_pgentry(0);
   10.13 -    }
   10.14 -#endif
   10.15      stack_start.esp = stack + STACK_SIZE - STACK_RESERVED;
   10.16  
   10.17 +    /* Debug build: detect stack overflow by setting up a guard page. */
   10.18 +    memguard_guard_range(__va(stack), PAGE_SIZE);
   10.19 +
   10.20      /*
   10.21       * This grunge runs the startup process for
   10.22       * the targeted processor.
    11.1 --- a/xen/arch/i386/traps.c	Wed Mar 03 12:59:48 2004 +0000
    11.2 +++ b/xen/arch/i386/traps.c	Fri Mar 05 18:03:19 2004 +0000
    11.3 @@ -370,6 +370,10 @@ asmlinkage void do_page_fault(struct pt_
    11.4              page = ((unsigned long *) __va(page))[(addr&0x3ff000)>>PAGE_SHIFT];
    11.5              printk(" *pte = %08lx\n", page);
    11.6          }
    11.7 +#ifdef MEMORY_GUARD
    11.8 +        if ( !(error_code & 1) )
    11.9 +            printk(" -- POSSIBLY AN ACCESS TO FREED MEMORY? --\n");
   11.10 +#endif
   11.11      }
   11.12  
   11.13      show_registers(regs);
    12.1 --- a/xen/common/event_channel.c	Wed Mar 03 12:59:48 2004 +0000
    12.2 +++ b/xen/common/event_channel.c	Fri Mar 05 18:03:19 2004 +0000
    12.3 @@ -230,9 +230,6 @@ static long __event_channel_close(struct
    12.4      guest_event_notify(cpu_mask);
    12.5  
    12.6   out:
    12.7 -    spin_unlock(&p1->event_channel_lock);
    12.8 -    put_task_struct(p1);
    12.9 -
   12.10      if ( p2 != NULL )
   12.11      {
   12.12          if ( p1 != p2 )
   12.13 @@ -240,6 +237,8 @@ static long __event_channel_close(struct
   12.14          put_task_struct(p2);
   12.15      }
   12.16      
   12.17 +    spin_unlock(&p1->event_channel_lock);
   12.18 +
   12.19      return rc;
   12.20  }
   12.21  
    13.1 --- a/xen/common/kernel.c	Wed Mar 03 12:59:48 2004 +0000
    13.2 +++ b/xen/common/kernel.c	Fri Mar 05 18:03:19 2004 +0000
    13.3 @@ -110,6 +110,7 @@ void cmain(unsigned long magic, multiboo
    13.4      unsigned long max_page;
    13.5      unsigned char *cmdline, *p;
    13.6      module_t *mod;
    13.7 +    void *heap_start;
    13.8      int i;
    13.9  
   13.10      /* Parse the command-line options. */
   13.11 @@ -222,7 +223,9 @@ void cmain(unsigned long magic, multiboo
   13.12      printk("Initialised all memory on a %luMB machine\n",
   13.13             max_page >> (20-PAGE_SHIFT));
   13.14  
   13.15 -    init_page_allocator(__pa(&_end), MAX_MONITOR_ADDRESS);
   13.16 +    heap_start = memguard_init(&_end);
   13.17 +
   13.18 +    init_page_allocator(__pa(heap_start), MAX_MONITOR_ADDRESS);
   13.19   
   13.20      /* Initialise the slab allocator. */
   13.21      kmem_cache_init();
   13.22 @@ -460,85 +463,6 @@ void printf(const char *fmt, ...)
   13.23  }
   13.24  
   13.25  
   13.26 -unsigned short compute_cksum(unsigned short *buf, int count)
   13.27 -{
   13.28 -    unsigned long sum = 0;
   13.29 -    while ( count-- )
   13.30 -        sum += *buf++;
   13.31 -    while ( sum >> 16 )
   13.32 -	sum = (sum & 0xffff) + (sum >> 16);
   13.33 -    return (unsigned short) ~sum;
   13.34 -}
   13.35 -
   13.36 -
   13.37 -/*
   13.38 - * Function written by ek247. Exports console output from all domains upwards 
   13.39 - * to domain0, by stuffing it into a fake network packet.
   13.40 - */
   13.41 -int console_export(char *str, int len)
   13.42 -{
   13.43 -    struct sk_buff *skb;
   13.44 -    struct iphdr *iph = NULL;  
   13.45 -    struct udphdr *udph = NULL; 
   13.46 -    struct ethhdr *ethh = NULL; 
   13.47 -    int hdr_size = sizeof(struct iphdr) + sizeof(struct udphdr); 
   13.48 -    u8 *skb_data;
   13.49 -
   13.50 -    skb = dev_alloc_skb(sizeof(struct ethhdr) + 
   13.51 -                                   hdr_size + len + 20);
   13.52 -    if ( skb == NULL ) return 0;
   13.53 -
   13.54 -    skb->dev = the_dev;
   13.55 -    skb_data = (u8 *)map_domain_mem((skb->pf - frame_table) << PAGE_SHIFT);
   13.56 -    skb_reserve(skb, 2);
   13.57 -
   13.58 -    /* Get a pointer to each header. */
   13.59 -    ethh = (struct ethhdr *) 
   13.60 -        (skb_data + (skb->data - skb->head));
   13.61 -    iph  = (struct iphdr *)(ethh + 1);
   13.62 -    udph = (struct udphdr *)(iph + 1); 
   13.63 -
   13.64 -    skb_reserve(skb, sizeof(struct ethhdr)); 
   13.65 -    skb_put(skb, hdr_size +  len); 
   13.66 -
   13.67 -    /* Build IP header. */
   13.68 -    iph->version = 4;
   13.69 -    iph->ihl     = 5;
   13.70 -    iph->tos	 = 0;
   13.71 -    iph->tot_len = htons(hdr_size + len);
   13.72 -    iph->id      = 0xdead;
   13.73 -    iph->frag_off= 0;
   13.74 -    iph->ttl     = 255;
   13.75 -    iph->protocol= 17;
   13.76 -    iph->daddr   = htonl(0xa9fe0100);  /* 169.254.1.0 */
   13.77 -    iph->saddr   = htonl(0xa9fefeff);  /* 169.254.254.255 */
   13.78 -    iph->check	 = 0;
   13.79 -    iph->check   = compute_cksum((__u16 *)iph, sizeof(struct iphdr)/2); 
   13.80 -
   13.81 -    /* Build UDP header. */
   13.82 -    udph->source = htons(current->domain);
   13.83 -    udph->dest   = htons(666);
   13.84 -    udph->len    = htons(sizeof(struct udphdr) + len);
   13.85 -    udph->check  = 0;
   13.86 -
   13.87 -    /* Build the UDP payload. */
   13.88 -    memcpy((char *)(udph + 1), str, len); 
   13.89 -
   13.90 -    /* Fix Ethernet header. */
   13.91 -    memset(ethh->h_source, 0, ETH_ALEN);
   13.92 -    memset(ethh->h_dest,   0, ETH_ALEN);
   13.93 -    ethh->h_proto = htons(ETH_P_IP);
   13.94 -    skb->mac.ethernet= (struct ethhdr *)ethh;
   13.95 -
   13.96 -    unmap_domain_mem(skb_data);
   13.97 -    
   13.98 -    skb->dst_vif = find_net_vif(0, 0);
   13.99 -    (void)netif_rx(skb);
  13.100 -
  13.101 -    return 1;
  13.102 -}
  13.103 -
  13.104 -
  13.105  long do_console_write(char *str, unsigned int count)
  13.106  {
  13.107  #define SIZEOF_BUF 256
  13.108 @@ -583,9 +507,6 @@ long do_console_write(char *str, unsigne
  13.109          __putstr(line_header);
  13.110          __putstr(single_line);
  13.111          spin_unlock_irqrestore(&console_lock, flags);
  13.112 -
  13.113 -        if ( current->domain != 0 )
  13.114 -            console_export(single_line, j);
  13.115      }
  13.116  
  13.117      return 0;
  13.118 @@ -648,28 +569,3 @@ long do_ni_syscall(void)
  13.119      /* No-op syscall. */
  13.120      return -ENOSYS;
  13.121  }
  13.122 -
  13.123 -
  13.124 -/*
  13.125 - * GRAVEYARD
  13.126 - */
  13.127 -#if 0
  13.128 -    if ( (mbi->flags & (1<<6)) )
  13.129 -    {
  13.130 -        memory_map_t *mmap = (memory_map_t *)mbi->mmap_addr;
  13.131 -        struct e820entry *e820 = E820_MAP;
  13.132 -
  13.133 -        while ( (unsigned long)mmap < (mbi->mmap_addr + mbi->mmap_length) )
  13.134 -        {
  13.135 -            e820->addr_lo = mmap->base_addr_low;
  13.136 -            e820->addr_hi = mmap->base_addr_high;
  13.137 -            e820->size_lo = mmap->length_low;
  13.138 -            e820->size_hi = mmap->length_high;
  13.139 -            e820->type    = mmap->type;
  13.140 -            e820++;
  13.141 -            mmap = (memory_map_t *) 
  13.142 -                ((unsigned long)mmap + mmap->size + sizeof (mmap->size));
  13.143 -        }
  13.144 -    }
  13.145 -#endif
  13.146 -
    14.1 --- a/xen/common/page_alloc.c	Wed Mar 03 12:59:48 2004 +0000
    14.2 +++ b/xen/common/page_alloc.c	Fri Mar 05 18:03:19 2004 +0000
    14.3 @@ -118,11 +118,90 @@ struct chunk_tail_st {
    14.4  #define FREELIST_SIZE ((sizeof(void*)<<3)-PAGE_SHIFT)
    14.5  static chunk_head_t *free_head[FREELIST_SIZE];
    14.6  static chunk_head_t  free_tail[FREELIST_SIZE];
    14.7 -#define FREELIST_EMPTY(_l) ((_l)->next == NULL)
    14.8 +#define FREELIST_EMPTY(_i) (free_head[_i] == &free_tail[i])
    14.9  
   14.10  #define round_pgdown(_p)  ((_p)&PAGE_MASK)
   14.11  #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
   14.12  
   14.13 +#ifdef MEMORY_GUARD
   14.14 +
   14.15 +/*
   14.16 + * Debug build: free memory chunks are made inaccessible.
   14.17 + */
   14.18 +
   14.19 +/* Make order-'o' pages inaccessible, from address 'p'. */
   14.20 +static inline void GUARD(void *p, int o)
   14.21 +{
   14.22 +    p = (void *)((unsigned long)p&PAGE_MASK);
   14.23 +    if ( p > (void *)&_end ) /* careful not to protect the 'free_tail' array */
   14.24 +        memguard_guard_range(p, (1<<(o+PAGE_SHIFT)));
   14.25 +}
   14.26 +
   14.27 +/* Make order-'o' pages accessible, from address 'p'. */
   14.28 +static inline void UNGUARD(void *p, int o)
   14.29 +{
   14.30 +    p = (void *)((unsigned long)p&PAGE_MASK);
   14.31 +    if ( p > (void *)&_end ) /* careful not to protect the 'free_tail' array */
   14.32 +        memguard_unguard_range(p, (1<<(o+PAGE_SHIFT)));
   14.33 +}
   14.34 +
   14.35 +/* Safe form of 'ch->level'. */
   14.36 +static inline int HEAD_LEVEL(chunk_head_t *ch)
   14.37 +{
   14.38 +    int l;
   14.39 +    ASSERT(memguard_is_guarded(ch));
   14.40 +    UNGUARD(ch, 0);
   14.41 +    l = ch->level;
   14.42 +    GUARD(ch, 0);
   14.43 +    return l;
   14.44 +}
   14.45 +
   14.46 +/* Safe form of 'ct->level'. */
   14.47 +static inline int TAIL_LEVEL(chunk_tail_t *ct)
   14.48 +{
   14.49 +    int l;
   14.50 +    ASSERT(memguard_is_guarded(ct));
   14.51 +    UNGUARD(ct, 0);
   14.52 +    l = ct->level;
   14.53 +    GUARD(ct, 0);
   14.54 +    return l;
   14.55 +}
   14.56 +
   14.57 +/* Safe form of '*ch->pprev = l'. */
   14.58 +static inline void UPDATE_PREV_FORWARDLINK(chunk_head_t *ch, chunk_head_t *l)
   14.59 +{
   14.60 +    ASSERT(((void *)ch->pprev < (void *)&_end) || 
   14.61 +           memguard_is_guarded(ch->pprev));
   14.62 +    UNGUARD(ch->pprev, 0);
   14.63 +    *ch->pprev = l;
   14.64 +    GUARD(ch->pprev, 0);
   14.65 +}
   14.66 +
   14.67 +/* Safe form of 'ch->next->pprev = l'. */
   14.68 +static inline void UPDATE_NEXT_BACKLINK(chunk_head_t *ch, chunk_head_t **l)
   14.69 +{
   14.70 +    ASSERT(((void *)ch->next < (void *)&_end) || 
   14.71 +           memguard_is_guarded(ch->next));
   14.72 +    UNGUARD(ch->next, 0);
   14.73 +    ch->next->pprev = l;
   14.74 +    GUARD(ch->next, 0);
   14.75 +}
   14.76 +
   14.77 +#else
   14.78 +
   14.79 +/*
   14.80 + * Non-debug build: free memory chunks are not made inaccessible.
   14.81 + */
   14.82 +
   14.83 +#define GUARD(_p,_o) ((void)0)
   14.84 +#define UNGUARD(_p,_o) ((void)0)
   14.85 +#define HEAD_LEVEL(_ch) ((_ch)->level)
   14.86 +#define TAIL_LEVEL(_ct) ((_ct)->level)
   14.87 +#define UPDATE_PREV_FORWARDLINK(_ch,_link) (*(_ch)->pprev = (_link))
   14.88 +#define UPDATE_NEXT_BACKLINK(_ch,_link) ((_ch)->next->pprev = (_link))
   14.89 +
   14.90 +#endif
   14.91 +
   14.92  
   14.93  /*
   14.94   * Initialise allocator, placing addresses [@min,@max] in free pool.
   14.95 @@ -131,7 +210,7 @@ static chunk_head_t  free_tail[FREELIST_
   14.96  void __init init_page_allocator(unsigned long min, unsigned long max)
   14.97  {
   14.98      int i;
   14.99 -    unsigned long range, bitmap_size;
  14.100 +    unsigned long range, bitmap_size, p, remaining;
  14.101      chunk_head_t *ch;
  14.102      chunk_tail_t *ct;
  14.103  
  14.104 @@ -161,19 +240,21 @@ void __init init_page_allocator(unsigned
  14.105      min += PAGE_OFFSET;
  14.106      max += PAGE_OFFSET;
  14.107  
  14.108 -    while ( range != 0 )
  14.109 +    p         = min;
  14.110 +    remaining = range;
  14.111 +    while ( remaining != 0 )
  14.112      {
  14.113          /*
  14.114 -         * Next chunk is limited by alignment of min, but also
  14.115 -         * must not be bigger than remaining range.
  14.116 +         * Next chunk is limited by alignment of p, but also must not be bigger
  14.117 +         * than remaining bytes.
  14.118           */
  14.119 -        for ( i = PAGE_SHIFT; (1<<(i+1)) <= range; i++ )
  14.120 -            if ( min & (1<<i) ) break;
  14.121 +        for ( i = PAGE_SHIFT; (1<<(i+1)) <= remaining; i++ )
  14.122 +            if ( p & (1<<i) ) break;
  14.123  
  14.124 -        ch = (chunk_head_t *)min;
  14.125 -        min   += (1<<i);
  14.126 -        range -= (1<<i);
  14.127 -        ct = (chunk_tail_t *)min-1;
  14.128 +        ch = (chunk_head_t *)p;
  14.129 +        p         += (1<<i);
  14.130 +        remaining -= (1<<i);
  14.131 +        ct = (chunk_tail_t *)p - 1;
  14.132          i -= PAGE_SHIFT;
  14.133          ch->level       = i;
  14.134          ch->next        = free_head[i];
  14.135 @@ -182,20 +263,8 @@ void __init init_page_allocator(unsigned
  14.136          free_head[i]    = ch;
  14.137          ct->level       = i;
  14.138      }
  14.139 -}
  14.140  
  14.141 -
  14.142 -/* Release a PHYSICAL address range to the allocator. */
  14.143 -void release_bytes_to_allocator(unsigned long min, unsigned long max)
  14.144 -{
  14.145 -    min = round_pgup  (min);
  14.146 -    max = round_pgdown(max);
  14.147 -
  14.148 -    while ( min < max )
  14.149 -    {
  14.150 -        __free_pages(min+PAGE_OFFSET, 0);
  14.151 -        min += PAGE_SIZE;
  14.152 -    }
  14.153 +    memguard_guard_range((void *)min, range);
  14.154  }
  14.155  
  14.156  
  14.157 @@ -212,7 +281,7 @@ retry:
  14.158  
  14.159      /* Find smallest order which can satisfy the request. */
  14.160      for ( i = order; i < FREELIST_SIZE; i++ ) {
  14.161 -	if ( !FREELIST_EMPTY(free_head[i]) ) 
  14.162 +	if ( !FREELIST_EMPTY(i) ) 
  14.163  	    break;
  14.164      }
  14.165  
  14.166 @@ -220,8 +289,10 @@ retry:
  14.167   
  14.168      /* Unlink a chunk. */
  14.169      alloc_ch = free_head[i];
  14.170 +    UNGUARD(alloc_ch, i);
  14.171      free_head[i] = alloc_ch->next;
  14.172 -    alloc_ch->next->pprev = alloc_ch->pprev;
  14.173 +    /* alloc_ch->next->pprev = alloc_ch->pprev */
  14.174 +    UPDATE_NEXT_BACKLINK(alloc_ch, alloc_ch->pprev);
  14.175  
  14.176      /* We may have to break the chunk a number of times. */
  14.177      while ( i != order )
  14.178 @@ -238,14 +309,21 @@ retry:
  14.179          spare_ct->level = i;
  14.180  
  14.181          /* Link in the spare chunk. */
  14.182 -        spare_ch->next->pprev = &spare_ch->next;
  14.183 +        /* spare_ch->next->pprev = &spare_ch->next */
  14.184 +        UPDATE_NEXT_BACKLINK(spare_ch, &spare_ch->next);
  14.185          free_head[i] = spare_ch;
  14.186 +        GUARD(spare_ch, i);
  14.187      }
  14.188      
  14.189      map_alloc(__pa(alloc_ch)>>PAGE_SHIFT, 1<<order);
  14.190  
  14.191      spin_unlock_irqrestore(&alloc_lock, flags);
  14.192  
  14.193 +#ifdef MEMORY_GUARD
  14.194 +    /* Now we blast the contents of the block. */
  14.195 +    memset(alloc_ch, 0x55, 1 << (order + PAGE_SHIFT));
  14.196 +#endif
  14.197 +
  14.198      return((unsigned long)alloc_ch);
  14.199  
  14.200   no_memory:
  14.201 @@ -274,6 +352,17 @@ void __free_pages(unsigned long p, int o
  14.202  
  14.203      spin_lock_irqsave(&alloc_lock, flags);
  14.204  
  14.205 +#ifdef MEMORY_GUARD
  14.206 +    /* Check that the block isn't already freed. */
  14.207 +    if ( !allocated_in_map(pagenr) )
  14.208 +        BUG();
  14.209 +    /* Check that the block isn't already guarded. */
  14.210 +    if ( __put_user(1, (int*)p) )
  14.211 +        BUG();
  14.212 +    /* Now we blast the contents of the block. */
  14.213 +    memset((void *)p, 0xaa, size);
  14.214 +#endif
  14.215 +
  14.216      map_free(pagenr, 1<<order);
  14.217      
  14.218      /* Merge chunks as far as possible. */
  14.219 @@ -282,23 +371,30 @@ void __free_pages(unsigned long p, int o
  14.220          if ( (p & size) )
  14.221          {
  14.222              /* Merge with predecessor block? */
  14.223 -            if ( allocated_in_map(pagenr-1) ) break;
  14.224 +            if ( allocated_in_map(pagenr-1) )
  14.225 +                break;
  14.226              ct = (chunk_tail_t *)p - 1;
  14.227 -            if ( ct->level != order ) break;
  14.228 +            if ( TAIL_LEVEL(ct) != order )
  14.229 +                break;
  14.230              ch = (chunk_head_t *)(p - size);
  14.231              p -= size;
  14.232          }
  14.233          else
  14.234          {
  14.235              /* Merge with successor block? */
  14.236 -            if ( allocated_in_map(pagenr+(1<<order)) ) break;
  14.237 +            if ( allocated_in_map(pagenr+(1<<order)) )
  14.238 +                break;
  14.239              ch = (chunk_head_t *)(p + size);
  14.240 -            if ( ch->level != order ) break;
  14.241 +            if ( HEAD_LEVEL(ch) != order )
  14.242 +                break;
  14.243          }
  14.244          
  14.245          /* Okay, unlink the neighbour. */
  14.246 -        *ch->pprev = ch->next;
  14.247 -        ch->next->pprev = ch->pprev;
  14.248 +        UNGUARD(ch, order);
  14.249 +        /* *ch->pprev = ch->next */
  14.250 +        UPDATE_PREV_FORWARDLINK(ch, ch->next);
  14.251 +        /* ch->next->pprev = ch->pprev */
  14.252 +        UPDATE_NEXT_BACKLINK(ch, ch->pprev);
  14.253  
  14.254          order++;
  14.255          size <<= 1;
  14.256 @@ -311,8 +407,10 @@ void __free_pages(unsigned long p, int o
  14.257      ch->level = order;
  14.258      ch->pprev = &free_head[order];
  14.259      ch->next  = free_head[order];
  14.260 -    ch->next->pprev = &ch->next;
  14.261 +    /* ch->next->pprev = &ch->next */
  14.262 +    UPDATE_NEXT_BACKLINK(ch, &ch->next);
  14.263      free_head[order] = ch;
  14.264 +    GUARD(ch, order);
  14.265  
  14.266      spin_unlock_irqrestore(&alloc_lock, flags);
  14.267  }
    15.1 --- a/xen/common/schedule.c	Wed Mar 03 12:59:48 2004 +0000
    15.2 +++ b/xen/common/schedule.c	Fri Mar 05 18:03:19 2004 +0000
    15.3 @@ -165,6 +165,7 @@ int sched_rem_domain(struct task_struct 
    15.4      do {
    15.5          if ( (x = y) == TASK_DYING ) return 0;
    15.6      } while ( (y = cmpxchg(&p->state, x, TASK_DYING)) != x );
    15.7 +    rem_ac_timer(&p->timer);
    15.8      return 1;
    15.9  }
   15.10  
    16.1 --- a/xen/include/xeno/config.h	Wed Mar 03 12:59:48 2004 +0000
    16.2 +++ b/xen/include/xeno/config.h	Fri Mar 05 18:03:19 2004 +0000
    16.3 @@ -148,7 +148,7 @@
    16.4  #ifndef NDEBUG
    16.5  #define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \
    16.6                             __FILE__ , __LINE__ , ## _a )
    16.7 -#define STACK_GUARD
    16.8 +#define MEMORY_GUARD
    16.9  #define TRACE_BUFFER
   16.10  #else
   16.11  #define DPRINTK(_f, _a...) ((void)0)
    17.1 --- a/xen/include/xeno/mm.h	Wed Mar 03 12:59:48 2004 +0000
    17.2 +++ b/xen/include/xeno/mm.h	Fri Mar 05 18:03:19 2004 +0000
    17.3 @@ -36,7 +36,6 @@
    17.4   */
    17.5  
    17.6  void init_page_allocator(unsigned long min, unsigned long max);
    17.7 -void release_bytes_to_allocator(unsigned long min, unsigned long max);
    17.8  unsigned long __get_free_pages(int mask, int order);
    17.9  void __free_pages(unsigned long p, int order);
   17.10  #define get_free_page(_m) (__get_free_pages((_m),0))
   17.11 @@ -317,4 +316,16 @@ int do_mmu_update(mmu_update_t *updates,
   17.12  #define DEFAULT_GDT_ENTRIES     ((LAST_RESERVED_GDT_ENTRY*8)+7)
   17.13  #define DEFAULT_GDT_ADDRESS     ((unsigned long)gdt_table)
   17.14  
   17.15 +#ifdef MEMORY_GUARD
   17.16 +void *memguard_init(void *heap_start);
   17.17 +void memguard_guard_range(void *p, unsigned long l);
   17.18 +void memguard_unguard_range(void *p, unsigned long l);
   17.19 +int memguard_is_guarded(void *p);
   17.20 +#else
   17.21 +#define memguard_init(_s)              (_s)
   17.22 +#define memguard_guard_range(_p,_l)    ((void)0)
   17.23 +#define memguard_unguard_range(_p,_l)  ((void)0)
   17.24 +#define memguard_is_guarded(_p)        (0)
   17.25 +#endif
   17.26 +
   17.27  #endif /* __XENO_MM_H__ */
    18.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/Makefile	Wed Mar 03 12:59:48 2004 +0000
    18.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/Makefile	Fri Mar 05 18:03:19 2004 +0000
    18.3 @@ -57,9 +57,9 @@ SUBDIRS += arch/xeno/drivers/dom0
    18.4  endif
    18.5  
    18.6  CORE_FILES += arch/xeno/kernel/kernel.o arch/xeno/mm/mm.o
    18.7 +CORE_FILES += arch/xeno/drivers/evtchn/evtchn.o
    18.8  CORE_FILES += arch/xeno/drivers/console/con.o
    18.9  CORE_FILES += arch/xeno/drivers/block/blk.o
   18.10 -CORE_FILES += arch/xeno/drivers/evtchn/evtchn.o
   18.11  CORE_FILES += arch/xeno/drivers/network/net.o
   18.12  ifdef CONFIG_XENO_PRIV
   18.13  CORE_FILES += arch/xeno/drivers/dom0/dom0.o
    19.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c	Wed Mar 03 12:59:48 2004 +0000
    19.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c	Fri Mar 05 18:03:19 2004 +0000
    19.3 @@ -1,5 +1,9 @@
    19.4  /******************************************************************************
    19.5   * console.c
    19.6 + * 
    19.7 + * Virtual console driver.
    19.8 + * 
    19.9 + * Copyright (c) 2002-2004, K A Fraser.
   19.10   */
   19.11  
   19.12  #include <linux/config.h>
   19.13 @@ -18,52 +22,77 @@
   19.14  #include <linux/slab.h>
   19.15  #include <linux/init.h>
   19.16  #include <linux/console.h>
   19.17 -
   19.18 +#include <asm/evtchn.h>
   19.19  #include <asm/io.h>
   19.20  #include <asm/irq.h>
   19.21  #include <asm/uaccess.h>
   19.22  #include <asm/hypervisor.h>
   19.23 +#include <asm/hypervisor-ifs/event_channel.h>
   19.24 +#include <asm/control_if.h>
   19.25 +
   19.26 +static spinlock_t xeno_console_lock = SPIN_LOCK_UNLOCKED;
   19.27  
   19.28  #define XENO_TTY_MINOR 123
   19.29  
   19.30 -/*** Useful function for console debugging -- goes straight to Xen ****/
   19.31 -asmlinkage int xprintk(const char *fmt, ...)
   19.32 +/******************** Kernel console driver ********************************/
   19.33 +
   19.34 +static void nonpriv_conwrite(const char *s, unsigned int count)
   19.35  {
   19.36 -    va_list args;
   19.37 -    int printk_len;
   19.38 -    static char printk_buf[1024];
   19.39 -    
   19.40 -    /* Emit the output into the temporary buffer */
   19.41 -    va_start(args, fmt);
   19.42 -    printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
   19.43 -    va_end(args);
   19.44 -    
   19.45 -    /* Send the processed output directly to Xen. */
   19.46 -    (void)HYPERVISOR_console_write(printk_buf, printk_len);
   19.47 +    control_if_t *ctrl_if;
   19.48 +    evtchn_op_t   evtchn_op;
   19.49 +    int           src, dst, p;
   19.50 +    unsigned long flags;
   19.51 +
   19.52 +    ctrl_if = (control_if_t *)((char *)HYPERVISOR_shared_info + 2048);
   19.53 +
   19.54 +    spin_lock_irqsave(&xeno_console_lock, flags);
   19.55 +
   19.56 +    while ( count != 0 )
   19.57 +    {
   19.58 +        /* Wait for the request ring to drain. */
   19.59 +        while ( ctrl_if->tx_resp_prod != ctrl_if->tx_req_prod )
   19.60 +            barrier();
   19.61  
   19.62 -    return 0;
   19.63 +        p = MASK_CONTROL_IDX(ctrl_if->tx_req_prod);
   19.64 +        
   19.65 +        ctrl_if->tx_ring[p].cmd_type    = CMD_CONSOLE;
   19.66 +        ctrl_if->tx_ring[p].cmd_subtype = CMD_CONSOLE_DATA;
   19.67 +        ctrl_if->tx_ring[p].id          = 0xaa;
   19.68 +        src = dst = 0;
   19.69 +        while ( (src < count) && (dst < (sizeof(ctrl_if->tx_ring[p].msg)-1)) )
   19.70 +        {
   19.71 +            if ( (ctrl_if->tx_ring[p].msg[dst++] = s[src++]) == '\n' )
   19.72 +                ctrl_if->tx_ring[p].msg[dst++] = '\r';
   19.73 +        }
   19.74 +        ctrl_if->tx_ring[p].length = dst;
   19.75 +        
   19.76 +        ctrl_if->tx_req_prod++;
   19.77 +        evtchn_op.cmd = EVTCHNOP_send;
   19.78 +        evtchn_op.u.send.local_port = 0;
   19.79 +        (void)HYPERVISOR_event_channel_op(&evtchn_op);
   19.80 +        
   19.81 +        s     += src;
   19.82 +        count -= src;
   19.83 +    }
   19.84 +
   19.85 +    spin_unlock_irqrestore(&xeno_console_lock, flags);
   19.86  }
   19.87  
   19.88 -
   19.89 -
   19.90 -/******************** Kernel console driver ********************************/
   19.91 -
   19.92 -static void xen_console_write(struct console *co, const char *s, unsigned count)
   19.93 +static void priv_conwrite(const char *s, unsigned int count)
   19.94  {
   19.95 -#define STRLEN 256
   19.96 -    static char str[STRLEN];
   19.97 +    static char str[256];
   19.98      static int pos = 0;
   19.99      int len;
  19.100 -    
  19.101 +
  19.102      /* We buffer output until we see a newline, or until the buffer is full. */
  19.103      while ( count != 0 )
  19.104      {
  19.105 -        len = ((STRLEN - pos) > count) ? count : STRLEN - pos;
  19.106 +        len = ((sizeof(str) - pos) > count) ? count : sizeof(str) - pos;
  19.107          memcpy(str + pos, s, len);
  19.108          pos   += len;
  19.109          s     += len;
  19.110          count -= len;
  19.111 -        if ( (pos == STRLEN) || (str[pos-1] == '\n') )
  19.112 +        if ( (pos == sizeof(str)) || (str[pos-1] == '\n') )
  19.113          {
  19.114              (void)HYPERVISOR_console_write(str, pos);
  19.115              pos = 0;
  19.116 @@ -71,6 +100,15 @@ static void xen_console_write(struct con
  19.117      }
  19.118  }
  19.119  
  19.120 +static void xen_console_write(struct console *co, const char *s, 
  19.121 +                              unsigned int count)
  19.122 +{
  19.123 +    if ( !(start_info.flags & SIF_INITDOMAIN) )
  19.124 +        nonpriv_conwrite(s, count);
  19.125 +    else
  19.126 +        priv_conwrite(s, count);
  19.127 +}
  19.128 +
  19.129  static kdev_t xen_console_device(struct console *c)
  19.130  {
  19.131      /*
  19.132 @@ -92,34 +130,184 @@ static struct console xen_console_info =
  19.133  
  19.134  void xen_console_init(void)
  19.135  {
  19.136 -  xprintk("xen_console_init\n");
  19.137 -  register_console(&xen_console_info);
  19.138 +    register_console(&xen_console_info);
  19.139  }
  19.140  
  19.141  
  19.142 -/******************** Initial /dev/console *********************************/
  19.143 +/*** Useful function for console debugging -- goes straight to Xen ****/
  19.144 +asmlinkage int xprintk(const char *fmt, ...)
  19.145 +{
  19.146 +    va_list args;
  19.147 +    int printk_len;
  19.148 +    static char printk_buf[1024];
  19.149 +    
  19.150 +    /* Emit the output into the temporary buffer */
  19.151 +    va_start(args, fmt);
  19.152 +    printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
  19.153 +    va_end(args);
  19.154 +    
  19.155 +    /* Send the processed output directly to Xen. */
  19.156 +    xen_console_write(NULL, printk_buf, printk_len);
  19.157  
  19.158 +    return 0;
  19.159 +}
  19.160 +
  19.161 +
  19.162 +/******************** User-space console driver (/dev/console) ************/
  19.163  
  19.164  static struct tty_driver xeno_console_driver;
  19.165  static int xeno_console_refcount;
  19.166  static struct tty_struct *xeno_console_table[1];
  19.167  static struct termios *xeno_console_termios[1];
  19.168  static struct termios *xeno_console_termios_locked[1];
  19.169 +static struct tty_struct *xeno_console_tty;
  19.170 +static int xeno_console_use_count;
  19.171 +
  19.172 +#define WBUF_SIZE     1024
  19.173 +#define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1))
  19.174 +static char wbuf[WBUF_SIZE], x_char;
  19.175 +static unsigned int wc, wp; /* write_cons, write_prod */
  19.176 +
  19.177 +static void __do_console_io(void)
  19.178 +{
  19.179 +    control_if_t    *ctrl_if;
  19.180 +    control_msg_t   *msg;
  19.181 +    evtchn_op_t      evtchn_op;
  19.182 +    CONTROL_RING_IDX c;
  19.183 +    int              i, len, work_done = 0;
  19.184 +
  19.185 +    if ( (start_info.flags & SIF_INITDOMAIN) || (xeno_console_tty == NULL) )
  19.186 +        return;
  19.187 +
  19.188 +    /* Acknowledge the notification. */
  19.189 +    evtchn_clear_port(0);
  19.190 +
  19.191 +    ctrl_if = (control_if_t *)((char *)HYPERVISOR_shared_info + 2048);
  19.192 +    
  19.193 +    /* Receive work. */
  19.194 +    for ( c = ctrl_if->rx_resp_prod; c != ctrl_if->rx_req_prod; c++ )
  19.195 +    {
  19.196 +        msg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(c)];
  19.197 +        if ( (msg->cmd_type == CMD_CONSOLE) &&
  19.198 +             (msg->cmd_subtype == CMD_CONSOLE_DATA) )
  19.199 +        {
  19.200 +            for ( i = 0; i < msg->length; i++ )
  19.201 +                tty_insert_flip_char(xeno_console_tty, msg->msg[i], 0);
  19.202 +        }
  19.203 +        msg->length = 0;
  19.204 +    }
  19.205 +    if ( ctrl_if->rx_resp_prod != c )
  19.206 +    {
  19.207 +        ctrl_if->rx_resp_prod = c;
  19.208 +        work_done = 1;
  19.209 +        tty_flip_buffer_push(xeno_console_tty);
  19.210 +    }
  19.211 +    
  19.212 +    /* Transmit work. */
  19.213 +    for ( c = ctrl_if->tx_req_prod; 
  19.214 +          (c - ctrl_if->tx_resp_prod) != CONTROL_RING_SIZE; 
  19.215 +          c++ )
  19.216 +    {
  19.217 +        if ( (wc == wp) && (x_char == 0) )
  19.218 +            break;
  19.219 +        msg = &ctrl_if->tx_ring[MASK_CONTROL_IDX(c)];
  19.220 +        msg->cmd_type    = CMD_CONSOLE;
  19.221 +        msg->cmd_subtype = CMD_CONSOLE_DATA;
  19.222 +        msg->id          = 0xaa;
  19.223 +        len = 0;
  19.224 +        if ( x_char != 0 ) /* Handle XON/XOFF urgently. */
  19.225 +        {
  19.226 +            msg->msg[len++] = x_char;
  19.227 +            x_char = 0;
  19.228 +        }
  19.229 +        while ( (len < sizeof(msg->msg)) && (wc != wp) )
  19.230 +            msg->msg[len++] = wbuf[WBUF_MASK(wc++)];
  19.231 +        msg->length = len;
  19.232 +    }
  19.233 +    if ( ctrl_if->tx_req_prod != c )
  19.234 +    {
  19.235 +        ctrl_if->tx_req_prod = c;
  19.236 +        work_done = 1;
  19.237 +    }
  19.238 +        
  19.239 +    if ( work_done )
  19.240 +    {
  19.241 +        /* Send a notification to the controller. */
  19.242 +        evtchn_op.cmd = EVTCHNOP_send;
  19.243 +        evtchn_op.u.send.local_port = 0;
  19.244 +        (void)HYPERVISOR_event_channel_op(&evtchn_op);
  19.245 +
  19.246 +        /* There might be something for waiters to do. */
  19.247 +        if ( xeno_console_tty != NULL )
  19.248 +            wake_up_interruptible(&xeno_console_tty->write_wait);
  19.249 +    }
  19.250 +}
  19.251 +
  19.252 +static void control_event(unsigned int port)
  19.253 +{
  19.254 +    unsigned long flags;
  19.255 +    spin_lock_irqsave(&xeno_console_lock, flags);
  19.256 +    __do_console_io();
  19.257 +    spin_unlock_irqrestore(&xeno_console_lock, flags);
  19.258 +}
  19.259  
  19.260  static int xeno_console_write_room(struct tty_struct *tty)
  19.261  {
  19.262 -    return INT_MAX;
  19.263 +    return WBUF_SIZE - (wp - wc);
  19.264  }
  19.265  
  19.266  static int xeno_console_chars_in_buffer(struct tty_struct *tty)
  19.267  {
  19.268 -    return 0;
  19.269 +    return wp - wc;
  19.270 +}
  19.271 +
  19.272 +static void xeno_console_send_xchar(struct tty_struct *tty, char ch)
  19.273 +{
  19.274 +    unsigned long flags;
  19.275 +    spin_lock_irqsave(&xeno_console_lock, flags);
  19.276 +    x_char = ch;
  19.277 +    __do_console_io();
  19.278 +    spin_unlock_irqrestore(&xeno_console_lock, flags);
  19.279 +}
  19.280 +
  19.281 +static void xeno_console_throttle(struct tty_struct *tty)
  19.282 +{
  19.283 +    if ( I_IXOFF(tty) )
  19.284 +        xeno_console_send_xchar(tty, STOP_CHAR(tty));
  19.285  }
  19.286  
  19.287 -static inline int xeno_console_xmit(int ch)
  19.288 +static void xeno_console_unthrottle(struct tty_struct *tty)
  19.289 +{
  19.290 +    if ( I_IXOFF(tty) )
  19.291 +    {
  19.292 +        if ( x_char != 0 )
  19.293 +            x_char = 0;
  19.294 +        else
  19.295 +            xeno_console_send_xchar(tty, START_CHAR(tty));
  19.296 +    }
  19.297 +}
  19.298 +
  19.299 +static void xeno_console_flush_buffer(struct tty_struct *tty)
  19.300  {
  19.301 -    char _ch = ch;
  19.302 -    xen_console_write(NULL, &_ch, 1);
  19.303 +    unsigned long flags;
  19.304 +    spin_lock_irqsave(&xeno_console_lock, flags);
  19.305 +    wc = wp = 0;
  19.306 +    spin_unlock_irqrestore(&xeno_console_lock, flags);
  19.307 +}
  19.308 +
  19.309 +static inline int __xeno_console_put_char(int ch)
  19.310 +{
  19.311 +    char _ch = (char)ch;
  19.312 +
  19.313 +    if ( start_info.flags & SIF_INITDOMAIN )
  19.314 +    {
  19.315 +        priv_conwrite(&_ch, 1);
  19.316 +        return 1;
  19.317 +    }
  19.318 +
  19.319 +    if ( (wp - wc) == WBUF_SIZE )
  19.320 +        return 0;
  19.321 +    wbuf[WBUF_MASK(wp++)] = _ch;
  19.322      return 1;
  19.323  }
  19.324  
  19.325 @@ -127,31 +315,47 @@ static int xeno_console_write(struct tty
  19.326                         const u_char * buf, int count)
  19.327  {
  19.328      int i;
  19.329 +    unsigned long flags;
  19.330  
  19.331      if ( from_user && verify_area(VERIFY_READ, buf, count) )
  19.332 -    {
  19.333          return -EINVAL;
  19.334 -    }
  19.335 +
  19.336 +    spin_lock_irqsave(&xeno_console_lock, flags);
  19.337  
  19.338      for ( i = 0; i < count; i++ )
  19.339      {
  19.340          char ch;
  19.341          if ( from_user )
  19.342 -        {
  19.343              __get_user(ch, buf + i);
  19.344 -        }
  19.345          else
  19.346 -        {
  19.347              ch = buf[i];
  19.348 -        }
  19.349 -        xeno_console_xmit(ch);
  19.350 +        if ( !__xeno_console_put_char(ch) )
  19.351 +            break;
  19.352      }
  19.353 +
  19.354 +    if ( i != 0 )
  19.355 +        __do_console_io();
  19.356 +
  19.357 +    spin_unlock_irqrestore(&xeno_console_lock, flags);
  19.358 +
  19.359      return i;
  19.360  }
  19.361  
  19.362  static void xeno_console_put_char(struct tty_struct *tty, u_char ch)
  19.363  {
  19.364 -    xeno_console_xmit(ch);
  19.365 +    unsigned long flags;
  19.366 +    spin_lock_irqsave(&xeno_console_lock, flags);
  19.367 +    (void)__xeno_console_put_char(ch);
  19.368 +    spin_unlock_irqrestore(&xeno_console_lock, flags);
  19.369 +}
  19.370 +
  19.371 +static void xeno_console_flush_chars(struct tty_struct *tty)
  19.372 +{
  19.373 +    unsigned long flags;
  19.374 +    spin_lock_irqsave(&xeno_console_lock, flags);
  19.375 +
  19.376 +    __do_console_io();
  19.377 +    spin_unlock_irqrestore(&xeno_console_lock, flags);    
  19.378  }
  19.379  
  19.380  static int xeno_console_open(struct tty_struct *tty, struct file *filp)
  19.381 @@ -167,12 +371,22 @@ static int xeno_console_open(struct tty_
  19.382      }
  19.383  
  19.384      tty->driver_data = NULL;
  19.385 +    if ( xeno_console_tty == NULL )
  19.386 +    {
  19.387 +        xeno_console_tty = tty;
  19.388 +        wc = wp = 0;
  19.389 +        __do_console_io();
  19.390 +    }
  19.391 +
  19.392 +    xeno_console_use_count++;
  19.393  
  19.394      return 0;
  19.395  }
  19.396  
  19.397  static void xeno_console_close(struct tty_struct *tty, struct file *filp)
  19.398  {
  19.399 +    if ( --xeno_console_use_count == 0 )
  19.400 +        xeno_console_tty = NULL;
  19.401      MOD_DEC_USE_COUNT;
  19.402  }
  19.403  
  19.404 @@ -180,36 +394,44 @@ int __init xeno_con_init(void)
  19.405  {
  19.406      memset(&xeno_console_driver, 0, sizeof(struct tty_driver));
  19.407      xeno_console_driver.magic           = TTY_DRIVER_MAGIC;
  19.408 -    xeno_console_driver.driver_name     = "xeno_console";
  19.409 -    xeno_console_driver.name            = "xencon";
  19.410 +    xeno_console_driver.name            = "xencons";
  19.411      xeno_console_driver.major           = TTY_MAJOR;
  19.412      xeno_console_driver.minor_start     = XENO_TTY_MINOR;
  19.413      xeno_console_driver.num             = 1;
  19.414      xeno_console_driver.type            = TTY_DRIVER_TYPE_SERIAL;
  19.415      xeno_console_driver.subtype         = SERIAL_TYPE_NORMAL;
  19.416      xeno_console_driver.init_termios    = tty_std_termios;
  19.417 -    xeno_console_driver.flags           = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
  19.418 +    xeno_console_driver.flags           = TTY_DRIVER_REAL_RAW;
  19.419      xeno_console_driver.refcount        = &xeno_console_refcount;
  19.420      xeno_console_driver.table           = xeno_console_table;
  19.421      xeno_console_driver.termios         = xeno_console_termios;
  19.422      xeno_console_driver.termios_locked  = xeno_console_termios_locked;
  19.423 -    /* Functions */
  19.424 +
  19.425      xeno_console_driver.open            = xeno_console_open;
  19.426      xeno_console_driver.close           = xeno_console_close;
  19.427      xeno_console_driver.write           = xeno_console_write;
  19.428      xeno_console_driver.write_room      = xeno_console_write_room;
  19.429      xeno_console_driver.put_char        = xeno_console_put_char;
  19.430 +    xeno_console_driver.flush_chars     = xeno_console_flush_chars;
  19.431      xeno_console_driver.chars_in_buffer = xeno_console_chars_in_buffer;
  19.432 +    xeno_console_driver.send_xchar      = xeno_console_send_xchar;
  19.433 +    xeno_console_driver.flush_buffer    = xeno_console_flush_buffer;
  19.434 +    xeno_console_driver.throttle        = xeno_console_throttle;
  19.435 +    xeno_console_driver.unthrottle      = xeno_console_unthrottle;
  19.436  
  19.437      if ( tty_register_driver(&xeno_console_driver) )
  19.438 +        panic("Couldn't register Xeno console driver\n");
  19.439 +
  19.440 +    if ( !(start_info.flags & SIF_INITDOMAIN) )
  19.441      {
  19.442 -        printk(KERN_ERR "Couldn't register Xeno console driver\n");
  19.443 -    }
  19.444 -    else
  19.445 -    {
  19.446 -        printk("Xeno console successfully installed\n");
  19.447 +        if ( evtchn_request_port(0, control_event) != 0 )
  19.448 +            BUG();
  19.449 +        /* Kickstart event delivery. */
  19.450 +        control_event(0);
  19.451      }
  19.452  
  19.453 +    printk("Xeno console successfully installed\n");
  19.454 +    
  19.455      return 0;
  19.456  }
  19.457  
  19.458 @@ -219,9 +441,10 @@ void __exit xeno_con_fini(void)
  19.459  
  19.460      ret = tty_unregister_driver(&xeno_console_driver);
  19.461      if ( ret != 0 )
  19.462 -    {
  19.463          printk(KERN_ERR "Unable to unregister Xeno console driver: %d\n", ret);
  19.464 -    }
  19.465 +
  19.466 +    if ( !(start_info.flags & SIF_INITDOMAIN) )
  19.467 +        (void)evtchn_free_port(0);
  19.468  }
  19.469  
  19.470  module_init(xeno_con_init);
    20.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c	Wed Mar 03 12:59:48 2004 +0000
    20.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/evtchn/xl_evtchn.c	Fri Mar 05 18:03:19 2004 +0000
    20.3 @@ -21,18 +21,7 @@
    20.4  #include <linux/devfs_fs_kernel.h>
    20.5  #include <linux/stat.h>
    20.6  #include <linux/poll.h>
    20.7 -
    20.8 -typedef void (*evtchn_receiver_t)(unsigned int);
    20.9 -#define PORT_NORMAL     0x0000
   20.10 -#define PORT_DISCONNECT 0x8000
   20.11 -#define PORTIDX_MASK    0x7fff
   20.12 -
   20.13 -/* /dev/xen/evtchn resides at device number major=10, minor=200 */
   20.14 -#define EVTCHN_MINOR 200
   20.15 -
   20.16 -/* /dev/xen/evtchn ioctls: */
   20.17 -/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
   20.18 -#define EVTCHN_RESET _IO('E', 1)
   20.19 +#include <asm/evtchn.h>
   20.20  
   20.21  /* NB. This must be shared amongst drivers if more things go in /dev/xen */
   20.22  static devfs_handle_t xen_dev_dir;
   20.23 @@ -110,18 +99,22 @@ int evtchn_free_port(unsigned int port)
   20.24  void evtchn_clear_port(unsigned int port)
   20.25  {
   20.26      unsigned int p = port & PORTIDX_MASK;
   20.27 +    unsigned long flags;
   20.28 +
   20.29 +    spin_lock_irqsave(&lock, flags);
   20.30 +
   20.31      if ( unlikely(port & PORT_DISCONNECT) )
   20.32      {
   20.33 +        clear_bit(p, &disc_outstanding[0]);
   20.34          clear_bit(p, &HYPERVISOR_shared_info->event_channel_disc[0]);
   20.35 -        wmb(); /* clear the source first, then our quenchmask */
   20.36 -        clear_bit(p, &disc_outstanding[0]);
   20.37      }
   20.38      else
   20.39      {
   20.40 +        clear_bit(p, &pend_outstanding[0]);
   20.41          clear_bit(p, &HYPERVISOR_shared_info->event_channel_pend[0]);
   20.42 -        wmb(); /* clear the source first, then our quenchmask */
   20.43 -        clear_bit(p, &pend_outstanding[0]);
   20.44      }
   20.45 +
   20.46 +    spin_unlock_irqrestore(&lock, flags);
   20.47  }
   20.48  
   20.49  static inline void process_bitmask(u32 *sel, 
   20.50 @@ -168,7 +161,6 @@ static inline void process_bitmask(u32 *
   20.51              }
   20.52          }
   20.53      }
   20.54 -
   20.55  }
   20.56  
   20.57  static void evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
   20.58 @@ -267,33 +259,37 @@ static ssize_t evtchn_read(struct file *
   20.59          schedule();
   20.60      }
   20.61  
   20.62 -    rc = -EFAULT;
   20.63 -
   20.64 -    /* Byte length of first chunk. May be truncated by ring wrap. */
   20.65 +    /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
   20.66      if ( ((c ^ p) & RING_SIZE) != 0 )
   20.67 +    {
   20.68          bytes1 = (RING_SIZE - RING_MASK(c)) * sizeof(u16);
   20.69 +        bytes2 = RING_MASK(p) * sizeof(u16);
   20.70 +    }
   20.71      else
   20.72 +    {
   20.73          bytes1 = (p - c) * sizeof(u16);
   20.74 -
   20.75 -    /* Further truncate chunk length according to caller's maximum count. */
   20.76 -    if ( bytes1 > count )
   20.77 -        bytes1 = count;
   20.78 -
   20.79 -    /* Copy the first chunk. */
   20.80 -    if ( copy_to_user(buf, &ring[c], bytes1) != 0 )
   20.81 -        goto out;
   20.82 -
   20.83 -    /* More bytes to copy? */
   20.84 -    if ( count > bytes1 )
   20.85 -    {
   20.86 -        bytes2 = RING_MASK(p) * sizeof(u16);
   20.87 -        if ( bytes2 > count )
   20.88 -            bytes2 = count;
   20.89 -        if ( (bytes2 != 0) && copy_to_user(&buf[bytes1], &ring[0], bytes2) )
   20.90 -            goto out;
   20.91 +        bytes2 = 0;
   20.92      }
   20.93  
   20.94 -    ring_cons = (bytes1 + bytes2) / sizeof(u16);
   20.95 +    /* Truncate chunks according to caller's maximum byte count. */
   20.96 +    if ( bytes1 > count )
   20.97 +    {
   20.98 +        bytes1 = count;
   20.99 +        bytes2 = 0;
  20.100 +    }
  20.101 +    else if ( (bytes1 + bytes2) > count )
  20.102 +    {
  20.103 +        bytes2 = count - bytes1;
  20.104 +    }
  20.105 +
  20.106 +    if ( copy_to_user(buf, &ring[RING_MASK(c)], bytes1) ||
  20.107 +         ((bytes2 != 0) && copy_to_user(&buf[bytes1], &ring[0], bytes2)) )
  20.108 +    {
  20.109 +        rc = -EFAULT;
  20.110 +        goto out;
  20.111 +    }
  20.112 +
  20.113 +    ring_cons += (bytes1 + bytes2) / sizeof(u16);
  20.114  
  20.115      rc = bytes1 + bytes2;
  20.116  
  20.117 @@ -465,6 +461,11 @@ static int __init init_module(void)
  20.118          return err;
  20.119      }
  20.120  
  20.121 +    /* Kickstart servicing of notifications. */
  20.122 +    evtchn_interrupt(0, NULL, NULL);
  20.123 +
  20.124 +    printk("Event-channel driver installed.\n");
  20.125 +
  20.126      return 0;
  20.127  }
  20.128  
    21.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c	Wed Mar 03 12:59:48 2004 +0000
    21.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/kernel/time.c	Fri Mar 05 18:03:19 2004 +0000
    21.3 @@ -531,6 +531,10 @@ int set_timeout_timer(void)
    21.4      if ( (timer = next_timer_event()) != NULL )
    21.5          alarm = __jiffies_to_st(timer->expires);
    21.6  
    21.7 +    /* Tasks on the timer task queue expect to be executed on the next tick. */
    21.8 +    if ( TQ_ACTIVE(tq_timer) )
    21.9 +        alarm = __jiffies_to_st(jiffies + 1);
   21.10 +
   21.11      /* Failure is pretty bad, but we'd best soldier on. */
   21.12      if ( HYPERVISOR_set_timer_op(alarm) != 0 )
   21.13          ret = -1;
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/control_if.h	Fri Mar 05 18:03:19 2004 +0000
    22.3 @@ -0,0 +1,32 @@
    22.4 +/******************************************************************************
    22.5 + * control_if.h
    22.6 + * 
    22.7 + * Copyright (c) 2004, K A Fraser
    22.8 + */
    22.9 +
   22.10 +#ifndef __CONTROL_IF_H__
   22.11 +#define __CONTROL_IF_H__
   22.12 +
   22.13 +typedef struct {
   22.14 +    u8 cmd_type;     /* echoed in response */
   22.15 +    u8 cmd_subtype;  /* echoed in response */
   22.16 +    u8 id;           /* echoed in response */
   22.17 +    u8 length;       /* number of bytes in 'msg' */
   22.18 +    unsigned char msg[60]; /* command-specific message data */
   22.19 +} control_msg_t;
   22.20 +
   22.21 +#define CONTROL_RING_SIZE 8
   22.22 +typedef unsigned int CONTROL_RING_IDX;
   22.23 +#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
   22.24 +
   22.25 +typedef struct {
   22.26 +    control_msg_t tx_ring[CONTROL_RING_SIZE]; /* guest-OS -> controller */
   22.27 +    control_msg_t rx_ring[CONTROL_RING_SIZE]; /* controller -> guest-OS */
   22.28 +    CONTROL_RING_IDX tx_req_prod, tx_resp_prod;
   22.29 +    CONTROL_RING_IDX rx_req_prod, rx_resp_prod;
   22.30 +} control_if_t;
   22.31 +
   22.32 +#define CMD_CONSOLE      0
   22.33 +#define CMD_CONSOLE_DATA 0
   22.34 +
   22.35 +#endif /* __CONTROL_IF_H__ */
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/evtchn.h	Fri Mar 05 18:03:19 2004 +0000
    23.3 @@ -0,0 +1,29 @@
    23.4 +/******************************************************************************
    23.5 + * evtchn.h
    23.6 + * 
    23.7 + * Driver for receiving and demuxing event-channel signals.
    23.8 + * 
    23.9 + * Copyright (c) 2004, K A Fraser
   23.10 + */
   23.11 +
   23.12 +#ifndef __ASM_EVTCHN_H__
   23.13 +#define __ASM_EVTCHN_H__
   23.14 +
   23.15 +typedef void (*evtchn_receiver_t)(unsigned int);
   23.16 +#define PORT_NORMAL     0x0000
   23.17 +#define PORT_DISCONNECT 0x8000
   23.18 +#define PORTIDX_MASK    0x7fff
   23.19 +
   23.20 +/* /dev/xen/evtchn resides at device number major=10, minor=200 */
   23.21 +#define EVTCHN_MINOR 200
   23.22 +
   23.23 +/* /dev/xen/evtchn ioctls: */
   23.24 +/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
   23.25 +#define EVTCHN_RESET _IO('E', 1)
   23.26 +
   23.27 +int evtchn_request_port(unsigned int port, evtchn_receiver_t rx_fn);
   23.28 +int evtchn_free_port(unsigned int port);
   23.29 +void evtchn_clear_port(unsigned int port);
   23.30 +
   23.31 +
   23.32 +#endif /* __ASM_EVTCHN_H__ */
    24.1 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h	Wed Mar 03 12:59:48 2004 +0000
    24.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h	Fri Mar 05 18:03:19 2004 +0000
    24.3 @@ -432,6 +432,17 @@ static inline int HYPERVISOR_update_va_m
    24.4      return ret;
    24.5  }
    24.6  
    24.7 +static inline int HYPERVISOR_event_channel_op(void *op)
    24.8 +{
    24.9 +    int ret;
   24.10 +    __asm__ __volatile__ (
   24.11 +        TRAP_INSTR
   24.12 +        : "=a" (ret) : "0" (__HYPERVISOR_event_channel_op),
   24.13 +        "b" (op) : "memory" );
   24.14 +
   24.15 +    return ret;
   24.16 +}
   24.17 +
   24.18  static inline int HYPERVISOR_xen_version(int cmd)
   24.19  {
   24.20      int ret;