diff options
author | Doug Rabson <dfr@FreeBSD.org> | 2009-03-11 15:30:12 +0000 |
---|---|---|
committer | Doug Rabson <dfr@FreeBSD.org> | 2009-03-11 15:30:12 +0000 |
commit | 126780243806a6b6cf345b9b548f68010e921aec (patch) | |
tree | 633dc40712503605071c68975d2c972638554000 /sys/xen/gnttab.c | |
parent | 802e54dc1f4ac7ebd3cc3f0091d2b825780a3c51 (diff) | |
download | src-126780243806a6b6cf345b9b548f68010e921aec.tar.gz src-126780243806a6b6cf345b9b548f68010e921aec.zip |
Merge in support for Xen HVM on amd64 architecture.
Notes
Notes:
svn path=/head/; revision=189699
Diffstat (limited to 'sys/xen/gnttab.c')
-rw-r--r-- | sys/xen/gnttab.c | 158 |
1 files changed, 114 insertions, 44 deletions
diff --git a/sys/xen/gnttab.c b/sys/xen/gnttab.c index 967565506dfc..d05790bbf84f 100644 --- a/sys/xen/gnttab.c +++ b/sys/xen/gnttab.c @@ -25,28 +25,20 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mman.h> -#include <vm/vm.h> -#include <vm/vm_extern.h> - -#include <vm/vm_page.h> -#include <vm/vm_kern.h> +#include <machine/xen/xen-os.h> #include <xen/hypervisor.h> #include <machine/xen/synch_bitops.h> -#include <xen/gnttab.h> -#define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c)) +#include <xen/hypervisor.h> +#include <xen/gnttab.h> -#if 1 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s': line %d, file %s\n", \ - #_p , __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) ((void)0) -#endif +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_extern.h> +#include <vm/pmap.h> -#define WPRINTK(fmt, args...) \ - printk("xen_grant: " fmt, ##args) +#define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c)) /* External tools reserve first few grant table entries. */ #define NR_RESERVED_ENTRIES 8 @@ -72,14 +64,14 @@ static int gnttab_expand(unsigned int req_entries); static int get_free_entries(int count, int *entries) { - int ref, rc; + int ref, error; grant_ref_t head; mtx_lock(&gnttab_list_lock); if ((gnttab_free_count < count) && - ((rc = gnttab_expand(count - gnttab_free_count)) != 0)) { + ((error = gnttab_expand(count - gnttab_free_count)) != 0)) { mtx_unlock(&gnttab_list_lock); - return (rc); + return (error); } ref = head = gnttab_free_head; gnttab_free_count -= count; @@ -163,6 +155,7 @@ void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, unsigned long frame, int readonly) { + shared[ref].frame = frame; shared[ref].domid = domid; wmb(); @@ -213,7 +206,8 @@ gnttab_end_foreign_access(grant_ref_t ref, void *page) } int -gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn) +gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn, + grant_ref_t *result) { int error, ref; @@ -223,7 +217,8 @@ gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn) gnttab_grant_foreign_transfer_ref(ref, domid, pfn); - return (ref); + *result = ref; + return (0); } void @@ -261,7 +256,7 @@ gnttab_end_foreign_transfer_ref(grant_ref_t ref) /* Read the frame number /after/ reading completion status. */ rmb(); frame = shared[ref].frame; - PANIC_IF(frame == 0); + KASSERT(frame != 0, ("grant table inconsistent")); return (frame); } @@ -320,6 +315,7 @@ gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head) int gnttab_empty_grant_references(const grant_ref_t *private_head) { + return (*private_head == GNTTAB_LIST_END); } @@ -331,20 +327,20 @@ gnttab_claim_grant_reference(grant_ref_t *private_head) if (unlikely(g == GNTTAB_LIST_END)) return (ENOSPC); *private_head = gnttab_entry(g); - return (g); } void gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release) { + gnttab_entry(release) = *private_head; *private_head = release; } void gnttab_request_free_callback(struct gnttab_free_callback *callback, - void (*fn)(void *), void *arg, uint16_t count) + void (*fn)(void *), void *arg, uint16_t count) { mtx_lock(&gnttab_list_lock); @@ -387,7 +383,8 @@ grow_gnttab_list(unsigned int more_frames) for (i = nr_grant_frames; i < new_nr_grant_frames; i++) { - gnttab_list[i] = (grant_ref_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); + gnttab_list[i] = (grant_ref_t *) + malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); if (!gnttab_list[i]) goto grow_nomem; @@ -405,12 +402,12 @@ grow_gnttab_list(unsigned int more_frames) check_free_callbacks(); - return 0; + return (0); grow_nomem: for ( ; i >= nr_grant_frames; i--) free(gnttab_list[i], M_DEVBUF); - return (-ENOMEM); + return (ENOMEM); } static unsigned int @@ -464,6 +461,8 @@ unmap_pte_fn(pte_t *pte, struct page *pmd_page, } #endif +#ifndef XENHVM + static int gnttab_map(unsigned int start_idx, unsigned int end_idx) { @@ -486,50 +485,117 @@ gnttab_map(unsigned int start_idx, unsigned int end_idx) free(frames, M_DEVBUF); return (ENOSYS); } - PANIC_IF(rc || setup.status); + KASSERT(!(rc || setup.status), + ("unexpected result from grant_table_op")); if (shared == NULL) { vm_offset_t area; area = kmem_alloc_nofault(kernel_map, PAGE_SIZE * max_nr_grant_frames()); - PANIC_IF(area == 0); + KASSERT(area, ("can't allocate VM space for grant table")); shared = (grant_entry_t *)area; } + for (i = 0; i < nr_gframes; i++) PT_SET_MA(((caddr_t)shared) + i*PAGE_SIZE, ((vm_paddr_t)frames[i]) << PAGE_SHIFT | PG_RW | PG_V); free(frames, M_DEVBUF); - return 0; + return (0); } int gnttab_resume(void) { + if (max_nr_grant_frames() < nr_grant_frames) - return -ENOSYS; - return gnttab_map(0, nr_grant_frames - 1); + return (ENOSYS); + return (gnttab_map(0, nr_grant_frames - 1)); } int gnttab_suspend(void) { - int i, pages; + int i; + + for (i = 0; i < nr_grant_frames; i++) + pmap_kremove((vm_offset_t) shared + i * PAGE_SIZE); + + return (0); +} + +#else /* XENHVM */ - pages = (PAGE_SIZE*nr_grant_frames) >> PAGE_SHIFT; +#include <dev/xen/xenpci/xenpcivar.h> - for (i = 0; i < pages; i++) - PT_SET_MA(shared + (i*PAGE_SIZE), (vm_paddr_t)0); +static vm_paddr_t resume_frames; + +static int gnttab_map(unsigned int start_idx, unsigned int end_idx) +{ + struct xen_add_to_physmap xatp; + unsigned int i = end_idx; + + /* + * Loop backwards, so that the first hypercall has the largest index, + * ensuring that the table will grow only once. + */ + do { + xatp.domid = DOMID_SELF; + xatp.idx = i; + xatp.space = XENMAPSPACE_grant_table; + xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i; + if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) + panic("HYPERVISOR_memory_op failed to map gnttab"); + } while (i-- > start_idx); + + if (shared == NULL) { + vm_offset_t area; + + area = kmem_alloc_nofault(kernel_map, + PAGE_SIZE * max_nr_grant_frames()); + KASSERT(area, ("can't allocate VM space for grant table")); + shared = (grant_entry_t *)area; + } + + for (i = start_idx; i <= end_idx; i++) { + pmap_kenter((vm_offset_t) shared + i * PAGE_SIZE, + resume_frames + i * PAGE_SIZE); + } return (0); } +int +gnttab_resume(void) +{ + int error; + unsigned int max_nr_gframes, nr_gframes; + + nr_gframes = nr_grant_frames; + max_nr_gframes = max_nr_grant_frames(); + if (max_nr_gframes < nr_gframes) + return (ENOSYS); + + if (!resume_frames) { + error = xenpci_alloc_space(PAGE_SIZE * max_nr_gframes, + &resume_frames); + if (error) { + printf("error mapping gnttab share frames\n"); + return (error); + } + } + + return (gnttab_map(0, nr_gframes - 1)); +} + +#endif + static int gnttab_expand(unsigned int req_entries) { - int rc; + int error; unsigned int cur, extra; cur = nr_grant_frames; @@ -538,10 +604,11 @@ gnttab_expand(unsigned int req_entries) if (cur + extra > max_nr_grant_frames()) return (ENOSPC); - if ((rc = gnttab_map(cur, cur + extra - 1)) == 0) - rc = grow_gnttab_list(extra); + error = gnttab_map(cur, cur + extra - 1); + if (!error) + error = grow_gnttab_list(extra); - return rc; + return (error); } int @@ -552,7 +619,7 @@ gnttab_init() unsigned int nr_init_grefs; if (!is_running_on_xen()) - return -ENODEV; + return (ENODEV); nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); @@ -571,7 +638,8 @@ gnttab_init() return (ENOMEM); for (i = 0; i < nr_grant_frames; i++) { - gnttab_list[i] = (grant_ref_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); + gnttab_list[i] = (grant_ref_t *) + malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); if (gnttab_list[i] == NULL) goto ini_nomem; } @@ -588,8 +656,10 @@ gnttab_init() gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES; gnttab_free_head = NR_RESERVED_ENTRIES; - printk("Grant table initialized\n"); - return 0; + if (bootverbose) + printf("Grant table initialized\n"); + + return (0); ini_nomem: for (i--; i >= 0; i--) |