2
* Manages grant mappings from other domains.
4
* Diego Ongaro <diego.ongaro@citrix.com>, July 2008
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.
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.
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:
21
* The above copyright notice and this permission notice shall be included in
22
* all copies or substantial portions of the Software.
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.
33
#include <mini-os/os.h>
34
#include <mini-os/lib.h>
35
#include <mini-os/xmalloc.h>
37
#include <xen/grant_table.h>
39
#include <mini-os/gntmap.h>
41
#define DEFAULT_MAX_GRANTS 128
44
unsigned long host_addr;
45
grant_handle_t handle;
49
gntmap_entry_used(struct gntmap_entry *entry)
51
return entry->host_addr != 0;
54
static struct gntmap_entry*
55
gntmap_find_free_entry(struct gntmap *map)
59
for (i = 0; i < map->nentries; i++) {
60
if (!gntmap_entry_used(&map->entries[i]))
61
return &map->entries[i];
65
printk("gntmap_find_free_entry(map=%p): all %d entries full\n",
71
static struct gntmap_entry*
72
gntmap_find_entry(struct gntmap *map, unsigned long addr)
76
for (i = 0; i < map->nentries; i++) {
77
if (map->entries[i].host_addr == addr)
78
return &map->entries[i];
84
gntmap_set_max_grants(struct gntmap *map, int count)
87
printk("gntmap_set_max_grants(map=%p, count=%d)\n", map, count);
90
if (map->nentries != 0)
93
map->entries = xmalloc_array(struct gntmap_entry, count);
94
if (map->entries == NULL)
97
memset(map->entries, 0, sizeof(struct gntmap_entry) * count);
98
map->nentries = count;
103
_gntmap_map_grant_ref(struct gntmap_entry *entry,
104
unsigned long host_addr,
109
struct gnttab_map_grant_ref op;
112
op.ref = (grant_ref_t) ref;
113
op.dom = (domid_t) domid;
114
op.host_addr = (uint64_t) host_addr;
115
op.flags = GNTMAP_host_map;
117
op.flags |= GNTMAP_readonly;
119
rc = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
120
if (rc != 0 || op.status != GNTST_okay) {
121
printk("GNTTABOP_map_grant_ref failed: "
122
"returned %d, status %" PRId16 "\n",
124
return rc != 0 ? rc : op.status;
127
entry->host_addr = host_addr;
128
entry->handle = op.handle;
133
_gntmap_unmap_grant_ref(struct gntmap_entry *entry)
135
struct gnttab_unmap_grant_ref op;
138
op.host_addr = (uint64_t) entry->host_addr;
140
op.handle = entry->handle;
142
rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
143
if (rc != 0 || op.status != GNTST_okay) {
144
printk("GNTTABOP_unmap_grant_ref failed: "
145
"returned %d, status %" PRId16 "\n",
147
return rc != 0 ? rc : op.status;
150
entry->host_addr = 0;
155
gntmap_munmap(struct gntmap *map, unsigned long start_address, int count)
158
struct gntmap_entry *ent;
161
printk("gntmap_munmap(map=%p, start_address=%lx, count=%d)\n",
162
map, start_address, count);
165
for (i = 0; i < count; i++) {
166
ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
168
printk("gntmap: tried to munmap unknown page\n");
172
rc = _gntmap_unmap_grant_ref(ent);
181
gntmap_map_grant_refs(struct gntmap *map,
189
struct gntmap_entry *ent;
193
printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
194
"domids=%p [%" PRIu32 "...], domids_stride=%d, "
195
"refs=%p [%" PRIu32 "...], writable=%d)\n",
197
domids, domids == NULL ? 0 : domids[0], domids_stride,
198
refs, refs == NULL ? 0 : refs[0], writable);
201
(void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
203
addr = allocate_ondemand((unsigned long) count, 1);
207
for (i = 0; i < count; i++) {
208
ent = gntmap_find_free_entry(map);
210
_gntmap_map_grant_ref(ent,
211
addr + PAGE_SIZE * i,
212
domids[i * domids_stride],
216
(void) gntmap_munmap(map, addr, i);
225
gntmap_init(struct gntmap *map)
228
printk("gntmap_init(map=%p)\n", map);
235
gntmap_fini(struct gntmap *map)
237
struct gntmap_entry *ent;
241
printk("gntmap_fini(map=%p)\n", map);
244
for (i = 0; i < map->nentries; i++) {
245
ent = &map->entries[i];
246
if (gntmap_entry_used(ent))
247
(void) _gntmap_unmap_grant_ref(ent);