|
@@ -56,10 +56,6 @@
|
|
|
/* External tools reserve first few grant table entries. */
|
|
|
#define NR_RESERVED_ENTRIES 8
|
|
|
#define GNTTAB_LIST_END 0xffffffff
|
|
|
-#define GREFS_PER_GRANT_FRAME \
|
|
|
-(grant_table_version == 1 ? \
|
|
|
-(PAGE_SIZE / sizeof(struct grant_entry_v1)) : \
|
|
|
-(PAGE_SIZE / sizeof(union grant_entry_v2)))
|
|
|
|
|
|
static grant_ref_t **gnttab_list;
|
|
|
static unsigned int nr_grant_frames;
|
|
@@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface;
|
|
|
static grant_status_t *grstatus;
|
|
|
|
|
|
static int grant_table_version;
|
|
|
+static int grefs_per_grant_frame;
|
|
|
|
|
|
static struct gnttab_free_callback *gnttab_free_callback_list;
|
|
|
|
|
@@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames)
|
|
|
unsigned int new_nr_grant_frames, extra_entries, i;
|
|
|
unsigned int nr_glist_frames, new_nr_glist_frames;
|
|
|
|
|
|
+ BUG_ON(grefs_per_grant_frame == 0);
|
|
|
+
|
|
|
new_nr_grant_frames = nr_grant_frames + more_frames;
|
|
|
- extra_entries = more_frames * GREFS_PER_GRANT_FRAME;
|
|
|
+ extra_entries = more_frames * grefs_per_grant_frame;
|
|
|
|
|
|
- nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
|
|
|
+ nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
|
|
|
new_nr_glist_frames =
|
|
|
- (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
|
|
|
+ (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / 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])
|
|
@@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames)
|
|
|
}
|
|
|
|
|
|
|
|
|
- for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
|
|
|
- i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
|
|
|
+ for (i = grefs_per_grant_frame * nr_grant_frames;
|
|
|
+ i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++)
|
|
|
gnttab_entry(i) = i + 1;
|
|
|
|
|
|
gnttab_entry(i) = gnttab_free_head;
|
|
|
- gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
|
|
|
+ gnttab_free_head = grefs_per_grant_frame * nr_grant_frames;
|
|
|
gnttab_free_count += extra_entries;
|
|
|
|
|
|
nr_grant_frames = new_nr_grant_frames;
|
|
@@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
|
|
|
|
|
|
static unsigned nr_status_frames(unsigned nr_grant_frames)
|
|
|
{
|
|
|
- return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
|
|
|
+ BUG_ON(grefs_per_grant_frame == 0);
|
|
|
+ return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP;
|
|
|
}
|
|
|
|
|
|
static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
|
|
@@ -1115,6 +1115,7 @@ static void gnttab_request_version(void)
|
|
|
rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
|
|
|
if (rc == 0 && gsv.version == 2) {
|
|
|
grant_table_version = 2;
|
|
|
+ grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2);
|
|
|
gnttab_interface = &gnttab_v2_ops;
|
|
|
} else if (grant_table_version == 2) {
|
|
|
/*
|
|
@@ -1127,17 +1128,17 @@ static void gnttab_request_version(void)
|
|
|
panic("we need grant tables version 2, but only version 1 is available");
|
|
|
} else {
|
|
|
grant_table_version = 1;
|
|
|
+ grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
|
|
|
gnttab_interface = &gnttab_v1_ops;
|
|
|
}
|
|
|
printk(KERN_INFO "Grant tables using version %d layout.\n",
|
|
|
grant_table_version);
|
|
|
}
|
|
|
|
|
|
-int gnttab_resume(void)
|
|
|
+static int gnttab_setup(void)
|
|
|
{
|
|
|
unsigned int max_nr_gframes;
|
|
|
|
|
|
- gnttab_request_version();
|
|
|
max_nr_gframes = gnttab_max_grant_frames();
|
|
|
if (max_nr_gframes < nr_grant_frames)
|
|
|
return -ENOSYS;
|
|
@@ -1160,6 +1161,12 @@ int gnttab_resume(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+int gnttab_resume(void)
|
|
|
+{
|
|
|
+ gnttab_request_version();
|
|
|
+ return gnttab_setup();
|
|
|
+}
|
|
|
+
|
|
|
int gnttab_suspend(void)
|
|
|
{
|
|
|
gnttab_interface->unmap_frames();
|
|
@@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries)
|
|
|
int rc;
|
|
|
unsigned int cur, extra;
|
|
|
|
|
|
+ BUG_ON(grefs_per_grant_frame == 0);
|
|
|
cur = nr_grant_frames;
|
|
|
- extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
|
|
|
- GREFS_PER_GRANT_FRAME);
|
|
|
+ extra = ((req_entries + (grefs_per_grant_frame-1)) /
|
|
|
+ grefs_per_grant_frame);
|
|
|
if (cur + extra > gnttab_max_grant_frames())
|
|
|
return -ENOSPC;
|
|
|
|
|
@@ -1191,21 +1199,23 @@ int gnttab_init(void)
|
|
|
unsigned int nr_init_grefs;
|
|
|
int ret;
|
|
|
|
|
|
+ gnttab_request_version();
|
|
|
nr_grant_frames = 1;
|
|
|
boot_max_nr_grant_frames = __max_nr_grant_frames();
|
|
|
|
|
|
/* Determine the maximum number of frames required for the
|
|
|
* grant reference free list on the current hypervisor.
|
|
|
*/
|
|
|
+ BUG_ON(grefs_per_grant_frame == 0);
|
|
|
max_nr_glist_frames = (boot_max_nr_grant_frames *
|
|
|
- GREFS_PER_GRANT_FRAME / RPP);
|
|
|
+ grefs_per_grant_frame / RPP);
|
|
|
|
|
|
gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
|
|
|
GFP_KERNEL);
|
|
|
if (gnttab_list == NULL)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
|
|
|
+ nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / 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) {
|
|
@@ -1214,12 +1224,12 @@ int gnttab_init(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (gnttab_resume() < 0) {
|
|
|
+ if (gnttab_setup() < 0) {
|
|
|
ret = -ENODEV;
|
|
|
goto ini_nomem;
|
|
|
}
|
|
|
|
|
|
- nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
|
|
|
+ nr_init_grefs = nr_grant_frames * grefs_per_grant_frame;
|
|
|
|
|
|
for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
|
|
|
gnttab_entry(i) = i + 1;
|