aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/grant_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'xen/common/grant_table.c')
-rw-r--r--xen/common/grant_table.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
new file mode 100644
index 0000000000..f1a73cb36a
--- /dev/null
+++ b/xen/common/grant_table.c
@@ -0,0 +1,134 @@
+/******************************************************************************
+ * common/grant_table.c
+ *
+ * Mechanism for granting foreign access to page frames, and receiving
+ * page-ownership transfers.
+ *
+ * Copyright (c) 2004 K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define __GRANT_TABLE_IMPLEMENTATION__
+typedef struct grant_table grant_table_t;
+
+#include <xen/config.h>
+#include <xen/sched.h>
+#include <hypervisor-ifs/grant_table.h>
+
+/* Active grant entry - used for shadowing GTF_permit_access grants. */
+typedef struct {
+ u32 counts; /* Reference count information. */
+ u16 next; /* Mapping hash chain. */
+ domid_t domid; /* Domain being granted access. */
+ unsigned long frame; /* Frame being granted. */
+} active_grant_entry_t;
+
+/* Bitfields in active_grant_entry_t:counts. */
+ /* Grant is pinned by 'domid' for read mappings and I/O. */
+#define _GNTCNT_read_pinned (0)
+#define GNTCNT_read_pinned (1<<_GNTCNT_read_pinned)
+ /* Grant is pinned by 'domid' for write mappings and I/O. */
+#define _GNTCNT_write_pinned (1)
+#define GNTCNT_write_pinned (1<<_GNTCNT_write_pinned)
+ /* Grant is pinned in IOMMU (read-only unless GNTCNT_write_pinned). */
+#define _GNTCNT_io_pinned (2)
+#define GNTCNT_io_pinned (1<<_GNTCNT_io_pinned)
+ /* Grant is mappable (read-only unless GNTCNT_write_pinned). */
+#define _GNTCNT_mappable (3)
+#define GNTCNT_mappable (1<<_GNTCNT_mappable)
+ /* Count of writable page mappings. (!GNTCNT_write_pinned => count==0). */
+#define GNTCNT_wmap_shift (4)
+#define GNTCNT_wmap_mask (0x3FFFU << GNTCNT_wmap_shift)
+ /* Count of read-only page mappings. */
+#define GNTCNT_rmap_shift (18)
+#define GNTCNT_rmap_mask (0x3FFFU << GNTCNT_rmap_shift)
+
+#define MAPHASH_SZ (256)
+#define MAPHASH(_k) ((_k) & (MAPHASH_SZ-1))
+#define MAPHASH_INVALID (0xFFFFU)
+
+#define NR_GRANT_ENTRIES (PAGE_SIZE / sizeof(grant_entry_t))
+
+/* Per-domain grant information. */
+struct grant_table {
+ /* Shared grant table (see include/hypervisor-ifs/grant_table.h). */
+ grant_entry_t *shared;
+ /* Active grant table. */
+ active_grant_entry_t *active;
+ /* Lock protecting updates to maphash and shared grant table. */
+ spinlock_t lock;
+ /* Hash table: frame -> active grant entry. */
+ u16 maphash[MAPHASH_SZ];
+};
+
+int grant_table_create(struct domain *d)
+{
+ grant_table_t *t;
+ int i;
+
+ if ( (t = xmalloc(sizeof(grant_table_t))) == NULL )
+ goto no_mem;
+
+ /* Simple stuff. */
+ t->shared = NULL;
+ t->active = NULL;
+ spin_lock_init(&t->lock);
+ for ( i = 0; i < MAPHASH_SZ; i++ )
+ t->maphash[i] = MAPHASH_INVALID;
+
+ /* Active grant-table page. */
+ if ( (t->active = xmalloc(sizeof(active_grant_entry_t) *
+ NR_GRANT_ENTRIES)) == NULL )
+ goto no_mem;
+
+ /* Set up shared grant-table page. */
+ if ( (t->shared = (void *)alloc_xenheap_page()) == NULL )
+ goto no_mem;
+ memset(t->shared, 0, PAGE_SIZE);
+ SHARE_PFN_WITH_DOMAIN(virt_to_page(t->shared), d);
+
+ /* Okay, install the structure. */
+ d->grant_table = t;
+ return 0;
+
+ no_mem:
+ if ( t != NULL )
+ {
+ if ( t->active != NULL )
+ xfree(t->active);
+ xfree(t);
+ }
+ return -ENOMEM;
+}
+
+void grant_table_destroy(struct domain *d)
+{
+ grant_table_t *t;
+
+ if ( (t = d->grant_table) != NULL )
+ {
+ /* Free memory relating to this grant table. */
+ d->grant_table = NULL;
+ free_xenheap_page((unsigned long)t->shared);
+ xfree(t->active);
+ xfree(t);
+ }
+}
+
+void grant_table_init(void)
+{
+ /* Nothing. */
+}