Sun Jul 31 18:00:54 2011 UTC ()
Fix typo in comment.


(jym)
diff -r1.8 -r1.9 src/sys/arch/xen/x86/xen_shm_machdep.c

cvs diff -r1.8 -r1.9 src/sys/arch/xen/x86/xen_shm_machdep.c (switch to unified diff)

--- src/sys/arch/xen/x86/xen_shm_machdep.c 2010/03/28 20:46:18 1.8
+++ src/sys/arch/xen/x86/xen_shm_machdep.c 2011/07/31 18:00:54 1.9
@@ -1,254 +1,254 @@ @@ -1,254 +1,254 @@
1/* $NetBSD: xen_shm_machdep.c,v 1.8 2010/03/28 20:46:18 snj Exp $ */ 1/* $NetBSD: xen_shm_machdep.c,v 1.9 2011/07/31 18:00:54 jym 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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: xen_shm_machdep.c,v 1.8 2010/03/28 20:46:18 snj Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: xen_shm_machdep.c,v 1.9 2011/07/31 18:00:54 jym Exp $");
30 30
31 31
32#include <sys/types.h> 32#include <sys/types.h>
33#include <sys/param.h> 33#include <sys/param.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/queue.h> 35#include <sys/queue.h>
36#include <sys/vmem.h> 36#include <sys/vmem.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
38#include <uvm/uvm.h> 38#include <uvm/uvm.h>
39 39
40#include <machine/pmap.h> 40#include <machine/pmap.h>
41#include <xen/hypervisor.h> 41#include <xen/hypervisor.h>
42#include <xen/xen.h> 42#include <xen/xen.h>
43#include <xen/evtchn.h> 43#include <xen/evtchn.h>
44#include <xen/xen_shm.h> 44#include <xen/xen_shm.h>
45 45
46/* 46/*
47 * Helper routines for the backend drivers. This implement the necessary 47 * Helper routines for the backend drivers. This implement the necessary
48 * functions to map a bunch of pages from foreign domains in our kernel VM 48 * functions to map a bunch of pages from foreign domains in our kernel VM
49 * space, do I/O to it, and unmap it. 49 * space, do I/O to it, and unmap it.
50 * 50 *
51 * At boot time, we grap some kernel VM space that we'll use to map the foreign 51 * At boot time, we grab some kernel VM space that we'll use to map the foreign
52 * pages. We also maintain a virtual to machine mapping table to give back 52 * pages. We also maintain a virtual to machine mapping table to give back
53 * the appropriate address to bus_dma if requested. 53 * the appropriate address to bus_dma if requested.
54 * If no more VM space is available, we return an error. The caller can then 54 * If no more VM space is available, we return an error. The caller can then
55 * register a callback which will be called when the required VM space is 55 * register a callback which will be called when the required VM space is
56 * available. 56 * available.
57 */ 57 */
58 58
59/* pointers to our VM space */ 59/* pointers to our VM space */
60static vaddr_t xen_shm_base_address; 60static vaddr_t xen_shm_base_address;
61static u_long xen_shm_base_address_pg; 61static u_long xen_shm_base_address_pg;
62static vaddr_t xen_shm_end_address; 62static vaddr_t xen_shm_end_address;
63 63
64/* Grab enough VM space to map an entire vbd ring. */ 64/* Grab enough VM space to map an entire vbd ring. */
65/* Xen3 linux guests seems to eat more pages, gives enough for 10 vbd rings */ 65/* Xen3 linux guests seems to eat more pages, gives enough for 10 vbd rings */
66#define BLKIF_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) 66#define BLKIF_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
67#define XENSHM_NPAGES (BLKIF_RING_SIZE * (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) * 10) 67#define XENSHM_NPAGES (BLKIF_RING_SIZE * (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) * 10)
68 68
69static vsize_t xen_shm_size = (XENSHM_NPAGES * PAGE_SIZE); 69static vsize_t xen_shm_size = (XENSHM_NPAGES * PAGE_SIZE);
70 70
71/* vm space management */ 71/* vm space management */
72static vmem_t *xen_shm_arena; 72static vmem_t *xen_shm_arena;
73 73
74/* callbacks are registered in a FIFO list. */ 74/* callbacks are registered in a FIFO list. */
75 75
76static SIMPLEQ_HEAD(xen_shm_callback_head, xen_shm_callback_entry) 76static SIMPLEQ_HEAD(xen_shm_callback_head, xen_shm_callback_entry)
77 xen_shm_callbacks; 77 xen_shm_callbacks;
78struct xen_shm_callback_entry { 78struct xen_shm_callback_entry {
79 SIMPLEQ_ENTRY(xen_shm_callback_entry) xshmc_entries; 79 SIMPLEQ_ENTRY(xen_shm_callback_entry) xshmc_entries;
80 int (*xshmc_callback)(void *); /* our callback */ 80 int (*xshmc_callback)(void *); /* our callback */
81 void *xshmc_arg; /* cookie passed to the callback */ 81 void *xshmc_arg; /* cookie passed to the callback */
82}; 82};
83/* a pool of struct xen_shm_callback_entry */ 83/* a pool of struct xen_shm_callback_entry */
84static struct pool xen_shm_callback_pool; 84static struct pool xen_shm_callback_pool;
85 85
86#ifdef DEBUG 86#ifdef DEBUG
87/* for ratecheck(9) */ 87/* for ratecheck(9) */
88static struct timeval xen_shm_errintvl = { 60, 0 }; /* a minute, each */ 88static struct timeval xen_shm_errintvl = { 60, 0 }; /* a minute, each */
89#endif 89#endif
90 90
91void 91void
92xen_shm_init(void) 92xen_shm_init(void)
93{ 93{
94 SIMPLEQ_INIT(&xen_shm_callbacks); 94 SIMPLEQ_INIT(&xen_shm_callbacks);
95 pool_init(&xen_shm_callback_pool, sizeof(struct xen_shm_callback_entry), 95 pool_init(&xen_shm_callback_pool, sizeof(struct xen_shm_callback_entry),
96 0, 0, 0, "xshmc", NULL, IPL_VM); 96 0, 0, 0, "xshmc", NULL, IPL_VM);
97 /* ensure we'll always get items */ 97 /* ensure we'll always get items */
98 if (pool_prime(&xen_shm_callback_pool, 98 if (pool_prime(&xen_shm_callback_pool,
99 PAGE_SIZE / sizeof(struct xen_shm_callback_entry)) != 0) { 99 PAGE_SIZE / sizeof(struct xen_shm_callback_entry)) != 0) {
100 panic("xen_shm_init can't prime pool"); 100 panic("xen_shm_init can't prime pool");
101 } 101 }
102 102
103 xen_shm_base_address = uvm_km_alloc(kernel_map, xen_shm_size, 0, 103 xen_shm_base_address = uvm_km_alloc(kernel_map, xen_shm_size, 0,
104 UVM_KMF_VAONLY); 104 UVM_KMF_VAONLY);
105 xen_shm_end_address = xen_shm_base_address + xen_shm_size; 105 xen_shm_end_address = xen_shm_base_address + xen_shm_size;
106 xen_shm_base_address_pg = xen_shm_base_address >> PAGE_SHIFT; 106 xen_shm_base_address_pg = xen_shm_base_address >> PAGE_SHIFT;
107 if (xen_shm_base_address == 0) { 107 if (xen_shm_base_address == 0) {
108 panic("xen_shm_init no VM space"); 108 panic("xen_shm_init no VM space");
109 } 109 }
110 xen_shm_arena = vmem_create("xen_shm", 110 xen_shm_arena = vmem_create("xen_shm",
111 xen_shm_base_address_pg, 111 xen_shm_base_address_pg,
112 (xen_shm_end_address >> PAGE_SHIFT) - 1 - xen_shm_base_address_pg, 112 (xen_shm_end_address >> PAGE_SHIFT) - 1 - xen_shm_base_address_pg,
113 1, NULL, NULL, NULL, 1, VM_NOSLEEP, IPL_VM); 113 1, NULL, NULL, NULL, 1, VM_NOSLEEP, IPL_VM);
114 if (xen_shm_arena == NULL) { 114 if (xen_shm_arena == NULL) {
115 panic("xen_shm_init no arena"); 115 panic("xen_shm_init no arena");
116 } 116 }
117} 117}
118 118
119int 119int
120xen_shm_map(int nentries, int domid, grant_ref_t *grefp, vaddr_t *vap, 120xen_shm_map(int nentries, int domid, grant_ref_t *grefp, vaddr_t *vap,
121 grant_handle_t *handlep, int flags) 121 grant_handle_t *handlep, int flags)
122{ 122{
123 int s, i; 123 int s, i;
124 vaddr_t new_va; 124 vaddr_t new_va;
125 u_long new_va_pg; 125 u_long new_va_pg;
126 int err; 126 int err;
127 gnttab_map_grant_ref_t op[XENSHM_MAX_PAGES_PER_REQUEST]; 127 gnttab_map_grant_ref_t op[XENSHM_MAX_PAGES_PER_REQUEST];
128 128
129#ifdef DIAGNOSTIC 129#ifdef DIAGNOSTIC
130 if (nentries > XENSHM_MAX_PAGES_PER_REQUEST) { 130 if (nentries > XENSHM_MAX_PAGES_PER_REQUEST) {
131 printf("xen_shm_map: %d entries\n", nentries); 131 printf("xen_shm_map: %d entries\n", nentries);
132 panic("xen_shm_map"); 132 panic("xen_shm_map");
133 } 133 }
134#endif 134#endif
135 s = splvm(); /* splvm is the lowest level blocking disk and net IRQ */ 135 s = splvm(); /* splvm is the lowest level blocking disk and net IRQ */
136 /* 136 /*
137 * if a driver is waiting for ressources, don't try to allocate 137 * if a driver is waiting for ressources, don't try to allocate
138 * yet. This is to avoid a flood of small requests stalling large 138 * yet. This is to avoid a flood of small requests stalling large
139 * ones. 139 * ones.
140 */ 140 */
141 if (__predict_false(SIMPLEQ_FIRST(&xen_shm_callbacks) != NULL) && 141 if (__predict_false(SIMPLEQ_FIRST(&xen_shm_callbacks) != NULL) &&
142 (flags & XSHM_CALLBACK) == 0) { 142 (flags & XSHM_CALLBACK) == 0) {
143#ifdef DEBUG 143#ifdef DEBUG
144 static struct timeval lasttime; 144 static struct timeval lasttime;
145#endif 145#endif
146 splx(s); 146 splx(s);
147#ifdef DEBUG 147#ifdef DEBUG
148 if (ratecheck(&lasttime, &xen_shm_errintvl)) 148 if (ratecheck(&lasttime, &xen_shm_errintvl))
149 printf("xen_shm_map: ENOMEM1\n"); 149 printf("xen_shm_map: ENOMEM1\n");
150#endif 150#endif
151 return ENOMEM; 151 return ENOMEM;
152 } 152 }
153 /* allocate the needed virtual space */ 153 /* allocate the needed virtual space */
154 new_va_pg = vmem_alloc(xen_shm_arena, nentries, 154 new_va_pg = vmem_alloc(xen_shm_arena, nentries,
155 VM_INSTANTFIT | VM_NOSLEEP); 155 VM_INSTANTFIT | VM_NOSLEEP);
156 if (new_va_pg == 0) { 156 if (new_va_pg == 0) {
157#ifdef DEBUG 157#ifdef DEBUG
158 static struct timeval lasttime; 158 static struct timeval lasttime;
159#endif 159#endif
160 splx(s); 160 splx(s);
161#ifdef DEBUG 161#ifdef DEBUG
162 if (ratecheck(&lasttime, &xen_shm_errintvl)) 162 if (ratecheck(&lasttime, &xen_shm_errintvl))
163 printf("xen_shm_map: ENOMEM\n"); 163 printf("xen_shm_map: ENOMEM\n");
164#endif 164#endif
165 return ENOMEM; 165 return ENOMEM;
166 } 166 }
167 splx(s); 167 splx(s);
168 168
169 new_va = new_va_pg << PAGE_SHIFT; 169 new_va = new_va_pg << PAGE_SHIFT;
170 for (i = 0; i < nentries; i++) { 170 for (i = 0; i < nentries; i++) {
171 op[i].host_addr = new_va + i * PAGE_SIZE; 171 op[i].host_addr = new_va + i * PAGE_SIZE;
172 op[i].dom = domid; 172 op[i].dom = domid;
173 op[i].ref = grefp[i]; 173 op[i].ref = grefp[i];
174 op[i].flags = GNTMAP_host_map | 174 op[i].flags = GNTMAP_host_map |
175 ((flags & XSHM_RO) ? GNTMAP_readonly : 0); 175 ((flags & XSHM_RO) ? GNTMAP_readonly : 0);
176 } 176 }
177 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, op, nentries); 177 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, op, nentries);
178 if (__predict_false(err)) 178 if (__predict_false(err))
179 panic("xen_shm_map: HYPERVISOR_grant_table_op failed"); 179 panic("xen_shm_map: HYPERVISOR_grant_table_op failed");
180 for (i = 0; i < nentries; i++) { 180 for (i = 0; i < nentries; i++) {
181 if (__predict_false(op[i].status)) 181 if (__predict_false(op[i].status))
182 return op[i].status; 182 return op[i].status;
183 handlep[i] = op[i].handle; 183 handlep[i] = op[i].handle;
184 } 184 }
185 *vap = new_va; 185 *vap = new_va;
186 return 0; 186 return 0;
187} 187}
188 188
189void 189void
190xen_shm_unmap(vaddr_t va, int nentries, grant_handle_t *handlep) 190xen_shm_unmap(vaddr_t va, int nentries, grant_handle_t *handlep)
191{ 191{
192 gnttab_unmap_grant_ref_t op[XENSHM_MAX_PAGES_PER_REQUEST]; 192 gnttab_unmap_grant_ref_t op[XENSHM_MAX_PAGES_PER_REQUEST];
193 int ret; 193 int ret;
194 int i; 194 int i;
195 int s; 195 int s;
196 struct xen_shm_callback_entry *xshmc; 196 struct xen_shm_callback_entry *xshmc;
197 197
198#ifdef DIAGNOSTIC 198#ifdef DIAGNOSTIC
199 if (nentries > XENSHM_MAX_PAGES_PER_REQUEST) { 199 if (nentries > XENSHM_MAX_PAGES_PER_REQUEST) {
200 printf("xen_shm_unmap: %d entries\n", nentries); 200 printf("xen_shm_unmap: %d entries\n", nentries);
201 panic("xen_shm_unmap"); 201 panic("xen_shm_unmap");
202 } 202 }
203#endif 203#endif
204 204
205 for (i = 0; i < nentries; i++) { 205 for (i = 0; i < nentries; i++) {
206 op[i].host_addr = va + i * PAGE_SIZE; 206 op[i].host_addr = va + i * PAGE_SIZE;
207 op[i].dev_bus_addr = 0; 207 op[i].dev_bus_addr = 0;
208 op[i].handle = handlep[i]; 208 op[i].handle = handlep[i];
209 } 209 }
210 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, 210 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
211 op, nentries); 211 op, nentries);
212 if (__predict_false(ret)) 212 if (__predict_false(ret))
213 panic("xen_shm_unmap: unmap failed"); 213 panic("xen_shm_unmap: unmap failed");
214 va = va >> PAGE_SHIFT; 214 va = va >> PAGE_SHIFT;
215 s = splvm(); /* splvm is the lowest level blocking disk and net IRQ */ 215 s = splvm(); /* splvm is the lowest level blocking disk and net IRQ */
216 vmem_free(xen_shm_arena, va, nentries); 216 vmem_free(xen_shm_arena, va, nentries);
217 while (__predict_false((xshmc = SIMPLEQ_FIRST(&xen_shm_callbacks)) 217 while (__predict_false((xshmc = SIMPLEQ_FIRST(&xen_shm_callbacks))
218 != NULL)) { 218 != NULL)) {
219 SIMPLEQ_REMOVE_HEAD(&xen_shm_callbacks, xshmc_entries); 219 SIMPLEQ_REMOVE_HEAD(&xen_shm_callbacks, xshmc_entries);
220 splx(s); 220 splx(s);
221 if (xshmc->xshmc_callback(xshmc->xshmc_arg) == 0) { 221 if (xshmc->xshmc_callback(xshmc->xshmc_arg) == 0) {
222 /* callback succeeded */ 222 /* callback succeeded */
223 s = splvm(); 223 s = splvm();
224 pool_put(&xen_shm_callback_pool, xshmc); 224 pool_put(&xen_shm_callback_pool, xshmc);
225 } else { 225 } else {
226 /* callback failed, probably out of ressources */ 226 /* callback failed, probably out of ressources */
227 s = splvm(); 227 s = splvm();
228 SIMPLEQ_INSERT_TAIL(&xen_shm_callbacks, xshmc, 228 SIMPLEQ_INSERT_TAIL(&xen_shm_callbacks, xshmc,
229 xshmc_entries); 229 xshmc_entries);
230 230
231 break; 231 break;
232 } 232 }
233 } 233 }
234 splx(s); 234 splx(s);
235} 235}
236 236
237int 237int
238xen_shm_callback(int (*callback)(void *), void *arg) 238xen_shm_callback(int (*callback)(void *), void *arg)
239{ 239{
240 struct xen_shm_callback_entry *xshmc; 240 struct xen_shm_callback_entry *xshmc;
241 int s; 241 int s;
242 242
243 s = splvm(); 243 s = splvm();
244 xshmc = pool_get(&xen_shm_callback_pool, PR_NOWAIT); 244 xshmc = pool_get(&xen_shm_callback_pool, PR_NOWAIT);
245 if (xshmc == NULL) { 245 if (xshmc == NULL) {
246 splx(s); 246 splx(s);
247 return ENOMEM; 247 return ENOMEM;
248 } 248 }
249 xshmc->xshmc_arg = arg; 249 xshmc->xshmc_arg = arg;
250 xshmc->xshmc_callback = callback; 250 xshmc->xshmc_callback = callback;
251 SIMPLEQ_INSERT_TAIL(&xen_shm_callbacks, xshmc, xshmc_entries); 251 SIMPLEQ_INSERT_TAIL(&xen_shm_callbacks, xshmc, xshmc_entries);
252 splx(s); 252 splx(s);
253 return 0; 253 return 0;
254} 254}