18d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata/****************************************************************************** 28d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * grant_table.c 38d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * x86 specific part 48d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * 58d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * Granting foreign access to our memory reservation. 68d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * 78d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * Copyright (c) 2005-2006, Christopher Clark 88d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * Copyright (c) 2004-2005, K A Fraser 98d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> 108d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * VA Linux Systems Japan. Split out x86 specific part. 118d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * 128d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * This program is free software; you can redistribute it and/or 138d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * modify it under the terms of the GNU General Public License version 2 148d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * as published by the Free Software Foundation; or, when distributed 158d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * separately from the Linux kernel or incorporated into other 168d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * software packages, subject to the following license: 178d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * 188d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * Permission is hereby granted, free of charge, to any person obtaining a copy 198d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * of this source file (the "Software"), to deal in the Software without 208d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * restriction, including without limitation the rights to use, copy, modify, 218d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * merge, publish, distribute, sublicense, and/or sell copies of the Software, 228d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * and to permit persons to whom the Software is furnished to do so, subject to 238d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * the following conditions: 248d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * 258d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * The above copyright notice and this permission notice shall be included in 268d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * all copies or substantial portions of the Software. 278d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * 288d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 298d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 308d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 318d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 328d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 338d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 348d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata * IN THE SOFTWARE. 358d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata */ 368d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata 378d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata#include <linux/sched.h> 388d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata#include <linux/mm.h> 39162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel#include <linux/slab.h> 408d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata#include <linux/vmalloc.h> 418d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata 428d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata#include <xen/interface/xen.h> 438d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata#include <xen/page.h> 448d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata#include <xen/grant_table.h> 45162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel#include <xen/xen.h> 468d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata 478d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata#include <asm/pgtable.h> 488d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata 49162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabelstatic struct gnttab_vm_area { 50162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel struct vm_struct *area; 51162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel pte_t **ptes; 52438b33c7145ca8a5131a30c36d8f59bce119a19aDavid Vrabel} gnttab_shared_vm_area; 53162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel 54162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabelint arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, 55162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel unsigned long max_nr_gframes, 56162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel void **__shared) 578d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata{ 58162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel void *shared = *__shared; 59162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel unsigned long addr; 60162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel unsigned long i; 618d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata 62162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel if (shared == NULL) 63162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel *__shared = shared = gnttab_shared_vm_area.area->addr; 648d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata 65162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel addr = (unsigned long)shared; 66162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel 67162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel for (i = 0; i < nr_gframes; i++) { 68162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel set_pte_at(&init_mm, addr, gnttab_shared_vm_area.ptes[i], 69162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel mfn_pte(frames[i], PAGE_KERNEL)); 70162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel addr += PAGE_SIZE; 71162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel } 7285ff6acb075a484780b3d763fdf41596d8fc0970Annie Li 7385ff6acb075a484780b3d763fdf41596d8fc0970Annie Li return 0; 7485ff6acb075a484780b3d763fdf41596d8fc0970Annie Li} 7585ff6acb075a484780b3d763fdf41596d8fc0970Annie Li 76162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabelvoid arch_gnttab_unmap(void *shared, unsigned long nr_gframes) 778d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata{ 78162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel unsigned long addr; 79162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel unsigned long i; 808d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata 81162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel addr = (unsigned long)shared; 82162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel 83162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel for (i = 0; i < nr_gframes; i++) { 84438b33c7145ca8a5131a30c36d8f59bce119a19aDavid Vrabel set_pte_at(&init_mm, addr, gnttab_shared_vm_area.ptes[i], 85438b33c7145ca8a5131a30c36d8f59bce119a19aDavid Vrabel __pte(0)); 86162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel addr += PAGE_SIZE; 87162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel } 888d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata} 898d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata 90162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabelstatic int arch_gnttab_valloc(struct gnttab_vm_area *area, unsigned nr_frames) 9185ff6acb075a484780b3d763fdf41596d8fc0970Annie Li{ 92162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel area->ptes = kmalloc(sizeof(pte_t *) * nr_frames, GFP_KERNEL); 93162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel if (area->ptes == NULL) 94162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel return -ENOMEM; 9585ff6acb075a484780b3d763fdf41596d8fc0970Annie Li 96162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel area->area = alloc_vm_area(PAGE_SIZE * nr_frames, area->ptes); 97162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel if (area->area == NULL) { 98162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel kfree(area->ptes); 99162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel return -ENOMEM; 10085ff6acb075a484780b3d763fdf41596d8fc0970Annie Li } 10185ff6acb075a484780b3d763fdf41596d8fc0970Annie Li 102162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel return 0; 10385ff6acb075a484780b3d763fdf41596d8fc0970Annie Li} 10485ff6acb075a484780b3d763fdf41596d8fc0970Annie Li 105438b33c7145ca8a5131a30c36d8f59bce119a19aDavid Vrabelint arch_gnttab_init(unsigned long nr_shared) 106162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel{ 107162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel if (!xen_pv_domain()) 108162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel return 0; 109162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel 110438b33c7145ca8a5131a30c36d8f59bce119a19aDavid Vrabel return arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared); 1118d3d2106c19f4e69f208f59fe484ca113fbb48b3Isaku Yamahata} 112162e371712768248a38646eefa71af38b6e0f8ceDavid Vrabel 1136926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk#ifdef CONFIG_XEN_PVH 1146926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk#include <xen/balloon.h> 1156926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk#include <xen/events.h> 1166926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk#include <linux/slab.h> 1176926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilkstatic int __init xlated_setup_gnttab_pages(void) 1186926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk{ 1196926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk struct page **pages; 1206926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk xen_pfn_t *pfns; 1217d951f3ccb0308c95bf76d5eef9886dea35a7013David Vrabel void *vaddr; 1226926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk int rc; 1236926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk unsigned int i; 1246926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk unsigned long nr_grant_frames = gnttab_max_grant_frames(); 1256926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk 1266926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk BUG_ON(nr_grant_frames == 0); 1276926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk pages = kcalloc(nr_grant_frames, sizeof(pages[0]), GFP_KERNEL); 1286926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk if (!pages) 1296926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk return -ENOMEM; 1306926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk 1316926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk pfns = kcalloc(nr_grant_frames, sizeof(pfns[0]), GFP_KERNEL); 1326926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk if (!pfns) { 1336926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk kfree(pages); 1346926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk return -ENOMEM; 1356926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk } 1366926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk rc = alloc_xenballooned_pages(nr_grant_frames, pages, 0 /* lowmem */); 1376926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk if (rc) { 1386926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk pr_warn("%s Couldn't balloon alloc %ld pfns rc:%d\n", __func__, 1396926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk nr_grant_frames, rc); 1406926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk kfree(pages); 1416926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk kfree(pfns); 1426926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk return rc; 1436926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk } 1446926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk for (i = 0; i < nr_grant_frames; i++) 1456926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk pfns[i] = page_to_pfn(pages[i]); 1466926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk 1477d951f3ccb0308c95bf76d5eef9886dea35a7013David Vrabel vaddr = vmap(pages, nr_grant_frames, 0, PAGE_KERNEL); 1487d951f3ccb0308c95bf76d5eef9886dea35a7013David Vrabel if (!vaddr) { 1496926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__, 1506926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk nr_grant_frames, rc); 1516926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk free_xenballooned_pages(nr_grant_frames, pages); 152f93576e1ac34fd7a93d6f3432e71295bbe6a27ceDave Jones kfree(pages); 1536926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk kfree(pfns); 1547d951f3ccb0308c95bf76d5eef9886dea35a7013David Vrabel return -ENOMEM; 1556926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk } 156f93576e1ac34fd7a93d6f3432e71295bbe6a27ceDave Jones kfree(pages); 1576926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk 1586926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk xen_auto_xlat_grant_frames.pfn = pfns; 1596926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk xen_auto_xlat_grant_frames.count = nr_grant_frames; 1607d951f3ccb0308c95bf76d5eef9886dea35a7013David Vrabel xen_auto_xlat_grant_frames.vaddr = vaddr; 1616926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk 1626926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk return 0; 1636926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk} 1646926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk 1656926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilkstatic int __init xen_pvh_gnttab_setup(void) 1666926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk{ 1676926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk if (!xen_pvh_domain()) 1686926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk return -ENODEV; 1696926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk 1706926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk return xlated_setup_gnttab_pages(); 1716926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk} 1726926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk/* Call it _before_ __gnttab_init as we need to initialize the 1736926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk * xen_auto_xlat_grant_frames first. */ 1746926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilkcore_initcall(xen_pvh_gnttab_setup); 1756926f6d6109714aab7b26df7099b12555e36676fKonrad Rzeszutek Wilk#endif 176