[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v11 1/3] 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 and correct the default gnttab_max_maptrack_frames uses. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> [non-ARM parts] --- V11: - add comment in include/asm-arm/grant_table.h (Julien Grall) V10: - lower INITIAL_NR_GRANT_FRAMES value to 1 - removed no longer needed variables (Jan Beulich) - stream lined messages (Jan Beulich) - corrected setting of gnttab_size on ARM 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 | 156 +++++++++++++++++++++--------------- xen/include/asm-arm/grant_table.h | 20 ++++- xen/include/asm-x86/grant_table.h | 7 +- xen/include/xen/grant_table.h | 5 +- 7 files changed, 138 insertions(+), 112 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..3723dc3f78 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_frames() << 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 71706f5cba..7c328b0a62 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 ) @@ -1673,7 +1671,7 @@ gnttab_grow_table(struct domain *d, unsigned int req_nr_frames) if ( req_nr_frames < INITIAL_NR_GRANT_FRAMES ) req_nr_frames = INITIAL_NR_GRANT_FRAMES; - 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", @@ -1730,7 +1728,8 @@ active_alloc_failed: } static int -grant_table_init(struct domain *d, struct grant_table *gt) +grant_table_init(struct domain *d, struct grant_table *gt, + unsigned int grant_frames, unsigned int maptrack_frames) { int ret; @@ -1742,25 +1741,31 @@ grant_table_init(struct domain *d, struct grant_table *gt) goto unlock; } + gt->max_grant_frames = grant_frames; + gt->max_maptrack_frames = maptrack_frames; + /* 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 no_mem; /* Tracking of mapped foreign frames table */ - gt->maptrack = vzalloc(max_maptrack_frames * sizeof(*gt->maptrack)); - if ( gt->maptrack == NULL ) - goto no_mem; + if ( gt->max_maptrack_frames ) + { + gt->maptrack = vzalloc(gt->max_maptrack_frames * sizeof(*gt->maptrack)); + if ( gt->maptrack == NULL ) + goto no_mem; + } /* 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 no_mem; /* 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; @@ -1793,7 +1798,8 @@ 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; @@ -1807,15 +1813,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; @@ -1835,6 +1832,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%d 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%d 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; @@ -1844,8 +1856,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%d 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; } @@ -1880,6 +1893,7 @@ gnttab_query_size( { struct gnttab_query_size op; struct domain *d; + struct grant_table *gt; if ( count != 1 ) return -EINVAL; @@ -1900,13 +1914,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 ) @@ -2981,7 +2997,7 @@ 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; @@ -3021,9 +3037,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, "Requested addresses of d%d for %u grant " + "status frames, but has only %u.\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%d 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; } @@ -3336,7 +3362,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; @@ -3385,7 +3411,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: @@ -3465,7 +3492,7 @@ grant_table_create( if ( d->domain_id == 0 ) { - ret = grant_table_init(d, t); + ret = grant_table_init(d, t, gnttab_dom0_frames(), max_maptrack_frames); } return ret; @@ -3666,11 +3693,15 @@ int grant_table_set_limits(struct domain *d, unsigned int grant_frames, { struct grant_table *gt = d->grant_table; + if ( grant_frames < INITIAL_NR_GRANT_FRAMES || + grant_frames > max_grant_frames || + maptrack_frames > max_maptrack_frames ) + return -EINVAL; if ( !gt ) return -ENOENT; /* Set limits. */ - return grant_table_init(d, gt); + return grant_table_init(d, gt, grant_frames, maptrack_frames); } #ifdef CONFIG_HAS_MEM_SHARING @@ -3742,7 +3773,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) ) @@ -3770,6 +3801,12 @@ static void gnttab_usage_print(struct domain *rd) grant_read_lock(gt); + printk("grant-table for remote d%d (v%u)\n" + " %u frames (%u max), %u maptrack frames (%u 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; @@ -3797,12 +3834,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", @@ -3814,8 +3846,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) @@ -3829,20 +3860,17 @@ 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; } __initcall(gnttab_usage_init); +unsigned int __init gnttab_dom0_frames(void) +{ + return min(max_grant_frames, gnttab_dom0_max()); +} + /* * Local variables: * mode: C diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h index 30db2d1616..0dfdc5577f 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 1U struct grant_table_arch { gfn_t *gfn; @@ -26,9 +28,21 @@ static inline int replace_grant_supported(void) return 1; } +/* + * The region used by Xen on the memory will never be mapped in DOM0 + * memory layout. Therefore it can be used for the grant table. + * + * Only use the text section as it's always present and will contain + * enough space for a large grant table + */ +static inline unsigned int gnttab_dom0_max(void) +{ + return PFN_DOWN(_etext - _stext); +} + #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 +66,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..d9157e4417 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 1U 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_max(void) +{ + return UINT_MAX; +} + #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..b3a95fda58 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); @@ -59,4 +56,6 @@ int mem_sharing_gref_to_gfn(struct grant_table *gt, grant_ref_t ref, int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn); +unsigned int gnttab_dom0_frames(void); + #endif /* __XEN_GRANT_TABLE_H__ */ -- 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 |