xref: /illumos-gate/usr/src/uts/common/xen/io/xpvtap.h (revision c9eab9d4e096bb9b983e9b007577edfa73c32eff)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _SYS_XPVTAP_H
28 #define	_SYS_XPVTAP_H
29 
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #include <sys/types.h>
36 
37 /* Notification from user app that it has pushed responses */
38 #define	XPVTAP_IOCTL_RESP_PUSH		1
39 
40 /* Number of bytes the user app should mmap for the gref pages */
41 #define	XPVTAP_GREF_BUFSIZE	\
42 	(BLKIF_RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGESIZE)
43 
44 
45 #ifdef	_KERNEL
46 
47 #include <xen/io/blk_common.h>
48 
49 
50 #define	XPVTAP_GREF_REQADDR(base, id) (caddr_t) \
51 	((uintptr_t)base + (id * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGESIZE))
52 
53 /* structure used to keep track of resources */
54 typedef struct xpvtap_rs_s {
55 	/*
56 	 * Bounds of resource allocation. We will start allocating at rs_min
57 	 * and rollover at rs_max+1 (rs_max is included). e.g. for rs_min=0
58 	 * and rs_max=7, we will have 8 total resources which can be alloced.
59 	 */
60 	uint_t rs_min;
61 	uint_t rs_max;
62 
63 	/*
64 	 * rs_free points to an array of 64-bit values used to track resource
65 	 * allocation. rs_free_size is the free buffer size in bytes.
66 	 */
67 	uint64_t *rs_free;
68 	uint_t rs_free_size;
69 
70 	/*
71 	 * last tracks the last alloc'd resource. This allows us to do a round
72 	 * robin allocation.
73 	 */
74 	uint_t rs_last;
75 
76 	/*
77 	 * set when flushing all allocated resources. We'll know the lock
78 	 * is held.
79 	 */
80 	boolean_t rs_flushing;
81 
82 	kmutex_t rs_mutex;
83 } xpvtap_rs_t;
84 typedef struct xpvtap_rs_s *xpvtap_rs_hdl_t;
85 
86 /* track if user app has the device open, and sleep waiting for close */
87 typedef struct xpvtap_open_s {
88 	kmutex_t	bo_mutex;
89 	boolean_t	bo_opened;
90 	kcondvar_t	bo_exit_cv;
91 } xpvtap_open_t;
92 
93 /*
94  * ring between driver and user app. requests are forwared from the
95  * guest to the user app on this ring. reponses from the user app come in
96  * on this ring are then are forwarded to the guest.
97  */
98 typedef struct xpvtap_user_ring_s {
99 	/* ring state */
100 	blkif_front_ring_t	ur_ring;
101 
102 	/*
103 	 * pointer to allocated memory for the ring which is shared between
104 	 * the driver and the app.
105 	 */
106 	blkif_sring_t		*ur_sring;
107 
108 	/* umem cookie for free'ing up the umem */
109 	ddi_umem_cookie_t	ur_cookie;
110 
111 	RING_IDX		ur_prod_polled;
112 } xpvtap_user_ring_t;
113 
114 /*
115  * track the requests that come in from the guest. we need to track the
116  * requests for two reasons. first, we need to know how many grefs we need
117  * to unmap when the app sends the response. second, since we use the ID in
118  * the request to index into um_guest_pages (tells the app where the segments
119  * are mapped), we need to have a mapping between the the ID we sent in the
120  * request to the app and the ID we got from the guest request. The response
121  * to the guest needs to have the later.
122  */
123 typedef struct xpvtap_user_map_s {
124 	/* address space of the user app. grab this in open */
125 	struct as		*um_as;
126 
127 	/* state to track request IDs we can send to the user app */
128 	xpvtap_rs_hdl_t		um_rs;
129 
130 	/*
131 	 * base user app VA of the mapped grefs. this VA space is large enough
132 	 * to map the max pages per request * max outstanding requests.
133 	 */
134 	caddr_t			um_guest_pages;
135 	size_t			um_guest_size;
136 
137 	/*
138 	 * have we locked down the gref buffer's ptes and registered
139 	 * them with segmf. This needs to happen after the user app
140 	 * has mmaped the gref buf.
141 	 */
142 	boolean_t		um_registered;
143 
144 	/*
145 	 * array of outstanding requests to the user app. Index into this
146 	 * array using the ID in the user app request.
147 	 */
148 	blkif_request_t		*um_outstanding_reqs;
149 } xpvtap_user_map_t;
150 
151 /* thread start, wake, exit state */
152 typedef struct xpvtap_user_thread_s {
153 	kmutex_t		ut_mutex;
154 	kcondvar_t		ut_wake_cv;
155 	volatile boolean_t	ut_wake;
156 	volatile boolean_t	ut_exit;
157 	kcondvar_t		ut_exit_done_cv;
158 	volatile boolean_t	ut_exit_done;
159 	ddi_taskq_t		*ut_taskq;
160 } xpvtap_user_thread_t;
161 
162 /* driver state */
163 typedef struct xpvtap_state_s {
164 	dev_info_t		*bt_dip;
165 	int			bt_instance;
166 
167 	/* ring between the guest and xpvtap */
168 	blk_ring_t		bt_guest_ring;
169 
170 	/* ring between xpvtap and the user app */
171 	xpvtap_user_ring_t	bt_user_ring;
172 
173 	xpvtap_user_map_t	bt_map;
174 	xpvtap_user_thread_t	bt_thread;
175 	struct pollhead		bt_pollhead;
176 	xpvtap_open_t		bt_open;
177 } xpvtap_state_t;
178 
179 #endif /* _KERNEL */
180 
181 #ifdef __cplusplus
182 }
183 #endif
184 
185 #endif /* _SYS_XPVTAP_H */
186