aboutsummaryrefslogtreecommitdiff
path: root/sys/xen/gnttab.c
diff options
context:
space:
mode:
authorDoug Rabson <dfr@FreeBSD.org>2009-03-11 15:30:12 +0000
committerDoug Rabson <dfr@FreeBSD.org>2009-03-11 15:30:12 +0000
commit126780243806a6b6cf345b9b548f68010e921aec (patch)
tree633dc40712503605071c68975d2c972638554000 /sys/xen/gnttab.c
parent802e54dc1f4ac7ebd3cc3f0091d2b825780a3c51 (diff)
downloadsrc-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.c158
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--)