1843e1988Sjohnlev /* 2843e1988Sjohnlev * CDDL HEADER START 3843e1988Sjohnlev * 4843e1988Sjohnlev * The contents of this file are subject to the terms of the 5843e1988Sjohnlev * Common Development and Distribution License (the "License"). 6843e1988Sjohnlev * You may not use this file except in compliance with the License. 7843e1988Sjohnlev * 8843e1988Sjohnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9843e1988Sjohnlev * or http://www.opensolaris.org/os/licensing. 10843e1988Sjohnlev * See the License for the specific language governing permissions 11843e1988Sjohnlev * and limitations under the License. 12843e1988Sjohnlev * 13843e1988Sjohnlev * When distributing Covered Code, include this CDDL HEADER in each 14843e1988Sjohnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15843e1988Sjohnlev * If applicable, add the following below this CDDL HEADER, with the 16843e1988Sjohnlev * fields enclosed by brackets "[]" replaced with your own identifying 17843e1988Sjohnlev * information: Portions Copyright [yyyy] [name of copyright owner] 18843e1988Sjohnlev * 19843e1988Sjohnlev * CDDL HEADER END 20843e1988Sjohnlev */ 21843e1988Sjohnlev 22843e1988Sjohnlev /* 23843e1988Sjohnlev * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24843e1988Sjohnlev * Use is subject to license terms. 25843e1988Sjohnlev */ 26843e1988Sjohnlev 27843e1988Sjohnlev #pragma ident "%Z%%M% %I% %E% SMI" 28843e1988Sjohnlev 29843e1988Sjohnlev /* 30843e1988Sjohnlev * gnttab.c 31843e1988Sjohnlev * 32843e1988Sjohnlev * Granting foreign access to our memory reservation. 33843e1988Sjohnlev * 34843e1988Sjohnlev * Copyright (c) 2005, Christopher Clark 35843e1988Sjohnlev * Copyright (c) 2004-2005, K A Fraser 36843e1988Sjohnlev * 37843e1988Sjohnlev * This file may be distributed separately from the Linux kernel, or 38843e1988Sjohnlev * incorporated into other software packages, subject to the following license: 39843e1988Sjohnlev * 40843e1988Sjohnlev * Permission is hereby granted, free of charge, to any person obtaining a copy 41843e1988Sjohnlev * of this source file (the "Software"), to deal in the Software without 42843e1988Sjohnlev * restriction, including without limitation the rights to use, copy, modify, 43843e1988Sjohnlev * merge, publish, distribute, sublicense, and/or sell copies of the Software, 44843e1988Sjohnlev * and to permit persons to whom the Software is furnished to do so, subject to 45843e1988Sjohnlev * the following conditions: 46843e1988Sjohnlev * 47843e1988Sjohnlev * The above copyright notice and this permission notice shall be included in 48843e1988Sjohnlev * all copies or substantial portions of the Software. 49843e1988Sjohnlev * 50843e1988Sjohnlev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 51843e1988Sjohnlev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52843e1988Sjohnlev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53843e1988Sjohnlev * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 54843e1988Sjohnlev * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 55843e1988Sjohnlev * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 56843e1988Sjohnlev * IN THE SOFTWARE. 57843e1988Sjohnlev */ 58843e1988Sjohnlev 59843e1988Sjohnlev #include <sys/types.h> 60843e1988Sjohnlev #include <sys/archsystm.h> 61*551bc2a6Smrj #ifdef XPV_HVM_DRIVER 62*551bc2a6Smrj #include <sys/xpv_support.h> 63*551bc2a6Smrj #include <sys/mman.h> 64*551bc2a6Smrj #include <vm/hat.h> 65*551bc2a6Smrj #endif 66843e1988Sjohnlev #include <sys/hypervisor.h> 67843e1988Sjohnlev #include <sys/gnttab.h> 68843e1988Sjohnlev #include <sys/sysmacros.h> 69843e1988Sjohnlev #include <sys/machsystm.h> 70843e1988Sjohnlev #include <sys/systm.h> 71843e1988Sjohnlev #include <sys/mutex.h> 72843e1988Sjohnlev #include <sys/atomic.h> 73843e1988Sjohnlev #include <sys/spl.h> 74843e1988Sjohnlev #include <sys/condvar.h> 75843e1988Sjohnlev #include <sys/cpuvar.h> 76843e1988Sjohnlev #include <sys/taskq.h> 77843e1988Sjohnlev #include <sys/panic.h> 78843e1988Sjohnlev #include <sys/cmn_err.h> 79843e1988Sjohnlev #include <sys/promif.h> 80843e1988Sjohnlev #include <sys/cpu.h> 81843e1988Sjohnlev #include <sys/vmem.h> 82843e1988Sjohnlev #include <vm/hat_i86.h> 83843e1988Sjohnlev #include <sys/bootconf.h> 84843e1988Sjohnlev #include <sys/bootsvcs.h> 85*551bc2a6Smrj #ifndef XPV_HVM_DRIVER 86843e1988Sjohnlev #include <sys/bootinfo.h> 87843e1988Sjohnlev #include <sys/multiboot.h> 88*551bc2a6Smrj #include <vm/kboot_mmu.h> 89*551bc2a6Smrj #endif 90843e1988Sjohnlev #include <sys/bootvfs.h> 91843e1988Sjohnlev #include <sys/bootprops.h> 92843e1988Sjohnlev #include <vm/seg_kmem.h> 93843e1988Sjohnlev 94843e1988Sjohnlev #define cmpxchg(t, c, n) atomic_cas_16((t), (c), (n)) 95843e1988Sjohnlev 96843e1988Sjohnlev /* External tools reserve first few grant table entries. */ 97843e1988Sjohnlev #define NR_RESERVED_ENTRIES 8 98843e1988Sjohnlev 99843e1988Sjohnlev #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * \ 100843e1988Sjohnlev MMU_PAGESIZE / sizeof (grant_entry_t)) 101843e1988Sjohnlev #define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1) 102843e1988Sjohnlev #define VALID_GRANT_REF(r) ((r) < NR_GRANT_ENTRIES) 103843e1988Sjohnlev 104843e1988Sjohnlev static grant_ref_t gnttab_list[NR_GRANT_ENTRIES]; 105843e1988Sjohnlev static int gnttab_free_count; 106843e1988Sjohnlev static grant_ref_t gnttab_free_head; 107843e1988Sjohnlev static kmutex_t gnttab_list_lock; 108843e1988Sjohnlev 109843e1988Sjohnlev static grant_entry_t *shared; 110843e1988Sjohnlev #define GT_PGADDR(i) ((uintptr_t)shared + ((i) << PAGESHIFT)) 111843e1988Sjohnlev 112843e1988Sjohnlev static struct gnttab_free_callback *gnttab_free_callback_list = NULL; 113843e1988Sjohnlev 114843e1988Sjohnlev static int 115843e1988Sjohnlev get_free_entries(int count) 116843e1988Sjohnlev { 117843e1988Sjohnlev int ref; 118843e1988Sjohnlev grant_ref_t head; 119843e1988Sjohnlev 120843e1988Sjohnlev mutex_enter(&gnttab_list_lock); 121843e1988Sjohnlev if (gnttab_free_count < count) { 122843e1988Sjohnlev mutex_exit(&gnttab_list_lock); 123843e1988Sjohnlev return (-1); 124843e1988Sjohnlev } 125843e1988Sjohnlev ref = head = gnttab_free_head; 126843e1988Sjohnlev gnttab_free_count -= count; 127843e1988Sjohnlev while (count-- > 1) 128843e1988Sjohnlev head = gnttab_list[head]; 129843e1988Sjohnlev gnttab_free_head = gnttab_list[head]; 130843e1988Sjohnlev gnttab_list[head] = GNTTAB_LIST_END; 131843e1988Sjohnlev mutex_exit(&gnttab_list_lock); 132843e1988Sjohnlev return (ref); 133843e1988Sjohnlev } 134843e1988Sjohnlev 135843e1988Sjohnlev #define get_free_entry() get_free_entries(1) 136843e1988Sjohnlev 137843e1988Sjohnlev static void 138843e1988Sjohnlev do_free_callbacks(void) 139843e1988Sjohnlev { 140843e1988Sjohnlev struct gnttab_free_callback *callback, *next; 141843e1988Sjohnlev 142843e1988Sjohnlev callback = gnttab_free_callback_list; 143843e1988Sjohnlev gnttab_free_callback_list = NULL; 144843e1988Sjohnlev 145843e1988Sjohnlev while (callback != NULL) { 146843e1988Sjohnlev next = callback->next; 147843e1988Sjohnlev if (gnttab_free_count >= callback->count) { 148843e1988Sjohnlev callback->next = NULL; 149843e1988Sjohnlev callback->fn(callback->arg); 150843e1988Sjohnlev } else { 151843e1988Sjohnlev callback->next = gnttab_free_callback_list; 152843e1988Sjohnlev gnttab_free_callback_list = callback; 153843e1988Sjohnlev } 154843e1988Sjohnlev callback = next; 155843e1988Sjohnlev } 156843e1988Sjohnlev } 157843e1988Sjohnlev 158843e1988Sjohnlev static void 159843e1988Sjohnlev check_free_callbacks(void) 160843e1988Sjohnlev { 161843e1988Sjohnlev if (gnttab_free_callback_list) 162843e1988Sjohnlev do_free_callbacks(); 163843e1988Sjohnlev } 164843e1988Sjohnlev 165843e1988Sjohnlev static void 166843e1988Sjohnlev put_free_entry(grant_ref_t ref) 167843e1988Sjohnlev { 168843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 169843e1988Sjohnlev 170843e1988Sjohnlev mutex_enter(&gnttab_list_lock); 171843e1988Sjohnlev gnttab_list[ref] = gnttab_free_head; 172843e1988Sjohnlev gnttab_free_head = ref; 173843e1988Sjohnlev gnttab_free_count++; 174843e1988Sjohnlev check_free_callbacks(); 175843e1988Sjohnlev mutex_exit(&gnttab_list_lock); 176843e1988Sjohnlev } 177843e1988Sjohnlev 178843e1988Sjohnlev /* 179843e1988Sjohnlev * Public grant-issuing interface functions 180843e1988Sjohnlev */ 181843e1988Sjohnlev 182843e1988Sjohnlev int 183843e1988Sjohnlev gnttab_grant_foreign_access(domid_t domid, gnttab_frame_t frame, int readonly) 184843e1988Sjohnlev { 185843e1988Sjohnlev int ref; 186843e1988Sjohnlev 187843e1988Sjohnlev if ((ref = get_free_entry()) == -1) 188843e1988Sjohnlev return (-1); 189843e1988Sjohnlev 190843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 191843e1988Sjohnlev 192843e1988Sjohnlev shared[ref].frame = frame; 193843e1988Sjohnlev shared[ref].domid = domid; 194843e1988Sjohnlev membar_producer(); 195843e1988Sjohnlev shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); 196843e1988Sjohnlev 197843e1988Sjohnlev return (ref); 198843e1988Sjohnlev } 199843e1988Sjohnlev 200843e1988Sjohnlev void 201843e1988Sjohnlev gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, 202843e1988Sjohnlev gnttab_frame_t frame, int readonly) 203843e1988Sjohnlev { 204843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 205843e1988Sjohnlev 206843e1988Sjohnlev shared[ref].frame = frame; 207843e1988Sjohnlev shared[ref].domid = domid; 208843e1988Sjohnlev membar_producer(); 209843e1988Sjohnlev shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); 210843e1988Sjohnlev } 211843e1988Sjohnlev 212843e1988Sjohnlev 213843e1988Sjohnlev int 214843e1988Sjohnlev gnttab_query_foreign_access(grant_ref_t ref) 215843e1988Sjohnlev { 216843e1988Sjohnlev uint16_t nflags; 217843e1988Sjohnlev 218843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 219843e1988Sjohnlev 220843e1988Sjohnlev nflags = shared[ref].flags; 221843e1988Sjohnlev 222843e1988Sjohnlev return (nflags & (GTF_reading|GTF_writing)); 223843e1988Sjohnlev } 224843e1988Sjohnlev 225843e1988Sjohnlev /* ARGSUSED */ 226843e1988Sjohnlev int 227843e1988Sjohnlev gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) 228843e1988Sjohnlev { 229843e1988Sjohnlev uint16_t flags, nflags; 230843e1988Sjohnlev 231843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 232843e1988Sjohnlev 233843e1988Sjohnlev nflags = shared[ref].flags; 234843e1988Sjohnlev do { 235843e1988Sjohnlev if ((flags = nflags) & (GTF_reading|GTF_writing)) { 236843e1988Sjohnlev cmn_err(CE_WARN, "g.e. still in use!"); 237843e1988Sjohnlev return (0); 238843e1988Sjohnlev } 239843e1988Sjohnlev } while ((nflags = cmpxchg(&shared[ref].flags, flags, 0)) != flags); 240843e1988Sjohnlev 241843e1988Sjohnlev return (1); 242843e1988Sjohnlev } 243843e1988Sjohnlev 244843e1988Sjohnlev void 245843e1988Sjohnlev gnttab_end_foreign_access(grant_ref_t ref, int readonly, gnttab_frame_t page) 246843e1988Sjohnlev { 247843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 248843e1988Sjohnlev 249843e1988Sjohnlev if (gnttab_end_foreign_access_ref(ref, readonly)) { 250843e1988Sjohnlev put_free_entry(ref); 251843e1988Sjohnlev /* 252843e1988Sjohnlev * XXPV - we don't support freeing a page here 253843e1988Sjohnlev */ 254843e1988Sjohnlev if (page != 0) { 255843e1988Sjohnlev cmn_err(CE_WARN, 256843e1988Sjohnlev "gnttab_end_foreign_access_ref: using unsupported free_page interface"); 257843e1988Sjohnlev /* free_page(page); */ 258843e1988Sjohnlev } 259843e1988Sjohnlev } else { 260843e1988Sjohnlev /* 261843e1988Sjohnlev * XXX This needs to be fixed so that the ref and page are 262843e1988Sjohnlev * placed on a list to be freed up later. 263843e1988Sjohnlev */ 264843e1988Sjohnlev cmn_err(CE_WARN, "leaking g.e. and page still in use!"); 265843e1988Sjohnlev } 266843e1988Sjohnlev } 267843e1988Sjohnlev 268843e1988Sjohnlev int 269843e1988Sjohnlev gnttab_grant_foreign_transfer(domid_t domid) 270843e1988Sjohnlev { 271843e1988Sjohnlev int ref; 272843e1988Sjohnlev 273843e1988Sjohnlev if ((ref = get_free_entry()) == -1) 274843e1988Sjohnlev return (-1); 275843e1988Sjohnlev 276843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 277843e1988Sjohnlev 278843e1988Sjohnlev shared[ref].frame = 0; 279843e1988Sjohnlev shared[ref].domid = domid; 280843e1988Sjohnlev membar_producer(); 281843e1988Sjohnlev shared[ref].flags = GTF_accept_transfer; 282843e1988Sjohnlev 283843e1988Sjohnlev return (ref); 284843e1988Sjohnlev } 285843e1988Sjohnlev 286843e1988Sjohnlev void 287843e1988Sjohnlev gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid) 288843e1988Sjohnlev { 289843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 290843e1988Sjohnlev 291843e1988Sjohnlev shared[ref].frame = 0; 292843e1988Sjohnlev shared[ref].domid = domid; 293843e1988Sjohnlev membar_producer(); 294843e1988Sjohnlev shared[ref].flags = GTF_accept_transfer; 295843e1988Sjohnlev } 296843e1988Sjohnlev 297843e1988Sjohnlev gnttab_frame_t 298843e1988Sjohnlev gnttab_end_foreign_transfer_ref(grant_ref_t ref) 299843e1988Sjohnlev { 300843e1988Sjohnlev gnttab_frame_t frame; 301843e1988Sjohnlev uint16_t flags; 302843e1988Sjohnlev 303843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 304843e1988Sjohnlev 305843e1988Sjohnlev /* 306843e1988Sjohnlev * If a transfer is not even yet started, try to reclaim the grant 307843e1988Sjohnlev * reference and return failure (== 0). 308843e1988Sjohnlev */ 309843e1988Sjohnlev while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { 310843e1988Sjohnlev if (cmpxchg(&shared[ref].flags, flags, 0) == flags) 311843e1988Sjohnlev return (0); 312843e1988Sjohnlev (void) HYPERVISOR_yield(); 313843e1988Sjohnlev } 314843e1988Sjohnlev 315843e1988Sjohnlev /* If a transfer is in progress then wait until it is completed. */ 316843e1988Sjohnlev while (!(flags & GTF_transfer_completed)) { 317843e1988Sjohnlev flags = shared[ref].flags; 318843e1988Sjohnlev (void) HYPERVISOR_yield(); 319843e1988Sjohnlev } 320843e1988Sjohnlev 321843e1988Sjohnlev /* Read the frame number /after/ reading completion status. */ 322843e1988Sjohnlev membar_consumer(); 323843e1988Sjohnlev frame = shared[ref].frame; 324843e1988Sjohnlev ASSERT(frame != 0); 325843e1988Sjohnlev 326843e1988Sjohnlev return (frame); 327843e1988Sjohnlev } 328843e1988Sjohnlev 329843e1988Sjohnlev gnttab_frame_t 330843e1988Sjohnlev gnttab_end_foreign_transfer(grant_ref_t ref) 331843e1988Sjohnlev { 332843e1988Sjohnlev gnttab_frame_t frame; 333843e1988Sjohnlev 334843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 335843e1988Sjohnlev 336843e1988Sjohnlev frame = gnttab_end_foreign_transfer_ref(ref); 337843e1988Sjohnlev put_free_entry(ref); 338843e1988Sjohnlev return (frame); 339843e1988Sjohnlev } 340843e1988Sjohnlev 341843e1988Sjohnlev void 342843e1988Sjohnlev gnttab_free_grant_reference(grant_ref_t ref) 343843e1988Sjohnlev { 344843e1988Sjohnlev ASSERT(VALID_GRANT_REF(ref)); 345843e1988Sjohnlev 346843e1988Sjohnlev put_free_entry(ref); 347843e1988Sjohnlev } 348843e1988Sjohnlev 349843e1988Sjohnlev void 350843e1988Sjohnlev gnttab_free_grant_references(grant_ref_t head) 351843e1988Sjohnlev { 352843e1988Sjohnlev grant_ref_t ref; 353843e1988Sjohnlev int count = 1; 354843e1988Sjohnlev 355843e1988Sjohnlev if (head == GNTTAB_LIST_END) 356843e1988Sjohnlev return; 357843e1988Sjohnlev mutex_enter(&gnttab_list_lock); 358843e1988Sjohnlev ref = head; 359843e1988Sjohnlev while (gnttab_list[ref] != GNTTAB_LIST_END) { 360843e1988Sjohnlev ref = gnttab_list[ref]; 361843e1988Sjohnlev count++; 362843e1988Sjohnlev } 363843e1988Sjohnlev gnttab_list[ref] = gnttab_free_head; 364843e1988Sjohnlev gnttab_free_head = head; 365843e1988Sjohnlev gnttab_free_count += count; 366843e1988Sjohnlev check_free_callbacks(); 367843e1988Sjohnlev mutex_exit(&gnttab_list_lock); 368843e1988Sjohnlev } 369843e1988Sjohnlev 370843e1988Sjohnlev int 371843e1988Sjohnlev gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head) 372843e1988Sjohnlev { 373843e1988Sjohnlev int h = get_free_entries(count); 374843e1988Sjohnlev 375843e1988Sjohnlev if (h == -1) 376843e1988Sjohnlev return (-1); 377843e1988Sjohnlev 378843e1988Sjohnlev *head = h; 379843e1988Sjohnlev 380843e1988Sjohnlev return (0); 381843e1988Sjohnlev } 382843e1988Sjohnlev 383843e1988Sjohnlev int 384843e1988Sjohnlev gnttab_claim_grant_reference(grant_ref_t *private_head) 385843e1988Sjohnlev { 386843e1988Sjohnlev grant_ref_t g = *private_head; 387843e1988Sjohnlev 388843e1988Sjohnlev if (g == GNTTAB_LIST_END) 389843e1988Sjohnlev return (-1); 390843e1988Sjohnlev *private_head = gnttab_list[g]; 391843e1988Sjohnlev return (g); 392843e1988Sjohnlev } 393843e1988Sjohnlev 394843e1988Sjohnlev void 395843e1988Sjohnlev gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release) 396843e1988Sjohnlev { 397843e1988Sjohnlev ASSERT(VALID_GRANT_REF(release)); 398843e1988Sjohnlev 399843e1988Sjohnlev gnttab_list[release] = *private_head; 400843e1988Sjohnlev *private_head = release; 401843e1988Sjohnlev } 402843e1988Sjohnlev 403843e1988Sjohnlev void 404843e1988Sjohnlev gnttab_request_free_callback(struct gnttab_free_callback *callback, 405843e1988Sjohnlev void (*fn)(void *), void *arg, uint16_t count) 406843e1988Sjohnlev { 407843e1988Sjohnlev mutex_enter(&gnttab_list_lock); 408843e1988Sjohnlev if (callback->next) 409843e1988Sjohnlev goto out; 410843e1988Sjohnlev callback->fn = fn; 411843e1988Sjohnlev callback->arg = arg; 412843e1988Sjohnlev callback->count = count; 413843e1988Sjohnlev callback->next = gnttab_free_callback_list; 414843e1988Sjohnlev gnttab_free_callback_list = callback; 415843e1988Sjohnlev check_free_callbacks(); 416843e1988Sjohnlev out: 417843e1988Sjohnlev mutex_exit(&gnttab_list_lock); 418843e1988Sjohnlev } 419843e1988Sjohnlev 420*551bc2a6Smrj #ifdef XPV_HVM_DRIVER 421*551bc2a6Smrj 422*551bc2a6Smrj static void 423*551bc2a6Smrj gnttab_map(void) 424*551bc2a6Smrj { 425*551bc2a6Smrj struct xen_add_to_physmap xatp; 426*551bc2a6Smrj caddr_t va; 427*551bc2a6Smrj pfn_t pfn; 428*551bc2a6Smrj int i; 429*551bc2a6Smrj 430*551bc2a6Smrj va = (caddr_t)shared; 431*551bc2a6Smrj for (i = 0; i < NR_GRANT_FRAMES; i++) { 432*551bc2a6Smrj pfn = hat_getpfnum(kas.a_hat, va); 433*551bc2a6Smrj 434*551bc2a6Smrj xatp.domid = DOMID_SELF; 435*551bc2a6Smrj xatp.idx = i; 436*551bc2a6Smrj xatp.space = XENMAPSPACE_grant_table; 437*551bc2a6Smrj xatp.gpfn = pfn; 438*551bc2a6Smrj hat_unload(kas.a_hat, va, MMU_PAGESIZE, HAT_UNLOAD); 439*551bc2a6Smrj if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0) 440*551bc2a6Smrj panic("Couldn't map grant table"); 441*551bc2a6Smrj 442*551bc2a6Smrj hat_devload(kas.a_hat, va, MMU_PAGESIZE, pfn, 443*551bc2a6Smrj PROT_READ | PROT_WRITE, 444*551bc2a6Smrj HAT_LOAD | HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST); 445*551bc2a6Smrj 446*551bc2a6Smrj va += MMU_PAGESIZE; 447*551bc2a6Smrj } 448*551bc2a6Smrj } 449*551bc2a6Smrj 450*551bc2a6Smrj void 451*551bc2a6Smrj gnttab_init(void) 452*551bc2a6Smrj { 453*551bc2a6Smrj int i; 454*551bc2a6Smrj 455*551bc2a6Smrj shared = (grant_entry_t *)xen_alloc_pages(NR_GRANT_FRAMES); 456*551bc2a6Smrj 457*551bc2a6Smrj gnttab_map(); 458*551bc2a6Smrj 459*551bc2a6Smrj for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++) 460*551bc2a6Smrj gnttab_list[i] = i + 1; 461*551bc2a6Smrj gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES; 462*551bc2a6Smrj gnttab_free_head = NR_RESERVED_ENTRIES; 463*551bc2a6Smrj 464*551bc2a6Smrj mutex_init(&gnttab_list_lock, NULL, MUTEX_DEFAULT, NULL); 465*551bc2a6Smrj } 466*551bc2a6Smrj 467*551bc2a6Smrj void 468*551bc2a6Smrj gnttab_resume(void) 469*551bc2a6Smrj { 470*551bc2a6Smrj gnttab_map(); 471*551bc2a6Smrj } 472*551bc2a6Smrj 473*551bc2a6Smrj #else /* XPV_HVM_DRIVER */ 474*551bc2a6Smrj 475843e1988Sjohnlev void 476843e1988Sjohnlev gnttab_init(void) 477843e1988Sjohnlev { 478843e1988Sjohnlev gnttab_setup_table_t set; 479843e1988Sjohnlev gnttab_frame_t frames[NR_GRANT_FRAMES]; 480843e1988Sjohnlev int i; 481843e1988Sjohnlev 482843e1988Sjohnlev set.dom = DOMID_SELF; 483843e1988Sjohnlev set.nr_frames = NR_GRANT_FRAMES; 484843e1988Sjohnlev /*LINTED: constant in conditional context*/ 485843e1988Sjohnlev set_xen_guest_handle(set.frame_list, frames); 486843e1988Sjohnlev 487843e1988Sjohnlev /* 488843e1988Sjohnlev * Take 4 pages of grant table space from the hypervisor and map it 489843e1988Sjohnlev */ 490843e1988Sjohnlev if ((HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &set, 1) != 0) || 491843e1988Sjohnlev (set.status != 0)) { 492843e1988Sjohnlev cmn_err(CE_PANIC, "Grant Table setup failed"); 493843e1988Sjohnlev } 494843e1988Sjohnlev 495843e1988Sjohnlev shared = vmem_xalloc(heap_arena, NR_GRANT_FRAMES * MMU_PAGESIZE, 496843e1988Sjohnlev MMU_PAGESIZE, 0, 0, 0, 0, VM_SLEEP); 497843e1988Sjohnlev 498843e1988Sjohnlev for (i = 0; i < NR_GRANT_FRAMES; i++) 499843e1988Sjohnlev kbm_map_ma(FRAME_TO_MA(frames[i]), GT_PGADDR(i), 0); 500843e1988Sjohnlev 501843e1988Sjohnlev for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++) 502843e1988Sjohnlev gnttab_list[i] = i + 1; 503843e1988Sjohnlev gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES; 504843e1988Sjohnlev gnttab_free_head = NR_RESERVED_ENTRIES; 505843e1988Sjohnlev 506843e1988Sjohnlev mutex_init(&gnttab_list_lock, NULL, MUTEX_DEFAULT, NULL); 507843e1988Sjohnlev } 508843e1988Sjohnlev 509843e1988Sjohnlev void 510843e1988Sjohnlev gnttab_resume(void) 511843e1988Sjohnlev { 512843e1988Sjohnlev gnttab_setup_table_t set; 513843e1988Sjohnlev gnttab_frame_t frames[NR_GRANT_FRAMES]; 514843e1988Sjohnlev int i; 515843e1988Sjohnlev 516843e1988Sjohnlev set.dom = DOMID_SELF; 517843e1988Sjohnlev set.nr_frames = NR_GRANT_FRAMES; 518843e1988Sjohnlev /*LINTED: constant in conditional context*/ 519843e1988Sjohnlev set_xen_guest_handle(set.frame_list, frames); 520843e1988Sjohnlev 521843e1988Sjohnlev /* 522843e1988Sjohnlev * Take NR_GRANT_FRAMES pages of grant table space from the 523843e1988Sjohnlev * hypervisor and map it 524843e1988Sjohnlev */ 525843e1988Sjohnlev if ((HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &set, 1) != 0) || 526843e1988Sjohnlev (set.status != 0)) { 527843e1988Sjohnlev cmn_err(CE_PANIC, "Grant Table setup failed"); 528843e1988Sjohnlev } 529843e1988Sjohnlev 530843e1988Sjohnlev for (i = 0; i < NR_GRANT_FRAMES; i++) { 531843e1988Sjohnlev (void) HYPERVISOR_update_va_mapping(GT_PGADDR(i), 532843e1988Sjohnlev FRAME_TO_MA(frames[i]) | PT_VALID | PT_WRITABLE, 533843e1988Sjohnlev UVMF_INVLPG | UVMF_ALL); 534843e1988Sjohnlev } 535843e1988Sjohnlev } 536843e1988Sjohnlev 537*551bc2a6Smrj #endif /* XPV_HVM_DRIVER */ 538*551bc2a6Smrj 539843e1988Sjohnlev void 540843e1988Sjohnlev gnttab_suspend(void) 541843e1988Sjohnlev { 542843e1988Sjohnlev int i; 543843e1988Sjohnlev 544843e1988Sjohnlev /* 545843e1988Sjohnlev * clear grant table mappings before suspending 546843e1988Sjohnlev */ 547843e1988Sjohnlev for (i = 0; i < NR_GRANT_FRAMES; i++) { 548843e1988Sjohnlev (void) HYPERVISOR_update_va_mapping(GT_PGADDR(i), 549843e1988Sjohnlev 0, UVMF_INVLPG); 550843e1988Sjohnlev } 551843e1988Sjohnlev } 552843e1988Sjohnlev 553843e1988Sjohnlev /* 554843e1988Sjohnlev * Local variables: 555843e1988Sjohnlev * c-file-style: "solaris" 556843e1988Sjohnlev * indent-tabs-mode: t 557843e1988Sjohnlev * c-indent-level: 8 558843e1988Sjohnlev * c-basic-offset: 8 559843e1988Sjohnlev * tab-width: 8 560843e1988Sjohnlev * End: 561843e1988Sjohnlev */ 562