Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:GA
xen.8005
5a955800-gnttab-dont-free-status-pages-on-ver-c...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 5a955800-gnttab-dont-free-status-pages-on-ver-change.patch of Package xen.8005
# Commit 38bfcc165dda5f4284d7c218b91df9e144ddd88d # Date 2018-02-27 14:07:12 +0100 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> gnttab: don't blindly free status pages upon version change There may still be active mappings, which would trigger the respective BUG_ON(). Split the loop into one dealing with the page attributes and the second (when the first fully passed) freeing the pages. Return an error if any pages still have pending references. This is part of XSA-255. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -1027,12 +1027,22 @@ int xenmem_add_to_physmap_one( mfn = INVALID_MFN; } + if ( mfn != INVALID_MFN && + gnttab_get_frame_gfn(d, status, idx) != INVALID_GFN ) + { + rc = guest_physmap_remove_page(d, + gnttab_get_frame_gfn(d, status, idx), + mfn, 0); + if ( rc ) + { + spin_unlock(&d->grant_table->lock); + return rc; + } + } + if ( mfn != INVALID_MFN ) { - if ( status ) - d->arch.grant_status_gfn[idx] = gpfn; - else - d->arch.grant_shared_gfn[idx] = gpfn; + gnttab_set_frame_gfn(d, status, idx, gpfn); t = p2m_ram_rw; } --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -1229,23 +1229,73 @@ status_alloc_failed: return -ENOMEM; } -static void +static int gnttab_unpopulate_status_frames(struct domain *d, struct grant_table *gt) { - int i; + unsigned int i; for ( i = 0; i < nr_status_frames(gt); i++ ) { struct page_info *pg = virt_to_page(gt->status[i]); + unsigned long gfn = gnttab_get_frame_gfn(d, 1, i); + + /* + * For translated domains, recovering from failure after partial + * changes were made is more complicated than it seems worth + * implementing at this time. Hence respective error paths below + * crash the domain in such a case. + */ + if ( paging_mode_translate(d) ) + { + int rc = gfn == INVALID_GFN + ? 0 + : guest_physmap_remove_page(d, gfn, page_to_mfn(pg), 0); + + if ( rc ) + { + gdprintk(XENLOG_ERR, + "Could not remove status frame %u (GFN %#lx) from P2M\n", + i, gfn); + domain_crash(d); + return rc; + } + gnttab_set_frame_gfn(d, 1, i, INVALID_GFN); + } BUG_ON(page_get_owner(pg) != d); if ( test_and_clear_bit(_PGC_allocated, &pg->count_info) ) put_page(pg); - BUG_ON(pg->count_info & ~PGC_xen_heap); + + if ( pg->count_info & ~PGC_xen_heap ) + { + if ( paging_mode_translate(d) ) + { + gdprintk(XENLOG_ERR, + "Wrong page state %#lx of status frame %u (GFN %#lx)\n", + pg->count_info, i, gfn); + domain_crash(d); + } + else + { + if ( get_page(pg, d) ) + set_bit(_PGC_allocated, &pg->count_info); + while ( i-- ) + gnttab_create_status_page(d, gt, i); + } + return -EBUSY; + } + + page_set_owner(pg, NULL); + } + + for ( i = 0; i < nr_status_frames(gt); i++ ) + { free_xenheap_page(gt->status[i]); gt->status[i] = NULL; } gt->nr_status_frames = 0; + + return 0; } int @@ -2333,8 +2383,9 @@ gnttab_set_version(XEN_GUEST_HANDLE_PARA } } - if ( op.version < 2 && gt->gt_version == 2 ) - gnttab_unpopulate_status_frames(d, gt); + if ( op.version < 2 && gt->gt_version == 2 && + (res = gnttab_unpopulate_status_frames(d, gt)) != 0 ) + goto out_unlock; /* Make sure there's no crud left over in the table from the old version. */ --- a/xen/include/asm-arm/grant_table.h +++ b/xen/include/asm-arm/grant_table.h @@ -21,6 +21,16 @@ static inline int replace_grant_supporte return 1; } +#define gnttab_set_frame_gfn(d, st, idx, gfn) \ + do { \ + ((st) ? (d)->arch.grant_status_gfn \ + : (d)->arch.grant_shared_gfn)[idx] = (gfn); \ + } while ( 0 ) + +#define gnttab_get_frame_gfn(d, st, idx) \ + ((st) ? gnttab_status_gmfn(d, (d)->grant_table, idx) \ + : gnttab_shared_gmfn(d, (d)->grant_table, idx)) + #define gnttab_create_shared_page(d, t, i) \ do { \ share_xen_page_with_guest( \ --- a/xen/include/asm-x86/grant_table.h +++ b/xen/include/asm-x86/grant_table.h @@ -18,6 +18,14 @@ int create_grant_host_mapping(uint64_t a int replace_grant_host_mapping( uint64_t addr, unsigned long frame, uint64_t new_addr, unsigned int flags); +#define gnttab_set_frame_gfn(d, st, idx, gfn) do {} while ( 0 ) +#define gnttab_get_frame_gfn(d, st, idx) ({ \ + unsigned long mfn_ = (st) ? gnttab_status_mfn((d)->grant_table, idx) \ + : gnttab_shared_mfn((d)->grant_table, idx); \ + unsigned long gpfn_ = get_gpfn_from_mfn(mfn_); \ + VALID_M2P(gpfn_) ? gpfn_ : INVALID_GFN; \ +}) + #define gnttab_create_shared_page(d, t, i) \ do { \ share_xen_page_with_guest( \ @@ -33,11 +41,11 @@ int replace_grant_host_mapping( } while ( 0 ) -#define gnttab_shared_mfn(d, t, i) \ +#define gnttab_shared_mfn(t, i) \ ((virt_to_maddr((t)->shared_raw[i]) >> PAGE_SHIFT)) #define gnttab_shared_gmfn(d, t, i) \ - (mfn_to_gmfn(d, gnttab_shared_mfn(d, t, i))) + (mfn_to_gmfn(d, gnttab_shared_mfn(t, i))) #define gnttab_status_mfn(t, i) \
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor