|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 2/7] x86/mm: Normalize X86 per-domain page counters to unsigned long
Prepare x86 for >16 TiB domains by normalizing the per-domain page counts
in paging_domain (total_pages, free_pages, p2m_pages) to unsigned long
and widen page counts in related x86 allocation functions accordingly:
- paging_domain.{total,free,p2m}_pages: unsigned int -> unsigned long
- x86/mm/shadow/common.c:
- unsigned long sh_min_allocation(d)
- unsigned long shadow_min_acceptable_pages(d)
- unsigned long shadow_get_allocation(d)
- shadow_set_allocation(unsigned long pages)
- shadow_enable(): fix narrowing from d->arch.paging.total_pages to
unsigned int
- x86/mm/hap/hap.c:
- unsigned long hap_get_allocation(d)
- hap_set_allocation(unsigned long pages)
- hap_enable(): fix narrowing from d->arch.paging.total_pages to
unsigned int
- x86/mm/paging.c:
- paging_set_allocation(unsigned long pages)
- arch_set_paging_mempool_size() don't truncate pages
Note: pages in _shadow_prealloc(), shadow_alloc(), shadow_free() and
shadow_prealloc() is intentionally kept as unsigned int. It carries
the per-shadow-entry page count from shadow_size() (uint8_t-backed,
max 4), not the pool allocation count.
Note: xen_domctl_shadow_op.mb stays uint32_t, and the domctl ABI remains
MB-based and caps at 4 PiB, replacing the 16 TiB per-domain limit.
Casts widen the mb-to-pages arithmetic to unsigned long where needed.
Suggested-by: Jan Beulich <jbeulich@xxxxxxxx>
Signed-off-by: Bernhard Kaindl <bernhard.kaindl@xxxxxxxxxx>
---
xen/arch/x86/include/asm/domain.h | 6 ++---
xen/arch/x86/include/asm/hap.h | 4 +--
xen/arch/x86/include/asm/paging.h | 2 +-
xen/arch/x86/include/asm/shadow.h | 2 +-
xen/arch/x86/mm/hap/hap.c | 19 +++++++-------
xen/arch/x86/mm/paging.c | 9 +++----
xen/arch/x86/mm/shadow/common.c | 42 +++++++++++++++----------------
7 files changed, 41 insertions(+), 43 deletions(-)
diff --git a/xen/arch/x86/include/asm/domain.h
b/xen/arch/x86/include/asm/domain.h
index 385a6666dafa..d3021a863353 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -221,9 +221,9 @@ struct paging_domain {
/* Memory allocation (common to shadow and HAP) */
struct page_list_head freelist;
- unsigned int total_pages; /* number of pages allocated */
- unsigned int free_pages; /* number of pages on freelists */
- unsigned int p2m_pages; /* number of pages allocated to p2m
*/
+ unsigned long total_pages; /* number of pages allocated */
+ unsigned long free_pages; /* number of pages on freelists */
+ unsigned long p2m_pages; /* number of pages allocated to p2m
*/
/* log dirty support */
struct log_dirty_domain log_dirty;
diff --git a/xen/arch/x86/include/asm/hap.h b/xen/arch/x86/include/asm/hap.h
index f01ce73fb4f3..061181724e90 100644
--- a/xen/arch/x86/include/asm/hap.h
+++ b/xen/arch/x86/include/asm/hap.h
@@ -33,8 +33,8 @@ int hap_track_dirty_vram(struct domain *d,
XEN_GUEST_HANDLE(void) guest_dirty_bitmap);
extern const struct paging_mode *hap_paging_get_mode(struct vcpu *v);
-int hap_set_allocation(struct domain *d, unsigned int pages, bool *preempted);
-unsigned int hap_get_allocation(struct domain *d);
+int hap_set_allocation(struct domain *d, unsigned long pages, bool *preempted);
+unsigned long hap_get_allocation(struct domain *d);
#endif /* XEN_HAP_H */
diff --git a/xen/arch/x86/include/asm/paging.h
b/xen/arch/x86/include/asm/paging.h
index 291ab386e865..fd52290cfe89 100644
--- a/xen/arch/x86/include/asm/paging.h
+++ b/xen/arch/x86/include/asm/paging.h
@@ -310,7 +310,7 @@ void paging_dump_vcpu_info(struct vcpu *v);
* Input might be rounded up to at minimum amount of pages, plus
* space for the p2m table.
* Returns 0 for success, non-zero for failure. */
-int paging_set_allocation(struct domain *d, unsigned int pages,
+int paging_set_allocation(struct domain *d, unsigned long pages,
bool *preempted);
/* Is gfn within maxphysaddr for the domain? */
diff --git a/xen/arch/x86/include/asm/shadow.h
b/xen/arch/x86/include/asm/shadow.h
index 60589c3cacee..8aac018132ac 100644
--- a/xen/arch/x86/include/asm/shadow.h
+++ b/xen/arch/x86/include/asm/shadow.h
@@ -91,7 +91,7 @@ void shadow_blow_tables_per_domain(struct domain *d);
* Input will be rounded up to at least shadow_min_acceptable_pages(),
* plus space for the p2m table.
* Returns 0 for success, non-zero for failure. */
-int shadow_set_allocation(struct domain *d, unsigned int pages,
+int shadow_set_allocation(struct domain *d, unsigned long pages,
bool *preempted);
/* Helper to invoke for deferred releasing of a top-level shadow's reference.
*/
diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
index 5ccb80bda5d3..ccea676c361b 100644
--- a/xen/arch/x86/mm/hap/hap.c
+++ b/xen/arch/x86/mm/hap/hap.c
@@ -327,18 +327,18 @@ static void cf_check hap_free_p2m_page(struct domain *d,
struct page_info *pg)
}
/* Return the size of the pool, rounded up to the nearest MB */
-unsigned int hap_get_allocation(struct domain *d)
+unsigned long hap_get_allocation(struct domain *d)
{
- unsigned int pg = d->arch.paging.total_pages
+ unsigned long pg = d->arch.paging.total_pages
+ d->arch.paging.p2m_pages;
return ((pg >> (20 - PAGE_SHIFT))
- + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
+ + ((pg & ((1UL << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
}
/* Set the pool of pages to the required number of pages.
* Returns 0 for success, non-zero for failure. */
-int hap_set_allocation(struct domain *d, unsigned int pages, bool *preempted)
+int hap_set_allocation(struct domain *d, unsigned long pages, bool *preempted)
{
struct page_info *pg;
@@ -456,7 +456,6 @@ void hap_domain_init(struct domain *d)
/* return 0 for success, -errno for failure */
int hap_enable(struct domain *d, u32 mode)
{
- unsigned int old_pages;
unsigned int i;
int rv = 0;
@@ -469,8 +468,7 @@ int hap_enable(struct domain *d, u32 mode)
domain_pause(d);
- old_pages = d->arch.paging.total_pages;
- if ( old_pages == 0 )
+ if ( d->arch.paging.total_pages == 0UL )
{
paging_lock(d);
rv = hap_set_allocation(d, 256, NULL);
@@ -623,14 +621,14 @@ void hap_teardown(struct domain *d, bool *preempted)
paging_lock(d); /* Keep various asserts happy */
- if ( d->arch.paging.total_pages != 0 )
+ if ( d->arch.paging.total_pages != 0UL )
{
hap_set_allocation(d, 0, preempted);
if ( preempted && *preempted )
goto out;
- ASSERT(d->arch.paging.total_pages == 0);
+ ASSERT(d->arch.paging.total_pages == 0UL);
}
d->arch.paging.mode &= ~PG_log_dirty;
@@ -651,7 +649,8 @@ int hap_domctl(struct domain *d, struct
xen_domctl_shadow_op *sc,
{
case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION:
paging_lock(d);
- rc = hap_set_allocation(d, sc->mb << (20 - PAGE_SHIFT), &preempted);
+ rc = hap_set_allocation(d, (unsigned long)sc->mb << (20 - PAGE_SHIFT),
+ &preempted);
paging_unlock(d);
if ( preempted )
/* Not finished. Set up to re-run the call. */
diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
index 2396f81ad54a..fa269b8cf39c 100644
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -812,7 +812,7 @@ void paging_final_teardown(struct domain *d)
{
bool hap = hap_enabled(d);
- PAGING_PRINTK("%pd start: total = %u, free = %u, p2m = %u\n",
+ PAGING_PRINTK("%pd start: total = %lu, free = %lu, p2m = %lu\n",
d, d->arch.paging.total_pages,
d->arch.paging.free_pages, d->arch.paging.p2m_pages);
@@ -834,7 +834,7 @@ void paging_final_teardown(struct domain *d)
/* It is now safe to pull down the p2m map. */
p2m_teardown(p2m_get_hostp2m(d), true, NULL);
- PAGING_PRINTK("%pd done: total = %u, free = %u, p2m = %u\n",
+ PAGING_PRINTK("%pd done: total = %lu, free = %lu, p2m = %lu\n",
d, d->arch.paging.total_pages,
d->arch.paging.free_pages, d->arch.paging.p2m_pages);
ASSERT(!d->arch.paging.p2m_pages);
@@ -941,7 +941,7 @@ void paging_update_nestedmode(struct vcpu *v)
hvm_asid_flush_vcpu(v);
}
-int __init paging_set_allocation(struct domain *d, unsigned int pages,
+int __init paging_set_allocation(struct domain *d, unsigned long pages,
bool *preempted)
{
int rc;
@@ -983,8 +983,7 @@ int arch_set_paging_mempool_size(struct domain *d, uint64_t
size)
if ( is_pv_domain(d) ) /* TODO: Relax in due course */
return -EOPNOTSUPP;
- if ( size & ~PAGE_MASK || /* Non page-sized request? */
- pages != (unsigned int)pages ) /* Overflow $X_set_allocation()? */
+ if ( size & ~PAGE_MASK ) /* Non page-sized request? */
return -EINVAL;
paging_lock(d);
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index e300898fe789..814907cec31e 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -302,7 +302,7 @@ sh_validate_guest_entry(struct vcpu *v, mfn_t gmfn, void
*entry, u32 size)
* allow for more than ninety allocated pages per vcpu. We round that
* up to 128 pages, or half a megabyte per vcpu.
*/
-static unsigned int shadow_min_acceptable_pages(const struct domain *d)
+static unsigned long shadow_min_acceptable_pages(const struct domain *d)
{
return d->max_vcpus * 128;
}
@@ -408,7 +408,7 @@ static bool __must_check _shadow_prealloc(struct domain *d,
unsigned int pages)
/* Nothing more we can do: all remaining shadows are of pages that
* hold Xen mappings for some vcpu. This can never happen. */
printk(XENLOG_ERR "Can't pre-allocate %u shadow pages!\n"
- " shadow pages total = %u, free = %u, p2m=%u\n",
+ " shadow pages total = %lu, free = %lu, p2m=%lu\n",
pages, d->arch.paging.total_pages,
d->arch.paging.free_pages, d->arch.paging.p2m_pages);
@@ -709,7 +709,7 @@ shadow_alloc_p2m_page(struct domain *d)
{
d->arch.paging.p2m_alloc_failed = 1;
dprintk(XENLOG_ERR,
- "d%d failed to allocate from shadow pool (tot=%u p2m=%u
min=%u)\n",
+ "d%d failed to allocate from shadow pool (tot=%lu p2m=%lu
min=%lu)\n",
d->domain_id, d->arch.paging.total_pages,
d->arch.paging.p2m_pages,
shadow_min_acceptable_pages(d));
@@ -760,22 +760,22 @@ shadow_free_p2m_page(struct domain *d, struct page_info
*pg)
paging_unlock(d);
}
-static unsigned int sh_min_allocation(const struct domain *d)
+static unsigned long sh_min_allocation(const struct domain *d)
{
/*
* Don't allocate less than the minimum acceptable, plus one page per
* megabyte of RAM (for the p2m table, minimally enough for HVM's setting
* up of slot zero and an LAPIC page), plus one for HVM's 1-to-1 pagetable.
*/
- unsigned int extra = max(domain_tot_pages(d) / 256,
- is_hvm_domain(d) ? CONFIG_PAGING_LEVELS + 2 :
0UL) +
- is_hvm_domain(d);
+ unsigned long extra = max(domain_tot_pages(d) / 256,
+ is_hvm_domain(d) ? CONFIG_PAGING_LEVELS + 2 :
0UL) +
+ is_hvm_domain(d);
return shadow_min_acceptable_pages(d) +
max(extra, d->arch.paging.p2m_pages);
}
-int shadow_set_allocation(struct domain *d, unsigned int pages, bool
*preempted)
+int shadow_set_allocation(struct domain *d, unsigned long pages, bool
*preempted)
{
struct page_info *sp;
@@ -784,14 +784,14 @@ int shadow_set_allocation(struct domain *d, unsigned int
pages, bool *preempted)
if ( pages > 0 )
{
/* Check for minimum value. */
- unsigned int lower_bound = sh_min_allocation(d);
+ unsigned long lower_bound = sh_min_allocation(d);
if ( pages < lower_bound )
pages = lower_bound;
pages -= d->arch.paging.p2m_pages;
}
- SHADOW_PRINTK("current %i target %i\n",
+ SHADOW_PRINTK("current %lu target %lu\n",
d->arch.paging.total_pages, pages);
for ( ; ; )
@@ -846,12 +846,12 @@ int shadow_set_allocation(struct domain *d, unsigned int
pages, bool *preempted)
}
/* Return the size of the shadow pool, rounded up to the nearest MB */
-static unsigned int shadow_get_allocation(struct domain *d)
+static unsigned long shadow_get_allocation(struct domain *d)
{
- unsigned int pg = d->arch.paging.total_pages
+ unsigned long pg = d->arch.paging.total_pages
+ d->arch.paging.p2m_pages;
return ((pg >> (20 - PAGE_SHIFT))
- + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
+ + ((pg & ((1UL << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
}
/**************************************************************************/
@@ -2085,7 +2085,6 @@ int shadow_enable(struct domain *d, u32 mode)
* disabled.
* Returns 0 for success, -errno for failure. */
{
- unsigned int old_pages;
struct page_info *pg = NULL;
uint32_t *e;
int rv = 0;
@@ -2103,8 +2102,7 @@ int shadow_enable(struct domain *d, u32 mode)
}
/* Init the shadow memory allocation if the user hasn't done so */
- old_pages = d->arch.paging.total_pages;
- if ( old_pages < sh_min_allocation(d) )
+ if ( d->arch.paging.total_pages < sh_min_allocation(d) )
{
paging_lock(d);
rv = shadow_set_allocation(d, 1024, NULL); /* Use at least 4MB */
@@ -2283,7 +2281,7 @@ void shadow_teardown(struct domain *d, bool *preempted)
}
#endif /* (SHADOW_OPTIMIZATIONS & (SHOPT_VIRTUAL_TLB|SHOPT_OUT_OF_SYNC)) */
- if ( d->arch.paging.total_pages != 0 )
+ if ( d->arch.paging.total_pages != 0UL )
{
/* Destroy all the shadows and release memory to domheap */
shadow_set_allocation(d, 0, preempted);
@@ -2295,7 +2293,7 @@ void shadow_teardown(struct domain *d, bool *preempted)
if (d->arch.paging.shadow.hash_table)
shadow_hash_teardown(d);
- ASSERT(d->arch.paging.total_pages == 0);
+ ASSERT(d->arch.paging.total_pages == 0UL);
}
/* Free the non-paged-vcpus pagetable; must happen after we've
@@ -2410,7 +2408,7 @@ static int shadow_one_bit_disable(struct domain *d, u32
mode)
{
/* Get this domain off shadows */
SHADOW_PRINTK("un-shadowing of domain %u starts."
- " Shadow pages total = %u, free = %u, p2m=%u\n",
+ " Shadow pages total = %lu, free = %lu, p2m=%lu\n",
d->domain_id, d->arch.paging.total_pages,
d->arch.paging.free_pages, d->arch.paging.p2m_pages);
for_each_vcpu(d, v)
@@ -2441,7 +2439,7 @@ static int shadow_one_bit_disable(struct domain *d, u32
mode)
BUG(); /* In fact, we will have BUG()ed already */
shadow_hash_teardown(d);
SHADOW_PRINTK("un-shadowing of domain %u done."
- " Shadow pages total = %u, free = %u, p2m=%u\n",
+ " Shadow pages total = %lu, free = %lu, p2m=%lu\n",
d->domain_id, d->arch.paging.total_pages,
d->arch.paging.free_pages, d->arch.paging.p2m_pages);
}
@@ -2573,7 +2571,9 @@ int shadow_domctl(struct domain *d,
paging_unlock(d);
return -EINVAL;
}
- rc = shadow_set_allocation(d, sc->mb << (20 - PAGE_SHIFT), &preempted);
+ rc = shadow_set_allocation(d,
+ (unsigned long)sc->mb << (20 - PAGE_SHIFT),
+ &preempted);
paging_unlock(d);
if ( preempted )
/* Not finished. Set up to re-run the call. */
--
2.39.5
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |