Assuming that the accounting for IOMMU page tables will also take care
of the P2M needs was wrong: dom0_paging_pages() can determine a far
higher value, high enough for the system to run out of memory while
setting up Dom0. Hence in the case of shared page tables the larger of
the two values needs to be used (without shared page tables the sum of
both continues to be applicable).
While there also account for two further aspects in the PV case: With
"iommu=dom0-passthrough" no IOMMU page tables would get allocated, so
none need accounting for. And if shadow mode is to be enabled, setting
aside a suitable amount for the P2M pool to get populated is also
necessary (i.e. similar to the non-shared-page-tables case of PVH).
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/dom0_build.c
+++ b/xen/arch/x86/dom0_build.c
@@ -318,7 +318,7 @@ unsigned long __init dom0_compute_nr_pag
struct domain *d, struct elf_dom_parms *parms, unsigned long initrd_len)
{
nodeid_t node;
- unsigned long avail = 0, nr_pages, min_pages, max_pages;
+ unsigned long avail = 0, nr_pages, min_pages, max_pages, iommu_pages = 0;
bool need_paging;
/* The ordering of operands is to work around a clang5 issue. */
@@ -337,18 +337,23 @@ unsigned long __init dom0_compute_nr_pag
avail -= d->max_vcpus - 1;
/* Reserve memory for iommu_dom0_init() (rough estimate). */
- if ( is_iommu_enabled(d) )
+ if ( is_iommu_enabled(d) && !iommu_hwdom_passthrough )
{
unsigned int s;
for ( s = 9; s < BITS_PER_LONG; s += 9 )
- avail -= max_pdx >> s;
+ iommu_pages += max_pdx >> s;
+
+ avail -= iommu_pages;
}
- need_paging = is_hvm_domain(d) &&
- (!iommu_use_hap_pt(d) || !paging_mode_hap(d));
+ need_paging = is_hvm_domain(d)
+ ? !iommu_use_hap_pt(d) || !paging_mode_hap(d)
+ : opt_dom0_shadow;
for ( ; ; need_paging = false )
{
+ unsigned long paging_pages;
+
nr_pages = get_memsize(&dom0_size, avail);
min_pages = get_memsize(&dom0_min_size, avail);
max_pages = get_memsize(&dom0_max_size, avail);
@@ -377,11 +382,20 @@ unsigned long __init dom0_compute_nr_pag
nr_pages = min(nr_pages, max_pages);
nr_pages = min(nr_pages, avail);
- if ( !need_paging )
- break;
+ paging_pages = paging_mode_enabled(d) || need_paging
+ ? dom0_paging_pages(d, nr_pages) : 0;
/* Reserve memory for shadow or HAP. */
- avail -= dom0_paging_pages(d, nr_pages);
+ if ( !need_paging )
+ {
+ if ( paging_pages <= iommu_pages )
+ break;
+
+ avail -= paging_pages - iommu_pages;
+ }
+ else
+ avail -= paging_pages;
+ iommu_pages = paging_pages;
}
if ( is_pv_domain(d) &&
On 30/08/2021 14:03, Jan Beulich wrote: > Assuming that the accounting for IOMMU page tables will also take care > of the P2M needs was wrong: dom0_paging_pages() can determine a far > higher value, high enough for the system to run out of memory while > setting up Dom0. Hence in the case of shared page tables the larger of > the two values needs to be used (without shared page tables the sum of > both continues to be applicable). I'm afraid that I can't follow this at all. What causes the system to run out of RAM while constructing dom0? > > While there also account for two further aspects in the PV case: With > "iommu=dom0-passthrough" no IOMMU page tables would get allocated, so > none need accounting for. And if shadow mode is to be enabled, setting > aside a suitable amount for the P2M pool to get populated is also > necessary (i.e. similar to the non-shared-page-tables case of PVH). > > Signed-off-by: Jan Beulich <jbeulich@suse.com> > > --- a/xen/arch/x86/dom0_build.c > +++ b/xen/arch/x86/dom0_build.c > @@ -318,7 +318,7 @@ unsigned long __init dom0_compute_nr_pag > struct domain *d, struct elf_dom_parms *parms, unsigned long initrd_len) > { > nodeid_t node; > - unsigned long avail = 0, nr_pages, min_pages, max_pages; > + unsigned long avail = 0, nr_pages, min_pages, max_pages, iommu_pages = 0; > bool need_paging; > > /* The ordering of operands is to work around a clang5 issue. */ > @@ -337,18 +337,23 @@ unsigned long __init dom0_compute_nr_pag > avail -= d->max_vcpus - 1; > > /* Reserve memory for iommu_dom0_init() (rough estimate). */ > - if ( is_iommu_enabled(d) ) > + if ( is_iommu_enabled(d) && !iommu_hwdom_passthrough ) > { > unsigned int s; > > for ( s = 9; s < BITS_PER_LONG; s += 9 ) > - avail -= max_pdx >> s; > + iommu_pages += max_pdx >> s; > + > + avail -= iommu_pages; > } > > - need_paging = is_hvm_domain(d) && > - (!iommu_use_hap_pt(d) || !paging_mode_hap(d)); > + need_paging = is_hvm_domain(d) > + ? !iommu_use_hap_pt(d) || !paging_mode_hap(d) > + : opt_dom0_shadow; As per patch 4, this condition needs adjusting. ~Andrew > for ( ; ; need_paging = false ) > { > + unsigned long paging_pages; > + > nr_pages = get_memsize(&dom0_size, avail); > min_pages = get_memsize(&dom0_min_size, avail); > max_pages = get_memsize(&dom0_max_size, avail); > @@ -377,11 +382,20 @@ unsigned long __init dom0_compute_nr_pag > nr_pages = min(nr_pages, max_pages); > nr_pages = min(nr_pages, avail); > > - if ( !need_paging ) > - break; > + paging_pages = paging_mode_enabled(d) || need_paging > + ? dom0_paging_pages(d, nr_pages) : 0; > > /* Reserve memory for shadow or HAP. */ > - avail -= dom0_paging_pages(d, nr_pages); > + if ( !need_paging ) > + { > + if ( paging_pages <= iommu_pages ) > + break; > + > + avail -= paging_pages - iommu_pages; > + } > + else > + avail -= paging_pages; > + iommu_pages = paging_pages; > } > > if ( is_pv_domain(d) && >
On 31.08.2021 16:07, Andrew Cooper wrote: > On 30/08/2021 14:03, Jan Beulich wrote: >> Assuming that the accounting for IOMMU page tables will also take care >> of the P2M needs was wrong: dom0_paging_pages() can determine a far >> higher value, high enough for the system to run out of memory while >> setting up Dom0. Hence in the case of shared page tables the larger of >> the two values needs to be used (without shared page tables the sum of >> both continues to be applicable). > > I'm afraid that I can't follow this at all. > > What causes the system to run out of RAM while constructing dom0? Without any "dom0_mem=" we set aside 128Mb. In my .config that was in use I default to "dom0_mem=-255". Yet this was still far from enough to cover the gap between the original IOMMU page table accounting and the value returned from dom0_paging_pages(). Since this is what also gets used to actually populate Dom0's P2M pool, with the P2M pool populated there wasn't enough RAM anymore to reach the Dom0 size which dom0_compute_nr_pages() did establish. Putting it in a simplified formula, what we did so far when sharing page tables was RAM = total - IOMMU but what we need is RAM = total - max(IOMMU, P2M) In the non-shared case we already correctly did RAM = total - (IOMMU + P2M) Jan
© 2016 - 2024 Red Hat, Inc.