From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
xen-devel@lists.xensource.com
Cc: julien.grall@citrix.com, Ian.Campbell@citrix.com
Subject: Re: [PATCH v2 3/4] xen/arm: introduce GNTTABOP_cache_flush
Date: Fri, 3 Oct 2014 16:16:49 +0100 [thread overview]
Message-ID: <542EBDE1.2000702@citrix.com> (raw)
In-Reply-To: <1412347845-27755-3-git-send-email-stefano.stabellini@eu.citrix.com>
On 03/10/14 15:50, Stefano Stabellini wrote:
> Introduce a new hypercall to perform cache maintenance operation on
> behalf of the guest. The argument is a machine address and a size. The
> implementation checks that the memory range is owned by the guest or the
> guest has been granted access to it by another domain.
>
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
>
> ---
>
> Changes in v2:
> - do not check for mfn_to_page errors;
> - take a reference to the page;
> - replace printk with gdprintk;
> - split long line;
> - remove out label;
> - move rcu_lock_current_domain down before the loop.
> - move the hypercall to GNTTABOP;
> - take a spin_lock before calling grant_map_exists.
> ---
> xen/common/grant_table.c | 73 ++++++++++++++++++++++++++++++++++++++
> xen/include/public/grant_table.h | 19 ++++++++++
> 2 files changed, 92 insertions(+)
>
> diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
> index 7a6399b..d5bb4f7 100644
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -2641,6 +2641,79 @@ do_grant_table_op(
> }
> break;
> }
> + case GNTTABOP_cache_flush:
> + {
> + struct gnttab_cache_flush cflush;
> + struct domain *d, *owner;
> + struct page_info *page;
> + uint64_t mfn;
> + void *v;
> +
> + /* currently unimplemented */
> + if ( count != 1 )
> + return -ENOSYS;
ENOTSUPP (and elsewhere).
> +
> + if ( copy_from_guest(&cflush, uop, 1) )
> + return -EFAULT;
> +
> + if ( cflush.offset + cflush.size > PAGE_SIZE )
> + return -EINVAL;
This logic can still be fooled by cleverly crafted overflows, resulting
in garbage being used later, which I am guessing will be a bad thing.
You need to bound check them individually before bounds-checking the
addition of the two.
> +
> + if ( cflush.size == 0 || cflush.op == 0 )
> + return 0;
> +
> + if ( cflush.op & ~(GNTTAB_CACHE_INVAL|GNTTAB_CACHE_CLEAN) )
> + return -EINVAL;
> +
> + /* currently unimplemented */
> + if ( cflush.a.ref != 0 )
> + return -ENOSYS;
> +
> + d = rcu_lock_current_domain();
> + if ( d == NULL )
> + return -ESRCH;
rcu_lock_current_domain() cannot possibly fail.
> +
> + mfn = cflush.a.dev_bus_addr >> PAGE_SHIFT;
> +
> + if ( !mfn_valid(mfn) )
> + {
> + gdprintk(XENLOG_G_ERR, "mfn=%llx is not valid\n", mfn);
PRIx64, as mfn is uint64_t (and elsewhere).
> + rcu_unlock_domain(d);
> + return -EINVAL;
> + }
> +
> + page = mfn_to_page(mfn);
> + owner = page_get_owner_and_reference(page);
> + if ( !owner )
> + {
> + rcu_unlock_domain(d);
> + return -EFAULT;
EPERM seems better, as it is an ownership check on an existing mfn.
> + }
> +
> + spin_lock(&owner->grant_table->lock);
Is this safe without taking the paging lock and doing a dying check on
'owner' ?
> +
> + if ( !grant_map_exists(d, owner->grant_table, mfn) )
> + {
> + spin_unlock(&owner->grant_table->lock);
> + put_page(page);
> + rcu_unlock_domain(d);
These two can be reordered to reduce the length of time the rcu lock is
held.
> + gdprintk(XENLOG_G_ERR, "mfn %llx hasn't been granted by %d to %d\n",
> + mfn, owner->domain_id, d->domain_id);
"hasn't been granted by d%d to d%d", to indicate that the numbers are
domids.
> + return -EINVAL;
> + }
> +
> + v = map_domain_page(mfn);
> + v += cflush.offset;
> +
> + if ( cflush.op & GNTTAB_CACHE_INVAL )
> + invalidate_xen_dcache_va_range(v, cflush.size);
> + if ( cflush.op & GNTTAB_CACHE_CLEAN )
> + clean_xen_dcache_va_range(v, cflush.size);
> +
> + unmap_domain_page(v);
> + spin_unlock(&owner->grant_table->lock);
These two can be reordered to reduce the length of time the grant lock
is held. (especially as it is a remote domains grant lock)
~Andrew
> + put_page(page);
> + }
> default:
> rc = -ENOSYS;
> break;
> diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h
> index b8a3d6c..1833bba 100644
> --- a/xen/include/public/grant_table.h
> +++ b/xen/include/public/grant_table.h
> @@ -309,6 +309,7 @@ typedef uint16_t grant_status_t;
> #define GNTTABOP_get_status_frames 9
> #define GNTTABOP_get_version 10
> #define GNTTABOP_swap_grant_ref 11
> +#define GNTTABOP_cache_flush 12
> #endif /* __XEN_INTERFACE_VERSION__ */
> /* ` } */
>
> @@ -574,6 +575,24 @@ struct gnttab_swap_grant_ref {
> typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
> DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
>
> +/*
> + * Issue one or more cache maintenance operations on a portion of a
> + * page granted to the calling domain by a foreign domain.
> + */
> +struct gnttab_cache_flush {
> + union {
> + uint64_t dev_bus_addr;
> + grant_ref_t ref;
> + } a;
> + uint32_t offset; /* offset from start of grant */
> + uint32_t size; /* size within the grant */
> +#define GNTTAB_CACHE_CLEAN (1<<0)
> +#define GNTTAB_CACHE_INVAL (1<<1)
> + uint32_t op;
> +};
> +typedef struct gnttab_cache_flush gnttab_cache_flush_t;
> +DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
> +
> #endif /* __XEN_INTERFACE_VERSION__ */
>
> /*
next prev parent reply other threads:[~2014-10-03 15:16 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-03 14:47 [PATCH v2 0/4] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
2014-10-03 14:50 ` [PATCH v2 1/4] xen/arm: introduce invalidate_xen_dcache_va_range Stefano Stabellini
2014-10-03 14:50 ` [PATCH v2 2/4] xen: introduce grant_map_exists Stefano Stabellini
2014-10-03 15:02 ` Andrew Cooper
2014-10-03 16:20 ` Stefano Stabellini
2014-10-06 8:22 ` Jan Beulich
2014-10-06 9:37 ` Stefano Stabellini
2014-10-06 10:20 ` Jan Beulich
2014-10-06 13:08 ` Stefano Stabellini
2014-10-06 13:39 ` Jan Beulich
2014-10-06 13:46 ` Stefano Stabellini
2014-10-06 14:01 ` Jan Beulich
2014-10-06 14:34 ` Stefano Stabellini
2014-10-06 14:56 ` Jan Beulich
2014-10-06 14:57 ` Stefano Stabellini
2014-10-06 15:09 ` Jan Beulich
2014-10-06 9:41 ` Stefano Stabellini
2014-10-06 10:17 ` Jan Beulich
2014-10-03 14:50 ` [PATCH v2 3/4] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
2014-10-03 14:53 ` Stefano Stabellini
2014-10-03 15:16 ` Andrew Cooper [this message]
2014-10-03 16:33 ` Stefano Stabellini
2014-10-03 16:37 ` Andrew Cooper
2014-10-03 16:37 ` Ian Campbell
2014-10-06 8:49 ` Jan Beulich
2014-10-06 9:00 ` Jan Beulich
2014-10-06 15:21 ` David Vrabel
2014-10-08 11:54 ` Stefano Stabellini
2014-10-08 12:06 ` David Vrabel
2014-10-08 12:52 ` Stefano Stabellini
2014-10-08 13:01 ` Ian Campbell
2014-10-08 12:17 ` Ian Campbell
2014-10-08 12:45 ` David Vrabel
2014-10-03 14:50 ` [PATCH v2 4/4] Revert "xen/arm: introduce XENFEAT_grant_map_identity" Stefano Stabellini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=542EBDE1.2000702@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=Ian.Campbell@citrix.com \
--cc=julien.grall@citrix.com \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.