100 lines
1.9 KiB
C
100 lines
1.9 KiB
C
/*
|
|
* 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;
|
|
}
|