diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-08-20 16:23:53 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-08-20 16:23:53 +0000 |
commit | aacd829062b0e4d6c5d9edf8eb393a27d15a732c (patch) | |
tree | 61802c0e47cd9ee9a6029dbaa066038c53751004 | |
parent | 5b401367bf9f11d71890105bb62c317875a6300e (diff) | |
parent | 1143caf2de0467cec229d3f2b740f86d7530f885 (diff) | |
download | xen-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-- | .rootkeys | 2 | ||||
-rw-r--r-- | xen/arch/x86/domain.c | 17 | ||||
-rw-r--r-- | xen/common/domain.c | 8 | ||||
-rw-r--r-- | xen/common/grant_table.c | 134 | ||||
-rw-r--r-- | xen/common/kernel.c | 2 | ||||
-rw-r--r-- | xen/common/page_alloc.c | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/mm.h | 1 | ||||
-rw-r--r-- | xen/include/xen/grant_table.h | 38 | ||||
-rw-r--r-- | xen/include/xen/sched.h | 8 |
9 files changed, 200 insertions, 12 deletions
@@ -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 |