diff options
-rw-r--r-- | xen/arch/x86/mm/paging.c | 1 | ||||
-rw-r--r-- | xen/arch/x86/mm/shadow/common.c | 12 | ||||
-rw-r--r-- | xen/include/asm-x86/paging.h | 4 |
3 files changed, 16 insertions, 1 deletions
diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index 97ac9ccf59..9fb66e65cd 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -280,6 +280,7 @@ void paging_mark_pfn_dirty(struct domain *d, pfn_t pfn) if ( unlikely(!VALID_M2P(pfn_x(pfn))) ) return; + BUILD_BUG_ON(paging_logdirty_levels() != 4); i1 = L1_LOGDIRTY_IDX(pfn); i2 = L2_LOGDIRTY_IDX(pfn); i3 = L3_LOGDIRTY_IDX(pfn); diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 1de0139742..c14a269935 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -1015,7 +1015,17 @@ bool shadow_prealloc(struct domain *d, unsigned int type, unsigned int count) if ( unlikely(d->is_dying) ) return false; - ret = _shadow_prealloc(d, shadow_size(type) * count); + count *= shadow_size(type); + /* + * Log-dirty handling may result in allocations when populating its + * tracking structures. Tie this to the caller requesting space for L1 + * shadows. + */ + if ( paging_mode_log_dirty(d) && + ((SHF_L1_ANY | SHF_FL1_ANY) & (1u << type)) ) + count += paging_logdirty_levels(); + + ret = _shadow_prealloc(d, count); if ( !ret && (!d->is_shutting_down || d->shutdown_code != SHUTDOWN_crash) ) /* * Failing to allocate memory required for shadow usage can only result in diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h index 27890791d8..c6b429c691 100644 --- a/xen/include/asm-x86/paging.h +++ b/xen/include/asm-x86/paging.h @@ -192,6 +192,10 @@ int paging_mfn_is_dirty(struct domain *d, mfn_t gmfn); #define L4_LOGDIRTY_IDX(pfn) ((pfn_x(pfn) >> (PAGE_SHIFT + 3 + PAGETABLE_ORDER * 2)) & \ (LOGDIRTY_NODE_ENTRIES-1)) +#define paging_logdirty_levels() \ + (DIV_ROUND_UP(PADDR_BITS - PAGE_SHIFT - (PAGE_SHIFT + 3), \ + PAGE_SHIFT - ilog2(sizeof(mfn_t))) + 1) + #ifdef CONFIG_HVM /* VRAM dirty tracking support */ struct sh_dirty_vram { |