@@ -71,6 +71,9 @@ struct grant_table {
* what version to use yet.
*/
unsigned gt_version;
+ /* Resource limits of the domain. */
+ unsigned int max_grant_frames;
+ unsigned int max_maptrack_frames;
};
#ifndef DEFAULT_MAX_NR_GRANT_FRAMES /* to allow arch to override */
@@ -287,8 +290,8 @@ num_act_frames_from_sha_frames(const unsigned int num)
return DIV_ROUND_UP(num * sha_per_page, ACGNT_PER_PAGE);
}
-#define max_nr_active_grant_frames \
- num_act_frames_from_sha_frames(max_grant_frames)
+#define max_nr_active_grant_frames(gt) \
+ num_act_frames_from_sha_frames(gt->max_grant_frames)
static inline unsigned int
nr_active_grant_frames(struct grant_table *gt)
@@ -526,7 +529,7 @@ get_maptrack_handle(
* out of memory, try stealing an entry from another VCPU (in case the
* guest isn't mapping across its VCPUs evenly).
*/
- if ( nr_maptrack_frames(lgt) < max_maptrack_frames )
+ if ( nr_maptrack_frames(lgt) < lgt->max_maptrack_frames )
new_mt = alloc_xenheap_page();
if ( !new_mt )
@@ -1664,14 +1667,15 @@ grant_table_init(struct domain *d)
if ( gt->nr_grant_frames )
return 0;
- gt->nr_grant_frames = INITIAL_NR_GRANT_FRAMES;
+ gt->nr_grant_frames = min_t(unsigned int, INITIAL_NR_GRANT_FRAMES,
+ gt->max_grant_frames);
/* Active grant table. */
if ( (gt->active = xzalloc_array(struct active_grant_entry *,
- max_nr_active_grant_frames)) == NULL )
+ max_nr_active_grant_frames(gt))) == NULL )
goto no_mem_1;
for ( i = 0;
- i < num_act_frames_from_sha_frames(INITIAL_NR_GRANT_FRAMES); i++ )
+ i < num_act_frames_from_sha_frames(gt->nr_grant_frames); i++ )
{
if ( (gt->active[i] = alloc_xenheap_page()) == NULL )
goto no_mem_2;
@@ -1681,14 +1685,14 @@ grant_table_init(struct domain *d)
}
/* Tracking of mapped foreign frames table */
- gt->maptrack = vzalloc(max_maptrack_frames * sizeof(*gt->maptrack));
+ gt->maptrack = vzalloc(gt->max_maptrack_frames * sizeof(*gt->maptrack));
if ( gt->maptrack == NULL )
goto no_mem_2;
/* Shared grant table. */
- if ( (gt->shared_raw = xzalloc_array(void *, max_grant_frames)) == NULL )
+ if ( (gt->shared_raw = xzalloc_array(void *, gt->max_grant_frames)) == NULL )
goto no_mem_3;
- for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
+ for ( i = 0; i < gt->nr_grant_frames; i++ )
{
if ( (gt->shared_raw[i] = alloc_xenheap_page()) == NULL )
goto no_mem_4;
@@ -1697,11 +1701,11 @@ grant_table_init(struct domain *d)
/* Status pages for grant table - for version 2 */
gt->status = xzalloc_array(grant_status_t *,
- grant_to_status_frames(max_grant_frames));
+ grant_to_status_frames(gt->max_grant_frames));
if ( gt->status == NULL )
goto no_mem_4;
- for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
+ for ( i = 0; i < gt->nr_grant_frames; i++ )
gnttab_create_shared_page(d, gt, i);
gt->nr_status_frames = 0;
@@ -1709,7 +1713,7 @@ grant_table_init(struct domain *d)
return 0;
no_mem_4:
- for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
+ for ( i = 0; i < gt->nr_grant_frames; i++ )
free_xenheap_page(gt->shared_raw[i]);
xfree(gt->shared_raw);
gt->shared_raw = NULL;
@@ -1718,7 +1722,7 @@ grant_table_init(struct domain *d)
gt->maptrack = NULL;
no_mem_2:
for ( i = 0;
- i < num_act_frames_from_sha_frames(INITIAL_NR_GRANT_FRAMES); i++ )
+ i < num_act_frames_from_sha_frames(gt->nr_grant_frames); i++ )
free_xenheap_page(gt->active[i]);
xfree(gt->active);
gt->active = NULL;
@@ -1743,7 +1747,7 @@ gnttab_grow_table(struct domain *d, unsigned int req_nr_frames)
return 0;
}
- ASSERT(req_nr_frames <= max_grant_frames);
+ ASSERT(req_nr_frames <= gt->max_grant_frames);
gdprintk(XENLOG_INFO,
"Expanding dom (%d) grant table from (%d) to (%d) frames.\n",
@@ -1815,15 +1819,6 @@ gnttab_setup_table(
if ( unlikely(copy_from_guest(&op, uop, 1)) )
return -EFAULT;
- if ( unlikely(op.nr_frames > max_grant_frames) )
- {
- gdprintk(XENLOG_INFO, "Xen only supports up to %d grant-table frames"
- " per domain.\n",
- max_grant_frames);
- op.status = GNTST_general_error;
- goto out;
- }
-
if ( !guest_handle_okay(op.frame_list, op.nr_frames) )
return -EFAULT;
@@ -1843,6 +1838,14 @@ gnttab_setup_table(
gt = d->grant_table;
grant_write_lock(gt);
+ if ( unlikely(op.nr_frames > gt->max_grant_frames) )
+ {
+ gdprintk(XENLOG_INFO, "Domain is limited to %d grant-table frames.\n",
+ gt->max_grant_frames);
+ op.status = GNTST_general_error;
+ goto unlock;
+ }
+
if ( gt->gt_version == 0 )
gt->gt_version = 1;
@@ -1853,7 +1856,7 @@ gnttab_setup_table(
{
gdprintk(XENLOG_INFO,
"Expand grant table to %u failed. Current: %u Max: %u\n",
- op.nr_frames, nr_grant_frames(gt), max_grant_frames);
+ op.nr_frames, nr_grant_frames(gt), gt->max_grant_frames);
op.status = GNTST_general_error;
goto unlock;
}
@@ -1888,6 +1891,7 @@ gnttab_query_size(
{
struct gnttab_query_size op;
struct domain *d;
+ struct grant_table *gt;
if ( count != 1 )
return -EINVAL;
@@ -1908,13 +1912,15 @@ gnttab_query_size(
goto out;
}
- grant_read_lock(d->grant_table);
+ gt = d->grant_table;
+
+ grant_read_lock(gt);
- op.nr_frames = nr_grant_frames(d->grant_table);
- op.max_nr_frames = max_grant_frames;
+ op.nr_frames = nr_grant_frames(gt);
+ op.max_nr_frames = gt->max_grant_frames;
op.status = GNTST_okay;
- grant_read_unlock(d->grant_table);
+ grant_read_unlock(gt);
out:
if ( d )
@@ -3465,6 +3471,8 @@ grant_table_create(
/* Simple stuff. */
percpu_rwlock_resource_init(&t->lock, grant_rwlock);
spin_lock_init(&t->maptrack_lock);
+ t->max_grant_frames = max_grant_frames;
+ t->max_maptrack_frames = max_maptrack_frames;
/* Okay, install the structure. */
d->grant_table = t;
@@ -3728,7 +3736,7 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
}
else
{
- if ( (idx >= nr_grant_frames(gt)) && (idx < max_grant_frames) )
+ if ( (idx >= nr_grant_frames(gt)) && (idx < gt->max_grant_frames) )
gnttab_grow_table(d, idx + 1);
if ( idx < nr_grant_frames(gt) )
@@ -3755,6 +3763,12 @@ static void gnttab_usage_print(struct domain *rd)
grant_read_lock(gt);
+ printk("grant-table for remote domain:%5d (v%d)\n"
+ " %d frames (%d max), %d maptrack frames (%d max)\n",
+ rd->domain_id, gt->gt_version,
+ nr_grant_frames(gt), gt->max_grant_frames,
+ nr_maptrack_frames(gt), gt->max_maptrack_frames);
+
for ( ref = 0; ref != nr_grant_entries(gt); ref++ )
{
struct active_grant_entry *act;
@@ -3782,12 +3796,7 @@ static void gnttab_usage_print(struct domain *rd)
status = status_entry(gt, ref);
}
- if ( first )
- {
- printk("grant-table for remote domain:%5d (v%d)\n",
- rd->domain_id, gt->gt_version);
- first = 0;
- }
+ first = 0;
/* [0xXXX] ddddd 0xXXXXXX 0xXXXXXXXX ddddd 0xXXXXXX 0xXX */
printk("[0x%03x] %5d 0x%06lx 0x%08x %5d 0x%06"PRIx64" 0x%02x\n",
@@ -3799,8 +3808,7 @@ static void gnttab_usage_print(struct domain *rd)
grant_read_unlock(gt);
if ( first )
- printk("grant-table for remote domain:%5d ... "
- "no active grant table entries\n", rd->domain_id);
+ printk("no active grant table entries\n");
}
static void gnttab_usage_print_all(unsigned char key)