aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-08-20 16:23:53 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-08-20 16:23:53 +0000
commitaacd829062b0e4d6c5d9edf8eb393a27d15a732c (patch)
tree61802c0e47cd9ee9a6029dbaa066038c53751004
parent5b401367bf9f11d71890105bb62c317875a6300e (diff)
parent1143caf2de0467cec229d3f2b740f86d7530f885 (diff)
downloadxen-aacd829062b0e4d6c5d9edf8eb393a27d15a732c.tar.gz
xen-aacd829062b0e4d6c5d9edf8eb393a27d15a732c.tar.bz2
xen-aacd829062b0e4d6c5d9edf8eb393a27d15a732c.zip
bitkeeper revision 1.1159.45.13 (41262599YpMzJIP5GvyznLSES5h5OQ)
Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xeno
-rw-r--r--.rootkeys2
-rw-r--r--xen/arch/x86/domain.c17
-rw-r--r--xen/common/domain.c8
-rw-r--r--xen/common/grant_table.c134
-rw-r--r--xen/common/kernel.c2
-rw-r--r--xen/common/page_alloc.c2
-rw-r--r--xen/include/asm-x86/mm.h1
-rw-r--r--xen/include/xen/grant_table.h38
-rw-r--r--xen/include/xen/sched.h8
9 files changed, 200 insertions, 12 deletions
diff --git a/.rootkeys b/.rootkeys
index 8914576fd3..fb385053ed 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -572,6 +572,7 @@
3ddb79bdYO5D8Av12NHqPeSviav7cg xen/common/domain.c
40f2b4a27xPOh3R6zD4M_aabz-TDyg xen/common/elf.c
3fba5b96H0khoxNiKbjdi0inpXV-Pw xen/common/event_channel.c
+41262590gGIOn-1pvF5KpUu8Wb6_JA xen/common/grant_table.c
3ddb79bd9drcFPVxd4w2GPOIjLlXpA xen/common/kernel.c
3e4cd9d8LAAghUY0hNIK72uc2ch_Nw xen/common/keyhandler.c
3ddb79bduhSEZI8xa7IbGQCpap5y2A xen/common/lib.c
@@ -720,6 +721,7 @@
3ddb79c2O729EttZTYu1c8LcsUO_GQ xen/include/xen/elf.h
3ddb79c0HIghfBF8zFUdmXhOU8i6hA xen/include/xen/errno.h
3ddb79c1W0lQca8gRV7sN6j3iY4Luw xen/include/xen/event.h
+41262590CyJy4vd42dnqzsn8-eeGvw xen/include/xen/grant_table.h
3ddb79c0GurNF9tDWqQbAwJFH8ugfA xen/include/xen/init.h
3ddb79c1nzaWu8NoF4xCCMSFJR4MlA xen/include/xen/ioport.h
3ddb79c2qAxCOABlkKtD8Txohe-qEw xen/include/xen/irq.h
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index c95d5021c9..7a3afdd753 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -472,13 +472,19 @@ void domain_relinquish_memory(struct domain *d)
*/
destroy_gdt(d);
- /* Relinquish Xen-heap pages. Currently this can only be 'shared_info'. */
- page = virt_to_page(d->shared_info);
- if ( test_and_clear_bit(_PGC_allocated, &page->u.inuse.count_info) )
- put_page(page);
+ /* Use a recursive lock, as we may enter 'free_domheap_page'. */
+ spin_lock_recursive(&d->page_alloc_lock);
+
+ /* Relinquish Xen-heap pages. */
+ list_for_each_safe ( ent, tmp, &d->xenpage_list )
+ {
+ page = list_entry(ent, struct pfn_info, list);
+
+ if ( test_and_clear_bit(_PGC_allocated, &page->u.inuse.count_info) )
+ put_page(page);
+ }
/* Relinquish all pages on the domain's allocation list. */
- spin_lock_recursive(&d->page_alloc_lock); /* may enter free_domheap_page */
list_for_each_safe ( ent, tmp, &d->page_list )
{
page = list_entry(ent, struct pfn_info, list);
@@ -507,6 +513,7 @@ void domain_relinquish_memory(struct domain *d)
}
while ( unlikely(y != x) );
}
+
spin_unlock_recursive(&d->page_alloc_lock);
}
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 4ca9f58135..7f5d2bafe8 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -45,7 +45,7 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
spin_lock_init(&d->page_alloc_lock);
INIT_LIST_HEAD(&d->page_list);
- d->max_pages = d->tot_pages = 0;
+ INIT_LIST_HEAD(&d->xenpage_list);
/* Per-domain PCI-device list. */
spin_lock_init(&d->pcidev_lock);
@@ -53,12 +53,13 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
if ( d->domain != IDLE_DOMAIN_ID )
{
- if ( init_event_channels(d) != 0 )
+ if ( (init_event_channels(d) != 0) || (grant_table_create(d) != 0) )
{
+ destroy_event_channels(d);
free_domain_struct(d);
return NULL;
}
-
+
/* We use a large intermediate to avoid overflow in sprintf. */
sprintf(buf, "Domain-%u", dom_id);
strncpy(d->name, buf, MAX_DOMAIN_NAME);
@@ -256,6 +257,7 @@ void domain_destruct(struct domain *d)
write_unlock_irqrestore(&tasklist_lock, flags);
destroy_event_channels(d);
+ grant_table_destroy(d);
free_perdomain_pt(d);
free_xenheap_page((unsigned long)d->shared_info);
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. */
+}
diff --git a/xen/common/kernel.c b/xen/common/kernel.c
index 707cede7f1..6c0775c9d2 100644
--- a/xen/common/kernel.c
+++ b/xen/common/kernel.c
@@ -304,6 +304,8 @@ void cmain(multiboot_info_t *mbi)
start_of_day();
+ grant_table_init();
+
/* Create initial domain 0. */
new_dom = do_createdomain(0, 0);
if ( new_dom == NULL )
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 323ecd244e..52da9c042b 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -418,6 +418,8 @@ void free_domheap_pages(struct pfn_info *pg, int order)
if ( unlikely(IS_XEN_HEAP_FRAME(pg)) )
{
spin_lock_recursive(&d->page_alloc_lock);
+ for ( i = 0; i < (1 << order); i++ )
+ list_del(&pg[i].list);
d->xenheap_pages -= 1 << order;
drop_dom_ref = (d->xenheap_pages == 0);
spin_unlock_recursive(&d->page_alloc_lock);
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index a2fc40e0b3..5cd3c01ae6 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -109,6 +109,7 @@ struct pfn_info
(_pfn)->u.inuse.count_info = PGC_allocated | 1; \
if ( unlikely((_dom)->xenheap_pages++ == 0) ) \
get_knownalive_domain(_dom); \
+ list_add_tail(&(_pfn)->list, &(_dom)->xenpage_list); \
spin_unlock(&(_dom)->page_alloc_lock); \
} while ( 0 )
diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
new file mode 100644
index 0000000000..92a81de929
--- /dev/null
+++ b/xen/include/xen/grant_table.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ * include/xen/grant_table.h
+ *
+ * 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
+ */
+
+#ifndef __XEN_GRANT_H__
+#define __XEN_GRANT_H__
+
+#ifndef __GRANT_TABLE_IMPLEMENTATION__
+typedef void grant_table_t;
+#endif
+
+/* Start-of-day system initialisation. */
+void grant_table_init(void);
+
+/* Create/destroy per-domain grant table context. */
+int grant_table_create(struct domain *d);
+void grant_table_destroy(struct domain *d);
+
+#endif /* __XEN_GRANT_H__ */
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index af74cf5380..dfea4b7509 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -4,16 +4,13 @@
#include <xen/config.h>
#include <xen/types.h>
#include <xen/spinlock.h>
-#ifdef LINUX_2_6
-#include <linux/thread_info.h>
-#endif
#include <asm/ptrace.h>
#include <xen/smp.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <hypervisor-ifs/hypervisor-if.h>
#include <hypervisor-ifs/dom0_ops.h>
-
+#include <xen/grant_table.h>
#include <xen/list.h>
#include <xen/time.h>
#include <xen/ac_timer.h>
@@ -95,6 +92,7 @@ struct domain
spinlock_t page_alloc_lock; /* protects all the following fields */
struct list_head page_list; /* linked list, of size tot_pages */
+ struct list_head xenpage_list; /* linked list, of size xenheap_pages */
unsigned int tot_pages; /* number of pages currently possesed */
unsigned int max_pages; /* maximum value for tot_pages */
unsigned int xenheap_pages; /* # pages allocated from Xen heap */
@@ -121,6 +119,8 @@ struct domain
unsigned int max_event_channel;
spinlock_t event_channel_lock;
+ grant_table_t *grant_table;
+
/*
* Interrupt to event-channel mappings. Updates should be protected by the
* domain's event-channel spinlock. Read accesses can also synchronise on