aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/mm.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-07-18 10:05:14 +0200
committerJan Beulich <jbeulich@suse.com>2013-07-18 10:05:14 +0200
commite36e07bc9b0be0d899d4dd0ea675f6c225dafe5c (patch)
tree83149dec311543a053c445db196073824996ac8d /xen/arch/x86/mm.c
parent915a59f25c5eddd86bc2cae6389d0ed2ab87e69e (diff)
downloadxen-e36e07bc9b0be0d899d4dd0ea675f6c225dafe5c.tar.gz
xen-e36e07bc9b0be0d899d4dd0ea675f6c225dafe5c.tar.bz2
xen-e36e07bc9b0be0d899d4dd0ea675f6c225dafe5c.zip
x86: fix cache flushing condition in map_pages_to_xen()
This fixes yet another shortcoming of the function (exposed by 8bfaa2c2 ["x86: add locking to map_pages_to_xen()"]'s adjustment to msix_put_fixmap()): It must not flush caches when transitioning to a non-present mapping. Doing so causes the CLFLUSH to fault, if used in favor of WBINVD. To help code readability, factor out the whole flush flags updating in map_pages_to_xen() into a helper macro. Signed-off-by: Jan Beulich <jbeulich@suse.com> Tested-by: Sander Eikelenboom <linux@eikelenboom.it> Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/mm.c')
-rw-r--r--xen/arch/x86/mm.c56
1 files changed, 20 insertions, 36 deletions
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 286e903182..c00841cd84 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -5441,6 +5441,15 @@ int map_pages_to_xen(
l1_pgentry_t *pl1e, ol1e;
unsigned int i;
+#define flush_flags(oldf) do { \
+ unsigned int o_ = (oldf); \
+ if ( (o_) & _PAGE_GLOBAL ) \
+ flush_flags |= FLUSH_TLB_GLOBAL; \
+ if ( (flags & _PAGE_PRESENT) && \
+ (((o_) ^ flags) & PAGE_CACHE_ATTRS) ) \
+ flush_flags |= FLUSH_CACHE; \
+} while (0)
+
while ( nr_mfns != 0 )
{
l3_pgentry_t ol3e, *pl3e = virt_to_xen_l3e(virt);
@@ -5465,11 +5474,7 @@ int map_pages_to_xen(
if ( l3e_get_flags(ol3e) & _PAGE_PSE )
{
- if ( l3e_get_flags(ol3e) & _PAGE_GLOBAL )
- flush_flags |= FLUSH_TLB_GLOBAL;
- if ( (lNf_to_l1f(l3e_get_flags(ol3e)) ^ flags) &
- PAGE_CACHE_ATTRS )
- flush_flags |= FLUSH_CACHE;
+ flush_flags(lNf_to_l1f(l3e_get_flags(ol3e)));
flush_area(virt, flush_flags);
}
else
@@ -5481,27 +5486,14 @@ int map_pages_to_xen(
if ( !(l2e_get_flags(ol2e) & _PAGE_PRESENT) )
continue;
if ( l2e_get_flags(ol2e) & _PAGE_PSE )
- {
- if ( l2e_get_flags(ol2e) & _PAGE_GLOBAL )
- flush_flags |= FLUSH_TLB_GLOBAL;
- if ( (lNf_to_l1f(l2e_get_flags(ol2e)) ^ flags) &
- PAGE_CACHE_ATTRS )
- flush_flags |= FLUSH_CACHE;
- }
+ flush_flags(lNf_to_l1f(l2e_get_flags(ol2e)));
else
{
unsigned int j;
pl1e = l2e_to_l1e(ol2e);
for ( j = 0; j < L1_PAGETABLE_ENTRIES; j++ )
- {
- ol1e = pl1e[j];
- if ( l1e_get_flags(ol1e) & _PAGE_GLOBAL )
- flush_flags |= FLUSH_TLB_GLOBAL;
- if ( (l1e_get_flags(ol1e) ^ flags) &
- PAGE_CACHE_ATTRS )
- flush_flags |= FLUSH_CACHE;
- }
+ flush_flags(l1e_get_flags(pl1e[j]));
}
}
flush_area(virt, flush_flags);
@@ -5595,24 +5587,14 @@ int map_pages_to_xen(
if ( l2e_get_flags(ol2e) & _PAGE_PSE )
{
- if ( l2e_get_flags(ol2e) & _PAGE_GLOBAL )
- flush_flags |= FLUSH_TLB_GLOBAL;
- if ( (lNf_to_l1f(l2e_get_flags(ol2e)) ^ flags) &
- PAGE_CACHE_ATTRS )
- flush_flags |= FLUSH_CACHE;
+ flush_flags(lNf_to_l1f(l2e_get_flags(ol2e)));
flush_area(virt, flush_flags);
}
else
{
pl1e = l2e_to_l1e(ol2e);
for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
- {
- if ( l1e_get_flags(pl1e[i]) & _PAGE_GLOBAL )
- flush_flags |= FLUSH_TLB_GLOBAL;
- if ( (l1e_get_flags(pl1e[i]) ^ flags) &
- PAGE_CACHE_ATTRS )
- flush_flags |= FLUSH_CACHE;
- }
+ flush_flags(l1e_get_flags(pl1e[i]));
flush_area(virt, flush_flags);
free_xen_pagetable(pl1e);
}
@@ -5687,10 +5669,8 @@ int map_pages_to_xen(
if ( (l1e_get_flags(ol1e) & _PAGE_PRESENT) )
{
unsigned int flush_flags = FLUSH_TLB | FLUSH_ORDER(0);
- if ( l1e_get_flags(ol1e) & _PAGE_GLOBAL )
- flush_flags |= FLUSH_TLB_GLOBAL;
- if ( (l1e_get_flags(ol1e) ^ flags) & PAGE_CACHE_ATTRS )
- flush_flags |= FLUSH_CACHE;
+
+ flush_flags(l1e_get_flags(ol1e));
flush_area(virt, flush_flags);
}
@@ -5766,6 +5746,8 @@ int map_pages_to_xen(
}
}
+#undef flush_flags
+
return 0;
}
@@ -5908,6 +5890,8 @@ void destroy_xen_mappings(unsigned long s, unsigned long e)
flush_area(NULL, FLUSH_TLB_GLOBAL);
}
+#undef flush_area
+
void __set_fixmap(
enum fixed_addresses idx, unsigned long mfn, unsigned long flags)
{