diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index c6c6c942d8..417a0e82ba 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -763,6 +763,30 @@ static void __init assign_static_memory_11(struct domain *d, } #ifdef CONFIG_STATIC_SHM +static int __init acquire_nr_borrower_domain(struct domain *d, + paddr_t pbase, paddr_t psize, + unsigned long *nr_borrowers) +{ + unsigned int bank; + + /* Iterate reserved memory to find requested shm bank. */ + for ( bank = 0 ; bank < bootinfo.reserved_mem.nr_banks; bank++ ) + { + paddr_t bank_start = bootinfo.reserved_mem.bank[bank].start; + paddr_t bank_size = bootinfo.reserved_mem.bank[bank].size; + + if ( (pbase == bank_start) && (psize == bank_size) ) + break; + } + + if ( bank == bootinfo.reserved_mem.nr_banks ) + return -ENOENT; + + *nr_borrowers = bootinfo.reserved_mem.bank[bank].nr_shm_borrowers; + + return 0; +} + /* * This function checks whether the static shared memory region is * already allocated to dom_io. @@ -829,6 +853,8 @@ static int __init assign_shared_memory(struct domain *d, { mfn_t smfn; int ret = 0; + unsigned long nr_pages, nr_borrowers, i; + struct page_info *page; dprintk(XENLOG_INFO, "%pd: allocate static shared memory BANK %#"PRIpaddr"-%#"PRIpaddr".\n", @@ -842,6 +868,7 @@ static int __init assign_shared_memory(struct domain *d, * DOMID_IO is not auto-translated (i.e. it sees RAM 1:1). So we do not need * to create mapping in the P2M. */ + nr_pages = PFN_DOWN(psize); if ( d != dom_io ) { ret = guest_physmap_add_pages(d, gaddr_to_gfn(gbase), smfn, @@ -853,6 +880,39 @@ static int __init assign_shared_memory(struct domain *d, } } + /* + * Get the right amount of references per page, which is the number of + * borrower domains. + */ + ret = acquire_nr_borrower_domain(d, pbase, psize, &nr_borrowers); + if ( ret ) + return ret; + + /* + * Instead of letting borrower domain get a page ref, we add as many + * additional reference as the number of borrowers when the owner + * is allocated, since there is a chance that owner is created + * after borrower. + * So if the borrower is created first, it will cause adding pages + * in the P2M without reference. + */ + page = mfn_to_page(smfn); + for ( i = 0; i < nr_pages; i++ ) + { + if ( !get_page_nr(page + i, d, nr_borrowers) ) + { + printk(XENLOG_ERR + "Failed to add %lu references to page %"PRI_mfn".\n", + nr_borrowers, mfn_x(smfn) + i); + goto fail; + } + } + + return 0; + + fail: + while ( --i >= 0 ) + put_page_nr(page + i, nr_borrowers); return ret; }