tools/dombuilder: Don't allocate dom->p2m_host[] for translated domains

xc_dom_p2m() and dom->p2m_host[] implement a linear transform for translated
domains, but waste a substantial chunk of RAM doing so.

ARM literally never reads dom->p2m_host[] (because of the xc_dom_translated()
short circuit in xc_dom_p2m()).  Drop it all.

x86 HVM does use dom->p2m_host[] for xc_domain_populate_physmap_exact() calls
when populating 4k pages.  Reuse the same tactic from 2M/1G ranges and use an
on-stack array instead.  Drop the memory allocation.

x86 PV guests do use dom->p2m_host[] as a non-identity transform.  Rename the
field to pv_p2m to make it clear it is PV-only.

No change in the constructed guests.

Reported-by: Varad Gautam <vrd@amazon.de>
Reported-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Wei Liu <wl@xen.org>
This commit is contained in:
Andrew Cooper committed 2020-01-07 12:46:03 +00:00
1 parent d9b16799f6
commit 97e34ad22d
4 files changed
+54 -79

No files matched your search

+14 -14
View File
@@ -87,17 +87,17 @@ static void do_exchange(struct xc_dom_image *dom, xen_pfn_t target_pfn, xen_pfn_
xen_pfn_t target_mfn;
for (source_pfn = 0; source_pfn < start_info.nr_pages; source_pfn++)
if (dom->p2m_host[source_pfn] == source_mfn)
if (dom->pv_p2m[source_pfn] == source_mfn)
break;
ASSERT(source_pfn < start_info.nr_pages);
target_mfn = dom->p2m_host[target_pfn];
target_mfn = dom->pv_p2m[target_pfn];
/* Put target MFN at source PFN */
dom->p2m_host[source_pfn] = target_mfn;
dom->pv_p2m[source_pfn] = target_mfn;
/* Put source MFN at target PFN */
dom->p2m_host[target_pfn] = source_mfn;
dom->pv_p2m[target_pfn] = source_mfn;
}
int kexec_allocate(struct xc_dom_image *dom)
@@ -110,7 +110,7 @@ int kexec_allocate(struct xc_dom_image *dom)
pages_moved2pfns = realloc(pages_moved2pfns, new_allocated * sizeof(*pages_moved2pfns));
for (i = allocated; i < new_allocated; i++) {
/* Exchange old page of PFN i with a newly allocated page. */
xen_pfn_t old_mfn = dom->p2m_host[i];
xen_pfn_t old_mfn = dom->pv_p2m[i];
xen_pfn_t new_pfn;
xen_pfn_t new_mfn;
@@ -122,7 +122,7 @@ int kexec_allocate(struct xc_dom_image *dom)
/*
* If PFN of newly allocated page (new_pfn) is less then currently
* requested PFN (i) then look for relevant PFN/MFN pair. In this
* situation dom->p2m_host[new_pfn] no longer contains proper MFN
* situation dom->pv_p2m[new_pfn] no longer contains proper MFN
* because original page with new_pfn was moved earlier
* to different location.
*/
@@ -132,10 +132,10 @@ int kexec_allocate(struct xc_dom_image *dom)
pages_moved2pfns[i] = new_pfn;
/* Put old page at new PFN */
dom->p2m_host[new_pfn] = old_mfn;
dom->pv_p2m[new_pfn] = old_mfn;
/* Put new page at PFN i */
dom->p2m_host[i] = new_mfn;
dom->pv_p2m[i] = new_mfn;
}
allocated = new_allocated;
@@ -282,11 +282,11 @@ void kexec(void *kernel, long kernel_size, void *module, long module_size, char
dom->p2m_size = dom->total_pages;
/* setup initial p2m */
dom->p2m_host = malloc(sizeof(*dom->p2m_host) * dom->p2m_size);
dom->pv_p2m = malloc(sizeof(*dom->pv_p2m) * dom->p2m_size);
/* Start with our current P2M */
for (i = 0; i < dom->p2m_size; i++)
dom->p2m_host[i] = pfn_to_mfn(i);
dom->pv_p2m[i] = pfn_to_mfn(i);
if ( (rc = xc_dom_build_image(dom)) != 0 ) {
printk("xc_dom_build_image returned %d\n", rc);
@@ -373,7 +373,7 @@ void kexec(void *kernel, long kernel_size, void *module, long module_size, char
_boot_oldpdmfn = virt_to_mfn(start_info.pt_base);
DEBUG("boot old pd mfn %lx\n", _boot_oldpdmfn);
DEBUG("boot pd virt %lx\n", dom->pgtables_seg.vstart);
_boot_pdmfn = dom->p2m_host[PHYS_PFN(dom->pgtables_seg.vstart - dom->parms.virt_base)];
_boot_pdmfn = dom->pv_p2m[PHYS_PFN(dom->pgtables_seg.vstart - dom->parms.virt_base)];
DEBUG("boot pd mfn %lx\n", _boot_pdmfn);
_boot_stack = _boot_target + PAGE_SIZE;
DEBUG("boot stack %lx\n", _boot_stack);
@@ -384,13 +384,13 @@ void kexec(void *kernel, long kernel_size, void *module, long module_size, char
/* Keep only useful entries */
for (nr_m2p_updates = pfn = 0; pfn < start_info.nr_pages; pfn++)
if (dom->p2m_host[pfn] != pfn_to_mfn(pfn))
if (dom->pv_p2m[pfn] != pfn_to_mfn(pfn))
nr_m2p_updates++;
m2p_updates = malloc(sizeof(*m2p_updates) * nr_m2p_updates);
for (i = pfn = 0; pfn < start_info.nr_pages; pfn++)
if (dom->p2m_host[pfn] != pfn_to_mfn(pfn)) {
m2p_updates[i].ptr = PFN_PHYS(dom->p2m_host[pfn]) | MMU_MACHPHYS_UPDATE;
if (dom->pv_p2m[pfn] != pfn_to_mfn(pfn)) {
m2p_updates[i].ptr = PFN_PHYS(dom->pv_p2m[pfn]) | MMU_MACHPHYS_UPDATE;
m2p_updates[i].val = pfn;
i++;
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.