1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /******************************************************************************
6 * Granting foreign access to our memory reservation.
8 * Copyright (c) 2005-2006, Christopher Clark
9 * Copyright (c) 2004-2005, K A Fraser
10 * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
11 * VA Linux Systems Japan. Split out x86 specific part.
14 #include <linux/sched.h>
16 #include <linux/slab.h>
17 #include <linux/vmalloc.h>
19 #include <xen/interface/xen.h>
21 #include <xen/grant_table.h>
25 static struct gnttab_vm_area
{
26 struct vm_struct
*area
;
29 } gnttab_shared_vm_area
, gnttab_status_vm_area
;
31 int arch_gnttab_map_shared(unsigned long *frames
, unsigned long nr_gframes
,
32 unsigned long max_nr_gframes
,
35 void *shared
= *__shared
;
40 *__shared
= shared
= gnttab_shared_vm_area
.area
->addr
;
42 addr
= (unsigned long)shared
;
44 for (i
= 0; i
< nr_gframes
; i
++) {
45 set_pte_at(&init_mm
, addr
, gnttab_shared_vm_area
.ptes
[i
],
46 mfn_pte(frames
[i
], PAGE_KERNEL
));
53 int arch_gnttab_map_status(uint64_t *frames
, unsigned long nr_gframes
,
54 unsigned long max_nr_gframes
,
55 grant_status_t
**__shared
)
57 grant_status_t
*shared
= *__shared
;
62 *__shared
= shared
= gnttab_status_vm_area
.area
->addr
;
64 addr
= (unsigned long)shared
;
66 for (i
= 0; i
< nr_gframes
; i
++) {
67 set_pte_at(&init_mm
, addr
, gnttab_status_vm_area
.ptes
[i
],
68 mfn_pte(frames
[i
], PAGE_KERNEL
));
75 void arch_gnttab_unmap(void *shared
, unsigned long nr_gframes
)
81 if (shared
== gnttab_status_vm_area
.area
->addr
)
82 ptes
= gnttab_status_vm_area
.ptes
;
84 ptes
= gnttab_shared_vm_area
.ptes
;
86 addr
= (unsigned long)shared
;
88 for (i
= 0; i
< nr_gframes
; i
++) {
89 set_pte_at(&init_mm
, addr
, ptes
[i
], __pte(0));
94 static int gnttab_apply(pte_t
*pte
, unsigned long addr
, void *data
)
96 struct gnttab_vm_area
*area
= data
;
98 area
->ptes
[area
->idx
++] = pte
;
102 static int arch_gnttab_valloc(struct gnttab_vm_area
*area
, unsigned nr_frames
)
104 area
->ptes
= kmalloc_array(nr_frames
, sizeof(*area
->ptes
), GFP_KERNEL
);
105 if (area
->ptes
== NULL
)
107 area
->area
= get_vm_area(PAGE_SIZE
* nr_frames
, VM_IOREMAP
);
110 if (apply_to_page_range(&init_mm
, (unsigned long)area
->area
->addr
,
111 PAGE_SIZE
* nr_frames
, gnttab_apply
, area
))
112 goto out_free_vm_area
;
115 free_vm_area(area
->area
);
121 static void arch_gnttab_vfree(struct gnttab_vm_area
*area
)
123 free_vm_area(area
->area
);
127 int arch_gnttab_init(unsigned long nr_shared
, unsigned long nr_status
)
131 if (!xen_pv_domain())
134 ret
= arch_gnttab_valloc(&gnttab_shared_vm_area
, nr_shared
);
139 * Always allocate the space for the status frames in case
140 * we're migrated to a host with V2 support.
142 ret
= arch_gnttab_valloc(&gnttab_status_vm_area
, nr_status
);
148 arch_gnttab_vfree(&gnttab_shared_vm_area
);
152 #ifdef CONFIG_XEN_PVH
153 #include <xen/events.h>
154 #include <xen/xen-ops.h>
155 static int __init
xen_pvh_gnttab_setup(void)
157 if (!xen_pvh_domain())
160 xen_auto_xlat_grant_frames
.count
= gnttab_max_grant_frames();
162 return xen_xlate_map_ballooned_pages(&xen_auto_xlat_grant_frames
.pfn
,
163 &xen_auto_xlat_grant_frames
.vaddr
,
164 xen_auto_xlat_grant_frames
.count
);
166 /* Call it _before_ __gnttab_init as we need to initialize the
167 * xen_auto_xlat_grant_frames first. */
168 core_initcall(xen_pvh_gnttab_setup
);