ia64/xen-unstable

view extras/mini-os/gntmap.c @ 19557:226ef307cd2e

AMD IOMMU: Fix ioapic interrupt remapping

A few ioapic redirection entries are initialized by hypervisor before
enabling iommu hardware. This patch copies those entries from ioapic
redirection table into interrupt remapping table after interrupt
remapping table has been allocated.

Signed-off-by: Wei Wang <wei.wang2@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Apr 17 13:16:39 2009 +0100 (2009-04-17)
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 }