[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v9 09/10] xen: make grant resource limits per domain
Instead of using the same global resource limits of grant tables (max. number of grant frames, max. number of maptrack frames) for all domains make these limits per domain. Set those per-domain limits in grant_table_set_limits(). The global settings are serving as an upper boundary now which must not be exceeded by a per-domain value. The default of max_grant_frames is set to the maximum default xl will use. While updating the semantics of the boot parameters remove the documentation of the no longer existing gnttab_max_nr_frames. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> --- V9: - add caps for per-domain limits (Jan Beulich) - some error messages enhanced (Jan Beulich) - adjusted some types (Jan Beulich) - merge parts of (former) patch 14 into this one - make parameters changeable at runtime - limit size of dom0's grant table on ARM - set default max_grant_frames to 64 V6: - several changes due to new patch order V3: - correct error message (Paul Durrant) --- docs/misc/xen-command-line.markdown | 25 +++--- xen/arch/arm/domain_build.c | 6 +- xen/common/compat/grant_table.c | 31 ++----- xen/common/grant_table.c | 159 +++++++++++++++++++++--------------- xen/include/asm-arm/grant_table.h | 18 +++- xen/include/asm-x86/grant_table.h | 7 +- xen/include/xen/grant_table.h | 3 - 7 files changed, 134 insertions(+), 115 deletions(-) diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown index 9797c8db2d..9b6cd8e9d0 100644 --- a/docs/misc/xen-command-line.markdown +++ b/docs/misc/xen-command-line.markdown @@ -875,27 +875,28 @@ Specify which console gdbstub should use. See **console**. ### gnttab\_max\_frames > `= <integer>` -> Default: `32` +> Default: `64` + +> Can be modified at runtime Specify the maximum number of frames which any domain may use as part -of its grant table. +of its grant table. This value is an upper boundary of the per-domain +value settable via Xen tools. + +Dom0 is using this value for sizing its grant table. ### gnttab\_max\_maptrack\_frames > `= <integer>` -> Default: `8 * gnttab_max_frames` - -Specify the maximum number of frames to use as part of a domains -maptrack array. +> Default: `1024` -### gnttab\_max\_nr\_frames -> `= <integer>` +> Can be modified at runtime -*Deprecated* -Use **gnttab\_max\_frames** and **gnttab\_max\_maptrack\_frames** instead. +Specify the maximum number of frames to use as part of a domains +maptrack array. This value is an upper boundary of the per-domain +value settable via Xen tools. -Specify the maximum number of frames per grant table operation and the -maximum number of maptrack frames domain. +Dom0 is using this value for sizing its maptrack table. ### guest\_loglvl > `= <level>[/<rate-limited level>]` where level is `none | error | warning | > info | debug | all` diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index c34238ec1b..4664f3906d 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -2095,11 +2095,7 @@ static void __init find_gnttab_region(struct domain *d, * enough space for a large grant table */ kinfo->gnttab_start = __pa(_stext); - kinfo->gnttab_size = (_etext - _stext) & PAGE_MASK; - - /* Make sure the grant table will fit in the region */ - if ( (kinfo->gnttab_size >> PAGE_SHIFT) < max_grant_frames ) - panic("Cannot find a space for the grant table region\n"); + kinfo->gnttab_size = gnttab_dom0_max() << PAGE_SHIFT; #ifdef CONFIG_ARM_32 /* diff --git a/xen/common/compat/grant_table.c b/xen/common/compat/grant_table.c index cce3ff0b9a..ff1d678f01 100644 --- a/xen/common/compat/grant_table.c +++ b/xen/common/compat/grant_table.c @@ -157,21 +157,14 @@ int compat_grant_table_op(unsigned int cmd, unsigned int max_frame_list_size_in_page = (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.setup)) / sizeof(*nat.setup->frame_list.p); - if ( max_frame_list_size_in_page < max_grant_frames ) - { - gdprintk(XENLOG_WARNING, - "max_grant_frames is too large (%u,%u)\n", - max_grant_frames, max_frame_list_size_in_page); - rc = -EINVAL; - } - else - { + #define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \ - set_xen_guest_handle((_d_)->frame_list, (unsigned long *)(nat.setup + 1)) - XLAT_gnttab_setup_table(nat.setup, &cmp.setup); + set_xen_guest_handle((_d_)->frame_list, (unsigned long *)(nat.setup + 1)) + XLAT_gnttab_setup_table(nat.setup, &cmp.setup); #undef XLAT_gnttab_setup_table_HNDL_frame_list - rc = gnttab_setup_table(guest_handle_cast(nat.uop, gnttab_setup_table_t), 1); - } + rc = gnttab_setup_table(guest_handle_cast(nat.uop, + gnttab_setup_table_t), + 1, max_frame_list_size_in_page); } ASSERT(rc <= 0); if ( rc == 0 ) @@ -294,16 +287,6 @@ int compat_grant_table_op(unsigned int cmd, rc = -EFAULT; break; } - if ( max_frame_list_size_in_pages < - grant_to_status_frames(max_grant_frames) ) - { - gdprintk(XENLOG_WARNING, - "grant_to_status_frames(max_grant_frames) is too large (%u,%u)\n", - grant_to_status_frames(max_grant_frames), - max_frame_list_size_in_pages); - rc = -EINVAL; - break; - } #define XLAT_gnttab_get_status_frames_HNDL_frame_list(_d_, _s_) \ set_xen_guest_handle((_d_)->frame_list, (uint64_t *)(nat.get_status + 1)) @@ -312,7 +295,7 @@ int compat_grant_table_op(unsigned int cmd, rc = gnttab_get_status_frames( guest_handle_cast(nat.uop, gnttab_get_status_frames_t), - count); + count, max_frame_list_size_in_pages); if ( rc >= 0 ) { #define XLAT_gnttab_get_status_frames_HNDL_frame_list(_d_, _s_) \ diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 73ba915a30..d835f5ab80 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -54,6 +54,9 @@ struct grant_table { * what version to use yet. */ unsigned int gt_version; + /* Resource limits of the domain. */ + unsigned int max_grant_frames; + unsigned int max_maptrack_frames; /* Table size. Number of frames shared with guest */ unsigned int nr_grant_frames; /* Number of grant status frames shared with guest (for version 2) */ @@ -78,23 +81,18 @@ struct grant_table { #ifndef DEFAULT_MAX_NR_GRANT_FRAMES /* to allow arch to override */ /* Default maximum size of a grant table. [POLICY] */ -#define DEFAULT_MAX_NR_GRANT_FRAMES 32 +#define DEFAULT_MAX_NR_GRANT_FRAMES 64 #endif -unsigned int __read_mostly max_grant_frames; -integer_param("gnttab_max_frames", max_grant_frames); +static unsigned int __read_mostly max_grant_frames = + DEFAULT_MAX_NR_GRANT_FRAMES; +integer_runtime_param("gnttab_max_frames", max_grant_frames); -/* The maximum number of grant mappings is defined as a multiplier of the - * maximum number of grant table entries. This defines the multiplier used. - * Pretty arbitrary. [POLICY] - * As gnttab_max_nr_frames has been deprecated, this multiplier is deprecated too. - * New options allow to set max_maptrack_frames and - * map_grant_table_frames independently. - */ #define DEFAULT_MAX_MAPTRACK_FRAMES 1024 -static unsigned int __read_mostly max_maptrack_frames; -integer_param("gnttab_max_maptrack_frames", max_maptrack_frames); +static unsigned int __read_mostly max_maptrack_frames = + DEFAULT_MAX_MAPTRACK_FRAMES; +integer_runtime_param("gnttab_max_maptrack_frames", max_maptrack_frames); /* * Note that the three values below are effectively part of the ABI, even if @@ -290,8 +288,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) @@ -530,7 +528,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 ) @@ -1672,8 +1670,8 @@ gnttab_grow_table(struct domain *d, unsigned int req_nr_frames) ASSERT(gt->active); if ( req_nr_frames < INITIAL_NR_GRANT_FRAMES ) - req_nr_frames = INITIAL_NR_GRANT_FRAMES; - ASSERT(req_nr_frames <= max_grant_frames); + req_nr_frames = min(INITIAL_NR_GRANT_FRAMES, gt->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", @@ -1739,23 +1737,26 @@ grant_table_init(struct domain *d, struct grant_table *gt) /* Active grant table. */ gt->active = xzalloc_array(struct active_grant_entry *, - max_nr_active_grant_frames); + max_nr_active_grant_frames(gt)); if ( gt->active == NULL ) goto out; /* Tracking of mapped foreign frames table */ - gt->maptrack = vzalloc(max_maptrack_frames * sizeof(*gt->maptrack)); - if ( gt->maptrack == NULL ) - goto out; + if ( gt->max_maptrack_frames ) + { + gt->maptrack = vzalloc(gt->max_maptrack_frames * sizeof(*gt->maptrack)); + if ( gt->maptrack == NULL ) + goto out; + } /* Shared grant table. */ - gt->shared_raw = xzalloc_array(void *, max_grant_frames); + gt->shared_raw = xzalloc_array(void *, gt->max_grant_frames); if ( gt->shared_raw == NULL ) goto out; /* 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 out; @@ -1782,13 +1783,15 @@ grant_table_init(struct domain *d, struct grant_table *gt) static long gnttab_setup_table( - XEN_GUEST_HANDLE_PARAM(gnttab_setup_table_t) uop, unsigned int count) + XEN_GUEST_HANDLE_PARAM(gnttab_setup_table_t) uop, unsigned int count, + unsigned int limit_max) { struct vcpu *curr = current; struct gnttab_setup_table op; struct domain *d = NULL; struct grant_table *gt; unsigned int i; + int ret = 0; if ( count != 1 ) return -EINVAL; @@ -1796,15 +1799,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; @@ -1824,6 +1818,21 @@ gnttab_setup_table( gt = d->grant_table; grant_write_lock(gt); + if ( unlikely(op.nr_frames > gt->max_grant_frames) ) + { + gdprintk(XENLOG_INFO, "d%u is limited to %u grant-table frames.\n", + d->domain_id, gt->max_grant_frames); + op.status = GNTST_general_error; + goto unlock; + } + if ( unlikely(limit_max < op.nr_frames) ) + { + gdprintk(XENLOG_WARNING, "nr_frames for d%u is too large (%u,%u)\n", + d->domain_id, op.nr_frames, limit_max); + op.status = GNTST_general_error; + goto unlock; + } + if ( gt->gt_version == 0 ) gt->gt_version = 1; @@ -1833,8 +1842,9 @@ gnttab_setup_table( !gnttab_grow_table(d, op.nr_frames) ) { gdprintk(XENLOG_INFO, - "Expand grant table to %u failed. Current: %u Max: %u\n", - op.nr_frames, nr_grant_frames(gt), max_grant_frames); + "Expand grant table of d%u to %u failed. Current: %u Max: %u\n", + d->domain_id, op.nr_frames, nr_grant_frames(gt), + gt->max_grant_frames); op.status = GNTST_general_error; goto unlock; } @@ -1857,10 +1867,10 @@ gnttab_setup_table( if ( d ) rcu_unlock_domain(d); - if ( unlikely(__copy_field_to_guest(uop, &op, status)) ) + if ( !ret && unlikely(__copy_field_to_guest(uop, &op, status)) ) return -EFAULT; - return 0; + return ret; } static long @@ -1869,6 +1879,7 @@ gnttab_query_size( { struct gnttab_query_size op; struct domain *d; + struct grant_table *gt; if ( count != 1 ) return -EINVAL; @@ -1889,13 +1900,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 ) @@ -2970,14 +2983,14 @@ gnttab_set_version(XEN_GUEST_HANDLE_PARAM(gnttab_set_version_t) uop) static long gnttab_get_status_frames(XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_t) uop, - int count) + unsigned int count, unsigned int limit_max) { gnttab_get_status_frames_t op; struct domain *d; struct grant_table *gt; uint64_t gmfn; int i; - int rc; + int rc, ret = 0; if ( count != 1 ) return -EINVAL; @@ -3010,9 +3023,19 @@ gnttab_get_status_frames(XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_t) uop, if ( unlikely(op.nr_frames > nr_status_frames(gt)) ) { - gdprintk(XENLOG_INFO, "Guest requested addresses for %d grant status " - "frames, but only %d are available.\n", - op.nr_frames, nr_status_frames(gt)); + gdprintk(XENLOG_INFO, "Guest requested addresses of d%u for %u grant " + "status frames, but only %u are available.\n", + d->domain_id, op.nr_frames, nr_status_frames(gt)); + op.status = GNTST_general_error; + goto unlock; + } + + if ( unlikely(limit_max < grant_to_status_frames(op.nr_frames)) ) + { + gdprintk(XENLOG_WARNING, + "grant_to_status_frames(%u) for d%u is too large (%u,%u)\n", + op.nr_frames, d->domain_id, + grant_to_status_frames(op.nr_frames), limit_max); op.status = GNTST_general_error; goto unlock; } @@ -3029,10 +3052,10 @@ gnttab_get_status_frames(XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_t) uop, out2: rcu_unlock_domain(d); out1: - if ( unlikely(__copy_field_to_guest(uop, &op, status)) ) + if ( !ret && unlikely(__copy_field_to_guest(uop, &op, status)) ) return -EFAULT; - return 0; + return ret; } static long @@ -3325,7 +3348,7 @@ do_grant_table_op( case GNTTABOP_setup_table: rc = gnttab_setup_table( - guest_handle_cast(uop, gnttab_setup_table_t), count); + guest_handle_cast(uop, gnttab_setup_table_t), count, UINT_MAX); ASSERT(rc <= 0); break; @@ -3374,7 +3397,8 @@ do_grant_table_op( case GNTTABOP_get_status_frames: rc = gnttab_get_status_frames( - guest_handle_cast(uop, gnttab_get_status_frames_t), count); + guest_handle_cast(uop, gnttab_get_status_frames_t), count, + UINT_MAX); break; case GNTTABOP_get_version: @@ -3454,6 +3478,8 @@ grant_table_create( if ( d->domain_id == 0 ) { + t->max_grant_frames = gnttab_dom0_frames(max_grant_frames); + t->max_maptrack_frames = max_maptrack_frames; grant_write_lock(t); ret = grant_table_init(d, t); grant_write_unlock(t); @@ -3658,6 +3684,9 @@ int grant_table_set_limits(struct domain *d, unsigned int grant_frames, struct grant_table *gt = d->grant_table; int ret = -EBUSY; + if ( !grant_frames || grant_frames > max_grant_frames || + maptrack_frames > max_maptrack_frames ) + return -EINVAL; if ( !gt ) return -ENOENT; @@ -3665,7 +3694,11 @@ int grant_table_set_limits(struct domain *d, unsigned int grant_frames, /* Set limits. */ if ( !gt->active ) + { + gt->max_grant_frames = grant_frames; + gt->max_maptrack_frames = maptrack_frames; ret = grant_table_init(d, gt); + } grant_write_unlock(gt); @@ -3741,7 +3774,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) ) @@ -3769,6 +3802,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; @@ -3796,12 +3835,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", @@ -3813,8 +3847,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) @@ -3828,14 +3861,6 @@ static void gnttab_usage_print_all(unsigned char key) static int __init gnttab_usage_init(void) { - BUILD_BUG_ON(DEFAULT_MAX_MAPTRACK_FRAMES < DEFAULT_MAX_NR_GRANT_FRAMES); - - if ( !max_grant_frames ) - max_grant_frames = DEFAULT_MAX_NR_GRANT_FRAMES; - - if ( !max_maptrack_frames ) - max_maptrack_frames = DEFAULT_MAX_MAPTRACK_FRAMES; - register_keyhandler('g', gnttab_usage_print_all, "print grant table usage", 1); return 0; diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h index 30db2d1616..44ebcfb6e6 100644 --- a/xen/include/asm-arm/grant_table.h +++ b/xen/include/asm-arm/grant_table.h @@ -2,9 +2,11 @@ #define __ASM_GRANT_TABLE_H__ #include <xen/grant_table.h> +#include <xen/kernel.h> +#include <xen/pfn.h> #include <xen/sched.h> -#define INITIAL_NR_GRANT_FRAMES 4 +#define INITIAL_NR_GRANT_FRAMES 4U struct grant_table_arch { gfn_t *gfn; @@ -26,9 +28,19 @@ static inline int replace_grant_supported(void) return 1; } +static inline unsigned int gnttab_dom0_max(void) +{ + return PFN_DOWN(_etext - _stext); +} + +static inline unsigned int gnttab_dom0_frames(unsigned int max_frames) +{ + return min(max_frames, gnttab_dom0_max()); +} + #define gnttab_init_arch(gt) \ ({ \ - (gt)->arch.gfn = xzalloc_array(gfn_t, max_grant_frames); \ + (gt)->arch.gfn = xzalloc_array(gfn_t, (gt)->max_grant_frames); \ ( (gt)->arch.gfn ? 0 : -ENOMEM ); \ }) @@ -52,7 +64,7 @@ static inline int replace_grant_supported(void) #define gnttab_shared_gmfn(d, t, i) \ ( ((i >= nr_grant_frames(t)) && \ - (i < max_grant_frames)) ? 0 : gfn_x(t->arch.gfn[i])) + (i < (t)->max_grant_frames))? 0 : gfn_x((t)->arch.gfn[i])) #define gnttab_need_iommu_mapping(d) \ (is_domain_direct_mapped(d) && need_iommu(d)) diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h index 1b93c5720d..f1aa9b3209 100644 --- a/xen/include/asm-x86/grant_table.h +++ b/xen/include/asm-x86/grant_table.h @@ -12,7 +12,7 @@ #include <asm/hvm/grant_table.h> #include <asm/pv/grant_table.h> -#define INITIAL_NR_GRANT_FRAMES 4 +#define INITIAL_NR_GRANT_FRAMES 4U struct grant_table_arch { }; @@ -39,6 +39,11 @@ static inline int replace_grant_host_mapping(uint64_t addr, unsigned long frame, return replace_grant_pv_mapping(addr, frame, new_addr, flags); } +static inline unsigned int gnttab_dom0_frames(unsigned int max_frames) +{ + return max_frames; +} + #define gnttab_init_arch(gt) 0 #define gnttab_destroy_arch(gt) do {} while ( 0 ) #define gnttab_set_frame_gfn(gt, idx, gfn) do {} while ( 0 ) diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h index d2bd2416c4..2b194c3526 100644 --- a/xen/include/xen/grant_table.h +++ b/xen/include/xen/grant_table.h @@ -31,9 +31,6 @@ struct grant_table; -/* The maximum size of a grant table. */ -extern unsigned int max_grant_frames; - /* Create/destroy per-domain grant table context. */ int grant_table_create( struct domain *d); -- 2.12.3 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |