4 * Interfaces for the Xen block tap driver.
6 * (c) 2004, Andrew Warfield, University of Cambridge
13 #include <linux/version.h>
14 #include <linux/blkdev.h>
15 #include <linux/config.h>
16 #include <linux/sched.h>
17 #include <linux/interrupt.h>
18 #include <asm-xen/ctrl_if.h>
19 #include <linux/slab.h>
20 #include <linux/blkdev.h>
22 #include <asm/setup.h>
23 #include <asm/pgalloc.h>
24 #include <asm-xen/hypervisor.h>
25 #include <asm-xen/xen-public/io/blkif.h>
26 #include <asm-xen/xen-public/io/ring.h>
28 /* Used to signal to the backend that this is a tap domain. */
29 #define BLKTAP_COOKIE 0xbeadfeed
31 /* -------[ debug / pretty printing ]--------------------------------- */
33 #define PRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
34 __FILE__ , __LINE__ , ## _a )
36 #define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
37 __FILE__ , __LINE__ , ## _a )
39 #define DPRINTK(_f, _a...) ((void)0)
44 if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
45 __LINE__, __FILE__); *(int*)0=0; }
47 #define ASSERT(_p) ((void)0)
50 #define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
53 /* -------[ state descriptors ]--------------------------------------- */
55 #define BLKIF_STATE_CLOSED 0
56 #define BLKIF_STATE_DISCONNECTED 1
57 #define BLKIF_STATE_CONNECTED 2
59 /* -------[ connection tracking ]------------------------------------- */
61 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
62 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
65 extern spinlock_t blkif_io_lock;
67 typedef struct blkif_st {
68 /* Unique identifier for this interface. */
71 /* Physical parameters of the comms window. */
72 unsigned long shmem_frame;
75 /* Comms information. */
76 blkif_back_ring_t blk_ring;
78 enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
80 * DISCONNECT response is deferred until pending requests are ack'ed.
81 * We therefore need to store the id from the original request.
84 struct blkif_st *hash_next;
85 struct list_head blkdev_list;
86 spinlock_t blk_ring_lock;
88 struct work_struct work;
91 blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
92 void blkif_disconnect_complete(blkif_t *blkif);
93 #define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
94 #define blkif_put(_b) \
96 if ( atomic_dec_and_test(&(_b)->refcnt) ) \
97 blkif_disconnect_complete(_b); \
101 /* -------[ active request tracking ]--------------------------------- */
107 unsigned long mach_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
108 unsigned long virt_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
112 typedef unsigned int ACTIVE_RING_IDX;
114 active_req_t *lookup_active_req(ACTIVE_RING_IDX idx);
116 extern inline unsigned int ID_TO_IDX(unsigned long id)
118 return ( id & 0x0000ffff );
121 extern inline domid_t ID_TO_DOM(unsigned long id)
126 void active_reqs_init(void);
128 /* -------[ interposition -> character device interface ]------------- */
130 /* /dev/xen/blktap resides at device number major=10, minor=200 */
131 #define BLKTAP_MINOR 202
133 /* size of the extra VMA area to map in attached pages. */
134 #define BLKTAP_VMA_PAGES BLKIF_RING_SIZE
137 #define BLKTAP_IOCTL_KICK_FE 1
138 #define BLKTAP_IOCTL_KICK_BE 2
139 #define BLKTAP_IOCTL_SETMODE 3
140 #define BLKTAP_IOCTL_PRINT_IDXS 100
142 /* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE) */
143 #define BLKTAP_MODE_PASSTHROUGH 0x00000000 /* default */
144 #define BLKTAP_MODE_INTERCEPT_FE 0x00000001
145 #define BLKTAP_MODE_INTERCEPT_BE 0x00000002
146 #define BLKTAP_MODE_COPY_FE 0x00000004
147 #define BLKTAP_MODE_COPY_BE 0x00000008
148 #define BLKTAP_MODE_COPY_FE_PAGES 0x00000010
149 #define BLKTAP_MODE_COPY_BE_PAGES 0x00000020
151 #define BLKTAP_MODE_INTERPOSE \
152 (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
154 #define BLKTAP_MODE_COPY_BOTH \
155 (BLKTAP_MODE_COPY_FE | BLKTAP_MODE_COPY_BE)
157 #define BLKTAP_MODE_COPY_BOTH_PAGES \
158 (BLKTAP_MODE_COPY_FE_PAGES | BLKTAP_MODE_COPY_BE_PAGES)
160 static inline int BLKTAP_MODE_VALID(unsigned long arg)
163 ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
164 ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
165 ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
166 ( arg == BLKTAP_MODE_INTERPOSE ) ||
167 ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
168 ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
169 ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
175 /* -------[ Mappings to User VMA ]------------------------------------ */
176 #define MAX_PENDING_REQS 64
177 #define BATCH_PER_DOMAIN 16
178 extern struct vm_area_struct *blktap_vma;
180 /* The following are from blkback.c and should probably be put in a
181 * header and included from there.
182 * The mmap area described here is where attached data pages eill be mapped.
185 extern unsigned long mmap_vstart;
186 #define MMAP_PAGES_PER_REQUEST \
187 (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
189 (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
190 #define MMAP_VADDR(_req,_seg) \
192 ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
193 ((_seg) * PAGE_SIZE))
195 /* immediately before the mmap area, we have a bunch of pages reserved
196 * for shared memory rings.
199 #define RING_PAGES 3 /* Ctrl, Front, and Back */
200 extern unsigned long rings_vstart;
203 /* -------[ Here be globals ]----------------------------------------- */
204 extern unsigned long blktap_mode;
206 /* Connection to a single backend domain. */
207 extern blkif_front_ring_t blktap_be_ring;
208 extern unsigned int blktap_be_evtchn;
209 extern unsigned int blktap_be_state;
211 /* User ring status. */
212 extern unsigned long blktap_ring_ok;
214 /* -------[ ...and function prototypes. ]----------------------------- */
216 /* init function for character device interface. */
217 int blktap_init(void);
219 /* init function for the blkif cache. */
220 void __init blkif_interface_init(void);
221 void __init blkdev_schedule_init(void);
222 void blkif_deschedule(blkif_t *blkif);
224 /* interfaces to the char driver, passing messages to and from apps. */
225 void blktap_kick_user(void);
227 /* user ring access functions: */
228 int blktap_write_fe_ring(blkif_request_t *req);
229 int blktap_write_be_ring(blkif_response_t *rsp);
230 int blktap_write_ctrl_ring(ctrl_msg_t *msg);
232 /* fe/be ring access functions: */
233 int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp);
234 int write_req_to_be_ring(blkif_request_t *req);
236 /* event notification functions */
237 void kick_fe_domain(blkif_t *blkif);
238 void kick_be_domain(void);
240 /* Interrupt handlers. */
241 irqreturn_t blkif_ptbe_int(int irq, void *dev_id,
242 struct pt_regs *ptregs);
243 irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs);
245 /* Control message receiver. */
246 extern void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id);
249 void print_vm_ring_idxs(void);