summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2015-12-22 22:16:54 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2015-12-22 22:16:54 +0000
commitbaec026e1d85d3d6a77263ad1491a627a2ccd8f7 (patch)
tree28a55d443ceaa4a49b7161d45a7ea1caa4896af1
parent52b52cce5d8bdf6b0288e6f304933bba62299408 (diff)
Implement a bus_dma(9) abstraction on top of Grant Table API
-rw-r--r--sys/dev/pv/xen.c379
-rw-r--r--sys/dev/pv/xenreg.h126
-rw-r--r--sys/dev/pv/xenstore.c4
-rw-r--r--sys/dev/pv/xenvar.h26
4 files changed, 529 insertions, 6 deletions
diff --git a/sys/dev/pv/xen.c b/sys/dev/pv/xen.c
index d2e7072ff09..751bc2faa6e 100644
--- a/sys/dev/pv/xen.c
+++ b/sys/dev/pv/xen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xen.c,v 1.18 2015/12/21 19:43:16 mikeb Exp $ */
+/* $OpenBSD: xen.c,v 1.19 2015/12/22 22:16:53 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -44,6 +44,13 @@ int xen_getfeatures(struct xen_softc *);
int xen_init_info_page(struct xen_softc *);
int xen_init_cbvec(struct xen_softc *);
int xen_init_interrupts(struct xen_softc *);
+int xen_init_grant_tables(struct xen_softc *);
+struct xen_gntent *
+ xen_grant_table_grow(struct xen_softc *);
+int xen_grant_table_alloc(struct xen_softc *, grant_ref_t *);
+void xen_grant_table_free(struct xen_softc *, grant_ref_t);
+int xen_grant_table_enter(struct xen_softc *, grant_ref_t, paddr_t, int);
+void xen_grant_table_remove(struct xen_softc *, grant_ref_t);
void xen_disable_emulated_devices(struct xen_softc *);
int xen_match(struct device *, void *, void *);
@@ -53,6 +60,16 @@ void xen_resume(struct device *);
int xen_activate(struct device *, int);
int xen_probe_devices(struct xen_softc *);
+void xen_bus_dma_init(struct xen_softc *);
+int xen_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
+ bus_size_t, int, bus_dmamap_t *);
+void xen_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
+int xen_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
+ struct proc *, int);
+int xen_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *,
+ int);
+void xen_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
+
int xs_attach(struct xen_softc *);
struct cfdriver xen_cd = {
@@ -63,6 +80,24 @@ const struct cfattach xen_ca = {
sizeof(struct xen_softc), xen_match, xen_attach, NULL, xen_activate
};
+struct bus_dma_tag xen_bus_dma_tag = {
+ NULL,
+ xen_bus_dmamap_create,
+ xen_bus_dmamap_destroy,
+ xen_bus_dmamap_load,
+ xen_bus_dmamap_load_mbuf,
+ NULL,
+ NULL,
+ xen_bus_dmamap_unload,
+ _bus_dmamap_sync,
+ _bus_dmamem_alloc,
+ NULL,
+ _bus_dmamem_free,
+ _bus_dmamem_map,
+ _bus_dmamem_unmap,
+ NULL,
+};
+
int
xen_match(struct device *parent, void *match, void *aux)
{
@@ -105,6 +140,9 @@ xen_attach(struct device *parent, struct device *self, void *aux)
if (xen_init_interrupts(sc))
return;
+ if (xen_init_grant_tables(sc))
+ return;
+
if (xs_attach(sc))
return;
@@ -732,6 +770,343 @@ xen_intr_unmask(xen_intr_handle_t xih)
return (0);
}
+int
+xen_init_grant_tables(struct xen_softc *sc)
+{
+ struct gnttab_query_size gqs;
+ struct gnttab_get_version ggv;
+ struct gnttab_set_version gsv;
+ int i;
+
+ gqs.dom = DOMID_SELF;
+ if (xen_hypercall(sc, XC_GNTTAB, 3, GNTTABOP_query_size, &gqs, 1)) {
+ printf("%s: failed the query for grant table pages\n",
+ sc->sc_dev.dv_xname);
+ return (-1);
+ }
+ if (gqs.nr_frames == 0 || gqs.nr_frames > gqs.max_nr_frames) {
+ printf("%s: invalid number of grant table pages: %u/%u\n",
+ sc->sc_dev.dv_xname, gqs.nr_frames, gqs.max_nr_frames);
+ return (-1);
+ }
+
+ DPRINTF("%s: grant table frames allocated %u, max %u\n",
+ sc->sc_dev.dv_xname, gqs.nr_frames, gqs.max_nr_frames);
+
+ gsv.version = 2;
+ ggv.dom = DOMID_SELF;
+ if (xen_hypercall(sc, XC_GNTTAB, 3, GNTTABOP_set_version, &gsv, 1) ||
+ xen_hypercall(sc, XC_GNTTAB, 3, GNTTABOP_get_version, &ggv, 1) ||
+ ggv.version != 2) {
+ printf("%s: failed to set grant tables API version\n",
+ sc->sc_dev.dv_xname);
+ return (-1);
+ }
+
+ SLIST_INIT(&sc->sc_gnts);
+
+ for (i = 0; i < gqs.nr_frames; i++)
+ if (xen_grant_table_grow(sc) == NULL)
+ break;
+
+ sc->sc_gntmax = gqs.max_nr_frames;
+
+ xen_bus_dma_init(sc);
+
+ return (0);
+}
+
+struct xen_gntent *
+xen_grant_table_grow(struct xen_softc *sc)
+{
+ struct xen_add_to_physmap xatp;
+ struct xen_gntent *ge;
+ paddr_t pa;
+
+ ge = malloc(sizeof(*ge), M_DEVBUF, M_ZERO | M_NOWAIT);
+ if (ge == NULL) {
+ printf("%s: failed to allocate a grant table entry\n",
+ sc->sc_dev.dv_xname);
+ return (NULL);
+ }
+ ge->ge_table = km_alloc(PAGE_SIZE, &kv_any, &kp_zero,
+ &kd_nowait);
+ if (ge->ge_table == NULL) {
+ free(ge, M_DEVBUF, sizeof(*ge));
+ return (NULL);
+ }
+ if (!pmap_extract(pmap_kernel(), (vaddr_t)ge->ge_table, &pa)) {
+ printf("%s: grant table page PA extraction failed\n",
+ sc->sc_dev.dv_xname);
+ km_free(ge->ge_table, PAGE_SIZE, &kv_any, &kp_zero);
+ free(ge, M_DEVBUF, sizeof(*ge));
+ return (NULL);
+ }
+ xatp.domid = DOMID_SELF;
+ xatp.idx = sc->sc_gntcnt;
+ xatp.space = XENMAPSPACE_grant_table;
+ xatp.gpfn = atop(pa);
+ if (xen_hypercall(sc, XC_MEMORY, 2, XENMEM_add_to_physmap, &xatp)) {
+ printf("%s: failed to add a grant table page\n",
+ sc->sc_dev.dv_xname);
+ km_free(ge->ge_table, PAGE_SIZE, &kv_any, &kp_zero);
+ free(ge, M_DEVBUF, sizeof(*ge));
+ return (NULL);
+ }
+ ge->ge_start = sc->sc_gntcnt * GNTTAB_NEPG;
+ /* First page has 8 reserved entries */
+ ge->ge_reserved = ge->ge_start == 0 ? GNTTAB_NR_RESERVED_ENTRIES : 0;
+ ge->ge_free = GNTTAB_NEPG - ge->ge_reserved;
+ ge->ge_next = ge->ge_reserved ? ge->ge_reserved + 1 : 0;
+ mtx_init(&ge->ge_mtx, IPL_NET);
+ SLIST_INSERT_HEAD(&sc->sc_gnts, ge, ge_entry);
+
+ DPRINTF("%s: grant table frame %d start %d pa %#lx\n",
+ sc->sc_dev.dv_xname, sc->sc_gntcnt, ge->ge_start, pa);
+
+ sc->sc_gntcnt++;
+
+ return (ge);
+}
+
+int
+xen_grant_table_alloc(struct xen_softc *sc, grant_ref_t *ref)
+{
+ struct xen_gntent *ge;
+ int i;
+
+ retry:
+ SLIST_FOREACH(ge, &sc->sc_gnts, ge_entry) {
+ if (!ge->ge_free)
+ continue;
+ mtx_enter(&ge->ge_mtx);
+ for (i = ge->ge_next;
+ /* Math works here because GNTTAB_NEPG is a power of 2 */
+ i != ((ge->ge_next + GNTTAB_NEPG - 1) & (GNTTAB_NEPG - 1));
+ i++) {
+ if (i == GNTTAB_NEPG)
+ i = 0;
+ if (ge->ge_reserved && i < ge->ge_reserved)
+ continue;
+ if (ge->ge_table[i].hdr.flags != GTF_invalid &&
+ ge->ge_table[i].full_page.frame != 0)
+ continue;
+ *ref = ge->ge_start + i;
+ /* XXX Mark as taken */
+ ge->ge_table[i].full_page.frame = 0xffffffff;
+ if ((ge->ge_next = i + 1) == GNTTAB_NEPG)
+ ge->ge_next = ge->ge_reserved + 1;
+ ge->ge_free--;
+ mtx_leave(&ge->ge_mtx);
+ return (0);
+ }
+ mtx_leave(&ge->ge_mtx);
+ }
+
+ /* We're out of entries, try growing the table */
+ if (sc->sc_gntcnt >= sc->sc_gntmax)
+ return (-1);
+
+ if (xen_grant_table_grow(sc) != NULL)
+ goto retry;
+
+ return (-1);
+}
+
+void
+xen_grant_table_free(struct xen_softc *sc, grant_ref_t ref)
+{
+ struct xen_gntent *ge;
+
+ SLIST_FOREACH(ge, &sc->sc_gnts, ge_entry) {
+ if (ref < ge->ge_start || ref > ge->ge_start + GNTTAB_NEPG)
+ continue;
+ ref -= ge->ge_start;
+ mtx_enter(&ge->ge_mtx);
+ if (ge->ge_table[ref].hdr.flags != GTF_invalid) {
+ mtx_leave(&ge->ge_mtx);
+ return;
+ }
+ ge->ge_table[ref].full_page.frame = 0;
+ ge->ge_next = ref;
+ ge->ge_free++;
+ mtx_leave(&ge->ge_mtx);
+ }
+}
+
+int
+xen_grant_table_enter(struct xen_softc *sc, grant_ref_t ref, paddr_t pa,
+ int flags)
+{
+ struct xen_gntent *ge;
+
+ SLIST_FOREACH(ge, &sc->sc_gnts, ge_entry) {
+ if (ref < ge->ge_start || ref > ge->ge_start + GNTTAB_NEPG)
+ continue;
+ ref -= ge->ge_start;
+ mtx_enter(&ge->ge_mtx);
+ ge->ge_table[ref].full_page.frame = atop(pa);
+ ge->ge_table[ref].full_page.hdr.domid = 0;
+ membar_producer();
+ ge->ge_table[ref].full_page.hdr.flags =
+ GTF_permit_access | flags;
+ mtx_leave(&ge->ge_mtx);
+ return (0);
+ }
+ return (ENOBUFS);
+}
+
+void
+xen_grant_table_remove(struct xen_softc *sc, grant_ref_t ref)
+{
+ struct xen_gntent *ge;
+ uint32_t flags, *ptr;
+
+ SLIST_FOREACH(ge, &sc->sc_gnts, ge_entry) {
+ if (ref < ge->ge_start || ref > ge->ge_start + GNTTAB_NEPG)
+ continue;
+ ref -= ge->ge_start;
+
+ mtx_enter(&ge->ge_mtx);
+ /* Invalidate the grant reference */
+ ptr = (uint32_t *)&ge->ge_table[ref].hdr;
+ flags = (ge->ge_table[ref].hdr.flags &
+ ~(GTF_reading | GTF_writing));
+ while (atomic_cas_uint(ptr, flags, 0) != flags)
+ CPU_BUSY_CYCLE();
+ ge->ge_table[ref].full_page.frame = 0xffffffff;
+ mtx_leave(&ge->ge_mtx);
+ break;
+ }
+}
+
+void
+xen_bus_dma_init(struct xen_softc *sc)
+{
+ xen_bus_dma_tag._cookie = sc;
+}
+
+int
+xen_bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
+ bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
+{
+ struct xen_softc *sc = t->_cookie;
+ struct xen_gntmap *gm;
+ int i, error;
+
+ if (maxsegsz < PAGE_SIZE)
+ return (EINVAL);
+
+ /* Allocate a dma map structure */
+ error = _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary,
+ flags, dmamp);
+ if (error)
+ return (error);
+ /* ALlocate an array of grant table pa<->ref maps */
+ gm = mallocarray(nsegments, sizeof(struct xen_gntmap), M_DEVBUF,
+ M_ZERO | ((flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK));
+ if (gm == NULL) {
+ _bus_dmamap_destroy(t, *dmamp);
+ *dmamp = NULL;
+ return (ENOMEM);
+ }
+ /* Wire it to the dma map */
+ (*dmamp)->_dm_cookie = gm;
+ /* Claim references from the grant table */
+ for (i = 0; i < (*dmamp)->_dm_segcnt; i++) {
+ if (xen_grant_table_alloc(sc, &gm[i].gm_ref)) {
+ xen_bus_dmamap_destroy(t, *dmamp);
+ *dmamp = NULL;
+ return (ENOBUFS);
+ }
+ }
+ return (0);
+}
+
+void
+xen_bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
+{
+ struct xen_softc *sc = t->_cookie;
+ struct xen_gntmap *gm;
+ int i;
+
+ gm = map->_dm_cookie;
+ for (i = 0; i < map->_dm_segcnt; i++) {
+ if (gm[i].gm_ref == 0)
+ continue;
+ xen_grant_table_free(sc, gm[i].gm_ref);
+ }
+ free(gm, M_DEVBUF, map->_dm_segcnt * sizeof(struct xen_gntmap));
+ _bus_dmamap_destroy(t, map);
+}
+
+int
+xen_bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
+ bus_size_t buflen, struct proc *p, int flags)
+{
+ struct xen_softc *sc = t->_cookie;
+ struct xen_gntmap *gm = map->_dm_cookie;
+ int i, error;
+
+ error = _bus_dmamap_load(t, map, buf, buflen, p, flags);
+ if (error)
+ return (error);
+ for (i = 0; i < map->dm_nsegs; i++) {
+ error = xen_grant_table_enter(sc, gm[i].gm_ref,
+ map->dm_segs[i].ds_addr, flags & BUS_DMA_WRITE ?
+ GTF_readonly : 0);
+ if (error) {
+ xen_bus_dmamap_unload(t, map);
+ return (error);
+ }
+ gm[i].gm_paddr = map->dm_segs[i].ds_addr;
+ map->dm_segs[i].ds_addr = gm[i].gm_ref;
+ }
+ return (0);
+}
+
+int
+xen_bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0,
+ int flags)
+{
+ struct xen_softc *sc = t->_cookie;
+ struct xen_gntmap *gm = map->_dm_cookie;
+ int i, error;
+
+ error = _bus_dmamap_load_mbuf(t, map, m0, flags);
+ if (error)
+ return (error);
+ for (i = 0; i < map->dm_nsegs; i++) {
+ error = xen_grant_table_enter(sc, gm[i].gm_ref,
+ map->dm_segs[i].ds_addr, flags & BUS_DMA_WRITE ?
+ GTF_readonly : 0);
+ if (error) {
+ xen_bus_dmamap_unload(t, map);
+ return (error);
+ }
+ gm[i].gm_paddr = map->dm_segs[i].ds_addr;
+ map->dm_segs[i].ds_addr = gm[i].gm_ref;
+ }
+ return (0);
+}
+
+void
+xen_bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
+{
+ struct xen_softc *sc = t->_cookie;
+ struct xen_gntmap *gm = map->_dm_cookie;
+ int i;
+
+ for (i = 0; i < map->dm_nsegs; i++) {
+ if (gm[i].gm_paddr == 0)
+ continue;
+ xen_grant_table_remove(sc, gm[i].gm_ref);
+ map->dm_segs[i].ds_addr = gm[i].gm_paddr;
+ gm[i].gm_paddr = 0;
+ }
+ _bus_dmamap_unload(t, map);
+}
+
static int
xen_attach_print(void *aux, const char *name)
{
@@ -765,6 +1140,7 @@ xen_probe_devices(struct xen_softc *sc)
/* Special handling */
if (!strcmp("suspend", (char *)iovp1[i].iov_base)) {
xa.xa_parent = sc;
+ xa.xa_dmat = &xen_bus_dma_tag;
strlcpy(xa.xa_name, (char *)iovp1[i].iov_base,
sizeof(xa.xa_name));
snprintf(xa.xa_node, sizeof(xa.xa_node), "device/%s",
@@ -782,6 +1158,7 @@ xen_probe_devices(struct xen_softc *sc)
}
for (j = 0; j < iov2_cnt; j++) {
xa.xa_parent = sc;
+ xa.xa_dmat = &xen_bus_dma_tag;
strlcpy(xa.xa_name, (char *)iovp1[i].iov_base,
sizeof(xa.xa_name));
snprintf(xa.xa_node, sizeof(xa.xa_node), "device/%s/%s",
diff --git a/sys/dev/pv/xenreg.h b/sys/dev/pv/xenreg.h
index d3a694f3aa8..5bdbbd709dd 100644
--- a/sys/dev/pv/xenreg.h
+++ b/sys/dev/pv/xenreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xenreg.h,v 1.5 2015/12/12 21:07:45 reyk Exp $ */
+/* $OpenBSD: xenreg.h,v 1.6 2015/12/22 22:16:53 mikeb Exp $ */
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -578,6 +578,130 @@ struct evtchn_unmask {
/* operation as Dom0 is supported */
#define XENFEAT_dom0 11
+
+/*
+ * interface/grant_table.h
+ */
+
+/*
+ * Reference to a grant entry in a specified domain's grant table.
+ */
+typedef uint32_t grant_ref_t;
+
+/*
+ * The first few grant table entries will be preserved across grant table
+ * version changes and may be pre-populated at domain creation by tools.
+ */
+#define GNTTAB_NR_RESERVED_ENTRIES 8
+
+/*
+ * Type of grant entry.
+ * GTF_invalid: This grant entry grants no privileges.
+ * GTF_permit_access: Allow @domid to map/access @frame.
+ * GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
+ * to this guest. Xen writes the page number to @frame.
+ * GTF_transitive: Allow @domid to transitively access a subrange of
+ * @trans_grant in @trans_domid. No mappings are allowed.
+ */
+#define GTF_invalid (0<<0)
+#define GTF_permit_access (1<<0)
+#define GTF_accept_transfer (2<<0)
+#define GTF_transitive (3<<0)
+#define GTF_type_mask (3<<0)
+
+/*
+ * Subflags for GTF_permit_access.
+ * GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
+ * GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
+ * GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
+ * GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
+ * GTF_sub_page: Grant access to only a subrange of the page. @domid
+ * will only be allowed to copy from the grant, and not
+ * map it. [GST]
+ */
+#define GTF_readonly (1<<2)
+#define GTF_reading (1<<3)
+#define GTF_writing (1<<4)
+#define GTF_PWT (1<<5)
+#define GTF_PCD (1<<6)
+#define GTF_PAT (1<<7)
+#define GTF_sub_page (1<<8)
+
+struct grant_entry_header {
+ uint16_t flags;
+ domid_t domid;
+};
+
+typedef union grant_entry {
+ struct grant_entry_header hdr;
+
+ /*
+ * This member is used for V1-style full page grants, where either:
+ *
+ * -- hdr.type is GTF_accept_transfer, or
+ * -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
+ *
+ * In that case, the frame field has the same semantics as the
+ * field of the same name in the V1 entry structure.
+ */
+ struct {
+ struct grant_entry_header hdr;
+ uint32_t pad0;
+ uint64_t frame;
+ } full_page;
+
+ uint32_t __spacer[4]; /* Pad to a power of two */
+} grant_entry_t;
+
+/* Number of grant table entries per memory page */
+#define GNTTAB_NEPG (PAGE_SIZE / sizeof(grant_entry_t))
+
+#define GNTTABOP_query_size 6
+#define GNTTABOP_unmap_and_replace 7
+#define GNTTABOP_set_version 8
+#define GNTTABOP_get_version 10
+
+/*
+ * GNTTABOP_query_size: Query the current and maximum sizes of the shared
+ * grant table.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
+ */
+struct gnttab_query_size {
+ /* IN parameters. */
+ domid_t dom;
+ /* OUT parameters. */
+ uint32_t nr_frames;
+ uint32_t max_nr_frames;
+ int16_t status; /* => enum grant_status */
+};
+
+/*
+ * GNTTABOP_set_version: Request a particular version of the grant
+ * table shared table structure. This operation can only be performed
+ * once in any given domain. It must be performed before any grants
+ * are activated; otherwise, the domain will be stuck with version 1.
+ * The only defined versions are 1 and 2.
+ */
+struct gnttab_set_version {
+ /* IN/OUT parameters */
+ uint32_t version;
+};
+
+/*
+ * GNTTABOP_get_version: Get the grant table version which is in
+ * effect for domain <dom>.
+ */
+struct gnttab_get_version {
+ /* IN parameters */
+ domid_t dom;
+ uint16_t pad;
+ /* OUT parameters */
+ uint32_t version;
+};
+
+
/*
* interface/memory.h
*
diff --git a/sys/dev/pv/xenstore.c b/sys/dev/pv/xenstore.c
index 53e67283cc4..45d1664be9d 100644
--- a/sys/dev/pv/xenstore.c
+++ b/sys/dev/pv/xenstore.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xenstore.c,v 1.9 2015/12/21 18:17:36 mikeb Exp $ */
+/* $OpenBSD: xenstore.c,v 1.10 2015/12/22 22:16:53 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -24,6 +24,8 @@
#include <sys/device.h>
#include <sys/mutex.h>
+#include <machine/bus.h>
+
#include <uvm/uvm_extern.h>
#include <dev/pv/xenreg.h>
diff --git a/sys/dev/pv/xenvar.h b/sys/dev/pv/xenvar.h
index 6b0c136c58f..2d693d5eb07 100644
--- a/sys/dev/pv/xenvar.h
+++ b/sys/dev/pv/xenvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xenvar.h,v 1.15 2015/12/21 19:43:16 mikeb Exp $ */
+/* $OpenBSD: xenvar.h,v 1.16 2015/12/22 22:16:53 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -33,8 +33,23 @@ struct xen_intsrc {
void *xi_arg;
struct evcount xi_evcnt;
evtchn_port_t xi_port;
- int xi_noclose;
- int xi_masked;
+ short xi_noclose;
+ short xi_masked;
+};
+
+struct xen_gntent {
+ SLIST_ENTRY(xen_gntent) ge_entry;
+ grant_entry_t *ge_table;
+ grant_ref_t ge_start;
+ short ge_reserved;
+ short ge_next;
+ short ge_free;
+ struct mutex ge_mtx;
+};
+
+struct xen_gntmap {
+ grant_ref_t gm_ref;
+ paddr_t gm_paddr;
};
struct xen_softc {
@@ -51,6 +66,10 @@ struct xen_softc {
struct evcount sc_evcnt; /* upcall counter */
SLIST_HEAD(, xen_intsrc) sc_intrs;
+ SLIST_HEAD(, xen_gntent) sc_gnts; /* grant table entries */
+ int sc_gntcnt; /* current number of pages */
+ int sc_gntmax; /* maximum number of pages */
+
/*
* Xenstore
*/
@@ -64,6 +83,7 @@ struct xen_attach_args {
char xa_name[16];
char xa_node[64];
char xa_backend[128];
+ bus_dma_tag_t xa_dmat;
};
/*