blob: d4e5500e6dd118877e58f594fb100c17f3fdef0f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/*
* Sharing page frames with other domains
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
enum {
Nframes = 1, // XXX don't increase this without setting up extra mappings in xengrant_init()
};
static struct {
Lock;
ushort free;
ushort *refs;
} refalloc;
static grant_entry_t *granttab;
void
xengrantinit(void)
{
gnttab_setup_table_t setup;
ulong frames[Nframes];
int nrefs, i;
setup.dom = DOMID_SELF;
setup.nr_frames = Nframes;
set_xen_guest_handle(setup.frame_list, frames);
if (HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0 || setup.status != 0)
panic("xen grant table setup");
granttab = (grant_entry_t*)mmumapframe(XENGRANTTAB, frames[0]);
nrefs = Nframes * BY2PG / sizeof(grant_entry_t);
refalloc.refs = (ushort*)malloc(nrefs*sizeof(ushort));
for (i = 0; i < nrefs; i++)
refalloc.refs[i] = i-1;
refalloc.free = nrefs-1;
}
static int
allocref(void)
{
int ref;
ilock(&refalloc);
ref = refalloc.free;
if (ref > 0)
refalloc.free = refalloc.refs[ref];
iunlock(&refalloc);
return ref;
}
static void
freeref(int ref)
{
ilock(&refalloc);
refalloc.refs[ref] = refalloc.free;
refalloc.free = ref;
iunlock(&refalloc);
}
int
xengrant(domid_t domid, ulong frame, int flags)
{
int ref;
grant_entry_t *gt;
if ((ref = allocref()) < 0)
panic("out of xengrant refs");
gt = &granttab[ref];
gt->frame = frame;
gt->domid = domid;
coherence();
gt->flags = flags;
return ref;
}
int
xengrantend(int ref)
{
grant_entry_t *gt;
int frame;
gt = &granttab[ref];
coherence();
if (gt->flags>F_accept_transfer) {
if ((gt->flags>F_transfer_completed) == 0)
panic("xengrantend transfer in progress");
} else {
if (gt->flags&(GTF_reading|GTF_writing))
panic("xengrantend frame in use");
}
coherence();
frame = gt->frame;
gt->flags = GTF_invalid;
freeref(ref);
return frame;
}
|