ia64/xen-unstable

view extras/mini-os/gntmap.c @ 18811:390ef36eb596

Remove Xen-private definitions from kexec public header.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 19 13:13:39 2008 +0000 (2008-11-19)
parents a47b54fadce4
children
line source
1 /*
2 * Manages grant mappings from other domains.
3 *
4 * Diego Ongaro <diego.ongaro@citrix.com>, July 2008
5 *
6 * Files of type FTYPE_GNTMAP contain a gntmap, which is an array of
7 * (host address, grant handle) pairs. Grant handles come from a hypervisor map
8 * operation and are needed for the corresponding unmap.
9 *
10 * This is a rather naive implementation in terms of performance. If we start
11 * using it frequently, there's definitely some low-hanging fruit here.
12 *
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this software and associated documentation files (the "Software"), to
16 * deal in the Software without restriction, including without limitation the
17 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 * sell copies of the Software, and to permit persons to whom the Software is
19 * furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 * DEALINGS IN THE SOFTWARE.
31 */
33 #include <os.h>
34 #include <xmalloc.h>
35 #include <errno.h>
36 #include <xen/grant_table.h>
37 #include <inttypes.h>
38 #include "gntmap.h"
40 #define DEFAULT_MAX_GRANTS 128
42 struct gntmap_entry {
43 unsigned long host_addr;
44 grant_handle_t handle;
45 };
47 static inline int
48 gntmap_entry_used(struct gntmap_entry *entry)
49 {
50 return entry->host_addr != 0;
51 }
53 static struct gntmap_entry*
54 gntmap_find_free_entry(struct gntmap *map)
55 {
56 int i;
58 for (i = 0; i < map->nentries; i++) {
59 if (!gntmap_entry_used(&map->entries[i]))
60 return &map->entries[i];
61 }
63 #ifdef GNTMAP_DEBUG
64 printk("gntmap_find_free_entry(map=%p): all %d entries full\n",
65 map, map->nentries);
66 #endif
67 return NULL;
68 }
70 static struct gntmap_entry*
71 gntmap_find_entry(struct gntmap *map, unsigned long addr)
72 {
73 int i;
75 for (i = 0; i < map->nentries; i++) {
76 if (map->entries[i].host_addr == addr)
77 return &map->entries[i];
78 }
79 return NULL;
80 }
82 int
83 gntmap_set_max_grants(struct gntmap *map, int count)
84 {
85 #ifdef GNTMAP_DEBUG
86 printk("gntmap_set_max_grants(map=%p, count=%d)\n", map, count);
87 #endif
89 if (map->nentries != 0)
90 return -EBUSY;
92 map->entries = xmalloc_array(struct gntmap_entry, count);
93 if (map->entries == NULL)
94 return -ENOMEM;
96 memset(map->entries, 0, sizeof(struct gntmap_entry) * count);
97 map->nentries = count;
98 return 0;
99 }
101 static int
102 _gntmap_map_grant_ref(struct gntmap_entry *entry,
103 unsigned long host_addr,
104 uint32_t domid,
105 uint32_t ref,
106 int writable)
107 {
108 struct gnttab_map_grant_ref op;
109 int rc;
111 op.ref = (grant_ref_t) ref;
112 op.dom = (domid_t) domid;
113 op.host_addr = (uint64_t) host_addr;
114 op.flags = GNTMAP_host_map;
115 if (!writable)
116 op.flags |= GNTMAP_readonly;
118 rc = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
119 if (rc != 0 || op.status != GNTST_okay) {
120 printk("GNTTABOP_map_grant_ref failed: "
121 "returned %d, status %" PRId16 "\n",
122 rc, op.status);
123 return rc != 0 ? rc : op.status;
124 }
126 entry->host_addr = host_addr;
127 entry->handle = op.handle;
128 return 0;
129 }
131 static int
132 _gntmap_unmap_grant_ref(struct gntmap_entry *entry)
133 {
134 struct gnttab_unmap_grant_ref op;
135 int rc;
137 op.host_addr = (uint64_t) entry->host_addr;
138 op.dev_bus_addr = 0;
139 op.handle = entry->handle;
141 rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
142 if (rc != 0 || op.status != GNTST_okay) {
143 printk("GNTTABOP_unmap_grant_ref failed: "
144 "returned %d, status %" PRId16 "\n",
145 rc, op.status);
146 return rc != 0 ? rc : op.status;
147 }
149 entry->host_addr = 0;
150 return 0;
151 }
153 int
154 gntmap_munmap(struct gntmap *map, unsigned long start_address, int count)
155 {
156 int i, rc;
157 struct gntmap_entry *ent;
159 #ifdef GNTMAP_DEBUG
160 printk("gntmap_munmap(map=%p, start_address=%lx, count=%d)\n",
161 map, start_address, count);
162 #endif
164 for (i = 0; i < count; i++) {
165 ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
166 if (ent == NULL) {
167 printk("gntmap: tried to munmap unknown page\n");
168 return -EINVAL;
169 }
171 rc = _gntmap_unmap_grant_ref(ent);
172 if (rc != 0)
173 return rc;
174 }
176 return 0;
177 }
179 void*
180 gntmap_map_grant_refs(struct gntmap *map,
181 uint32_t count,
182 uint32_t *domids,
183 int domids_stride,
184 uint32_t *refs,
185 int writable)
186 {
187 unsigned long addr;
188 struct gntmap_entry *ent;
189 int i;
191 #ifdef GNTMAP_DEBUG
192 printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
193 "domids=%p [%" PRIu32 "...], domids_stride=%d, "
194 "refs=%p [%" PRIu32 "...], writable=%d)\n",
195 map, count,
196 domids, domids == NULL ? 0 : domids[0], domids_stride,
197 refs, refs == NULL ? 0 : refs[0], writable);
198 #endif
200 (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
202 addr = allocate_ondemand((unsigned long) count, 1);
203 if (addr == 0)
204 return NULL;
206 for (i = 0; i < count; i++) {
207 ent = gntmap_find_free_entry(map);
208 if (ent == NULL ||
209 _gntmap_map_grant_ref(ent,
210 addr + PAGE_SIZE * i,
211 domids[i * domids_stride],
212 refs[i],
213 writable) != 0) {
215 (void) gntmap_munmap(map, addr, i);
216 return NULL;
217 }
218 }
220 return (void*) addr;
221 }
223 void
224 gntmap_init(struct gntmap *map)
225 {
226 #ifdef GNTMAP_DEBUG
227 printk("gntmap_init(map=%p)\n", map);
228 #endif
229 map->nentries = 0;
230 map->entries = NULL;
231 }
233 void
234 gntmap_fini(struct gntmap *map)
235 {
236 struct gntmap_entry *ent;
237 int i;
239 #ifdef GNTMAP_DEBUG
240 printk("gntmap_fini(map=%p)\n", map);
241 #endif
243 for (i = 0; i < map->nentries; i++) {
244 ent = &map->entries[i];
245 if (gntmap_entry_used(ent))
246 (void) _gntmap_unmap_grant_ref(ent);
247 }
249 xfree(map->entries);
250 map->entries = NULL;
251 map->nentries = 0;
252 }