Fri Dec 9 03:58:12 2011 UTC ()
Use mutex(9) instead of spl(9). Add further locks around grant table access.


(cherry)
diff -r1.20 -r1.21 src/sys/arch/xen/xen/xengnt.c

cvs diff -r1.20 -r1.21 src/sys/arch/xen/xen/xengnt.c (expand / switch to unified diff)

--- src/sys/arch/xen/xen/xengnt.c 2011/09/20 00:12:24 1.20
+++ src/sys/arch/xen/xen/xengnt.c 2011/12/09 03:58:12 1.21
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: xengnt.c,v 1.20 2011/09/20 00:12:24 jym Exp $ */ 1/* $NetBSD: xengnt.c,v 1.21 2011/12/09 03:58:12 cherry Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Manuel Bouyer. 4 * Copyright (c) 2006 Manuel Bouyer.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -16,35 +16,36 @@ @@ -16,35 +16,36 @@
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * 25 *
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: xengnt.c,v 1.20 2011/09/20 00:12:24 jym Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: xengnt.c,v 1.21 2011/12/09 03:58:12 cherry Exp $");
30 30
31#include <sys/types.h> 31#include <sys/types.h>
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/systm.h> 33#include <sys/systm.h>
34#include <sys/malloc.h> 34#include <sys/malloc.h>
35#include <sys/queue.h> 35#include <sys/queue.h>
36#include <sys/extent.h> 36#include <sys/extent.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
 38#include <sys/mutex.h>
38#include <uvm/uvm.h> 39#include <uvm/uvm.h>
39 40
40#include <xen/hypervisor.h> 41#include <xen/hypervisor.h>
41#include <xen/xen.h> 42#include <xen/xen.h>
42#include <xen/granttables.h> 43#include <xen/granttables.h>
43 44
44/* #define XENDEBUG */ 45/* #define XENDEBUG */
45#ifdef XENDEBUG 46#ifdef XENDEBUG
46#define DPRINTF(x) printf x 47#define DPRINTF(x) printf x
47#else 48#else
48#define DPRINTF(x) 49#define DPRINTF(x)
49#endif 50#endif
50 51
@@ -54,26 +55,27 @@ __KERNEL_RCSID(0, "$NetBSD: xengnt.c,v 1 @@ -54,26 +55,27 @@ __KERNEL_RCSID(0, "$NetBSD: xengnt.c,v 1
54int gnt_nr_grant_frames; 55int gnt_nr_grant_frames;
55/* Maximum number of frames that can make up the grant table */ 56/* Maximum number of frames that can make up the grant table */
56int gnt_max_grant_frames; 57int gnt_max_grant_frames;
57 58
58/* table of free grant entries */ 59/* table of free grant entries */
59grant_ref_t *gnt_entries; 60grant_ref_t *gnt_entries;
60/* last free entry */ 61/* last free entry */
61int last_gnt_entry; 62int last_gnt_entry;
62/* empty entry in the list */ 63/* empty entry in the list */
63#define XENGNT_NO_ENTRY 0xffffffff 64#define XENGNT_NO_ENTRY 0xffffffff
64 65
65/* VM address of the grant table */ 66/* VM address of the grant table */
66grant_entry_t *grant_table; 67grant_entry_t *grant_table;
 68kmutex_t grant_lock;
67 69
68static grant_ref_t xengnt_get_entry(void); 70static grant_ref_t xengnt_get_entry(void);
69static void xengnt_free_entry(grant_ref_t); 71static void xengnt_free_entry(grant_ref_t);
70static int xengnt_more_entries(void); 72static int xengnt_more_entries(void);
71 73
72void 74void
73xengnt_init(void) 75xengnt_init(void)
74{ 76{
75 struct gnttab_query_size query; 77 struct gnttab_query_size query;
76 int rc; 78 int rc;
77 int nr_grant_entries; 79 int nr_grant_entries;
78 int i; 80 int i;
79 81
@@ -89,26 +91,28 @@ xengnt_init(void) @@ -89,26 +91,28 @@ xengnt_init(void)
89 gnt_max_grant_frames * NR_GRANT_ENTRIES_PER_PAGE; 91 gnt_max_grant_frames * NR_GRANT_ENTRIES_PER_PAGE;
90 92
91 grant_table = (void *)uvm_km_alloc(kernel_map, 93 grant_table = (void *)uvm_km_alloc(kernel_map,
92 gnt_max_grant_frames * PAGE_SIZE, 0, UVM_KMF_VAONLY); 94 gnt_max_grant_frames * PAGE_SIZE, 0, UVM_KMF_VAONLY);
93 if (grant_table == NULL) 95 if (grant_table == NULL)
94 panic("xengnt_init() no VM space"); 96 panic("xengnt_init() no VM space");
95 gnt_entries = malloc((nr_grant_entries + 1) * sizeof(grant_ref_t), 97 gnt_entries = malloc((nr_grant_entries + 1) * sizeof(grant_ref_t),
96 M_DEVBUF, M_NOWAIT); 98 M_DEVBUF, M_NOWAIT);
97 if (gnt_entries == NULL) 99 if (gnt_entries == NULL)
98 panic("xengnt_init() no space for bitmask"); 100 panic("xengnt_init() no space for bitmask");
99 for (i = 0; i <= nr_grant_entries; i++) 101 for (i = 0; i <= nr_grant_entries; i++)
100 gnt_entries[i] = XENGNT_NO_ENTRY; 102 gnt_entries[i] = XENGNT_NO_ENTRY;
101 103
 104 mutex_init(&grant_lock, MUTEX_DEFAULT, IPL_VM);
 105
102 xengnt_resume(); 106 xengnt_resume();
103 107
104} 108}
105 109
106/* 110/*
107 * Resume grant table state 111 * Resume grant table state
108 */ 112 */
109bool 113bool
110xengnt_resume(void) 114xengnt_resume(void)
111{ 115{
112 int previous_nr_grant_frames = gnt_nr_grant_frames; 116 int previous_nr_grant_frames = gnt_nr_grant_frames;
113 117
114 last_gnt_entry = 0; 118 last_gnt_entry = 0;
@@ -207,115 +211,119 @@ xengnt_more_entries(void) @@ -207,115 +211,119 @@ xengnt_more_entries(void)
207 } 211 }
208 gnt_nr_grant_frames = nframes_new; 212 gnt_nr_grant_frames = nframes_new;
209 free(pages, M_DEVBUF); 213 free(pages, M_DEVBUF);
210 return 0; 214 return 0;
211} 215}
212 216
213/* 217/*
214 * Returns a reference to the first free entry in grant table 218 * Returns a reference to the first free entry in grant table
215 */ 219 */
216static grant_ref_t 220static grant_ref_t
217xengnt_get_entry(void) 221xengnt_get_entry(void)
218{ 222{
219 grant_ref_t entry; 223 grant_ref_t entry;
220 int s = splvm(); 224 mutex_enter(&grant_lock);
221 static struct timeval xengnt_nonmemtime; 225 static struct timeval xengnt_nonmemtime;
222 static const struct timeval xengnt_nonmemintvl = {5,0}; 226 static const struct timeval xengnt_nonmemintvl = {5,0};
223 227
224 if (last_gnt_entry == 0) { 228 if (last_gnt_entry == 0) {
225 if (xengnt_more_entries()) { 229 if (xengnt_more_entries()) {
226 splx(s); 230 mutex_exit(&grant_lock);
227 if (ratecheck(&xengnt_nonmemtime, &xengnt_nonmemintvl)) 231 if (ratecheck(&xengnt_nonmemtime, &xengnt_nonmemintvl))
228 printf("xengnt_get_entry: out of grant " 232 printf("xengnt_get_entry: out of grant "
229 "table entries\n"); 233 "table entries\n");
230 return XENGNT_NO_ENTRY; 234 return XENGNT_NO_ENTRY;
231 } 235 }
232 } 236 }
233 KASSERT(gnt_entries[last_gnt_entry] == XENGNT_NO_ENTRY); 237 KASSERT(gnt_entries[last_gnt_entry] == XENGNT_NO_ENTRY);
234 last_gnt_entry--; 238 last_gnt_entry--;
235 entry = gnt_entries[last_gnt_entry]; 239 entry = gnt_entries[last_gnt_entry];
236 gnt_entries[last_gnt_entry] = XENGNT_NO_ENTRY; 240 gnt_entries[last_gnt_entry] = XENGNT_NO_ENTRY;
237 splx(s); 241 mutex_exit(&grant_lock);
238 KASSERT(entry != XENGNT_NO_ENTRY); 242 KASSERT(entry != XENGNT_NO_ENTRY);
239 KASSERT(last_gnt_entry >= 0); 243 KASSERT(last_gnt_entry >= 0);
240 KASSERT(last_gnt_entry <= gnt_max_grant_frames * NR_GRANT_ENTRIES_PER_PAGE); 244 KASSERT(last_gnt_entry <= gnt_max_grant_frames * NR_GRANT_ENTRIES_PER_PAGE);
241 return entry; 245 return entry;
242} 246}
243 247
244/* 248/*
245 * Mark the grant table entry as free 249 * Mark the grant table entry as free
246 */ 250 */
247static void 251static void
248xengnt_free_entry(grant_ref_t entry) 252xengnt_free_entry(grant_ref_t entry)
249{ 253{
250 int s = splvm(); 254 mutex_enter(&grant_lock);
251 KASSERT(gnt_entries[last_gnt_entry] == XENGNT_NO_ENTRY); 255 KASSERT(gnt_entries[last_gnt_entry] == XENGNT_NO_ENTRY);
252 KASSERT(last_gnt_entry >= 0); 256 KASSERT(last_gnt_entry >= 0);
253 KASSERT(last_gnt_entry <= gnt_max_grant_frames * NR_GRANT_ENTRIES_PER_PAGE); 257 KASSERT(last_gnt_entry <= gnt_max_grant_frames * NR_GRANT_ENTRIES_PER_PAGE);
254 gnt_entries[last_gnt_entry] = entry; 258 gnt_entries[last_gnt_entry] = entry;
255 last_gnt_entry++; 259 last_gnt_entry++;
256 splx(s); 260 mutex_exit(&grant_lock);
257} 261}
258 262
259int 263int
260xengnt_grant_access(domid_t dom, paddr_t ma, int ro, grant_ref_t *entryp) 264xengnt_grant_access(domid_t dom, paddr_t ma, int ro, grant_ref_t *entryp)
261{ 265{
262 *entryp = xengnt_get_entry(); 266 *entryp = xengnt_get_entry();
263 if (__predict_false(*entryp == XENGNT_NO_ENTRY)) 267 if (__predict_false(*entryp == XENGNT_NO_ENTRY))
264 return ENOMEM; 268 return ENOMEM;
265 269
 270 mutex_enter(&grant_lock);
266 grant_table[*entryp].frame = ma >> PAGE_SHIFT; 271 grant_table[*entryp].frame = ma >> PAGE_SHIFT;
267 grant_table[*entryp].domid = dom; 272 grant_table[*entryp].domid = dom;
268 /* 273 /*
269 * ensure that the above values reach global visibility  274 * ensure that the above values reach global visibility
270 * before permitting frame's access (done when we set flags) 275 * before permitting frame's access (done when we set flags)
271 */ 276 */
272 xen_rmb(); 277 xen_rmb();
273 grant_table[*entryp].flags = 278 grant_table[*entryp].flags =
274 GTF_permit_access | (ro ? GTF_readonly : 0); 279 GTF_permit_access | (ro ? GTF_readonly : 0);
 280 mutex_exit(&grant_lock);
275 return 0; 281 return 0;
276} 282}
277 283
278void 284void
279xengnt_revoke_access(grant_ref_t entry) 285xengnt_revoke_access(grant_ref_t entry)
280{ 286{
281 uint16_t flags, nflags; 287 uint16_t flags, nflags;
282 288
283 nflags = grant_table[entry].flags; 289 nflags = grant_table[entry].flags;
284 290
285 do { 291 do {
286 if ((flags = nflags) & (GTF_reading|GTF_writing)) 292 if ((flags = nflags) & (GTF_reading|GTF_writing))
287 panic("xengnt_revoke_access: still in use"); 293 panic("xengnt_revoke_access: still in use");
288 nflags = xen_atomic_cmpxchg16(&grant_table[entry].flags, 294 nflags = xen_atomic_cmpxchg16(&grant_table[entry].flags,
289 flags, 0); 295 flags, 0);
290 } while (nflags != flags); 296 } while (nflags != flags);
291 xengnt_free_entry(entry); 297 xengnt_free_entry(entry);
292} 298}
293 299
294int 300int
295xengnt_grant_transfer(domid_t dom, grant_ref_t *entryp) 301xengnt_grant_transfer(domid_t dom, grant_ref_t *entryp)
296{ 302{
297 *entryp = xengnt_get_entry(); 303 *entryp = xengnt_get_entry();
298 if (__predict_false(*entryp == XENGNT_NO_ENTRY)) 304 if (__predict_false(*entryp == XENGNT_NO_ENTRY))
299 return ENOMEM; 305 return ENOMEM;
300 306
 307 mutex_enter(&grant_lock);
301 grant_table[*entryp].frame = 0; 308 grant_table[*entryp].frame = 0;
302 grant_table[*entryp].domid = dom; 309 grant_table[*entryp].domid = dom;
303 /* 310 /*
304 * ensure that the above values reach global visibility  311 * ensure that the above values reach global visibility
305 * before permitting frame's transfer (done when we set flags) 312 * before permitting frame's transfer (done when we set flags)
306 */ 313 */
307 xen_rmb(); 314 xen_rmb();
308 grant_table[*entryp].flags = GTF_accept_transfer; 315 grant_table[*entryp].flags = GTF_accept_transfer;
 316 mutex_exit(&grant_lock);
309 return 0; 317 return 0;
310} 318}
311 319
312paddr_t 320paddr_t
313xengnt_revoke_transfer(grant_ref_t entry) 321xengnt_revoke_transfer(grant_ref_t entry)
314{ 322{
315 paddr_t page; 323 paddr_t page;
316 uint16_t flags; 324 uint16_t flags;
317 325
318 /* if the transfer has not started, free the entry and return 0 */ 326 /* if the transfer has not started, free the entry and return 0 */
319 while (!((flags = grant_table[entry].flags) & GTF_transfer_committed)) { 327 while (!((flags = grant_table[entry].flags) & GTF_transfer_committed)) {
320 if (xen_atomic_cmpxchg16(&grant_table[entry].flags, 328 if (xen_atomic_cmpxchg16(&grant_table[entry].flags,
321 flags, 0) == flags ) { 329 flags, 0) == flags ) {