ia64/xen-unstable

changeset 5844:7bc4ebdd5660

add grant table capabilities to netback and netfront.

Signed-off-by: Vincent Hanquez <vincent@xensource.com>
author vh249@firebug.cl.cam.ac.uk
date Mon Jul 25 17:07:31 2005 +0000 (2005-07-25)
parents a49bf96419a4
children 6feba419cead
files linux-2.6-xen-sparse/arch/xen/Kconfig linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c linux-2.6-xen-sparse/drivers/xen/netback/common.h linux-2.6-xen-sparse/drivers/xen/netback/netback.c linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c xen/common/grant_table.c xen/include/public/grant_table.h xen/include/public/io/netif.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/Kconfig	Mon Jul 25 09:56:50 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/Kconfig	Mon Jul 25 17:07:31 2005 +0000
     1.3 @@ -97,6 +97,20 @@ config XEN_NETDEV_FRONTEND
     1.4  	  dedicated device-driver domain, or your master control domain
     1.5  	  (domain 0), then you almost certainly want to say Y here.
     1.6  
     1.7 +config XEN_NETDEV_GRANT_TX
     1.8 +        bool "Grant table substrate for net drivers tx path (DANGEROUS)"
     1.9 +        default n
    1.10 +        help
    1.11 +          This introduces the use of grant tables as a data exhange mechanism
    1.12 +          between the frontend and backend network drivers.
    1.13 +
    1.14 +config XEN_NETDEV_GRANT_RX
    1.15 +        bool "Grant table substrate for net drivers rx path (DANGEROUS)"
    1.16 +        default n
    1.17 +        help
    1.18 +          This introduces the use of grant tables as a data exhange mechanism
    1.19 +          between the frontend and backend network drivers.
    1.20 +
    1.21  config XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER
    1.22  	bool "Pipelined transmitter (DANGEROUS)"
    1.23  	depends on XEN_NETDEV_FRONTEND
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32	Mon Jul 25 09:56:50 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32	Mon Jul 25 17:07:31 2005 +0000
     2.3 @@ -1,7 +1,7 @@
     2.4  #
     2.5  # Automatically generated make config: don't edit
     2.6  # Linux kernel version: 2.6.12-xen0
     2.7 -# Sat Jul  9 09:19:47 2005
     2.8 +# Mon Jul 25 09:48:34 2005
     2.9  #
    2.10  CONFIG_XEN=y
    2.11  CONFIG_ARCH_XEN=y
    2.12 @@ -18,6 +18,8 @@ CONFIG_XEN_BLKDEV_GRANT=y
    2.13  CONFIG_XEN_NETDEV_BACKEND=y
    2.14  CONFIG_XEN_BLKDEV_FRONTEND=y
    2.15  CONFIG_XEN_NETDEV_FRONTEND=y
    2.16 +# CONFIG_XEN_NETDEV_GRANT_TX is not set
    2.17 +# CONFIG_XEN_NETDEV_GRANT_RX is not set
    2.18  # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
    2.19  # CONFIG_XEN_BLKDEV_TAP is not set
    2.20  # CONFIG_XEN_SHADOW_MODE is not set
    2.21 @@ -176,38 +178,12 @@ CONFIG_ISA=y
    2.22  # PCI Hotplug Support
    2.23  #
    2.24  # CONFIG_HOTPLUG_PCI is not set
    2.25 -
    2.26 -#
    2.27 -# Kernel hacking
    2.28 -#
    2.29 -# CONFIG_PRINTK_TIME is not set
    2.30 -CONFIG_DEBUG_KERNEL=y
    2.31 -CONFIG_MAGIC_SYSRQ=y
    2.32 -CONFIG_LOG_BUF_SHIFT=14
    2.33 -# CONFIG_SCHEDSTATS is not set
    2.34 -# CONFIG_DEBUG_SLAB is not set
    2.35 -# CONFIG_DEBUG_PREEMPT is not set
    2.36 -# CONFIG_DEBUG_SPINLOCK is not set
    2.37 -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
    2.38 -# CONFIG_DEBUG_KOBJECT is not set
    2.39 -# CONFIG_DEBUG_HIGHMEM is not set
    2.40 -CONFIG_DEBUG_BUGVERBOSE=y
    2.41 -# CONFIG_DEBUG_INFO is not set
    2.42 -# CONFIG_DEBUG_FS is not set
    2.43 -# CONFIG_FRAME_POINTER is not set
    2.44 -CONFIG_EARLY_PRINTK=y
    2.45 -# CONFIG_DEBUG_STACKOVERFLOW is not set
    2.46 -# CONFIG_KPROBES is not set
    2.47 -# CONFIG_DEBUG_STACK_USAGE is not set
    2.48 -# CONFIG_DEBUG_PAGEALLOC is not set
    2.49 -# CONFIG_4KSTACKS is not set
    2.50 -CONFIG_X86_FIND_SMP_CONFIG=y
    2.51 -CONFIG_X86_MPPARSE=y
    2.52  CONFIG_GENERIC_HARDIRQS=y
    2.53  CONFIG_GENERIC_IRQ_PROBE=y
    2.54  CONFIG_X86_BIOS_REBOOT=y
    2.55  CONFIG_PC=y
    2.56  CONFIG_SECCOMP=y
    2.57 +CONFIG_EARLY_PRINTK=y
    2.58  
    2.59  #
    2.60  # Executable file formats
    2.61 @@ -1274,3 +1250,29 @@ CONFIG_CRYPTO_CRC32C=m
    2.62  CONFIG_CRC32=y
    2.63  CONFIG_LIBCRC32C=y
    2.64  CONFIG_ZLIB_INFLATE=y
    2.65 +
    2.66 +#
    2.67 +# Kernel hacking
    2.68 +#
    2.69 +# CONFIG_PRINTK_TIME is not set
    2.70 +CONFIG_DEBUG_KERNEL=y
    2.71 +CONFIG_MAGIC_SYSRQ=y
    2.72 +CONFIG_LOG_BUF_SHIFT=14
    2.73 +# CONFIG_SCHEDSTATS is not set
    2.74 +# CONFIG_DEBUG_SLAB is not set
    2.75 +# CONFIG_DEBUG_PREEMPT is not set
    2.76 +# CONFIG_DEBUG_SPINLOCK is not set
    2.77 +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
    2.78 +# CONFIG_DEBUG_KOBJECT is not set
    2.79 +# CONFIG_DEBUG_HIGHMEM is not set
    2.80 +CONFIG_DEBUG_BUGVERBOSE=y
    2.81 +# CONFIG_DEBUG_INFO is not set
    2.82 +# CONFIG_DEBUG_FS is not set
    2.83 +# CONFIG_FRAME_POINTER is not set
    2.84 +# CONFIG_DEBUG_STACKOVERFLOW is not set
    2.85 +# CONFIG_KPROBES is not set
    2.86 +# CONFIG_DEBUG_STACK_USAGE is not set
    2.87 +# CONFIG_DEBUG_PAGEALLOC is not set
    2.88 +# CONFIG_4KSTACKS is not set
    2.89 +CONFIG_X86_FIND_SMP_CONFIG=y
    2.90 +CONFIG_X86_MPPARSE=y
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32	Mon Jul 25 09:56:50 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32	Mon Jul 25 17:07:31 2005 +0000
     3.3 @@ -1,7 +1,7 @@
     3.4  #
     3.5  # Automatically generated make config: don't edit
     3.6  # Linux kernel version: 2.6.12-xenU
     3.7 -# Sun Jul 10 17:32:04 2005
     3.8 +# Mon Jul 25 10:06:06 2005
     3.9  #
    3.10  CONFIG_XEN=y
    3.11  CONFIG_ARCH_XEN=y
    3.12 @@ -15,6 +15,8 @@ CONFIG_NO_IDLE_HZ=y
    3.13  CONFIG_XEN_BLKDEV_GRANT=y
    3.14  CONFIG_XEN_BLKDEV_FRONTEND=y
    3.15  CONFIG_XEN_NETDEV_FRONTEND=y
    3.16 +# CONFIG_XEN_NETDEV_GRANT_TX is not set
    3.17 +# CONFIG_XEN_NETDEV_GRANT_RX is not set
    3.18  # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
    3.19  # CONFIG_XEN_BLKDEV_TAP is not set
    3.20  # CONFIG_XEN_SHADOW_MODE is not set
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c	Mon Jul 25 09:56:50 2005 +0000
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c	Mon Jul 25 17:07:31 2005 +0000
     4.3 @@ -166,8 +166,14 @@ gnttab_end_foreign_transfer(
     4.4      u16           flags;
     4.5  
     4.6      flags = shared[ref].flags;
     4.7 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
     4.8 +    /*
     4.9 +     * But can't flags == (GTF_accept_transfer | GTF_transfer_completed)
    4.10 +     * if gnttab_donate executes without interruption???
    4.11 +     */
    4.12 +#else
    4.13      ASSERT(flags == (GTF_accept_transfer | GTF_transfer_committed));
    4.14 -
    4.15 +#endif
    4.16      /*
    4.17       * If a transfer is committed then wait for the frame address to appear.
    4.18       * Otherwise invalidate the grant entry against future use.
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h	Mon Jul 25 09:56:50 2005 +0000
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h	Mon Jul 25 17:07:31 2005 +0000
     5.3 @@ -50,6 +50,9 @@ typedef struct netif_st {
     5.4      /* Private indexes into shared ring. */
     5.5      NETIF_RING_IDX rx_req_cons;
     5.6      NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */
     5.7 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
     5.8 +    NETIF_RING_IDX rx_resp_prod_copy; /* private version of shared variable */
     5.9 +#endif
    5.10      NETIF_RING_IDX tx_req_cons;
    5.11      NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */
    5.12  
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Jul 25 09:56:50 2005 +0000
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Jul 25 17:07:31 2005 +0000
     6.3 @@ -18,6 +18,24 @@
     6.4  #include <linux/delay.h>
     6.5  #endif
     6.6  
     6.7 +#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
     6.8 +#include <asm-xen/xen-public/grant_table.h>
     6.9 +#include <asm-xen/gnttab.h>
    6.10 +#ifdef GRANT_DEBUG
    6.11 +static void
    6.12 +dump_packet(int tag, u32 addr, unsigned char *p)
    6.13 +{
    6.14 +	int i;
    6.15 +
    6.16 +	printk(KERN_ALERT "#### rx_action %c %08x ", tag & 0xff, addr);
    6.17 +	for (i = 0; i < 20; i++) {
    6.18 +		printk("%02x", p[i]);
    6.19 +	}
    6.20 +	printk("\n");
    6.21 +}
    6.22 +#endif
    6.23 +#endif
    6.24 +
    6.25  static void netif_idx_release(u16 pending_idx);
    6.26  static void netif_page_release(struct page *page);
    6.27  static void make_tx_response(netif_t *netif, 
    6.28 @@ -41,7 +59,9 @@ static struct timer_list net_timer;
    6.29  static struct sk_buff_head rx_queue;
    6.30  static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1];
    6.31  static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
    6.32 +#ifndef CONFIG_XEN_NETDEV_GRANT_RX
    6.33  static struct mmuext_op rx_mmuext[NETIF_RX_RING_SIZE];
    6.34 +#endif
    6.35  static unsigned char rx_notify[NR_EVENT_CHANNELS];
    6.36  
    6.37  /* Don't currently gate addition of an interface to the tx scheduling list. */
    6.38 @@ -68,7 +88,20 @@ static u16 dealloc_ring[MAX_PENDING_REQS
    6.39  static PEND_RING_IDX dealloc_prod, dealloc_cons;
    6.40  
    6.41  static struct sk_buff_head tx_queue;
    6.42 +
    6.43 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
    6.44 +static u16 grant_tx_ref[MAX_PENDING_REQS];
    6.45 +#endif
    6.46 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
    6.47 +static gnttab_donate_t grant_rx_op[MAX_PENDING_REQS];
    6.48 +#endif
    6.49 +#ifndef CONFIG_XEN_NETDEV_GRANT_TX
    6.50  static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
    6.51 +#endif
    6.52 +
    6.53 +#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
    6.54 +#define GRANT_INVALID_REF (0xFFFF)
    6.55 +#endif
    6.56  
    6.57  static struct list_head net_schedule_list;
    6.58  static spinlock_t net_schedule_list_lock;
    6.59 @@ -91,6 +124,7 @@ static unsigned long alloc_mfn(void)
    6.60      return mfn;
    6.61  }
    6.62  
    6.63 +#ifndef CONFIG_XEN_NETDEV_GRANT_RX
    6.64  static void free_mfn(unsigned long mfn)
    6.65  {
    6.66      unsigned long flags;
    6.67 @@ -102,6 +136,7 @@ static void free_mfn(unsigned long mfn)
    6.68          BUG();
    6.69      spin_unlock_irqrestore(&mfn_lock, flags);
    6.70  }
    6.71 +#endif
    6.72  
    6.73  static inline void maybe_schedule_tx_action(void)
    6.74  {
    6.75 @@ -160,7 +195,17 @@ int netif_be_start_xmit(struct sk_buff *
    6.76          dev_kfree_skb(skb);
    6.77          skb = nskb;
    6.78      }
    6.79 -
    6.80 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
    6.81 +#ifdef DEBUG_GRANT
    6.82 +    printk(KERN_ALERT "#### be_xmit: req_prod=%d req_cons=%d id=%04x gr=%04x\n",
    6.83 +           netif->rx->req_prod,
    6.84 +           netif->rx_req_cons,
    6.85 +           netif->rx->ring[
    6.86 +		   MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.id,
    6.87 +           netif->rx->ring[
    6.88 +		   MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.gref);
    6.89 +#endif
    6.90 +#endif
    6.91      netif->rx_req_cons++;
    6.92      netif_get(netif);
    6.93  
    6.94 @@ -201,7 +246,11 @@ static void net_rx_action(unsigned long 
    6.95      u16 size, id, evtchn;
    6.96      multicall_entry_t *mcl;
    6.97      mmu_update_t *mmu;
    6.98 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
    6.99 +    gnttab_donate_t *gop;
   6.100 +#else
   6.101      struct mmuext_op *mmuext;
   6.102 +#endif
   6.103      unsigned long vdata, mdata, new_mfn;
   6.104      struct sk_buff_head rxq;
   6.105      struct sk_buff *skb;
   6.106 @@ -212,7 +261,12 @@ static void net_rx_action(unsigned long 
   6.107  
   6.108      mcl = rx_mcl;
   6.109      mmu = rx_mmu;
   6.110 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   6.111 +    gop = grant_rx_op;
   6.112 +#else
   6.113      mmuext = rx_mmuext;
   6.114 +#endif
   6.115 +
   6.116      while ( (skb = skb_dequeue(&rx_queue)) != NULL )
   6.117      {
   6.118          netif   = netdev_priv(skb->dev);
   6.119 @@ -228,7 +282,6 @@ static void net_rx_action(unsigned long 
   6.120              skb_queue_head(&rx_queue, skb);
   6.121              break;
   6.122          }
   6.123 -
   6.124          /*
   6.125           * Set the new P2M table entry before reassigning the old data page.
   6.126           * Heed the comment in pgtable-2level.h:pte_page(). :-)
   6.127 @@ -239,6 +292,14 @@ static void net_rx_action(unsigned long 
   6.128  				pfn_pte_ma(new_mfn, PAGE_KERNEL), 0);
   6.129          mcl++;
   6.130  
   6.131 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   6.132 +        gop->mfn = mdata >> PAGE_SHIFT;
   6.133 +        gop->domid = netif->domid;
   6.134 +        gop->handle = netif->rx->ring[
   6.135 +        MASK_NETIF_RX_IDX(netif->rx_resp_prod_copy)].req.gref;
   6.136 +        netif->rx_resp_prod_copy++;
   6.137 +        gop++;
   6.138 +#else
   6.139          mcl->op = __HYPERVISOR_mmuext_op;
   6.140          mcl->args[0] = (unsigned long)mmuext;
   6.141          mcl->args[1] = 1;
   6.142 @@ -249,13 +310,16 @@ static void net_rx_action(unsigned long 
   6.143          mmuext->cmd = MMUEXT_REASSIGN_PAGE;
   6.144          mmuext->mfn = mdata >> PAGE_SHIFT;
   6.145          mmuext++;
   6.146 -
   6.147 +#endif
   6.148          mmu->ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
   6.149          mmu->val = __pa(vdata) >> PAGE_SHIFT;  
   6.150          mmu++;
   6.151  
   6.152          __skb_queue_tail(&rxq, skb);
   6.153  
   6.154 +#ifdef DEBUG_GRANT
   6.155 +        dump_packet('a', mdata, vdata);
   6.156 +#endif
   6.157          /* Filled the batch queue? */
   6.158          if ( (mcl - rx_mcl) == ARRAY_SIZE(rx_mcl) )
   6.159              break;
   6.160 @@ -271,12 +335,24 @@ static void net_rx_action(unsigned long 
   6.161      mcl->args[3] = DOMID_SELF;
   6.162      mcl++;
   6.163  
   6.164 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   6.165 +    mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
   6.166 +#else
   6.167      mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
   6.168 +#endif
   6.169      if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) )
   6.170          BUG();
   6.171  
   6.172      mcl = rx_mcl;
   6.173 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   6.174 +    if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_donate,
   6.175 +                                           grant_rx_op, gop - grant_rx_op))) {
   6.176 +        BUG();
   6.177 +    }
   6.178 +    gop = grant_rx_op;
   6.179 +#else
   6.180      mmuext = rx_mmuext;
   6.181 +#endif
   6.182      while ( (skb = __skb_dequeue(&rxq)) != NULL )
   6.183      {
   6.184          netif   = netdev_priv(skb->dev);
   6.185 @@ -284,9 +360,12 @@ static void net_rx_action(unsigned long 
   6.186  
   6.187          /* Rederive the machine addresses. */
   6.188          new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
   6.189 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   6.190 +        mdata = (unsigned long)skb->data & ~PAGE_MASK;
   6.191 +#else
   6.192          mdata   = ((mmuext[0].mfn << PAGE_SHIFT) |
   6.193                     ((unsigned long)skb->data & ~PAGE_MASK));
   6.194 -        
   6.195 +#endif
   6.196          atomic_set(&(skb_shinfo(skb)->dataref), 1);
   6.197          skb_shinfo(skb)->nr_frags = 0;
   6.198          skb_shinfo(skb)->frag_list = NULL;
   6.199 @@ -299,13 +378,16 @@ static void net_rx_action(unsigned long 
   6.200  
   6.201          /* Check the reassignment error code. */
   6.202          status = NETIF_RSP_OKAY;
   6.203 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   6.204 +        BUG_ON(gop->status != 0);
   6.205 +#else
   6.206          if ( unlikely(mcl[1].result != 0) )
   6.207          {
   6.208              DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid);
   6.209              free_mfn(mdata >> PAGE_SHIFT);
   6.210              status = NETIF_RSP_ERROR;
   6.211          }
   6.212 -
   6.213 +#endif
   6.214          evtchn = netif->evtchn;
   6.215          id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
   6.216          if ( make_rx_response(netif, id, status, mdata,
   6.217 @@ -318,9 +400,13 @@ static void net_rx_action(unsigned long 
   6.218  
   6.219          netif_put(netif);
   6.220          dev_kfree_skb(skb);
   6.221 -
   6.222 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   6.223 +        mcl++;
   6.224 +        gop++;
   6.225 +#else
   6.226          mcl += 2;
   6.227          mmuext += 1;
   6.228 +#endif
   6.229      }
   6.230  
   6.231      while ( notify_nr != 0 )
   6.232 @@ -404,6 +490,7 @@ static void tx_credit_callback(unsigned 
   6.233      netif_schedule_work(netif);
   6.234  }
   6.235  
   6.236 +/* Called after netfront has transmitted */
   6.237  static void net_tx_action(unsigned long unused)
   6.238  {
   6.239      struct list_head *ent;
   6.240 @@ -412,13 +499,40 @@ static void net_tx_action(unsigned long 
   6.241      netif_tx_request_t txreq;
   6.242      u16 pending_idx;
   6.243      NETIF_RING_IDX i;
   6.244 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.245 +    gnttab_unmap_grant_ref_t unmap_ops[MAX_PENDING_REQS];
   6.246 +    gnttab_unmap_grant_ref_t *gop;
   6.247 +
   6.248 +    gnttab_map_grant_ref_t map_ops[MAX_PENDING_REQS];
   6.249 +    gnttab_map_grant_ref_t *mop;
   6.250 +#else
   6.251      multicall_entry_t *mcl;
   6.252 +#endif
   6.253      PEND_RING_IDX dc, dp;
   6.254      unsigned int data_len;
   6.255  
   6.256 +
   6.257      if ( (dc = dealloc_cons) == (dp = dealloc_prod) )
   6.258          goto skip_dealloc;
   6.259  
   6.260 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.261 +    /*
   6.262 +     * Free up any grants we have finished using
   6.263 +     */
   6.264 +    gop = unmap_ops;
   6.265 +    while (dc != dp) {
   6.266 +        pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
   6.267 +        gop->host_virt_addr = MMAP_VADDR(pending_idx);
   6.268 +        gop->dev_bus_addr = 0;
   6.269 +        gop->handle = grant_tx_ref[pending_idx];
   6.270 +        grant_tx_ref[pending_idx] = GRANT_INVALID_REF;
   6.271 +        gop++;
   6.272 +    }
   6.273 +    if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
   6.274 +                                           unmap_ops, gop - unmap_ops))) {
   6.275 +        BUG();
   6.276 +    }
   6.277 +#else
   6.278      mcl = tx_mcl;
   6.279      while ( dc != dp )
   6.280      {
   6.281 @@ -433,10 +547,13 @@ static void net_tx_action(unsigned long 
   6.282          BUG();
   6.283  
   6.284      mcl = tx_mcl;
   6.285 +#endif
   6.286      while ( dealloc_cons != dp )
   6.287      {
   6.288 +#ifndef CONFIG_XEN_NETDEV_GRANT_TX
   6.289          /* The update_va_mapping() must not fail. */
   6.290          BUG_ON(mcl[0].result != 0);
   6.291 +#endif
   6.292  
   6.293          pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
   6.294  
   6.295 @@ -460,11 +577,17 @@ static void net_tx_action(unsigned long 
   6.296          
   6.297          netif_put(netif);
   6.298  
   6.299 +#ifndef CONFIG_XEN_NETDEV_GRANT_TX
   6.300          mcl++;
   6.301 +#endif
   6.302      }
   6.303  
   6.304   skip_dealloc:
   6.305 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.306 +    mop = map_ops;
   6.307 +#else
   6.308      mcl = tx_mcl;
   6.309 +#endif
   6.310      while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
   6.311              !list_empty(&net_schedule_list) )
   6.312      {
   6.313 @@ -486,7 +609,6 @@ static void net_tx_action(unsigned long 
   6.314          rmb(); /* Ensure that we see the request before we copy it. */
   6.315          memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, 
   6.316                 sizeof(txreq));
   6.317 -
   6.318          /* Credit-based scheduling. */
   6.319          if ( txreq.size > netif->remaining_credit )
   6.320          {
   6.321 @@ -566,13 +688,20 @@ static void net_tx_action(unsigned long 
   6.322  
   6.323          /* Packets passed to netif_rx() must have some headroom. */
   6.324          skb_reserve(skb, 16);
   6.325 -
   6.326 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.327 +        mop->host_virt_addr = MMAP_VADDR(pending_idx);
   6.328 +        mop->dom = netif->domid;
   6.329 +        mop->ref = txreq.addr >> PAGE_SHIFT;
   6.330 +        mop->flags = GNTMAP_host_map | GNTMAP_readonly;
   6.331 +        mop++;
   6.332 +#else
   6.333  	MULTI_update_va_mapping_otherdomain(
   6.334  	    mcl, MMAP_VADDR(pending_idx),
   6.335  	    pfn_pte_ma(txreq.addr >> PAGE_SHIFT, PAGE_KERNEL),
   6.336  	    0, netif->domid);
   6.337  
   6.338          mcl++;
   6.339 +#endif
   6.340  
   6.341          memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq));
   6.342          pending_tx_info[pending_idx].netif = netif;
   6.343 @@ -582,11 +711,26 @@ static void net_tx_action(unsigned long 
   6.344  
   6.345          pending_cons++;
   6.346  
   6.347 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.348 +        if ((mop - map_ops) >= ARRAY_SIZE(map_ops))
   6.349 +            break;
   6.350 +#else
   6.351          /* Filled the batch queue? */
   6.352          if ( (mcl - tx_mcl) == ARRAY_SIZE(tx_mcl) )
   6.353              break;
   6.354 +#endif
   6.355      }
   6.356  
   6.357 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.358 +    if (mop == map_ops) {
   6.359 +        return;
   6.360 +    }
   6.361 +    if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
   6.362 +                                           map_ops, mop - map_ops))) {
   6.363 +        BUG();
   6.364 +    }
   6.365 +    mop = map_ops;
   6.366 +#else
   6.367      if ( mcl == tx_mcl )
   6.368          return;
   6.369  
   6.370 @@ -594,6 +738,7 @@ static void net_tx_action(unsigned long 
   6.371          BUG();
   6.372  
   6.373      mcl = tx_mcl;
   6.374 +#endif
   6.375      while ( (skb = __skb_dequeue(&tx_queue)) != NULL )
   6.376      {
   6.377          pending_idx = *((u16 *)skb->data);
   6.378 @@ -601,6 +746,20 @@ static void net_tx_action(unsigned long 
   6.379          memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq));
   6.380  
   6.381          /* Check the remap error code. */
   6.382 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.383 +        if (unlikely(mop->dev_bus_addr == 0)) {
   6.384 +            printk(KERN_ALERT "#### netback grant fails\n");
   6.385 +            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
   6.386 +            netif_put(netif);
   6.387 +            kfree_skb(skb);
   6.388 +            mop++;
   6.389 +            pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
   6.390 +            continue;
   6.391 +        }
   6.392 +        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
   6.393 +                             FOREIGN_FRAME(mop->dev_bus_addr);
   6.394 +        grant_tx_ref[pending_idx] = mop->handle;
   6.395 +#else
   6.396          if ( unlikely(mcl[0].result != 0) )
   6.397          {
   6.398              DPRINTK("Bad page frame\n");
   6.399 @@ -614,6 +773,7 @@ static void net_tx_action(unsigned long 
   6.400  
   6.401          phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
   6.402              FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT);
   6.403 +#endif
   6.404  
   6.405          data_len = (txreq.size > PKT_PROT_LEN) ? PKT_PROT_LEN : txreq.size;
   6.406  
   6.407 @@ -621,7 +781,6 @@ static void net_tx_action(unsigned long 
   6.408          memcpy(skb->data, 
   6.409                 (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)),
   6.410                 data_len);
   6.411 -
   6.412          if ( data_len < txreq.size )
   6.413          {
   6.414              /* Append the packet payload as a fragment. */
   6.415 @@ -655,7 +814,11 @@ static void net_tx_action(unsigned long 
   6.416          netif_rx(skb);
   6.417          netif->dev->last_rx = jiffies;
   6.418  
   6.419 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.420 +        mop++;
   6.421 +#else
   6.422          mcl++;
   6.423 +#endif
   6.424      }
   6.425  }
   6.426  
   6.427 @@ -775,6 +938,12 @@ static int __init netback_init(void)
   6.428          return 0;
   6.429  
   6.430      printk("Initialising Xen netif backend\n");
   6.431 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   6.432 +    printk("#### netback tx using grant tables\n");
   6.433 +#endif
   6.434 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   6.435 +    printk("#### netback rx using grant tables\n");
   6.436 +#endif
   6.437  
   6.438      /* We can increase reservation by this much in net_rx_action(). */
   6.439      balloon_update_driver_allowance(NETIF_RX_RING_SIZE);
     7.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Mon Jul 25 09:56:50 2005 +0000
     7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Mon Jul 25 17:07:31 2005 +0000
     7.3 @@ -54,6 +54,25 @@
     7.4  #include <asm/page.h>
     7.5  #include <asm/uaccess.h>
     7.6  
     7.7 +#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
     7.8 +#include <asm-xen/xen-public/grant_table.h>
     7.9 +#include <asm-xen/gnttab.h>
    7.10 +#ifdef GRANT_DEBUG
    7.11 +static void
    7.12 +dump_packet(int tag, u32 addr, u32 ap)
    7.13 +{
    7.14 +    unsigned char *p = (unsigned char *)ap;
    7.15 +    int i;
    7.16 +    
    7.17 +    printk(KERN_ALERT "#### rx_poll   %c %08x ", tag & 0xff, addr);
    7.18 +    for (i = 0; i < 20; i++) {
    7.19 +        printk("%02x", p[i]);
    7.20 +    }
    7.21 +    printk("\n");
    7.22 +}
    7.23 +#endif
    7.24 +#endif
    7.25 +
    7.26  #ifndef __GFP_NOWARN
    7.27  #define __GFP_NOWARN 0
    7.28  #endif
    7.29 @@ -82,6 +101,21 @@
    7.30  #define TX_TEST_IDX req_cons  /* conservative: not seen all our requests? */
    7.31  #endif
    7.32  
    7.33 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
    7.34 +static grant_ref_t gref_tx_head, gref_tx_terminal;
    7.35 +static grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1];
    7.36 +#endif
    7.37 +
    7.38 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
    7.39 +static grant_ref_t gref_rx_head, gref_rx_terminal;
    7.40 +static grant_ref_t grant_rx_ref[NETIF_RX_RING_SIZE + 1];
    7.41 +#endif
    7.42 +
    7.43 +#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
    7.44 +static domid_t rdomid = 0;
    7.45 +#define GRANT_INVALID_REF	(0xFFFF)
    7.46 +#endif
    7.47 +
    7.48  static void network_tx_buf_gc(struct net_device *dev);
    7.49  static void network_alloc_rx_buffers(struct net_device *dev);
    7.50  
    7.51 @@ -322,6 +356,14 @@ static void network_tx_buf_gc(struct net
    7.52          for (i = np->tx_resp_cons; i != prod; i++) {
    7.53              id  = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
    7.54              skb = np->tx_skbs[id];
    7.55 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
    7.56 +            if (gnttab_query_foreign_access(grant_tx_ref[id]) != 0) {
    7.57 +                printk(KERN_ALERT "netfront: query foreign access\n");
    7.58 +            }
    7.59 +            gnttab_end_foreign_access(grant_tx_ref[id], GNTMAP_readonly);
    7.60 +            gnttab_release_grant_reference(&gref_tx_head, grant_tx_ref[id]);
    7.61 +            grant_tx_ref[id] = GRANT_INVALID_REF;
    7.62 +#endif
    7.63              ADD_ID_TO_FREELIST(np->tx_skbs, id);
    7.64              dev_kfree_skb_irq(skb);
    7.65          }
    7.66 @@ -356,6 +398,9 @@ static void network_alloc_rx_buffers(str
    7.67      struct sk_buff *skb;
    7.68      int i, batch_target;
    7.69      NETIF_RING_IDX req_prod = np->rx->req_prod;
    7.70 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
    7.71 +    int ref;
    7.72 +#endif
    7.73  
    7.74      if (unlikely(np->backend_state != BEST_CONNECTED))
    7.75          return;
    7.76 @@ -388,7 +433,16 @@ static void network_alloc_rx_buffers(str
    7.77          np->rx_skbs[id] = skb;
    7.78          
    7.79          np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id;
    7.80 -        
    7.81 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
    7.82 +        if ((ref = gnttab_claim_grant_reference(&gref_rx_head, gref_rx_terminal)) < 0) {
    7.83 +            printk(KERN_ALERT "#### netfront can't claim rx reference\n");
    7.84 +            BUG();
    7.85 +        }
    7.86 +        grant_rx_ref[id] = ref;
    7.87 +        gnttab_grant_foreign_transfer_ref(ref, rdomid,
    7.88 +        virt_to_machine(skb->head) >> PAGE_SHIFT);
    7.89 +        np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref;
    7.90 +#endif
    7.91          rx_pfn_array[i] = virt_to_machine(skb->head) >> PAGE_SHIFT;
    7.92  
    7.93  	/* Remove this page from pseudo phys map before passing back to Xen. */
    7.94 @@ -436,6 +490,10 @@ static int network_start_xmit(struct sk_
    7.95      struct net_private *np = netdev_priv(dev);
    7.96      netif_tx_request_t *tx;
    7.97      NETIF_RING_IDX i;
    7.98 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
    7.99 +    unsigned int ref;
   7.100 +    unsigned long mfn;
   7.101 +#endif
   7.102  
   7.103      if (unlikely(np->tx_full)) {
   7.104          printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name);
   7.105 @@ -470,7 +528,18 @@ static int network_start_xmit(struct sk_
   7.106      tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req;
   7.107  
   7.108      tx->id   = id;
   7.109 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   7.110 +    if ((ref = gnttab_claim_grant_reference(&gref_tx_head, gref_tx_terminal)) < 0) {
   7.111 +        printk(KERN_ALERT "#### netfront can't claim tx grant reference\n");
   7.112 +        BUG();
   7.113 +    }
   7.114 +    mfn = virt_to_machine(skb->data) >> PAGE_SHIFT;
   7.115 +    gnttab_grant_foreign_access_ref(ref, rdomid, mfn, GNTMAP_readonly);
   7.116 +    tx->addr = (ref << PAGE_SHIFT) | ((unsigned long)skb->data & ~PAGE_MASK);
   7.117 +    grant_tx_ref[id] = ref;
   7.118 +#else
   7.119      tx->addr = virt_to_machine(skb->data);
   7.120 +#endif
   7.121      tx->size = skb->len;
   7.122      tx->csum_blank = (skb->ip_summed == CHECKSUM_HW);
   7.123  
   7.124 @@ -530,6 +599,10 @@ static int netif_poll(struct net_device 
   7.125      int work_done, budget, more_to_do = 1;
   7.126      struct sk_buff_head rxq;
   7.127      unsigned long flags;
   7.128 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.129 +    unsigned long mfn;
   7.130 +    grant_ref_t ref;
   7.131 +#endif
   7.132  
   7.133      spin_lock(&np->rx_lock);
   7.134  
   7.135 @@ -542,7 +615,6 @@ static int netif_poll(struct net_device 
   7.136  
   7.137      if ((budget = *pbudget) > dev->quota)
   7.138          budget = dev->quota;
   7.139 -
   7.140      rp = np->rx->resp_prod;
   7.141      rmb(); /* Ensure we see queued responses up to 'rp'. */
   7.142  
   7.143 @@ -550,7 +622,6 @@ static int netif_poll(struct net_device 
   7.144  		    (i != rp) && (work_done < budget);
   7.145  		    i++, work_done++) {
   7.146          rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
   7.147 -
   7.148          /*
   7.149           * An error here is very odd. Usually indicates a backend bug,
   7.150           * low-memory condition, or that we didn't have reservation headroom.
   7.151 @@ -565,11 +636,23 @@ static int netif_poll(struct net_device 
   7.152              continue;
   7.153          }
   7.154  
   7.155 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.156 +        ref = grant_rx_ref[rx->id];
   7.157 +        grant_rx_ref[rx->id] = GRANT_INVALID_REF;
   7.158 +
   7.159 +        mfn = gnttab_end_foreign_transfer(ref);
   7.160 +        gnttab_release_grant_reference(&gref_rx_head, ref);
   7.161 +#endif
   7.162 +
   7.163          skb = np->rx_skbs[rx->id];
   7.164          ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
   7.165  
   7.166          /* NB. We handle skb overflow later. */
   7.167 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.168 +        skb->data = skb->head + rx->addr;
   7.169 +#else
   7.170          skb->data = skb->head + (rx->addr & ~PAGE_MASK);
   7.171 +#endif
   7.172          skb->len  = rx->status;
   7.173          skb->tail = skb->data + skb->len;
   7.174  
   7.175 @@ -580,16 +663,32 @@ static int netif_poll(struct net_device 
   7.176          np->stats.rx_bytes += rx->status;
   7.177  
   7.178          /* Remap the page. */
   7.179 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.180 +        mmu->ptr = mfn << PAGE_SHIFT | MMU_MACHPHYS_UPDATE;
   7.181 +#else
   7.182          mmu->ptr  = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE;
   7.183 +#endif
   7.184          mmu->val  = __pa(skb->head) >> PAGE_SHIFT;
   7.185          mmu++;
   7.186 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.187 +	MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
   7.188 +				pfn_pte_ma(mfn, PAGE_KERNEL), 0);
   7.189 +#else
   7.190  	MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
   7.191  				pfn_pte_ma(rx->addr >> PAGE_SHIFT, PAGE_KERNEL), 0);
   7.192 +#endif
   7.193          mcl++;
   7.194  
   7.195          phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = 
   7.196 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.197 +            mfn;
   7.198 +#else
   7.199              rx->addr >> PAGE_SHIFT;
   7.200 -
   7.201 +#endif
   7.202 +#ifdef GRANT_DEBUG
   7.203 +        printk(KERN_ALERT "#### rx_poll     enqueue vdata=%08x mfn=%08x ref=%04x\n",
   7.204 +               skb->data, mfn, ref);
   7.205 +#endif
   7.206          __skb_queue_tail(&rxq, skb);
   7.207      }
   7.208  
   7.209 @@ -608,6 +707,11 @@ static int netif_poll(struct net_device 
   7.210      }
   7.211  
   7.212      while ((skb = __skb_dequeue(&rxq)) != NULL) {
   7.213 +#ifdef GRANT_DEBUG
   7.214 +         printk(KERN_ALERT "#### rx_poll     dequeue vdata=%08x mfn=%08x\n",
   7.215 +                skb->data, virt_to_machine(skb->data)>>PAGE_SHIFT);
   7.216 +         dump_packet('d', skb->data, (unsigned long)skb->data);
   7.217 +#endif
   7.218          /*
   7.219           * Enough room in skbuff for the data we were passed? Also, Linux 
   7.220           * expects at least 16 bytes headroom in each receive buffer.
   7.221 @@ -616,6 +720,7 @@ static int netif_poll(struct net_device 
   7.222  			unlikely((skb->data - skb->head) < 16)) {
   7.223              nskb = NULL;
   7.224  
   7.225 +
   7.226              /* Only copy the packet if it fits in the current MTU. */
   7.227              if (skb->len <= (dev->mtu + ETH_HLEN)) {
   7.228                  if ((skb->tail > skb->end) && net_ratelimit())
   7.229 @@ -646,7 +751,6 @@ static int netif_poll(struct net_device 
   7.230          
   7.231          /* Set the shared-info area, which is hidden behind the real data. */
   7.232          init_skb_shinfo(skb);
   7.233 -
   7.234          /* Ethernet-specific work. Delayed to here as it peeks the header. */
   7.235          skb->protocol = eth_type_trans(skb, dev);
   7.236  
   7.237 @@ -919,6 +1023,9 @@ vif_connect(struct net_private *np, neti
   7.238      network_connect(dev, status);
   7.239      np->evtchn = status->evtchn;
   7.240      np->irq = bind_evtchn_to_irq(np->evtchn);
   7.241 +#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
   7.242 +    rdomid = status->domid;
   7.243 +#endif
   7.244      (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, dev->name, dev);
   7.245      netctrl_connected_count();
   7.246      (void)send_fake_arp(dev);
   7.247 @@ -962,10 +1069,18 @@ static int create_netdev(int handle, str
   7.248      np->rx_max_target = RX_MAX_TARGET;
   7.249  
   7.250      /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
   7.251 -    for (i = 0; i <= NETIF_TX_RING_SIZE; i++)
   7.252 +    for (i = 0; i <= NETIF_TX_RING_SIZE; i++) {
   7.253          np->tx_skbs[i] = (void *)((unsigned long) i+1);
   7.254 -    for (i = 0; i <= NETIF_RX_RING_SIZE; i++)
   7.255 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   7.256 +        grant_tx_ref[i] = GRANT_INVALID_REF;
   7.257 +#endif
   7.258 +    }
   7.259 +    for (i = 0; i <= NETIF_RX_RING_SIZE; i++) {
   7.260          np->rx_skbs[i] = (void *)((unsigned long) i+1);
   7.261 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.262 +        grant_rx_ref[i] = GRANT_INVALID_REF;
   7.263 +#endif
   7.264 +    }
   7.265  
   7.266      dev->open            = network_open;
   7.267      dev->hard_start_xmit = network_start_xmit;
   7.268 @@ -1267,6 +1382,22 @@ static int __init netif_init(void)
   7.269  
   7.270      if (xen_start_info.flags & SIF_INITDOMAIN)
   7.271          return 0;
   7.272 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   7.273 +    if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
   7.274 +                                      &gref_tx_head, &gref_tx_terminal) < 0) {
   7.275 +        printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
   7.276 +        return 1;
   7.277 +    }
   7.278 +    printk(KERN_ALERT "#### netfront tx using grant tables\n");
   7.279 +#endif
   7.280 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.281 +    if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE,
   7.282 +                                      &gref_rx_head, &gref_rx_terminal) < 0) {
   7.283 +        printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
   7.284 +        return 1;
   7.285 +    }
   7.286 +    printk(KERN_ALERT "#### netfront rx using grant tables\n");
   7.287 +#endif
   7.288  
   7.289      if ((err = xennet_proc_init()) != 0)
   7.290          return err;
   7.291 @@ -1286,6 +1417,16 @@ static int __init netif_init(void)
   7.292      return err;
   7.293  }
   7.294  
   7.295 +static void netif_exit(void)
   7.296 +{
   7.297 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   7.298 +    gnttab_free_grant_references(NETIF_TX_RING_SIZE, gref_tx_head);
   7.299 +#endif
   7.300 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
   7.301 +    gnttab_free_grant_references(NETIF_RX_RING_SIZE, gref_rx_head);
   7.302 +#endif
   7.303 +}
   7.304 +
   7.305  static void vif_suspend(struct net_private *np)
   7.306  {
   7.307      /* Avoid having tx/rx stuff happen until we're ready. */
   7.308 @@ -1478,3 +1619,4 @@ static void xennet_proc_delif(struct net
   7.309  #endif
   7.310  
   7.311  module_init(netif_init);
   7.312 +module_exit(netif_exit);
     8.1 --- a/xen/common/grant_table.c	Mon Jul 25 09:56:50 2005 +0000
     8.2 +++ b/xen/common/grant_table.c	Mon Jul 25 17:07:31 2005 +0000
     8.3 @@ -809,6 +809,146 @@ gnttab_dump_table(gnttab_dump_table_t *u
     8.4  }
     8.5  #endif
     8.6  
     8.7 +static long
     8.8 +gnttab_donate(gnttab_donate_t *uop, unsigned int count)
     8.9 +{
    8.10 +    struct domain *d = current->domain;
    8.11 +    struct domain *e;
    8.12 +    struct pfn_info *page;
    8.13 +    u32 _d, _nd, x, y;
    8.14 +    int i;
    8.15 +    int result = GNTST_okay;
    8.16 +
    8.17 +    for (i = 0; i < count; i++) {
    8.18 +        gnttab_donate_t *gop = &uop[i];
    8.19 +#if GRANT_DEBUG
    8.20 +        printk("gnttab_donate: i=%d mfn=%08x domid=%d gref=%08x\n",
    8.21 +               i, gop->mfn, gop->domid, gop->handle);
    8.22 +#endif
    8.23 +        page = &frame_table[gop->mfn];
    8.24 +
    8.25 +        if (unlikely(IS_XEN_HEAP_FRAME(page))) { 
    8.26 +            printk("gnttab_donate: xen heap frame mfn=%lx\n", (unsigned long) gop->mfn);
    8.27 +            gop->status = GNTST_bad_virt_addr;
    8.28 +            continue;
    8.29 +        }
    8.30 +        if (unlikely(!pfn_valid(page_to_pfn(page)))) {
    8.31 +            printk("gnttab_donate: invalid pfn for mfn=%lx\n", (unsigned long) gop->mfn);
    8.32 +            gop->status = GNTST_bad_virt_addr;
    8.33 +            continue;
    8.34 +        }
    8.35 +        if (unlikely((e = find_domain_by_id(gop->domid)) == NULL)) {
    8.36 +            printk("gnttab_donate: can't find domain %d\n", gop->domid);
    8.37 +            gop->status = GNTST_bad_domain;
    8.38 +            continue;
    8.39 +        }
    8.40 +
    8.41 +        spin_lock(&d->page_alloc_lock);
    8.42 +
    8.43 +        /*
    8.44 +         * The tricky bit: atomically release ownership while
    8.45 +         * there is just one benign reference to the page
    8.46 +         * (PGC_allocated). If that reference disappears then the
    8.47 +         * deallocation routine will safely spin.
    8.48 +         */
    8.49 +        _d  = pickle_domptr(d);
    8.50 +        _nd = page->u.inuse._domain;
    8.51 +        y   = page->count_info;
    8.52 +        do {
    8.53 +            x = y;
    8.54 +            if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
    8.55 +                         (1 | PGC_allocated)) || unlikely(_nd != _d)) {
    8.56 +                printk("gnttab_donate: Bad page values %p: ed=%p(%u), sd=%p,"
    8.57 +                        " caf=%08x, taf=%08x\n", (void *) page_to_pfn(page),
    8.58 +                        d, d->domain_id, unpickle_domptr(_nd), x, 
    8.59 +                        page->u.inuse.type_info);
    8.60 +                spin_unlock(&d->page_alloc_lock);
    8.61 +                put_domain(e);
    8.62 +                return 0;
    8.63 +            }
    8.64 +            __asm__ __volatile__(
    8.65 +                LOCK_PREFIX "cmpxchg8b %2"
    8.66 +                : "=d" (_nd), "=a" (y),
    8.67 +                "=m" (*(volatile u64 *)(&page->count_info))
    8.68 +                : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
    8.69 +        } while (unlikely(_nd != _d) || unlikely(y != x));
    8.70 +
    8.71 +        /*
    8.72 +         * Unlink from 'd'. At least one reference remains (now
    8.73 +         * anonymous), so noone else is spinning to try to delete
    8.74 +         * this page from 'd'.
    8.75 +         */
    8.76 +        d->tot_pages--;
    8.77 +        list_del(&page->list);
    8.78 +
    8.79 +        spin_unlock(&d->page_alloc_lock);
    8.80 +
    8.81 +        spin_lock(&e->page_alloc_lock);
    8.82 +
    8.83 +        /*
    8.84 +         * Check that 'e' will accept the page and has reservation
    8.85 +         * headroom.  Also, a domain mustn't have PGC_allocated
    8.86 +         * pages when it is dying.
    8.87 +         */
    8.88 +#ifdef GRANT_DEBUG
    8.89 +        if (unlikely(e->tot_pages >= e->max_pages)) {
    8.90 +            printk("gnttab_dontate: no headroom tot_pages=%d max_pages=%d\n",
    8.91 +                   e->tot_pages, e->max_pages);
    8.92 +            spin_unlock(&e->page_alloc_lock);
    8.93 +            put_domain(e);
    8.94 +            result = GNTST_general_error;
    8.95 +            break;
    8.96 +        }
    8.97 +        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags))) {
    8.98 +            printk("gnttab_donate: target domain is dying\n");
    8.99 +            spin_unlock(&e->page_alloc_lock);
   8.100 +            put_domain(e);
   8.101 +            result = GNTST_general_error;
   8.102 +            break;
   8.103 +        }
   8.104 +        if (unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) {
   8.105 +            printk("gnttab_donate: gnttab_prepare_for_transfer fails\n");
   8.106 +            spin_unlock(&e->page_alloc_lock);
   8.107 +            put_domain(e);
   8.108 +            result = GNTST_general_error;
   8.109 +            break;
   8.110 +        }
   8.111 +#else
   8.112 +        ASSERT(e->tot_pages <= e->max_pages);
   8.113 +        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) ||
   8.114 +            unlikely(e->tot_pages == e->max_pages) ||
   8.115 +            unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) {
   8.116 +            printk("gnttab_donate: Transferee has no reservation headroom (%d,%d), or "
   8.117 +                    "provided a bad grant ref (%08x), or is dying (%p).\n",
   8.118 +                    e->tot_pages, e->max_pages, gop->handle, e->d_flags);
   8.119 +            spin_unlock(&e->page_alloc_lock);
   8.120 +            put_domain(e);
   8.121 +            result = GNTST_general_error;
   8.122 +            break;
   8.123 +        }
   8.124 +#endif
   8.125 +        /* Okay, add the page to 'e'. */
   8.126 +        if (unlikely(e->tot_pages++ == 0)) {
   8.127 +            get_knownalive_domain(e);
   8.128 +        }
   8.129 +        list_add_tail(&page->list, &e->page_list);
   8.130 +        page_set_owner(page, e);
   8.131 +
   8.132 +        spin_unlock(&e->page_alloc_lock);
   8.133 +
   8.134 +        /*
   8.135 +         * Transfer is all done: tell the guest about its new page
   8.136 +         * frame.
   8.137 +         */
   8.138 +        gnttab_notify_transfer(e, d, gop->handle, gop->mfn);
   8.139 +        
   8.140 +        put_domain(e);
   8.141 +
   8.142 +        gop->status = GNTST_okay;
   8.143 +    }
   8.144 +    return result;
   8.145 +}
   8.146 +
   8.147  long 
   8.148  do_grant_table_op(
   8.149      unsigned int cmd, void *uop, unsigned int count)
   8.150 @@ -843,6 +983,11 @@ do_grant_table_op(
   8.151          rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
   8.152          break;
   8.153  #endif
   8.154 +    case GNTTABOP_donate:
   8.155 +        if (unlikely(!array_access_ok(uop, count, sizeof(gnttab_donate_t))))
   8.156 +            goto out;
   8.157 +        rc = gnttab_donate(uop, count);
   8.158 +        break;
   8.159      default:
   8.160          rc = -ENOSYS;
   8.161          break;
     9.1 --- a/xen/include/public/grant_table.h	Mon Jul 25 09:56:50 2005 +0000
     9.2 +++ b/xen/include/public/grant_table.h	Mon Jul 25 17:07:31 2005 +0000
     9.3 @@ -213,6 +213,19 @@ typedef struct gnttab_dump_table {
     9.4      s16         status;               /* GNTST_* */
     9.5  } gnttab_dump_table_t;
     9.6  
     9.7 +/*
     9.8 + * GNTTABOP_donate_grant_ref: Donate <frame> to a foreign domain.  The
     9.9 + * foreign domain has previously registered the details of the transfer.
    9.10 + * These can be identified from <handle>, a grant reference.
    9.11 + */
    9.12 +#define GNTTABOP_donate                4
    9.13 +typedef struct {
    9.14 +    memory_t    mfn;		      /*  0 */
    9.15 +    domid_t     domid;		      /*  4 */
    9.16 +    u16         handle;               /*  8 */
    9.17 +    s16         status;               /*  10: GNTST_* */
    9.18 +    u32         __pad;
    9.19 +} gnttab_donate_t;	      /*  14 bytes */
    9.20  
    9.21  /*
    9.22   * Bitfield values for update_pin_status.flags.
    10.1 --- a/xen/include/public/io/netif.h	Mon Jul 25 09:56:50 2005 +0000
    10.2 +++ b/xen/include/public/io/netif.h	Mon Jul 25 17:07:31 2005 +0000
    10.3 @@ -23,10 +23,17 @@ typedef struct netif_tx_response {
    10.4  
    10.5  typedef struct {
    10.6      u16       id;    /* Echoed in response message.        */
    10.7 +#ifdef CONFIG_XEN_NETDEV_GRANT_RX
    10.8 +    grant_ref_t gref;	/* 2: Reference to incoming granted frame */
    10.9 +#endif
   10.10  } netif_rx_request_t;
   10.11  
   10.12  typedef struct {
   10.13 +#ifdef CONFIG_XEN_NETDEV_GRANT_TX
   10.14 +    u32      addr;   /*  0: Offset in page of start of received packet  */
   10.15 +#else
   10.16      memory_t addr;   /* Machine address of packet.              */
   10.17 +#endif
   10.18      u16      csum_valid:1; /* Protocol checksum is validated?       */
   10.19      u16      id:15;
   10.20      s16      status; /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */