alloc_vcpu_struct() and free_vcpu_struct() contain little
architecture-specific logic and are suitable for sharing across
architectures. Move both helpers to common code.
To support the remaining architectural differences, introduce
arch_vcpu_struct_memflags(), allowing architectures to override the
memory flags passed to alloc_xenheap_pages(). This is currently needed
by x86, which may require MEMF_bits(32) for HVM guests using shadow
paging.
The ARM implementation of alloc/free_vcpu_struct() is removed and
replaced by the common version. Stub implementations are also dropped
from PPC and RISC-V.
Finally, make alloc_vcpu_struct() and free_vcpu_struct() static to
common/domain.c, as they are no longer used outside common code.
No functional changes.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in v2:
- Rework alloc/free_vcpu_struct() to work with only one page.
- Return back the comment about the restriction inside x86's
arch_vcpu_struct_memflags().
- Drop MAX_PAGES_PER_VCPU.
---
xen/arch/arm/domain.c | 17 -----------------
xen/arch/ppc/stubs.c | 10 ----------
xen/arch/riscv/stubs.c | 10 ----------
xen/arch/x86/domain.c | 17 ++---------------
xen/arch/x86/include/asm/domain.h | 3 +++
xen/common/domain.c | 20 ++++++++++++++++++++
xen/include/xen/domain.h | 4 ----
7 files changed, 25 insertions(+), 56 deletions(-)
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index e566023340..507df807ed 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -473,23 +473,6 @@ void dump_pageframe_info(struct domain *d)
}
-struct vcpu *alloc_vcpu_struct(const struct domain *d)
-{
- struct vcpu *v;
-
- BUILD_BUG_ON(sizeof(*v) > PAGE_SIZE);
- v = alloc_xenheap_pages(0, 0);
- if ( v )
- clear_page(v);
-
- return v;
-}
-
-void free_vcpu_struct(struct vcpu *v)
-{
- free_xenheap_page(v);
-}
-
int arch_vcpu_create(struct vcpu *v)
{
int rc = 0;
diff --git a/xen/arch/ppc/stubs.c b/xen/arch/ppc/stubs.c
index 9953ea1c6c..f7f6e7ed97 100644
--- a/xen/arch/ppc/stubs.c
+++ b/xen/arch/ppc/stubs.c
@@ -152,11 +152,6 @@ void dump_pageframe_info(struct domain *d)
BUG_ON("unimplemented");
}
-void free_vcpu_struct(struct vcpu *v)
-{
- BUG_ON("unimplemented");
-}
-
int arch_vcpu_create(struct vcpu *v)
{
BUG_ON("unimplemented");
@@ -264,11 +259,6 @@ void vcpu_kick(struct vcpu *v)
BUG_ON("unimplemented");
}
-struct vcpu *alloc_vcpu_struct(const struct domain *d)
-{
- BUG_ON("unimplemented");
-}
-
unsigned long
hypercall_create_continuation(unsigned int op, const char *format, ...)
{
diff --git a/xen/arch/riscv/stubs.c b/xen/arch/riscv/stubs.c
index fe7d85ee1d..579c4215c8 100644
--- a/xen/arch/riscv/stubs.c
+++ b/xen/arch/riscv/stubs.c
@@ -126,11 +126,6 @@ void dump_pageframe_info(struct domain *d)
BUG_ON("unimplemented");
}
-void free_vcpu_struct(struct vcpu *v)
-{
- BUG_ON("unimplemented");
-}
-
int arch_vcpu_create(struct vcpu *v)
{
BUG_ON("unimplemented");
@@ -238,11 +233,6 @@ void vcpu_kick(struct vcpu *v)
BUG_ON("unimplemented");
}
-struct vcpu *alloc_vcpu_struct(const struct domain *d)
-{
- BUG_ON("unimplemented");
-}
-
unsigned long
hypercall_create_continuation(unsigned int op, const char *format, ...)
{
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 7632d5e2d6..68c7503eda 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -493,28 +493,15 @@ unsigned int arch_domain_struct_memflags(void)
return MEMF_bits(bits);
}
-struct vcpu *alloc_vcpu_struct(const struct domain *d)
+unsigned int arch_vcpu_struct_memflags(const struct domain *d)
{
- struct vcpu *v;
/*
* This structure contains embedded PAE PDPTEs, used when an HVM guest
* runs on shadow pagetables outside of 64-bit mode. In this case the CPU
* may require that the shadow CR3 points below 4GB, and hence the whole
* structure must satisfy this restriction. Thus we specify MEMF_bits(32).
*/
- unsigned int memflags =
- (is_hvm_domain(d) && paging_mode_shadow(d)) ? MEMF_bits(32) : 0;
-
- BUILD_BUG_ON(sizeof(*v) > PAGE_SIZE);
- v = alloc_xenheap_pages(0, memflags);
- if ( v != NULL )
- clear_page(v);
- return v;
-}
-
-void free_vcpu_struct(struct vcpu *v)
-{
- free_xenheap_page(v);
+ return (is_hvm_domain(d) && paging_mode_shadow(d)) ? MEMF_bits(32) : 0;
}
/* Initialise various registers to their architectural INIT/RESET state. */
diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
index 7e5cbd11a4..576f9202b4 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -15,6 +15,9 @@
unsigned int arch_domain_struct_memflags(void);
#define arch_domain_struct_memflags arch_domain_struct_memflags
+unsigned int arch_vcpu_struct_memflags(const struct domain *d);
+#define arch_vcpu_struct_memflags arch_vcpu_struct_memflags
+
#define has_32bit_shinfo(d) ((d)->arch.has_32bit_shinfo)
/*
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 93c71bc766..92fc0684fc 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -392,6 +392,26 @@ static int vcpu_teardown(struct vcpu *v)
return 0;
}
+static struct vcpu *alloc_vcpu_struct(const struct domain *d)
+{
+#ifndef arch_vcpu_struct_memflags
+# define arch_vcpu_struct_memflags(d) 0
+#endif
+ struct vcpu *v;
+
+ BUILD_BUG_ON(sizeof(*v) > PAGE_SIZE);
+ v = alloc_xenheap_pages(0, arch_vcpu_struct_memflags(d));
+ if ( v )
+ clear_page(v);
+
+ return v;
+}
+
+static void free_vcpu_struct(struct vcpu *v)
+{
+ free_xenheap_page(v);
+}
+
/*
* Destoy a vcpu once all references to it have been dropped. Used either
* from domain_destroy()'s RCU path, or from the vcpu_create() error path
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 8aab05ae93..644f5ac3f2 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -70,10 +70,6 @@ void domid_free(domid_t domid);
struct domain *alloc_domain_struct(void);
void free_domain_struct(struct domain *d);
-/* Allocate/free a VCPU structure. */
-struct vcpu *alloc_vcpu_struct(const struct domain *d);
-void free_vcpu_struct(struct vcpu *v);
-
/* Allocate/free a PIRQ structure. */
#ifndef alloc_pirq_struct
struct pirq *alloc_pirq_struct(struct domain *d);
--
2.52.0
On 18/12/2025 5:28 pm, Oleksii Kurochko wrote:
> alloc_vcpu_struct() and free_vcpu_struct() contain little
> architecture-specific logic and are suitable for sharing across
> architectures. Move both helpers to common code.
>
> To support the remaining architectural differences, introduce
> arch_vcpu_struct_memflags(), allowing architectures to override the
> memory flags passed to alloc_xenheap_pages(). This is currently needed
> by x86, which may require MEMF_bits(32) for HVM guests using shadow
> paging.
>
> The ARM implementation of alloc/free_vcpu_struct() is removed and
> replaced by the common version. Stub implementations are also dropped
> from PPC and RISC-V.
>
> Finally, make alloc_vcpu_struct() and free_vcpu_struct() static to
> common/domain.c, as they are no longer used outside common code.
>
> No functional changes.
>
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
> ---
> Changes in v2:
> - Rework alloc/free_vcpu_struct() to work with only one page.
> - Return back the comment about the restriction inside x86's
> arch_vcpu_struct_memflags().
> - Drop MAX_PAGES_PER_VCPU.
> ---
> xen/arch/arm/domain.c | 17 -----------------
> xen/arch/ppc/stubs.c | 10 ----------
> xen/arch/riscv/stubs.c | 10 ----------
> xen/arch/x86/domain.c | 17 ++---------------
> xen/arch/x86/include/asm/domain.h | 3 +++
> xen/common/domain.c | 20 ++++++++++++++++++++
> xen/include/xen/domain.h | 4 ----
> 7 files changed, 25 insertions(+), 56 deletions(-)
Much nicer.
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index 7632d5e2d6..68c7503eda 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -493,28 +493,15 @@ unsigned int arch_domain_struct_memflags(void)
> return MEMF_bits(bits);
> }
>
> -struct vcpu *alloc_vcpu_struct(const struct domain *d)
> +unsigned int arch_vcpu_struct_memflags(const struct domain *d)
> {
> - struct vcpu *v;
> /*
> * This structure contains embedded PAE PDPTEs, used when an HVM guest
> * runs on shadow pagetables outside of 64-bit mode. In this case the CPU
> * may require that the shadow CR3 points below 4GB, and hence the whole
> * structure must satisfy this restriction. Thus we specify MEMF_bits(32).
> */
> - unsigned int memflags =
> - (is_hvm_domain(d) && paging_mode_shadow(d)) ? MEMF_bits(32) : 0;
> -
> - BUILD_BUG_ON(sizeof(*v) > PAGE_SIZE);
> - v = alloc_xenheap_pages(0, memflags);
> - if ( v != NULL )
> - clear_page(v);
> - return v;
> -}
> -
> -void free_vcpu_struct(struct vcpu *v)
> -{
> - free_xenheap_page(v);
> + return (is_hvm_domain(d) && paging_mode_shadow(d)) ? MEMF_bits(32) : 0;
> }
>
> /* Initialise various registers to their architectural INIT/RESET state. */
> diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h
> index 7e5cbd11a4..576f9202b4 100644
> --- a/xen/arch/x86/include/asm/domain.h
> +++ b/xen/arch/x86/include/asm/domain.h
> @@ -15,6 +15,9 @@
> unsigned int arch_domain_struct_memflags(void);
> #define arch_domain_struct_memflags arch_domain_struct_memflags
>
> +unsigned int arch_vcpu_struct_memflags(const struct domain *d);
> +#define arch_vcpu_struct_memflags arch_vcpu_struct_memflags
> +
Given the single caller and simplicity, this would be better as a static
inline, except it can't yet for header reasons. So, instead, I'd
suggest simply:
/*
* $COMMENT
*/
#define arch_vcpu_struct_memflags(d) \
(is_hvm_domain(d) && paging_mode_shadow(d) ? MEMF_bits(32) : 0)
This form does double expand 'd'. The more complex form would be to
match
https://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=c37bcb35f928c81cbeea7c05f86b6779f8a2b8c4
with a local variable.
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index 93c71bc766..92fc0684fc 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -392,6 +392,26 @@ static int vcpu_teardown(struct vcpu *v)
> return 0;
> }
>
> +static struct vcpu *alloc_vcpu_struct(const struct domain *d)
> +{
> +#ifndef arch_vcpu_struct_memflags
> +# define arch_vcpu_struct_memflags(d) 0
((void)d, 0)
~Andrew
On 18.12.2025 19:34, Andrew Cooper wrote:
> On 18/12/2025 5:28 pm, Oleksii Kurochko wrote:
>> --- a/xen/common/domain.c
>> +++ b/xen/common/domain.c
>> @@ -392,6 +392,26 @@ static int vcpu_teardown(struct vcpu *v)
>> return 0;
>> }
>>
>> +static struct vcpu *alloc_vcpu_struct(const struct domain *d)
>> +{
>> +#ifndef arch_vcpu_struct_memflags
>> +# define arch_vcpu_struct_memflags(d) 0
>
> ((void)d, 0)
Nit: ((void)(d), 0)
Jan
© 2016 - 2026 Red Hat, Inc.