From patchwork Tue Sep 19 09:58:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 9958611 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DA73F6038F for ; Tue, 19 Sep 2017 10:01:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E8C95201A4 for ; Tue, 19 Sep 2017 10:01:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DD85528991; Tue, 19 Sep 2017 10:01:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1BF20201A4 for ; Tue, 19 Sep 2017 10:01:40 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1duFJ4-0007xq-RE; Tue, 19 Sep 2017 09:59:06 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1duFJ3-0007sU-4E for xen-devel@lists.xenproject.org; Tue, 19 Sep 2017 09:59:05 +0000 Received: from [193.109.254.147] by server-11.bemta-6.messagelabs.com id EC/F8-03616-86AE0C95; Tue, 19 Sep 2017 09:59:04 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrCLMWRWlGSWpSXmKPExsVyuP0Ov276qwO RBu1b9S2+b5nM5MDocfjDFZYAxijWzLyk/IoE1oxN9zewFbwrr7j/+BVjA+Pz0C5GTg4JASOJ txP/MXUxcnEICSxilLhy7jsTSIJNQFViw/VTrCC2iICSxL1Vk8GKmAV+Mkp8m7iQrYuRg0NYw EXibk85SA0LUP2pa5/A6nkFTCXWb1jCDrFAXqLjwGQWEJsTKD53ziSwGiEBE4mNj/cwTWDkXs DIsIpRozi1qCy1SNfYUC+pKDM9oyQ3MTNH19DATC83tbg4MT01JzGpWC85P3cTI9C/DECwg7F pUeAhRkkOJiVRXtHI/ZFCfEn5KZUZicUZ8UWlOanFhxg1ODgE+tasvsAoxZKXn5eqJMG79S9Q nWBRanpqRVpmDjAAYUolOHiURHhngqR5iwsSc4sz0yFSpxiNOY5tuvyHiaPj5t0/TEJgk6TEe aeBlAqAlGaU5sENgkXGJUZZKWFeRqAzhXgKUotyM0tQ5V8xinMwKgnz3gCZwpOZVwK37xXQKU xAp7Ts2ANySkkiQkqqgXHKs/YZTCEc2l6B7L8E32R/qVptEW+23vNcooWs+7lb3WqdN1Uk1re f3nFQTOnSN91fYoseJ7x9OIV7qZG/sPKkb37uEqujzh7xFmtebpcpfrQz8crk7pawn0a/fJIb Zt3xKrI+Wm245+5OtpQzUXc1zT6dfmiVcfnF9vmhyvGG5ityJNat/6rEUpyRaKjFXFScCAAQZ tHlhwIAAA== X-Env-Sender: jgross@suse.com X-Msg-Ref: server-5.tower-27.messagelabs.com!1505815143!111972040!1 X-Originating-IP: [195.135.220.15] X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 22382 invoked from network); 19 Sep 2017 09:59:03 -0000 Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by server-5.tower-27.messagelabs.com with DHE-RSA-CAMELLIA256-SHA encrypted SMTP; 19 Sep 2017 09:59:03 -0000 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 59DBB5CB7F; Tue, 19 Sep 2017 09:59:03 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Tue, 19 Sep 2017 11:58:50 +0200 Message-Id: <20170919095852.15785-15-jgross@suse.com> X-Mailer: git-send-email 2.12.3 In-Reply-To: <20170919095852.15785-1-jgross@suse.com> References: <20170919095852.15785-1-jgross@suse.com> Cc: Juergen Gross , sstabellini@kernel.org, wei.liu2@citrix.com, George.Dunlap@eu.citrix.com, andrew.cooper3@citrix.com, ian.jackson@eu.citrix.com, tim@xen.org, julien.grall@arm.com, jbeulich@suse.com, dgdegra@tycho.nsa.gov Subject: [Xen-devel] [PATCH v7 14/16] xen: make grant resource limits per domain X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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(). Signed-off-by: Juergen Gross Reviewed-by: Paul Durrant --- V6: - several changes due to new patch order V3: - correct error message (Paul Durrant) --- xen/common/compat/grant_table.c | 31 +++------- xen/common/grant_table.c | 121 ++++++++++++++++++++++++-------------- xen/include/asm-arm/grant_table.h | 6 +- 3 files changed, 88 insertions(+), 70 deletions(-) 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 26f9a32656..a0d8f32869 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) */ @@ -290,8 +293,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) @@ -528,7 +531,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 ) @@ -1667,23 +1670,26 @@ grant_table_init(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; @@ -1718,8 +1724,9 @@ 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_t(unsigned int, 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", @@ -1777,13 +1784,15 @@ active_alloc_failed: 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; + long ret = 0; if ( count != 1 ) return -EINVAL; @@ -1791,15 +1800,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; @@ -1819,6 +1819,21 @@ 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 ( unlikely(limit_max < gt->max_grant_frames) ) + { + gdprintk(XENLOG_WARNING, "max_grant_frames is too large (%u,%u)\n", + gt->max_grant_frames, limit_max); + ret = -EINVAL; + goto unlock; + } + if ( gt->gt_version == 0 ) gt->gt_version = 1; @@ -1829,7 +1844,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; } @@ -1852,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 @@ -1864,6 +1879,7 @@ gnttab_query_size( { struct gnttab_query_size op; struct domain *d; + struct grant_table *gt; if ( count != 1 ) return -EINVAL; @@ -1884,13 +1900,15 @@ gnttab_query_size( goto out; } - grant_read_lock(d->grant_table); + gt = d->grant_table; - op.nr_frames = nr_grant_frames(d->grant_table); - op.max_nr_frames = max_grant_frames; + grant_read_lock(gt); + + 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 ) @@ -2965,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) + 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; @@ -3012,6 +3030,15 @@ gnttab_get_status_frames(XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_t) uop, goto unlock; } + if ( unlikely(limit_max < grant_to_status_frames(gt->max_grant_frames)) ) + { + gdprintk(XENLOG_WARNING, + "grant_to_status_frames(max_grant_frames) is too large (%u,%u)\n", + grant_to_status_frames(gt->max_grant_frames), limit_max); + ret = -EINVAL; + goto unlock; + } + for ( i = 0; i < op.nr_frames; i++ ) { gmfn = gnttab_status_gmfn(d, gt, i); @@ -3024,10 +3051,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 @@ -3320,7 +3347,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, ~0); ASSERT(rc <= 0); break; @@ -3369,7 +3396,7 @@ 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, ~0); break; case GNTTABOP_get_version: @@ -3442,6 +3469,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; @@ -3648,6 +3677,8 @@ 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 ) + return -EINVAL; if ( !gt ) return -ENOENT; @@ -3655,7 +3686,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(gt); + } grant_write_unlock(gt); @@ -3731,7 +3766,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) ) @@ -3759,6 +3794,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; @@ -3786,12 +3827,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", @@ -3803,8 +3839,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) diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h index 0870b5b782..9a60e4e614 100644 --- a/xen/include/asm-arm/grant_table.h +++ b/xen/include/asm-arm/grant_table.h @@ -26,8 +26,8 @@ static inline int replace_grant_supported(void) return 1; } -#define gnttab_init_arch(gt) \ - ( ((gt)->arch.gfn = xzalloc_array(gfn_t, max_grant_frames)) == 0 \ +#define gnttab_init_arch(gt) \ + ( ((gt)->arch.gfn = xzalloc_array(gfn_t, (gt)->max_grant_frames)) == 0 \ ? 0 : -ENOMEM ) #define gnttab_destroy_arch(gt) \ @@ -49,7 +49,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))