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>
24 #include <asm/pgtable.h>
26 static struct gnttab_vm_area
{
27 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 arch_gnttab_valloc(struct gnttab_vm_area
*area
, unsigned nr_frames
)
96 area
->ptes
= kmalloc_array(nr_frames
, sizeof(*area
->ptes
), GFP_KERNEL
);
97 if (area
->ptes
== NULL
)
100 area
->area
= alloc_vm_area(PAGE_SIZE
* nr_frames
, area
->ptes
);
101 if (area
->area
== NULL
) {
109 static void arch_gnttab_vfree(struct gnttab_vm_area
*area
)
111 free_vm_area(area
->area
);
115 int arch_gnttab_init(unsigned long nr_shared
, unsigned long nr_status
)
119 if (!xen_pv_domain())
122 ret
= arch_gnttab_valloc(&gnttab_shared_vm_area
, nr_shared
);
127 * Always allocate the space for the status frames in case
128 * we're migrated to a host with V2 support.
130 ret
= arch_gnttab_valloc(&gnttab_status_vm_area
, nr_status
);
136 arch_gnttab_vfree(&gnttab_shared_vm_area
);
140 #ifdef CONFIG_XEN_PVH
141 #include <xen/events.h>
142 #include <xen/xen-ops.h>
143 static int __init
xen_pvh_gnttab_setup(void)
145 if (!xen_pvh_domain())
148 xen_auto_xlat_grant_frames
.count
= gnttab_max_grant_frames();
150 return xen_xlate_map_ballooned_pages(&xen_auto_xlat_grant_frames
.pfn
,
151 &xen_auto_xlat_grant_frames
.vaddr
,
152 xen_auto_xlat_grant_frames
.count
);
154 /* Call it _before_ __gnttab_init as we need to initialize the
155 * xen_auto_xlat_grant_frames first. */
156 core_initcall(xen_pvh_gnttab_setup
);