Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * MMU operations common to all auto-translated physmap guests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2015 Citrix Systems R&D Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * This program is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * modify it under the terms of the GNU General Public License version 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * as published by the Free Software Foundation; or, when distributed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * separately from the Linux kernel or incorporated into other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * software packages, subject to the following license:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * Permission is hereby granted, free of charge, to any person obtaining a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * of this source file (the "Software"), to deal in the Software without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * restriction, including without limitation the rights to use, copy, modify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * and to permit persons to whom the Software is furnished to do so, subject to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * the following conditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * The above copyright notice and this permission notice shall be included in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * all copies or substantial portions of the Software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * IN THE SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <asm/xen/hypercall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <asm/xen/hypervisor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include <xen/xen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #include <xen/xen-ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #include <xen/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #include <xen/interface/xen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #include <xen/interface/memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #include <xen/balloon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) typedef void (*xen_gfn_fn_t)(unsigned long gfn, void *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) /* Break down the pages in 4KB chunk and call fn for each gfn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) static void xen_for_each_gfn(struct page **pages, unsigned nr_gfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			     xen_gfn_fn_t fn, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned long xen_pfn = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	for (i = 0; i < nr_gfn; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		if ((i % XEN_PFN_PER_PAGE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 			page = pages[i / XEN_PFN_PER_PAGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			xen_pfn = page_to_xen_pfn(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		fn(pfn_to_gfn(xen_pfn++), data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) struct remap_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	xen_pfn_t *fgfn; /* foreign domain's gfn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	int nr_fgfn; /* Number of foreign gfn left to map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	pgprot_t prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	domid_t  domid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	struct vm_area_struct *vma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	struct page **pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct xen_remap_gfn_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	int *err_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	int mapped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	/* Hypercall parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	int h_errs[XEN_PFN_PER_PAGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	xen_ulong_t h_idxs[XEN_PFN_PER_PAGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	xen_pfn_t h_gpfns[XEN_PFN_PER_PAGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	int h_iter;	/* Iterator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) static void setup_hparams(unsigned long gfn, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	struct remap_data *info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	info->h_idxs[info->h_iter] = *info->fgfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	info->h_gpfns[info->h_iter] = gfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	info->h_errs[info->h_iter] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	info->h_iter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	info->fgfn++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) static int remap_pte_fn(pte_t *ptep, unsigned long addr, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct remap_data *info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	struct page *page = info->pages[info->index++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), info->prot));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	int rc, nr_gfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	uint32_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	struct xen_add_to_physmap_range xatp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		.domid = DOMID_SELF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		.foreign_domid = info->domid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		.space = XENMAPSPACE_gmfn_foreign,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	nr_gfn = min_t(typeof(info->nr_fgfn), XEN_PFN_PER_PAGE, info->nr_fgfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	info->nr_fgfn -= nr_gfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	info->h_iter = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	xen_for_each_gfn(&page, nr_gfn, setup_hparams, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	BUG_ON(info->h_iter != nr_gfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	set_xen_guest_handle(xatp.idxs, info->h_idxs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	set_xen_guest_handle(xatp.gpfns, info->h_gpfns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	set_xen_guest_handle(xatp.errs, info->h_errs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	xatp.size = nr_gfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	/* info->err_ptr expect to have one error status per Xen PFN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	for (i = 0; i < nr_gfn; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		int err = (rc < 0) ? rc : info->h_errs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		*(info->err_ptr++) = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			info->mapped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	 * Note: The hypercall will return 0 in most of the case if even if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	 * all the fgmfn are not mapped. We still have to update the pte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	 * as the userspace may decide to continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		set_pte_at(info->vma->vm_mm, addr, ptep, pte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int xen_xlate_remap_gfn_array(struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			      unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			      xen_pfn_t *gfn, int nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			      int *err_ptr, pgprot_t prot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			      unsigned domid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			      struct page **pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	struct remap_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	unsigned long range = DIV_ROUND_UP(nr, XEN_PFN_PER_PAGE) << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	/* Kept here for the purpose of making sure code doesn't break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	   x86 PVOPS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	data.fgfn = gfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	data.nr_fgfn = nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	data.prot  = prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	data.domid = domid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	data.vma   = vma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	data.pages = pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	data.index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	data.err_ptr = err_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	data.mapped = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	err = apply_to_page_range(vma->vm_mm, addr, range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 				  remap_pte_fn, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	return err < 0 ? err : data.mapped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) EXPORT_SYMBOL_GPL(xen_xlate_remap_gfn_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void unmap_gfn(unsigned long gfn, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	struct xen_remove_from_physmap xrp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	xrp.domid = DOMID_SELF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	xrp.gpfn = gfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	(void)HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			      int nr, struct page **pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	xen_for_each_gfn(pages, nr, unmap_gfn, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) EXPORT_SYMBOL_GPL(xen_xlate_unmap_gfn_range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct map_balloon_pages {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	xen_pfn_t *pfns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void setup_balloon_gfn(unsigned long gfn, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	struct map_balloon_pages *info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	info->pfns[info->idx++] = gfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * xen_xlate_map_ballooned_pages - map a new set of ballooned pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  * @gfns: returns the array of corresponding GFNs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  * @virt: returns the virtual address of the mapped region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  * @nr_grant_frames: number of GFNs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)  * @return 0 on success, error otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)  * This allocates a set of ballooned pages and maps them into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  * kernel's address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int __init xen_xlate_map_ballooned_pages(xen_pfn_t **gfns, void **virt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 					 unsigned long nr_grant_frames)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	struct page **pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	xen_pfn_t *pfns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	void *vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	struct map_balloon_pages data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	unsigned long nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	BUG_ON(nr_grant_frames == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	nr_pages = DIV_ROUND_UP(nr_grant_frames, XEN_PFN_PER_PAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	pages = kcalloc(nr_pages, sizeof(pages[0]), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (!pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	pfns = kcalloc(nr_grant_frames, sizeof(pfns[0]), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (!pfns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		kfree(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	rc = xen_alloc_unpopulated_pages(nr_pages, pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		pr_warn("%s Couldn't balloon alloc %ld pages rc:%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			nr_pages, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		kfree(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		kfree(pfns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	data.pfns = pfns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	data.idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	xen_for_each_gfn(pages, nr_grant_frames, setup_balloon_gfn, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	vaddr = vmap(pages, nr_pages, 0, PAGE_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	if (!vaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		pr_warn("%s Couldn't map %ld pages rc:%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 			nr_pages, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		xen_free_unpopulated_pages(nr_pages, pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		kfree(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		kfree(pfns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	kfree(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	*gfns = pfns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	*virt = vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) EXPORT_SYMBOL_GPL(xen_xlate_map_ballooned_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct remap_pfn {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	struct mm_struct *mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	struct page **pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	pgprot_t prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int remap_pfn_fn(pte_t *ptep, unsigned long addr, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	struct remap_pfn *r = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	struct page *page = r->pages[r->i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), r->prot));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	set_pte_at(r->mm, addr, ptep, pte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	r->i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* Used by the privcmd module, but has to be built-in on ARM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int xen_remap_vma_range(struct vm_area_struct *vma, unsigned long addr, unsigned long len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	struct remap_pfn r = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		.mm = vma->vm_mm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		.pages = vma->vm_private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		.prot = vma->vm_page_prot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	return apply_to_page_range(vma->vm_mm, addr, len, remap_pfn_fn, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) EXPORT_SYMBOL_GPL(xen_remap_vma_range);