~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to extras/mini-os/gntmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
 
32
 
 
33
#include <mini-os/os.h>
 
34
#include <mini-os/lib.h>
 
35
#include <mini-os/xmalloc.h>
 
36
#include <errno.h>
 
37
#include <xen/grant_table.h>
 
38
#include <inttypes.h>
 
39
#include <mini-os/gntmap.h>
 
40
 
 
41
#define DEFAULT_MAX_GRANTS 128
 
42
 
 
43
struct gntmap_entry {
 
44
    unsigned long host_addr;
 
45
    grant_handle_t handle;
 
46
};
 
47
 
 
48
static inline int
 
49
gntmap_entry_used(struct gntmap_entry *entry)
 
50
{
 
51
    return entry->host_addr != 0;
 
52
}
 
53
 
 
54
static struct gntmap_entry*
 
55
gntmap_find_free_entry(struct gntmap *map)
 
56
{
 
57
    int i;
 
58
 
 
59
    for (i = 0; i < map->nentries; i++) {
 
60
        if (!gntmap_entry_used(&map->entries[i]))
 
61
            return &map->entries[i];
 
62
    }
 
63
 
 
64
#ifdef GNTMAP_DEBUG
 
65
    printk("gntmap_find_free_entry(map=%p): all %d entries full\n",
 
66
           map, map->nentries);
 
67
#endif
 
68
    return NULL;
 
69
}
 
70
 
 
71
static struct gntmap_entry*
 
72
gntmap_find_entry(struct gntmap *map, unsigned long addr)
 
73
{
 
74
    int i;
 
75
 
 
76
    for (i = 0; i < map->nentries; i++) {
 
77
        if (map->entries[i].host_addr == addr)
 
78
            return &map->entries[i];
 
79
    }
 
80
    return NULL;
 
81
}
 
82
 
 
83
int
 
84
gntmap_set_max_grants(struct gntmap *map, int count)
 
85
{
 
86
#ifdef GNTMAP_DEBUG
 
87
    printk("gntmap_set_max_grants(map=%p, count=%d)\n", map, count);
 
88
#endif
 
89
 
 
90
    if (map->nentries != 0)
 
91
        return -EBUSY;
 
92
 
 
93
    map->entries = xmalloc_array(struct gntmap_entry, count);
 
94
    if (map->entries == NULL)
 
95
        return -ENOMEM;
 
96
 
 
97
    memset(map->entries, 0, sizeof(struct gntmap_entry) * count);
 
98
    map->nentries = count;
 
99
    return 0;
 
100
}
 
101
 
 
102
static int
 
103
_gntmap_map_grant_ref(struct gntmap_entry *entry, 
 
104
                      unsigned long host_addr,
 
105
                      uint32_t domid,
 
106
                      uint32_t ref,
 
107
                      int writable)
 
108
{
 
109
    struct gnttab_map_grant_ref op;
 
110
    int rc;
 
111
 
 
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;
 
116
    if (!writable)
 
117
        op.flags |= GNTMAP_readonly;
 
118
 
 
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",
 
123
               rc, op.status);
 
124
        return rc != 0 ? rc : op.status;
 
125
    }
 
126
 
 
127
    entry->host_addr = host_addr;
 
128
    entry->handle = op.handle;
 
129
    return 0;
 
130
}
 
131
 
 
132
static int
 
133
_gntmap_unmap_grant_ref(struct gntmap_entry *entry)
 
134
{
 
135
    struct gnttab_unmap_grant_ref op;
 
136
    int rc;
 
137
 
 
138
    op.host_addr    = (uint64_t) entry->host_addr;
 
139
    op.dev_bus_addr = 0;
 
140
    op.handle       = entry->handle;
 
141
 
 
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",
 
146
               rc, op.status);
 
147
        return rc != 0 ? rc : op.status;
 
148
    }
 
149
 
 
150
    entry->host_addr = 0;
 
151
    return 0;
 
152
}
 
153
 
 
154
int
 
155
gntmap_munmap(struct gntmap *map, unsigned long start_address, int count)
 
156
{
 
157
    int i, rc;
 
158
    struct gntmap_entry *ent;
 
159
 
 
160
#ifdef GNTMAP_DEBUG
 
161
    printk("gntmap_munmap(map=%p, start_address=%lx, count=%d)\n",
 
162
           map, start_address, count);
 
163
#endif
 
164
 
 
165
    for (i = 0; i < count; i++) {
 
166
        ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
 
167
        if (ent == NULL) {
 
168
            printk("gntmap: tried to munmap unknown page\n");
 
169
            return -EINVAL;
 
170
        }
 
171
 
 
172
        rc = _gntmap_unmap_grant_ref(ent);
 
173
        if (rc != 0)
 
174
            return rc;
 
175
    }
 
176
 
 
177
    return 0;
 
178
}
 
179
 
 
180
void*
 
181
gntmap_map_grant_refs(struct gntmap *map, 
 
182
                      uint32_t count,
 
183
                      uint32_t *domids,
 
184
                      int domids_stride,
 
185
                      uint32_t *refs,
 
186
                      int writable)
 
187
{
 
188
    unsigned long addr;
 
189
    struct gntmap_entry *ent;
 
190
    int i;
 
191
 
 
192
#ifdef GNTMAP_DEBUG
 
193
    printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
 
194
           "domids=%p [%" PRIu32 "...], domids_stride=%d, "
 
195
           "refs=%p [%" PRIu32 "...], writable=%d)\n",
 
196
           map, count,
 
197
           domids, domids == NULL ? 0 : domids[0], domids_stride,
 
198
           refs, refs == NULL ? 0 : refs[0], writable);
 
199
#endif
 
200
 
 
201
    (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
 
202
 
 
203
    addr = allocate_ondemand((unsigned long) count, 1);
 
204
    if (addr == 0)
 
205
        return NULL;
 
206
 
 
207
    for (i = 0; i < count; i++) {
 
208
        ent = gntmap_find_free_entry(map);
 
209
        if (ent == NULL ||
 
210
            _gntmap_map_grant_ref(ent,
 
211
                                  addr + PAGE_SIZE * i,
 
212
                                  domids[i * domids_stride],
 
213
                                  refs[i],
 
214
                                  writable) != 0) {
 
215
 
 
216
            (void) gntmap_munmap(map, addr, i);
 
217
            return NULL;
 
218
        }
 
219
    }
 
220
 
 
221
    return (void*) addr;
 
222
}
 
223
 
 
224
void
 
225
gntmap_init(struct gntmap *map)
 
226
{
 
227
#ifdef GNTMAP_DEBUG
 
228
    printk("gntmap_init(map=%p)\n", map);
 
229
#endif
 
230
    map->nentries = 0;
 
231
    map->entries = NULL;
 
232
}
 
233
 
 
234
void
 
235
gntmap_fini(struct gntmap *map)
 
236
{
 
237
    struct gntmap_entry *ent;
 
238
    int i;
 
239
 
 
240
#ifdef GNTMAP_DEBUG
 
241
    printk("gntmap_fini(map=%p)\n", map);
 
242
#endif
 
243
 
 
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);
 
248
    }
 
249
 
 
250
    xfree(map->entries);
 
251
    map->entries = NULL;
 
252
    map->nentries = 0;
 
253
}