diff options
Diffstat (limited to 'meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch')
-rw-r--r-- | meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch new file mode 100644 index 00000000..48dcf7d7 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch | |||
@@ -0,0 +1,262 @@ | |||
1 | From 90496d4c71e3b9334aebca118661bf72631ed0f0 Mon Sep 17 00:00:00 2001 | ||
2 | From: Juergen Gross <jgross@suse.com> | ||
3 | Date: Fri, 26 Aug 2022 13:57:06 +0200 | ||
4 | Subject: [PATCH 10/11] xen: add map and unmap callbacks for grant region | ||
5 | |||
6 | Add the callbacks for mapping/unmapping guest memory via grants to the | ||
7 | special grant memory region. | ||
8 | |||
9 | Signed-off-by: Juergen Gross <jgross@suse.com> | ||
10 | Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com> | ||
11 | --- | ||
12 | hw/xen/xen-mapcache.c | 176 +++++++++++++++++++++++++++++++++++++++++- | ||
13 | softmmu/physmem.c | 11 ++- | ||
14 | 2 files changed, 182 insertions(+), 5 deletions(-) | ||
15 | |||
16 | diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c | ||
17 | index 8a61c7dde6..e071328fc5 100644 | ||
18 | --- a/hw/xen/xen-mapcache.c | ||
19 | +++ b/hw/xen/xen-mapcache.c | ||
20 | @@ -9,6 +9,8 @@ | ||
21 | */ | ||
22 | |||
23 | #include "qemu/osdep.h" | ||
24 | +#include "qemu/queue.h" | ||
25 | +#include "qemu/thread.h" | ||
26 | #include "qemu/units.h" | ||
27 | #include "qemu/error-report.h" | ||
28 | |||
29 | @@ -23,6 +25,8 @@ | ||
30 | #include "sysemu/xen-mapcache.h" | ||
31 | #include "trace.h" | ||
32 | |||
33 | +#include <xenevtchn.h> | ||
34 | +#include <xengnttab.h> | ||
35 | |||
36 | //#define MAPCACHE_DEBUG | ||
37 | |||
38 | @@ -385,7 +389,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, | ||
39 | return p; | ||
40 | } | ||
41 | |||
42 | -ram_addr_t xen_ram_addr_from_mapcache(void *ptr) | ||
43 | +static ram_addr_t xen_ram_addr_from_mapcache_try(void *ptr) | ||
44 | { | ||
45 | MapCacheEntry *entry = NULL; | ||
46 | MapCacheRev *reventry; | ||
47 | @@ -594,10 +598,179 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr, | ||
48 | return p; | ||
49 | } | ||
50 | |||
51 | +struct XENMappedGrantRegion { | ||
52 | + void *addr; | ||
53 | + unsigned int pages; | ||
54 | + unsigned int refs; | ||
55 | + unsigned int prot; | ||
56 | + uint32_t idx; | ||
57 | + QLIST_ENTRY(XENMappedGrantRegion) list; | ||
58 | +}; | ||
59 | + | ||
60 | +static xengnttab_handle *xen_region_gnttabdev; | ||
61 | +static QLIST_HEAD(GrantRegionList, XENMappedGrantRegion) xen_grant_mappings = | ||
62 | + QLIST_HEAD_INITIALIZER(xen_grant_mappings); | ||
63 | +static QemuMutex xen_map_mutex; | ||
64 | + | ||
65 | +static void *xen_map_grant_dyn(MemoryRegion **mr, hwaddr addr, hwaddr *plen, | ||
66 | + bool is_write, MemTxAttrs attrs) | ||
67 | +{ | ||
68 | + unsigned int page_off = addr & (XC_PAGE_SIZE - 1); | ||
69 | + unsigned int i; | ||
70 | + unsigned int total_grants = 0; | ||
71 | + unsigned int nrefs = (page_off + *plen + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT; | ||
72 | + uint32_t ref = (addr - XEN_GRANT_ADDR_OFF) >> XC_PAGE_SHIFT; | ||
73 | + uint32_t *refs = NULL; | ||
74 | + unsigned int prot = PROT_READ; | ||
75 | + struct XENMappedGrantRegion *mgr = NULL; | ||
76 | + | ||
77 | + if (is_write) { | ||
78 | + prot |= PROT_WRITE; | ||
79 | + } | ||
80 | + | ||
81 | + qemu_mutex_lock(&xen_map_mutex); | ||
82 | + | ||
83 | + QLIST_FOREACH(mgr, &xen_grant_mappings, list) { | ||
84 | + if (mgr->idx == ref && | ||
85 | + mgr->pages == nrefs && | ||
86 | + (mgr->prot & prot) == prot) { | ||
87 | + break; | ||
88 | + } | ||
89 | + | ||
90 | + total_grants += mgr->pages; | ||
91 | + } | ||
92 | + | ||
93 | + if (!mgr) { | ||
94 | + if (nrefs + total_grants >= XEN_MAX_VIRTIO_GRANTS) { | ||
95 | + qemu_mutex_unlock(&xen_map_mutex); | ||
96 | + return NULL; | ||
97 | + } | ||
98 | + | ||
99 | + mgr = g_new(struct XENMappedGrantRegion, 1); | ||
100 | + | ||
101 | + if (nrefs == 1) { | ||
102 | + refs = &ref; | ||
103 | + } else { | ||
104 | + refs = g_new(uint32_t, nrefs); | ||
105 | + for (i = 0; i < nrefs; i++) { | ||
106 | + refs[i] = ref + i; | ||
107 | + } | ||
108 | + } | ||
109 | + mgr->addr = xengnttab_map_domain_grant_refs(xen_region_gnttabdev, nrefs, | ||
110 | + xen_domid, refs, prot); | ||
111 | + if (mgr->addr) { | ||
112 | + mgr->pages = nrefs; | ||
113 | + mgr->refs = 1; | ||
114 | + mgr->prot = prot; | ||
115 | + mgr->idx = ref; | ||
116 | + | ||
117 | + QLIST_INSERT_HEAD(&xen_grant_mappings, mgr, list); | ||
118 | + } else { | ||
119 | + g_free(mgr); | ||
120 | + mgr = NULL; | ||
121 | + } | ||
122 | + } else { | ||
123 | + mgr->refs++; | ||
124 | + } | ||
125 | + | ||
126 | + qemu_mutex_unlock(&xen_map_mutex); | ||
127 | + | ||
128 | + if (nrefs > 1) { | ||
129 | + g_free(refs); | ||
130 | + } | ||
131 | + | ||
132 | + return mgr ? mgr->addr + page_off : NULL; | ||
133 | +} | ||
134 | + | ||
135 | +static void xen_unmap_grant_dyn(MemoryRegion *mr, void *buffer, ram_addr_t addr, | ||
136 | + hwaddr len, bool is_write, hwaddr access_len) | ||
137 | +{ | ||
138 | + unsigned int page_off = (unsigned long)buffer & (XC_PAGE_SIZE - 1); | ||
139 | + unsigned int nrefs = (page_off + len + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT; | ||
140 | + unsigned int prot = PROT_READ; | ||
141 | + struct XENMappedGrantRegion *mgr = NULL; | ||
142 | + | ||
143 | + if (is_write) { | ||
144 | + prot |= PROT_WRITE; | ||
145 | + } | ||
146 | + | ||
147 | + qemu_mutex_lock(&xen_map_mutex); | ||
148 | + | ||
149 | + QLIST_FOREACH(mgr, &xen_grant_mappings, list) { | ||
150 | + if (mgr->addr == buffer - page_off && | ||
151 | + mgr->pages == nrefs && | ||
152 | + (mgr->prot & prot) == prot) { | ||
153 | + break; | ||
154 | + } | ||
155 | + } | ||
156 | + if (mgr) { | ||
157 | + mgr->refs--; | ||
158 | + if (!mgr->refs) { | ||
159 | + xengnttab_unmap(xen_region_gnttabdev, mgr->addr, nrefs); | ||
160 | + | ||
161 | + QLIST_REMOVE(mgr, list); | ||
162 | + g_free(mgr); | ||
163 | + } | ||
164 | + } else { | ||
165 | + error_report("xen_unmap_grant_dyn() trying to unmap unknown buffer"); | ||
166 | + } | ||
167 | + | ||
168 | + qemu_mutex_unlock(&xen_map_mutex); | ||
169 | +} | ||
170 | + | ||
171 | +static ram_addr_t xen_ram_addr_from_grant_cache(void *ptr) | ||
172 | +{ | ||
173 | + unsigned int page_off = (unsigned long)ptr & (XC_PAGE_SIZE - 1); | ||
174 | + struct XENMappedGrantRegion *mgr = NULL; | ||
175 | + ram_addr_t raddr = RAM_ADDR_INVALID; | ||
176 | + | ||
177 | + qemu_mutex_lock(&xen_map_mutex); | ||
178 | + | ||
179 | + QLIST_FOREACH(mgr, &xen_grant_mappings, list) { | ||
180 | + if (mgr->addr == ptr - page_off) { | ||
181 | + break; | ||
182 | + } | ||
183 | + } | ||
184 | + | ||
185 | + if (mgr) { | ||
186 | + raddr = (mgr->idx << XC_PAGE_SHIFT) + page_off + XEN_GRANT_ADDR_OFF; | ||
187 | + } | ||
188 | + | ||
189 | + qemu_mutex_unlock(&xen_map_mutex); | ||
190 | + | ||
191 | + return raddr; | ||
192 | +} | ||
193 | + | ||
194 | +ram_addr_t xen_ram_addr_from_mapcache(void *ptr) | ||
195 | +{ | ||
196 | + ram_addr_t raddr; | ||
197 | + | ||
198 | + raddr = xen_ram_addr_from_mapcache_try(ptr); | ||
199 | + if (raddr == RAM_ADDR_INVALID) { | ||
200 | + raddr = xen_ram_addr_from_grant_cache(ptr); | ||
201 | + } | ||
202 | + | ||
203 | + return raddr; | ||
204 | +} | ||
205 | + | ||
206 | +static const struct MemoryRegionOps xen_grant_mr_ops = { | ||
207 | + .map = xen_map_grant_dyn, | ||
208 | + .unmap = xen_unmap_grant_dyn, | ||
209 | + .endianness = DEVICE_LITTLE_ENDIAN, | ||
210 | +}; | ||
211 | + | ||
212 | MemoryRegion *xen_init_grant_ram(void) | ||
213 | { | ||
214 | RAMBlock *block; | ||
215 | |||
216 | + qemu_mutex_init(&xen_map_mutex); | ||
217 | + | ||
218 | + xen_region_gnttabdev = xengnttab_open(NULL, 0); | ||
219 | + if (xen_region_gnttabdev == NULL) { | ||
220 | + fprintf(stderr, "can't open gnttab device\n"); | ||
221 | + return NULL; | ||
222 | + } | ||
223 | + | ||
224 | memory_region_init(&ram_grants, NULL, "xen.grants", | ||
225 | XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE); | ||
226 | block = g_malloc0(sizeof(*block)); | ||
227 | @@ -612,6 +785,7 @@ MemoryRegion *xen_init_grant_ram(void) | ||
228 | ram_grants.ram_block = block; | ||
229 | ram_grants.ram = true; | ||
230 | ram_grants.terminates = true; | ||
231 | + ram_grants.ops = &xen_grant_mr_ops; | ||
232 | ram_block_add_list(block); | ||
233 | memory_region_add_subregion(get_system_memory(), XEN_GRANT_ADDR_OFF, | ||
234 | &ram_grants); | ||
235 | diff --git a/softmmu/physmem.c b/softmmu/physmem.c | ||
236 | index a1e2030424..e1057304f1 100644 | ||
237 | --- a/softmmu/physmem.c | ||
238 | +++ b/softmmu/physmem.c | ||
239 | @@ -2210,13 +2210,16 @@ RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset, | ||
240 | |||
241 | if (xen_enabled()) { | ||
242 | ram_addr_t ram_addr; | ||
243 | + | ||
244 | RCU_READ_LOCK_GUARD(); | ||
245 | ram_addr = xen_ram_addr_from_mapcache(ptr); | ||
246 | - block = qemu_get_ram_block(ram_addr); | ||
247 | - if (block) { | ||
248 | - *offset = ram_addr - block->offset; | ||
249 | + if (ram_addr != RAM_ADDR_INVALID) { | ||
250 | + block = qemu_get_ram_block(ram_addr); | ||
251 | + if (block) { | ||
252 | + *offset = ram_addr - block->offset; | ||
253 | + } | ||
254 | + return block; | ||
255 | } | ||
256 | - return block; | ||
257 | } | ||
258 | |||
259 | RCU_READ_LOCK_GUARD(); | ||
260 | -- | ||
261 | 2.39.2 | ||
262 | |||