@@ -761,6 +761,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.
@@ -827,6 +851,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",
@@ -840,6 +866,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,
@@ -851,6 +878,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;
}