direct-io.hg

changeset 1341:91373787e780

bitkeeper revision 1.888 (4097ba830csxjT0x_cALWOM7ixvRVQ)

On the way towards a network interface for new i/o world.
author kaf24@scramble.cl.cam.ac.uk
date Tue May 04 15:45:07 2004 +0000 (2004-05-04)
parents 9e1ef2196d83
children edc18ca91c16
files .rootkeys tools/xend/lib/domain_controller.h xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/blkif.h xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/Makefile xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/common.h xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/control.c xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c xenolinux-2.4.26-sparse/arch/xen/drivers/netif/netif.h xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c
line diff
     1.1 --- a/.rootkeys	Tue May 04 15:01:49 2004 +0000
     1.2 +++ b/.rootkeys	Tue May 04 15:45:07 2004 +0000
     1.3 @@ -682,9 +682,13 @@ 40420a6ebRqDjufoN1WSJvolEW2Wjw xenolinux
     1.4  40420a73Wou6JlsZDiu6YwjYomsm7A xenolinux-2.4.26-sparse/arch/xen/drivers/evtchn/evtchn.c
     1.5  4083dc16-Kd5y9psK_yk161sme5j5Q xenolinux-2.4.26-sparse/arch/xen/drivers/netif/Makefile
     1.6  4083dc16UmHXxS9g_UFVnkUpN-oP2Q xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/Makefile
     1.7 +4097ba83pPKYqMS3Gl-PVKIgYU1FZw xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/common.h
     1.8 +4097ba83glWYwQTkbPqgLIlYDOPVLg xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/control.c
     1.9 +4097ba837h2tuiweIWp-voNVzCRI6g xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c
    1.10  4087cf0d5dudKw_DecIJgOhLlBF_0Q xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c
    1.11  405853f2wg7JXZJNltspMwOZJklxgw xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/Makefile
    1.12  405853f6nbeazrNyEWNHBuoSg2PiPA xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c
    1.13 +4097ba83Qy2eafeFUhGhm6_4iMIIDw xenolinux-2.4.26-sparse/arch/xen/drivers/netif/netif.h
    1.14  3e5a4e65gZBRBB6RsSVg1c9iahigAw xenolinux-2.4.26-sparse/arch/xen/drivers/network/Makefile
    1.15  3e5a4e65ZxKrbFetVB84JhrTyZ1YuQ xenolinux-2.4.26-sparse/arch/xen/drivers/network/network.c
    1.16  3e5a4e65lWzkiPXsZdzPt2RNnJGG1g xenolinux-2.4.26-sparse/arch/xen/kernel/Makefile
     2.1 --- a/tools/xend/lib/domain_controller.h	Tue May 04 15:01:49 2004 +0000
     2.2 +++ b/tools/xend/lib/domain_controller.h	Tue May 04 15:45:07 2004 +0000
     2.3 @@ -52,9 +52,11 @@ typedef struct {
     2.4  /*
     2.5   * Top-level command types.
     2.6   */
     2.7 -#define CMSG_CONSOLE            0  /* Console               */
     2.8 -#define CMSG_BLKIF_BE           1  /* Block-device backend  */
     2.9 -#define CMSG_BLKIF_FE           2  /* Block-device frontend */
    2.10 +#define CMSG_CONSOLE        0  /* Console                 */
    2.11 +#define CMSG_BLKIF_BE       1  /* Block-device backend    */
    2.12 +#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
    2.13 +#define CMSG_NETIF_BE       3  /* Network-device backend  */
    2.14 +#define CMSG_NETIF_FE       4  /* Network-device frontend */
    2.15  
    2.16  
    2.17  /******************************************************************************
    2.18 @@ -112,7 +114,14 @@ typedef struct {
    2.19  #define BLKIF_DRIVER_STATUS_DOWN   0
    2.20  #define BLKIF_DRIVER_STATUS_UP     1
    2.21  typedef struct {
    2.22 +    /* IN */
    2.23      unsigned int status; /* BLKIF_DRIVER_STATUS_??? */
    2.24 +    /* OUT */
    2.25 +    /*
    2.26 +     * Tells driver how many interfaces it should expect to immediately
    2.27 +     * receive notifications about.
    2.28 +     */
    2.29 +    unsigned int nr_interfaces;
    2.30  } blkif_fe_driver_status_changed_t;
    2.31  
    2.32  /*
    2.33 @@ -131,14 +140,7 @@ typedef struct {
    2.34   *  STATUS_DISCONNECTED message.
    2.35   */
    2.36  typedef struct {
    2.37 -    /* IN */
    2.38      unsigned int handle;
    2.39 -    /* OUT */
    2.40 -    /*
    2.41 -     * Tells driver how many interfaces it should expect to immediately
    2.42 -     * receive notifications about.
    2.43 -     */
    2.44 -    unsigned int nr_interfaces;
    2.45  } blkif_fe_interface_disconnect_t;
    2.46  
    2.47  
    2.48 @@ -313,4 +315,188 @@ typedef struct {
    2.49      unsigned int nr_interfaces;
    2.50  } blkif_be_driver_status_changed_t;
    2.51  
    2.52 +
    2.53 +/******************************************************************************
    2.54 + * NETWORK-INTERFACE FRONTEND DEFINITIONS
    2.55 + */
    2.56 +
    2.57 +/* Messages from domain controller to guest. */
    2.58 +#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
    2.59 +
    2.60 +/* Messages from guest to domain controller. */
    2.61 +#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
    2.62 +#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
    2.63 +#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
    2.64 +
    2.65 +/*
    2.66 + * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
    2.67 + *  Notify a guest about a status change on one of its network interfaces.
    2.68 + *  If the interface is DESTROYED or DOWN then the interface is disconnected:
    2.69 + *   1. The shared-memory frame is available for reuse.
    2.70 + *   2. Any unacknowledged messgaes pending on the interface were dropped.
    2.71 + */
    2.72 +#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
    2.73 +#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
    2.74 +#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
    2.75 +typedef struct {
    2.76 +    unsigned int handle;
    2.77 +    unsigned int status;
    2.78 +    unsigned int evtchn; /* status == NETIF_INTERFACE_STATUS_CONNECTED */
    2.79 +} netif_fe_interface_status_changed_t;
    2.80 +
    2.81 +/*
    2.82 + * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
    2.83 + *  Notify the domain controller that the front-end driver is DOWN or UP.
    2.84 + *  When the driver goes DOWN then the controller will send no more
    2.85 + *  status-change notifications. When the driver comes UP then the controller
    2.86 + *  will send a notification for each interface that currently exists.
    2.87 + *  If the driver goes DOWN while interfaces are still UP, the domain
    2.88 + *  will automatically take the interfaces DOWN.
    2.89 + */
    2.90 +#define NETIF_DRIVER_STATUS_DOWN   0
    2.91 +#define NETIF_DRIVER_STATUS_UP     1
    2.92 +typedef struct {
    2.93 +    /* IN */
    2.94 +    unsigned int status; /* NETIF_DRIVER_STATUS_??? */
    2.95 +    /* OUT */
    2.96 +    /*
    2.97 +     * Tells driver how many interfaces it should expect to immediately
    2.98 +     * receive notifications about.
    2.99 +     */
   2.100 +    unsigned int nr_interfaces;
   2.101 +} netif_fe_driver_status_changed_t;
   2.102 +
   2.103 +/*
   2.104 + * CMSG_NETIF_FE_INTERFACE_CONNECT:
   2.105 + *  If successful, the domain controller will acknowledge with a
   2.106 + *  STATUS_CONNECTED message.
   2.107 + */
   2.108 +typedef struct {
   2.109 +    unsigned int  handle;
   2.110 +    unsigned long shmem_frame;
   2.111 +} netif_fe_interface_connect_t;
   2.112 +
   2.113 +/*
   2.114 + * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
   2.115 + *  If successful, the domain controller will acknowledge with a
   2.116 + *  STATUS_DISCONNECTED message.
   2.117 + */
   2.118 +typedef struct {
   2.119 +    unsigned int handle;
   2.120 +} netif_fe_interface_disconnect_t;
   2.121 +
   2.122 +
   2.123 +/******************************************************************************
   2.124 + * NETWORK-INTERFACE BACKEND DEFINITIONS
   2.125 + */
   2.126 +
   2.127 +/* Messages from domain controller. */
   2.128 +#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
   2.129 +#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
   2.130 +#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
   2.131 +#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
   2.132 +
   2.133 +/* Messages to domain controller. */
   2.134 +#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
   2.135 +
   2.136 +/*
   2.137 + * Message request/response definitions for net-device messages.
   2.138 + */
   2.139 +
   2.140 +/* Non-specific 'okay' return. */
   2.141 +#define NETIF_BE_STATUS_OKAY                0
   2.142 +/* Non-specific 'error' return. */
   2.143 +#define NETIF_BE_STATUS_ERROR               1
   2.144 +/* The following are specific error returns. */
   2.145 +#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
   2.146 +#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
   2.147 +#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
   2.148 +#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
   2.149 +#define NETIF_BE_STATUS_MAPPING_ERROR       6
   2.150 +
   2.151 +/* This macro can be used to create an array of descriptive error strings. */
   2.152 +#define NETIF_BE_STATUS_ERRORS {    \
   2.153 +    "Okay",                         \
   2.154 +    "Non-specific error",           \
   2.155 +    "Interface already exists",     \
   2.156 +    "Interface not found",          \
   2.157 +    "Interface is still connected", \
   2.158 +    "Out of memory",                \
   2.159 +    "Could not map domain memory" }
   2.160 +
   2.161 +/*
   2.162 + * CMSG_NETIF_BE_CREATE:
   2.163 + *  When the driver sends a successful response then the interface is fully
   2.164 + *  created. The controller will send a DOWN notification to the front-end
   2.165 + *  driver.
   2.166 + */
   2.167 +typedef struct { 
   2.168 +    /* IN */
   2.169 +    domid_t        domid;             /* Domain attached to new interface.   */
   2.170 +    unsigned int   netif_handle;      /* Domain-specific interface handle.   */
   2.171 +    /* OUT */
   2.172 +    unsigned int   status;
   2.173 +} netif_be_create_t; 
   2.174 +
   2.175 +/*
   2.176 + * CMSG_NETIF_BE_DESTROY:
   2.177 + *  When the driver sends a successful response then the interface is fully
   2.178 + *  torn down. The controller will send a DESTROYED notification to the
   2.179 + *  front-end driver.
   2.180 + */
   2.181 +typedef struct { 
   2.182 +    /* IN */
   2.183 +    domid_t        domid;             /* Identify interface to be destroyed. */
   2.184 +    unsigned int   netif_handle;      /* ...ditto...                         */
   2.185 +    /* OUT */
   2.186 +    unsigned int   status;
   2.187 +} netif_be_destroy_t; 
   2.188 +
   2.189 +/*
   2.190 + * CMSG_NETIF_BE_CONNECT:
   2.191 + *  When the driver sends a successful response then the interface is fully
   2.192 + *  connected. The controller will send a CONNECTED notification to the
   2.193 + *  front-end driver.
   2.194 + */
   2.195 +typedef struct { 
   2.196 +    /* IN */
   2.197 +    domid_t        domid;             /* Domain attached to new interface.   */
   2.198 +    unsigned int   netif_handle;      /* Domain-specific interface handle.   */
   2.199 +    unsigned int   evtchn;            /* Event channel for notifications.    */
   2.200 +    unsigned long  shmem_frame;       /* Page cont. shared comms window.     */
   2.201 +    /* OUT */
   2.202 +    unsigned int   status;
   2.203 +} netif_be_connect_t; 
   2.204 +
   2.205 +/*
   2.206 + * CMSG_NETIF_BE_DISCONNECT:
   2.207 + *  When the driver sends a successful response then the interface is fully
   2.208 + *  disconnected. The controller will send a DOWN notification to the front-end
   2.209 + *  driver.
   2.210 + */
   2.211 +typedef struct { 
   2.212 +    /* IN */
   2.213 +    domid_t        domid;             /* Domain attached to new interface.   */
   2.214 +    unsigned int   netif_handle;      /* Domain-specific interface handle.   */
   2.215 +    /* OUT */
   2.216 +    unsigned int   status;
   2.217 +} netif_be_disconnect_t; 
   2.218 +
   2.219 +/*
   2.220 + * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
   2.221 + *  Notify the domain controller that the back-end driver is DOWN or UP.
   2.222 + *  If the driver goes DOWN while interfaces are still UP, the domain
   2.223 + *  will automatically send DOWN notifications.
   2.224 + */
   2.225 +typedef struct {
   2.226 +    /* IN */
   2.227 +    unsigned int status; /* NETIF_DRIVER_STATUS_??? */
   2.228 +    /* OUT */
   2.229 +    /*
   2.230 +     * Tells driver how many interfaces it should expect to immediately
   2.231 +     * receive notifications about.
   2.232 +     */
   2.233 +    unsigned int nr_interfaces;
   2.234 +} netif_be_driver_status_changed_t;
   2.235 +
   2.236  #endif /* __DOMAIN_CONTROLLER_H__ */
     3.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c	Tue May 04 15:01:49 2004 +0000
     3.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/backend/main.c	Tue May 04 15:45:07 2004 +0000
     3.3 @@ -380,6 +380,7 @@ static void dispatch_rw_block_io(blkif_t
     3.4      pending_req->operation = operation;
     3.5      pending_req->status    = BLKIF_RSP_OKAY;
     3.6      atomic_set(&pending_req->pendcnt, nr_psegs);
     3.7 +    pending_cons++;
     3.8  
     3.9      blkif_get(blkif);
    3.10  
    3.11 @@ -412,7 +413,6 @@ static void dispatch_rw_block_io(blkif_t
    3.12          generic_make_request(operation, bh);
    3.13      }
    3.14  
    3.15 -    pending_cons++;
    3.16      return;
    3.17  
    3.18   bad_descriptor:
     4.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/blkif.h	Tue May 04 15:01:49 2004 +0000
     4.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/blkif/blkif.h	Tue May 04 15:45:07 2004 +0000
     4.3 @@ -29,8 +29,8 @@
     4.4  #define BLKIF_MAX_SECTORS_PER_SEGMENT  16
     4.5  
     4.6  typedef struct {
     4.7 -    unsigned char  operation;        /* BLKIF_OP_???                         */
     4.8 -    unsigned char  nr_segments;      /* number of segments                   */
     4.9 +    u8             operation;        /* BLKIF_OP_???                         */
    4.10 +    u8             nr_segments;      /* number of segments                   */
    4.11      blkif_vdev_t   device;           /* only for read/write requests         */
    4.12      unsigned long  id;               /* private guest value, echoed in resp  */
    4.13      blkif_sector_t sector_number;    /* start sector idx on disk (r/w only)  */
    4.14 @@ -41,8 +41,8 @@ typedef struct {
    4.15  
    4.16  typedef struct {
    4.17      unsigned long   id;              /* copied from request */
    4.18 -    unsigned char   operation;       /* copied from request */
    4.19 -    int             status;          /* BLKIF_RSP_???       */
    4.20 +    u8              operation;       /* copied from request */
    4.21 +    s16             status;          /* BLKIF_RSP_???       */
    4.22  } blkif_response_t;
    4.23  
    4.24  #define BLKIF_RSP_ERROR  -1 /* non-specific 'error' */
    4.25 @@ -104,9 +104,9 @@ typedef struct {
    4.26  #define VDISK_VIRTUAL(_x)  ((_x) & VDISK_FLAG_VIRT) 
    4.27  
    4.28  typedef struct {
    4.29 +    blkif_sector_t capacity;     /* Size in terms of 512-byte sectors.   */
    4.30      blkif_vdev_t   device;       /* Device number (opaque 16 bit value). */
    4.31 -    unsigned short info;         /* Device type and flags (VDISK_*).     */
    4.32 -    blkif_sector_t capacity;     /* Size in terms of 512-byte sectors.   */
    4.33 +    u16            info;         /* Device type and flags (VDISK_*).     */
    4.34  } vdisk_t;
    4.35  
    4.36  #endif /* __SHARED_BLKIF_H__ */
     5.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/Makefile	Tue May 04 15:01:49 2004 +0000
     5.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/Makefile	Tue May 04 15:45:07 2004 +0000
     5.3 @@ -1,3 +1,3 @@
     5.4  O_TARGET := drv.o
     5.5 -obj-y := main.o
     5.6 +obj-y := main.o control.o interface.o
     5.7  include $(TOPDIR)/Rules.make
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/common.h	Tue May 04 15:45:07 2004 +0000
     6.3 @@ -0,0 +1,98 @@
     6.4 +/******************************************************************************
     6.5 + * arch/xen/drivers/netif/backend/common.h
     6.6 + */
     6.7 +
     6.8 +#ifndef __NETIF__BACKEND__COMMON_H__
     6.9 +#define __NETIF__BACKEND__COMMON_H__
    6.10 +
    6.11 +#include <linux/config.h>
    6.12 +#include <linux/module.h>
    6.13 +#include <linux/interrupt.h>
    6.14 +#include <linux/slab.h>
    6.15 +#include <linux/ip.h>
    6.16 +#include <linux/in.h>
    6.17 +#include <linux/netdevice.h>
    6.18 +#include <linux/etherdevice.h>
    6.19 +#include <asm/ctrl_if.h>
    6.20 +#include <asm/io.h>
    6.21 +#include "../netif.h"
    6.22 +
    6.23 +#ifndef NDEBUG
    6.24 +#define ASSERT(_p) \
    6.25 +    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
    6.26 +    __LINE__, __FILE__); *(int*)0=0; }
    6.27 +#define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \
    6.28 +                           __FILE__ , __LINE__ , ## _a )
    6.29 +#else
    6.30 +#define ASSERT(_p) ((void)0)
    6.31 +#define DPRINTK(_f, _a...) ((void)0)
    6.32 +#endif
    6.33 +
    6.34 +typedef struct {
    6.35 +    /* Unique identifier for this interface. */
    6.36 +    domid_t          domid;
    6.37 +    unsigned int     handle;
    6.38 +
    6.39 +    /* Physical parameters of the comms window. */
    6.40 +    unsigned long    tx_shmem_frame;
    6.41 +    unsigned long    rx_shmem_frame;
    6.42 +    unsigned int     evtchn;
    6.43 +    int              irq;
    6.44 +
    6.45 +    /* The shared rings and indexes. */
    6.46 +    netif_tx_interface_t *tx;
    6.47 +    netif_rx_interface_t *rx;
    6.48 +
    6.49 +    /* Private indexes into shared ring. */
    6.50 +    NETIF_RING_IDX rx_req_cons;
    6.51 +    NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */
    6.52 +    NETIF_RING_IDX tx_req_cons;
    6.53 +    NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */
    6.54 +
    6.55 +    /* Usage accounting */
    6.56 +    long long total_bytes_sent;
    6.57 +    long long total_bytes_received;
    6.58 +    long long total_packets_sent;
    6.59 +    long long total_packets_received;
    6.60 +
    6.61 +    /* Trasnmit shaping: allow 'credit_bytes' every 'credit_usec'. */
    6.62 +    unsigned long   credit_bytes;
    6.63 +    unsigned long   credit_usec;
    6.64 +    unsigned long   remaining_credit;
    6.65 +    struct timer_list credit_timeout;
    6.66 +
    6.67 +    /* Miscellaneous private stuff. */
    6.68 +    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
    6.69 +    /*
    6.70 +     * DISCONNECT response is deferred until pending requests are ack'ed.
    6.71 +     * We therefore need to store the id from the original request.
    6.72 +     */
    6.73 +    u8               disconnect_rspid;
    6.74 +    struct netif_st *hash_next;
    6.75 +    struct list_head list;  /* scheduling list */
    6.76 +    atomic_t         refcnt;
    6.77 +    spinlock_t       rx_lock, tx_lock;
    6.78 +    unsigned char    vmac[ETH_ALEN];
    6.79 +} netif_t;
    6.80 +
    6.81 +void netif_create(netif_be_create_t *create);
    6.82 +void netif_destroy(netif_be_destroy_t *destroy);
    6.83 +void netif_connect(netif_be_connect_t *connect);
    6.84 +int  netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id);
    6.85 +void __netif_disconnect_complete(netif_t *netif);
    6.86 +netif_t *netif_find_by_handle(domid_t domid, unsigned int handle);
    6.87 +#define netif_get(_b) (atomic_inc(&(_b)->refcnt))
    6.88 +#define netif_put(_b)                             \
    6.89 +    do {                                          \
    6.90 +        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
    6.91 +            __netif_disconnect_complete(_b);      \
    6.92 +    } while (0)
    6.93 +
    6.94 +void netif_interface_init(void);
    6.95 +void netif_ctrlif_init(void);
    6.96 +
    6.97 +void netif_deschedule(netif_t *netif);
    6.98 +
    6.99 +void netif_be_int(int irq, void *dev_id, struct pt_regs *regs);
   6.100 +
   6.101 +#endif /* __NETIF__BACKEND__COMMON_H__ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/control.c	Tue May 04 15:45:07 2004 +0000
     7.3 @@ -0,0 +1,66 @@
     7.4 +/******************************************************************************
     7.5 + * arch/xen/drivers/netif/backend/control.c
     7.6 + * 
     7.7 + * Routines for interfacing with the control plane.
     7.8 + * 
     7.9 + * Copyright (c) 2004, Keir Fraser
    7.10 + */
    7.11 +
    7.12 +#include "common.h"
    7.13 +
    7.14 +static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
    7.15 +{
    7.16 +    DPRINTK("Received netif backend message, subtype=%d\n", msg->subtype);
    7.17 +    
    7.18 +    switch ( msg->subtype )
    7.19 +    {
    7.20 +    case CMSG_NETIF_BE_CREATE:
    7.21 +        if ( msg->length != sizeof(netif_be_create_t) )
    7.22 +            goto parse_error;
    7.23 +        netif_create((netif_be_create_t *)&msg->msg[0]);
    7.24 +        break;        
    7.25 +    case CMSG_NETIF_BE_DESTROY:
    7.26 +        if ( msg->length != sizeof(netif_be_destroy_t) )
    7.27 +            goto parse_error;
    7.28 +        netif_destroy((netif_be_destroy_t *)&msg->msg[0]);
    7.29 +        break;        
    7.30 +    case CMSG_NETIF_BE_CONNECT:
    7.31 +        if ( msg->length != sizeof(netif_be_connect_t) )
    7.32 +            goto parse_error;
    7.33 +        netif_connect((netif_be_connect_t *)&msg->msg[0]);
    7.34 +        break;        
    7.35 +    case CMSG_NETIF_BE_DISCONNECT:
    7.36 +        if ( msg->length != sizeof(netif_be_disconnect_t) )
    7.37 +            goto parse_error;
    7.38 +        if ( !netif_disconnect((netif_be_disconnect_t *)&msg->msg[0],msg->id) )
    7.39 +            return; /* Sending the response is deferred until later. */
    7.40 +        break;        
    7.41 +    default:
    7.42 +        goto parse_error;
    7.43 +    }
    7.44 +
    7.45 +    ctrl_if_send_response(msg);
    7.46 +    return;
    7.47 +
    7.48 + parse_error:
    7.49 +    DPRINTK("Parse error while reading message subtype %d, len %d\n",
    7.50 +            msg->subtype, msg->length);
    7.51 +    msg->length = 0;
    7.52 +    ctrl_if_send_response(msg);
    7.53 +}
    7.54 +
    7.55 +void netif_ctrlif_init(void)
    7.56 +{
    7.57 +    ctrl_msg_t                       cmsg;
    7.58 +    netif_be_driver_status_changed_t st;
    7.59 +
    7.60 +    (void)ctrl_if_register_receiver(CMSG_NETIF_BE, netif_ctrlif_rx);
    7.61 +
    7.62 +    /* Send a driver-UP notification to the domain controller. */
    7.63 +    cmsg.type      = CMSG_NETIF_BE;
    7.64 +    cmsg.subtype   = CMSG_NETIF_BE_DRIVER_STATUS_CHANGED;
    7.65 +    cmsg.length    = sizeof(netif_be_driver_status_changed_t);
    7.66 +    st.status      = NETIF_DRIVER_STATUS_UP;
    7.67 +    memcpy(cmsg.msg, &st, sizeof(st));
    7.68 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
    7.69 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/interface.c	Tue May 04 15:45:07 2004 +0000
     8.3 @@ -0,0 +1,330 @@
     8.4 +/******************************************************************************
     8.5 + * arch/xen/drivers/netif/backend/interface.c
     8.6 + * 
     8.7 + * Network-device interface management.
     8.8 + * 
     8.9 + * Copyright (c) 2004, Keir Fraser
    8.10 + */
    8.11 +
    8.12 +#include "common.h"
    8.13 +
    8.14 +#define NETIF_HASHSZ 1024
    8.15 +#define NETIF_HASH(_d,_h) \
    8.16 +    (((int)(_d)^(int)((_d)>>32)^(int)(_h))&(NETIF_HASHSZ-1))
    8.17 +
    8.18 +static kmem_cache_t *netif_cachep;
    8.19 +static netif_t      *netif_hash[NETIF_HASHSZ];
    8.20 +
    8.21 +netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
    8.22 +{
    8.23 +    netif_t *netif = netif_hash[NETIF_HASH(domid, handle)];
    8.24 +    while ( (netif != NULL) && 
    8.25 +            ((netif->domid != domid) || (netif->handle != handle)) )
    8.26 +        netif = netif->hash_next;
    8.27 +    return netif;
    8.28 +}
    8.29 +
    8.30 +void __netif_disconnect_complete(netif_t *netif)
    8.31 +{
    8.32 +    ctrl_msg_t            cmsg;
    8.33 +    netif_be_disconnect_t disc;
    8.34 +
    8.35 +    /*
    8.36 +     * These can't be done in __netif_disconnect() because at that point there
    8.37 +     * may be outstanding requests at the disc whose asynchronous responses
    8.38 +     * must still be notified to the remote driver.
    8.39 +     */
    8.40 +    unbind_evtchn_from_irq(netif->evtchn);
    8.41 +    vfree(netif->net_ring_base);
    8.42 +
    8.43 +    /* Construct the deferred response message. */
    8.44 +    cmsg.type         = CMSG_NETIF_BE;
    8.45 +    cmsg.subtype      = CMSG_NETIF_BE_DISCONNECT;
    8.46 +    cmsg.id           = netif->disconnect_rspid;
    8.47 +    cmsg.length       = sizeof(netif_be_disconnect_t);
    8.48 +    disc.domid        = netif->domid;
    8.49 +    disc.netif_handle = netif->handle;
    8.50 +    disc.status       = NETIF_BE_STATUS_OKAY;
    8.51 +    memcpy(cmsg.msg, &disc, sizeof(disc));
    8.52 +
    8.53 +    /*
    8.54 +     * Make sure message is constructed /before/ status change, because
    8.55 +     * after the status change the 'netif' structure could be deallocated at
    8.56 +     * any time. Also make sure we send the response /after/ status change,
    8.57 +     * as otherwise a subsequent CONNECT request could spuriously fail if
    8.58 +     * another CPU doesn't see the status change yet.
    8.59 +     */
    8.60 +    mb();
    8.61 +    if ( netif->status != DISCONNECTING )
    8.62 +        BUG();
    8.63 +    netif->status = DISCONNECTED;
    8.64 +    mb();
    8.65 +
    8.66 +    /* Send the successful response. */
    8.67 +    ctrl_if_send_response(&cmsg);
    8.68 +}
    8.69 +
    8.70 +void netif_create(netif_be_create_t *create)
    8.71 +{
    8.72 +    domid_t       domid  = create->domid;
    8.73 +    unsigned int  handle = create->netif_handle;
    8.74 +    netif_t     **pnetif, *netif;
    8.75 +
    8.76 +    if ( (netif = kmem_cache_alloc(netif_cachep, GFP_ATOMIC)) == NULL )
    8.77 +    {
    8.78 +        DPRINTK("Could not create netif: out of memory\n");
    8.79 +        create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
    8.80 +        return;
    8.81 +    }
    8.82 +
    8.83 +    memset(netif, 0, sizeof(*netif));
    8.84 +    netif->domid  = domid;
    8.85 +    netif->handle = handle;
    8.86 +    netif->status = DISCONNECTED;
    8.87 +    spin_lock_init(&netif->vbd_lock);
    8.88 +    spin_lock_init(&netif->net_ring_lock);
    8.89 +    atomic_set(&netif->refcnt, 0);
    8.90 +
    8.91 +    pnetif = &netif_hash[NETIF_HASH(domid, handle)];
    8.92 +    while ( *pnetif != NULL )
    8.93 +    {
    8.94 +        if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) )
    8.95 +        {
    8.96 +            DPRINTK("Could not create netif: already exists\n");
    8.97 +            create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
    8.98 +            kmem_cache_free(netif_cachep, netif);
    8.99 +            return;
   8.100 +        }
   8.101 +        pnetif = &(*pnetif)->hash_next;
   8.102 +    }
   8.103 +
   8.104 +    netif->hash_next = *pnetif;
   8.105 +    *pnetif = netif;
   8.106 +
   8.107 +    DPRINTK("Successfully created netif\n");
   8.108 +    create->status = NETIF_BE_STATUS_OKAY;
   8.109 +}
   8.110 +
   8.111 +void netif_destroy(netif_be_destroy_t *destroy)
   8.112 +{
   8.113 +    domid_t       domid  = destroy->domid;
   8.114 +    unsigned int  handle = destroy->netif_handle;
   8.115 +    netif_t     **pnetif, *netif;
   8.116 +
   8.117 +    pnetif = &netif_hash[NETIF_HASH(domid, handle)];
   8.118 +    while ( (netif = *pnetif) != NULL )
   8.119 +    {
   8.120 +        if ( (netif->domid == domid) && (netif->handle == handle) )
   8.121 +        {
   8.122 +            if ( netif->status != DISCONNECTED )
   8.123 +                goto still_connected;
   8.124 +            goto destroy;
   8.125 +        }
   8.126 +        pnetif = &netif->hash_next;
   8.127 +    }
   8.128 +
   8.129 +    destroy->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
   8.130 +    return;
   8.131 +
   8.132 + still_connected:
   8.133 +    destroy->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
   8.134 +    return;
   8.135 +
   8.136 + destroy:
   8.137 +    *pnetif = netif->hash_next;
   8.138 +    destroy_all_vbds(netif);
   8.139 +    kmem_cache_free(netif_cachep, netif);
   8.140 +    destroy->status = NETIF_BE_STATUS_OKAY;
   8.141 +}
   8.142 +
   8.143 +void netif_connect(netif_be_connect_t *connect)
   8.144 +{
   8.145 +    domid_t       domid  = connect->domid;
   8.146 +    unsigned int  handle = connect->netif_handle;
   8.147 +    unsigned int  evtchn = connect->evtchn;
   8.148 +    unsigned long shmem_frame = connect->shmem_frame;
   8.149 +    struct vm_struct *vma;
   8.150 +    pgprot_t      prot;
   8.151 +    int           error;
   8.152 +    netif_t      *netif;
   8.153 +
   8.154 +    netif = netif_find_by_handle(domid, handle);
   8.155 +    if ( unlikely(netif == NULL) )
   8.156 +    {
   8.157 +        DPRINTK("netif_connect attempted for non-existent netif (%llu,%u)\n", 
   8.158 +                connect->domid, connect->netif_handle); 
   8.159 +        connect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
   8.160 +        return;
   8.161 +    }
   8.162 +
   8.163 +    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
   8.164 +    {
   8.165 +        connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
   8.166 +        return;
   8.167 +    }
   8.168 +
   8.169 +    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
   8.170 +    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
   8.171 +                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
   8.172 +                                    prot, domid);
   8.173 +    if ( error != 0 )
   8.174 +    {
   8.175 +        if ( error == -ENOMEM )
   8.176 +            connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
   8.177 +        else if ( error == -EFAULT )
   8.178 +            connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
   8.179 +        else
   8.180 +            connect->status = NETIF_BE_STATUS_ERROR;
   8.181 +        vfree(vma->addr);
   8.182 +        return;
   8.183 +    }
   8.184 +
   8.185 +    if ( netif->status != DISCONNECTED )
   8.186 +    {
   8.187 +        connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
   8.188 +        vfree(vma->addr);
   8.189 +        return;
   8.190 +    }
   8.191 +
   8.192 +    netif->evtchn        = evtchn;
   8.193 +    netif->irq           = bind_evtchn_to_irq(evtchn);
   8.194 +    netif->shmem_frame   = shmem_frame;
   8.195 +    netif->net_ring_base = (netif_ring_t *)vma->addr;
   8.196 +    netif->status        = CONNECTED;
   8.197 +    netif_get(netif);
   8.198 +
   8.199 +    request_irq(netif->irq, netif_be_int, 0, "netif-backend", netif);
   8.200 +
   8.201 +    connect->status = NETIF_BE_STATUS_OKAY;
   8.202 +}
   8.203 +
   8.204 +int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
   8.205 +{
   8.206 +    domid_t       domid  = disconnect->domid;
   8.207 +    unsigned int  handle = disconnect->netif_handle;
   8.208 +    netif_t      *netif;
   8.209 +
   8.210 +    netif = netif_find_by_handle(domid, handle);
   8.211 +    if ( unlikely(netif == NULL) )
   8.212 +    {
   8.213 +        DPRINTK("netif_disconnect attempted for non-existent netif"
   8.214 +                " (%llu,%u)\n", disconnect->domid, disconnect->netif_handle); 
   8.215 +        disconnect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
   8.216 +        return 1; /* Caller will send response error message. */
   8.217 +    }
   8.218 +
   8.219 +    if ( netif->status == CONNECTED )
   8.220 +    {
   8.221 +        netif->status = DISCONNECTING;
   8.222 +        netif->disconnect_rspid = rsp_id;
   8.223 +        wmb(); /* Let other CPUs see the status change. */
   8.224 +        free_irq(netif->irq, NULL);
   8.225 +        netif_deschedule(netif);
   8.226 +        netif_put(netif);
   8.227 +    }
   8.228 +
   8.229 +    return 0; /* Caller should not send response message. */
   8.230 +}
   8.231 +
   8.232 +net_vif_t *create_net_vif(domid_t dom)
   8.233 +{
   8.234 +    unsigned int idx;
   8.235 +    net_vif_t *new_vif = NULL;
   8.236 +    net_ring_t *new_ring = NULL;
   8.237 +    struct task_struct *p = NULL;
   8.238 +    unsigned long flags, vmac_hash;
   8.239 +    unsigned char vmac_key[ETH_ALEN + 2 + MAX_DOMAIN_NAME];
   8.240 +
   8.241 +    if ( (p = find_domain_by_id(dom)) == NULL )
   8.242 +        return NULL;
   8.243 +    
   8.244 +    write_lock_irqsave(&tasklist_lock, flags);
   8.245 +
   8.246 +    for ( idx = 0; idx < MAX_DOMAIN_VIFS; idx++ )
   8.247 +        if ( p->net_vif_list[idx] == NULL )
   8.248 +            break;
   8.249 +    if ( idx == MAX_DOMAIN_VIFS )
   8.250 +        goto fail;
   8.251 +
   8.252 +    if ( (new_vif = kmem_cache_alloc(net_vif_cache, GFP_KERNEL)) == NULL )
   8.253 +        goto fail;
   8.254 +
   8.255 +    memset(new_vif, 0, sizeof(*new_vif));
   8.256 +    
   8.257 +    if ( sizeof(net_ring_t) > PAGE_SIZE )
   8.258 +        BUG();
   8.259 +    new_ring = (net_ring_t *)get_free_page(GFP_KERNEL);
   8.260 +    clear_page(new_ring);
   8.261 +    SHARE_PFN_WITH_DOMAIN(virt_to_page(new_ring), p);
   8.262 +
   8.263 +    /*
   8.264 +     * Fill in the new vif struct. Note that, while the vif's refcnt is
   8.265 +     * non-zero, we hold a reference to the task structure.
   8.266 +     */
   8.267 +    atomic_set(&new_vif->refcnt, 1);
   8.268 +    new_vif->shared_rings = new_ring;
   8.269 +    new_vif->shared_idxs  = &p->shared_info->net_idx[idx];
   8.270 +    new_vif->domain       = p;
   8.271 +    new_vif->idx          = idx;
   8.272 +    new_vif->list.next    = NULL;
   8.273 +    spin_lock_init(&new_vif->rx_lock);
   8.274 +    spin_lock_init(&new_vif->tx_lock);
   8.275 +
   8.276 +    new_vif->credit_bytes = new_vif->remaining_credit = ~0UL;
   8.277 +    new_vif->credit_usec  = 0UL;
   8.278 +    init_ac_timer(&new_vif->credit_timeout);
   8.279 +
   8.280 +    if ( (p->domain == 0) && (idx == 0) )
   8.281 +    {
   8.282 +        /*
   8.283 +         * DOM0/VIF0 gets the real physical MAC address, so that users can
   8.284 +         * easily get a Xen-based machine up and running by using an existing
   8.285 +         * DHCP entry.
   8.286 +         */
   8.287 +        memcpy(new_vif->vmac, the_dev->dev_addr, ETH_ALEN);
   8.288 +    }
   8.289 +    else
   8.290 +    {
   8.291 +        /*
   8.292 +         * Most VIFs get a random MAC address with a "special" vendor id.
   8.293 +         * We try to get MAC addresses to be unique across multiple servers
   8.294 +         * by including the physical MAC address in the hash. The hash also
   8.295 +         * includes the vif index and the domain's name.
   8.296 +         * 
   8.297 +         * NB. The vendor is currently an "obsolete" one that used to belong
   8.298 +         * to DEC (AA-00-00). Using it is probably a bit rude :-)
   8.299 +         * 
   8.300 +         * NB2. The first bit of the first random octet is set to zero for
   8.301 +         * all dynamic MAC addresses. This may allow us to manually specify
   8.302 +         * MAC addresses for some VIFs with no fear of clashes.
   8.303 +         */
   8.304 +        memcpy(&vmac_key[0], the_dev->dev_addr, ETH_ALEN);
   8.305 +        *(__u16 *)(&vmac_key[ETH_ALEN]) = htons(idx);
   8.306 +        strcpy(&vmac_key[ETH_ALEN+2], p->name);
   8.307 +        vmac_hash = hash(vmac_key, ETH_ALEN + 2 + strlen(p->name));
   8.308 +        memcpy(new_vif->vmac, "\xaa\x00\x00", 3);
   8.309 +        new_vif->vmac[3] = (vmac_hash >> 16) & 0xef; /* First bit is zero. */
   8.310 +        new_vif->vmac[4] = (vmac_hash >>  8) & 0xff;
   8.311 +        new_vif->vmac[5] = (vmac_hash >>  0) & 0xff;
   8.312 +    }
   8.313 +
   8.314 +    p->net_vif_list[idx] = new_vif;
   8.315 +    
   8.316 +    write_unlock_irqrestore(&tasklist_lock, flags);
   8.317 +    return new_vif;
   8.318 +    
   8.319 + fail:
   8.320 +    write_unlock_irqrestore(&tasklist_lock, flags);
   8.321 +    if ( new_vif != NULL )
   8.322 +        kmem_cache_free(net_vif_cache, new_vif);
   8.323 +    if ( p != NULL )
   8.324 +        put_task_struct(p);
   8.325 +    return NULL;
   8.326 +}
   8.327 +
   8.328 +void netif_interface_init(void)
   8.329 +{
   8.330 +    netif_cachep = kmem_cache_create("netif_cache", sizeof(netif_t), 
   8.331 +                                     0, 0, NULL, NULL);
   8.332 +    memset(netif_hash, 0, sizeof(netif_hash));
   8.333 +}
     9.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c	Tue May 04 15:01:49 2004 +0000
     9.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c	Tue May 04 15:45:07 2004 +0000
     9.3 @@ -7,20 +7,469 @@
     9.4   * reference front-end implementation can be found in:
     9.5   *  arch/xen/drivers/netif/frontend
     9.6   * 
     9.7 - * Copyright (c) 2004, K A Fraser
     9.8 + * Copyright (c) 2002-2004, K A Fraser
     9.9 + */
    9.10 +
    9.11 +#include "common.h"
    9.12 +
    9.13 +static void make_tx_response(netif_t *netif, 
    9.14 +                             u16      id,
    9.15 +                             s8       st);
    9.16 +static void make_rx_response(netif_t     *netif, 
    9.17 +                             u16          id, 
    9.18 +                             s8           st,
    9.19 +                             netif_addr_t addr,
    9.20 +                             u16          size);
    9.21 +
    9.22 +/* Don't currently gate addition of an interface to the tx scheduling list. */
    9.23 +#define tx_work_exists(_if) (1)
    9.24 +
    9.25 +#define MAX_PENDING_REQS 256
    9.26 +static struct vm_struct *mmap_vma;
    9.27 +#define MMAP_VADDR(_req) ((unsigned long)mmap_vma->addr + ((_req) * PAGE_SIZE))
    9.28 +
    9.29 +/*static pending_req_t pending_reqs[MAX_PENDING_REQS];*/
    9.30 +static u16 pending_ring[MAX_PENDING_REQS];
    9.31 +static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
    9.32 +/* NB. We use a different index type to differentiate from shared blk rings. */
    9.33 +typedef unsigned int PEND_RING_IDX;
    9.34 +#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
    9.35 +static PEND_RING_IDX pending_prod, pending_cons;
    9.36 +#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
    9.37 +
    9.38 +/*
    9.39 + * This is the primary RECEIVE function for a network interface.
    9.40 + * Note that, from the p.o.v. of /this/ OS it looks like a transmit.
    9.41 + */
    9.42 +static void netif_start_xmit(struct sk_buff *skb, struct net_device *dev)
    9.43 +{
    9.44 +    netif_t *netif = (netif_t *)dev->priv;
    9.45 +    s8 status = BLKIF_RSP_OKAY;
    9.46 +    u16 size;
    9.47 +    mmu_update_t mmu[4];
    9.48 +
    9.49 +    memcpy(skb->mac.ethernet->h_dest, netif->vmac, ETH_ALEN);
    9.50 +    if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
    9.51 +        memcpy(skb->nh.raw + 18, netif->vmac, ETH_ALEN);
    9.52 +
    9.53 +    spin_lock(&netif->rx_lock);
    9.54 +
    9.55 +    mmu[0].val  = (unsigned long)(netif->domid<<16) & ~0xFFFFUL;
    9.56 +    mmu[0].ptr  = (unsigned long)(netif->domid<< 0) & ~0xFFFFUL;
    9.57 +    mmu[1].val  = (unsigned long)(netif->domid>>16) & ~0xFFFFUL;
    9.58 +    mmu[1].ptr  = (unsigned long)(netif->domid>>32) & ~0xFFFFUL;
    9.59 +    mmu[0].ptr |= MMU_EXTENDED_COMMAND;
    9.60 +    mmu[0].val |= MMUEXT_SET_SUBJECTDOM_L;
    9.61 +    mmu[1].ptr |= MMU_EXTENDED_COMMAND;
    9.62 +    mmu[1].val |= MMUEXT_SET_SUBJECTDOM_H;
    9.63 +
    9.64 +    mmu[2].ptr  = ptr | MMU_EXTENDED_COMMAND;
    9.65 +    mmu[2].val  = MMUEXT_REASSIGN_PAGE;
    9.66 +
    9.67 +    mmu[3].ptr  = ppte;
    9.68 +    mmu[3].val  = newpage;
    9.69 +
    9.70 +    if ( unlikely(HYPERVISOR_mmu_update(mmu, 4) < 0) )
    9.71 +    {
    9.72 +        status = BLKIF_RSP_ERROR;
    9.73 +        goto out;
    9.74 +    }
    9.75 +
    9.76 +    /* Record this so they can be billed. */
    9.77 +    netif->total_packets_received++;
    9.78 +    netif->total_bytes_received += size;
    9.79 +
    9.80 + out:
    9.81 +    make_rx_response(netif, rx->id, status, addr, size);
    9.82 +    spin_unlock(&netif->rx_lock);    
    9.83 +    dev_kfree_skb(skb);
    9.84 +}
    9.85 +
    9.86 +
    9.87 +/*************************************************************
    9.88 + * NEW TRANSMIT SCHEDULER
    9.89 + * 
    9.90 + * NB. We ought also to only send a limited number of bytes to the NIC
    9.91 + * for transmission at any one time (to avoid head-of-line blocking).
    9.92 + * However, driver rings are small enough that they provide a reasonable
    9.93 + * limit.
    9.94 + * 
    9.95 + * eg. 3c905 has 16 descriptors == 8 packets, at 100Mbps
    9.96 + *     e1000 has 256 descriptors == 128 packets, at 1000Mbps
    9.97 + *     tg3 has 512 descriptors == 256 packets, at 1000Mbps
    9.98 + * 
    9.99 + * So, worst case is tg3 with 256 1500-bytes packets == 375kB.
   9.100 + * This would take 3ms, and represents our worst-case HoL blocking cost.
   9.101 + * 
   9.102 + * We think this is reasonable.
   9.103   */
   9.104  
   9.105 -#include <linux/config.h>
   9.106 -#include <linux/module.h>
   9.107 +struct list_head net_schedule_list;
   9.108 +spinlock_t net_schedule_list_lock;
   9.109 +
   9.110 +static int __on_net_schedule_list(netif_t *netif)
   9.111 +{
   9.112 +    return netif->list.next != NULL;
   9.113 +}
   9.114 +
   9.115 +static void remove_from_net_schedule_list(netif_t *netif)
   9.116 +{
   9.117 +    spin_lock(&net_schedule_list_lock);
   9.118 +    ASSERT(__on_net_schedule_list(netif));
   9.119 +    list_del(&netif->list);
   9.120 +    netif->list.next = NULL;
   9.121 +    netif_put(netif);
   9.122 +    spin_unlock(&net_schedule_list_lock);
   9.123 +}
   9.124 +
   9.125 +static void add_to_net_schedule_list_tail(netif_t *netif)
   9.126 +{
   9.127 +    if ( __on_net_schedule_list(netif) )
   9.128 +        return;
   9.129 +
   9.130 +    spin_lock(&net_schedule_list_lock);
   9.131 +    if ( likely(!__on_net_schedule_list(netif)) )
   9.132 +    {
   9.133 +        list_add_tail(&netif->list, &net_schedule_list);
   9.134 +        netif_get(netif);
   9.135 +    }
   9.136 +    spin_unlock(&net_schedule_list_lock);
   9.137 +}
   9.138 +
   9.139 +
   9.140 +static void tx_skb_release(struct sk_buff *skb);
   9.141 +    
   9.142 +static inline int init_tx_header(netif_t *netif, u8 *data, 
   9.143 +                                 unsigned int len, struct net_device *dev)
   9.144 +{
   9.145 +    int proto = ntohs(*(unsigned short *)(data + 12));
   9.146 +
   9.147 +    memcpy(data + ETH_ALEN, dev->dev_addr, ETH_ALEN);
   9.148 +        
   9.149 +    switch ( proto )
   9.150 +    {
   9.151 +    case ETH_P_ARP:
   9.152 +        if ( len < 42 ) break;
   9.153 +        memcpy(data + 22, dev->dev_addr, ETH_ALEN);
   9.154 +        break;
   9.155 +    case ETH_P_IP:
   9.156 +        break;
   9.157 +    default:
   9.158 +        /* Unsupported protocols are onyl allowed to/from NETIF0/0. */
   9.159 +        if ( (netif->domain->domain != 0) || (netif->idx != 0) )
   9.160 +            proto = 0;
   9.161 +        break;
   9.162 +    }
   9.163 +    return proto;
   9.164 +}
   9.165 +
   9.166 +
   9.167 +static void tx_credit_callback(unsigned long data)
   9.168 +{
   9.169 +    netif_t *netif = (netif_t *)data;
   9.170 +
   9.171 +    netif->remaining_credit = netif->credit_bytes;
   9.172 +
   9.173 +    if ( tx_work_exists(netif) )
   9.174 +    {
   9.175 +        add_to_net_schedule_list_tail(netif);
   9.176 +        maybe_schedule_tx_action();
   9.177 +    }    
   9.178 +}
   9.179 +
   9.180 +static void net_tx_action(unsigned long unused)
   9.181 +{
   9.182 +    struct list_head *ent;
   9.183 +    struct sk_buff *skb;
   9.184 +    netif_t *netif;
   9.185 +    netif_tx_request_t txreq;
   9.186 +    u16 pending_idx;
   9.187 +    pgprot_t prot = __pgprot(_PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED);
   9.188 +
   9.189 +    while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
   9.190 +            !list_empty(&net_schedule_list) )
   9.191 +    {
   9.192 +        /* Get a netif from the list with work to do. */
   9.193 +        ent = net_schedule_list.next;
   9.194 +        netif = list_entry(ent, netif_t, list);
   9.195 +        netif_get(netif);
   9.196 +        remove_from_net_schedule_list(netif);
   9.197 +
   9.198 +        /* Work to do? */
   9.199 +        i = netif->tx_req_cons;
   9.200 +        if ( (i == shared_idxs->tx_req_prod) && 
   9.201 +             ((i-netif->tx_resp_prod) == NETIF_TX_RING_SIZE) )
   9.202 +        {
   9.203 +            netif_put(netif);
   9.204 +            continue;
   9.205 +        }
   9.206 +        memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, 
   9.207 +               sizeof(txreq));
   9.208 +        netif->tx_req_cons++;
   9.209 +
   9.210 +#if 0
   9.211 +        /* Credit-based scheduling. */
   9.212 +        if ( tx.size > netif->remaining_credit )
   9.213 +        {
   9.214 +            s_time_t now = NOW(), next_credit = 
   9.215 +                netif->credit_timeout.expires + MICROSECS(netif->credit_usec);
   9.216 +            if ( next_credit <= now )
   9.217 +            {
   9.218 +                netif->credit_timeout.expires = now;
   9.219 +                netif->remaining_credit = netif->credit_bytes;
   9.220 +            }
   9.221 +            else
   9.222 +            {
   9.223 +                netif->remaining_credit = 0;
   9.224 +                netif->credit_timeout.expires  = next_credit;
   9.225 +                netif->credit_timeout.data     = (unsigned long)netif;
   9.226 +                netif->credit_timeout.function = tx_credit_callback;
   9.227 +                netif->credit_timeout.cpu      = smp_processor_id();
   9.228 +                add_ac_timer(&netif->credit_timeout);
   9.229 +                break;
   9.230 +            }
   9.231 +        }
   9.232 +        netif->remaining_credit -= tx.size;
   9.233 +#endif
   9.234 +
   9.235 +        add_to_net_schedule_list_tail(netif);
   9.236 +
   9.237 +        if ( unlikely(txreq.size <= PKT_PROT_LEN) || 
   9.238 +             unlikely(txreq.size > ETH_FRAME_LEN) )
   9.239 +        {
   9.240 +            DPRINTK("Bad packet size: %d\n", txreq.size);
   9.241 +            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
   9.242 +            netif_put(netif);
   9.243 +            continue; 
   9.244 +        }
   9.245 +
   9.246 +        /* No crossing a page boundary as the payload mustn't fragment. */
   9.247 +        if ( unlikely(((txreq.addr & ~PAGE_MASK) + txreq.size) >= PAGE_SIZE) ) 
   9.248 +        {
   9.249 +            DPRINTK("tx.addr: %lx, size: %u, end: %lu\n", 
   9.250 +                    txreq.addr, txreq.size, 
   9.251 +                    (txreq.addr &~PAGE_MASK) + txreq.size);
   9.252 +            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
   9.253 +            netif_put(netif);
   9.254 +            continue;
   9.255 +        }
   9.256 +
   9.257 +        pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
   9.258 +
   9.259 +        if ( direct_remap_area_pages(&init_mm,
   9.260 +                                     MMAP_VADDR(pending_idx),
   9.261 +                                     txreq.addr & PAGE_MASK,
   9.262 +                                     PAGE_SIZE, prot, netif->domid) != 0 )
   9.263 +        {
   9.264 +            DPRINTK("Bad page frame\n");
   9.265 +            make_tx_response(netif, tx.id, NETIF_RSP_ERROR);
   9.266 +            netif_put(netif);
   9.267 +            continue;
   9.268 +        }
   9.269 +            
   9.270 +        if ( unlikely((skb = alloc_skb(PKT_PROT_LEN, GFP_ATOMIC)) == NULL) )
   9.271 +        {
   9.272 +            make_tx_response(netif, tx.id, BLKIF_RSP_ERROR);
   9.273 +            netif_put(netif);
   9.274 +            vmfree_area_pages(MMAP_VADDR(pending_idx), PAGE_SIZE);
   9.275 +            break;
   9.276 +        }
   9.277 +        
   9.278 +        __skb_put(PKT_PROT_LEN);
   9.279 +        memcpy(skb->data, src, PKT_PROT_LEN);
   9.280 +        protocol = __constant_htons(
   9.281 +            init_tx_header(netif, g_data, tx.size, the_dev));
   9.282 +        if ( protocol == 0 )
   9.283 +        {
   9.284 +            make_tx_response(netif, tx.id, NETIF_RSP_ERROR);
   9.285 +            netif_put(netif);
   9.286 +            dev_kfree_skb(skb);
   9.287 +            goto cleanup_and_continue;
   9.288 +        }
   9.289 +
   9.290 +        skb->dev        = netif->dev;
   9.291 +        skb->protocol   = eth_type_trans(skb, skb->dev);
   9.292 +        
   9.293 +        /* Append the packet payload as a fragment. */
   9.294 +        skb_shinfo(skb)->frags[0].page        = 
   9.295 +          &mem_map[txreq.addr >> PAGE_SHIFT];
   9.296 +        skb_shinfo(skb)->frags[0].size        = txreq.size - PKT_PROT_LEN;
   9.297 +        skb_shinfo(skb)->frags[0].page_offset = 
   9.298 +            (txreq.addr + PKT_PROT_LEN) & ~PAGE_MASK;
   9.299 +        skb_shinfo(skb)->nr_frags = 1;
   9.300 +        skb->data_len  = tx->size - PKT_PROT_LEN;
   9.301 +        skb->len      += skb->data_len;
   9.302 +
   9.303 +        /* Destructor information. */
   9.304 +        skb->destructor = tx_skb_release;
   9.305 +        skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].page = (struct page *)netif;
   9.306 +        skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].size = pending_idx;
   9.307 +
   9.308 +        /* Record the transmission so they can be billed. */
   9.309 +        netif->total_packets_sent++;
   9.310 +        netif->total_bytes_sent += tx->size;
   9.311 +
   9.312 +        pending_cons++;
   9.313 +        netif_rx(skb);
   9.314 +        netif->dev->last_rx = jiffies;
   9.315 +    }
   9.316 +}
   9.317 +
   9.318 +DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
   9.319 +
   9.320 +
   9.321 +static inline void maybe_schedule_tx_action(void)
   9.322 +{
   9.323 +    smp_mb();
   9.324 +    if ( !netif_queue_stopped(the_dev) &&
   9.325 +         !list_empty(&net_schedule_list) )
   9.326 +        tasklet_schedule(&net_tx_tasklet);
   9.327 +}
   9.328 +
   9.329 +
   9.330 +/* Destructor function for tx skbs. */
   9.331 +static void tx_skb_release(struct sk_buff *skb)
   9.332 +{
   9.333 +    int i;
   9.334 +    netif_t *netif = (netif_t)skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].page;
   9.335 +    u16 pending_idx = skb_shinfo(skb)->frags[MAX_SKB_FRAGS-1].size;
   9.336 +
   9.337 +    vmfree_area_pages(MMAP_VADDR(pending_idx), PAGE_SIZE);
   9.338 +    
   9.339 +    skb_shinfo(skb)->nr_frags = 0; 
   9.340 +    
   9.341 +    spin_lock(&netif->tx_lock);
   9.342 +    make_tx_response(netif, skb->guest_id, NETIF_RSP_OKAY);
   9.343 +    spin_unlock(&netif->tx_lock);
   9.344 +    
   9.345 +    /*
   9.346 +     * Checks below must happen after the above response is posted. This avoids
   9.347 +     * a possible race with a guest OS on another CPU.
   9.348 +     */
   9.349 +    mb();
   9.350 +    
   9.351 +    if ( tx_work_exists(netif) )
   9.352 +    {
   9.353 +        add_to_net_schedule_list_tail(netif);
   9.354 +        maybe_schedule_tx_action();        
   9.355 +    }
   9.356 +    
   9.357 +    netif_put(netif);
   9.358 +}
   9.359 +
   9.360 +
   9.361 +long flush_bufs_for_netif(netif_t *netif)
   9.362 +{
   9.363 +    NET_RING_IDX i;
   9.364 +
   9.365 +    /* Return any outstanding receive buffers to the guest OS. */
   9.366 +    spin_lock(&netif->rx_lock);
   9.367 +    for ( i = netif->rx_req_cons; 
   9.368 +          (i != netif->rx->req_prod) &&
   9.369 +              ((i-netif->rx_resp_prod) != NETIF_RX_RING_SIZE);
   9.370 +          i++ )
   9.371 +    {
   9.372 +        make_rx_response(netif,
   9.373 +                         netif->rx->ring[MASK_NETIF_RX_IDX(i)].req.id,
   9.374 +                         NETIF_RSP_DROPPED, 0, 0);
   9.375 +    }
   9.376 +    netif->rx_req_cons = i;
   9.377 +    spin_unlock(&netif->rx_lock);
   9.378 +
   9.379 +    /*
   9.380 +     * Flush pending transmit buffers. The guest may still have to wait for
   9.381 +     * buffers that are queued at a physical NIC.
   9.382 +     */
   9.383 +    spin_lock(&netif->tx_lock);
   9.384 +    for ( i = netif->tx_req_cons; 
   9.385 +          (i != netif->tx->req_prod) &&
   9.386 +              ((i-netif->tx_resp_prod) != NETIF_TX_RING_SIZE);
   9.387 +          i++ )
   9.388 +    {
   9.389 +        make_tx_response(netif,
   9.390 +                         netif->tx->ring[MASK_NETIF_TX_IDX(i)].req.id,
   9.391 +                         NETIF_RSP_DROPPED);
   9.392 +    }
   9.393 +    netif->tx_req_cons = i;
   9.394 +    spin_unlock(&netif->tx_lock);
   9.395 +
   9.396 +    return 0;
   9.397 +}
   9.398 +
   9.399 +void netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
   9.400 +{
   9.401 +    netif_t *netif = dev_id;
   9.402 +    if ( tx_work_exists(netif) )
   9.403 +    {
   9.404 +        add_to_net_schedule_list_tail(netif);
   9.405 +        maybe_schedule_tx_action();
   9.406 +    }
   9.407 +}
   9.408 +
   9.409 +static void make_tx_response(netif_t *netif, 
   9.410 +                             u16      id,
   9.411 +                             s8       st)
   9.412 +{
   9.413 +    NET_RING_IDX i = netif->tx_resp_prod;
   9.414 +    netif_tx_response_t *resp;
   9.415 +
   9.416 +    resp = &netif->tx->ring[MASK_NETIF_TX_IDX(i)].resp;
   9.417 +    resp->id     = id;
   9.418 +    resp->status = st;
   9.419 +    wmb();
   9.420 +    netif->tx->resp_prod = netif->tx_resp_prod = ++i;
   9.421 +
   9.422 +    mb(); /* Update producer before checking event threshold. */
   9.423 +    if ( i == netif->tx->event )
   9.424 +        notify_via_evtchn(netif->evtchn);
   9.425 +}
   9.426 +
   9.427 +
   9.428 +static void make_rx_response(netif_t     *netif, 
   9.429 +                             u16          id, 
   9.430 +                             s8           st,
   9.431 +                             netif_addr_t addr,
   9.432 +                             u16          size)
   9.433 +{
   9.434 +    NET_RING_IDX i = netif->rx_resp_prod;
   9.435 +    netif_rx_response_t *resp;
   9.436 +
   9.437 +    resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
   9.438 +    resp->addr   = addr;
   9.439 +    resp->id     = id;
   9.440 +    resp->status = (s16)size;
   9.441 +    if ( st < 0 )
   9.442 +        resp->status = (s16)st;
   9.443 +    wmb();
   9.444 +    netif->rx->resp_prod = netif->rx_resp_prod = ++i;
   9.445 +
   9.446 +    mb(); /* Update producer before checking event threshold. */
   9.447 +    if ( i == netif->rx->event )
   9.448 +        notify_via_evtchn(netif->evtchn);
   9.449 +}
   9.450 +
   9.451  
   9.452  static int __init init_module(void)
   9.453  {
   9.454 +    netif_interface_init();
   9.455 +
   9.456 +    if ( (mmap_vma = get_vm_area(MAX_PENDING_REQS * PAGE_SIZE, 
   9.457 +                                 VM_IOREMAP)) == NULL )
   9.458 +    {
   9.459 +        printk(KERN_WARNING "Could not allocate VMA for netif backend.\n");
   9.460 +        return -ENOMEM;
   9.461 +    }
   9.462 +
   9.463 +    netif_ctrlif_init();
   9.464 +
   9.465      return 0;
   9.466  }
   9.467  
   9.468 +
   9.469  static void cleanup_module(void)
   9.470  {
   9.471  }
   9.472  
   9.473 +
   9.474  module_init(init_module);
   9.475  module_exit(cleanup_module);
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/netif.h	Tue May 04 15:45:07 2004 +0000
    10.3 @@ -0,0 +1,83 @@
    10.4 +/******************************************************************************
    10.5 + * netif.h
    10.6 + * 
    10.7 + * Unified network-device I/O interface for Xen guest OSes.
    10.8 + * 
    10.9 + * Copyright (c) 2003-2004, Keir Fraser
   10.10 + */
   10.11 +
   10.12 +#ifndef __SHARED_NETIF_H__
   10.13 +#define __SHARED_NETIF_H__
   10.14 +
   10.15 +typedef unsigned long netif_addr_t;
   10.16 +
   10.17 +typedef struct {
   10.18 +    netif_addr_t addr;   /* Machine address of packet.  */
   10.19 +    u16          id;     /* Echoed in response message. */
   10.20 +    u16          size;   /* Packet size in bytes.       */
   10.21 +} netif_tx_request_t;
   10.22 +
   10.23 +typedef struct {
   10.24 +    u16          id;
   10.25 +    s8           status;
   10.26 +} netif_tx_response_t;
   10.27 +
   10.28 +typedef struct {
   10.29 +    u16          id;     /* Echoed in response message.        */
   10.30 +} netif_rx_request_t;
   10.31 +
   10.32 +typedef struct {
   10.33 +    netif_addr_t addr;   /* Machine address of packet.              */
   10.34 +    u16          id;
   10.35 +    s16          status; /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */
   10.36 +} netif_rx_response_t;
   10.37 +
   10.38 +/*
   10.39 + * We use a special capitalised type name because it is _essential_ that all 
   10.40 + * arithmetic on indexes is done on an integer type of the correct size.
   10.41 + */
   10.42 +typedef unsigned int NETIF_RING_IDX;
   10.43 +
   10.44 +/*
   10.45 + * Ring indexes are 'free running'. That is, they are not stored modulo the
   10.46 + * size of the ring buffer. The following macros convert a free-running counter
   10.47 + * into a value that can directly index a ring-buffer array.
   10.48 + */
   10.49 +#define MASK_NETIF_RX_IDX(_i) ((_i)&(NETIF_RX_RING_SIZE-1))
   10.50 +#define MASK_NETIF_TX_IDX(_i) ((_i)&(NETIF_TX_RING_SIZE-1))
   10.51 +
   10.52 +#define NETIF_TX_RING_SIZE 256
   10.53 +#define NETIF_RX_RING_SIZE 256
   10.54 +
   10.55 +/* This structure must fit in a memory page. */
   10.56 +typedef struct {
   10.57 +    union {
   10.58 +        netif_tx_request_t  req;
   10.59 +        netif_tx_response_t resp;
   10.60 +    } ring[NETIF_TX_RING_SIZE];
   10.61 +    /*
   10.62 +     * Frontend places packets into ring at tx_req_prod.
   10.63 +     * Frontend receives event when tx_resp_prod passes tx_event.
   10.64 +     */
   10.65 +    NETIF_RING_IDX req_prod, resp_prod, event;
   10.66 +} netif_tx_interface_t;
   10.67 +
   10.68 +/* This structure must fit in a memory page. */
   10.69 +typedef struct {
   10.70 +    union {
   10.71 +        netif_rx_request_t  req;
   10.72 +        netif_rx_response_t resp;
   10.73 +    } ring[NETIF_RX_RING_SIZE];
   10.74 +    /*
   10.75 +     * Frontend places empty buffers into ring at rx_req_prod.
   10.76 +     * Frontend receives event when rx_resp_prod passes rx_event.
   10.77 +     */
   10.78 +    NETIF_RING_IDX req_prod, resp_prod, event;
   10.79 +} netif_rx_interface_t;
   10.80 +
   10.81 +/* Descriptor status values */
   10.82 +#define NETIF_RSP_DROPPED         -2
   10.83 +#define NETIF_RSP_ERROR           -1
   10.84 +#define NETIF_RSP_OKAY             0
   10.85 +
   10.86 +#endif
    11.1 --- a/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c	Tue May 04 15:01:49 2004 +0000
    11.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c	Tue May 04 15:45:07 2004 +0000
    11.3 @@ -36,7 +36,7 @@ static inline int direct_remap_area_pte(
    11.4  {
    11.5      unsigned long end;
    11.6  #define MAX_DIRECTMAP_MMU_QUEUE 130
    11.7 -    mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *v;
    11.8 +    mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *v, *w;
    11.9  
   11.10      address &= ~PMD_MASK;
   11.11      end = address + size;
   11.12 @@ -45,23 +45,31 @@ static inline int direct_remap_area_pte(
   11.13      if (address >= end)
   11.14          BUG();
   11.15  
   11.16 - reset_buffer:
   11.17      /* If not I/O mapping then specify General-Purpose Subject Domain (GPS). */
   11.18 -    v = &u[0];
   11.19      if ( domid != 0 )
   11.20      {
   11.21 -        v[0].val  = (unsigned long)(domid<<16) & ~0xFFFFUL;
   11.22 -        v[0].ptr  = (unsigned long)(domid<< 0) & ~0xFFFFUL;
   11.23 -        v[1].val  = (unsigned long)(domid>>16) & ~0xFFFFUL;
   11.24 -        v[1].ptr  = (unsigned long)(domid>>32) & ~0xFFFFUL;
   11.25 -        v[0].ptr |= MMU_EXTENDED_COMMAND;
   11.26 -        v[0].val |= MMUEXT_SET_SUBJECTDOM_L;
   11.27 -        v[1].ptr |= MMU_EXTENDED_COMMAND;
   11.28 -        v[1].val |= MMUEXT_SET_SUBJECTDOM_H;
   11.29 -        v += 2;
   11.30 +        u[0].val  = (unsigned long)(domid<<16) & ~0xFFFFUL;
   11.31 +        u[0].ptr  = (unsigned long)(domid<< 0) & ~0xFFFFUL;
   11.32 +        u[1].val  = (unsigned long)(domid>>16) & ~0xFFFFUL;
   11.33 +        u[1].ptr  = (unsigned long)(domid>>32) & ~0xFFFFUL;
   11.34 +        u[0].ptr |= MMU_EXTENDED_COMMAND;
   11.35 +        u[0].val |= MMUEXT_SET_SUBJECTDOM_L;
   11.36 +        u[1].ptr |= MMU_EXTENDED_COMMAND;
   11.37 +        u[1].val |= MMUEXT_SET_SUBJECTDOM_H;
   11.38 +        v = w = &u[2];
   11.39 +    }
   11.40 +    else
   11.41 +    {
   11.42 +        v = w = &u[0];
   11.43      }
   11.44  
   11.45      do {
   11.46 +        if ( (v-u) == MAX_DIRECTMAP_MMU_QUEUE )
   11.47 +        {
   11.48 +            if ( HYPERVISOR_mmu_update(u, MAX_DIRECTMAP_MMU_QUEUE) < 0 )
   11.49 +                return -EFAULT;
   11.50 +            v = w;
   11.51 +        }
   11.52  #if 0  /* thanks to new ioctl mmaping interface this is no longer a bug */
   11.53          if (!pte_none(*pte)) {
   11.54              printk("direct_remap_area_pte: page already exists\n");
   11.55 @@ -70,23 +78,14 @@ static inline int direct_remap_area_pte(
   11.56  #endif
   11.57          v->ptr = virt_to_machine(pte);
   11.58          v->val = (machine_addr & PAGE_MASK) | pgprot_val(prot) | _PAGE_IO;
   11.59 -        if ( ( ++v - u )== MAX_DIRECTMAP_MMU_QUEUE ) 
   11.60 -        {
   11.61 -            if ( HYPERVISOR_mmu_update(u, MAX_DIRECTMAP_MMU_QUEUE) < 0 )
   11.62 -                return -EFAULT;
   11.63 -            goto reset_buffer;
   11.64 -        }
   11.65 +        v++;
   11.66          address += PAGE_SIZE;
   11.67          machine_addr += PAGE_SIZE;
   11.68          pte++;
   11.69      } while (address && (address < end));
   11.70  
   11.71 -    if ( ((v-u) > 2) && (HYPERVISOR_mmu_update(u, v-u) < 0) )
   11.72 -    {
   11.73 -        printk(KERN_WARNING "Failed to ioremap %08lx->%08lx (%08lx)\n",
   11.74 -               end-size, end, machine_addr-size);
   11.75 -	return -EINVAL;
   11.76 -    }
   11.77 +    if ( ((v-w) != 0) && (HYPERVISOR_mmu_update(u, v-u) < 0) )
   11.78 +        return -EFAULT;
   11.79  
   11.80      return 0;
   11.81  }
   11.82 @@ -113,7 +112,6 @@ static inline int direct_remap_area_pmd(
   11.83          pte_t * pte = pte_alloc(mm, pmd, address);
   11.84          if (!pte)
   11.85              return -ENOMEM;
   11.86 -
   11.87          error = direct_remap_area_pte(pte, address, end - address, 
   11.88                                        address + machine_addr, prot, domid);
   11.89          if ( error )
   11.90 @@ -135,9 +133,6 @@ int direct_remap_area_pages(struct mm_st
   11.91      pgd_t * dir;
   11.92      unsigned long end = address + size;
   11.93  
   11.94 -/*printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n",
   11.95 -       address, machine_addr, size);*/
   11.96 -
   11.97      machine_addr -= address;
   11.98      dir = pgd_offset(mm, address);
   11.99      flush_cache_all();