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