ia64/xen-unstable

changeset 3085:3cfac953da9e

bitkeeper revision 1.1159.183.5 (41a26b294k_qNaQn_V2H5pnhsFA15w)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-2.0-testing.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
author iap10@labyrinth.cl.cam.ac.uk
date Mon Nov 22 22:41:45 2004 +0000 (2004-11-22)
parents 5281b60ddd27 d6216cd62518
children 7ef582b6c9c4
files .rootkeys linux-2.6.9-xen-sparse/arch/xen/Kconfig linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig linux-2.6.9-xen-sparse/drivers/xen/Makefile linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c
line diff
     1.1 --- a/.rootkeys	Mon Nov 22 22:40:14 2004 +0000
     1.2 +++ b/.rootkeys	Mon Nov 22 22:41:45 2004 +0000
     1.3 @@ -192,6 +192,12 @@ 40f562395atl9x4suKGhPkjqLOXESg linux-2.6
     1.4  40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c
     1.5  40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.9-xen-sparse/drivers/xen/blkfront/block.h
     1.6  40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.9-xen-sparse/drivers/xen/blkfront/vbd.c
     1.7 +41a226e0vjAcDXHOnXE5ummcdUD2mg linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile
     1.8 +41a226e0VeZA1N8tbU6nvJ3OxUcJmw linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c
     1.9 +41a226e1k4J5VMLnrYXDWRqElS49YQ linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h
    1.10 +41a226e1-A_Hy7utS8vJKaXnH_tzfA linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c
    1.11 +41a226e19NoUUTOvs7jumDMRYDIO4Q linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c
    1.12 +41a226e1MNSyWWK5dEVgvSQ5OW0fDA linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c
    1.13  40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.9-xen-sparse/drivers/xen/console/Makefile
    1.14  3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.9-xen-sparse/drivers/xen/console/console.c
    1.15  40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.9-xen-sparse/drivers/xen/evtchn/Makefile
     2.1 --- a/linux-2.6.9-xen-sparse/arch/xen/Kconfig	Mon Nov 22 22:40:14 2004 +0000
     2.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/Kconfig	Mon Nov 22 22:41:45 2004 +0000
     2.3 @@ -49,6 +49,20 @@ config XEN_BLKDEV_BACKEND
     2.4            block devices to other guests via a high-performance shared-memory
     2.5            interface.
     2.6  
     2.7 +if XEN_BLKDEV_BACKEND
     2.8 +config XEN_BLKDEV_TAP_BE
     2.9 +        bool "Block Tap support for backend driver (DANGEROUS)"
    2.10 +        default n
    2.11 +        help
    2.12 +          If you intend to use the block tap driver, the backend domain will
    2.13 +          not know the domain id of the real frontend, and so will not be able
    2.14 +          to map its data pages.  This modifies the backend to attempt to map
    2.15 +          from both the tap domain and the real frontend.  This presents a
    2.16 +          security risk, and so should ONLY be used for development
    2.17 +          with the blktap.  This option will be removed as the block drivers are
    2.18 +          modified to use grant tables.
    2.19 +endif
    2.20 +
    2.21  config XEN_NETDEV_BACKEND
    2.22          bool "Network-device backend driver"
    2.23          default y if XEN_PHYSDEV_ACCESS
    2.24 @@ -94,6 +108,16 @@ config XEN_NETDEV_FRONTEND_PIPELINED_TRA
    2.25            enabled; then you must say N here.
    2.26  endif
    2.27  
    2.28 +config XEN_BLKDEV_TAP
    2.29 +        bool "Block device tap driver"
    2.30 +        default n
    2.31 +        help
    2.32 +          This driver allows a VM to interact on block device channels
    2.33 +          to other VMs.  Block messages may be passed through or redirected
    2.34 +          to a character device, allowing device prototyping in application
    2.35 +          space.  Odds are that you want to say N here.
    2.36 +
    2.37 +
    2.38  config XEN_WRITABLE_PAGETABLES
    2.39  	bool
    2.40  	default y
     3.1 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig	Mon Nov 22 22:40:14 2004 +0000
     3.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig	Mon Nov 22 22:41:45 2004 +0000
     3.3 @@ -13,9 +13,11 @@ CONFIG_NO_IDLE_HZ=y
     3.4  CONFIG_XEN_PRIVILEGED_GUEST=y
     3.5  CONFIG_XEN_PHYSDEV_ACCESS=y
     3.6  CONFIG_XEN_BLKDEV_BACKEND=y
     3.7 +# CONFIG_XEN_BLKDEV_TAP_BE is not set
     3.8  CONFIG_XEN_NETDEV_BACKEND=y
     3.9  CONFIG_XEN_BLKDEV_FRONTEND=y
    3.10  CONFIG_XEN_NETDEV_FRONTEND=y
    3.11 +# CONFIG_XEN_BLKDEV_TAP is not set
    3.12  # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
    3.13  CONFIG_XEN_WRITABLE_PAGETABLES=y
    3.14  CONFIG_XEN_SCRUB_PAGES=y
     4.1 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig	Mon Nov 22 22:40:14 2004 +0000
     4.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig	Mon Nov 22 22:41:45 2004 +0000
     4.3 @@ -13,9 +13,11 @@ CONFIG_NO_IDLE_HZ=y
     4.4  # CONFIG_XEN_PRIVILEGED_GUEST is not set
     4.5  # CONFIG_XEN_PHYSDEV_ACCESS is not set
     4.6  # CONFIG_XEN_BLKDEV_BACKEND is not set
     4.7 +# CONFIG_XEN_BLKDEV_TAP_BE is not set
     4.8  # CONFIG_XEN_NETDEV_BACKEND is not set
     4.9  CONFIG_XEN_BLKDEV_FRONTEND=y
    4.10  CONFIG_XEN_NETDEV_FRONTEND=y
    4.11 +# CONFIG_XEN_BLKDEV_TAP is not set
    4.12  # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
    4.13  CONFIG_XEN_WRITABLE_PAGETABLES=y
    4.14  CONFIG_XEN_SCRUB_PAGES=y
     5.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/Makefile	Mon Nov 22 22:40:14 2004 +0000
     5.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/Makefile	Mon Nov 22 22:41:45 2004 +0000
     5.3 @@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkb
     5.4  obj-$(CONFIG_XEN_NETDEV_BACKEND)	+= netback/
     5.5  obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= blkfront/
     5.6  obj-$(CONFIG_XEN_NETDEV_FRONTEND)	+= netfront/
     5.7 +obj-$(CONFIG_XEN_BLKDEV_TAP)    	+= blktap/
     5.8  
     6.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c	Mon Nov 22 22:40:14 2004 +0000
     6.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c	Mon Nov 22 22:41:45 2004 +0000
     6.3 @@ -68,6 +68,19 @@ static PEND_RING_IDX pending_prod, pendi
     6.4  static kmem_cache_t *buffer_head_cachep;
     6.5  #endif
     6.6  
     6.7 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
     6.8 +/*
     6.9 + * If the tap driver is used, we may get pages belonging to either the tap
    6.10 + * or (more likely) the real frontend.  The backend must specify which domain
    6.11 + * a given page belongs to in update_va_mapping though.  For the moment, 
    6.12 + * we pass in the domid of the real frontend in PROBE messages and store 
    6.13 + * this value in alt_dom.  Then on mapping, we try both.  This is a Guiness 
    6.14 + * book of records-calibre grim hack, and represents a bit of a security risk.
    6.15 + * Grant tables will soon solve the problem though!
    6.16 + */
    6.17 +static domid_t alt_dom = 0;
    6.18 +#endif
    6.19 +
    6.20  static int do_block_io_op(blkif_t *blkif, int max_to_do);
    6.21  static void dispatch_probe(blkif_t *blkif, blkif_request_t *req);
    6.22  static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req);
    6.23 @@ -323,12 +336,27 @@ static void dispatch_probe(blkif_t *blki
    6.24           (blkif_last_sect(req->frame_and_sects[0]) != 7) )
    6.25          goto out;
    6.26  
    6.27 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
    6.28 +    /* Grab the real frontend out of the probe message. */
    6.29 +    alt_dom = (domid_t)req->frame_and_sects[1];
    6.30 +#endif
    6.31 +    
    6.32      if ( HYPERVISOR_update_va_mapping_otherdomain(
    6.33          MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT,
    6.34          (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
    6.35 -        0, blkif->domid) )
    6.36 +        0, blkif->domid) ) {
    6.37 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
    6.38 +        /* That didn't work.  Try alt_dom. */
    6.39 +        if ( HYPERVISOR_update_va_mapping_otherdomain(
    6.40 +            MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT,
    6.41 +            (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
    6.42 +            0, alt_dom) )
    6.43 +            goto out;
    6.44 +#else  
    6.45          goto out;
    6.46 -
    6.47 +#endif
    6.48 +    }
    6.49 +    
    6.50      rsp = vbd_probe(blkif, (vdisk_t *)MMAP_VADDR(pending_idx, 0), 
    6.51                      PAGE_SIZE / sizeof(vdisk_t));
    6.52  
    6.53 @@ -411,8 +439,11 @@ static void dispatch_rw_block_io(blkif_t
    6.54          mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT;
    6.55          mcl[i].args[1] = (phys_seg[i].buffer & PAGE_MASK) | remap_prot;
    6.56          mcl[i].args[2] = 0;
    6.57 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
    6.58 +        mcl[i].args[3] = (alt_dom != 0) ? alt_dom : blkif->domid;
    6.59 +#else
    6.60          mcl[i].args[3] = blkif->domid;
    6.61 -
    6.62 +#endif
    6.63          phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
    6.64              FOREIGN_FRAME(phys_seg[i].buffer >> PAGE_SHIFT);
    6.65      }
    6.66 @@ -579,7 +610,10 @@ static int __init blkif_init(void)
    6.67  #endif
    6.68  
    6.69      blkif_ctrlif_init();
    6.70 -
    6.71 +    
    6.72 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
    6.73 +    printk(KERN_ALERT "NOTE: Blkif backend is running with tap support on!\n");
    6.74 +#endif
    6.75      return 0;
    6.76  }
    6.77  
     7.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Nov 22 22:40:14 2004 +0000
     7.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Nov 22 22:41:45 2004 +0000
     7.3 @@ -1262,7 +1262,8 @@ static void blkif_status(blkif_fe_interf
     7.4  {
     7.5      if ( status->handle != blkif_handle )
     7.6      {
     7.7 -        WPRINTK(" Invalid blkif: handle=%u", status->handle);
     7.8 +        WPRINTK(" Invalid blkif: handle=%u\n", status->handle);
     7.9 +        unexpected(status);
    7.10          return;
    7.11      }
    7.12  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile	Mon Nov 22 22:41:45 2004 +0000
     8.3 @@ -0,0 +1,3 @@
     8.4 +
     8.5 +obj-y	:= blktap_userdev.o blktap_datapath.o blktap_controlmsg.o blktap.o 
     8.6 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c	Mon Nov 22 22:41:45 2004 +0000
     9.3 @@ -0,0 +1,86 @@
     9.4 +/******************************************************************************
     9.5 + * blktap.c
     9.6 + * 
     9.7 + * XenLinux virtual block-device tap.
     9.8 + * 
     9.9 + * Copyright (c) 2004, Andrew Warfield
    9.10 + *
    9.11 + * Based on the original split block driver:
    9.12 + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
    9.13 + * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
    9.14 + * Copyright (c) 2004, Christian Limpach
    9.15 + * 
    9.16 + * Note that unlike the split block driver code, this driver has been developed
    9.17 + * strictly for Linux 2.6
    9.18 + */
    9.19 +
    9.20 +#include "blktap.h"
    9.21 +
    9.22 +int __init xlblk_init(void)
    9.23 +{
    9.24 +    ctrl_msg_t               cmsg;
    9.25 +    blkif_fe_driver_status_t fe_st;
    9.26 +    blkif_be_driver_status_t be_st;
    9.27 +
    9.28 +    printk(KERN_INFO "Initialising Xen block tap device\n");
    9.29 +
    9.30 +    DPRINTK("   tap - Backend connection init:\n");
    9.31 +
    9.32 +
    9.33 +    (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
    9.34 +                                    CALLBACK_IN_BLOCKING_CONTEXT);
    9.35 +
    9.36 +    /* Send a driver-UP notification to the domain controller. */
    9.37 +    cmsg.type      = CMSG_BLKIF_FE;
    9.38 +    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
    9.39 +    cmsg.length    = sizeof(blkif_fe_driver_status_t);
    9.40 +    fe_st.status   = BLKIF_DRIVER_STATUS_UP;
    9.41 +    memcpy(cmsg.msg, &fe_st, sizeof(fe_st));
    9.42 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
    9.43 +
    9.44 +    DPRINTK("   tap - Frontend connection init:\n");
    9.45 +    
    9.46 +    active_reqs_init();
    9.47 +    
    9.48 +    ptfe_blkif.status = DISCONNECTED;
    9.49 +
    9.50 +    (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, 
    9.51 +                                    CALLBACK_IN_BLOCKING_CONTEXT);
    9.52 +
    9.53 +    /* Send a driver-UP notification to the domain controller. */
    9.54 +    cmsg.type      = CMSG_BLKIF_BE;
    9.55 +    cmsg.subtype   = CMSG_BLKIF_BE_DRIVER_STATUS;
    9.56 +    cmsg.length    = sizeof(blkif_be_driver_status_t);
    9.57 +    be_st.status   = BLKIF_DRIVER_STATUS_UP;
    9.58 +    memcpy(cmsg.msg, &be_st, sizeof(be_st));
    9.59 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
    9.60 +
    9.61 +    DPRINTK("   tap - Userland channel init:\n");
    9.62 +
    9.63 +    blktap_init();
    9.64 +
    9.65 +    DPRINTK("Blkif tap device initialized.\n");
    9.66 +
    9.67 +    return 0;
    9.68 +}
    9.69 +
    9.70 +void blkdev_suspend(void)
    9.71 +{
    9.72 +}
    9.73 +
    9.74 +void blkdev_resume(void)
    9.75 +{
    9.76 +    ctrl_msg_t               cmsg;
    9.77 +    blkif_fe_driver_status_t st;    
    9.78 +
    9.79 +    /* Send a driver-UP notification to the domain controller. */
    9.80 +    cmsg.type      = CMSG_BLKIF_FE;
    9.81 +    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
    9.82 +    cmsg.length    = sizeof(blkif_fe_driver_status_t);
    9.83 +    st.status      = BLKIF_DRIVER_STATUS_UP;
    9.84 +    memcpy(cmsg.msg, &st, sizeof(st));
    9.85 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
    9.86 +}
    9.87 +
    9.88 +
    9.89 +__initcall(xlblk_init);
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h	Mon Nov 22 22:41:45 2004 +0000
    10.3 @@ -0,0 +1,254 @@
    10.4 +/*
    10.5 + * blktap.h
    10.6 + * 
    10.7 + * Interfaces for the Xen block tap driver.
    10.8 + * 
    10.9 + * (c) 2004, Andrew Warfield, University of Cambridge
   10.10 + * 
   10.11 + */
   10.12 +
   10.13 +#ifndef __BLKTAP_H__
   10.14 +#define __BLKTAP_H__
   10.15 +
   10.16 +#include <linux/version.h>
   10.17 +#include <linux/blkdev.h>
   10.18 +#include <linux/config.h>
   10.19 +#include <linux/sched.h>
   10.20 +#include <linux/interrupt.h>
   10.21 +#include <asm-xen/ctrl_if.h>
   10.22 +#include <linux/slab.h>
   10.23 +#include <linux/blkdev.h>
   10.24 +#include <asm/io.h>
   10.25 +#include <asm/setup.h>
   10.26 +#include <asm/pgalloc.h>
   10.27 +#include <asm-xen/hypervisor.h>
   10.28 +#include <asm-xen/xen-public/io/blkif.h>
   10.29 +
   10.30 +/* -------[ debug / pretty printing ]--------------------------------- */
   10.31 +
   10.32 +#if 0
   10.33 +#define ASSERT(_p) \
   10.34 +    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
   10.35 +    __LINE__, __FILE__); *(int*)0=0; }
   10.36 +#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
   10.37 +                           __FILE__ , __LINE__ , ## _a )
   10.38 +#else
   10.39 +#define ASSERT(_p) ((void)0)
   10.40 +#define DPRINTK(_f, _a...) ((void)0)
   10.41 +#endif
   10.42 +
   10.43 +#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
   10.44 +
   10.45 +/* -------[ connection / request tracking ]--------------------------- */
   10.46 +
   10.47 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   10.48 +#define VMALLOC_VMADDR(x) ((unsigned long)(x))
   10.49 +#endif
   10.50 +
   10.51 +extern spinlock_t blkif_io_lock;
   10.52 +
   10.53 +typedef struct blkif_st {
   10.54 +    /* Unique identifier for this interface. */
   10.55 +    domid_t          domid;
   10.56 +    unsigned int     handle;
   10.57 +    /* Physical parameters of the comms window. */
   10.58 +    unsigned long    shmem_frame;
   10.59 +    unsigned int     evtchn;
   10.60 +    int              irq;
   10.61 +    /* Comms information. */
   10.62 +    blkif_ring_t    *blk_ring_base; /* ioremap()'ed ptr to shmem_frame. */
   10.63 +    BLKIF_RING_IDX     blk_req_cons;  /* Request consumer. */
   10.64 +    BLKIF_RING_IDX     blk_resp_prod; /* Private version of resp. producer. */
   10.65 +    
   10.66 +    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
   10.67 +    /*
   10.68 +     * DISCONNECT response is deferred until pending requests are ack'ed.
   10.69 +     * We therefore need to store the id from the original request.
   10.70 +     */    u8               disconnect_rspid;
   10.71 +    struct blkif_st *hash_next;
   10.72 +    struct list_head blkdev_list;
   10.73 +    spinlock_t       blk_ring_lock;
   10.74 +    atomic_t         refcnt;
   10.75 +    
   10.76 +    struct work_struct work;
   10.77 +} blkif_t;
   10.78 +
   10.79 +typedef struct {
   10.80 +    blkif_t       *blkif;
   10.81 +    unsigned long  id;
   10.82 +    int            nr_pages;
   10.83 +    unsigned long  mach_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   10.84 +    unsigned long  virt_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   10.85 +    int            next_free;
   10.86 +} active_req_t;
   10.87 +
   10.88 +
   10.89 +/* -------[ block ring structs ]-------------------------------------- */
   10.90 +
   10.91 +/* Types of ring. */
   10.92 +#define BLKIF_REQ_RING_TYPE 1
   10.93 +#define BLKIF_RSP_RING_TYPE 2
   10.94 +
   10.95 +/* generic ring struct. */
   10.96 +typedef struct blkif_generic_ring_struct {
   10.97 +    int type;
   10.98 +} blkif_generic_ring_t;
   10.99 +
  10.100 +/* A requestor's view of a ring. */
  10.101 +typedef struct blkif_req_ring_struct {
  10.102 +
  10.103 +    int type;                    /* Will be BLKIF_REQ_RING_TYPE        */
  10.104 +    BLKIF_RING_IDX req_prod;     /* PRIVATE req_prod index             */
  10.105 +    BLKIF_RING_IDX rsp_cons;     /* Response consumer index            */
  10.106 +    blkif_ring_t *ring;          /* Pointer to shared ring struct      */
  10.107 +
  10.108 +} blkif_req_ring_t;
  10.109 +
  10.110 +#define BLKIF_REQ_RING_INIT { BLKIF_REQ_RING_TYPE, 0, 0, 0 }
  10.111 +
  10.112 +/* A responder's view of a ring. */
  10.113 +typedef struct blkif_rsp_ring_struct {
  10.114 +
  10.115 +    int type;       
  10.116 +    BLKIF_RING_IDX rsp_prod;     /* PRIVATE rsp_prod index             */
  10.117 +    BLKIF_RING_IDX req_cons;     /* Request consumer index             */
  10.118 +    blkif_ring_t *ring;          /* Pointer to shared ring struct      */
  10.119 +
  10.120 +} blkif_rsp_ring_t;
  10.121 +
  10.122 +#define BLKIF_RSP_RING_INIT = { BLKIF_RSP_RING_TYPE, 0, 0, 0 }
  10.123 +
  10.124 +#define RING(a) (blkif_generic_ring_t *)(a)
  10.125 +
  10.126 +inline int BLKTAP_RING_FULL(blkif_generic_ring_t *ring);
  10.127 +
  10.128 +
  10.129 +/* -------[ interposition -> character device interface ]------------- */
  10.130 +
  10.131 +/* /dev/xen/blktap resides at device number major=10, minor=200        */ 
  10.132 +#define BLKTAP_MINOR 202
  10.133 +
  10.134 +/* size of the extra VMA area to map in attached pages. */
  10.135 +#define BLKTAP_VMA_PAGES BLKIF_RING_SIZE
  10.136 +
  10.137 +/* blktap IOCTLs:                                                      */
  10.138 +#define BLKTAP_IOCTL_KICK_FE         1
  10.139 +#define BLKTAP_IOCTL_KICK_BE         2
  10.140 +#define BLKTAP_IOCTL_SETMODE         3
  10.141 +
  10.142 +/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE)             */
  10.143 +#define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */
  10.144 +#define BLKTAP_MODE_INTERCEPT_FE     0x00000001
  10.145 +#define BLKTAP_MODE_INTERCEPT_BE     0x00000002
  10.146 +#define BLKTAP_MODE_COPY_FE          0x00000004
  10.147 +#define BLKTAP_MODE_COPY_BE          0x00000008
  10.148 +#define BLKTAP_MODE_COPY_FE_PAGES    0x00000010
  10.149 +#define BLKTAP_MODE_COPY_BE_PAGES    0x00000020
  10.150 +
  10.151 +#define BLKTAP_MODE_INTERPOSE \
  10.152 +           (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
  10.153 +
  10.154 +#define BLKTAP_MODE_COPY_BOTH \
  10.155 +           (BLKTAP_MODE_COPY_FE | BLKTAP_MODE_COPY_BE)
  10.156 +
  10.157 +#define BLKTAP_MODE_COPY_BOTH_PAGES \
  10.158 +           (BLKTAP_MODE_COPY_FE_PAGES | BLKTAP_MODE_COPY_BE_PAGES)
  10.159 +
  10.160 +static inline int BLKTAP_MODE_VALID(unsigned long arg)
  10.161 +{
  10.162 +    return (
  10.163 +        ( arg == BLKTAP_MODE_PASSTHROUGH  ) ||
  10.164 +        ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
  10.165 +        ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
  10.166 +        ( arg == BLKTAP_MODE_INTERPOSE    ) ||
  10.167 +        ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
  10.168 +        ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
  10.169 +        ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
  10.170 +        );
  10.171 +}
  10.172 +
  10.173 +
  10.174 +
  10.175 +/* -------[ Mappings to User VMA ]------------------------------------ */
  10.176 +#define MAX_PENDING_REQS 64
  10.177 +#define BATCH_PER_DOMAIN 16
  10.178 +extern struct vm_area_struct *blktap_vma;
  10.179 +
  10.180 +/* The following are from blkback.c and should probably be put in a
  10.181 + * header and included from there.
  10.182 + * The mmap area described here is where attached data pages eill be mapped.
  10.183 + */
  10.184 + 
  10.185 +extern unsigned long mmap_vstart;
  10.186 +#define MMAP_PAGES_PER_REQUEST \
  10.187 +    (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
  10.188 +#define MMAP_PAGES             \
  10.189 +    (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
  10.190 +#define MMAP_VADDR(_req,_seg)                        \
  10.191 +    (mmap_vstart +                                   \
  10.192 +     ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
  10.193 +     ((_seg) * PAGE_SIZE))
  10.194 +
  10.195 +/* immediately before the mmap area, we have a bunch of pages reserved
  10.196 + * for shared memory rings.
  10.197 + */
  10.198 +
  10.199 +#define RING_PAGES 128 
  10.200 +extern unsigned long rings_vstart;
  10.201 +
  10.202 +/* -------[ Here be globals ]----------------------------------------- */
  10.203 +
  10.204 +extern unsigned long blktap_mode;
  10.205 +
  10.206 +
  10.207 +/* blkif struct, containing ring to FE domain */
  10.208 +extern blkif_t ptfe_blkif; 
  10.209 +
  10.210 +/* Connection to a single backend domain. */
  10.211 +extern blkif_ring_t *blk_ptbe_ring;   /* Ring from the PT to the BE dom    */ 
  10.212 +extern BLKIF_RING_IDX ptbe_resp_cons; /* Response consumer for comms ring. */
  10.213 +extern BLKIF_RING_IDX ptbe_req_prod;  /* Private request producer.         */
  10.214 +
  10.215 +/* Rings up to user space. */ 
  10.216 +extern blkif_req_ring_t fe_ring;// = BLKIF_REQ_RING_INIT;
  10.217 +extern blkif_rsp_ring_t be_ring;// = BLKIF_RSP_RING_INIT;
  10.218 +
  10.219 +/* Event channel to backend domain. */
  10.220 +extern unsigned int blkif_ptbe_evtchn;
  10.221 +
  10.222 +/* User ring status... this will soon vanish into a ring struct. */
  10.223 +extern unsigned long blktap_ring_ok;
  10.224 +
  10.225 +/* -------[ ...and function prototypes. ]----------------------------- */
  10.226 +
  10.227 +/* init function for character device interface.                       */
  10.228 +int blktap_init(void);
  10.229 +
  10.230 +/* interfaces to the char driver, passing messages to and from apps.   */
  10.231 +void blktap_kick_user(void);
  10.232 +int blktap_write_to_ring(blkif_request_t *req);
  10.233 +
  10.234 +
  10.235 +/* user ring access functions: */
  10.236 +int blktap_write_fe_ring(blkif_request_t *req);
  10.237 +int blktap_write_be_ring(blkif_response_t *rsp);
  10.238 +int blktap_read_fe_ring(void);
  10.239 +int blktap_read_be_ring(void);
  10.240 +
  10.241 +/* and the helpers they call: */
  10.242 +inline int write_resp_to_fe_ring(blkif_response_t *rsp);
  10.243 +inline void kick_fe_domain(void);
  10.244 +
  10.245 +inline int write_req_to_be_ring(blkif_request_t *req);
  10.246 +inline void kick_be_domain(void);
  10.247 +
  10.248 +/* Interrupt handlers. */
  10.249 +irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 
  10.250 +                                  struct pt_regs *ptregs);
  10.251 +irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs);
  10.252 +
  10.253 +/* Control message receiver. */
  10.254 +extern void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id);
  10.255 +
  10.256 +#define __BLKINT_H__
  10.257 +#endif
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c	Mon Nov 22 22:41:45 2004 +0000
    11.3 @@ -0,0 +1,358 @@
    11.4 +/******************************************************************************
    11.5 + * blktap_controlmsg.c
    11.6 + * 
    11.7 + * XenLinux virtual block-device tap.
    11.8 + * Control interfaces to the frontend and backend drivers.
    11.9 + * 
   11.10 + * Copyright (c) 2004, Andrew Warfield
   11.11 + *
   11.12 + */
   11.13 + 
   11.14 +#include "blktap.h"
   11.15 +
   11.16 +#define BLKIF_STATE_CLOSED       0
   11.17 +#define BLKIF_STATE_DISCONNECTED 1
   11.18 +#define BLKIF_STATE_CONNECTED    2
   11.19 +
   11.20 +static char *blkif_state_name[] = {
   11.21 +    [BLKIF_STATE_CLOSED]       = "closed",
   11.22 +    [BLKIF_STATE_DISCONNECTED] = "disconnected",
   11.23 +    [BLKIF_STATE_CONNECTED]    = "connected",
   11.24 +};
   11.25 +
   11.26 +static char * blkif_status_name[] = {
   11.27 +    [BLKIF_INTERFACE_STATUS_CLOSED]       = "closed",
   11.28 +    [BLKIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
   11.29 +    [BLKIF_INTERFACE_STATUS_CONNECTED]    = "connected",
   11.30 +    [BLKIF_INTERFACE_STATUS_CHANGED]      = "changed",
   11.31 +};
   11.32 +static unsigned int blkif_pt_state = BLKIF_STATE_CLOSED;
   11.33 +static unsigned blkif_ptbe_irq;
   11.34 +unsigned int blkif_ptbe_evtchn;
   11.35 +
   11.36 +/*-----[ Control Messages to/from Frontend VMs ]--------------------------*/
   11.37 +
   11.38 +
   11.39 +void blkif_ptfe_create(blkif_be_create_t *create)
   11.40 +{
   11.41 +    blkif_t      *blkif;
   11.42 +    domid_t       domid  = create->domid;
   11.43 +    unsigned int  handle = create->blkif_handle;
   11.44 +
   11.45 +
   11.46 +    /* May want to store info on the connecting domain here. */
   11.47 +
   11.48 +    DPRINTK("PT got BE_CREATE\n");
   11.49 +    blkif = &ptfe_blkif; /* for convenience if the hash is readded later. */
   11.50 +
   11.51 +    /* blkif struct init code from blkback.c */
   11.52 +    memset(blkif, 0, sizeof(*blkif));
   11.53 +    blkif->domid  = domid;
   11.54 +    blkif->handle = handle;
   11.55 +    blkif->status = DISCONNECTED;    
   11.56 +    spin_lock_init(&blkif->blk_ring_lock);
   11.57 +    atomic_set(&blkif->refcnt, 0);
   11.58 +
   11.59 +    create->status = BLKIF_BE_STATUS_OKAY;
   11.60 +}
   11.61 +
   11.62 +
   11.63 +void blkif_ptfe_destroy(blkif_be_destroy_t *destroy)
   11.64 +{
   11.65 +    /* Clear anything that we initialized above. */
   11.66 +
   11.67 +    DPRINTK("PT got BE_DESTROY\n");
   11.68 +    destroy->status = BLKIF_BE_STATUS_OKAY;
   11.69 +}
   11.70 +
   11.71 +void blkif_ptfe_connect(blkif_be_connect_t *connect)
   11.72 +{
   11.73 +    domid_t       domid  = connect->domid;
   11.74 +    /*unsigned int  handle = connect->blkif_handle;*/
   11.75 +    unsigned int  evtchn = connect->evtchn;
   11.76 +    unsigned long shmem_frame = connect->shmem_frame;
   11.77 +    struct vm_struct *vma;
   11.78 +    pgprot_t      prot;
   11.79 +    int           error;
   11.80 +    blkif_t      *blkif;
   11.81 +
   11.82 +    DPRINTK("PT got BE_CONNECT\n");
   11.83 +
   11.84 +    blkif = &ptfe_blkif; /* for convenience if the hash is readded later. */
   11.85 +
   11.86 +    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
   11.87 +    {
   11.88 +        connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
   11.89 +        return;
   11.90 +    }
   11.91 +
   11.92 +    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
   11.93 +    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
   11.94 +                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
   11.95 +                                    prot, domid);
   11.96 +    if ( error != 0 )
   11.97 +    {
   11.98 +        WPRINTK("BE_CONNECT: error! (%d)\n", error);
   11.99 +        if ( error == -ENOMEM ) 
  11.100 +            connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
  11.101 +        else if ( error == -EFAULT ) {
  11.102 +            connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
  11.103 +            WPRINTK("BE_CONNECT: MAPPING error!\n");
  11.104 +        }
  11.105 +        else
  11.106 +            connect->status = BLKIF_BE_STATUS_ERROR;
  11.107 +        vfree(vma->addr);
  11.108 +        return;
  11.109 +    }
  11.110 +
  11.111 +    if ( blkif->status != DISCONNECTED )
  11.112 +    {
  11.113 +        connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
  11.114 +        vfree(vma->addr);
  11.115 +        return;
  11.116 +    }
  11.117 +
  11.118 +    blkif->evtchn        = evtchn;
  11.119 +    blkif->irq           = bind_evtchn_to_irq(evtchn);
  11.120 +    blkif->shmem_frame   = shmem_frame;
  11.121 +    blkif->blk_ring_base = (blkif_ring_t *)vma->addr;
  11.122 +    blkif->status        = CONNECTED;
  11.123 +    /*blkif_get(blkif);*/
  11.124 +
  11.125 +    request_irq(blkif->irq, blkif_ptfe_int, 0, "blkif-pt-backend", blkif);
  11.126 +
  11.127 +    connect->status = BLKIF_BE_STATUS_OKAY;
  11.128 +}
  11.129 +
  11.130 +void blkif_ptfe_disconnect(blkif_be_disconnect_t *disconnect)
  11.131 +{
  11.132 +    /*
  11.133 +     * don't actually set the passthrough to disconnected.
  11.134 +     * We just act as a pipe, and defer to the real ends to handle things like
  11.135 +     * recovery.
  11.136 +     */
  11.137 +
  11.138 +    DPRINTK("PT got BE_DISCONNECT\n");
  11.139 +
  11.140 +    disconnect->status = BLKIF_BE_STATUS_OKAY;
  11.141 +    return;
  11.142 +}
  11.143 +
  11.144 +/*-----[ Control Messages to/from Backend VM ]----------------------------*/
  11.145 +
  11.146 +/* Tell the controller to bring up the interface. */
  11.147 +static void blkif_ptbe_send_interface_connect(void)
  11.148 +{
  11.149 +    ctrl_msg_t cmsg = {
  11.150 +        .type    = CMSG_BLKIF_FE,
  11.151 +        .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
  11.152 +        .length  = sizeof(blkif_fe_interface_connect_t),
  11.153 +    };
  11.154 +    blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
  11.155 +    msg->handle      = 0;
  11.156 +    msg->shmem_frame = virt_to_machine(blk_ptbe_ring) >> PAGE_SHIFT;
  11.157 +    
  11.158 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
  11.159 +}
  11.160 +
  11.161 +static void blkif_ptbe_close(void)
  11.162 +{
  11.163 +}
  11.164 +
  11.165 +/* Move from CLOSED to DISCONNECTED state. */
  11.166 +static void blkif_ptbe_disconnect(void)
  11.167 +{
  11.168 +    blk_ptbe_ring = (blkif_ring_t *)__get_free_page(GFP_KERNEL);
  11.169 +    blk_ptbe_ring->req_prod = blk_ptbe_ring->resp_prod 
  11.170 +                            = ptbe_resp_cons = ptbe_req_prod = 0;
  11.171 +    blkif_pt_state  = BLKIF_STATE_DISCONNECTED;
  11.172 +    DPRINTK("Blkif-Passthrough-BE is now DISCONNECTED.\n");
  11.173 +    blkif_ptbe_send_interface_connect();
  11.174 +}
  11.175 +
  11.176 +static void blkif_ptbe_connect(blkif_fe_interface_status_t *status)
  11.177 +{
  11.178 +    int err = 0;
  11.179 +    
  11.180 +    blkif_ptbe_evtchn = status->evtchn;
  11.181 +    blkif_ptbe_irq    = bind_evtchn_to_irq(blkif_ptbe_evtchn);
  11.182 +
  11.183 +    err = request_irq(blkif_ptbe_irq, blkif_ptbe_int, 
  11.184 +                      SA_SAMPLE_RANDOM, "blkif", NULL);
  11.185 +    if ( err ) {
  11.186 +	WPRINTK("blkfront request_irq failed (%d)\n", err);
  11.187 +        return;
  11.188 +    } else {
  11.189 +	/* transtion to connected in case we need to do a 
  11.190 +           a partion probe on a whole disk */
  11.191 +        blkif_pt_state = BLKIF_STATE_CONNECTED;
  11.192 +    }
  11.193 +}
  11.194 +
  11.195 +static void unexpected(blkif_fe_interface_status_t *status)
  11.196 +{
  11.197 +    WPRINTK(" TAP: Unexpected blkif status %s in state %s\n", 
  11.198 +           blkif_status_name[status->status],
  11.199 +           blkif_state_name[blkif_pt_state]);
  11.200 +}
  11.201 +
  11.202 +static void blkif_ptbe_status(
  11.203 +    blkif_fe_interface_status_t *status)
  11.204 +{
  11.205 +    if ( status->handle != 0 )
  11.206 +    {
  11.207 +        DPRINTK("Status change on unsupported blkif %d\n",
  11.208 +               status->handle);
  11.209 +        return;
  11.210 +    }
  11.211 +
  11.212 +    DPRINTK("ptbe_status: got %s\n", blkif_status_name[status->status]);
  11.213 +    
  11.214 +    switch ( status->status )
  11.215 +    {
  11.216 +    case BLKIF_INTERFACE_STATUS_CLOSED:
  11.217 +        switch ( blkif_pt_state )
  11.218 +        {
  11.219 +        case BLKIF_STATE_CLOSED:
  11.220 +            unexpected(status);
  11.221 +            break;
  11.222 +        case BLKIF_STATE_DISCONNECTED:
  11.223 +        case BLKIF_STATE_CONNECTED:
  11.224 +            unexpected(status);
  11.225 +            blkif_ptbe_close();
  11.226 +            break;
  11.227 +        }
  11.228 +        break;
  11.229 +        
  11.230 +    case BLKIF_INTERFACE_STATUS_DISCONNECTED:
  11.231 +        switch ( blkif_pt_state )
  11.232 +        {
  11.233 +        case BLKIF_STATE_CLOSED:
  11.234 +            blkif_ptbe_disconnect();
  11.235 +            break;
  11.236 +        case BLKIF_STATE_DISCONNECTED:
  11.237 +        case BLKIF_STATE_CONNECTED:
  11.238 +            printk(KERN_ALERT "*** add recovery code to the tap driver. ***\n");
  11.239 +            unexpected(status);
  11.240 +            break;
  11.241 +        }
  11.242 +        break;
  11.243 +        
  11.244 +    case BLKIF_INTERFACE_STATUS_CONNECTED:
  11.245 +        switch ( blkif_pt_state )
  11.246 +        {
  11.247 +        case BLKIF_STATE_CLOSED:
  11.248 +            unexpected(status);
  11.249 +            blkif_ptbe_disconnect();
  11.250 +            blkif_ptbe_connect(status);
  11.251 +            break;
  11.252 +        case BLKIF_STATE_DISCONNECTED:
  11.253 +            blkif_ptbe_connect(status);
  11.254 +            break;
  11.255 +        case BLKIF_STATE_CONNECTED:
  11.256 +            unexpected(status);
  11.257 +            blkif_ptbe_connect(status);
  11.258 +            break;
  11.259 +        }
  11.260 +        break;
  11.261 +
  11.262 +   case BLKIF_INTERFACE_STATUS_CHANGED:
  11.263 +        switch ( blkif_pt_state )
  11.264 +        {
  11.265 +        case BLKIF_STATE_CLOSED:
  11.266 +        case BLKIF_STATE_DISCONNECTED:
  11.267 +            unexpected(status);
  11.268 +            break;
  11.269 +        case BLKIF_STATE_CONNECTED:
  11.270 +            /* vbd_update(); */
  11.271 +            /* tap doesn't really get state changes... */
  11.272 +            unexpected(status);
  11.273 +            break;
  11.274 +        }
  11.275 +       break;
  11.276 +       
  11.277 +    default:
  11.278 +        DPRINTK("Status change to unknown value %d\n", status->status);
  11.279 +        break;
  11.280 +    }
  11.281 +}
  11.282 +
  11.283 +/*-----[ All control messages enter here: ]-------------------------------*/
  11.284 +
  11.285 +void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
  11.286 +{
  11.287 +    switch ( msg->type )
  11.288 +    {
  11.289 +    case CMSG_BLKIF_FE:
  11.290 +
  11.291 +        switch ( msg->subtype )
  11.292 +        {
  11.293 +        case CMSG_BLKIF_FE_INTERFACE_STATUS:
  11.294 +            if ( msg->length != sizeof(blkif_fe_interface_status_t) )
  11.295 +                goto parse_error;
  11.296 +            blkif_ptbe_status((blkif_fe_interface_status_t *) &msg->msg[0]);
  11.297 +            break;        
  11.298 +
  11.299 +        default:
  11.300 +            goto parse_error;
  11.301 +        }
  11.302 +
  11.303 +    case CMSG_BLKIF_BE:
  11.304 +        
  11.305 +        switch ( msg->subtype )
  11.306 +        {
  11.307 +        case CMSG_BLKIF_BE_CREATE:
  11.308 +            if ( msg->length != sizeof(blkif_be_create_t) )
  11.309 +                goto parse_error;
  11.310 +            blkif_ptfe_create((blkif_be_create_t *)&msg->msg[0]);
  11.311 +            break; 
  11.312 +        case CMSG_BLKIF_BE_DESTROY:
  11.313 +            if ( msg->length != sizeof(blkif_be_destroy_t) )
  11.314 +                goto parse_error;
  11.315 +            blkif_ptfe_destroy((blkif_be_destroy_t *)&msg->msg[0]);
  11.316 +            break;        
  11.317 +        case CMSG_BLKIF_BE_CONNECT:
  11.318 +            if ( msg->length != sizeof(blkif_be_connect_t) )
  11.319 +                goto parse_error;
  11.320 +            blkif_ptfe_connect((blkif_be_connect_t *)&msg->msg[0]);
  11.321 +            break;        
  11.322 +        case CMSG_BLKIF_BE_DISCONNECT:
  11.323 +            if ( msg->length != sizeof(blkif_be_disconnect_t) )
  11.324 +                goto parse_error;
  11.325 +            blkif_ptfe_disconnect((blkif_be_disconnect_t *)&msg->msg[0]);
  11.326 +            break;        
  11.327 +
  11.328 +        /* We just ignore anything to do with vbds for now. */
  11.329 +        
  11.330 +        case CMSG_BLKIF_BE_VBD_CREATE:
  11.331 +            DPRINTK("PT got VBD_CREATE\n");
  11.332 +            ((blkif_be_vbd_create_t *)&msg->msg[0])->status 
  11.333 +                = BLKIF_BE_STATUS_OKAY;
  11.334 +            break;
  11.335 +        case CMSG_BLKIF_BE_VBD_DESTROY:
  11.336 +            DPRINTK("PT got VBD_DESTROY\n");
  11.337 +            ((blkif_be_vbd_destroy_t *)&msg->msg[0])->status
  11.338 +                = BLKIF_BE_STATUS_OKAY;
  11.339 +            break;
  11.340 +        case CMSG_BLKIF_BE_VBD_GROW:
  11.341 +            DPRINTK("PT got VBD_GROW\n");
  11.342 +            ((blkif_be_vbd_grow_t *)&msg->msg[0])->status
  11.343 +                = BLKIF_BE_STATUS_OKAY;
  11.344 +            break;
  11.345 +        case CMSG_BLKIF_BE_VBD_SHRINK:
  11.346 +            DPRINTK("PT got VBD_SHRINK\n");
  11.347 +            ((blkif_be_vbd_shrink_t *)&msg->msg[0])->status
  11.348 +                = BLKIF_BE_STATUS_OKAY;
  11.349 +            break;
  11.350 +        default:
  11.351 +            goto parse_error;
  11.352 +        }
  11.353 +    }
  11.354 +
  11.355 +    ctrl_if_send_response(msg);
  11.356 +    return;
  11.357 +
  11.358 + parse_error:
  11.359 +    msg->length = 0;
  11.360 +    ctrl_if_send_response(msg);
  11.361 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c	Mon Nov 22 22:41:45 2004 +0000
    12.3 @@ -0,0 +1,517 @@
    12.4 +/******************************************************************************
    12.5 + * blktap_datapath.c
    12.6 + * 
    12.7 + * XenLinux virtual block-device tap.
    12.8 + * Block request routing data path.
    12.9 + * 
   12.10 + * Copyright (c) 2004, Andrew Warfield
   12.11 + *
   12.12 + */
   12.13 + 
   12.14 +#include "blktap.h"
   12.15 +
   12.16 +/*-----[ The data paths ]-------------------------------------------------*/
   12.17 + 
   12.18 +/* Connections to the frontend domains.*/
   12.19 +blkif_t   ptfe_blkif; 
   12.20 + 
   12.21 +/* Connection to a single backend domain. */
   12.22 +blkif_ring_t *blk_ptbe_ring;   /* Ring from the PT to the BE dom    */ 
   12.23 +BLKIF_RING_IDX ptbe_resp_cons; /* Response consumer for comms ring. */
   12.24 +BLKIF_RING_IDX ptbe_req_prod;  /* Private request producer.         */
   12.25 +
   12.26 +/* Rings up to user space. */ 
   12.27 +blkif_req_ring_t fe_ring;// = BLKIF_REQ_RING_INIT;
   12.28 +blkif_rsp_ring_t be_ring;// = BLKIF_RSP_RING_INIT;
   12.29 +
   12.30 +/*-----[ Ring helpers ]---------------------------------------------------*/
   12.31 +
   12.32 +inline int BLKTAP_RING_FULL(blkif_generic_ring_t *ring)
   12.33 +{
   12.34 +    if (ring->type == BLKIF_REQ_RING_TYPE) {
   12.35 +        blkif_req_ring_t *r = (blkif_req_ring_t *)ring;
   12.36 +        return ( ( r->req_prod - r->rsp_cons ) == BLKIF_RING_SIZE );
   12.37 +    }
   12.38 +    
   12.39 +    /* for now assume that there is always room in the response path. */
   12.40 +    return 0;
   12.41 +}
   12.42 +
   12.43 +/*-----[ Tracking active requests ]---------------------------------------*/
   12.44 +
   12.45 +/* this must be the same as MAX_PENDING_REQS in blkback.c */
   12.46 +#define MAX_ACTIVE_REQS 64
   12.47 +
   12.48 +active_req_t  active_reqs[MAX_ACTIVE_REQS];
   12.49 +unsigned char active_req_ring[MAX_ACTIVE_REQS];
   12.50 +spinlock_t    active_req_lock = SPIN_LOCK_UNLOCKED;
   12.51 +typedef unsigned int ACTIVE_RING_IDX;
   12.52 +ACTIVE_RING_IDX active_prod, active_cons;
   12.53 +#define MASK_ACTIVE_IDX(_i) ((_i)&(MAX_ACTIVE_REQS-1))
   12.54 +#define ACTIVE_IDX(_ar) (_ar - active_reqs)
   12.55 +
   12.56 +inline active_req_t *get_active_req(void) 
   12.57 +{
   12.58 +    ASSERT(active_cons != active_prod);    
   12.59 +    return &active_reqs[MASK_ACTIVE_IDX(active_cons++)];
   12.60 +}
   12.61 +
   12.62 +inline void free_active_req(active_req_t *ar) 
   12.63 +{
   12.64 +    unsigned long flags;
   12.65 +        
   12.66 +    spin_lock_irqsave(&active_req_lock, flags);
   12.67 +    active_req_ring[MASK_ACTIVE_IDX(active_prod++)] = ACTIVE_IDX(ar);
   12.68 +    spin_unlock_irqrestore(&active_req_lock, flags);
   12.69 +}
   12.70 +
   12.71 +inline void active_reqs_init(void)
   12.72 +{
   12.73 +    ACTIVE_RING_IDX i;
   12.74 +    
   12.75 +    active_cons = 0;
   12.76 +    active_prod = MAX_ACTIVE_REQS;
   12.77 +    memset(active_reqs, 0, sizeof(active_reqs));
   12.78 +    for ( i = 0; i < MAX_ACTIVE_REQS; i++ )
   12.79 +        active_req_ring[i] = i;
   12.80 +}
   12.81 +
   12.82 +/*-----[ Data to/from Frontend (client) VMs ]-----------------------------*/
   12.83 +
   12.84 +irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)
   12.85 +{
   12.86 +    /* we have pending messages from the real frontend. */
   12.87 +
   12.88 +    blkif_request_t *req_s, *req_d;
   12.89 +    BLKIF_RING_IDX fe_rp;
   12.90 +    unsigned long flags;
   12.91 +    int notify;
   12.92 +    unsigned long i;
   12.93 +    active_req_t *ar;
   12.94 +    
   12.95 +    DPRINTK("PT got FE interrupt.\n");
   12.96 +    
   12.97 +    /* lock both rings */
   12.98 +    spin_lock_irqsave(&blkif_io_lock, flags);
   12.99 +
  12.100 +    /* While there are REQUESTS on FERing: */
  12.101 +    fe_rp = ptfe_blkif.blk_ring_base->req_prod;
  12.102 +    rmb();
  12.103 +    notify = (ptfe_blkif.blk_req_cons != fe_rp);
  12.104 +
  12.105 +    for (i = ptfe_blkif.blk_req_cons; i != fe_rp; i++) {
  12.106 +
  12.107 +        /* Get the next request */
  12.108 +        req_s = &ptfe_blkif.blk_ring_base->ring[MASK_BLKIF_IDX(i)].req;
  12.109 +        
  12.110 +        /* This is a new request:  
  12.111 +         * Assign an active request record, and remap the id. 
  12.112 +         */
  12.113 +        ar = get_active_req();
  12.114 +        ar->id = req_s->id;
  12.115 +        req_s->id = ACTIVE_IDX(ar);
  12.116 +        DPRINTK("%3lu < %3lu\n", req_s->id, ar->id);
  12.117 +
  12.118 +        /* FE -> BE interposition point is here. */
  12.119 +        
  12.120 +        /* ------------------------------------------------------------- */
  12.121 +        /* BLKIF_OP_PROBE_HACK:                                          */
  12.122 +        /* Until we have grant tables, we need to allow the backent to   */
  12.123 +        /* map pages that are either from this domain, or more commonly  */
  12.124 +        /* from the real front end.  We achieve this in a terrible way,  */
  12.125 +        /* by passing the front end's domid allong with PROBE messages   */
  12.126 +        /* Once grant tables appear, this should all go away.            */
  12.127 +
  12.128 +        if (req_s->operation == BLKIF_OP_PROBE) {
  12.129 +            DPRINTK("Adding FE domid to PROBE request.\n");
  12.130 +            (domid_t)(req_s->frame_and_sects[1]) = ptfe_blkif.domid;
  12.131 +        }
  12.132 +
  12.133 +        /* ------------------------------------------------------------- */
  12.134 +
  12.135 +        /* If we are in MODE_INTERCEPT_FE or MODE_COPY_FE: */
  12.136 +        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  12.137 +             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
  12.138 +            
  12.139 +            /* Copy the response message to UFERing */
  12.140 +            /* In MODE_INTERCEPT_FE, map attached pages into the app vma */
  12.141 +            /* In MODE_COPY_FE_PAGES, copy attached pages into the app vma */
  12.142 +
  12.143 +            /* XXX: mapping/copying of attached pages is still not done! */
  12.144 +
  12.145 +            DPRINTK("req->UFERing\n"); 
  12.146 +            blktap_write_fe_ring(req_s);
  12.147 +
  12.148 +
  12.149 +        }
  12.150 +
  12.151 +        /* If we are not in MODE_INTERCEPT_FE or MODE_INTERCEPT_BE: */
  12.152 +        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  12.153 +               (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) {
  12.154 +            
  12.155 +            /* be included to prevent noise from the fe when its off */
  12.156 +            /* copy the request message to the BERing */
  12.157 +
  12.158 +            DPRINTK("blktap: FERing[%u] -> BERing[%u]\n", 
  12.159 +                    (unsigned)MASK_BLKIF_IDX(i), 
  12.160 +                    (unsigned)MASK_BLKIF_IDX(ptbe_req_prod));
  12.161 +
  12.162 +            req_d = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(ptbe_req_prod)].req;
  12.163 +            
  12.164 +            memcpy(req_d, req_s, sizeof(blkif_request_t));
  12.165 +
  12.166 +            ptbe_req_prod++;
  12.167 +        }
  12.168 +    }
  12.169 +
  12.170 +    ptfe_blkif.blk_req_cons = i;
  12.171 +
  12.172 +    /* If we have forwarded any responses, notify the appropriate ends. */
  12.173 +    if (notify) {
  12.174 +
  12.175 +        /* we have sent stuff to the be, notify it. */
  12.176 +        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  12.177 +               (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) {
  12.178 +            wmb();
  12.179 +            blk_ptbe_ring->req_prod = ptbe_req_prod;
  12.180 +
  12.181 +            notify_via_evtchn(blkif_ptbe_evtchn);
  12.182 +            DPRINTK(" -- and notified.\n");
  12.183 +        }
  12.184 +
  12.185 +        /* we sent stuff to the app, notify it. */
  12.186 +        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  12.187 +             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
  12.188 +
  12.189 +            blktap_kick_user();
  12.190 +        }
  12.191 +    }
  12.192 +
  12.193 +    /* unlock rings */
  12.194 +    spin_unlock_irqrestore(&blkif_io_lock, flags);
  12.195 +
  12.196 +    return IRQ_HANDLED;
  12.197 +}
  12.198 +
  12.199 +inline int write_req_to_be_ring(blkif_request_t *req)
  12.200 +{
  12.201 +    blkif_request_t *req_d;
  12.202 +
  12.203 +    req_d = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(ptbe_req_prod)].req;
  12.204 +    memcpy(req_d, req, sizeof(blkif_request_t));
  12.205 +    ptbe_req_prod++;
  12.206 +
  12.207 +    return 0;
  12.208 +}
  12.209 +
  12.210 +inline void kick_be_domain(void) {
  12.211 +    wmb();
  12.212 +    blk_ptbe_ring->req_prod = ptbe_req_prod;
  12.213 +    notify_via_evtchn(blkif_ptbe_evtchn);
  12.214 +}
  12.215 +
  12.216 +/*-----[ Data to/from Backend (server) VM ]------------------------------*/
  12.217 +
  12.218 +
  12.219 +irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 
  12.220 +                                  struct pt_regs *ptregs)
  12.221 +{
  12.222 +    blkif_response_t  *resp_s, *resp_d;
  12.223 +    BLKIF_RING_IDX be_rp;
  12.224 +    unsigned long flags;
  12.225 +    int notify;
  12.226 +    unsigned long i;
  12.227 +    active_req_t *ar;
  12.228 +
  12.229 +    DPRINTK("PT got BE interrupt.\n");
  12.230 +
  12.231 +    /* lock both rings */
  12.232 +    spin_lock_irqsave(&blkif_io_lock, flags);
  12.233 +    
  12.234 +    /* While there are RESPONSES on BERing: */
  12.235 +    be_rp = blk_ptbe_ring->resp_prod;
  12.236 +    rmb();
  12.237 +    notify = (ptbe_resp_cons != be_rp);
  12.238 +    
  12.239 +    for ( i = ptbe_resp_cons; i != be_rp; i++ )
  12.240 +    {
  12.241 +        /* BE -> FE interposition point is here. */
  12.242 +        
  12.243 +        /* Get the next response */
  12.244 +        resp_s = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(i)].resp;
  12.245 +    
  12.246 +       
  12.247 +        /* If we are in MODE_INTERCEPT_BE or MODE_COPY_BE: */
  12.248 +        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  12.249 +             (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
  12.250 +
  12.251 +            /* Copy the response message to UBERing */
  12.252 +            /* In MODE_INTERCEPT_BE, map attached pages into the app vma */
  12.253 +            /* In MODE_COPY_BE_PAGES, copy attached pages into the app vma */
  12.254 +
  12.255 +            /* XXX: copy/map the attached page! */
  12.256 +
  12.257 +            DPRINTK("rsp->UBERing\n"); 
  12.258 +            blktap_write_be_ring(resp_s);
  12.259 +
  12.260 +        }
  12.261 +       
  12.262 +        /* If we are NOT in MODE_INTERCEPT_BE or MODE_INTERCEPT_FE: */
  12.263 +        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  12.264 +               (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) {
  12.265 +            
  12.266 +            /* (fe included to prevent random interference from the BE) */
  12.267 +            /* Copy the response message to FERing */
  12.268 +         
  12.269 +            DPRINTK("blktap: BERing[%u] -> FERing[%u]\n", 
  12.270 +                    (unsigned) MASK_BLKIF_IDX(i), 
  12.271 +                    (unsigned) MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod));
  12.272 +
  12.273 +            /* remap id, and free the active req. blkif lookup goes here too.*/
  12.274 +            ar = &active_reqs[resp_s->id];
  12.275 +            DPRINTK("%3lu > %3lu\n", resp_s->id, ar->id);
  12.276 +            resp_s->id = ar->id;
  12.277 +            free_active_req(ar);
  12.278 +           
  12.279 +            resp_d = &ptfe_blkif.blk_ring_base->ring[
  12.280 +                MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)].resp;
  12.281 +
  12.282 +            memcpy(resp_d, resp_s, sizeof(blkif_response_t));
  12.283 +            
  12.284 +            ptfe_blkif.blk_resp_prod++;
  12.285 +
  12.286 +        }
  12.287 +    }
  12.288 +
  12.289 +    ptbe_resp_cons = i;
  12.290 +    
  12.291 +    /* If we have forwarded any responses, notify the apropriate domains. */
  12.292 +    if (notify) {
  12.293 +
  12.294 +        /* we have sent stuff to the fe.  notify it. */
  12.295 +        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  12.296 +               (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) {
  12.297 +            wmb();
  12.298 +            ptfe_blkif.blk_ring_base->resp_prod = ptfe_blkif.blk_resp_prod;
  12.299 +        
  12.300 +            notify_via_evtchn(ptfe_blkif.evtchn);
  12.301 +            DPRINTK(" -- and notified.\n");
  12.302 +        }
  12.303 +
  12.304 +        /* we sent stuff to the app, notify it. */
  12.305 +        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  12.306 +             (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
  12.307 +
  12.308 +            blktap_kick_user();
  12.309 +        }
  12.310 +    }
  12.311 +
  12.312 +    spin_unlock_irqrestore(&blkif_io_lock, flags);
  12.313 +    return IRQ_HANDLED;
  12.314 +}
  12.315 +
  12.316 +inline int write_resp_to_fe_ring(blkif_response_t *rsp)
  12.317 +{
  12.318 +    blkif_response_t *resp_d;
  12.319 +    active_req_t *ar;
  12.320 +    
  12.321 +    /* remap id, and free the active req. blkif lookup goes here too.*/
  12.322 +    ar = &active_reqs[rsp->id];
  12.323 +    DPRINTK("%3lu > %3lu\n", rsp->id, ar->id);
  12.324 +    rsp->id = ar->id;
  12.325 +    free_active_req(ar);
  12.326 +            
  12.327 +    resp_d = &ptfe_blkif.blk_ring_base->ring[
  12.328 +        MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)].resp;
  12.329 +
  12.330 +    memcpy(resp_d, rsp, sizeof(blkif_response_t));
  12.331 +    ptfe_blkif.blk_resp_prod++;
  12.332 +
  12.333 +    return 0;
  12.334 +}
  12.335 +
  12.336 +inline void kick_fe_domain(void) {
  12.337 +    wmb();
  12.338 +    ptfe_blkif.blk_ring_base->resp_prod = ptfe_blkif.blk_resp_prod;
  12.339 +    notify_via_evtchn(ptfe_blkif.evtchn);
  12.340 +    
  12.341 +}
  12.342 +
  12.343 +static inline void flush_requests(void)
  12.344 +{
  12.345 +    wmb(); /* Ensure that the frontend can see the requests. */
  12.346 +    blk_ptbe_ring->req_prod = ptbe_req_prod;
  12.347 +    notify_via_evtchn(blkif_ptbe_evtchn);
  12.348 +}
  12.349 +
  12.350 +/*-----[ Data to/from user space ]----------------------------------------*/
  12.351 +
  12.352 +
  12.353 +int blktap_write_fe_ring(blkif_request_t *req)
  12.354 +{
  12.355 +    blkif_request_t *target;
  12.356 +    int error, i;
  12.357 +
  12.358 +    /*
  12.359 +     * This is called to pass a request from the real frontend domain's
  12.360 +     * blkif ring to the character device.
  12.361 +     */
  12.362 +
  12.363 +    if ( ! blktap_ring_ok ) {
  12.364 +        DPRINTK("blktap: fe_ring not ready for a request!\n");
  12.365 +        return 0;
  12.366 +    }
  12.367 +
  12.368 +    if ( BLKTAP_RING_FULL(RING(&fe_ring)) ) {
  12.369 +        DPRINTK("blktap: fe_ring is full, can't add.\n");
  12.370 +        return 0;
  12.371 +    }
  12.372 +
  12.373 +    target = &fe_ring.ring->ring[MASK_BLKIF_IDX(fe_ring.req_prod)].req;
  12.374 +    memcpy(target, req, sizeof(*req));
  12.375 +
  12.376 +/* maybe move this stuff out into a seperate func ------------------- */
  12.377 +
  12.378 +    /*
  12.379 +     * For now, map attached page into a fixed position into the vma.
  12.380 +     * XXX: make this map to a free page.
  12.381 +     */
  12.382 +
  12.383 +    /* Attempt to map the foreign pages directly in to the application */
  12.384 +    for (i=0; i<target->nr_segments; i++) {
  12.385 +
  12.386 +        /* get an unused virtual address from the char device */
  12.387 +        /* store the old page address */
  12.388 +        /* replace the address with the virtual address */
  12.389 +
  12.390 +        /* blktap_vma->vm_start+((2+i)*PAGE_SIZE) */
  12.391 +
  12.392 +        error = direct_remap_area_pages(blktap_vma->vm_mm, 
  12.393 +                                        MMAP_VADDR(req->id, i), 
  12.394 +                                        target->frame_and_sects[0] & PAGE_MASK,
  12.395 +                                        PAGE_SIZE,
  12.396 +                                        blktap_vma->vm_page_prot,
  12.397 +                                        ptfe_blkif.domid);
  12.398 +        if ( error != 0 ) {
  12.399 +            printk(KERN_INFO "remapping attached page failed! (%d)\n", error);
  12.400 +            return 0;
  12.401 +        }
  12.402 +    }
  12.403 +    /* fix the address of the attached page in the message. */
  12.404 +    /* TODO:      preserve the segment number stuff here... */
  12.405 +    /* target->frame_and_sects[0] = blktap_vma->vm_start + PAGE_SIZE;*/
  12.406 +/* ------------------------------------------------------------------ */
  12.407 +
  12.408 +    
  12.409 +    fe_ring.req_prod++;
  12.410 +
  12.411 +    return 0;
  12.412 +}
  12.413 +
  12.414 +int blktap_write_be_ring(blkif_response_t *rsp)
  12.415 +{
  12.416 +    blkif_response_t *target;
  12.417 +
  12.418 +    /*
  12.419 +     * This is called to pass a request from the real backend domain's
  12.420 +     * blkif ring to the character device.
  12.421 +     */
  12.422 +
  12.423 +    if ( ! blktap_ring_ok ) {
  12.424 +        DPRINTK("blktap: be_ring not ready for a request!\n");
  12.425 +        return 0;
  12.426 +    }
  12.427 +
  12.428 +    if ( BLKTAP_RING_FULL(RING(&be_ring)) ) {
  12.429 +        DPRINTK("blktap: be_ring is full, can't add.\n");
  12.430 +        return 0;
  12.431 +    }
  12.432 +
  12.433 +    target = &be_ring.ring->ring[MASK_BLKIF_IDX(be_ring.rsp_prod)].resp;
  12.434 +    memcpy(target, rsp, sizeof(*rsp));
  12.435 +
  12.436 +
  12.437 +    /* XXX: map attached pages and fix-up addresses in the copied address. */
  12.438 +
  12.439 +    be_ring.rsp_prod++;
  12.440 +
  12.441 +    return 0;
  12.442 +}
  12.443 +
  12.444 +int blktap_read_fe_ring(void)
  12.445 +{
  12.446 +    /* This is called to read responses from the UFE ring. */
  12.447 +
  12.448 +    BLKIF_RING_IDX fe_rp;
  12.449 +    unsigned long i;
  12.450 +    int notify;
  12.451 +
  12.452 +    DPRINTK("blktap_read_fe_ring()\n");
  12.453 +
  12.454 +    fe_rp = fe_ring.ring->resp_prod;
  12.455 +    rmb();
  12.456 +    notify = (fe_rp != fe_ring.rsp_cons);
  12.457 +
  12.458 +    /* if we are forwarding from UFERring to FERing */
  12.459 +    if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
  12.460 +
  12.461 +        /* for each outstanding message on the UFEring  */
  12.462 +        for ( i = fe_ring.rsp_cons; i != fe_rp; i++ ) {
  12.463 +
  12.464 +            /* XXX: remap pages on that message as necessary */
  12.465 +            /* copy the message to the UBEring */
  12.466 +
  12.467 +            DPRINTK("resp->fe_ring\n");
  12.468 +            write_resp_to_fe_ring(&fe_ring.ring->ring[MASK_BLKIF_IDX(i)].resp);
  12.469 +        }
  12.470 +    
  12.471 +        fe_ring.rsp_cons = fe_rp;
  12.472 +
  12.473 +        /* notify the fe if necessary */
  12.474 +        if ( notify ) {
  12.475 +            DPRINTK("kick_fe_domain()\n");
  12.476 +            kick_fe_domain();
  12.477 +        }
  12.478 +    }
  12.479 +
  12.480 +    return 0;
  12.481 +}
  12.482 +
  12.483 +int blktap_read_be_ring(void)
  12.484 +{
  12.485 +    /* This is called to read responses from the UBE ring. */
  12.486 +
  12.487 +    BLKIF_RING_IDX be_rp;
  12.488 +    unsigned long i;
  12.489 +    int notify;
  12.490 +
  12.491 +    DPRINTK("blktap_read_be_ring()\n");
  12.492 +
  12.493 +    be_rp = be_ring.ring->req_prod;
  12.494 +    rmb();
  12.495 +    notify = (be_rp != be_ring.req_cons);
  12.496 +
  12.497 +    /* if we are forwarding from UFERring to FERing */
  12.498 +    if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) {
  12.499 +
  12.500 +        /* for each outstanding message on the UFEring  */
  12.501 +        for ( i = be_ring.req_cons; i != be_rp; i++ ) {
  12.502 +
  12.503 +            /* XXX: remap pages on that message as necessary */
  12.504 +            /* copy the message to the UBEring */
  12.505 +
  12.506 +            DPRINTK("req->be_ring\n");
  12.507 +            write_req_to_be_ring(&be_ring.ring->ring[MASK_BLKIF_IDX(i)].req);
  12.508 +        }
  12.509 +    
  12.510 +        be_ring.req_cons = be_rp;
  12.511 +
  12.512 +        /* notify the fe if necessary */
  12.513 +        if ( notify ) {
  12.514 +            DPRINTK("kick_be_domain()\n");
  12.515 +            kick_be_domain();
  12.516 +        }
  12.517 +    }
  12.518 +
  12.519 +    return 0;
  12.520 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Mon Nov 22 22:41:45 2004 +0000
    13.3 @@ -0,0 +1,243 @@
    13.4 +/******************************************************************************
    13.5 + * blktap_userdev.c
    13.6 + * 
    13.7 + * XenLinux virtual block-device tap.
    13.8 + * Control interface between the driver and a character device.
    13.9 + * 
   13.10 + * Copyright (c) 2004, Andrew Warfield
   13.11 + *
   13.12 + */
   13.13 +
   13.14 +#include <linux/config.h>
   13.15 +#include <linux/module.h>
   13.16 +#include <linux/kernel.h>
   13.17 +#include <linux/fs.h>
   13.18 +#include <linux/mm.h>
   13.19 +#include <linux/miscdevice.h>
   13.20 +#include <linux/errno.h>
   13.21 +#include <linux/major.h>
   13.22 +#include <linux/gfp.h>
   13.23 +#include <linux/poll.h>
   13.24 +#include <asm/pgalloc.h>
   13.25 +
   13.26 +#include "blktap.h"
   13.27 +
   13.28 +
   13.29 +unsigned long blktap_mode = BLKTAP_MODE_PASSTHROUGH;
   13.30 +
   13.31 +/* Only one process may open /dev/xen/blktap at any time. */
   13.32 +static unsigned long blktap_dev_inuse;
   13.33 +unsigned long blktap_ring_ok; /* make this ring->state */
   13.34 +
   13.35 +/* for poll: */
   13.36 +static wait_queue_head_t blktap_wait;
   13.37 +
   13.38 +/* Where things are inside the device mapping. */
   13.39 +struct vm_area_struct *blktap_vma;
   13.40 +unsigned long mmap_vstart;
   13.41 +unsigned long rings_vstart;
   13.42 +
   13.43 +/* -------[ blktap vm ops ]------------------------------------------- */
   13.44 +
   13.45 +static struct page *blktap_nopage(struct vm_area_struct *vma,
   13.46 +                                             unsigned long address,
   13.47 +                                             int *type)
   13.48 +{
   13.49 +    /*
   13.50 +     * if the page has not been mapped in by the driver then generate
   13.51 +     * a SIGBUS to the domain.
   13.52 +     */
   13.53 +
   13.54 +    force_sig(SIGBUS, current);
   13.55 +
   13.56 +    return 0;
   13.57 +}
   13.58 +
   13.59 +struct vm_operations_struct blktap_vm_ops = {
   13.60 +    nopage:   blktap_nopage,
   13.61 +};
   13.62 +
   13.63 +/* -------[ blktap file ops ]----------------------------------------- */
   13.64 +
   13.65 +static int blktap_open(struct inode *inode, struct file *filp)
   13.66 +{
   13.67 +    if ( test_and_set_bit(0, &blktap_dev_inuse) )
   13.68 +        return -EBUSY;
   13.69 +
   13.70 +    printk(KERN_ALERT "blktap open.\n");
   13.71 +
   13.72 +    /* Allocate the fe ring. */
   13.73 +    fe_ring.ring = (blkif_ring_t *)get_zeroed_page(GFP_KERNEL);
   13.74 +    if (fe_ring.ring == NULL)
   13.75 +        goto fail_nomem;
   13.76 +
   13.77 +    SetPageReserved(virt_to_page(fe_ring.ring));
   13.78 +    
   13.79 +    fe_ring.ring->req_prod = fe_ring.ring->resp_prod
   13.80 +                           = fe_ring.req_prod
   13.81 +                           = fe_ring.rsp_cons
   13.82 +                           = 0;
   13.83 +
   13.84 +    /* Allocate the be ring. */
   13.85 +    be_ring.ring = (blkif_ring_t *)get_zeroed_page(GFP_KERNEL);
   13.86 +    if (be_ring.ring == NULL)
   13.87 +        goto fail_free_fe;
   13.88 +
   13.89 +    SetPageReserved(virt_to_page(be_ring.ring));
   13.90 +    
   13.91 +    be_ring.ring->req_prod = be_ring.ring->resp_prod
   13.92 +                           = be_ring.rsp_prod
   13.93 +                           = be_ring.req_cons
   13.94 +                           = 0;
   13.95 +
   13.96 +    DPRINTK(KERN_ALERT "blktap open.\n");
   13.97 +
   13.98 +    return 0;
   13.99 +
  13.100 + fail_free_fe:
  13.101 +    free_page( (unsigned long) fe_ring.ring);
  13.102 +
  13.103 + fail_nomem:
  13.104 +    return -ENOMEM;
  13.105 +}
  13.106 +
  13.107 +static int blktap_release(struct inode *inode, struct file *filp)
  13.108 +{
  13.109 +    blktap_dev_inuse = 0;
  13.110 +    blktap_ring_ok = 0;
  13.111 +
  13.112 +    printk(KERN_ALERT "blktap closed.\n");
  13.113 +
  13.114 +    /* Free the ring page. */
  13.115 +    ClearPageReserved(virt_to_page(fe_ring.ring));
  13.116 +    free_page((unsigned long) fe_ring.ring);
  13.117 +
  13.118 +    ClearPageReserved(virt_to_page(be_ring.ring));
  13.119 +    free_page((unsigned long) be_ring.ring);
  13.120 +    
  13.121 +    return 0;
  13.122 +}
  13.123 +
  13.124 +static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
  13.125 +{
  13.126 +    int size;
  13.127 +
  13.128 +    printk(KERN_ALERT "blktap mmap (%lx, %lx)\n",
  13.129 +           vma->vm_start, vma->vm_end);
  13.130 +
  13.131 +    vma->vm_ops = &blktap_vm_ops;
  13.132 +
  13.133 +    size = vma->vm_end - vma->vm_start;
  13.134 +    if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
  13.135 +        printk(KERN_INFO 
  13.136 +               "blktap: you _must_ map exactly %d pages!\n",
  13.137 +               MMAP_PAGES + RING_PAGES);
  13.138 +        return -EAGAIN;
  13.139 +    }
  13.140 +
  13.141 +    size >>= PAGE_SHIFT;
  13.142 +    printk(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
  13.143 +    
  13.144 +    rings_vstart = vma->vm_start;
  13.145 +    mmap_vstart  = rings_vstart + (RING_PAGES << PAGE_SHIFT);
  13.146 +    
  13.147 +    /* Map the ring pages to the start of the region and reserve it. */
  13.148 +
  13.149 +    /* not sure if I really need to do this... */
  13.150 +    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  13.151 +
  13.152 +    DPRINTK("Mapping be_ring page %lx.\n", __pa(be_ring.ring));
  13.153 +    if (remap_page_range(vma, vma->vm_start, __pa(be_ring.ring), PAGE_SIZE, 
  13.154 +                         vma->vm_page_prot)) {
  13.155 +        printk(KERN_ERR "be_ring: remap_page_range failure!\n");
  13.156 +    }
  13.157 +
  13.158 +    DPRINTK("Mapping fe_ring page %lx.\n", __pa(fe_ring.ring));
  13.159 +    if (remap_page_range(vma, vma->vm_start + PAGE_SIZE, __pa(fe_ring.ring), 
  13.160 +                         PAGE_SIZE, vma->vm_page_prot)) {
  13.161 +        printk(KERN_ERR "fe_ring: remap_page_range failure!\n");
  13.162 +    }
  13.163 +
  13.164 +    blktap_vma = vma;
  13.165 +    blktap_ring_ok = 1;
  13.166 +
  13.167 +    return 0;
  13.168 +}
  13.169 +
  13.170 +static int blktap_ioctl(struct inode *inode, struct file *filp,
  13.171 +                        unsigned int cmd, unsigned long arg)
  13.172 +{
  13.173 +    switch(cmd) {
  13.174 +    case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
  13.175 +        return blktap_read_fe_ring();
  13.176 +
  13.177 +    case BLKTAP_IOCTL_KICK_BE: /* There are be messages to process. */
  13.178 +        return blktap_read_be_ring();
  13.179 +
  13.180 +    case BLKTAP_IOCTL_SETMODE:
  13.181 +        if (BLKTAP_MODE_VALID(arg)) {
  13.182 +            blktap_mode = arg;
  13.183 +            /* XXX: may need to flush rings here. */
  13.184 +            printk(KERN_INFO "blktap: set mode to %lx\n", arg);
  13.185 +            return 0;
  13.186 +        }
  13.187 +        /* XXX: return a more meaningful error case here. */
  13.188 +    }
  13.189 +    return -ENOIOCTLCMD;
  13.190 +}
  13.191 +
  13.192 +static unsigned int blktap_poll(struct file *file, poll_table *wait)
  13.193 +{
  13.194 +        poll_wait(file, &blktap_wait, wait);
  13.195 +
  13.196 +        if ( (fe_ring.req_prod != fe_ring.ring->req_prod) ||
  13.197 +             (be_ring.rsp_prod != be_ring.ring->resp_prod) ) {
  13.198 +
  13.199 +            fe_ring.ring->req_prod = fe_ring.req_prod;
  13.200 +            be_ring.ring->resp_prod = be_ring.rsp_prod;
  13.201 +            return POLLIN | POLLRDNORM;
  13.202 +        }
  13.203 +
  13.204 +        return 0;
  13.205 +}
  13.206 +
  13.207 +void blktap_kick_user(void)
  13.208 +{
  13.209 +    /* blktap_ring->req_prod = blktap_req_prod; */
  13.210 +    wake_up_interruptible(&blktap_wait);
  13.211 +}
  13.212 +
  13.213 +static struct file_operations blktap_fops = {
  13.214 +    owner:    THIS_MODULE,
  13.215 +    poll:     blktap_poll,
  13.216 +    ioctl:    blktap_ioctl,
  13.217 +    open:     blktap_open,
  13.218 +    release:  blktap_release,
  13.219 +    mmap:     blktap_mmap,
  13.220 +};
  13.221 +
  13.222 +/* -------[ blktap module setup ]------------------------------------- */
  13.223 +
  13.224 +static struct miscdevice blktap_miscdev = {
  13.225 +    .minor        = BLKTAP_MINOR,
  13.226 +    .name         = "blktap",
  13.227 +    .fops         = &blktap_fops,
  13.228 +    .devfs_name   = "misc/blktap",
  13.229 +};
  13.230 +
  13.231 +int blktap_init(void)
  13.232 +{
  13.233 +    int err;
  13.234 +
  13.235 +    err = misc_register(&blktap_miscdev);
  13.236 +    if ( err != 0 )
  13.237 +    {
  13.238 +        printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
  13.239 +        return err;
  13.240 +    }
  13.241 +
  13.242 +    init_waitqueue_head(&blktap_wait);
  13.243 +
  13.244 +
  13.245 +    return 0;
  13.246 +}