xref: /onnv-gate/usr/src/uts/common/xen/os/gnttab.c (revision 5741:58423876d513)
1*5741Smrj /*
2*5741Smrj  * CDDL HEADER START
3*5741Smrj  *
4*5741Smrj  * The contents of this file are subject to the terms of the
5*5741Smrj  * Common Development and Distribution License (the "License").
6*5741Smrj  * You may not use this file except in compliance with the License.
7*5741Smrj  *
8*5741Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5741Smrj  * or http://www.opensolaris.org/os/licensing.
10*5741Smrj  * See the License for the specific language governing permissions
11*5741Smrj  * and limitations under the License.
12*5741Smrj  *
13*5741Smrj  * When distributing Covered Code, include this CDDL HEADER in each
14*5741Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5741Smrj  * If applicable, add the following below this CDDL HEADER, with the
16*5741Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
17*5741Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5741Smrj  *
19*5741Smrj  * CDDL HEADER END
20*5741Smrj  */
21*5741Smrj 
22*5741Smrj /*
23*5741Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*5741Smrj  * Use is subject to license terms.
25*5741Smrj  */
26*5741Smrj 
27*5741Smrj #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*5741Smrj 
29*5741Smrj /*
30*5741Smrj  * gnttab.c
31*5741Smrj  *
32*5741Smrj  * Granting foreign access to our memory reservation.
33*5741Smrj  *
34*5741Smrj  * Copyright (c) 2005, Christopher Clark
35*5741Smrj  * Copyright (c) 2004-2005, K A Fraser
36*5741Smrj  *
37*5741Smrj  * This file may be distributed separately from the Linux kernel, or
38*5741Smrj  * incorporated into other software packages, subject to the following license:
39*5741Smrj  *
40*5741Smrj  * Permission is hereby granted, free of charge, to any person obtaining a copy
41*5741Smrj  * of this source file (the "Software"), to deal in the Software without
42*5741Smrj  * restriction, including without limitation the rights to use, copy, modify,
43*5741Smrj  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
44*5741Smrj  * and to permit persons to whom the Software is furnished to do so, subject to
45*5741Smrj  * the following conditions:
46*5741Smrj  *
47*5741Smrj  * The above copyright notice and this permission notice shall be included in
48*5741Smrj  * all copies or substantial portions of the Software.
49*5741Smrj  *
50*5741Smrj  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51*5741Smrj  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52*5741Smrj  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
53*5741Smrj  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54*5741Smrj  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
55*5741Smrj  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
56*5741Smrj  * IN THE SOFTWARE.
57*5741Smrj  */
58*5741Smrj 
59*5741Smrj #include <sys/types.h>
60*5741Smrj #include <sys/archsystm.h>
61*5741Smrj #ifdef XPV_HVM_DRIVER
62*5741Smrj #include <sys/xpv_support.h>
63*5741Smrj #include <sys/mman.h>
64*5741Smrj #include <vm/hat.h>
65*5741Smrj #endif
66*5741Smrj #include <sys/hypervisor.h>
67*5741Smrj #include <sys/gnttab.h>
68*5741Smrj #include <sys/sysmacros.h>
69*5741Smrj #include <sys/machsystm.h>
70*5741Smrj #include <sys/systm.h>
71*5741Smrj #include <sys/mutex.h>
72*5741Smrj #include <sys/atomic.h>
73*5741Smrj #include <sys/spl.h>
74*5741Smrj #include <sys/condvar.h>
75*5741Smrj #include <sys/cpuvar.h>
76*5741Smrj #include <sys/taskq.h>
77*5741Smrj #include <sys/panic.h>
78*5741Smrj #include <sys/cmn_err.h>
79*5741Smrj #include <sys/promif.h>
80*5741Smrj #include <sys/cpu.h>
81*5741Smrj #include <sys/vmem.h>
82*5741Smrj #include <vm/hat_i86.h>
83*5741Smrj #include <sys/bootconf.h>
84*5741Smrj #include <sys/bootsvcs.h>
85*5741Smrj #ifndef XPV_HVM_DRIVER
86*5741Smrj #include <sys/bootinfo.h>
87*5741Smrj #include <sys/multiboot.h>
88*5741Smrj #include <vm/kboot_mmu.h>
89*5741Smrj #endif
90*5741Smrj #include <sys/bootvfs.h>
91*5741Smrj #include <sys/bootprops.h>
92*5741Smrj #include <vm/seg_kmem.h>
93*5741Smrj 
94*5741Smrj #define	cmpxchg(t, c, n) atomic_cas_16((t), (c), (n))
95*5741Smrj 
96*5741Smrj /* External tools reserve first few grant table entries. */
97*5741Smrj #define	NR_RESERVED_ENTRIES 8
98*5741Smrj 
99*5741Smrj #define	NR_GRANT_ENTRIES (NR_GRANT_FRAMES * \
100*5741Smrj 	    MMU_PAGESIZE / sizeof (grant_entry_t))
101*5741Smrj #define	GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1)
102*5741Smrj #define	VALID_GRANT_REF(r) ((r) < NR_GRANT_ENTRIES)
103*5741Smrj 
104*5741Smrj static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
105*5741Smrj static int gnttab_free_count;
106*5741Smrj static grant_ref_t gnttab_free_head;
107*5741Smrj static kmutex_t gnttab_list_lock;
108*5741Smrj 
109*5741Smrj static grant_entry_t *shared;
110*5741Smrj #define	GT_PGADDR(i) ((uintptr_t)shared + ((i) << PAGESHIFT))
111*5741Smrj 
112*5741Smrj static struct gnttab_free_callback *gnttab_free_callback_list = NULL;
113*5741Smrj 
114*5741Smrj static int
115*5741Smrj get_free_entries(int count)
116*5741Smrj {
117*5741Smrj 	int ref;
118*5741Smrj 	grant_ref_t head;
119*5741Smrj 
120*5741Smrj 	mutex_enter(&gnttab_list_lock);
121*5741Smrj 	if (gnttab_free_count < count) {
122*5741Smrj 		mutex_exit(&gnttab_list_lock);
123*5741Smrj 		return (-1);
124*5741Smrj 	}
125*5741Smrj 	ref = head = gnttab_free_head;
126*5741Smrj 	gnttab_free_count -= count;
127*5741Smrj 	while (count-- > 1)
128*5741Smrj 		head = gnttab_list[head];
129*5741Smrj 	gnttab_free_head = gnttab_list[head];
130*5741Smrj 	gnttab_list[head] = GNTTAB_LIST_END;
131*5741Smrj 	mutex_exit(&gnttab_list_lock);
132*5741Smrj 	return (ref);
133*5741Smrj }
134*5741Smrj 
135*5741Smrj #define	get_free_entry() get_free_entries(1)
136*5741Smrj 
137*5741Smrj static void
138*5741Smrj do_free_callbacks(void)
139*5741Smrj {
140*5741Smrj 	struct gnttab_free_callback *callback, *next;
141*5741Smrj 
142*5741Smrj 	callback = gnttab_free_callback_list;
143*5741Smrj 	gnttab_free_callback_list = NULL;
144*5741Smrj 
145*5741Smrj 	while (callback != NULL) {
146*5741Smrj 		next = callback->next;
147*5741Smrj 		if (gnttab_free_count >= callback->count) {
148*5741Smrj 			callback->next = NULL;
149*5741Smrj 			callback->fn(callback->arg);
150*5741Smrj 		} else {
151*5741Smrj 			callback->next = gnttab_free_callback_list;
152*5741Smrj 			gnttab_free_callback_list = callback;
153*5741Smrj 		}
154*5741Smrj 		callback = next;
155*5741Smrj 	}
156*5741Smrj }
157*5741Smrj 
158*5741Smrj static void
159*5741Smrj check_free_callbacks(void)
160*5741Smrj {
161*5741Smrj 	if (gnttab_free_callback_list)
162*5741Smrj 		do_free_callbacks();
163*5741Smrj }
164*5741Smrj 
165*5741Smrj static void
166*5741Smrj put_free_entry(grant_ref_t ref)
167*5741Smrj {
168*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
169*5741Smrj 
170*5741Smrj 	mutex_enter(&gnttab_list_lock);
171*5741Smrj 	gnttab_list[ref] = gnttab_free_head;
172*5741Smrj 	gnttab_free_head = ref;
173*5741Smrj 	gnttab_free_count++;
174*5741Smrj 	check_free_callbacks();
175*5741Smrj 	mutex_exit(&gnttab_list_lock);
176*5741Smrj }
177*5741Smrj 
178*5741Smrj /*
179*5741Smrj  * Public grant-issuing interface functions
180*5741Smrj  */
181*5741Smrj 
182*5741Smrj int
183*5741Smrj gnttab_grant_foreign_access(domid_t domid, gnttab_frame_t frame, int readonly)
184*5741Smrj {
185*5741Smrj 	int ref;
186*5741Smrj 
187*5741Smrj 	if ((ref = get_free_entry()) == -1)
188*5741Smrj 		return (-1);
189*5741Smrj 
190*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
191*5741Smrj 
192*5741Smrj 	shared[ref].frame = frame;
193*5741Smrj 	shared[ref].domid = domid;
194*5741Smrj 	membar_producer();
195*5741Smrj 	shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
196*5741Smrj 
197*5741Smrj 	return (ref);
198*5741Smrj }
199*5741Smrj 
200*5741Smrj void
201*5741Smrj gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
202*5741Smrj 				gnttab_frame_t frame, int readonly)
203*5741Smrj {
204*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
205*5741Smrj 
206*5741Smrj 	shared[ref].frame = frame;
207*5741Smrj 	shared[ref].domid = domid;
208*5741Smrj 	membar_producer();
209*5741Smrj 	shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
210*5741Smrj }
211*5741Smrj 
212*5741Smrj 
213*5741Smrj int
214*5741Smrj gnttab_query_foreign_access(grant_ref_t ref)
215*5741Smrj {
216*5741Smrj 	uint16_t nflags;
217*5741Smrj 
218*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
219*5741Smrj 
220*5741Smrj 	nflags = shared[ref].flags;
221*5741Smrj 
222*5741Smrj 	return (nflags & (GTF_reading|GTF_writing));
223*5741Smrj }
224*5741Smrj 
225*5741Smrj /* ARGSUSED */
226*5741Smrj int
227*5741Smrj gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
228*5741Smrj {
229*5741Smrj 	uint16_t flags, nflags;
230*5741Smrj 
231*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
232*5741Smrj 
233*5741Smrj 	nflags = shared[ref].flags;
234*5741Smrj 	do {
235*5741Smrj 		if ((flags = nflags) & (GTF_reading|GTF_writing)) {
236*5741Smrj 			cmn_err(CE_WARN, "g.e. still in use!");
237*5741Smrj 			return (0);
238*5741Smrj 		}
239*5741Smrj 	} while ((nflags = cmpxchg(&shared[ref].flags, flags, 0)) != flags);
240*5741Smrj 
241*5741Smrj 	return (1);
242*5741Smrj }
243*5741Smrj 
244*5741Smrj void
245*5741Smrj gnttab_end_foreign_access(grant_ref_t ref, int readonly, gnttab_frame_t page)
246*5741Smrj {
247*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
248*5741Smrj 
249*5741Smrj 	if (gnttab_end_foreign_access_ref(ref, readonly)) {
250*5741Smrj 		put_free_entry(ref);
251*5741Smrj 		/*
252*5741Smrj 		 * XXPV - we don't support freeing a page here
253*5741Smrj 		 */
254*5741Smrj 		if (page != 0) {
255*5741Smrj 			cmn_err(CE_WARN,
256*5741Smrj 	"gnttab_end_foreign_access_ref: using unsupported free_page interface");
257*5741Smrj 			/* free_page(page); */
258*5741Smrj 		}
259*5741Smrj 	} else {
260*5741Smrj 		/*
261*5741Smrj 		 * XXX This needs to be fixed so that the ref and page are
262*5741Smrj 		 * placed on a list to be freed up later.
263*5741Smrj 		 */
264*5741Smrj 		cmn_err(CE_WARN, "leaking g.e. and page still in use!");
265*5741Smrj 	}
266*5741Smrj }
267*5741Smrj 
268*5741Smrj int
269*5741Smrj gnttab_grant_foreign_transfer(domid_t domid)
270*5741Smrj {
271*5741Smrj 	int ref;
272*5741Smrj 
273*5741Smrj 	if ((ref = get_free_entry()) == -1)
274*5741Smrj 		return (-1);
275*5741Smrj 
276*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
277*5741Smrj 
278*5741Smrj 	shared[ref].frame = 0;
279*5741Smrj 	shared[ref].domid = domid;
280*5741Smrj 	membar_producer();
281*5741Smrj 	shared[ref].flags = GTF_accept_transfer;
282*5741Smrj 
283*5741Smrj 	return (ref);
284*5741Smrj }
285*5741Smrj 
286*5741Smrj void
287*5741Smrj gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid)
288*5741Smrj {
289*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
290*5741Smrj 
291*5741Smrj 	shared[ref].frame = 0;
292*5741Smrj 	shared[ref].domid = domid;
293*5741Smrj 	membar_producer();
294*5741Smrj 	shared[ref].flags = GTF_accept_transfer;
295*5741Smrj }
296*5741Smrj 
297*5741Smrj gnttab_frame_t
298*5741Smrj gnttab_end_foreign_transfer_ref(grant_ref_t ref)
299*5741Smrj {
300*5741Smrj 	gnttab_frame_t frame;
301*5741Smrj 	uint16_t flags;
302*5741Smrj 
303*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
304*5741Smrj 
305*5741Smrj 	/*
306*5741Smrj 	 * If a transfer is not even yet started, try to reclaim the grant
307*5741Smrj 	 * reference and return failure (== 0).
308*5741Smrj 	 */
309*5741Smrj 	while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
310*5741Smrj 		if (cmpxchg(&shared[ref].flags, flags, 0) == flags)
311*5741Smrj 			return (0);
312*5741Smrj 		(void) HYPERVISOR_yield();
313*5741Smrj 	}
314*5741Smrj 
315*5741Smrj 	/* If a transfer is in progress then wait until it is completed. */
316*5741Smrj 	while (!(flags & GTF_transfer_completed)) {
317*5741Smrj 		flags = shared[ref].flags;
318*5741Smrj 		(void) HYPERVISOR_yield();
319*5741Smrj 	}
320*5741Smrj 
321*5741Smrj 	/* Read the frame number /after/ reading completion status. */
322*5741Smrj 	membar_consumer();
323*5741Smrj 	frame = shared[ref].frame;
324*5741Smrj 	ASSERT(frame != 0);
325*5741Smrj 
326*5741Smrj 	return (frame);
327*5741Smrj }
328*5741Smrj 
329*5741Smrj gnttab_frame_t
330*5741Smrj gnttab_end_foreign_transfer(grant_ref_t ref)
331*5741Smrj {
332*5741Smrj 	gnttab_frame_t frame;
333*5741Smrj 
334*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
335*5741Smrj 
336*5741Smrj 	frame = gnttab_end_foreign_transfer_ref(ref);
337*5741Smrj 	put_free_entry(ref);
338*5741Smrj 	return (frame);
339*5741Smrj }
340*5741Smrj 
341*5741Smrj void
342*5741Smrj gnttab_free_grant_reference(grant_ref_t ref)
343*5741Smrj {
344*5741Smrj 	ASSERT(VALID_GRANT_REF(ref));
345*5741Smrj 
346*5741Smrj 	put_free_entry(ref);
347*5741Smrj }
348*5741Smrj 
349*5741Smrj void
350*5741Smrj gnttab_free_grant_references(grant_ref_t head)
351*5741Smrj {
352*5741Smrj 	grant_ref_t ref;
353*5741Smrj 	int count = 1;
354*5741Smrj 
355*5741Smrj 	if (head == GNTTAB_LIST_END)
356*5741Smrj 		return;
357*5741Smrj 	mutex_enter(&gnttab_list_lock);
358*5741Smrj 	ref = head;
359*5741Smrj 	while (gnttab_list[ref] != GNTTAB_LIST_END) {
360*5741Smrj 		ref = gnttab_list[ref];
361*5741Smrj 		count++;
362*5741Smrj 	}
363*5741Smrj 	gnttab_list[ref] = gnttab_free_head;
364*5741Smrj 	gnttab_free_head = head;
365*5741Smrj 	gnttab_free_count += count;
366*5741Smrj 	check_free_callbacks();
367*5741Smrj 	mutex_exit(&gnttab_list_lock);
368*5741Smrj }
369*5741Smrj 
370*5741Smrj int
371*5741Smrj gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head)
372*5741Smrj {
373*5741Smrj 	int h = get_free_entries(count);
374*5741Smrj 
375*5741Smrj 	if (h == -1)
376*5741Smrj 		return (-1);
377*5741Smrj 
378*5741Smrj 	*head = h;
379*5741Smrj 
380*5741Smrj 	return (0);
381*5741Smrj }
382*5741Smrj 
383*5741Smrj int
384*5741Smrj gnttab_claim_grant_reference(grant_ref_t *private_head)
385*5741Smrj {
386*5741Smrj 	grant_ref_t g = *private_head;
387*5741Smrj 
388*5741Smrj 	if (g == GNTTAB_LIST_END)
389*5741Smrj 		return (-1);
390*5741Smrj 	*private_head = gnttab_list[g];
391*5741Smrj 	return (g);
392*5741Smrj }
393*5741Smrj 
394*5741Smrj void
395*5741Smrj gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release)
396*5741Smrj {
397*5741Smrj 	ASSERT(VALID_GRANT_REF(release));
398*5741Smrj 
399*5741Smrj 	gnttab_list[release] = *private_head;
400*5741Smrj 	*private_head = release;
401*5741Smrj }
402*5741Smrj 
403*5741Smrj void
404*5741Smrj gnttab_request_free_callback(struct gnttab_free_callback *callback,
405*5741Smrj 	void (*fn)(void *), void *arg, uint16_t count)
406*5741Smrj {
407*5741Smrj 	mutex_enter(&gnttab_list_lock);
408*5741Smrj 	if (callback->next)
409*5741Smrj 		goto out;
410*5741Smrj 	callback->fn = fn;
411*5741Smrj 	callback->arg = arg;
412*5741Smrj 	callback->count = count;
413*5741Smrj 	callback->next = gnttab_free_callback_list;
414*5741Smrj 	gnttab_free_callback_list = callback;
415*5741Smrj 	check_free_callbacks();
416*5741Smrj out:
417*5741Smrj 	mutex_exit(&gnttab_list_lock);
418*5741Smrj }
419*5741Smrj 
420*5741Smrj #ifdef XPV_HVM_DRIVER
421*5741Smrj 
422*5741Smrj static void
423*5741Smrj gnttab_map(void)
424*5741Smrj {
425*5741Smrj 	struct xen_add_to_physmap xatp;
426*5741Smrj 	caddr_t va;
427*5741Smrj 	pfn_t pfn;
428*5741Smrj 	int i;
429*5741Smrj 
430*5741Smrj 	va = (caddr_t)shared;
431*5741Smrj 	for (i = 0; i < NR_GRANT_FRAMES; i++) {
432*5741Smrj 		pfn = hat_getpfnum(kas.a_hat, va);
433*5741Smrj 
434*5741Smrj 		xatp.domid = DOMID_SELF;
435*5741Smrj 		xatp.idx = i;
436*5741Smrj 		xatp.space = XENMAPSPACE_grant_table;
437*5741Smrj 		xatp.gpfn = pfn;
438*5741Smrj 		hat_unload(kas.a_hat, va, MMU_PAGESIZE, HAT_UNLOAD);
439*5741Smrj 		if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0)
440*5741Smrj 			panic("Couldn't map grant table");
441*5741Smrj 
442*5741Smrj 		hat_devload(kas.a_hat, va, MMU_PAGESIZE, pfn,
443*5741Smrj 		    PROT_READ | PROT_WRITE,
444*5741Smrj 		    HAT_LOAD | HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST);
445*5741Smrj 
446*5741Smrj 		va += MMU_PAGESIZE;
447*5741Smrj 	}
448*5741Smrj }
449*5741Smrj 
450*5741Smrj void
451*5741Smrj gnttab_init(void)
452*5741Smrj {
453*5741Smrj 	int i;
454*5741Smrj 
455*5741Smrj 	shared = (grant_entry_t *)xen_alloc_pages(NR_GRANT_FRAMES);
456*5741Smrj 
457*5741Smrj 	gnttab_map();
458*5741Smrj 
459*5741Smrj 	for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
460*5741Smrj 		gnttab_list[i] = i + 1;
461*5741Smrj 	gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES;
462*5741Smrj 	gnttab_free_head  = NR_RESERVED_ENTRIES;
463*5741Smrj 
464*5741Smrj 	mutex_init(&gnttab_list_lock, NULL, MUTEX_DEFAULT, NULL);
465*5741Smrj }
466*5741Smrj 
467*5741Smrj void
468*5741Smrj gnttab_resume(void)
469*5741Smrj {
470*5741Smrj 	gnttab_map();
471*5741Smrj }
472*5741Smrj 
473*5741Smrj #else /* XPV_HVM_DRIVER */
474*5741Smrj 
475*5741Smrj void
476*5741Smrj gnttab_init(void)
477*5741Smrj {
478*5741Smrj 	gnttab_setup_table_t set;
479*5741Smrj 	gnttab_frame_t frames[NR_GRANT_FRAMES];
480*5741Smrj 	int i;
481*5741Smrj 
482*5741Smrj 	set.dom = DOMID_SELF;
483*5741Smrj 	set.nr_frames = NR_GRANT_FRAMES;
484*5741Smrj 	/*LINTED: constant in conditional context*/
485*5741Smrj 	set_xen_guest_handle(set.frame_list, frames);
486*5741Smrj 
487*5741Smrj 	/*
488*5741Smrj 	 * Take 4 pages of grant table space from the hypervisor and map it
489*5741Smrj 	 */
490*5741Smrj 	if ((HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &set, 1) != 0) ||
491*5741Smrj 	    (set.status != 0)) {
492*5741Smrj 		cmn_err(CE_PANIC, "Grant Table setup failed");
493*5741Smrj 	}
494*5741Smrj 
495*5741Smrj 	shared = vmem_xalloc(heap_arena, NR_GRANT_FRAMES * MMU_PAGESIZE,
496*5741Smrj 	    MMU_PAGESIZE, 0, 0, 0, 0, VM_SLEEP);
497*5741Smrj 
498*5741Smrj 	for (i = 0; i < NR_GRANT_FRAMES; i++)
499*5741Smrj 		kbm_map_ma(FRAME_TO_MA(frames[i]), GT_PGADDR(i), 0);
500*5741Smrj 
501*5741Smrj 	for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
502*5741Smrj 		gnttab_list[i] = i + 1;
503*5741Smrj 	gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES;
504*5741Smrj 	gnttab_free_head  = NR_RESERVED_ENTRIES;
505*5741Smrj 
506*5741Smrj 	mutex_init(&gnttab_list_lock, NULL, MUTEX_DEFAULT, NULL);
507*5741Smrj }
508*5741Smrj 
509*5741Smrj void
510*5741Smrj gnttab_resume(void)
511*5741Smrj {
512*5741Smrj 	gnttab_setup_table_t set;
513*5741Smrj 	gnttab_frame_t frames[NR_GRANT_FRAMES];
514*5741Smrj 	int i;
515*5741Smrj 
516*5741Smrj 	set.dom = DOMID_SELF;
517*5741Smrj 	set.nr_frames = NR_GRANT_FRAMES;
518*5741Smrj 	/*LINTED: constant in conditional context*/
519*5741Smrj 	set_xen_guest_handle(set.frame_list, frames);
520*5741Smrj 
521*5741Smrj 	/*
522*5741Smrj 	 * Take NR_GRANT_FRAMES pages of grant table space from the
523*5741Smrj 	 * hypervisor and map it
524*5741Smrj 	 */
525*5741Smrj 	if ((HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &set, 1) != 0) ||
526*5741Smrj 	    (set.status != 0)) {
527*5741Smrj 		cmn_err(CE_PANIC, "Grant Table setup failed");
528*5741Smrj 	}
529*5741Smrj 
530*5741Smrj 	for (i = 0; i < NR_GRANT_FRAMES; i++) {
531*5741Smrj 		(void) HYPERVISOR_update_va_mapping(GT_PGADDR(i),
532*5741Smrj 		    FRAME_TO_MA(frames[i]) | PT_VALID | PT_WRITABLE,
533*5741Smrj 		    UVMF_INVLPG | UVMF_ALL);
534*5741Smrj 	}
535*5741Smrj }
536*5741Smrj 
537*5741Smrj #endif /* XPV_HVM_DRIVER */
538*5741Smrj 
539*5741Smrj void
540*5741Smrj gnttab_suspend(void)
541*5741Smrj {
542*5741Smrj 	int i;
543*5741Smrj 
544*5741Smrj 	/*
545*5741Smrj 	 * clear grant table mappings before suspending
546*5741Smrj 	 */
547*5741Smrj 	for (i = 0; i < NR_GRANT_FRAMES; i++) {
548*5741Smrj 		(void) HYPERVISOR_update_va_mapping(GT_PGADDR(i),
549*5741Smrj 		    0, UVMF_INVLPG);
550*5741Smrj 	}
551*5741Smrj }
552*5741Smrj 
553*5741Smrj /*
554*5741Smrj  * Local variables:
555*5741Smrj  *  c-file-style: "solaris"
556*5741Smrj  *  indent-tabs-mode: t
557*5741Smrj  *  c-indent-level: 8
558*5741Smrj  *  c-basic-offset: 8
559*5741Smrj  *  tab-width: 8
560*5741Smrj  * End:
561*5741Smrj  */
562