# HG changeset patch # User Keir Fraser # Date 1232986782 0 # Node ID 39517e863cc89a085341e1d53317aaa7ceddd127 # Parent 055c589f4791811797867736857b08fdd0fd6d49 x86_64: Widen page counts to avoid overflow. References: bnc#470949 Signed-off-by: Keir Fraser # HG changeset patch # User Keir Fraser # Date 1232988758 0 # Node ID 728d1892f0e24c2531df2d61a2d95177400ceb17 # Parent 90909b81b3b9cf9b303e2bc457580603da3ac7fd x86: Clean up shadow_page_info after page_info changes. Signed-off-by: Keir Fraser # HG changeset patch # User Keir Fraser # Date 1233056759 0 # Node ID 6e623569455c08b57e43e3355f6809b3a4ba0707 # Parent 7b56dbd1b439e0996083810489398cb51dc43aa6 x86: clean up struct page_info Remove the now unnecessary (and leading to misalignment of cpumask on x86-64) 'packed' attributes. Signed-off-by: Jan Beulich --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -143,7 +143,7 @@ void dump_pageframe_info(struct domain * { list_for_each_entry ( page, &d->page_list, list ) { - printk(" DomPage %p: caf=%08x, taf=%" PRtype_info "\n", + printk(" DomPage %p: caf=%08lx, taf=%" PRtype_info "\n", _p(page_to_mfn(page)), page->count_info, page->u.inuse.type_info); } @@ -151,7 +151,7 @@ void dump_pageframe_info(struct domain * list_for_each_entry ( page, &d->xenpage_list, list ) { - printk(" XenPage %p: caf=%08x, taf=%" PRtype_info "\n", + printk(" XenPage %p: caf=%08lx, taf=%" PRtype_info "\n", _p(page_to_mfn(page)), page->count_info, page->u.inuse.type_info); } --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -714,8 +714,8 @@ get_page_from_l1e( else if ( pte_flags_to_cacheattr(l1f) != ((page->count_info >> PGC_cacheattr_base) & 7) ) { - uint32_t x, nx, y = page->count_info; - uint32_t cacheattr = pte_flags_to_cacheattr(l1f); + unsigned long x, nx, y = page->count_info; + unsigned long cacheattr = pte_flags_to_cacheattr(l1f); if ( is_xen_heap_page(page) ) { @@ -1869,7 +1869,7 @@ static int mod_l4_entry(l4_pgentry_t *pl void put_page(struct page_info *page) { - u32 nx, x, y = page->count_info; + unsigned long nx, x, y = page->count_info; do { x = y; @@ -1887,7 +1887,7 @@ void put_page(struct page_info *page) int get_page(struct page_info *page, struct domain *domain) { - u32 x, y = page->count_info; + unsigned long x, y = page->count_info; do { x = y; @@ -1906,7 +1906,7 @@ int get_page(struct page_info *page, str fail: if ( !_shadow_mode_refcounts(domain) && !domain->is_dying ) gdprintk(XENLOG_INFO, - "Error pfn %lx: rd=%p, od=%p, caf=%08x, taf=%" PRtype_info, + "Error pfn %lx: rd=%p, od=%p, caf=%08lx, taf=%" PRtype_info, page_to_mfn(page), domain, page_get_owner(page), y, page->u.inuse.type_info); return 0; @@ -1922,7 +1922,7 @@ int get_page(struct page_info *page, str */ static void get_page_light(struct page_info *page) { - u32 x, nx, y = page->count_info; + unsigned long x, nx, y = page->count_info; do { x = y; @@ -1963,7 +1963,7 @@ static int alloc_page_type(struct page_i rc = alloc_segdesc_page(page); break; default: - printk("Bad type in alloc_page_type %lx t=%" PRtype_info " c=%x\n", + printk("Bad type in alloc_page_type %lx t=%" PRtype_info " c=%lx\n", type, page->u.inuse.type_info, page->count_info); rc = -EINVAL; @@ -1987,7 +1987,7 @@ static int alloc_page_type(struct page_i { ASSERT(rc < 0); MEM_LOG("Error while validating mfn %lx (pfn %lx) for type %" - PRtype_info ": caf=%08x taf=%" PRtype_info, + PRtype_info ": caf=%08lx taf=%" PRtype_info, page_to_mfn(page), get_gpfn_from_mfn(page_to_mfn(page)), type, page->count_info, page->u.inuse.type_info); page->u.inuse.type_info = 0; @@ -3144,7 +3144,7 @@ static int create_grant_pte_mapping( void *va; unsigned long gmfn, mfn; struct page_info *page; - u32 type; + unsigned long type; l1_pgentry_t ol1e; struct domain *d = v->domain; @@ -3205,7 +3205,7 @@ static int destroy_grant_pte_mapping( void *va; unsigned long gmfn, mfn; struct page_info *page; - u32 type; + unsigned long type; l1_pgentry_t ol1e; gmfn = addr >> PAGE_SHIFT; @@ -3431,7 +3431,7 @@ int replace_grant_host_mapping( int steal_page( struct domain *d, struct page_info *page, unsigned int memflags) { - u32 x, y; + unsigned long x, y; spin_lock(&d->page_alloc_lock); @@ -3468,7 +3468,7 @@ int steal_page( fail: spin_unlock(&d->page_alloc_lock); - MEM_LOG("Bad page %p: ed=%p(%u), sd=%p, caf=%08x, taf=%" PRtype_info, + MEM_LOG("Bad page %p: ed=%p(%u), sd=%p, caf=%08lx, taf=%" PRtype_info, (void *)page_to_mfn(page), d, d->domain_id, page_get_owner(page), page->count_info, page->u.inuse.type_info); return -1; --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -166,7 +166,7 @@ void hap_free_p2m_page(struct domain *d, ASSERT(page_get_owner(pg) == d); /* Should have just the one ref we gave it in alloc_p2m_page() */ if ( (pg->count_info & PGC_count_mask) != 1 ) - HAP_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n", + HAP_ERROR("Odd p2m page count c=%#lx t=%"PRtype_info"\n", pg->count_info, pg->u.inuse.type_info); pg->count_info = 0; /* Free should not decrement domain's total allocation, since --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -1678,7 +1678,7 @@ shadow_free_p2m_page(struct domain *d, s /* Should have just the one ref we gave it in alloc_p2m_page() */ if ( (pg->count_info & PGC_count_mask) != 1 ) { - SHADOW_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n", + SHADOW_ERROR("Odd p2m page count c=%#lx t=%"PRtype_info"\n", pg->count_info, pg->u.inuse.type_info); } pg->count_info = 0; @@ -1796,14 +1796,21 @@ static unsigned int sh_set_allocation(st sp = list_entry(d->arch.paging.shadow.freelists[order].next, struct shadow_page_info, list); list_del(&sp->list); -#if defined(__x86_64__) /* - * Re-instate lock field which we overwrite with shadow_page_info. - * This was safe, since the lock is only used on guest pages. + * The pages were allocated anonymously, but the owner field + * may get overwritten, so need to clear it here. */ for ( j = 0; j < 1U << order; j++ ) + { + page_set_owner(&((struct page_info *)sp)[j], NULL); +#if defined(__x86_64__) + /* + * Re-instate lock field which we overwrite with shadow_page_info. + * This was safe, since the lock is only used on guest pages. + */ spin_lock_init(&((struct page_info *)sp)[j].lock); #endif + } d->arch.paging.shadow.free_pages -= 1 << order; d->arch.paging.shadow.total_pages -= 1 << order; free_domheap_pages((struct page_info *)sp, order); @@ -2516,7 +2523,7 @@ int sh_remove_all_mappings(struct vcpu * && (page->u.inuse.type_info & PGT_count_mask) == 0) ) { SHADOW_ERROR("can't find all mappings of mfn %lx: " - "c=%08x t=%08lx\n", mfn_x(gmfn), + "c=%08lx t=%08lx\n", mfn_x(gmfn), page->count_info, page->u.inuse.type_info); } } @@ -3591,7 +3598,6 @@ int shadow_track_dirty_vram(struct domai for ( i = 0; i < nr; i++ ) { mfn_t mfn = gfn_to_mfn(d, begin_pfn + i, &t); struct page_info *page; - u32 count_info; int dirty = 0; paddr_t sl1ma = d->dirty_vram->sl1ma[i]; @@ -3602,8 +3608,7 @@ int shadow_track_dirty_vram(struct domai else { page = mfn_to_page(mfn); - count_info = page->u.inuse.type_info & PGT_count_mask; - switch (count_info) + switch (page->u.inuse.type_info & PGT_count_mask) { case 0: /* No guest reference, nothing to track. */ --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -1334,9 +1334,8 @@ static inline void shadow_vram_get_l1e(s if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) ) { unsigned long i = gfn - d->dirty_vram->begin_pfn; struct page_info *page = mfn_to_page(mfn); - u32 count_info = page->u.inuse.type_info & PGT_count_mask; - if ( count_info == 1 ) + if ( (page->u.inuse.type_info & PGT_count_mask) == 1 ) /* Initial guest reference, record it */ d->dirty_vram->sl1ma[i] = pfn_to_paddr(mfn_x(sl1mfn)) | ((unsigned long)sl1e & ~PAGE_MASK); @@ -1362,12 +1361,11 @@ static inline void shadow_vram_put_l1e(s if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) ) { unsigned long i = gfn - d->dirty_vram->begin_pfn; struct page_info *page = mfn_to_page(mfn); - u32 count_info = page->u.inuse.type_info & PGT_count_mask; int dirty = 0; paddr_t sl1ma = pfn_to_paddr(mfn_x(sl1mfn)) | ((unsigned long)sl1e & ~PAGE_MASK); - if ( count_info == 1 ) { + if ( (page->u.inuse.type_info & PGT_count_mask) == 1 ) { /* Last reference */ if ( d->dirty_vram->sl1ma[i] == INVALID_PADDR ) { /* We didn't know it was that one, let's say it is dirty */ --- a/xen/arch/x86/mm/shadow/private.h +++ b/xen/arch/x86/mm/shadow/private.h @@ -201,12 +201,11 @@ struct shadow_page_info u32 tlbflush_timestamp; }; struct { - unsigned int type:5; /* What kind of shadow is this? */ - unsigned int pinned:1; /* Is the shadow pinned? */ - unsigned int count:26; /* Reference count */ - u32 mbz; /* Must be zero: this is where the - * owner field lives in page_info */ - } __attribute__((packed)); + unsigned long mbz; /* Must be zero: count_info is here. */ + unsigned long type:5; /* What kind of shadow is this? */ + unsigned long pinned:1; /* Is the shadow pinned? */ + unsigned long count:26; /* Reference count */ + }; union { /* For unused shadow pages, a list of pages of this order; for * pinnable shadows, if pinned, a list of other pinned shadows @@ -229,7 +228,7 @@ static inline void shadow_check_page_str BUILD_BUG_ON(sizeof (struct shadow_page_info) != sizeof (struct page_info)); BUILD_BUG_ON(offsetof(struct shadow_page_info, mbz) != - offsetof(struct page_info, u.inuse._domain)); + offsetof(struct page_info, count_info)); }; /* Shadow type codes */ --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c @@ -159,15 +159,6 @@ void __init subarch_init_memory(void) unsigned long m2p_start_mfn; unsigned int i, j; - /* - * We are rather picky about the layout of 'struct page_info'. The - * count_info and domain fields must be adjacent, as we perform atomic - * 64-bit operations on them. Also, just for sanity, we assert the size - * of the structure here. - */ - BUILD_BUG_ON(offsetof(struct page_info, u.inuse._domain) != - (offsetof(struct page_info, count_info) + sizeof(u32))); - BUILD_BUG_ON((offsetof(struct page_info, count_info) & 7) != 0); BUILD_BUG_ON(sizeof(struct page_info) != 24); /* M2P table is mappable read-only by privileged domains. */ --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -225,17 +225,6 @@ void __init subarch_init_memory(void) l3_pgentry_t l3e; l2_pgentry_t l2e; - /* - * We are rather picky about the layout of 'struct page_info'. The - * count_info and domain fields must be adjacent, as we perform atomic - * 64-bit operations on them. - */ - BUILD_BUG_ON(offsetof(struct page_info, u.inuse._domain) != - (offsetof(struct page_info, count_info) + sizeof(u32))); - BUILD_BUG_ON((offsetof(struct page_info, count_info) & 7) != 0); - BUILD_BUG_ON(sizeof(struct page_info) != - (32 + BITS_TO_LONGS(NR_CPUS)*sizeof(long))); - /* M2P table is mappable read-only by privileged domains. */ for ( v = RDWR_MPT_VIRT_START; v != RDWR_MPT_VIRT_END; --- a/xen/common/xenoprof.c +++ b/xen/common/xenoprof.c @@ -142,8 +142,8 @@ share_xenoprof_page_with_guest(struct do struct page_info *page = mfn_to_page(mfn + i); if ( (page->count_info & (PGC_allocated|PGC_count_mask)) != 0 ) { - gdprintk(XENLOG_INFO, "mfn 0x%lx page->count_info 0x%x\n", - mfn + i, page->count_info); + gdprintk(XENLOG_INFO, "mfn 0x%lx page->count_info 0x%lx\n", + mfn + i, (unsigned long)page->count_info); return -EBUSY; } page_set_owner(page, NULL); --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -23,7 +23,7 @@ struct page_info struct list_head list; /* Reference count and various PGC_xxx flags and fields. */ - u32 count_info; + unsigned long count_info; /* Context-dependent fields follow... */ union { @@ -34,7 +34,7 @@ struct page_info u32 _domain; /* pickled format */ /* Type reference count and various PGT_xxx flags and fields. */ unsigned long type_info; - } __attribute__ ((packed)) inuse; + } inuse; /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */ struct { @@ -42,7 +42,7 @@ struct page_info u32 order; /* Mask of possibly-tainted TLBs. */ cpumask_t cpumask; - } __attribute__ ((packed)) free; + } free; } u; @@ -102,48 +102,53 @@ struct page_info }; }; +#define PG_shift(idx) (BITS_PER_LONG - (idx)) +#define PG_mask(x, idx) (x ## UL << PG_shift(idx)) + /* The following page types are MUTUALLY EXCLUSIVE. */ -#define PGT_none (0U<<29) /* no special uses of this page */ -#define PGT_l1_page_table (1U<<29) /* using this page as an L1 page table? */ -#define PGT_l2_page_table (2U<<29) /* using this page as an L2 page table? */ -#define PGT_l3_page_table (3U<<29) /* using this page as an L3 page table? */ -#define PGT_l4_page_table (4U<<29) /* using this page as an L4 page table? */ -#define PGT_seg_desc_page (5U<<29) /* using this page in a GDT/LDT? */ -#define PGT_writable_page (7U<<29) /* has writable mappings of this page? */ -#define PGT_type_mask (7U<<29) /* Bits 29-31. */ +#define PGT_none PG_mask(0, 3) /* no special uses of this page */ +#define PGT_l1_page_table PG_mask(1, 3) /* using as an L1 page table? */ +#define PGT_l2_page_table PG_mask(2, 3) /* using as an L2 page table? */ +#define PGT_l3_page_table PG_mask(3, 3) /* using as an L3 page table? */ +#define PGT_l4_page_table PG_mask(4, 3) /* using as an L4 page table? */ +#define PGT_seg_desc_page PG_mask(5, 3) /* using this page in a GDT/LDT? */ +#define PGT_writable_page PG_mask(7, 3) /* has writable mappings? */ +#define PGT_type_mask PG_mask(7, 3) /* Bits 29-31. */ /* Owning guest has pinned this page to its current type? */ -#define _PGT_pinned 28 -#define PGT_pinned (1U<<_PGT_pinned) +#define _PGT_pinned PG_shift(4) +#define PGT_pinned PG_mask(1, 4) /* Has this page been validated for use as its current type? */ -#define _PGT_validated 27 -#define PGT_validated (1U<<_PGT_validated) +#define _PGT_validated PG_shift(5) +#define PGT_validated PG_mask(1, 5) /* PAE only: is this an L2 page directory containing Xen-private mappings? */ -#define _PGT_pae_xen_l2 26 -#define PGT_pae_xen_l2 (1U<<_PGT_pae_xen_l2) +#define _PGT_pae_xen_l2 PG_shift(6) +#define PGT_pae_xen_l2 PG_mask(1, 6) /* Has this page been *partially* validated for use as its current type? */ -#define _PGT_partial 25 -#define PGT_partial (1U<<_PGT_partial) +#define _PGT_partial PG_shift(7) +#define PGT_partial PG_mask(1, 7) - /* 25-bit count of uses of this frame as its current type. */ -#define PGT_count_mask ((1U<<25)-1) + /* Count of uses of this frame as its current type. */ +#define PGT_count_width PG_shift(7) +#define PGT_count_mask ((1UL<