[RFC PATCH 11/16] xen/grant-table: make grant-table xenhost aware

From: Ankur Arora
Date: Thu May 09 2019 - 13:27:53 EST


Largely mechanical changes: the exported grant table symbols now take
xenhost_t * as a parameter. Also, move the grant table global state
inside xenhost_t.

If there's more than one xenhost, then initialize both.

Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx>
---
arch/x86/xen/grant-table.c | 71 +++--
drivers/xen/grant-table.c | 611 +++++++++++++++++++++----------------
include/xen/grant_table.h | 72 ++---
include/xen/xenhost.h | 11 +
4 files changed, 443 insertions(+), 322 deletions(-)

diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c
index ecb0d5450334..8f4b071427f9 100644
--- a/arch/x86/xen/grant-table.c
+++ b/arch/x86/xen/grant-table.c
@@ -23,48 +23,54 @@

#include <asm/pgtable.h>

-static struct gnttab_vm_area {
+struct gnttab_vm_area {
struct vm_struct *area;
pte_t **ptes;
-} gnttab_shared_vm_area, gnttab_status_vm_area;
+};

-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
- unsigned long max_nr_gframes,
- void **__shared)
+int arch_gnttab_map_shared(xenhost_t *xh, unsigned long *frames,
+ unsigned long nr_gframes,
+ unsigned long max_nr_gframes,
+ void **__shared)
{
void *shared = *__shared;
unsigned long addr;
unsigned long i;

if (shared == NULL)
- *__shared = shared = gnttab_shared_vm_area.area->addr;
+ *__shared = shared = ((struct gnttab_vm_area *)
+ xh->gnttab_shared_vm_area)->area->addr;

addr = (unsigned long)shared;

for (i = 0; i < nr_gframes; i++) {
- set_pte_at(&init_mm, addr, gnttab_shared_vm_area.ptes[i],
- mfn_pte(frames[i], PAGE_KERNEL));
+ set_pte_at(&init_mm, addr,
+ ((struct gnttab_vm_area *) xh->gnttab_shared_vm_area)->ptes[i],
+ mfn_pte(frames[i], PAGE_KERNEL));
addr += PAGE_SIZE;
}

return 0;
}

-int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
- unsigned long max_nr_gframes,
- grant_status_t **__shared)
+int arch_gnttab_map_status(xenhost_t *xh, uint64_t *frames,
+ unsigned long nr_gframes,
+ unsigned long max_nr_gframes,
+ grant_status_t **__shared)
{
grant_status_t *shared = *__shared;
unsigned long addr;
unsigned long i;

if (shared == NULL)
- *__shared = shared = gnttab_status_vm_area.area->addr;
+ *__shared = shared = ((struct gnttab_vm_area *)
+ xh->gnttab_status_vm_area)->area->addr;

addr = (unsigned long)shared;

for (i = 0; i < nr_gframes; i++) {
- set_pte_at(&init_mm, addr, gnttab_status_vm_area.ptes[i],
+ set_pte_at(&init_mm, addr, ((struct gnttab_vm_area *)
+ xh->gnttab_status_vm_area)->ptes[i],
mfn_pte(frames[i], PAGE_KERNEL));
addr += PAGE_SIZE;
}
@@ -72,16 +78,17 @@ int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
return 0;
}

-void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
+void arch_gnttab_unmap(xenhost_t *xh, void *shared, unsigned long nr_gframes)
{
pte_t **ptes;
unsigned long addr;
unsigned long i;

- if (shared == gnttab_status_vm_area.area->addr)
- ptes = gnttab_status_vm_area.ptes;
+ if (shared == ((struct gnttab_vm_area *)
+ xh->gnttab_status_vm_area)->area->addr)
+ ptes = ((struct gnttab_vm_area *) xh->gnttab_status_vm_area)->ptes;
else
- ptes = gnttab_shared_vm_area.ptes;
+ ptes = ((struct gnttab_vm_area *) xh->gnttab_shared_vm_area)->ptes;

addr = (unsigned long)shared;

@@ -112,14 +119,15 @@ static void arch_gnttab_vfree(struct gnttab_vm_area *area)
kfree(area->ptes);
}

-int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
+int arch_gnttab_init(xenhost_t *xh, unsigned long nr_shared, unsigned long nr_status)
{
int ret;

if (!xen_pv_domain())
return 0;

- ret = arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared);
+ ret = arch_gnttab_valloc((struct gnttab_vm_area *)
+ xh->gnttab_shared_vm_area, nr_shared);
if (ret < 0)
return ret;

@@ -127,13 +135,15 @@ int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
* Always allocate the space for the status frames in case
* we're migrated to a host with V2 support.
*/
- ret = arch_gnttab_valloc(&gnttab_status_vm_area, nr_status);
+ ret = arch_gnttab_valloc((struct gnttab_vm_area *)
+ xh->gnttab_status_vm_area, nr_status);
if (ret < 0)
goto err;

return 0;
err:
- arch_gnttab_vfree(&gnttab_shared_vm_area);
+ arch_gnttab_vfree((struct gnttab_vm_area *)
+ xh->gnttab_shared_vm_area);
return -ENOMEM;
}

@@ -142,16 +152,25 @@ int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
#include <xen/xen-ops.h>
static int __init xen_pvh_gnttab_setup(void)
{
+ xenhost_t **xh;
+ int err;
+
if (!xen_pvh_domain())
return -ENODEV;

- xen_auto_xlat_grant_frames.count = gnttab_max_grant_frames();
+ for_each_xenhost(xh) {
+ struct grant_frames *gf = (struct grant_frames *) (*xh)->auto_xlat_grant_frames;

- return xen_xlate_map_ballooned_pages(&xen_auto_xlat_grant_frames.pfn,
- &xen_auto_xlat_grant_frames.vaddr,
- xen_auto_xlat_grant_frames.count);
+ gf->count = gnttab_max_grant_frames(*xh);
+
+ err = xen_xlate_map_ballooned_pages(&gf->pfn, &gf->vaddr, gf->count);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
/* Call it _before_ __gnttab_init as we need to initialize the
- * xen_auto_xlat_grant_frames first. */
+ * auto_xlat_grant_frames first. */
core_initcall(xen_pvh_gnttab_setup);
#endif
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index ec90769907a4..959b81ade113 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -72,21 +72,10 @@
#define NR_RESERVED_ENTRIES 8
#define GNTTAB_LIST_END 0xffffffff

-static grant_ref_t **gnttab_list;
-static unsigned int nr_grant_frames;
-static int gnttab_free_count;
-static grant_ref_t gnttab_free_head;
static DEFINE_SPINLOCK(gnttab_list_lock);
-struct grant_frames xen_auto_xlat_grant_frames;
static unsigned int xen_gnttab_version;
module_param_named(version, xen_gnttab_version, uint, 0);

-static union {
- struct grant_entry_v1 *v1;
- union grant_entry_v2 *v2;
- void *addr;
-} gnttab_shared;
-
/*This is a structure of function pointers for grant table*/
struct gnttab_ops {
/*
@@ -103,12 +92,12 @@ struct gnttab_ops {
* nr_gframes is the number of frames to map grant table. Returning
* GNTST_okay means success and negative value means failure.
*/
- int (*map_frames)(xen_pfn_t *frames, unsigned int nr_gframes);
+ int (*map_frames)(xenhost_t *xh, xen_pfn_t *frames, unsigned int nr_gframes);
/*
* Release a list of frames which are mapped in map_frames for grant
* entry status.
*/
- void (*unmap_frames)(void);
+ void (*unmap_frames)(xenhost_t *xh);
/*
* Introducing a valid entry into the grant table, granting the frame of
* this grant entry to domain for accessing or transfering. Ref
@@ -116,7 +105,7 @@ struct gnttab_ops {
* granted domain, frame is the page frame to be granted, and flags is
* status of the grant entry to be updated.
*/
- void (*update_entry)(grant_ref_t ref, domid_t domid,
+ void (*update_entry)(xenhost_t *xh, grant_ref_t ref, domid_t domid,
unsigned long frame, unsigned flags);
/*
* Stop granting a grant entry to domain for accessing. Ref parameter is
@@ -126,7 +115,7 @@ struct gnttab_ops {
* directly and don't tear down the grant access. Otherwise, stop grant
* access for this entry and return success(==1).
*/
- int (*end_foreign_access_ref)(grant_ref_t ref, int readonly);
+ int (*end_foreign_access_ref)(xenhost_t *xh, grant_ref_t ref, int readonly);
/*
* Stop granting a grant entry to domain for transfer. Ref parameter is
* reference of a grant entry whose grant transfer will be stopped. If
@@ -134,14 +123,14 @@ struct gnttab_ops {
* failure(==0). Otherwise, wait for the transfer to complete and then
* return the frame.
*/
- unsigned long (*end_foreign_transfer_ref)(grant_ref_t ref);
+ unsigned long (*end_foreign_transfer_ref)(xenhost_t *xh, grant_ref_t ref);
/*
* Query the status of a grant entry. Ref parameter is reference of
* queried grant entry, return value is the status of queried entry.
* Detailed status(writing/reading) can be gotten from the return value
* by bit operations.
*/
- int (*query_foreign_access)(grant_ref_t ref);
+ int (*query_foreign_access)(xenhost_t *xh, grant_ref_t ref);
};

struct unmap_refs_callback_data {
@@ -149,85 +138,105 @@ struct unmap_refs_callback_data {
int result;
};

-static const struct gnttab_ops *gnttab_interface;
+struct gnttab_private {
+ const struct gnttab_ops *gnttab_interface;
+ grant_status_t *grstatus;
+ grant_ref_t gnttab_free_head;
+ unsigned int nr_grant_frames;
+ int gnttab_free_count;
+ struct gnttab_free_callback *gnttab_free_callback_list;
+ struct grant_frames auto_xlat_grant_frames;
+ grant_ref_t **gnttab_list;

-/* This reflects status of grant entries, so act as a global value. */
-static grant_status_t *grstatus;
+ union {
+ struct grant_entry_v1 *v1;
+ union grant_entry_v2 *v2;
+ void *addr;
+ } gnttab_shared;
+};

-static struct gnttab_free_callback *gnttab_free_callback_list;
+#define gt_priv(xh) ((struct gnttab_private *) (xh)->gnttab_private)

-static int gnttab_expand(unsigned int req_entries);
+static int gnttab_expand(xenhost_t *xh, unsigned int req_entries);

#define RPP (PAGE_SIZE / sizeof(grant_ref_t))
#define SPP (PAGE_SIZE / sizeof(grant_status_t))

-static inline grant_ref_t *__gnttab_entry(grant_ref_t entry)
+static inline grant_ref_t *__gnttab_entry(xenhost_t *xh, grant_ref_t entry)
{
- return &gnttab_list[(entry) / RPP][(entry) % RPP];
+ struct gnttab_private *gt = gt_priv(xh);
+
+ return &gt->gnttab_list[(entry) / RPP][(entry) % RPP];
}
/* This can be used as an l-value */
-#define gnttab_entry(entry) (*__gnttab_entry(entry))
+#define gnttab_entry(xh, entry) (*__gnttab_entry(xh, entry))

-static int get_free_entries(unsigned count)
+static int get_free_entries(xenhost_t *xh, unsigned count)
{
unsigned long flags;
int ref, rc = 0;
grant_ref_t head;
+ struct gnttab_private *gt = gt_priv(xh);

spin_lock_irqsave(&gnttab_list_lock, flags);

- if ((gnttab_free_count < count) &&
- ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) {
+ if ((gt->gnttab_free_count < count) &&
+ ((rc = gnttab_expand(xh, count - gt->gnttab_free_count)) < 0)) {
spin_unlock_irqrestore(&gnttab_list_lock, flags);
return rc;
}

- ref = head = gnttab_free_head;
- gnttab_free_count -= count;
+ ref = head = gt->gnttab_free_head;
+ gt->gnttab_free_count -= count;
while (count-- > 1)
- head = gnttab_entry(head);
- gnttab_free_head = gnttab_entry(head);
- gnttab_entry(head) = GNTTAB_LIST_END;
+ head = gnttab_entry(xh, head);
+ gt->gnttab_free_head = gnttab_entry(xh, head);
+ gnttab_entry(xh, head) = GNTTAB_LIST_END;

spin_unlock_irqrestore(&gnttab_list_lock, flags);

return ref;
}

-static void do_free_callbacks(void)
+static void do_free_callbacks(xenhost_t *xh)
{
struct gnttab_free_callback *callback, *next;
+ struct gnttab_private *gt = gt_priv(xh);

- callback = gnttab_free_callback_list;
- gnttab_free_callback_list = NULL;
+ callback = gt->gnttab_free_callback_list;
+ gt->gnttab_free_callback_list = NULL;

while (callback != NULL) {
next = callback->next;
- if (gnttab_free_count >= callback->count) {
+ if (gt->gnttab_free_count >= callback->count) {
callback->next = NULL;
callback->fn(callback->arg);
} else {
- callback->next = gnttab_free_callback_list;
- gnttab_free_callback_list = callback;
+ callback->next = gt->gnttab_free_callback_list;
+ gt->gnttab_free_callback_list = callback;
}
callback = next;
}
}

-static inline void check_free_callbacks(void)
+static inline void check_free_callbacks(xenhost_t *xh)
{
- if (unlikely(gnttab_free_callback_list))
- do_free_callbacks();
+ struct gnttab_private *gt = gt_priv(xh);
+
+ if (unlikely(gt->gnttab_free_callback_list))
+ do_free_callbacks(xh);
}

-static void put_free_entry(grant_ref_t ref)
+static void put_free_entry(xenhost_t *xh, grant_ref_t ref)
{
unsigned long flags;
+ struct gnttab_private *gt = gt_priv(xh);
+
spin_lock_irqsave(&gnttab_list_lock, flags);
- gnttab_entry(ref) = gnttab_free_head;
- gnttab_free_head = ref;
- gnttab_free_count++;
- check_free_callbacks();
+ gnttab_entry(xh, ref) = gt->gnttab_free_head;
+ gt->gnttab_free_head = ref;
+ gt->gnttab_free_count++;
+ check_free_callbacks(xh);
spin_unlock_irqrestore(&gnttab_list_lock, flags);
}

@@ -242,72 +251,85 @@ static void put_free_entry(grant_ref_t ref)
* 3. Write memory barrier (WMB).
* 4. Write ent->flags, inc. valid type.
*/
-static void gnttab_update_entry_v1(grant_ref_t ref, domid_t domid,
+static void gnttab_update_entry_v1(xenhost_t *xh, grant_ref_t ref, domid_t domid,
unsigned long frame, unsigned flags)
{
- gnttab_shared.v1[ref].domid = domid;
- gnttab_shared.v1[ref].frame = frame;
+ struct gnttab_private *gt = gt_priv(xh);
+
+ gt->gnttab_shared.v1[ref].domid = domid;
+ gt->gnttab_shared.v1[ref].frame = frame;
wmb();
- gnttab_shared.v1[ref].flags = flags;
+ gt->gnttab_shared.v1[ref].flags = flags;
}

-static void gnttab_update_entry_v2(grant_ref_t ref, domid_t domid,
+static void gnttab_update_entry_v2(xenhost_t *xh, grant_ref_t ref, domid_t domid,
unsigned long frame, unsigned int flags)
{
- gnttab_shared.v2[ref].hdr.domid = domid;
- gnttab_shared.v2[ref].full_page.frame = frame;
+ struct gnttab_private *gt = gt_priv(xh);
+
+ gt->gnttab_shared.v2[ref].hdr.domid = domid;
+ gt->gnttab_shared.v2[ref].full_page.frame = frame;
wmb(); /* Hypervisor concurrent accesses. */
- gnttab_shared.v2[ref].hdr.flags = GTF_permit_access | flags;
+ gt->gnttab_shared.v2[ref].hdr.flags = GTF_permit_access | flags;
}

/*
* Public grant-issuing interface functions
*/
-void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+void gnttab_grant_foreign_access_ref(xenhost_t *xh, grant_ref_t ref, domid_t domid,
unsigned long frame, int readonly)
{
- gnttab_interface->update_entry(ref, domid, frame,
+ struct gnttab_private *gt = gt_priv(xh);
+
+ gt->gnttab_interface->update_entry(xh, ref, domid, frame,
GTF_permit_access | (readonly ? GTF_readonly : 0));
}
EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);

-int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
+int gnttab_grant_foreign_access(xenhost_t *xh, domid_t domid, unsigned long frame,
int readonly)
{
int ref;

- ref = get_free_entries(1);
+ ref = get_free_entries(xh, 1);
if (unlikely(ref < 0))
return -ENOSPC;

- gnttab_grant_foreign_access_ref(ref, domid, frame, readonly);
+ gnttab_grant_foreign_access_ref(xh, ref, domid, frame, readonly);

return ref;
}
EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);

-static int gnttab_query_foreign_access_v1(grant_ref_t ref)
+static int gnttab_query_foreign_access_v1(xenhost_t *xh, grant_ref_t ref)
{
- return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
+ struct gnttab_private *gt = gt_priv(xh);
+
+ return gt->gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
}

-static int gnttab_query_foreign_access_v2(grant_ref_t ref)
+static int gnttab_query_foreign_access_v2(xenhost_t *xh, grant_ref_t ref)
{
- return grstatus[ref] & (GTF_reading|GTF_writing);
+ struct gnttab_private *gt = gt_priv(xh);
+
+ return gt->grstatus[ref] & (GTF_reading|GTF_writing);
}

-int gnttab_query_foreign_access(grant_ref_t ref)
+int gnttab_query_foreign_access(xenhost_t *xh, grant_ref_t ref)
{
- return gnttab_interface->query_foreign_access(ref);
+ struct gnttab_private *gt = gt_priv(xh);
+
+ return gt->gnttab_interface->query_foreign_access(xh, ref);
}
EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);

-static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
+static int gnttab_end_foreign_access_ref_v1(xenhost_t *xh, grant_ref_t ref, int readonly)
{
+ struct gnttab_private *gt = gt_priv(xh);
u16 flags, nflags;
u16 *pflags;

- pflags = &gnttab_shared.v1[ref].flags;
+ pflags = &gt->gnttab_shared.v1[ref].flags;
nflags = *pflags;
do {
flags = nflags;
@@ -318,11 +340,13 @@ static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
return 1;
}

-static int gnttab_end_foreign_access_ref_v2(grant_ref_t ref, int readonly)
+static int gnttab_end_foreign_access_ref_v2(xenhost_t *xh, grant_ref_t ref, int readonly)
{
- gnttab_shared.v2[ref].hdr.flags = 0;
+ struct gnttab_private *gt = gt_priv(xh);
+
+ gt->gnttab_shared.v2[ref].hdr.flags = 0;
mb(); /* Concurrent access by hypervisor. */
- if (grstatus[ref] & (GTF_reading|GTF_writing)) {
+ if (gt->grstatus[ref] & (GTF_reading|GTF_writing)) {
return 0;
} else {
/*
@@ -341,14 +365,16 @@ static int gnttab_end_foreign_access_ref_v2(grant_ref_t ref, int readonly)
return 1;
}

-static inline int _gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
+static inline int _gnttab_end_foreign_access_ref(xenhost_t *xh, grant_ref_t ref, int readonly)
{
- return gnttab_interface->end_foreign_access_ref(ref, readonly);
+ struct gnttab_private *gt = gt_priv(xh);
+
+ return gt->gnttab_interface->end_foreign_access_ref(xh, ref, readonly);
}

-int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
+int gnttab_end_foreign_access_ref(xenhost_t *xh, grant_ref_t ref, int readonly)
{
- if (_gnttab_end_foreign_access_ref(ref, readonly))
+ if (_gnttab_end_foreign_access_ref(xh, ref, readonly))
return 1;
pr_warn("WARNING: g.e. %#x still in use!\n", ref);
return 0;
@@ -361,6 +387,7 @@ struct deferred_entry {
bool ro;
uint16_t warn_delay;
struct page *page;
+ xenhost_t *xh;
};
static LIST_HEAD(deferred_list);
static void gnttab_handle_deferred(struct timer_list *);
@@ -382,8 +409,8 @@ static void gnttab_handle_deferred(struct timer_list *unused)
break;
list_del(&entry->list);
spin_unlock_irqrestore(&gnttab_list_lock, flags);
- if (_gnttab_end_foreign_access_ref(entry->ref, entry->ro)) {
- put_free_entry(entry->ref);
+ if (_gnttab_end_foreign_access_ref(entry->xh, entry->ref, entry->ro)) {
+ put_free_entry(entry->xh, entry->ref);
if (entry->page) {
pr_debug("freeing g.e. %#x (pfn %#lx)\n",
entry->ref, page_to_pfn(entry->page));
@@ -411,7 +438,7 @@ static void gnttab_handle_deferred(struct timer_list *unused)
spin_unlock_irqrestore(&gnttab_list_lock, flags);
}

-static void gnttab_add_deferred(grant_ref_t ref, bool readonly,
+static void gnttab_add_deferred(xenhost_t *xh, grant_ref_t ref, bool readonly,
struct page *page)
{
struct deferred_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
@@ -423,6 +450,7 @@ static void gnttab_add_deferred(grant_ref_t ref, bool readonly,
entry->ref = ref;
entry->ro = readonly;
entry->page = page;
+ entry->xh = xh;
entry->warn_delay = 60;
spin_lock_irqsave(&gnttab_list_lock, flags);
list_add_tail(&entry->list, &deferred_list);
@@ -437,46 +465,49 @@ static void gnttab_add_deferred(grant_ref_t ref, bool readonly,
what, ref, page ? page_to_pfn(page) : -1);
}

-void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
+void gnttab_end_foreign_access(xenhost_t *xh, grant_ref_t ref, int readonly,
unsigned long page)
{
- if (gnttab_end_foreign_access_ref(ref, readonly)) {
- put_free_entry(ref);
+ if (gnttab_end_foreign_access_ref(xh, ref, readonly)) {
+ put_free_entry(xh, ref);
if (page != 0)
put_page(virt_to_page(page));
} else
- gnttab_add_deferred(ref, readonly,
+ gnttab_add_deferred(xh, ref, readonly,
page ? virt_to_page(page) : NULL);
}
EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);

-int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
+int gnttab_grant_foreign_transfer(xenhost_t *xh, domid_t domid, unsigned long pfn)
{
int ref;

- ref = get_free_entries(1);
+ ref = get_free_entries(xh, 1);
if (unlikely(ref < 0))
return -ENOSPC;
- gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
+ gnttab_grant_foreign_transfer_ref(xh, ref, domid, pfn);

return ref;
}
EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);

-void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
+void gnttab_grant_foreign_transfer_ref(xenhost_t *xh, grant_ref_t ref, domid_t domid,
unsigned long pfn)
{
- gnttab_interface->update_entry(ref, domid, pfn, GTF_accept_transfer);
+ struct gnttab_private *gt = gt_priv(xh);
+
+ gt->gnttab_interface->update_entry(xh, ref, domid, pfn, GTF_accept_transfer);
}
EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);

-static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)
+static unsigned long gnttab_end_foreign_transfer_ref_v1(xenhost_t *xh, grant_ref_t ref)
{
+ struct gnttab_private *gt = gt_priv(xh);
unsigned long frame;
u16 flags;
u16 *pflags;

- pflags = &gnttab_shared.v1[ref].flags;
+ pflags = &gt->gnttab_shared.v1[ref].flags;

/*
* If a transfer is not even yet started, try to reclaim the grant
@@ -495,19 +526,20 @@ static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)
}

rmb(); /* Read the frame number /after/ reading completion status. */
- frame = gnttab_shared.v1[ref].frame;
+ frame = gt->gnttab_shared.v1[ref].frame;
BUG_ON(frame == 0);

return frame;
}

-static unsigned long gnttab_end_foreign_transfer_ref_v2(grant_ref_t ref)
+static unsigned long gnttab_end_foreign_transfer_ref_v2(xenhost_t *xh, grant_ref_t ref)
{
unsigned long frame;
u16 flags;
u16 *pflags;
+ struct gnttab_private *gt = gt_priv(xh);

- pflags = &gnttab_shared.v2[ref].hdr.flags;
+ pflags = &gt->gnttab_shared.v2[ref].hdr.flags;

/*
* If a transfer is not even yet started, try to reclaim the grant
@@ -526,34 +558,39 @@ static unsigned long gnttab_end_foreign_transfer_ref_v2(grant_ref_t ref)
}

rmb(); /* Read the frame number /after/ reading completion status. */
- frame = gnttab_shared.v2[ref].full_page.frame;
+ frame = gt->gnttab_shared.v2[ref].full_page.frame;
BUG_ON(frame == 0);

return frame;
}

-unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
+unsigned long gnttab_end_foreign_transfer_ref(xenhost_t *xh, grant_ref_t ref)
{
- return gnttab_interface->end_foreign_transfer_ref(ref);
+ struct gnttab_private *gt = gt_priv(xh);
+
+ return gt->gnttab_interface->end_foreign_transfer_ref(xh, ref);
}
EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);

-unsigned long gnttab_end_foreign_transfer(grant_ref_t ref)
+unsigned long gnttab_end_foreign_transfer(xenhost_t *xh, grant_ref_t ref)
{
- unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
- put_free_entry(ref);
+ unsigned long frame = gnttab_end_foreign_transfer_ref(xh, ref);
+
+ put_free_entry(xh, ref);
+
return frame;
}
EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);

-void gnttab_free_grant_reference(grant_ref_t ref)
+void gnttab_free_grant_reference(xenhost_t *xh, grant_ref_t ref)
{
- put_free_entry(ref);
+ put_free_entry(xh, ref);
}
EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);

-void gnttab_free_grant_references(grant_ref_t head)
+void gnttab_free_grant_references(xenhost_t *xh, grant_ref_t head)
{
+ struct gnttab_private *gt = gt_priv(xh);
grant_ref_t ref;
unsigned long flags;
int count = 1;
@@ -561,21 +598,21 @@ void gnttab_free_grant_references(grant_ref_t head)
return;
spin_lock_irqsave(&gnttab_list_lock, flags);
ref = head;
- while (gnttab_entry(ref) != GNTTAB_LIST_END) {
- ref = gnttab_entry(ref);
+ while (gnttab_entry(xh, ref) != GNTTAB_LIST_END) {
+ ref = gnttab_entry(xh, ref);
count++;
}
- gnttab_entry(ref) = gnttab_free_head;
- gnttab_free_head = head;
- gnttab_free_count += count;
- check_free_callbacks();
+ gnttab_entry(xh, ref) = gt->gnttab_free_head;
+ gt->gnttab_free_head = head;
+ gt->gnttab_free_count += count;
+ check_free_callbacks(xh);
spin_unlock_irqrestore(&gnttab_list_lock, flags);
}
EXPORT_SYMBOL_GPL(gnttab_free_grant_references);

-int gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
+int gnttab_alloc_grant_references(xenhost_t *xh, u16 count, grant_ref_t *head)
{
- int h = get_free_entries(count);
+ int h = get_free_entries(xh, count);

if (h < 0)
return -ENOSPC;
@@ -586,40 +623,41 @@ int gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
}
EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);

-int gnttab_empty_grant_references(const grant_ref_t *private_head)
+int gnttab_empty_grant_references(xenhost_t *xh, const grant_ref_t *private_head)
{
return (*private_head == GNTTAB_LIST_END);
}
EXPORT_SYMBOL_GPL(gnttab_empty_grant_references);

-int gnttab_claim_grant_reference(grant_ref_t *private_head)
+int gnttab_claim_grant_reference(xenhost_t *xh, grant_ref_t *private_head)
{
grant_ref_t g = *private_head;
if (unlikely(g == GNTTAB_LIST_END))
return -ENOSPC;
- *private_head = gnttab_entry(g);
+ *private_head = gnttab_entry(xh, g);
return g;
}
EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);

-void gnttab_release_grant_reference(grant_ref_t *private_head,
+void gnttab_release_grant_reference(xenhost_t *xh, grant_ref_t *private_head,
grant_ref_t release)
{
- gnttab_entry(release) = *private_head;
+ gnttab_entry(xh, release) = *private_head;
*private_head = release;
}
EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);

-void gnttab_request_free_callback(struct gnttab_free_callback *callback,
+void gnttab_request_free_callback(xenhost_t *xh, struct gnttab_free_callback *callback,
void (*fn)(void *), void *arg, u16 count)
{
unsigned long flags;
struct gnttab_free_callback *cb;
+ struct gnttab_private *gt = gt_priv(xh);

spin_lock_irqsave(&gnttab_list_lock, flags);

/* Check if the callback is already on the list */
- cb = gnttab_free_callback_list;
+ cb = gt->gnttab_free_callback_list;
while (cb) {
if (cb == callback)
goto out;
@@ -629,21 +667,23 @@ void gnttab_request_free_callback(struct gnttab_free_callback *callback,
callback->fn = fn;
callback->arg = arg;
callback->count = count;
- callback->next = gnttab_free_callback_list;
- gnttab_free_callback_list = callback;
- check_free_callbacks();
+ callback->next = gt->gnttab_free_callback_list;
+ gt->gnttab_free_callback_list = callback;
+ check_free_callbacks(xh);
out:
spin_unlock_irqrestore(&gnttab_list_lock, flags);
}
EXPORT_SYMBOL_GPL(gnttab_request_free_callback);

-void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
+void gnttab_cancel_free_callback(xenhost_t *xh, struct gnttab_free_callback *callback)
{
struct gnttab_free_callback **pcb;
unsigned long flags;
+ struct gnttab_private *gt = gt_priv(xh);
+

spin_lock_irqsave(&gnttab_list_lock, flags);
- for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
+ for (pcb = &gt->gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
if (*pcb == callback) {
*pcb = callback->next;
break;
@@ -653,75 +693,78 @@ void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
}
EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback);

-static unsigned int gnttab_frames(unsigned int frames, unsigned int align)
+static unsigned int gnttab_frames(xenhost_t *xh, unsigned int frames, unsigned int align)
{
- return (frames * gnttab_interface->grefs_per_grant_frame + align - 1) /
+ struct gnttab_private *gt = gt_priv(xh);
+
+ return (frames * gt->gnttab_interface->grefs_per_grant_frame + align - 1) /
align;
}

-static int grow_gnttab_list(unsigned int more_frames)
+static int grow_gnttab_list(xenhost_t *xh, unsigned int more_frames)
{
unsigned int new_nr_grant_frames, extra_entries, i;
unsigned int nr_glist_frames, new_nr_glist_frames;
unsigned int grefs_per_frame;
+ struct gnttab_private *gt = gt_priv(xh);

- BUG_ON(gnttab_interface == NULL);
- grefs_per_frame = gnttab_interface->grefs_per_grant_frame;
+ BUG_ON(gt->gnttab_interface == NULL);
+ grefs_per_frame = gt->gnttab_interface->grefs_per_grant_frame;

- new_nr_grant_frames = nr_grant_frames + more_frames;
+ new_nr_grant_frames = gt->nr_grant_frames + more_frames;
extra_entries = more_frames * grefs_per_frame;

- nr_glist_frames = gnttab_frames(nr_grant_frames, RPP);
- new_nr_glist_frames = gnttab_frames(new_nr_grant_frames, RPP);
+ nr_glist_frames = gnttab_frames(xh, gt->nr_grant_frames, RPP);
+ new_nr_glist_frames = gnttab_frames(xh, new_nr_grant_frames, RPP);
for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
- gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
- if (!gnttab_list[i])
+ gt->gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
+ if (!gt->gnttab_list[i])
goto grow_nomem;
}


- for (i = grefs_per_frame * nr_grant_frames;
+ for (i = grefs_per_frame * gt->nr_grant_frames;
i < grefs_per_frame * new_nr_grant_frames - 1; i++)
- gnttab_entry(i) = i + 1;
+ gnttab_entry(xh, i) = i + 1;

- gnttab_entry(i) = gnttab_free_head;
- gnttab_free_head = grefs_per_frame * nr_grant_frames;
- gnttab_free_count += extra_entries;
+ gnttab_entry(xh, i) = gt->gnttab_free_head;
+ gt->gnttab_free_head = grefs_per_frame * gt->nr_grant_frames;
+ gt->gnttab_free_count += extra_entries;

- nr_grant_frames = new_nr_grant_frames;
+ gt->nr_grant_frames = new_nr_grant_frames;

- check_free_callbacks();
+ check_free_callbacks(xh);

return 0;

grow_nomem:
while (i-- > nr_glist_frames)
- free_page((unsigned long) gnttab_list[i]);
+ free_page((unsigned long) gt->gnttab_list[i]);
return -ENOMEM;
}

-static unsigned int __max_nr_grant_frames(void)
+static unsigned int __max_nr_grant_frames(xenhost_t *xh)
{
struct gnttab_query_size query;
int rc;

query.dom = DOMID_SELF;

- rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1);
+ rc = hypervisor_grant_table_op(xh, GNTTABOP_query_size, &query, 1);
if ((rc < 0) || (query.status != GNTST_okay))
return 4; /* Legacy max supported number of frames */

return query.max_nr_frames;
}

-unsigned int gnttab_max_grant_frames(void)
+unsigned int gnttab_max_grant_frames(xenhost_t *xh)
{
- unsigned int xen_max = __max_nr_grant_frames();
+ unsigned int xen_max = __max_nr_grant_frames(xh);
static unsigned int boot_max_nr_grant_frames;

/* First time, initialize it properly. */
if (!boot_max_nr_grant_frames)
- boot_max_nr_grant_frames = __max_nr_grant_frames();
+ boot_max_nr_grant_frames = __max_nr_grant_frames(xh);

if (xen_max > boot_max_nr_grant_frames)
return boot_max_nr_grant_frames;
@@ -729,14 +772,15 @@ unsigned int gnttab_max_grant_frames(void)
}
EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);

-int gnttab_setup_auto_xlat_frames(phys_addr_t addr)
+int gnttab_setup_auto_xlat_frames(xenhost_t *xh, phys_addr_t addr)
{
+ struct gnttab_private *gt = gt_priv(xh);
xen_pfn_t *pfn;
- unsigned int max_nr_gframes = __max_nr_grant_frames();
+ unsigned int max_nr_gframes = __max_nr_grant_frames(xh);
unsigned int i;
void *vaddr;

- if (xen_auto_xlat_grant_frames.count)
+ if (gt->auto_xlat_grant_frames.count)
return -EINVAL;

vaddr = xen_remap(addr, XEN_PAGE_SIZE * max_nr_gframes);
@@ -753,24 +797,26 @@ int gnttab_setup_auto_xlat_frames(phys_addr_t addr)
for (i = 0; i < max_nr_gframes; i++)
pfn[i] = XEN_PFN_DOWN(addr) + i;

- xen_auto_xlat_grant_frames.vaddr = vaddr;
- xen_auto_xlat_grant_frames.pfn = pfn;
- xen_auto_xlat_grant_frames.count = max_nr_gframes;
+ gt->auto_xlat_grant_frames.vaddr = vaddr;
+ gt->auto_xlat_grant_frames.pfn = pfn;
+ gt->auto_xlat_grant_frames.count = max_nr_gframes;

return 0;
}
EXPORT_SYMBOL_GPL(gnttab_setup_auto_xlat_frames);

-void gnttab_free_auto_xlat_frames(void)
+void gnttab_free_auto_xlat_frames(xenhost_t *xh)
{
- if (!xen_auto_xlat_grant_frames.count)
+ struct gnttab_private *gt = gt_priv(xh);
+
+ if (!gt->auto_xlat_grant_frames.count)
return;
- kfree(xen_auto_xlat_grant_frames.pfn);
- xen_unmap(xen_auto_xlat_grant_frames.vaddr);
+ kfree(gt->auto_xlat_grant_frames.pfn);
+ xen_unmap(gt->auto_xlat_grant_frames.vaddr);

- xen_auto_xlat_grant_frames.pfn = NULL;
- xen_auto_xlat_grant_frames.count = 0;
- xen_auto_xlat_grant_frames.vaddr = NULL;
+ gt->auto_xlat_grant_frames.pfn = NULL;
+ gt->auto_xlat_grant_frames.count = 0;
+ gt->auto_xlat_grant_frames.vaddr = NULL;
}
EXPORT_SYMBOL_GPL(gnttab_free_auto_xlat_frames);

@@ -800,17 +846,17 @@ EXPORT_SYMBOL_GPL(gnttab_pages_set_private);
* @nr_pages: number of pages to alloc
* @pages: returns the pages
*/
-int gnttab_alloc_pages(int nr_pages, struct page **pages)
+int gnttab_alloc_pages(xenhost_t *xh, int nr_pages, struct page **pages)
{
int ret;

- ret = alloc_xenballooned_pages(xh_default, nr_pages, pages);
+ ret = alloc_xenballooned_pages(xh, nr_pages, pages);
if (ret < 0)
return ret;

ret = gnttab_pages_set_private(nr_pages, pages);
if (ret < 0)
- gnttab_free_pages(nr_pages, pages);
+ gnttab_free_pages(xh, nr_pages, pages);

return ret;
}
@@ -836,10 +882,10 @@ EXPORT_SYMBOL_GPL(gnttab_pages_clear_private);
* @nr_pages; number of pages to free
* @pages: the pages
*/
-void gnttab_free_pages(int nr_pages, struct page **pages)
+void gnttab_free_pages(xenhost_t *xh, int nr_pages, struct page **pages)
{
gnttab_pages_clear_private(nr_pages, pages);
- free_xenballooned_pages(xh_default, nr_pages, pages);
+ free_xenballooned_pages(xh, nr_pages, pages);
}
EXPORT_SYMBOL_GPL(gnttab_free_pages);

@@ -848,12 +894,15 @@ EXPORT_SYMBOL_GPL(gnttab_free_pages);
* gnttab_dma_alloc_pages - alloc DMAable pages suitable for grant mapping into
* @args: arguments to the function
*/
-int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args)
+int gnttab_dma_alloc_pages(xenhost_t *xh, struct gnttab_dma_alloc_args *args)
{
unsigned long pfn, start_pfn;
size_t size;
int i, ret;

+ if (xh->type != xenhost_r1)
+ return -EINVAL;
+
size = args->nr_pages << PAGE_SHIFT;
if (args->coherent)
args->vaddr = dma_alloc_coherent(args->dev, size,
@@ -903,11 +952,14 @@ EXPORT_SYMBOL_GPL(gnttab_dma_alloc_pages);
* gnttab_dma_free_pages - free DMAable pages
* @args: arguments to the function
*/
-int gnttab_dma_free_pages(struct gnttab_dma_alloc_args *args)
+int gnttab_dma_free_pages(xenhost_t *xh, struct gnttab_dma_alloc_args *args)
{
size_t size;
int i, ret;

+ if (xh->type != xenhost_r1)
+ return -EINVAL;
+
gnttab_pages_clear_private(args->nr_pages, args->pages);

for (i = 0; i < args->nr_pages; i++)
@@ -939,13 +991,13 @@ EXPORT_SYMBOL_GPL(gnttab_dma_free_pages);
/* Handling of paged out grant targets (GNTST_eagain) */
#define MAX_DELAY 256
static inline void
-gnttab_retry_eagain_gop(unsigned int cmd, void *gop, int16_t *status,
+gnttab_retry_eagain_gop(xenhost_t *xh, unsigned int cmd, void *gop, int16_t *status,
const char *func)
{
unsigned delay = 1;

do {
- BUG_ON(HYPERVISOR_grant_table_op(cmd, gop, 1));
+ BUG_ON(hypervisor_grant_table_op(xh, cmd, gop, 1));
if (*status == GNTST_eagain)
msleep(delay++);
} while ((*status == GNTST_eagain) && (delay < MAX_DELAY));
@@ -956,28 +1008,28 @@ gnttab_retry_eagain_gop(unsigned int cmd, void *gop, int16_t *status,
}
}

-void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count)
+void gnttab_batch_map(xenhost_t *xh, struct gnttab_map_grant_ref *batch, unsigned count)
{
struct gnttab_map_grant_ref *op;

- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, batch, count))
+ if (hypervisor_grant_table_op(xh, GNTTABOP_map_grant_ref, batch, count))
BUG();
for (op = batch; op < batch + count; op++)
if (op->status == GNTST_eagain)
- gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, op,
+ gnttab_retry_eagain_gop(xh, GNTTABOP_map_grant_ref, op,
&op->status, __func__);
}
EXPORT_SYMBOL_GPL(gnttab_batch_map);

-void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count)
+void gnttab_batch_copy(xenhost_t *xh, struct gnttab_copy *batch, unsigned count)
{
struct gnttab_copy *op;

- if (HYPERVISOR_grant_table_op(GNTTABOP_copy, batch, count))
+ if (hypervisor_grant_table_op(xh, GNTTABOP_copy, batch, count))
BUG();
for (op = batch; op < batch + count; op++)
if (op->status == GNTST_eagain)
- gnttab_retry_eagain_gop(GNTTABOP_copy, op,
+ gnttab_retry_eagain_gop(xh, GNTTABOP_copy, op,
&op->status, __func__);
}
EXPORT_SYMBOL_GPL(gnttab_batch_copy);
@@ -1030,13 +1082,13 @@ void gnttab_foreach_grant(struct page **pages,
}
}

-int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
+int gnttab_map_refs(xenhost_t *xh, struct gnttab_map_grant_ref *map_ops,
struct gnttab_map_grant_ref *kmap_ops,
struct page **pages, unsigned int count)
{
int i, ret;

- ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
+ ret = hypervisor_grant_table_op(xh, GNTTABOP_map_grant_ref, map_ops, count);
if (ret)
return ret;

@@ -1059,7 +1111,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,

case GNTST_eagain:
/* Retry eagain maps */
- gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref,
+ gnttab_retry_eagain_gop(xh, GNTTABOP_map_grant_ref,
map_ops + i,
&map_ops[i].status, __func__);
/* Test status in next loop iteration. */
@@ -1075,14 +1127,14 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
}
EXPORT_SYMBOL_GPL(gnttab_map_refs);

-int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
+int gnttab_unmap_refs(xenhost_t *xh, struct gnttab_unmap_grant_ref *unmap_ops,
struct gnttab_unmap_grant_ref *kunmap_ops,
struct page **pages, unsigned int count)
{
unsigned int i;
int ret;

- ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
+ ret = hypervisor_grant_table_op(xh, GNTTABOP_unmap_grant_ref, unmap_ops, count);
if (ret)
return ret;

@@ -1122,7 +1174,7 @@ static void __gnttab_unmap_refs_async(struct gntab_unmap_queue_data* item)
}
}

- ret = gnttab_unmap_refs(item->unmap_ops, item->kunmap_ops,
+ ret = gnttab_unmap_refs(item->xh, item->unmap_ops, item->kunmap_ops,
item->pages, item->count);
item->done(ret, item);
}
@@ -1159,37 +1211,43 @@ int gnttab_unmap_refs_sync(struct gntab_unmap_queue_data *item)
}
EXPORT_SYMBOL_GPL(gnttab_unmap_refs_sync);

-static unsigned int nr_status_frames(unsigned int nr_grant_frames)
+static unsigned int nr_status_frames(xenhost_t *xh, unsigned int nr_grant_frames)
{
- BUG_ON(gnttab_interface == NULL);
- return gnttab_frames(nr_grant_frames, SPP);
+ struct gnttab_private *gt = gt_priv(xh);
+
+ BUG_ON(gt->gnttab_interface == NULL);
+ return gnttab_frames(xh, nr_grant_frames, SPP);
}

-static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v1(xenhost_t *xh, xen_pfn_t *frames, unsigned int nr_gframes)
{
int rc;
+ struct gnttab_private *gt = gt_priv(xh);

- rc = arch_gnttab_map_shared(frames, nr_gframes,
- gnttab_max_grant_frames(),
- &gnttab_shared.addr);
+ rc = arch_gnttab_map_shared(xh, frames, nr_gframes,
+ gnttab_max_grant_frames(xh),
+ &gt->gnttab_shared.addr);
BUG_ON(rc);

return 0;
}

-static void gnttab_unmap_frames_v1(void)
+static void gnttab_unmap_frames_v1(xenhost_t *xh)
{
- arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
+ struct gnttab_private *gt = gt_priv(xh);
+
+ arch_gnttab_unmap(xh, gt->gnttab_shared.addr, gt->nr_grant_frames);
}

-static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v2(xenhost_t *xh, xen_pfn_t *frames, unsigned int nr_gframes)
{
uint64_t *sframes;
unsigned int nr_sframes;
struct gnttab_get_status_frames getframes;
int rc;
+ struct gnttab_private *gt = gt_priv(xh);

- nr_sframes = nr_status_frames(nr_gframes);
+ nr_sframes = nr_status_frames(xh, nr_gframes);

/* No need for kzalloc as it is initialized in following hypercall
* GNTTABOP_get_status_frames.
@@ -1202,7 +1260,7 @@ static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes)
getframes.nr_frames = nr_sframes;
set_xen_guest_handle(getframes.frame_list, sframes);

- rc = HYPERVISOR_grant_table_op(GNTTABOP_get_status_frames,
+ rc = hypervisor_grant_table_op(xh, GNTTABOP_get_status_frames,
&getframes, 1);
if (rc == -ENOSYS) {
kfree(sframes);
@@ -1211,38 +1269,41 @@ static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes)

BUG_ON(rc || getframes.status);

- rc = arch_gnttab_map_status(sframes, nr_sframes,
- nr_status_frames(gnttab_max_grant_frames()),
- &grstatus);
+ rc = arch_gnttab_map_status(xh, sframes, nr_sframes,
+ nr_status_frames(xh, gnttab_max_grant_frames(xh)),
+ &gt->grstatus);
BUG_ON(rc);
kfree(sframes);

- rc = arch_gnttab_map_shared(frames, nr_gframes,
- gnttab_max_grant_frames(),
- &gnttab_shared.addr);
+ rc = arch_gnttab_map_shared(xh, frames, nr_gframes,
+ gnttab_max_grant_frames(xh),
+ &gt->gnttab_shared.addr);
BUG_ON(rc);

return 0;
}

-static void gnttab_unmap_frames_v2(void)
+static void gnttab_unmap_frames_v2(xenhost_t *xh)
{
- arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
- arch_gnttab_unmap(grstatus, nr_status_frames(nr_grant_frames));
+ struct gnttab_private *gt = gt_priv(xh);
+
+ arch_gnttab_unmap(xh, gt->gnttab_shared.addr, gt->nr_grant_frames);
+ arch_gnttab_unmap(xh, gt->grstatus, nr_status_frames(xh, gt->nr_grant_frames));
}

-static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+static int gnttab_map(xenhost_t *xh, unsigned int start_idx, unsigned int end_idx)
{
struct gnttab_setup_table setup;
xen_pfn_t *frames;
unsigned int nr_gframes = end_idx + 1;
+ struct gnttab_private *gt = gt_priv(xh);
int rc;

- if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ if (__xen_feature(xh, XENFEAT_auto_translated_physmap)) {
struct xen_add_to_physmap xatp;
unsigned int i = end_idx;
rc = 0;
- BUG_ON(xen_auto_xlat_grant_frames.count < nr_gframes);
+ BUG_ON(gt->auto_xlat_grant_frames.count < nr_gframes);
/*
* Loop backwards, so that the first hypercall has the largest
* index, ensuring that the table will grow only once.
@@ -1251,8 +1312,8 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
xatp.domid = DOMID_SELF;
xatp.idx = i;
xatp.space = XENMAPSPACE_grant_table;
- xatp.gpfn = xen_auto_xlat_grant_frames.pfn[i];
- rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
+ xatp.gpfn = gt->auto_xlat_grant_frames.pfn[i];
+ rc = hypervisor_memory_op(xh, XENMEM_add_to_physmap, &xatp);
if (rc != 0) {
pr_warn("grant table add_to_physmap failed, err=%d\n",
rc);
@@ -1274,7 +1335,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
setup.nr_frames = nr_gframes;
set_xen_guest_handle(setup.frame_list, frames);

- rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ rc = hypervisor_grant_table_op(xh, GNTTABOP_setup_table, &setup, 1);
if (rc == -ENOSYS) {
kfree(frames);
return -ENOSYS;
@@ -1282,7 +1343,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)

BUG_ON(rc || setup.status);

- rc = gnttab_interface->map_frames(frames, nr_gframes);
+ rc = gt->gnttab_interface->map_frames(xh, frames, nr_gframes);

kfree(frames);

@@ -1313,13 +1374,13 @@ static const struct gnttab_ops gnttab_v2_ops = {
.query_foreign_access = gnttab_query_foreign_access_v2,
};

-static bool gnttab_need_v2(void)
+static bool gnttab_need_v2(xenhost_t *xh)
{
#ifdef CONFIG_X86
uint32_t base, width;

if (xen_pv_domain()) {
- base = xenhost_cpuid_base(xh_default);
+ base = xenhost_cpuid_base(xh);
if (cpuid_eax(base) < 5)
return false; /* Information not available, use V1. */
width = cpuid_ebx(base + 5) &
@@ -1330,12 +1391,13 @@ static bool gnttab_need_v2(void)
return !!(max_possible_pfn >> 32);
}

-static void gnttab_request_version(void)
+static void gnttab_request_version(xenhost_t *xh)
{
long rc;
struct gnttab_set_version gsv;
+ struct gnttab_private *gt = gt_priv(xh);

- if (gnttab_need_v2())
+ if (gnttab_need_v2(xh))
gsv.version = 2;
else
gsv.version = 1;
@@ -1344,139 +1406,162 @@ static void gnttab_request_version(void)
if (xen_gnttab_version >= 1 && xen_gnttab_version <= 2)
gsv.version = xen_gnttab_version;

- rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
+ rc = hypervisor_grant_table_op(xh, GNTTABOP_set_version, &gsv, 1);
if (rc == 0 && gsv.version == 2)
- gnttab_interface = &gnttab_v2_ops;
+ gt->gnttab_interface = &gnttab_v2_ops;
else
- gnttab_interface = &gnttab_v1_ops;
+ gt->gnttab_interface = &gnttab_v1_ops;
+
pr_info("Grant tables using version %d layout\n",
- gnttab_interface->version);
+ gt->gnttab_interface->version);
}

-static int gnttab_setup(void)
+static int gnttab_setup(xenhost_t *xh)
{
unsigned int max_nr_gframes;
+ struct gnttab_private *gt = gt_priv(xh);

- max_nr_gframes = gnttab_max_grant_frames();
- if (max_nr_gframes < nr_grant_frames)
+ max_nr_gframes = gnttab_max_grant_frames(xh);
+ if (max_nr_gframes < gt->nr_grant_frames)
return -ENOSYS;

- if (xen_feature(XENFEAT_auto_translated_physmap) && gnttab_shared.addr == NULL) {
- gnttab_shared.addr = xen_auto_xlat_grant_frames.vaddr;
- if (gnttab_shared.addr == NULL) {
+ if (__xen_feature(xh, XENFEAT_auto_translated_physmap) && gt->gnttab_shared.addr == NULL) {
+ gt->gnttab_shared.addr = gt->auto_xlat_grant_frames.vaddr;
+ if (gt->gnttab_shared.addr == NULL) {
pr_warn("gnttab share frames (addr=0x%08lx) is not mapped!\n",
- (unsigned long)xen_auto_xlat_grant_frames.vaddr);
+ (unsigned long)gt->auto_xlat_grant_frames.vaddr);
return -ENOMEM;
}
}
- return gnttab_map(0, nr_grant_frames - 1);
+ return gnttab_map(xh, 0, gt->nr_grant_frames - 1);
}

int gnttab_resume(void)
{
- gnttab_request_version();
- return gnttab_setup();
+ xenhost_t **xh;
+ for_each_xenhost(xh) {
+ int err;
+
+ gnttab_request_version(*xh);
+ err = gnttab_setup(*xh);
+ if (err)
+ return err;
+ }
+ return 0;
}

int gnttab_suspend(void)
{
- if (!xen_feature(XENFEAT_auto_translated_physmap))
- gnttab_interface->unmap_frames();
+ xenhost_t **xh;
+ struct gnttab_private *gt;
+
+ for_each_xenhost(xh) {
+ gt = gt_priv(*xh);
+
+ if (!__xen_feature((*xh), XENFEAT_auto_translated_physmap))
+ gt->gnttab_interface->unmap_frames(*xh);
+ return 0;
+ }
return 0;
}

-static int gnttab_expand(unsigned int req_entries)
+static int gnttab_expand(xenhost_t *xh, unsigned int req_entries)
{
int rc;
unsigned int cur, extra;
+ struct gnttab_private *gt = gt_priv(xh);

- BUG_ON(gnttab_interface == NULL);
- cur = nr_grant_frames;
- extra = ((req_entries + gnttab_interface->grefs_per_grant_frame - 1) /
- gnttab_interface->grefs_per_grant_frame);
- if (cur + extra > gnttab_max_grant_frames()) {
+ BUG_ON(gt->gnttab_interface == NULL);
+ cur = gt->nr_grant_frames;
+ extra = ((req_entries + gt->gnttab_interface->grefs_per_grant_frame - 1) /
+ gt->gnttab_interface->grefs_per_grant_frame);
+ if (cur + extra > gnttab_max_grant_frames(xh)) {
pr_warn_ratelimited("xen/grant-table: max_grant_frames reached"
" cur=%u extra=%u limit=%u"
" gnttab_free_count=%u req_entries=%u\n",
- cur, extra, gnttab_max_grant_frames(),
- gnttab_free_count, req_entries);
+ cur, extra, gnttab_max_grant_frames(xh),
+ gt->gnttab_free_count, req_entries);
return -ENOSPC;
}

- rc = gnttab_map(cur, cur + extra - 1);
+ rc = gnttab_map(xh, cur, cur + extra - 1);
if (rc == 0)
- rc = grow_gnttab_list(extra);
+ rc = grow_gnttab_list(xh, extra);

return rc;
}

-int gnttab_init(void)
+int gnttab_init(xenhost_t *xh)
{
int i;
unsigned long max_nr_grant_frames;
unsigned int max_nr_glist_frames, nr_glist_frames;
unsigned int nr_init_grefs;
int ret;
+ struct gnttab_private *gt = gt_priv(xh);

- gnttab_request_version();
- max_nr_grant_frames = gnttab_max_grant_frames();
- nr_grant_frames = 1;
+ gnttab_request_version(xh);
+ max_nr_grant_frames = gnttab_max_grant_frames(xh);
+ gt->nr_grant_frames = 1;

/* Determine the maximum number of frames required for the
* grant reference free list on the current hypervisor.
*/
- BUG_ON(gnttab_interface == NULL);
+ BUG_ON(gt->gnttab_interface == NULL);
max_nr_glist_frames = (max_nr_grant_frames *
- gnttab_interface->grefs_per_grant_frame / RPP);
+ gt->gnttab_interface->grefs_per_grant_frame / RPP);

- gnttab_list = kmalloc_array(max_nr_glist_frames,
+ gt->gnttab_list = kmalloc_array(max_nr_glist_frames,
sizeof(grant_ref_t *),
GFP_KERNEL);
- if (gnttab_list == NULL)
+ if (gt->gnttab_list == NULL)
return -ENOMEM;

- nr_glist_frames = gnttab_frames(nr_grant_frames, RPP);
+ nr_glist_frames = gnttab_frames(xh, gt->nr_grant_frames, RPP);
for (i = 0; i < nr_glist_frames; i++) {
- gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
- if (gnttab_list[i] == NULL) {
+ gt->gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
+ if (gt->gnttab_list[i] == NULL) {
ret = -ENOMEM;
goto ini_nomem;
}
}

- ret = arch_gnttab_init(max_nr_grant_frames,
- nr_status_frames(max_nr_grant_frames));
+ ret = arch_gnttab_init(xh, max_nr_grant_frames,
+ nr_status_frames(xh, max_nr_grant_frames));
if (ret < 0)
goto ini_nomem;

- if (gnttab_setup() < 0) {
+ if (gnttab_setup(xh) < 0) {
ret = -ENODEV;
goto ini_nomem;
}

- nr_init_grefs = nr_grant_frames *
- gnttab_interface->grefs_per_grant_frame;
+ nr_init_grefs = gt->nr_grant_frames *
+ gt->gnttab_interface->grefs_per_grant_frame;

for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
- gnttab_entry(i) = i + 1;
+ gnttab_entry(xh, i) = i + 1;

- gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END;
- gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
- gnttab_free_head = NR_RESERVED_ENTRIES;
+ gnttab_entry(xh, nr_init_grefs - 1) = GNTTAB_LIST_END;
+ gt->gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
+ gt->gnttab_free_head = NR_RESERVED_ENTRIES;

printk("Grant table initialized\n");
return 0;

ini_nomem:
for (i--; i >= 0; i--)
- free_page((unsigned long)gnttab_list[i]);
- kfree(gnttab_list);
+ free_page((unsigned long)gt->gnttab_list[i]);
+ kfree(gt->gnttab_list);
return ret;
}
EXPORT_SYMBOL_GPL(gnttab_init);

static int __gnttab_init(void)
{
+ xenhost_t **xh;
+ int err;
+
if (!xen_domain())
return -ENODEV;

@@ -1484,8 +1569,14 @@ static int __gnttab_init(void)
if (xen_hvm_domain() && !xen_pvh_domain())
return 0;

- return gnttab_init();
+ for_each_xenhost(xh) {
+ err = gnttab_init(*xh);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
/* Starts after core_initcall so that xen_pvh_gnttab_setup can be called
- * beforehand to initialize xen_auto_xlat_grant_frames. */
+ * beforehand to initialize auto_xlat_grant_frames. */
core_initcall_sync(__gnttab_init);
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 9bc5bc07d4d3..827b790199fb 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -74,15 +74,16 @@ struct gntab_unmap_queue_data
struct gnttab_unmap_grant_ref *unmap_ops;
struct gnttab_unmap_grant_ref *kunmap_ops;
struct page **pages;
+ xenhost_t *xh;
unsigned int count;
unsigned int age;
};

-int gnttab_init(void);
+int gnttab_init(xenhost_t *xh);
int gnttab_suspend(void);
int gnttab_resume(void);

-int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
+int gnttab_grant_foreign_access(xenhost_t *xh, domid_t domid, unsigned long frame,
int readonly);

/*
@@ -90,7 +91,7 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
* longer in use. Return 1 if the grant entry was freed, 0 if it is still in
* use.
*/
-int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly);
+int gnttab_end_foreign_access_ref(xenhost_t *xh, grant_ref_t ref, int readonly);

/*
* Eventually end access through the given grant reference, and once that
@@ -98,49 +99,49 @@ int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly);
* immediately iff the grant entry is not in use, otherwise it will happen
* some time later. page may be 0, in which case no freeing will occur.
*/
-void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
+void gnttab_end_foreign_access(xenhost_t *xh, grant_ref_t ref, int readonly,
unsigned long page);

-int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
+int gnttab_grant_foreign_transfer(xenhost_t *xh, domid_t domid, unsigned long pfn);

-unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
-unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
+unsigned long gnttab_end_foreign_transfer_ref(xenhost_t *xh, grant_ref_t ref);
+unsigned long gnttab_end_foreign_transfer(xenhost_t *xh, grant_ref_t ref);

-int gnttab_query_foreign_access(grant_ref_t ref);
+int gnttab_query_foreign_access(xenhost_t *xh, grant_ref_t ref);

/*
* operations on reserved batches of grant references
*/
-int gnttab_alloc_grant_references(u16 count, grant_ref_t *pprivate_head);
+int gnttab_alloc_grant_references(xenhost_t *xh, u16 count, grant_ref_t *pprivate_head);

-void gnttab_free_grant_reference(grant_ref_t ref);
+void gnttab_free_grant_reference(xenhost_t *xh, grant_ref_t ref);

-void gnttab_free_grant_references(grant_ref_t head);
+void gnttab_free_grant_references(xenhost_t *xh, grant_ref_t head);

-int gnttab_empty_grant_references(const grant_ref_t *pprivate_head);
+int gnttab_empty_grant_references(xenhost_t *xh, const grant_ref_t *pprivate_head);

-int gnttab_claim_grant_reference(grant_ref_t *pprivate_head);
+int gnttab_claim_grant_reference(xenhost_t *xh, grant_ref_t *pprivate_head);

-void gnttab_release_grant_reference(grant_ref_t *private_head,
+void gnttab_release_grant_reference(xenhost_t *xh, grant_ref_t *private_head,
grant_ref_t release);

-void gnttab_request_free_callback(struct gnttab_free_callback *callback,
+void gnttab_request_free_callback(xenhost_t *xh, struct gnttab_free_callback *callback,
void (*fn)(void *), void *arg, u16 count);
-void gnttab_cancel_free_callback(struct gnttab_free_callback *callback);
+void gnttab_cancel_free_callback(xenhost_t *xh, struct gnttab_free_callback *callback);

-void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+void gnttab_grant_foreign_access_ref(xenhost_t *xh, grant_ref_t ref, domid_t domid,
unsigned long frame, int readonly);

/* Give access to the first 4K of the page */
static inline void gnttab_page_grant_foreign_access_ref_one(
- grant_ref_t ref, domid_t domid,
+ xenhost_t *xh, grant_ref_t ref, domid_t domid,
struct page *page, int readonly)
{
- gnttab_grant_foreign_access_ref(ref, domid, xen_page_to_gfn(page),
+ gnttab_grant_foreign_access_ref(xh, ref, domid, xen_page_to_gfn(page),
readonly);
}

-void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
+void gnttab_grant_foreign_transfer_ref(xenhost_t *xh, grant_ref_t, domid_t domid,
unsigned long pfn);

static inline void
@@ -174,29 +175,28 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr,
unmap->dev_bus_addr = 0;
}

-int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status);
-int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
+int arch_gnttab_init(xenhost_t *xh, unsigned long nr_shared, unsigned long nr_status);
+int arch_gnttab_map_shared(xenhost_t *xh, xen_pfn_t *frames, unsigned long nr_gframes,
unsigned long max_nr_gframes,
void **__shared);
-int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
+int arch_gnttab_map_status(xenhost_t *xh, uint64_t *frames, unsigned long nr_gframes,
unsigned long max_nr_gframes,
grant_status_t **__shared);
-void arch_gnttab_unmap(void *shared, unsigned long nr_gframes);
+void arch_gnttab_unmap(xenhost_t *xh, void *shared, unsigned long nr_gframes);

struct grant_frames {
xen_pfn_t *pfn;
unsigned int count;
void *vaddr;
};
-extern struct grant_frames xen_auto_xlat_grant_frames;
-unsigned int gnttab_max_grant_frames(void);
-int gnttab_setup_auto_xlat_frames(phys_addr_t addr);
-void gnttab_free_auto_xlat_frames(void);
+unsigned int gnttab_max_grant_frames(xenhost_t *xh);
+int gnttab_setup_auto_xlat_frames(xenhost_t *xh, phys_addr_t addr);
+void gnttab_free_auto_xlat_frames(xenhost_t *xh);

#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))

-int gnttab_alloc_pages(int nr_pages, struct page **pages);
-void gnttab_free_pages(int nr_pages, struct page **pages);
+int gnttab_alloc_pages(xenhost_t *xh, int nr_pages, struct page **pages);
+void gnttab_free_pages(xenhost_t *xh, int nr_pages, struct page **pages);

#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
struct gnttab_dma_alloc_args {
@@ -212,17 +212,17 @@ struct gnttab_dma_alloc_args {
dma_addr_t dev_bus_addr;
};

-int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args);
-int gnttab_dma_free_pages(struct gnttab_dma_alloc_args *args);
+int gnttab_dma_alloc_pages(xenhost_t *xh, struct gnttab_dma_alloc_args *args);
+int gnttab_dma_free_pages(xenhost_t *xh, struct gnttab_dma_alloc_args *args);
#endif

int gnttab_pages_set_private(int nr_pages, struct page **pages);
void gnttab_pages_clear_private(int nr_pages, struct page **pages);

-int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
+int gnttab_map_refs(xenhost_t *xh, struct gnttab_map_grant_ref *map_ops,
struct gnttab_map_grant_ref *kmap_ops,
struct page **pages, unsigned int count);
-int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
+int gnttab_unmap_refs(xenhost_t *xh, struct gnttab_unmap_grant_ref *unmap_ops,
struct gnttab_unmap_grant_ref *kunmap_ops,
struct page **pages, unsigned int count);
void gnttab_unmap_refs_async(struct gntab_unmap_queue_data* item);
@@ -238,8 +238,8 @@ int gnttab_unmap_refs_sync(struct gntab_unmap_queue_data *item);
* Return value in each iand every status field of the batch guaranteed
* to not be GNTST_eagain.
*/
-void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count);
-void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count);
+void gnttab_batch_map(xenhost_t *xh, struct gnttab_map_grant_ref *batch, unsigned count);
+void gnttab_batch_copy(xenhost_t *xh, struct gnttab_copy *batch, unsigned count);


struct xen_page_foreign {
diff --git a/include/xen/xenhost.h b/include/xen/xenhost.h
index 9e08627a9e3e..acee0c7872b6 100644
--- a/include/xen/xenhost.h
+++ b/include/xen/xenhost.h
@@ -129,6 +129,17 @@ typedef struct {
const struct evtchn_ops *evtchn_ops;
int **evtchn_to_irq;
};
+
+ /* grant table private state */
+ struct {
+ /* private to drivers/xen/grant-table.c */
+ void *gnttab_private;
+
+ /* x86/xen/grant-table.c */
+ void *gnttab_shared_vm_area;
+ void *gnttab_status_vm_area;
+ void *auto_xlat_grant_frames;
+ };
} xenhost_t;

typedef struct xenhost_ops {
--
2.20.1