|
@@ -29,6 +29,8 @@
|
|
*/
|
|
*/
|
|
#include <linux/kernel.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/mm.h>
|
|
|
|
+#include <linux/slab.h>
|
|
|
|
+#include <linux/vmalloc.h>
|
|
|
|
|
|
#include <asm/xen/hypercall.h>
|
|
#include <asm/xen/hypercall.h>
|
|
#include <asm/xen/hypervisor.h>
|
|
#include <asm/xen/hypervisor.h>
|
|
@@ -37,6 +39,7 @@
|
|
#include <xen/page.h>
|
|
#include <xen/page.h>
|
|
#include <xen/interface/xen.h>
|
|
#include <xen/interface/xen.h>
|
|
#include <xen/interface/memory.h>
|
|
#include <xen/interface/memory.h>
|
|
|
|
+#include <xen/balloon.h>
|
|
|
|
|
|
typedef void (*xen_gfn_fn_t)(unsigned long gfn, void *data);
|
|
typedef void (*xen_gfn_fn_t)(unsigned long gfn, void *data);
|
|
|
|
|
|
@@ -185,3 +188,61 @@ int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(xen_xlate_unmap_gfn_range);
|
|
EXPORT_SYMBOL_GPL(xen_xlate_unmap_gfn_range);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * xen_xlate_map_ballooned_pages - map a new set of ballooned pages
|
|
|
|
+ * @gfns: returns the array of corresponding GFNs
|
|
|
|
+ * @virt: returns the virtual address of the mapped region
|
|
|
|
+ * @nr_grant_frames: number of GFNs
|
|
|
|
+ * @return 0 on success, error otherwise
|
|
|
|
+ *
|
|
|
|
+ * This allocates a set of ballooned pages and maps them into the
|
|
|
|
+ * kernel's address space.
|
|
|
|
+ */
|
|
|
|
+int __init xen_xlate_map_ballooned_pages(xen_pfn_t **gfns, void **virt,
|
|
|
|
+ unsigned long nr_grant_frames)
|
|
|
|
+{
|
|
|
|
+ struct page **pages;
|
|
|
|
+ xen_pfn_t *pfns;
|
|
|
|
+ void *vaddr;
|
|
|
|
+ int rc;
|
|
|
|
+ unsigned int i;
|
|
|
|
+
|
|
|
|
+ BUG_ON(nr_grant_frames == 0);
|
|
|
|
+ pages = kcalloc(nr_grant_frames, sizeof(pages[0]), GFP_KERNEL);
|
|
|
|
+ if (!pages)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ pfns = kcalloc(nr_grant_frames, sizeof(pfns[0]), GFP_KERNEL);
|
|
|
|
+ if (!pfns) {
|
|
|
|
+ kfree(pages);
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ rc = alloc_xenballooned_pages(nr_grant_frames, pages);
|
|
|
|
+ if (rc) {
|
|
|
|
+ pr_warn("%s Couldn't balloon alloc %ld pfns rc:%d\n", __func__,
|
|
|
|
+ nr_grant_frames, rc);
|
|
|
|
+ kfree(pages);
|
|
|
|
+ kfree(pfns);
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
|
|
+ for (i = 0; i < nr_grant_frames; i++)
|
|
|
|
+ pfns[i] = page_to_pfn(pages[i]);
|
|
|
|
+
|
|
|
|
+ vaddr = vmap(pages, nr_grant_frames, 0, PAGE_KERNEL);
|
|
|
|
+ if (!vaddr) {
|
|
|
|
+ pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__,
|
|
|
|
+ nr_grant_frames, rc);
|
|
|
|
+ free_xenballooned_pages(nr_grant_frames, pages);
|
|
|
|
+ kfree(pages);
|
|
|
|
+ kfree(pfns);
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ kfree(pages);
|
|
|
|
+
|
|
|
|
+ *gfns = pfns;
|
|
|
|
+ *virt = vaddr;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(xen_xlate_map_ballooned_pages);
|