xen/arch/x86/domain.c | 5 ----- xen/arch/x86/include/asm/config.h | 2 +- xen/arch/x86/include/asm/domain.h | 8 ++++---- xen/arch/x86/pv/dom0_build.c | 2 +- xen/arch/x86/pv/domain.c | 2 ++ 5 files changed, 8 insertions(+), 11 deletions(-)
The hv_compat_vstart variable is hidden behind CONFIG_PV32 but lives in
arch_domain. Moving it into pv_domain is an obvious improvement.
The value however is less obvious, and a mess.
In !PV32 builds, it's uniformly 0, but in PV32 builds it's ~0U (HVM guests),
__HYPERVISOR_COMPAT_VIRT_START (PV guests), or custom (PV32 dom0). This seems
to work because uses are guarded behind is_pv32_{domain,vcpu}().
Simplify things by leaving it as 0 in PV32 builds for most domains,
initialising it in only in switch_compat() when a domain becomes 32bit PV.
dom0_construct() adjusts the value after calling switch_compat().
Suggested-by: Grygorii Strashko <grygorii_strashko@epam.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Grygorii Strashko <grygorii_strashko@epam.com>
Texturally, but not logically, depends on "[PATCH] x86/pv: Inline
domain_set_alloc_bitsize() into it's single caller"
Bloat-o-meter reports:
add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-65 (-65)
Function old new delta
switch_compat 472 463 -9
arch_domain_create 1056 1000 -56
The reason that switch_compat() gets smaller is because
MACH2PHYS_COMPAT_NR_ENTRIES(d) can now be calculated at compile time,
including the fls() thereof.
---
xen/arch/x86/domain.c | 5 -----
xen/arch/x86/include/asm/config.h | 2 +-
xen/arch/x86/include/asm/domain.h | 8 ++++----
xen/arch/x86/pv/dom0_build.c | 2 +-
xen/arch/x86/pv/domain.c | 2 ++
5 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index d33a42c8824c..5e37bfbd17d6 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -890,11 +890,6 @@ int arch_domain_create(struct domain *d,
}
d->arch.emulation_flags = emflags;
-#ifdef CONFIG_PV32
- d->arch.hv_compat_vstart =
- is_pv_domain(d) ? __HYPERVISOR_COMPAT_VIRT_START : ~0u;
-#endif
-
spec_ctrl_init_domain(d);
if ( (rc = paging_domain_init(d)) != 0 )
diff --git a/xen/arch/x86/include/asm/config.h b/xen/arch/x86/include/asm/config.h
index 156369695442..cc80f2c62310 100644
--- a/xen/arch/x86/include/asm/config.h
+++ b/xen/arch/x86/include/asm/config.h
@@ -201,7 +201,7 @@
/* This is not a fixed value, just a lower limit. */
#define __HYPERVISOR_COMPAT_VIRT_START 0xF5800000
-#define HYPERVISOR_COMPAT_VIRT_START(d) ((d)->arch.hv_compat_vstart)
+#define HYPERVISOR_COMPAT_VIRT_START(d) ((d)->arch.pv.hv_compat_vstart)
#else /* !CONFIG_PV32 */
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index 386ec6174589..7e5cbd11a464 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -288,6 +288,10 @@ struct pv_domain
/* Mitigate L1TF with shadow/crashing? */
bool check_l1tf;
+#ifdef CONFIG_PV32
+ unsigned int hv_compat_vstart;
+#endif
+
/* map_domain_page() mapping cache. */
struct mapcache_domain mapcache;
@@ -315,10 +319,6 @@ struct arch_domain
{
struct page_info *perdomain_l3_pg;
-#ifdef CONFIG_PV32
- unsigned int hv_compat_vstart;
-#endif
-
/* Maximum physical-address bitwidth supported by this guest. */
unsigned int physaddr_bitsize;
diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
index fed03dc15dcf..418b453ba8bf 100644
--- a/xen/arch/x86/pv/dom0_build.c
+++ b/xen/arch/x86/pv/dom0_build.c
@@ -521,7 +521,7 @@ static int __init dom0_construct(const struct boot_domain *bd)
printk("Dom0 expects too high a hypervisor start address\n");
return -ERANGE;
}
- d->arch.hv_compat_vstart =
+ d->arch.pv.hv_compat_vstart =
max_t(unsigned int, m2p_compat_vstart, value);
}
diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c
index 11db6a6d8396..ca5f6920516e 100644
--- a/xen/arch/x86/pv/domain.c
+++ b/xen/arch/x86/pv/domain.c
@@ -254,6 +254,8 @@ int switch_compat(struct domain *d)
goto undo_and_fail;
}
+ d->arch.pv.hv_compat_vstart = __HYPERVISOR_COMPAT_VIRT_START;
+
if ( MACH2PHYS_COMPAT_NR_ENTRIES(d) < max_page )
d->arch.physaddr_bitsize =
/* 2^n entries can be contained in guest's p2m mapping space */
--
2.39.5
On 09.12.2025 19:26, Andrew Cooper wrote:
> The hv_compat_vstart variable is hidden behind CONFIG_PV32 but lives in
> arch_domain. Moving it into pv_domain is an obvious improvement.
>
> The value however is less obvious, and a mess.
>
> In !PV32 builds, it's uniformly 0, but in PV32 builds it's ~0U (HVM guests),
> __HYPERVISOR_COMPAT_VIRT_START (PV guests), or custom (PV32 dom0). This seems
> to work because uses are guarded behind is_pv32_{domain,vcpu}().
>
> Simplify things by leaving it as 0 in PV32 builds for most domains,
> initialising it in only in switch_compat() when a domain becomes 32bit PV.
> dom0_construct() adjusts the value after calling switch_compat().
>
> Suggested-by: Grygorii Strashko <grygorii_strashko@epam.com>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
© 2016 - 2025 Red Hat, Inc.