^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0 OR MIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * grant_table.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * x86 specific part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Granting foreign access to our memory reservation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2005-2006, Christopher Clark
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2004-2005, K A Fraser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * VA Linux Systems Japan. Split out x86 specific part.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <xen/interface/xen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <xen/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <xen/grant_table.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <xen/xen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static struct gnttab_vm_area {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct vm_struct *area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) pte_t **ptes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) } gnttab_shared_vm_area, gnttab_status_vm_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) unsigned long max_nr_gframes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) void **__shared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) void *shared = *__shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (shared == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *__shared = shared = gnttab_shared_vm_area.area->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) addr = (unsigned long)shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) for (i = 0; i < nr_gframes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) set_pte_at(&init_mm, addr, gnttab_shared_vm_area.ptes[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) mfn_pte(frames[i], PAGE_KERNEL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) addr += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned long max_nr_gframes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) grant_status_t **__shared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) grant_status_t *shared = *__shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (shared == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *__shared = shared = gnttab_status_vm_area.area->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) addr = (unsigned long)shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) for (i = 0; i < nr_gframes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) set_pte_at(&init_mm, addr, gnttab_status_vm_area.ptes[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) mfn_pte(frames[i], PAGE_KERNEL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) addr += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pte_t **ptes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (shared == gnttab_status_vm_area.area->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ptes = gnttab_status_vm_area.ptes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ptes = gnttab_shared_vm_area.ptes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) addr = (unsigned long)shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) for (i = 0; i < nr_gframes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) set_pte_at(&init_mm, addr, ptes[i], __pte(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) addr += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int gnttab_apply(pte_t *pte, unsigned long addr, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct gnttab_vm_area *area = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) area->ptes[area->idx++] = pte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int arch_gnttab_valloc(struct gnttab_vm_area *area, unsigned nr_frames)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) area->ptes = kmalloc_array(nr_frames, sizeof(*area->ptes), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (area->ptes == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) area->area = get_vm_area(PAGE_SIZE * nr_frames, VM_IOREMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (!area->area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) goto out_free_ptes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (apply_to_page_range(&init_mm, (unsigned long)area->area->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) PAGE_SIZE * nr_frames, gnttab_apply, area))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) goto out_free_vm_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) out_free_vm_area:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) free_vm_area(area->area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) out_free_ptes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) kfree(area->ptes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void arch_gnttab_vfree(struct gnttab_vm_area *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) free_vm_area(area->area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) kfree(area->ptes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (!xen_pv_domain())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Always allocate the space for the status frames in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * we're migrated to a host with V2 support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ret = arch_gnttab_valloc(&gnttab_status_vm_area, nr_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) arch_gnttab_vfree(&gnttab_shared_vm_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #ifdef CONFIG_XEN_PVH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #include <xen/events.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #include <xen/xen-ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int __init xen_pvh_gnttab_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (!xen_pvh_domain())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) xen_auto_xlat_grant_frames.count = gnttab_max_grant_frames();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return xen_xlate_map_ballooned_pages(&xen_auto_xlat_grant_frames.pfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) &xen_auto_xlat_grant_frames.vaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) xen_auto_xlat_grant_frames.count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* Call it _before_ __gnttab_init as we need to initialize the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * xen_auto_xlat_grant_frames first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) core_initcall(xen_pvh_gnttab_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #endif