* [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush
@ 2014-10-22 16:38 Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 1/8] xen: introduce gnttab_max_frames and gnttab_max_maptrack_frames command line options Stefano Stabellini
` (7 more replies)
0 siblings, 8 replies; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:38 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, Ian Campbell, JBeulich, Stefano Stabellini
Hi all,
this patch series introduces a new hypercall to perform cache
maintenance operations on behalf of the guest. It is useful for dom0 to
be able to cache flush pages involved in a dma operation with
non-coherent devices.
It also removes XENFEAT_grant_map_identity as the feature is no longer
necessary: it was used to achieve the same goal but the guest can now
use the hypercall instead. Keeping the flag would also have a
significant performance impact as a new p2m mapping gets created and
then destroyed for every grant that is mapped and unmapped in dom0.
Changes in v11:
- make ref and max_iter unsigned int;
- remove useless initializations of ret to 0;
- check that cflush->op is valid;
- BUG() later on if cflush->op is invalid;
- fix blank lines;
- remove comment.
Changes on v10:
- fix coding style for comments;
- move BUILD_BUG_ON closer to where it matters;
- add a comment on dev_bus_addr;
- remove comment on max GNTTABOP;
- break long lines;
- remove ref_count local variable;
- use unsigned int* instead of grant_ref_t* as arguments.
Changes in v9:
- fix coding style for comments;
- other style fixes;
- fix whitespace indentation;
- remove useless ASSERT;
- add a comment on ARM callers assuming that these functions cannot
fail;
- grant_map_exists: calculate max iteration before the loop;
- do_grant_table_op: avoid shifts, use masks instead;
- set GNTTABOP_CONTINUATION_ARG_SHIFT to 12;
- remove MAX_GRANT_ENTRIES_ITER_SHIFT, use
GNTTABOP_CONTINUATION_ARG_SHIFT;
- move GNTTABOP_CMD_MASK and GNTTABOP_CONTINUATION_ARG_SHIFT to
grant_table.c.
Changes in v8:
- remove unused #include;
- set max_nr_grant_frames as __initdata;
- set max_grant_frames and max_maptrack_frames as __read_mostly;
- respent coding style for comments;
- remove MAX_MAPTRACK_TO_GRANTS_RATIO;
- avoid security issues, use two separate opaque variables to store the
input argument and the output argument;
- fix return values of grant_map_exists;
- rename CMD_MASK to GNTTABOP_CMD_MASK;
- rename OPAQUE_CONTINUATION_ARG_SHIFT to
GNTTABOP_CONTINUATION_ARG_SHIFT;
- save in the opaque argument the shifted ref_count;
- set GNTTABOP_CONTINUATION_ARG_SHIFT to 20 and
MAX_GRANT_ENTRIES_ITER_SHIFT to 12, to cover the full grant_ref_t value
range;
- move GNTTABOP_CONTINUATION_ARG_SHIFT and GNTTABOP_CMD_MASK to
include/xen/grant_table.h;
- cmd &= GNTTABOP_CMD_MASK in the compat wrapper.
Changes in v7:
- remove 0 initializers;
- make max_nr_grant_frames static;
- remove preprocessors check on max_nr_grant_frames;
- remove double black line;
- introduce DEFAULT_MAX_MAPTRACK_FRAMES;
- no long lines;
- set the new variables independently if the old one is passed as
argument;
- return the called function's return value from clean_dcache_va_range;
- remove warning message;
- prefix second line of the warning with XENLOG_WARNING;
- do not lower DEFAULT_MAX_NR_GRANT_FRAMES;
- no long lines;
- interrupt loops in grant_map_exists with more than 2048 iterations,
create an hypercall continuation if necessary.
Changes in v6:
- change ordering of new options in xen-command-line.markdown;
- initialize all options to 0, then set the defaults on an initcall
depending on what options are used;
- do not return int from flush_page_to_ram;
- set DEFAULT_MAX_NR_GRANT_FRAMES to 10;
- warn if max_grant_frames > 10.
Changes in v5:
- /max_nr_maptrack_frames/max_maptrack_frames/g;
- deprecate gnttab_max_nr_frames;
- introduce gnttab_max_frames;
- rename the max_nr_grant_frames variable to max_grant_frames;
- return int from flush_page_to_ram and *_dcache_va_range;
- return int from invalidate_dcache_va_range;
- make order an unsigned int;
- add a comment on sub-page granularity support;
- cache operations return error;
- move the functions to xen/include/asm-x86/flushtlb.h;
- make mfn unsigned long;
- remove unhelpful error message;
- handle errors returned by cache maintenance functions.
Changes in v4:
- add patch "xen: introduce gnttab_max_nr_maptrack_frames command line option";
- remove patch "introduce two different max_nr_dom0/domU_grant_frames
parameters";
- rename *_xen_dcache_* operations to *_dcache_*;
- implement the x86 cache maintenance functions using flush_area_local;
- ASSERT(spin_is_locked);
- return instead of break in grant_map_exists;
- pass a pointer to __gnttab_cache_flush;
- code style;
- unsigned int iterator in gnttab_cache_flush;
- return ret instead -ret;
- cflush.offset >= PAGE_SIZE return -EINVAL;
- revert "xen: introduce arch_grant_(un)map_page_identity"
Changes in v3:
- introduce two different max_nr_dom0/domU_grant_frames parameters;
- x86: introduce more cache maintenance operations;
- reduce the time the grant_table lock is held;
- fix warning message;
- s/EFAULT/EPERM;
- s/llx/PRIx64;
- check offset and size independetly before checking their sum;
- rcu_lock_current_domain cannot fail;
- s/ENOSYS/EOPNOTSUPP;
- use clean_and_invalidate_xen_dcache_va_range to do both operations at
once;
- fold grant_map_exists in this patch;
- support "count" argument;
- make correspondent changes to compat/grant_table.c;
- introduce GNTTAB_CACHE_SOURCE_GREF to select the type of input in the
union;
- rename size field to length;
- make length and offset uint16_t;
- only take spin_lock if d != owner.
Changes in v2:
- make grant_map_exists static;
- remove the spin_lock in grant_map_exists;
- move the hypercall to GNTTABOP;
- do not check for mfn_to_page errors in GNTTABOP_cache_flush;
- take a reference to the page in GNTTABOP_cache_flush;
- replace printk with gdprintk in GNTTABOP_cache_flush;
- split long line in GNTTABOP_cache_flush;
- remove out label in GNTTABOP_cache_flush;
- move rcu_lock_current_domain down before the loop in
GNTTABOP_cache_flush;
- take a spin_lock before calling grant_map_exists in
GNTTABOP_cache_flush.
Stefano Stabellini (8):
xen: introduce gnttab_max_frames and gnttab_max_maptrack_frames command line options
xen/arm: rename *_xen_dcache_* operations to *_dcache_*
xen/arm: return int from *_dcache_va_range
xen/arm: introduce invalidate_dcache_va_range
xen/x86: introduce more cache maintenance operations
xen/arm: introduce GNTTABOP_cache_flush
Revert "xen/arm: introduce XENFEAT_grant_map_identity"
Revert "xen: introduce arch_grant_(un)map_page_identity"
docs/misc/xen-command-line.markdown | 17 ++-
xen/arch/arm/domain.c | 2 +-
xen/arch/arm/guestcopy.c | 2 +-
xen/arch/arm/kernel.c | 2 +-
xen/arch/arm/mm.c | 26 ++--
xen/arch/arm/p2m.c | 30 +---
xen/arch/arm/smpboot.c | 2 +-
xen/arch/x86/mm.c | 2 +-
xen/common/compat/grant_table.c | 27 ++--
xen/common/grant_table.c | 265 ++++++++++++++++++++++++++++-------
xen/common/kernel.c | 2 -
xen/drivers/passthrough/arm/smmu.c | 42 ++++++
xen/include/asm-arm/arm32/page.h | 7 +-
xen/include/asm-arm/arm64/page.h | 7 +-
xen/include/asm-arm/grant_table.h | 5 +-
xen/include/asm-arm/p2m.h | 4 -
xen/include/asm-arm/page.h | 56 ++++++--
xen/include/asm-x86/flushtlb.h | 15 ++
xen/include/asm-x86/p2m.h | 4 -
xen/include/asm-x86/page.h | 3 -
xen/include/public/features.h | 4 +-
xen/include/public/grant_table.h | 20 +++
xen/include/xen/grant_table.h | 4 +-
xen/include/xlat.lst | 1 +
24 files changed, 413 insertions(+), 136 deletions(-)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v11 1/8] xen: introduce gnttab_max_frames and gnttab_max_maptrack_frames command line options
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
@ 2014-10-22 16:40 ` Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 2/8] xen/arm: rename *_xen_dcache_* operations to *_dcache_* Stefano Stabellini
` (6 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:40 UTC (permalink / raw)
To: xen-devel; +Cc: julien.grall, Ian.Campbell, JBeulich, Stefano Stabellini
Introduce gnttab_max_maptrack_frames: a new Xen command line option to
specify the max number of maptrack frames per domain.
Deprecate the old gnttab_max_nr_frames and introduce gnttab_max_frames
instead, that doesn't affect the maptrack. Keep gnttab_max_nr_frames for
compatibility.
Rename internally max_nr_grant_frames to max_grant_frames to avoid
confusions.
Introduce DEFAULT_MAX_MAPTRACK_FRAMES, that is completely independent
from max_nr_grant_frames.
Remove MAX_MAPTRACK_TO_GRANTS_RATIO that is now only used in one place
for compatibility.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in v10:
- fix coding style for comments;
- move BUILD_BUG_ON closer to where it matters.
Changes in v9:
- fix coding style for comments;
- other style fixes.
Changes in v8:
- remove unused #include;
- set max_nr_grant_frames as __initdata;
- set max_grant_frames and max_maptrack_frames as __read_mostly;
- fix coding style for comments;
- remove MAX_MAPTRACK_TO_GRANTS_RATIO.
Changes in v7:
- remove 0 initializers;
- make max_nr_grant_frames static;
- remove preprocessors check on max_nr_grant_frames;
- remove double black line;
- introduce DEFAULT_MAX_MAPTRACK_FRAMES;
- no long lines;
- set the new variables independently if the old one is passed as
argument.
Changes in v6:
- change ordering of options in xen-command-line.markdown;
- initialize all options to 0, then set the defaults on an initcall
depending on what options are used.
Changes in v5:
- /max_nr_maptrack_frames/max_maptrack_frames/g;
- deprecate gnttab_max_nr_frames;
- introduce gnttab_max_frames;
- rename the max_nr_grant_frames variable to max_grant_frames.
---
docs/misc/xen-command-line.markdown | 17 +++++++++-
xen/arch/arm/domain.c | 2 +-
xen/arch/arm/mm.c | 2 +-
xen/arch/x86/mm.c | 2 +-
xen/common/compat/grant_table.c | 12 +++----
xen/common/grant_table.c | 62 ++++++++++++++++++++++++-----------
xen/include/asm-arm/grant_table.h | 2 +-
xen/include/xen/grant_table.h | 4 +--
8 files changed, 70 insertions(+), 33 deletions(-)
diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown
index 28bbaaf..00416af 100644
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -608,11 +608,26 @@ does not provide VM\_ENTRY\_LOAD\_GUEST\_PAT.
Specify the serial parameters for the GDB stub.
-### gnttab\_max\_nr\_frames
+### gnttab\_max\_frames
> `= <integer>`
Specify the maximum number of frames per grant table operation.
+### gnttab\_max\_maptrack\_frames
+> `= <integer>`
+
+Specify the maximum number of maptrack frames domain.
+The default value is 8 times gnttab_max_frames.
+
+### gnttab\_max\_nr\_frames
+> `= <integer>`
+
+*Deprecated*
+Use gnttab\_max\_frames and gnttab\_max\_maptrack\_frames instead.
+
+Specify the maximum number of frames per grant table operation and the
+maximum number of maptrack frames domain.
+
### guest\_loglvl
> `= <level>[/<rate-limited level>]` where level is `none | error | warning | info | debug | all`
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 2b53931..57f09c3 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -409,7 +409,7 @@ struct domain *alloc_domain_struct(void)
return NULL;
clear_page(d);
- d->arch.grant_table_gpfn = xzalloc_array(xen_pfn_t, max_nr_grant_frames);
+ d->arch.grant_table_gpfn = xzalloc_array(xen_pfn_t, max_grant_frames);
return d;
}
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 97e5bc39..dd70d81 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -1054,7 +1054,7 @@ int xenmem_add_to_physmap_one(
else
{
if ( (idx >= nr_grant_frames(d->grant_table)) &&
- (idx < max_nr_grant_frames) )
+ (idx < max_grant_frames) )
gnttab_grow_table(d, idx + 1);
if ( idx < nr_grant_frames(d->grant_table) )
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 6cd7f45..edd1923 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -4564,7 +4564,7 @@ int xenmem_add_to_physmap_one(
else
{
if ( (idx >= nr_grant_frames(d->grant_table)) &&
- (idx < max_nr_grant_frames) )
+ (idx < max_grant_frames) )
gnttab_grow_table(d, idx + 1);
if ( idx < nr_grant_frames(d->grant_table) )
diff --git a/xen/common/compat/grant_table.c b/xen/common/compat/grant_table.c
index 7ebbbc1..2dc1e44 100644
--- a/xen/common/compat/grant_table.c
+++ b/xen/common/compat/grant_table.c
@@ -146,11 +146,11 @@ 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_nr_grant_frames )
+ if ( max_frame_list_size_in_page < max_grant_frames )
{
gdprintk(XENLOG_WARNING,
- "max_nr_grant_frames is too large (%u,%u)\n",
- max_nr_grant_frames, max_frame_list_size_in_page);
+ "max_grant_frames is too large (%u,%u)\n",
+ max_grant_frames, max_frame_list_size_in_page);
rc = -EINVAL;
}
else
@@ -284,11 +284,11 @@ int compat_grant_table_op(unsigned int cmd,
break;
}
if ( max_frame_list_size_in_pages <
- grant_to_status_frames(max_nr_grant_frames) )
+ grant_to_status_frames(max_grant_frames) )
{
gdprintk(XENLOG_WARNING,
- "grant_to_status_frames(max_nr_grant_frames) is too large (%u,%u)\n",
- grant_to_status_frames(max_nr_grant_frames),
+ "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;
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 23266c3..f9a9b44 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -40,16 +40,27 @@
#include <xsm/xsm.h>
#include <asm/flushtlb.h>
-#ifndef max_nr_grant_frames
-unsigned int max_nr_grant_frames = DEFAULT_MAX_NR_GRANT_FRAMES;
+/*
+ * This option is deprecated, use gnttab_max_frames and
+ * gnttab_max_maptrack_frames instead.
+ */
+static unsigned int __initdata max_nr_grant_frames;
integer_param("gnttab_max_nr_frames", max_nr_grant_frames);
-#endif
+
+unsigned int __read_mostly max_grant_frames;
+integer_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 MAX_MAPTRACK_TO_GRANTS_RATIO 8
+#define DEFAULT_MAX_MAPTRACK_FRAMES 256
+
+static unsigned int __read_mostly max_maptrack_frames;
+integer_param("gnttab_max_maptrack_frames", max_maptrack_frames);
/*
* The first two members of a grant entry are updated as a combined pair.
@@ -102,11 +113,6 @@ nr_maptrack_frames(struct grant_table *t)
return t->maptrack_limit / MAPTRACK_PER_PAGE;
}
-static unsigned inline int max_nr_maptrack_frames(void)
-{
- return (max_nr_grant_frames * MAX_MAPTRACK_TO_GRANTS_RATIO);
-}
-
#define MAPTRACK_TAIL (~0u)
#define SHGNT_PER_PAGE_V1 (PAGE_SIZE / sizeof(grant_entry_v1_t))
@@ -164,7 +170,7 @@ num_act_frames_from_sha_frames(const unsigned int num)
}
#define max_nr_active_grant_frames \
- num_act_frames_from_sha_frames(max_nr_grant_frames)
+ num_act_frames_from_sha_frames(max_grant_frames)
static inline unsigned int
nr_active_grant_frames(struct grant_table *gt)
@@ -271,7 +277,7 @@ get_maptrack_handle(
while ( unlikely((handle = __get_maptrack_handle(lgt)) == -1) )
{
nr_frames = nr_maptrack_frames(lgt);
- if ( nr_frames >= max_nr_maptrack_frames() )
+ if ( nr_frames >= max_maptrack_frames )
break;
new_mt = alloc_xenheap_page();
@@ -1265,7 +1271,7 @@ gnttab_grow_table(struct domain *d, unsigned int req_nr_frames)
struct grant_table *gt = d->grant_table;
unsigned int i;
- ASSERT(req_nr_frames <= max_nr_grant_frames);
+ ASSERT(req_nr_frames <= max_grant_frames);
gdprintk(XENLOG_INFO,
"Expanding dom (%d) grant table from (%d) to (%d) frames.\n",
@@ -1338,11 +1344,11 @@ gnttab_setup_table(
return -EFAULT;
}
- if ( unlikely(op.nr_frames > max_nr_grant_frames) )
+ if ( unlikely(op.nr_frames > max_grant_frames) )
{
gdprintk(XENLOG_INFO, "Xen only supports up to %d grant-table frames"
" per domain.\n",
- max_nr_grant_frames);
+ max_grant_frames);
op.status = GNTST_general_error;
goto out1;
}
@@ -1377,7 +1383,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_nr_grant_frames);
+ op.nr_frames, nr_grant_frames(gt), max_grant_frames);
op.status = GNTST_general_error;
goto out3;
}
@@ -1438,7 +1444,7 @@ gnttab_query_size(
spin_lock(&d->grant_table->lock);
op.nr_frames = nr_grant_frames(d->grant_table);
- op.max_nr_frames = max_nr_grant_frames;
+ op.max_nr_frames = max_grant_frames;
op.status = GNTST_okay;
spin_unlock(&d->grant_table->lock);
@@ -2659,7 +2665,7 @@ grant_table_create(
/* Tracking of mapped foreign frames table */
if ( (t->maptrack = xzalloc_array(struct grant_mapping *,
- max_nr_maptrack_frames())) == NULL )
+ max_maptrack_frames)) == NULL )
goto no_mem_2;
if ( (t->maptrack[0] = alloc_xenheap_page()) == NULL )
goto no_mem_3;
@@ -2670,7 +2676,7 @@ grant_table_create(
t->maptrack[0][i - 1].ref = MAPTRACK_TAIL;
/* Shared grant table. */
- if ( (t->shared_raw = xzalloc_array(void *, max_nr_grant_frames)) == NULL )
+ if ( (t->shared_raw = xzalloc_array(void *, max_grant_frames)) == NULL )
goto no_mem_3;
for ( i = 0; i < INITIAL_NR_GRANT_FRAMES; i++ )
{
@@ -2681,7 +2687,7 @@ grant_table_create(
/* Status pages for grant table - for version 2 */
t->status = xzalloc_array(grant_status_t *,
- grant_to_status_frames(max_nr_grant_frames));
+ grant_to_status_frames(max_grant_frames));
if ( t->status == NULL )
goto no_mem_4;
@@ -2930,6 +2936,24 @@ static struct keyhandler gnttab_usage_print_all_keyhandler = {
static int __init gnttab_usage_init(void)
{
+ if ( max_nr_grant_frames )
+ {
+ printk(XENLOG_WARNING
+ "gnttab_max_nr_frames is deprecated, use gnttab_max_frames instead\n");
+ if ( !max_grant_frames )
+ max_grant_frames = max_nr_grant_frames;
+ BUILD_BUG_ON(DEFAULT_MAX_MAPTRACK_FRAMES < DEFAULT_MAX_NR_GRANT_FRAMES);
+ if ( !max_maptrack_frames )
+ max_maptrack_frames = max_nr_grant_frames *
+ (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_keyhandler);
return 0;
}
diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
index 47147ce..e798880 100644
--- a/xen/include/asm-arm/grant_table.h
+++ b/xen/include/asm-arm/grant_table.h
@@ -31,7 +31,7 @@ static inline int replace_grant_supported(void)
#define gnttab_shared_gmfn(d, t, i) \
( ((i >= nr_grant_frames(d->grant_table)) && \
- (i < max_nr_grant_frames)) ? 0 : (d->arch.grant_table_gpfn[i]))
+ (i < max_grant_frames)) ? 0 : (d->arch.grant_table_gpfn[i]))
#define gnttab_need_iommu_mapping(d) (is_domain_direct_mapped(d))
diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
index 5941191..32f5786 100644
--- a/xen/include/xen/grant_table.h
+++ b/xen/include/xen/grant_table.h
@@ -49,10 +49,8 @@
/* Default maximum size of a grant table. [POLICY] */
#define DEFAULT_MAX_NR_GRANT_FRAMES 32
#endif
-#ifndef max_nr_grant_frames /* to allow arch to override */
/* The maximum size of a grant table. */
-extern unsigned int max_nr_grant_frames;
-#endif
+extern unsigned int max_grant_frames;
/*
* Tracks a mapping of another domain's grant reference. Each domain has a
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v11 2/8] xen/arm: rename *_xen_dcache_* operations to *_dcache_*
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 1/8] xen: introduce gnttab_max_frames and gnttab_max_maptrack_frames command line options Stefano Stabellini
@ 2014-10-22 16:40 ` Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 3/8] xen/arm: return int from *_dcache_va_range Stefano Stabellini
` (5 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:40 UTC (permalink / raw)
To: xen-devel; +Cc: julien.grall, Ian.Campbell, JBeulich, Stefano Stabellini
Given that we are in Xen, it is obvious that these are Xen flushes.
Also the correspondent x86 functions are going to be named without
_xen_, so remove it here for consistency.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v9:
- fix whitespace indentation.
---
xen/arch/arm/guestcopy.c | 2 +-
xen/arch/arm/kernel.c | 2 +-
xen/arch/arm/mm.c | 24 ++++++++++++------------
xen/arch/arm/p2m.c | 4 ++--
xen/arch/arm/smpboot.c | 2 +-
xen/include/asm-arm/arm32/page.h | 4 ++--
xen/include/asm-arm/arm64/page.h | 4 ++--
xen/include/asm-arm/page.h | 20 ++++++++++----------
8 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c
index 0173597..7dbaeca 100644
--- a/xen/arch/arm/guestcopy.c
+++ b/xen/arch/arm/guestcopy.c
@@ -27,7 +27,7 @@ static unsigned long raw_copy_to_guest_helper(void *to, const void *from,
p += offset;
memcpy(p, from, size);
if ( flush_dcache )
- clean_xen_dcache_va_range(p, size);
+ clean_dcache_va_range(p, size);
unmap_domain_page(p - offset);
put_page(page);
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index 1b8ac9a..209c3dd 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -57,7 +57,7 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len)
set_fixmap(FIXMAP_MISC, p, BUFFERABLE);
memcpy(dst, src + s, l);
- clean_xen_dcache_va_range(dst, l);
+ clean_dcache_va_range(dst, l);
paddr += l;
dst += l;
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index dd70d81..e43499a 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -388,7 +388,7 @@ void flush_page_to_ram(unsigned long mfn)
{
void *v = map_domain_page(mfn);
- clean_and_invalidate_xen_dcache_va_range(v, PAGE_SIZE);
+ clean_and_invalidate_dcache_va_range(v, PAGE_SIZE);
unmap_domain_page(v);
}
@@ -511,17 +511,17 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
/* Clear the copy of the boot pagetables. Each secondary CPU
* rebuilds these itself (see head.S) */
memset(boot_pgtable, 0x0, PAGE_SIZE);
- clean_and_invalidate_xen_dcache(boot_pgtable);
+ clean_and_invalidate_dcache(boot_pgtable);
#ifdef CONFIG_ARM_64
memset(boot_first, 0x0, PAGE_SIZE);
- clean_and_invalidate_xen_dcache(boot_first);
+ clean_and_invalidate_dcache(boot_first);
memset(boot_first_id, 0x0, PAGE_SIZE);
- clean_and_invalidate_xen_dcache(boot_first_id);
+ clean_and_invalidate_dcache(boot_first_id);
#endif
memset(boot_second, 0x0, PAGE_SIZE);
- clean_and_invalidate_xen_dcache(boot_second);
+ clean_and_invalidate_dcache(boot_second);
memset(boot_third, 0x0, PAGE_SIZE);
- clean_and_invalidate_xen_dcache(boot_third);
+ clean_and_invalidate_dcache(boot_third);
/* Break up the Xen mapping into 4k pages and protect them separately. */
for ( i = 0; i < LPAE_ENTRIES; i++ )
@@ -559,7 +559,7 @@ void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
/* Make sure it is clear */
memset(this_cpu(xen_dommap), 0, DOMHEAP_SECOND_PAGES*PAGE_SIZE);
- clean_xen_dcache_va_range(this_cpu(xen_dommap),
+ clean_dcache_va_range(this_cpu(xen_dommap),
DOMHEAP_SECOND_PAGES*PAGE_SIZE);
#endif
}
@@ -570,7 +570,7 @@ int init_secondary_pagetables(int cpu)
/* Set init_ttbr for this CPU coming up. All CPus share a single setof
* pagetables, but rewrite it each time for consistency with 32 bit. */
init_ttbr = (uintptr_t) xen_pgtable + phys_offset;
- clean_xen_dcache(init_ttbr);
+ clean_dcache(init_ttbr);
return 0;
}
#else
@@ -605,15 +605,15 @@ int init_secondary_pagetables(int cpu)
write_pte(&first[first_table_offset(DOMHEAP_VIRT_START+i*FIRST_SIZE)], pte);
}
- clean_xen_dcache_va_range(first, PAGE_SIZE);
- clean_xen_dcache_va_range(domheap, DOMHEAP_SECOND_PAGES*PAGE_SIZE);
+ clean_dcache_va_range(first, PAGE_SIZE);
+ clean_dcache_va_range(domheap, DOMHEAP_SECOND_PAGES*PAGE_SIZE);
per_cpu(xen_pgtable, cpu) = first;
per_cpu(xen_dommap, cpu) = domheap;
/* Set init_ttbr for this CPU coming up */
init_ttbr = __pa(first);
- clean_xen_dcache(init_ttbr);
+ clean_dcache(init_ttbr);
return 0;
}
@@ -1287,7 +1287,7 @@ void clear_and_clean_page(struct page_info *page)
void *p = __map_domain_page(page);
clear_page(p);
- clean_xen_dcache_va_range(p, PAGE_SIZE);
+ clean_dcache_va_range(p, PAGE_SIZE);
unmap_domain_page(p);
}
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 1585d35..20bcc9e 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -343,7 +343,7 @@ static inline void p2m_write_pte(lpae_t *p, lpae_t pte, bool_t flush_cache)
{
write_pte(p, pte);
if ( flush_cache )
- clean_xen_dcache(*p);
+ clean_dcache(*p);
}
/*
@@ -403,7 +403,7 @@ static int p2m_create_table(struct domain *d, lpae_t *entry,
clear_page(p);
if ( flush_cache )
- clean_xen_dcache_va_range(p, PAGE_SIZE);
+ clean_dcache_va_range(p, PAGE_SIZE);
unmap_domain_page(p);
diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
index ee395a1..14054ae 100644
--- a/xen/arch/arm/smpboot.c
+++ b/xen/arch/arm/smpboot.c
@@ -374,7 +374,7 @@ int __cpu_up(unsigned int cpu)
/* Open the gate for this CPU */
smp_up_cpu = cpu_logical_map(cpu);
- clean_xen_dcache(smp_up_cpu);
+ clean_dcache(smp_up_cpu);
rc = arch_cpu_up(cpu);
diff --git a/xen/include/asm-arm/arm32/page.h b/xen/include/asm-arm/arm32/page.h
index 9740672..20a6a7f 100644
--- a/xen/include/asm-arm/arm32/page.h
+++ b/xen/include/asm-arm/arm32/page.h
@@ -20,11 +20,11 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
}
/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
-#define __clean_xen_dcache_one(R) STORE_CP32(R, DCCMVAC)
+#define __clean_dcache_one(R) STORE_CP32(R, DCCMVAC)
/* Inline ASM to clean and invalidate dcache on register R (may be an
* inline asm operand) */
-#define __clean_and_invalidate_xen_dcache_one(R) STORE_CP32(R, DCCIMVAC)
+#define __clean_and_invalidate_dcache_one(R) STORE_CP32(R, DCCIMVAC)
/*
* Flush all hypervisor mappings from the TLB and branch predictor of
diff --git a/xen/include/asm-arm/arm64/page.h b/xen/include/asm-arm/arm64/page.h
index bb10164..101d7a8 100644
--- a/xen/include/asm-arm/arm64/page.h
+++ b/xen/include/asm-arm/arm64/page.h
@@ -15,11 +15,11 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
}
/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
-#define __clean_xen_dcache_one(R) "dc cvac, %" #R ";"
+#define __clean_dcache_one(R) "dc cvac, %" #R ";"
/* Inline ASM to clean and invalidate dcache on register R (may be an
* inline asm operand) */
-#define __clean_and_invalidate_xen_dcache_one(R) "dc civac, %" #R ";"
+#define __clean_and_invalidate_dcache_one(R) "dc civac, %" #R ";"
/*
* Flush all hypervisor mappings from the TLB of the local processor.
diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h
index d758b61..fb1e710 100644
--- a/xen/include/asm-arm/page.h
+++ b/xen/include/asm-arm/page.h
@@ -268,48 +268,48 @@ extern size_t cacheline_bytes;
/* Functions for flushing medium-sized areas.
* if 'range' is large enough we might want to use model-specific
* full-cache flushes. */
-static inline void clean_xen_dcache_va_range(const void *p, unsigned long size)
+static inline void clean_dcache_va_range(const void *p, unsigned long size)
{
const void *end;
dsb(sy); /* So the CPU issues all writes to the range */
for ( end = p + size; p < end; p += cacheline_bytes )
- asm volatile (__clean_xen_dcache_one(0) : : "r" (p));
+ asm volatile (__clean_dcache_one(0) : : "r" (p));
dsb(sy); /* So we know the flushes happen before continuing */
}
-static inline void clean_and_invalidate_xen_dcache_va_range
+static inline void clean_and_invalidate_dcache_va_range
(const void *p, unsigned long size)
{
const void *end;
dsb(sy); /* So the CPU issues all writes to the range */
for ( end = p + size; p < end; p += cacheline_bytes )
- asm volatile (__clean_and_invalidate_xen_dcache_one(0) : : "r" (p));
+ asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (p));
dsb(sy); /* So we know the flushes happen before continuing */
}
/* Macros for flushing a single small item. The predicate is always
* compile-time constant so this will compile down to 3 instructions in
* the common case. */
-#define clean_xen_dcache(x) do { \
+#define clean_dcache(x) do { \
typeof(x) *_p = &(x); \
if ( sizeof(x) > MIN_CACHELINE_BYTES || sizeof(x) > alignof(x) ) \
- clean_xen_dcache_va_range(_p, sizeof(x)); \
+ clean_dcache_va_range(_p, sizeof(x)); \
else \
asm volatile ( \
"dsb sy;" /* Finish all earlier writes */ \
- __clean_xen_dcache_one(0) \
+ __clean_dcache_one(0) \
"dsb sy;" /* Finish flush before continuing */ \
: : "r" (_p), "m" (*_p)); \
} while (0)
-#define clean_and_invalidate_xen_dcache(x) do { \
+#define clean_and_invalidate_dcache(x) do { \
typeof(x) *_p = &(x); \
if ( sizeof(x) > MIN_CACHELINE_BYTES || sizeof(x) > alignof(x) ) \
- clean_and_invalidate_xen_dcache_va_range(_p, sizeof(x)); \
+ clean_and_invalidate_dcache_va_range(_p, sizeof(x)); \
else \
asm volatile ( \
"dsb sy;" /* Finish all earlier writes */ \
- __clean_and_invalidate_xen_dcache_one(0) \
+ __clean_and_invalidate_dcache_one(0) \
"dsb sy;" /* Finish flush before continuing */ \
: : "r" (_p), "m" (*_p)); \
} while (0)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v11 3/8] xen/arm: return int from *_dcache_va_range
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 1/8] xen: introduce gnttab_max_frames and gnttab_max_maptrack_frames command line options Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 2/8] xen/arm: rename *_xen_dcache_* operations to *_dcache_* Stefano Stabellini
@ 2014-10-22 16:40 ` Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 4/8] xen/arm: introduce invalidate_dcache_va_range Stefano Stabellini
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:40 UTC (permalink / raw)
To: xen-devel; +Cc: julien.grall, Ian.Campbell, JBeulich, Stefano Stabellini
These functions cannot really fail on ARM, but their x86 equivalents can
(-EOPNOTSUPP). Change the prototype to return int.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v9:
- remove useless ASSERT;
- add a comment on ARM callers assuming that these functions cannot
fail.
Changes in v6:
- do not return int from flush_page_to_ram.
---
xen/include/asm-arm/page.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h
index fb1e710..69e9a61 100644
--- a/xen/include/asm-arm/page.h
+++ b/xen/include/asm-arm/page.h
@@ -268,16 +268,18 @@ extern size_t cacheline_bytes;
/* Functions for flushing medium-sized areas.
* if 'range' is large enough we might want to use model-specific
* full-cache flushes. */
-static inline void clean_dcache_va_range(const void *p, unsigned long size)
+static inline int clean_dcache_va_range(const void *p, unsigned long size)
{
const void *end;
dsb(sy); /* So the CPU issues all writes to the range */
for ( end = p + size; p < end; p += cacheline_bytes )
asm volatile (__clean_dcache_one(0) : : "r" (p));
dsb(sy); /* So we know the flushes happen before continuing */
+ /* ARM callers assume that dcache_* functions cannot fail. */
+ return 0;
}
-static inline void clean_and_invalidate_dcache_va_range
+static inline int clean_and_invalidate_dcache_va_range
(const void *p, unsigned long size)
{
const void *end;
@@ -285,6 +287,8 @@ static inline void clean_and_invalidate_dcache_va_range
for ( end = p + size; p < end; p += cacheline_bytes )
asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (p));
dsb(sy); /* So we know the flushes happen before continuing */
+ /* ARM callers assume that dcache_* functions cannot fail. */
+ return 0;
}
/* Macros for flushing a single small item. The predicate is always
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v11 4/8] xen/arm: introduce invalidate_dcache_va_range
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
` (2 preceding siblings ...)
2014-10-22 16:40 ` [PATCH v11 3/8] xen/arm: return int from *_dcache_va_range Stefano Stabellini
@ 2014-10-22 16:40 ` Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 5/8] xen/x86: introduce more cache maintenance operations Stefano Stabellini
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:40 UTC (permalink / raw)
To: xen-devel; +Cc: julien.grall, Ian.Campbell, JBeulich, Stefano Stabellini
Take care of handling non-cacheline aligned addresses and sizes.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v5:
- return int from invalidate_dcache_va_range.
Changes in v4:
- rename invalidate_xen_dcache_va_range to invalidate_dcache_va_range.
---
xen/include/asm-arm/arm32/page.h | 3 +++
xen/include/asm-arm/arm64/page.h | 3 +++
xen/include/asm-arm/page.h | 32 ++++++++++++++++++++++++++++++++
3 files changed, 38 insertions(+)
diff --git a/xen/include/asm-arm/arm32/page.h b/xen/include/asm-arm/arm32/page.h
index 20a6a7f..a07e217 100644
--- a/xen/include/asm-arm/arm32/page.h
+++ b/xen/include/asm-arm/arm32/page.h
@@ -19,6 +19,9 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
: : "r" (pte.bits), "r" (p) : "memory");
}
+/* Inline ASM to invalidate dcache on register R (may be an inline asm operand) */
+#define __invalidate_dcache_one(R) STORE_CP32(R, DCIMVAC)
+
/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
#define __clean_dcache_one(R) STORE_CP32(R, DCCMVAC)
diff --git a/xen/include/asm-arm/arm64/page.h b/xen/include/asm-arm/arm64/page.h
index 101d7a8..1fd416d 100644
--- a/xen/include/asm-arm/arm64/page.h
+++ b/xen/include/asm-arm/arm64/page.h
@@ -14,6 +14,9 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
: : "r" (pte.bits), "r" (p) : "memory");
}
+/* Inline ASM to invalidate dcache on register R (may be an inline asm operand) */
+#define __invalidate_dcache_one(R) "dc ivac, %" #R ";"
+
/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
#define __clean_dcache_one(R) "dc cvac, %" #R ";"
diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h
index 69e9a61..53d4b63 100644
--- a/xen/include/asm-arm/page.h
+++ b/xen/include/asm-arm/page.h
@@ -268,6 +268,38 @@ extern size_t cacheline_bytes;
/* Functions for flushing medium-sized areas.
* if 'range' is large enough we might want to use model-specific
* full-cache flushes. */
+
+static inline int invalidate_dcache_va_range(const void *p, unsigned long size)
+{
+ size_t off;
+ const void *end = p + size;
+
+ dsb(sy); /* So the CPU issues all writes to the range */
+
+ off = (unsigned long)p % cacheline_bytes;
+ if ( off )
+ {
+ p -= off;
+ asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (p));
+ p += cacheline_bytes;
+ size -= cacheline_bytes - off;
+ }
+ off = (unsigned long)end % cacheline_bytes;
+ if ( off )
+ {
+ end -= off;
+ size -= off;
+ asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (end));
+ }
+
+ for ( ; p < end; p += cacheline_bytes )
+ asm volatile (__invalidate_dcache_one(0) : : "r" (p));
+
+ dsb(sy); /* So we know the flushes happen before continuing */
+
+ return 0;
+}
+
static inline int clean_dcache_va_range(const void *p, unsigned long size)
{
const void *end;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v11 5/8] xen/x86: introduce more cache maintenance operations
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
` (3 preceding siblings ...)
2014-10-22 16:40 ` [PATCH v11 4/8] xen/arm: introduce invalidate_dcache_va_range Stefano Stabellini
@ 2014-10-22 16:40 ` Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 6/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:40 UTC (permalink / raw)
To: xen-devel; +Cc: julien.grall, Ian.Campbell, JBeulich, Stefano Stabellini
Move the existing flush_page_to_ram flushtlb.h.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in v7:
- return the called function's return value from clean_dcache_va_range.
Changes in v5:
- make order an unsigned int;
- add a comment on sub-page granularity support;
- cache operations return error;
- move the functions to xen/include/asm-x86/flushtlb.h.
Changes in v4:
- remove _xen in the function names;
- implement the functions using existing x86 flushing functions.
---
xen/include/asm-x86/flushtlb.h | 15 +++++++++++++++
xen/include/asm-x86/page.h | 3 ---
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/xen/include/asm-x86/flushtlb.h b/xen/include/asm-x86/flushtlb.h
index 7f46632..85e260a 100644
--- a/xen/include/asm-x86/flushtlb.h
+++ b/xen/include/asm-x86/flushtlb.h
@@ -11,6 +11,7 @@
#define __FLUSHTLB_H__
#include <xen/config.h>
+#include <xen/mm.h>
#include <xen/percpu.h>
#include <xen/smp.h>
#include <xen/types.h>
@@ -115,4 +116,18 @@ void flush_area_mask(const cpumask_t *, const void *va, unsigned int flags);
#define flush_tlb_one_all(v) \
flush_tlb_one_mask(&cpu_online_map, v)
+static inline void flush_page_to_ram(unsigned long mfn) {}
+static inline int invalidate_dcache_va_range(const void *p, unsigned long size) { return -EOPNOTSUPP; }
+static inline int clean_and_invalidate_dcache_va_range(const void *p, unsigned long size)
+{
+ unsigned int order = get_order_from_bytes(size);
+ /* sub-page granularity support needs to be added if necessary */
+ flush_area_local(p, FLUSH_CACHE|FLUSH_ORDER(order));
+ return 0;
+}
+static inline int clean_dcache_va_range(const void *p, unsigned long size)
+{
+ return clean_and_invalidate_dcache_va_range(p, size);
+}
+
#endif /* __FLUSHTLB_H__ */
diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h
index 9aa780e..a8bc999 100644
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -344,9 +344,6 @@ static inline uint32_t cacheattr_to_pte_flags(uint32_t cacheattr)
return ((cacheattr & 4) << 5) | ((cacheattr & 3) << 3);
}
-/* No cache maintenance required on x86 architecture. */
-static inline void flush_page_to_ram(unsigned long mfn) {}
-
/* return true if permission increased */
static inline bool_t
perms_strictly_increased(uint32_t old_flags, uint32_t new_flags)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v11 6/8] xen/arm: introduce GNTTABOP_cache_flush
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
` (4 preceding siblings ...)
2014-10-22 16:40 ` [PATCH v11 5/8] xen/x86: introduce more cache maintenance operations Stefano Stabellini
@ 2014-10-22 16:40 ` Stefano Stabellini
2014-10-23 8:34 ` Jan Beulich
2014-10-22 16:40 ` [PATCH v11 7/8] Revert "xen/arm: introduce XENFEAT_grant_map_identity" Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 8/8] Revert "xen: introduce arch_grant_(un)map_page_identity" Stefano Stabellini
7 siblings, 1 reply; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:40 UTC (permalink / raw)
To: xen-devel; +Cc: julien.grall, Ian.Campbell, JBeulich, Stefano Stabellini
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.
Introduce grant_map_exists: an internal grant table function to check
whether an mfn has been granted to a given domain on a target grant
table. Check hypercall_preempt_check() every 4096 iterations in the
implementation of grant_map_exists.
Use the top 20 bits of the GNTTABOP cmd encoding to save the last ref
across the hypercall continuation.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
Changes in v11:
- make ref and max_iter unsigned int;
- remove useless initializations of ret to 0;
- check that cflush->op is valid;
- BUG() later on if cflush->op is invalid;
- fix blank lines;
- remove comment.
Changes in v10:
- add a comment on dev_bus_addr;
- remove comment on max GNTTABOP;
- break long lines;
- remove ref_count local variable;
- use unsigned int* instead of grant_ref_t* as arguments.
Changes in v9:
- grant_map_exists: calculate max iteration before the loop;
- do_grant_table_op: avoid shifts, use masks instead;
- set GNTTABOP_CONTINUATION_ARG_SHIFT to 12;
- remove MAX_GRANT_ENTRIES_ITER_SHIFT, use
GNTTABOP_CONTINUATION_ARG_SHIFT;
- move GNTTABOP_CMD_MASK and GNTTABOP_CONTINUATION_ARG_SHIFT to
grant_table.c.
Changes in v8:
- avoid security issues, use two separate opaque variables to store the
input argument and the output argument;
- fix return values of grant_map_exists;
- rename CMD_MASK to GNTTABOP_CMD_MASK;
- rename OPAQUE_CONTINUATION_ARG_SHIFT to
GNTTABOP_CONTINUATION_ARG_SHIFT;
- save in the opaque argument the shifted ref_count;
- set GNTTABOP_CONTINUATION_ARG_SHIFT to 20 and
MAX_GRANT_ENTRIES_ITER_SHIFT to 12, to cover the full grant_ref_t value
range;
- move GNTTABOP_CONTINUATION_ARG_SHIFT and GNTTABOP_CMD_MASK to
include/xen/grant_table.h;
- cmd &= GNTTABOP_CMD_MASK in the compat wrapper.
Changes in v7:
- remove warning message;
- prefix second line of the warning with XENLOG_WARNING;
- do not lower DEFAULT_MAX_NR_GRANT_FRAMES;
- no long lines;
- interrupt loops in grant_map_exists with more than 2048 iterations,
create an hypercall continuation if necessary.
Changes in v6:
- set DEFAULT_MAX_NR_GRANT_FRAMES to 10;
- warn if max_grant_frames > 10.
Changes in v5:
- make mfn mfn unsigned long;
- remove unhelpful error message;
- handle errors returned by cache maintenance functions.
Changes in v4:
- ASSERT(spin_is_locked);
- return instead of break in grant_map_exists;
- pass a pointer to __gnttab_cache_flush;
- code style;
- unsigned int iterator in gnttab_cache_flush;
- return ret instead -ret;
- cflush.offset >= PAGE_SIZE return -EINVAL.
Changes in v3:
- reduce the time the grant_table lock is held;
- fix warning message;
- s/EFAULT/EPERM;
- s/llx/PRIx64;
- check offset and size independetly before checking their sum;
- rcu_lock_current_domain cannot fail;
- s/ENOSYS/EOPNOTSUPP;
- use clean_and_invalidate_xen_dcache_va_range to do both operations at
once;
- fold grant_map_exists in this patch;
- support "count" argument;
- make correspondent changes to compat/grant_table.c;
- introduce GNTTAB_CACHE_SOURCE_GREF to select the type of input in the
union;
- rename size field to length;
- make length and offset uint16_t;
- only take spin_lock if d != owner.
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/compat/grant_table.c | 15 +++-
xen/common/grant_table.c | 173 +++++++++++++++++++++++++++++++++++++-
xen/include/public/grant_table.h | 20 +++++
xen/include/xlat.lst | 1 +
4 files changed, 203 insertions(+), 6 deletions(-)
diff --git a/xen/common/compat/grant_table.c b/xen/common/compat/grant_table.c
index 2dc1e44..0368289 100644
--- a/xen/common/compat/grant_table.c
+++ b/xen/common/compat/grant_table.c
@@ -51,16 +51,21 @@ CHECK_gnttab_get_version;
CHECK_gnttab_swap_grant_ref;
#undef xen_gnttab_swap_grant_ref
+#define xen_gnttab_cache_flush gnttab_cache_flush
+CHECK_gnttab_cache_flush;
+#undef xen_gnttab_cache_flush
+
int compat_grant_table_op(unsigned int cmd,
XEN_GUEST_HANDLE_PARAM(void) cmp_uop,
unsigned int count)
{
int rc = 0;
- unsigned int i;
+ unsigned int i, cmd_op;
XEN_GUEST_HANDLE_PARAM(void) cnt_uop;
set_xen_guest_handle(cnt_uop, NULL);
- switch ( cmd )
+ cmd_op = cmd & GNTTABOP_CMD_MASK;
+ switch ( cmd_op )
{
#define CASE(name) \
case GNTTABOP_##name: \
@@ -106,6 +111,10 @@ int compat_grant_table_op(unsigned int cmd,
CASE(swap_grant_ref);
#endif
+#ifndef CHECK_gnttab_cache_flush
+ CASE(cache_flush);
+#endif
+
#undef CASE
default:
return do_grant_table_op(cmd, cmp_uop, count);
@@ -132,7 +141,7 @@ int compat_grant_table_op(unsigned int cmd,
} cmp;
set_xen_guest_handle(nat.uop, COMPAT_ARG_XLAT_VIRT_BASE);
- switch ( cmd )
+ switch ( cmd_op )
{
case GNTTABOP_setup_table:
if ( unlikely(count > 1) )
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index f9a9b44..9b1c338 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -62,6 +62,11 @@ integer_param("gnttab_max_frames", max_grant_frames);
static unsigned int __read_mostly max_maptrack_frames;
integer_param("gnttab_max_maptrack_frames", max_maptrack_frames);
+
+#define GNTTABOP_CONTINUATION_ARG_SHIFT 12
+#define GNTTABOP_CMD_MASK ((1<<GNTTABOP_CONTINUATION_ARG_SHIFT)-1)
+#define GNTTABOP_ARG_MASK (~GNTTABOP_CMD_MASK)
+
/*
* The first two members of a grant entry are updated as a combined pair.
* The following union allows that to happen in an endian-neutral fashion.
@@ -490,6 +495,43 @@ static int _set_status(unsigned gt_version,
return _set_status_v2(domid, readonly, mapflag, shah, act, status);
}
+static int grant_map_exists(const struct domain *ld,
+ struct grant_table *rgt,
+ unsigned long mfn,
+ unsigned int *ref_count)
+{
+ const struct active_grant_entry *act;
+ unsigned int ref, max_iter;
+
+ ASSERT(spin_is_locked(&rgt->lock));
+
+ max_iter = min(*ref_count + (1 << GNTTABOP_CONTINUATION_ARG_SHIFT),
+ nr_grant_entries(rgt));
+ for ( ref = *ref_count; ref < max_iter; ref++ )
+ {
+ act = &active_entry(rgt, ref);
+
+ if ( !act->pin )
+ continue;
+
+ if ( act->domid != ld->domain_id )
+ continue;
+
+ if ( act->frame != mfn )
+ continue;
+
+ return 0;
+ }
+
+ if ( ref < nr_grant_entries(rgt) )
+ {
+ *ref_count = ref;
+ return 1;
+ }
+
+ return -EINVAL;
+}
+
static void mapcount(
struct grant_table *lgt, struct domain *rd, unsigned long mfn,
unsigned int *wrc, unsigned int *rdc)
@@ -2488,16 +2530,124 @@ gnttab_swap_grant_ref(XEN_GUEST_HANDLE_PARAM(gnttab_swap_grant_ref_t) uop,
return 0;
}
+static int __gnttab_cache_flush(gnttab_cache_flush_t *cflush,
+ unsigned int *ref_count)
+{
+ struct domain *d, *owner;
+ struct page_info *page;
+ unsigned long mfn;
+ void *v;
+ int ret;
+
+ if ( (cflush->offset >= PAGE_SIZE) ||
+ (cflush->length > PAGE_SIZE) ||
+ (cflush->offset + cflush->length > PAGE_SIZE) )
+ return -EINVAL;
+
+ if ( cflush->length == 0 || cflush->op == 0 )
+ return 0;
+
+ /* currently unimplemented */
+ if ( cflush->op & GNTTAB_CACHE_SOURCE_GREF )
+ return -EOPNOTSUPP;
+
+ if ( !(cflush->op & (GNTTAB_CACHE_INVAL|GNTTAB_CACHE_CLEAN)) ||
+ (cflush->op & ~(GNTTAB_CACHE_INVAL|GNTTAB_CACHE_CLEAN)) )
+ return -EINVAL;
+
+ d = rcu_lock_current_domain();
+ mfn = cflush->a.dev_bus_addr >> PAGE_SHIFT;
+
+ if ( !mfn_valid(mfn) )
+ {
+ 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 -EPERM;
+ }
+
+ if ( d != owner )
+ {
+ spin_lock(&owner->grant_table->lock);
+
+ ret = grant_map_exists(d, owner->grant_table, mfn, ref_count);
+ if ( ret != 0 )
+ {
+ spin_unlock(&owner->grant_table->lock);
+ rcu_unlock_domain(d);
+ put_page(page);
+ return ret;
+ }
+ }
+
+ v = map_domain_page(mfn);
+ v += cflush->offset;
+
+ if ( (cflush->op & GNTTAB_CACHE_INVAL) && (cflush->op & GNTTAB_CACHE_CLEAN) )
+ ret = clean_and_invalidate_dcache_va_range(v, cflush->length);
+ else if ( cflush->op & GNTTAB_CACHE_INVAL )
+ ret = invalidate_dcache_va_range(v, cflush->length);
+ else if ( cflush->op & GNTTAB_CACHE_CLEAN )
+ ret = clean_dcache_va_range(v, cflush->length);
+ else
+ BUG();
+
+ if ( d != owner )
+ spin_unlock(&owner->grant_table->lock);
+ unmap_domain_page(v);
+ put_page(page);
+
+ return ret;
+}
+
+static long
+gnttab_cache_flush(XEN_GUEST_HANDLE_PARAM(gnttab_cache_flush_t) uop,
+ unsigned int *ref_count,
+ unsigned int count)
+{
+ int ret;
+ unsigned int i;
+ gnttab_cache_flush_t op;
+
+ for ( i = 0; i < count; i++ )
+ {
+ if ( i && hypercall_preempt_check() )
+ return i;
+ if ( unlikely(__copy_from_guest(&op, uop, 1)) )
+ return -EFAULT;
+ do {
+ ret = __gnttab_cache_flush(&op, ref_count);
+ if ( ret < 0 )
+ return ret;
+ if ( ret > 0 && hypercall_preempt_check() )
+ return i;
+ } while ( ret > 0 );
+ *ref_count = 0;
+ guest_handle_add_offset(uop, 1);
+ }
+ return 0;
+}
+
long
do_grant_table_op(
unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) uop, unsigned int count)
{
long rc;
+ unsigned int opaque_in = 0, opaque_out = 0;
if ( (int)count < 0 )
return -EINVAL;
rc = -EFAULT;
+
+ opaque_in = cmd & GNTTABOP_ARG_MASK;
+ cmd &= GNTTABOP_CMD_MASK;
switch ( cmd )
{
case GNTTABOP_map_grant_ref:
@@ -2617,17 +2767,34 @@ do_grant_table_op(
}
break;
}
+ case GNTTABOP_cache_flush:
+ {
+ XEN_GUEST_HANDLE_PARAM(gnttab_cache_flush_t) cflush =
+ guest_handle_cast(uop, gnttab_cache_flush_t);
+
+ if ( unlikely(!guest_handle_okay(cflush, count)) )
+ goto out;
+ rc = gnttab_cache_flush(cflush, &opaque_in, count);
+ if ( rc > 0 )
+ {
+ guest_handle_add_offset(cflush, rc);
+ uop = guest_handle_cast(cflush, void);
+ }
+ opaque_out = opaque_in;
+ break;
+ }
default:
rc = -ENOSYS;
break;
}
out:
- if ( rc > 0 )
+ if ( rc > 0 || opaque_out != 0 )
{
ASSERT(rc < count);
- rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op,
- "ihi", cmd, uop, count - rc);
+ ASSERT((opaque_out & GNTTABOP_CMD_MASK) == 0);
+ rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op, "ihi",
+ opaque_out | cmd, uop, count - rc);
}
return rc;
diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h
index b8a3d6c..20d4e77 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,25 @@ 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;
+ uint16_t offset; /* offset from start of grant */
+ uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN (1<<0)
+#define GNTTAB_CACHE_INVAL (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF (1<<31)
+ uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
#endif /* __XEN_INTERFACE_VERSION__ */
/*
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
index 234b668..9ce9fee 100644
--- a/xen/include/xlat.lst
+++ b/xen/include/xlat.lst
@@ -51,6 +51,7 @@
? grant_entry_header grant_table.h
? grant_entry_v2 grant_table.h
? gnttab_swap_grant_ref grant_table.h
+? gnttab_cache_flush grant_table.h
? kexec_exec kexec.h
! kexec_image kexec.h
! kexec_range kexec.h
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v11 7/8] Revert "xen/arm: introduce XENFEAT_grant_map_identity"
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
` (5 preceding siblings ...)
2014-10-22 16:40 ` [PATCH v11 6/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
@ 2014-10-22 16:40 ` Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 8/8] Revert "xen: introduce arch_grant_(un)map_page_identity" Stefano Stabellini
7 siblings, 0 replies; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:40 UTC (permalink / raw)
To: xen-devel; +Cc: julien.grall, Ian.Campbell, JBeulich, Stefano Stabellini
Revert commit id 8d09ef6906ca0a9957e21334ad2c3eed626abe63.
Just keep the definition of XENFEAT_grant_map_identity.
XENFEAT_grant_map_identity is superseeded by GNTTABOP_cache_flush. As
XENFEAT_grant_map_identity causes additional tlb flushes, it is best to
remove the feature entirely now.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v2:
- comment out the definition of XENFEAT_grant_map_identity.
---
xen/common/grant_table.c | 30 +++++-------------------------
xen/common/kernel.c | 2 --
xen/drivers/passthrough/arm/smmu.c | 33 +++++++++++++++++++++++++++++++++
xen/include/asm-arm/grant_table.h | 3 ++-
xen/include/public/features.h | 4 +++-
5 files changed, 43 insertions(+), 29 deletions(-)
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 9b1c338..6b3c1cd 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -786,23 +786,13 @@ __gnttab_map_grant_ref(
!(old_pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
{
if ( wrc == 0 )
- {
- if ( is_domain_direct_mapped(ld) )
- err = arch_grant_map_page_identity(ld, frame, 1);
- else
- err = iommu_map_page(ld, frame, frame,
- IOMMUF_readable|IOMMUF_writable);
- }
+ err = iommu_map_page(ld, frame, frame,
+ IOMMUF_readable|IOMMUF_writable);
}
else if ( act_pin && !old_pin )
{
if ( (wrc + rdc) == 0 )
- {
- if ( is_domain_direct_mapped(ld) )
- err = arch_grant_map_page_identity(ld, frame, 0);
- else
- err = iommu_map_page(ld, frame, frame, IOMMUF_readable);
- }
+ err = iommu_map_page(ld, frame, frame, IOMMUF_readable);
}
if ( err )
{
@@ -999,19 +989,9 @@ __gnttab_unmap_common(
int err = 0;
mapcount(lgt, rd, op->frame, &wrc, &rdc);
if ( (wrc + rdc) == 0 )
- {
- if ( is_domain_direct_mapped(ld) )
- err = arch_grant_unmap_page_identity(ld, op->frame);
- else
- err = iommu_unmap_page(ld, op->frame);
- }
+ err = iommu_unmap_page(ld, op->frame);
else if ( wrc == 0 )
- {
- if ( is_domain_direct_mapped(ld) )
- err = arch_grant_map_page_identity(ld, op->frame, 0);
- else
- err = iommu_map_page(ld, op->frame, op->frame, IOMMUF_readable);
- }
+ err = iommu_map_page(ld, op->frame, op->frame, IOMMUF_readable);
if ( err )
{
rc = GNTST_general_error;
diff --git a/xen/common/kernel.c b/xen/common/kernel.c
index ce65486..d23c422 100644
--- a/xen/common/kernel.c
+++ b/xen/common/kernel.c
@@ -332,8 +332,6 @@ DO(xen_version)(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
break;
}
#endif
- if ( is_domain_direct_mapped(d) )
- fi.submap |= 1U << XENFEAT_grant_map_identity;
break;
default:
return -EINVAL;
diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
index 3cbd206..9a95ac9 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -1536,6 +1536,37 @@ static void arm_smmu_iommu_domain_teardown(struct domain *d)
xfree(smmu_domain);
}
+static int arm_smmu_map_page(struct domain *d, unsigned long gfn,
+ unsigned long mfn, unsigned int flags)
+{
+ /* Grant mappings can be used for DMA requests. The dev_bus_addr returned by
+ * the hypercall is the MFN (not the IPA). For device protected by
+ * an IOMMU, Xen needs to add a 1:1 mapping in the domain p2m to
+ * allow DMA request to work.
+ * This is only valid when the domain is directed mapped. Hence this
+ * function should only be used by gnttab code with gfn == mfn.
+ */
+ BUG_ON(!is_domain_direct_mapped(d));
+ BUG_ON(mfn != gfn);
+
+ /* We only support readable and writable flags */
+ if ( !(flags & (IOMMUF_readable | IOMMUF_writable)) )
+ return -EINVAL;
+
+ return arch_grant_map_page_identity(d, mfn, flags & IOMMUF_writable);
+}
+
+static int arm_smmu_unmap_page(struct domain *d, unsigned long gfn)
+{
+ /* This function should only be used by gnttab code when the domain
+ * is direct mapped
+ */
+ if ( !is_domain_direct_mapped(d) )
+ return -EINVAL;
+
+ return arch_grant_unmap_page_identity(d, gfn);
+}
+
static const struct iommu_ops arm_smmu_iommu_ops = {
.init = arm_smmu_iommu_domain_init,
.hwdom_init = arm_smmu_iommu_hwdom_init,
@@ -1544,6 +1575,8 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
.iotlb_flush_all = arm_smmu_iotlb_flush_all,
.assign_dt_device = arm_smmu_attach_dev,
.reassign_dt_device = arm_smmu_reassign_dt_dev,
+ .map_page = arm_smmu_map_page,
+ .unmap_page = arm_smmu_unmap_page,
};
static int __init smmu_init(struct dt_device_node *dev,
diff --git a/xen/include/asm-arm/grant_table.h b/xen/include/asm-arm/grant_table.h
index e798880..0edad67 100644
--- a/xen/include/asm-arm/grant_table.h
+++ b/xen/include/asm-arm/grant_table.h
@@ -33,7 +33,8 @@ static inline int replace_grant_supported(void)
( ((i >= nr_grant_frames(d->grant_table)) && \
(i < max_grant_frames)) ? 0 : (d->arch.grant_table_gpfn[i]))
-#define gnttab_need_iommu_mapping(d) (is_domain_direct_mapped(d))
+#define gnttab_need_iommu_mapping(d) \
+ (is_domain_direct_mapped(d) && need_iommu(d))
#endif /* __ASM_GRANT_TABLE_H__ */
/*
diff --git a/xen/include/public/features.h b/xen/include/public/features.h
index b7bf83f..16d92aa 100644
--- a/xen/include/public/features.h
+++ b/xen/include/public/features.h
@@ -94,8 +94,10 @@
/* operation as Dom0 is supported */
#define XENFEAT_dom0 11
-/* Xen also maps grant references at pfn = mfn */
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
#define XENFEAT_grant_map_identity 12
+ */
#define XENFEAT_NR_SUBMAPS 1
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v11 8/8] Revert "xen: introduce arch_grant_(un)map_page_identity"
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
` (6 preceding siblings ...)
2014-10-22 16:40 ` [PATCH v11 7/8] Revert "xen/arm: introduce XENFEAT_grant_map_identity" Stefano Stabellini
@ 2014-10-22 16:40 ` Stefano Stabellini
7 siblings, 0 replies; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-22 16:40 UTC (permalink / raw)
To: xen-devel; +Cc: julien.grall, Ian.Campbell, JBeulich, Stefano Stabellini
This reverts commit e25a5f4d8cf3b55718048abdd21c7d0de64ae54c.
With the removal of XENFEAT_grant_map_identity, this commit is not
needed anymore.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
xen/arch/arm/p2m.c | 26 --------------------------
xen/drivers/passthrough/arm/smmu.c | 13 +++++++++++--
xen/include/asm-arm/p2m.h | 4 ----
xen/include/asm-x86/p2m.h | 4 ----
4 files changed, 11 insertions(+), 36 deletions(-)
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 20bcc9e..6b7569a 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -982,32 +982,6 @@ void guest_physmap_remove_page(struct domain *d,
pfn_to_paddr(mfn), MATTR_MEM, p2m_invalid);
}
-int arch_grant_map_page_identity(struct domain *d, unsigned long frame,
- bool_t writeable)
-{
- p2m_type_t t;
-
- ASSERT(is_domain_direct_mapped(d));
-
- /* This is not an IOMMU mapping but it is not a regular RAM p2m type
- * either. We are using IOMMU p2m types here to prevent the pages
- * from being used as grants. */
- if ( writeable )
- t = p2m_iommu_map_rw;
- else
- t = p2m_iommu_map_ro;
-
- return guest_physmap_add_entry(d, frame, frame, 0, t);
-}
-
-int arch_grant_unmap_page_identity(struct domain *d, unsigned long frame)
-{
- ASSERT(is_domain_direct_mapped(d));
-
- guest_physmap_remove_page(d, frame, frame, 0);
- return 0;
-}
-
int p2m_alloc_table(struct domain *d)
{
struct p2m_domain *p2m = &d->arch.p2m;
diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c
index 9a95ac9..42bde75 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -1539,6 +1539,8 @@ static void arm_smmu_iommu_domain_teardown(struct domain *d)
static int arm_smmu_map_page(struct domain *d, unsigned long gfn,
unsigned long mfn, unsigned int flags)
{
+ p2m_type_t t;
+
/* Grant mappings can be used for DMA requests. The dev_bus_addr returned by
* the hypercall is the MFN (not the IPA). For device protected by
* an IOMMU, Xen needs to add a 1:1 mapping in the domain p2m to
@@ -1553,7 +1555,12 @@ static int arm_smmu_map_page(struct domain *d, unsigned long gfn,
if ( !(flags & (IOMMUF_readable | IOMMUF_writable)) )
return -EINVAL;
- return arch_grant_map_page_identity(d, mfn, flags & IOMMUF_writable);
+ t = (flags & IOMMUF_writable) ? p2m_iommu_map_rw : p2m_iommu_map_ro;
+
+ /* The function guest_physmap_add_entry replaces the current mapping
+ * if there is already one...
+ */
+ return guest_physmap_add_entry(d, gfn, mfn, 0, t);
}
static int arm_smmu_unmap_page(struct domain *d, unsigned long gfn)
@@ -1564,7 +1571,9 @@ static int arm_smmu_unmap_page(struct domain *d, unsigned long gfn)
if ( !is_domain_direct_mapped(d) )
return -EINVAL;
- return arch_grant_unmap_page_identity(d, gfn);
+ guest_physmap_remove_page(d, gfn, gfn, 0);
+
+ return 0;
}
static const struct iommu_ops arm_smmu_iommu_ops = {
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index 10bf111..da36504 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -214,10 +214,6 @@ static inline int get_page_and_type(struct page_info *page,
return rc;
}
-int arch_grant_map_page_identity(struct domain *d, unsigned long frame,
- bool_t writeable);
-int arch_grant_unmap_page_identity(struct domain *d, unsigned long frame);
-
/* get host p2m table */
#define p2m_get_hostp2m(d) (&(d)->arch.p2m)
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 90ddd15..5f7fe71 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -709,10 +709,6 @@ static inline unsigned int p2m_get_iommu_flags(p2m_type_t p2mt)
return flags;
}
-extern int arch_grant_map_page_identity(struct domain *d, unsigned long frame,
- bool_t writeable);
-extern int arch_grant_unmap_page_identity(struct domain *d, unsigned long frame);
-
#endif /* _XEN_P2M_H */
/*
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v11 6/8] xen/arm: introduce GNTTABOP_cache_flush
2014-10-22 16:40 ` [PATCH v11 6/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
@ 2014-10-23 8:34 ` Jan Beulich
2014-10-23 9:41 ` Stefano Stabellini
0 siblings, 1 reply; 12+ messages in thread
From: Jan Beulich @ 2014-10-23 8:34 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: julien.grall, xen-devel, Ian.Campbell
>>> On 22.10.14 at 18:40, <stefano.stabellini@eu.citrix.com> 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.
>
> Introduce grant_map_exists: an internal grant table function to check
> whether an mfn has been granted to a given domain on a target grant
> table. Check hypercall_preempt_check() every 4096 iterations in the
> implementation of grant_map_exists.
> Use the top 20 bits of the GNTTABOP cmd encoding to save the last ref
> across the hypercall continuation.
>
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
albeit the subject still says "arm" while there isn't anything ARM-specific
in here and ...
> +static int __gnttab_cache_flush(gnttab_cache_flush_t *cflush,
> + unsigned int *ref_count)
> +{
> + struct domain *d, *owner;
> + struct page_info *page;
> + unsigned long mfn;
> + void *v;
> + int ret;
> +
> + if ( (cflush->offset >= PAGE_SIZE) ||
> + (cflush->length > PAGE_SIZE) ||
> + (cflush->offset + cflush->length > PAGE_SIZE) )
> + return -EINVAL;
> +
> + if ( cflush->length == 0 || cflush->op == 0 )
> + return 0;
> +
> + /* currently unimplemented */
> + if ( cflush->op & GNTTAB_CACHE_SOURCE_GREF )
> + return -EOPNOTSUPP;
> +
> + if ( !(cflush->op & (GNTTAB_CACHE_INVAL|GNTTAB_CACHE_CLEAN)) ||
... I think we should drop this because ...
> + (cflush->op & ~(GNTTAB_CACHE_INVAL|GNTTAB_CACHE_CLEAN)) )
> + return -EINVAL;
> +
> + d = rcu_lock_current_domain();
> + mfn = cflush->a.dev_bus_addr >> PAGE_SHIFT;
> +
> + if ( !mfn_valid(mfn) )
> + {
> + 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 -EPERM;
> + }
> +
> + if ( d != owner )
> + {
> + spin_lock(&owner->grant_table->lock);
> +
> + ret = grant_map_exists(d, owner->grant_table, mfn, ref_count);
> + if ( ret != 0 )
> + {
> + spin_unlock(&owner->grant_table->lock);
> + rcu_unlock_domain(d);
> + put_page(page);
> + return ret;
> + }
> + }
> +
> + v = map_domain_page(mfn);
> + v += cflush->offset;
> +
> + if ( (cflush->op & GNTTAB_CACHE_INVAL) && (cflush->op & GNTTAB_CACHE_CLEAN) )
> + ret = clean_and_invalidate_dcache_va_range(v, cflush->length);
> + else if ( cflush->op & GNTTAB_CACHE_INVAL )
> + ret = invalidate_dcache_va_range(v, cflush->length);
> + else if ( cflush->op & GNTTAB_CACHE_CLEAN )
> + ret = clean_dcache_va_range(v, cflush->length);
> + else
> + BUG();
... now that I think about it again it was a bad suggestion to BUG()
here - there's nothing wrong with the caller requesting an expensive
NOP.
Both could be fixed up while committing.
Jan
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v11 6/8] xen/arm: introduce GNTTABOP_cache_flush
2014-10-23 8:34 ` Jan Beulich
@ 2014-10-23 9:41 ` Stefano Stabellini
2014-10-23 9:57 ` Jan Beulich
0 siblings, 1 reply; 12+ messages in thread
From: Stefano Stabellini @ 2014-10-23 9:41 UTC (permalink / raw)
To: Jan Beulich; +Cc: julien.grall, xen-devel, Ian.Campbell, Stefano Stabellini
On Thu, 23 Oct 2014, Jan Beulich wrote:
> >>> On 22.10.14 at 18:40, <stefano.stabellini@eu.citrix.com> 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.
> >
> > Introduce grant_map_exists: an internal grant table function to check
> > whether an mfn has been granted to a given domain on a target grant
> > table. Check hypercall_preempt_check() every 4096 iterations in the
> > implementation of grant_map_exists.
> > Use the top 20 bits of the GNTTABOP cmd encoding to save the last ref
> > across the hypercall continuation.
> >
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
>
> Reviewed-by: Jan Beulich <jbeulich@suse.com>
> albeit the subject still says "arm" while there isn't anything ARM-specific
> in here and ...
>
> > +static int __gnttab_cache_flush(gnttab_cache_flush_t *cflush,
> > + unsigned int *ref_count)
> > +{
> > + struct domain *d, *owner;
> > + struct page_info *page;
> > + unsigned long mfn;
> > + void *v;
> > + int ret;
> > +
> > + if ( (cflush->offset >= PAGE_SIZE) ||
> > + (cflush->length > PAGE_SIZE) ||
> > + (cflush->offset + cflush->length > PAGE_SIZE) )
> > + return -EINVAL;
> > +
> > + if ( cflush->length == 0 || cflush->op == 0 )
> > + return 0;
> > +
> > + /* currently unimplemented */
> > + if ( cflush->op & GNTTAB_CACHE_SOURCE_GREF )
> > + return -EOPNOTSUPP;
> > +
> > + if ( !(cflush->op & (GNTTAB_CACHE_INVAL|GNTTAB_CACHE_CLEAN)) ||
>
> ... I think we should drop this because ...
>
> > + (cflush->op & ~(GNTTAB_CACHE_INVAL|GNTTAB_CACHE_CLEAN)) )
> > + return -EINVAL;
> > +
> > + d = rcu_lock_current_domain();
> > + mfn = cflush->a.dev_bus_addr >> PAGE_SHIFT;
> > +
> > + if ( !mfn_valid(mfn) )
> > + {
> > + 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 -EPERM;
> > + }
> > +
> > + if ( d != owner )
> > + {
> > + spin_lock(&owner->grant_table->lock);
> > +
> > + ret = grant_map_exists(d, owner->grant_table, mfn, ref_count);
> > + if ( ret != 0 )
> > + {
> > + spin_unlock(&owner->grant_table->lock);
> > + rcu_unlock_domain(d);
> > + put_page(page);
> > + return ret;
> > + }
> > + }
> > +
> > + v = map_domain_page(mfn);
> > + v += cflush->offset;
> > +
> > + if ( (cflush->op & GNTTAB_CACHE_INVAL) && (cflush->op & GNTTAB_CACHE_CLEAN) )
> > + ret = clean_and_invalidate_dcache_va_range(v, cflush->length);
> > + else if ( cflush->op & GNTTAB_CACHE_INVAL )
> > + ret = invalidate_dcache_va_range(v, cflush->length);
> > + else if ( cflush->op & GNTTAB_CACHE_CLEAN )
> > + ret = clean_dcache_va_range(v, cflush->length);
> > + else
> > + BUG();
>
> ... now that I think about it again it was a bad suggestion to BUG()
> here - there's nothing wrong with the caller requesting an expensive
> NOP.
>
> Both could be fixed up while committing.
Sure.
Given that the series already has all the required acks, are you up for
committing it yourself?
Do I need to do anything else?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v11 6/8] xen/arm: introduce GNTTABOP_cache_flush
2014-10-23 9:41 ` Stefano Stabellini
@ 2014-10-23 9:57 ` Jan Beulich
0 siblings, 0 replies; 12+ messages in thread
From: Jan Beulich @ 2014-10-23 9:57 UTC (permalink / raw)
To: Stefano Stabellini; +Cc: julien.grall, xen-devel, Ian.Campbell
>>> On 23.10.14 at 11:41, <stefano.stabellini@eu.citrix.com> wrote:
> On Thu, 23 Oct 2014, Jan Beulich wrote:
>> Both could be fixed up while committing.
>
> Sure.
> Given that the series already has all the required acks, are you up for
> committing it yourself?
> Do I need to do anything else?
No - I'm getting ready to commit it (albeit I found a few more things
to fix up, so double checking what ends up in the tree would be nice).
Jan
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-10-23 9:57 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-22 16:38 [PATCH v11 0/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 1/8] xen: introduce gnttab_max_frames and gnttab_max_maptrack_frames command line options Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 2/8] xen/arm: rename *_xen_dcache_* operations to *_dcache_* Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 3/8] xen/arm: return int from *_dcache_va_range Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 4/8] xen/arm: introduce invalidate_dcache_va_range Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 5/8] xen/x86: introduce more cache maintenance operations Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 6/8] xen/arm: introduce GNTTABOP_cache_flush Stefano Stabellini
2014-10-23 8:34 ` Jan Beulich
2014-10-23 9:41 ` Stefano Stabellini
2014-10-23 9:57 ` Jan Beulich
2014-10-22 16:40 ` [PATCH v11 7/8] Revert "xen/arm: introduce XENFEAT_grant_map_identity" Stefano Stabellini
2014-10-22 16:40 ` [PATCH v11 8/8] Revert "xen: introduce arch_grant_(un)map_page_identity" Stefano Stabellini
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.