aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-06-13 10:49:01 +0200
committerJan Beulich <jbeulich@suse.com>2013-06-13 10:49:01 +0200
commit61c6dfce3296da2643c4c4f90eaab6fa3c1cf8b3 (patch)
tree9d6e3618cdb7a48691ea3edd7083af0c4ed183df
parentfd0b06689555be4855b9a70c4f4995e623168e94 (diff)
downloadxen-61c6dfce3296da2643c4c4f90eaab6fa3c1cf8b3.tar.gz
xen-61c6dfce3296da2643c4c4f90eaab6fa3c1cf8b3.tar.bz2
xen-61c6dfce3296da2643c4c4f90eaab6fa3c1cf8b3.zip
x86: fix map_domain_page() last resort fallback
Guests with vCPU count not divisible by 4 have unused bits in the last word of their inuse bitmap, and the garbage collection code therefore would get mislead believing that some entries were actually recoverable for use. Also use an earlier established local variable in mapcache_vcpu_init() instead of re-calculating the value (noticed while investigating the generally better option of setting those overhanging bits once during setup - this didn't work out in a simple enough fashion because the mapping getting established there isn't in the current address space, and hence the bitmap isn't directly accessible there). Reported-by: Konrad Wilk <konrad.wilk@oracle.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org>
-rw-r--r--xen/arch/x86/domain_page.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/xen/arch/x86/domain_page.c b/xen/arch/x86/domain_page.c
index efda6afd8b..9297ea07e6 100644
--- a/xen/arch/x86/domain_page.c
+++ b/xen/arch/x86/domain_page.c
@@ -110,16 +110,17 @@ void *map_domain_page(unsigned long mfn)
idx = find_next_zero_bit(dcache->inuse, dcache->entries, dcache->cursor);
if ( unlikely(idx >= dcache->entries) )
{
- unsigned long accum = 0;
+ unsigned long accum = 0, prev = 0;
/* /First/, clean the garbage map and update the inuse list. */
for ( i = 0; i < BITS_TO_LONGS(dcache->entries); i++ )
{
+ accum |= prev;
dcache->inuse[i] &= ~xchg(&dcache->garbage[i], 0);
- accum |= ~dcache->inuse[i];
+ prev = ~dcache->inuse[i];
}
- if ( accum )
+ if ( accum | (prev & BITMAP_LAST_WORD_MASK(dcache->entries)) )
idx = find_first_zero_bit(dcache->inuse, dcache->entries);
else
{
@@ -279,8 +280,7 @@ int mapcache_vcpu_init(struct vcpu *v)
if ( ents > dcache->entries )
{
/* Populate page tables. */
- int rc = create_perdomain_mapping(d, MAPCACHE_VIRT_START,
- d->max_vcpus * MAPCACHE_VCPU_ENTRIES,
+ int rc = create_perdomain_mapping(d, MAPCACHE_VIRT_START, ents,
NIL(l1_pgentry_t *), NULL);
/* Populate bit maps. */