15741Smrj /* 25741Smrj * CDDL HEADER START 35741Smrj * 45741Smrj * The contents of this file are subject to the terms of the 55741Smrj * Common Development and Distribution License (the "License"). 65741Smrj * You may not use this file except in compliance with the License. 75741Smrj * 85741Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95741Smrj * or http://www.opensolaris.org/os/licensing. 105741Smrj * See the License for the specific language governing permissions 115741Smrj * and limitations under the License. 125741Smrj * 135741Smrj * When distributing Covered Code, include this CDDL HEADER in each 145741Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155741Smrj * If applicable, add the following below this CDDL HEADER, with the 165741Smrj * fields enclosed by brackets "[]" replaced with your own identifying 175741Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 185741Smrj * 195741Smrj * CDDL HEADER END 205741Smrj */ 215741Smrj 225741Smrj /* 23*6144Srab * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 245741Smrj * Use is subject to license terms. 255741Smrj */ 265741Smrj 275741Smrj #pragma ident "%Z%%M% %I% %E% SMI" 285741Smrj 295741Smrj /* 305741Smrj * gnttab.c 315741Smrj * 325741Smrj * Granting foreign access to our memory reservation. 335741Smrj * 34*6144Srab * Copyright (c) 2005-2006, Christopher Clark 355741Smrj * Copyright (c) 2004-2005, K A Fraser 365741Smrj * 37*6144Srab * This program is free software; you can redistribute it and/or 38*6144Srab * modify it under the terms of the GNU General Public License version 2 39*6144Srab * as published by the Free Software Foundation; or, when distributed 40*6144Srab * separately from the Linux kernel or incorporated into other 41*6144Srab * software packages, subject to the following license: 425741Smrj * 435741Smrj * Permission is hereby granted, free of charge, to any person obtaining a copy 445741Smrj * of this source file (the "Software"), to deal in the Software without 455741Smrj * restriction, including without limitation the rights to use, copy, modify, 465741Smrj * merge, publish, distribute, sublicense, and/or sell copies of the Software, 475741Smrj * and to permit persons to whom the Software is furnished to do so, subject to 485741Smrj * the following conditions: 495741Smrj * 505741Smrj * The above copyright notice and this permission notice shall be included in 515741Smrj * all copies or substantial portions of the Software. 525741Smrj * 535741Smrj * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 545741Smrj * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 555741Smrj * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 565741Smrj * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 575741Smrj * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 585741Smrj * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 595741Smrj * IN THE SOFTWARE. 605741Smrj */ 615741Smrj 625741Smrj #include <sys/types.h> 635741Smrj #include <sys/archsystm.h> 645741Smrj #ifdef XPV_HVM_DRIVER 655741Smrj #include <sys/xpv_support.h> 665741Smrj #include <sys/mman.h> 675741Smrj #include <vm/hat.h> 685741Smrj #endif 695741Smrj #include <sys/hypervisor.h> 705741Smrj #include <sys/gnttab.h> 715741Smrj #include <sys/sysmacros.h> 725741Smrj #include <sys/machsystm.h> 735741Smrj #include <sys/systm.h> 745741Smrj #include <sys/mutex.h> 755741Smrj #include <sys/atomic.h> 765741Smrj #include <sys/spl.h> 775741Smrj #include <sys/condvar.h> 785741Smrj #include <sys/cpuvar.h> 795741Smrj #include <sys/taskq.h> 805741Smrj #include <sys/panic.h> 815741Smrj #include <sys/cmn_err.h> 825741Smrj #include <sys/promif.h> 835741Smrj #include <sys/cpu.h> 845741Smrj #include <sys/vmem.h> 855741Smrj #include <vm/hat_i86.h> 865741Smrj #include <sys/bootconf.h> 875741Smrj #include <sys/bootsvcs.h> 885741Smrj #ifndef XPV_HVM_DRIVER 895741Smrj #include <sys/bootinfo.h> 905741Smrj #include <sys/multiboot.h> 915741Smrj #include <vm/kboot_mmu.h> 925741Smrj #endif 935741Smrj #include <sys/bootvfs.h> 945741Smrj #include <sys/bootprops.h> 955741Smrj #include <vm/seg_kmem.h> 96*6144Srab #include <sys/mman.h> 975741Smrj 98*6144Srab /* Globals */ 995741Smrj 100*6144Srab static grant_ref_t **gnttab_list; 101*6144Srab static uint_t nr_grant_frames; 1025741Smrj static int gnttab_free_count; 1035741Smrj static grant_ref_t gnttab_free_head; 1045741Smrj static kmutex_t gnttab_list_lock; 105*6144Srab static grant_entry_t *shared; 106*6144Srab static struct gnttab_free_callback *gnttab_free_callback_list; 1075741Smrj 108*6144Srab /* Macros */ 1095741Smrj 110*6144Srab #define GT_PGADDR(i) ((uintptr_t)shared + ((i) << MMU_PAGESHIFT)) 111*6144Srab #define VALID_GRANT_REF(r) ((r) < (nr_grant_frames * GREFS_PER_GRANT_FRAME)) 112*6144Srab #define RPP (PAGESIZE / sizeof (grant_ref_t)) 113*6144Srab #define GNTTAB_ENTRY(entry) (gnttab_list[(entry) / RPP][(entry) % RPP]) 114*6144Srab #define CMPXCHG(t, c, n) atomic_cas_16((t), (c), (n)) 115*6144Srab /* External tools reserve first few grant table entries. */ 116*6144Srab #define NR_RESERVED_ENTRIES 8 117*6144Srab #define GNTTAB_LIST_END 0xffffffff 118*6144Srab #define GREFS_PER_GRANT_FRAME (PAGESIZE / sizeof (grant_entry_t)) 1195741Smrj 120*6144Srab /* Implementation */ 121*6144Srab 122*6144Srab static uint_t 123*6144Srab max_nr_grant_frames(void) 124*6144Srab { 125*6144Srab struct gnttab_query_size query; 126*6144Srab int rc; 127*6144Srab 128*6144Srab query.dom = DOMID_SELF; 129*6144Srab 130*6144Srab rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1); 131*6144Srab if ((rc < 0) || (query.status != GNTST_okay)) 132*6144Srab return (4); /* Legacy max supported number of frames */ 133*6144Srab 134*6144Srab ASSERT(query.max_nr_frames); 135*6144Srab return (query.max_nr_frames); 1365741Smrj } 1375741Smrj 1385741Smrj static void 1395741Smrj do_free_callbacks(void) 1405741Smrj { 1415741Smrj struct gnttab_free_callback *callback, *next; 1425741Smrj 1435741Smrj callback = gnttab_free_callback_list; 1445741Smrj gnttab_free_callback_list = NULL; 1455741Smrj 1465741Smrj while (callback != NULL) { 1475741Smrj next = callback->next; 1485741Smrj if (gnttab_free_count >= callback->count) { 1495741Smrj callback->next = NULL; 1505741Smrj callback->fn(callback->arg); 1515741Smrj } else { 1525741Smrj callback->next = gnttab_free_callback_list; 1535741Smrj gnttab_free_callback_list = callback; 1545741Smrj } 1555741Smrj callback = next; 1565741Smrj } 1575741Smrj } 1585741Smrj 1595741Smrj static void 1605741Smrj check_free_callbacks(void) 1615741Smrj { 1625741Smrj if (gnttab_free_callback_list) 1635741Smrj do_free_callbacks(); 1645741Smrj } 1655741Smrj 166*6144Srab static int 167*6144Srab grow_gnttab_list(uint_t more_frames) 168*6144Srab { 169*6144Srab uint_t new_nr_grant_frames, extra_entries, i; 170*6144Srab 171*6144Srab ASSERT(MUTEX_HELD(&gnttab_list_lock)); 172*6144Srab 173*6144Srab new_nr_grant_frames = nr_grant_frames + more_frames; 174*6144Srab extra_entries = more_frames * GREFS_PER_GRANT_FRAME; 175*6144Srab 176*6144Srab for (i = nr_grant_frames; i < new_nr_grant_frames; i++) 177*6144Srab gnttab_list[i] = kmem_alloc(PAGESIZE, KM_SLEEP); 178*6144Srab 179*6144Srab for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; 180*6144Srab i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) 181*6144Srab GNTTAB_ENTRY(i) = i + 1; 182*6144Srab 183*6144Srab GNTTAB_ENTRY(i) = gnttab_free_head; 184*6144Srab gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; 185*6144Srab gnttab_free_count += extra_entries; 186*6144Srab 187*6144Srab nr_grant_frames = new_nr_grant_frames; 188*6144Srab 189*6144Srab check_free_callbacks(); 190*6144Srab 191*6144Srab return (0); 192*6144Srab } 193*6144Srab 194*6144Srab static int 195*6144Srab gnttab_expand(uint_t req_entries) 196*6144Srab { 197*6144Srab uint_t cur, extra; 198*6144Srab 199*6144Srab ASSERT(MUTEX_HELD(&gnttab_list_lock)); 200*6144Srab 201*6144Srab cur = nr_grant_frames; 202*6144Srab extra = ((req_entries + (GREFS_PER_GRANT_FRAME - 1)) / 203*6144Srab GREFS_PER_GRANT_FRAME); 204*6144Srab if (cur + extra > max_nr_grant_frames()) 205*6144Srab return (-1); 206*6144Srab 207*6144Srab return (grow_gnttab_list(extra)); 208*6144Srab } 209*6144Srab 210*6144Srab static int 211*6144Srab get_free_entries(int count) 212*6144Srab { 213*6144Srab int ref, rc; 214*6144Srab grant_ref_t head; 215*6144Srab 216*6144Srab mutex_enter(&gnttab_list_lock); 217*6144Srab if (gnttab_free_count < count && 218*6144Srab ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) { 219*6144Srab mutex_exit(&gnttab_list_lock); 220*6144Srab return (rc); 221*6144Srab } 222*6144Srab ref = head = gnttab_free_head; 223*6144Srab gnttab_free_count -= count; 224*6144Srab while (count-- > 1) 225*6144Srab head = GNTTAB_ENTRY(head); 226*6144Srab gnttab_free_head = GNTTAB_ENTRY(head); 227*6144Srab GNTTAB_ENTRY(head) = GNTTAB_LIST_END; 228*6144Srab mutex_exit(&gnttab_list_lock); 229*6144Srab return (ref); 230*6144Srab } 231*6144Srab 2325741Smrj static void 2335741Smrj put_free_entry(grant_ref_t ref) 2345741Smrj { 2355741Smrj ASSERT(VALID_GRANT_REF(ref)); 2365741Smrj 2375741Smrj mutex_enter(&gnttab_list_lock); 238*6144Srab GNTTAB_ENTRY(ref) = gnttab_free_head; 2395741Smrj gnttab_free_head = ref; 2405741Smrj gnttab_free_count++; 2415741Smrj check_free_callbacks(); 2425741Smrj mutex_exit(&gnttab_list_lock); 2435741Smrj } 2445741Smrj 2455741Smrj /* 2465741Smrj * Public grant-issuing interface functions 2475741Smrj */ 2485741Smrj 2495741Smrj int 2505741Smrj gnttab_grant_foreign_access(domid_t domid, gnttab_frame_t frame, int readonly) 2515741Smrj { 2525741Smrj int ref; 2535741Smrj 254*6144Srab if ((ref = get_free_entries(1)) == -1) 2555741Smrj return (-1); 2565741Smrj 2575741Smrj ASSERT(VALID_GRANT_REF(ref)); 2585741Smrj 2595741Smrj shared[ref].frame = frame; 2605741Smrj shared[ref].domid = domid; 2615741Smrj membar_producer(); 2625741Smrj shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); 2635741Smrj 2645741Smrj return (ref); 2655741Smrj } 2665741Smrj 2675741Smrj void 2685741Smrj gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, 2695741Smrj gnttab_frame_t frame, int readonly) 2705741Smrj { 2715741Smrj ASSERT(VALID_GRANT_REF(ref)); 2725741Smrj 2735741Smrj shared[ref].frame = frame; 2745741Smrj shared[ref].domid = domid; 2755741Smrj membar_producer(); 2765741Smrj shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); 2775741Smrj } 2785741Smrj 2795741Smrj 2805741Smrj int 2815741Smrj gnttab_query_foreign_access(grant_ref_t ref) 2825741Smrj { 2835741Smrj uint16_t nflags; 2845741Smrj 2855741Smrj ASSERT(VALID_GRANT_REF(ref)); 2865741Smrj 2875741Smrj nflags = shared[ref].flags; 2885741Smrj 2895741Smrj return (nflags & (GTF_reading|GTF_writing)); 2905741Smrj } 2915741Smrj 2925741Smrj /* ARGSUSED */ 2935741Smrj int 2945741Smrj gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) 2955741Smrj { 2965741Smrj uint16_t flags, nflags; 2975741Smrj 2985741Smrj ASSERT(VALID_GRANT_REF(ref)); 2995741Smrj 3005741Smrj nflags = shared[ref].flags; 3015741Smrj do { 3025741Smrj if ((flags = nflags) & (GTF_reading|GTF_writing)) { 3035741Smrj cmn_err(CE_WARN, "g.e. still in use!"); 3045741Smrj return (0); 3055741Smrj } 306*6144Srab } while ((nflags = CMPXCHG(&shared[ref].flags, flags, 0)) != flags); 3075741Smrj 3085741Smrj return (1); 3095741Smrj } 3105741Smrj 3115741Smrj void 3125741Smrj gnttab_end_foreign_access(grant_ref_t ref, int readonly, gnttab_frame_t page) 3135741Smrj { 3145741Smrj ASSERT(VALID_GRANT_REF(ref)); 3155741Smrj 3165741Smrj if (gnttab_end_foreign_access_ref(ref, readonly)) { 3175741Smrj put_free_entry(ref); 3185741Smrj /* 3195741Smrj * XXPV - we don't support freeing a page here 3205741Smrj */ 3215741Smrj if (page != 0) { 3225741Smrj cmn_err(CE_WARN, 3235741Smrj "gnttab_end_foreign_access_ref: using unsupported free_page interface"); 3245741Smrj /* free_page(page); */ 3255741Smrj } 3265741Smrj } else { 3275741Smrj /* 3285741Smrj * XXX This needs to be fixed so that the ref and page are 3295741Smrj * placed on a list to be freed up later. 3305741Smrj */ 3315741Smrj cmn_err(CE_WARN, "leaking g.e. and page still in use!"); 3325741Smrj } 3335741Smrj } 3345741Smrj 3355741Smrj int 336*6144Srab gnttab_grant_foreign_transfer(domid_t domid, pfn_t pfn) 3375741Smrj { 3385741Smrj int ref; 3395741Smrj 340*6144Srab if ((ref = get_free_entries(1)) == -1) 3415741Smrj return (-1); 3425741Smrj 3435741Smrj ASSERT(VALID_GRANT_REF(ref)); 3445741Smrj 345*6144Srab gnttab_grant_foreign_transfer_ref(ref, domid, pfn); 3465741Smrj 3475741Smrj return (ref); 3485741Smrj } 3495741Smrj 3505741Smrj void 351*6144Srab gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid, pfn_t pfn) 3525741Smrj { 3535741Smrj ASSERT(VALID_GRANT_REF(ref)); 3545741Smrj 355*6144Srab shared[ref].frame = pfn; 3565741Smrj shared[ref].domid = domid; 3575741Smrj membar_producer(); 3585741Smrj shared[ref].flags = GTF_accept_transfer; 3595741Smrj } 3605741Smrj 3615741Smrj gnttab_frame_t 3625741Smrj gnttab_end_foreign_transfer_ref(grant_ref_t ref) 3635741Smrj { 3645741Smrj gnttab_frame_t frame; 3655741Smrj uint16_t flags; 3665741Smrj 3675741Smrj ASSERT(VALID_GRANT_REF(ref)); 3685741Smrj 3695741Smrj /* 3705741Smrj * If a transfer is not even yet started, try to reclaim the grant 3715741Smrj * reference and return failure (== 0). 3725741Smrj */ 3735741Smrj while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { 374*6144Srab if (CMPXCHG(&shared[ref].flags, flags, 0) == flags) 3755741Smrj return (0); 3765741Smrj (void) HYPERVISOR_yield(); 3775741Smrj } 3785741Smrj 3795741Smrj /* If a transfer is in progress then wait until it is completed. */ 3805741Smrj while (!(flags & GTF_transfer_completed)) { 3815741Smrj flags = shared[ref].flags; 3825741Smrj (void) HYPERVISOR_yield(); 3835741Smrj } 3845741Smrj 3855741Smrj /* Read the frame number /after/ reading completion status. */ 3865741Smrj membar_consumer(); 3875741Smrj frame = shared[ref].frame; 3885741Smrj ASSERT(frame != 0); 3895741Smrj 3905741Smrj return (frame); 3915741Smrj } 3925741Smrj 3935741Smrj gnttab_frame_t 3945741Smrj gnttab_end_foreign_transfer(grant_ref_t ref) 3955741Smrj { 3965741Smrj gnttab_frame_t frame; 3975741Smrj 3985741Smrj ASSERT(VALID_GRANT_REF(ref)); 3995741Smrj 4005741Smrj frame = gnttab_end_foreign_transfer_ref(ref); 4015741Smrj put_free_entry(ref); 4025741Smrj return (frame); 4035741Smrj } 4045741Smrj 4055741Smrj void 4065741Smrj gnttab_free_grant_reference(grant_ref_t ref) 4075741Smrj { 4085741Smrj ASSERT(VALID_GRANT_REF(ref)); 4095741Smrj 4105741Smrj put_free_entry(ref); 4115741Smrj } 4125741Smrj 4135741Smrj void 4145741Smrj gnttab_free_grant_references(grant_ref_t head) 4155741Smrj { 4165741Smrj grant_ref_t ref; 4175741Smrj int count = 1; 4185741Smrj 4195741Smrj if (head == GNTTAB_LIST_END) 4205741Smrj return; 4215741Smrj mutex_enter(&gnttab_list_lock); 4225741Smrj ref = head; 423*6144Srab while (GNTTAB_ENTRY(ref) != GNTTAB_LIST_END) { 424*6144Srab ref = GNTTAB_ENTRY(ref); 4255741Smrj count++; 4265741Smrj } 427*6144Srab GNTTAB_ENTRY(ref) = gnttab_free_head; 4285741Smrj gnttab_free_head = head; 4295741Smrj gnttab_free_count += count; 4305741Smrj check_free_callbacks(); 4315741Smrj mutex_exit(&gnttab_list_lock); 4325741Smrj } 4335741Smrj 4345741Smrj int 4355741Smrj gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head) 4365741Smrj { 4375741Smrj int h = get_free_entries(count); 4385741Smrj 4395741Smrj if (h == -1) 4405741Smrj return (-1); 4415741Smrj 4425741Smrj *head = h; 4435741Smrj 4445741Smrj return (0); 4455741Smrj } 4465741Smrj 4475741Smrj int 448*6144Srab gnttab_empty_grant_references(const grant_ref_t *private_head) 449*6144Srab { 450*6144Srab return (*private_head == GNTTAB_LIST_END); 451*6144Srab } 452*6144Srab 453*6144Srab int 4545741Smrj gnttab_claim_grant_reference(grant_ref_t *private_head) 4555741Smrj { 4565741Smrj grant_ref_t g = *private_head; 4575741Smrj 4585741Smrj if (g == GNTTAB_LIST_END) 4595741Smrj return (-1); 460*6144Srab *private_head = GNTTAB_ENTRY(g); 4615741Smrj return (g); 4625741Smrj } 4635741Smrj 4645741Smrj void 4655741Smrj gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release) 4665741Smrj { 4675741Smrj ASSERT(VALID_GRANT_REF(release)); 4685741Smrj 469*6144Srab GNTTAB_ENTRY(release) = *private_head; 4705741Smrj *private_head = release; 4715741Smrj } 4725741Smrj 4735741Smrj void 4745741Smrj gnttab_request_free_callback(struct gnttab_free_callback *callback, 4755741Smrj void (*fn)(void *), void *arg, uint16_t count) 4765741Smrj { 4775741Smrj mutex_enter(&gnttab_list_lock); 4785741Smrj if (callback->next) 4795741Smrj goto out; 4805741Smrj callback->fn = fn; 4815741Smrj callback->arg = arg; 4825741Smrj callback->count = count; 4835741Smrj callback->next = gnttab_free_callback_list; 4845741Smrj gnttab_free_callback_list = callback; 4855741Smrj check_free_callbacks(); 4865741Smrj out: 4875741Smrj mutex_exit(&gnttab_list_lock); 4885741Smrj } 4895741Smrj 490*6144Srab void 491*6144Srab gnttab_cancel_free_callback(struct gnttab_free_callback *callback) 492*6144Srab { 493*6144Srab struct gnttab_free_callback **pcb; 494*6144Srab 495*6144Srab mutex_enter(&gnttab_list_lock); 496*6144Srab for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) { 497*6144Srab if (*pcb == callback) { 498*6144Srab *pcb = callback->next; 499*6144Srab break; 500*6144Srab } 501*6144Srab } 502*6144Srab mutex_exit(&gnttab_list_lock); 503*6144Srab } 504*6144Srab 505*6144Srab static gnttab_frame_t * 506*6144Srab gnttab_setup(gnttab_setup_table_t *pset) 507*6144Srab { 508*6144Srab gnttab_frame_t *frames; 509*6144Srab 510*6144Srab frames = kmem_alloc(pset->nr_frames * sizeof (gnttab_frame_t), 511*6144Srab KM_SLEEP); 512*6144Srab 513*6144Srab /*LINTED: constant in conditional context*/ 514*6144Srab set_xen_guest_handle(pset->frame_list, frames); 515*6144Srab 516*6144Srab /* 517*6144Srab * Take pset->nr_frames pages of grant table space from 518*6144Srab * the hypervisor and map it 519*6144Srab */ 520*6144Srab if ((HYPERVISOR_grant_table_op(GNTTABOP_setup_table, pset, 1) != 0) || 521*6144Srab (pset->status != 0)) { 522*6144Srab cmn_err(CE_PANIC, "Grant Table setup failed"); 523*6144Srab } 524*6144Srab 525*6144Srab return (frames); 526*6144Srab } 527*6144Srab 5285741Smrj #ifdef XPV_HVM_DRIVER 5295741Smrj static void 5305741Smrj gnttab_map(void) 5315741Smrj { 5325741Smrj struct xen_add_to_physmap xatp; 5335741Smrj caddr_t va; 5345741Smrj pfn_t pfn; 5355741Smrj int i; 5365741Smrj 5375741Smrj va = (caddr_t)shared; 538*6144Srab for (i = 0; i < max_nr_grant_frames(); i++) { 539*6144Srab if ((pfn = hat_getpfnum(kas.a_hat, va)) == PFN_INVALID) 540*6144Srab cmn_err(CE_PANIC, "gnttab_map: Invalid pfn"); 5415741Smrj 5425741Smrj xatp.domid = DOMID_SELF; 5435741Smrj xatp.idx = i; 5445741Smrj xatp.space = XENMAPSPACE_grant_table; 5455741Smrj xatp.gpfn = pfn; 5465741Smrj hat_unload(kas.a_hat, va, MMU_PAGESIZE, HAT_UNLOAD); 547*6144Srab /* 548*6144Srab * This call replaces the existing machine page backing 549*6144Srab * the given gpfn with the page from the allocated grant 550*6144Srab * table at index idx. The existing machine page is 551*6144Srab * returned to the free list. 552*6144Srab */ 5535741Smrj if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0) 5545741Smrj panic("Couldn't map grant table"); 5555741Smrj hat_devload(kas.a_hat, va, MMU_PAGESIZE, pfn, 5565741Smrj PROT_READ | PROT_WRITE, 5575741Smrj HAT_LOAD | HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST); 5585741Smrj va += MMU_PAGESIZE; 5595741Smrj } 5605741Smrj } 561*6144Srab #endif /* XPV_HVM_DRIVER */ 5625741Smrj 5635741Smrj void 5645741Smrj gnttab_init(void) 5655741Smrj { 5665741Smrj gnttab_setup_table_t set; 5675741Smrj int i; 568*6144Srab uint_t nr_init_grefs, max_nr_glist_frames; 569*6144Srab gnttab_frame_t *frames; 5705741Smrj 5715741Smrj /* 572*6144Srab * gnttab_init() should only be invoked once. 5735741Smrj */ 574*6144Srab mutex_enter(&gnttab_list_lock); 575*6144Srab ASSERT(nr_grant_frames == 0); 576*6144Srab nr_grant_frames = 1; 577*6144Srab mutex_exit(&gnttab_list_lock); 578*6144Srab 579*6144Srab max_nr_glist_frames = (max_nr_grant_frames() * 580*6144Srab GREFS_PER_GRANT_FRAME / (PAGESIZE / sizeof (grant_ref_t))); 581*6144Srab 582*6144Srab set.dom = DOMID_SELF; 583*6144Srab set.nr_frames = max_nr_grant_frames(); 584*6144Srab frames = gnttab_setup(&set); 585*6144Srab 586*6144Srab #ifdef XPV_HVM_DRIVER 587*6144Srab shared = (grant_entry_t *)xen_alloc_pages(set.nr_frames); 588*6144Srab 589*6144Srab gnttab_map(); 590*6144Srab #else /* XPV_HVM_DRIVER */ 591*6144Srab shared = vmem_xalloc(heap_arena, set.nr_frames * MMU_PAGESIZE, 592*6144Srab MMU_PAGESIZE, 0, 0, 0, 0, VM_SLEEP); 593*6144Srab for (i = 0; i < set.nr_frames; i++) { 594*6144Srab hat_devload(kas.a_hat, (caddr_t)GT_PGADDR(i), PAGESIZE, 595*6144Srab xen_assign_pfn(frames[i]), PROT_READ | PROT_WRITE, 596*6144Srab HAT_LOAD_LOCK); 597*6144Srab } 598*6144Srab #endif 599*6144Srab 600*6144Srab gnttab_list = kmem_alloc(max_nr_glist_frames * sizeof (grant_ref_t *), 601*6144Srab KM_SLEEP); 602*6144Srab 603*6144Srab for (i = 0; i < nr_grant_frames; i++) { 604*6144Srab gnttab_list[i] = kmem_alloc(PAGESIZE, KM_SLEEP); 6055741Smrj } 6065741Smrj 607*6144Srab kmem_free(frames, set.nr_frames * sizeof (gnttab_frame_t)); 6085741Smrj 609*6144Srab nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; 6105741Smrj 611*6144Srab for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) 612*6144Srab GNTTAB_ENTRY(i) = i + 1; 613*6144Srab 614*6144Srab GNTTAB_ENTRY(nr_init_grefs - 1) = GNTTAB_LIST_END; 615*6144Srab gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES; 6165741Smrj gnttab_free_head = NR_RESERVED_ENTRIES; 6175741Smrj } 6185741Smrj 6195741Smrj void 6205741Smrj gnttab_resume(void) 6215741Smrj { 6225741Smrj gnttab_setup_table_t set; 6235741Smrj int i; 624*6144Srab gnttab_frame_t *frames; 625*6144Srab uint_t available_frames = max_nr_grant_frames(); 626*6144Srab 627*6144Srab if (available_frames < nr_grant_frames) { 628*6144Srab cmn_err(CE_PANIC, "Hypervisor does not have enough grant " 629*6144Srab "frames: required(%u), available(%u)", nr_grant_frames, 630*6144Srab available_frames); 631*6144Srab } 632*6144Srab 633*6144Srab #ifdef XPV_HVM_DRIVER 634*6144Srab gnttab_map(); 635*6144Srab #endif /* XPV_HVM_DRIVER */ 6365741Smrj 6375741Smrj set.dom = DOMID_SELF; 638*6144Srab set.nr_frames = available_frames; 639*6144Srab frames = gnttab_setup(&set); 6405741Smrj 641*6144Srab for (i = 0; i < available_frames; i++) { 6425741Smrj (void) HYPERVISOR_update_va_mapping(GT_PGADDR(i), 6435741Smrj FRAME_TO_MA(frames[i]) | PT_VALID | PT_WRITABLE, 6445741Smrj UVMF_INVLPG | UVMF_ALL); 6455741Smrj } 646*6144Srab kmem_free(frames, set.nr_frames * sizeof (gnttab_frame_t)); 6475741Smrj } 6485741Smrj 6495741Smrj void 6505741Smrj gnttab_suspend(void) 6515741Smrj { 6525741Smrj int i; 6535741Smrj 6545741Smrj /* 6555741Smrj * clear grant table mappings before suspending 6565741Smrj */ 657*6144Srab for (i = 0; i < max_nr_grant_frames(); i++) { 6585741Smrj (void) HYPERVISOR_update_va_mapping(GT_PGADDR(i), 6595741Smrj 0, UVMF_INVLPG); 6605741Smrj } 6615741Smrj } 6625741Smrj 6635741Smrj /* 6645741Smrj * Local variables: 6655741Smrj * c-file-style: "solaris" 6665741Smrj * indent-tabs-mode: t 6675741Smrj * c-indent-level: 8 6685741Smrj * c-basic-offset: 8 6695741Smrj * tab-width: 8 6705741Smrj * End: 6715741Smrj */ 672