When CONFIG_NEW_VGIC=y and CONFIG_ARM_64=y, the size of struct vcpu
exceeds one page, which requires allocating two pages and led to the
introduction of MAX_PAGES_PER_VCPU.
To remove the need for MAX_PAGES_PER_VCPU in a follow-up patch, the vgic
member of NEW_VGIC's struct vgic_vcpu member private_irq is changed to a
pointer to struct vgic_irq.
As a result, the size of struct vcpu for Arm64 is reduced to 2176 bytes,
compared to 3840 bytes (without these changes and with CONFIG_ARM_64=y)
and 4736 bytes (without these changes and with both CONFIG_ARM_64=y and
CONFIG_NEW_VGIC=y).
Since the private_irqs member is now a pointer, vcpu_vgic_init() and
vcpu_vgic_free() are updated to allocate and free private_irqs instance.
Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
Change in v4:
- Add Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>.
---
Changes in v3:
- Make private_irqs member as pointer to vgic_irq in struct vgic_cpu
of new_vgic instead of vgic member of arch_vcpu.
---
Changes in v2:
- New patch.
---
xen/arch/arm/include/asm/new_vgic.h | 2 +-
xen/arch/arm/vgic/vgic-init.c | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/xen/arch/arm/include/asm/new_vgic.h b/xen/arch/arm/include/asm/new_vgic.h
index 1e762138939f..6f7af0e02b2b 100644
--- a/xen/arch/arm/include/asm/new_vgic.h
+++ b/xen/arch/arm/include/asm/new_vgic.h
@@ -155,7 +155,7 @@ struct vgic_dist {
};
struct vgic_cpu {
- struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
+ struct vgic_irq *private_irqs;
struct list_head ap_list_head;
spinlock_t ap_list_lock; /* Protects the ap_list */
diff --git a/xen/arch/arm/vgic/vgic-init.c b/xen/arch/arm/vgic/vgic-init.c
index aef526f2e717..4eb49d922492 100644
--- a/xen/arch/arm/vgic/vgic-init.c
+++ b/xen/arch/arm/vgic/vgic-init.c
@@ -202,6 +202,11 @@ int vcpu_vgic_init(struct vcpu *v)
{
int ret = 0;
+ v->arch.vgic.private_irqs =
+ xzalloc_array(struct vgic_irq, VGIC_NR_PRIVATE_IRQS);
+ if ( !v->arch.vgic.private_irqs )
+ return -ENOMEM;
+
vgic_vcpu_early_init(v);
if ( gic_hw_version() == GIC_V2 )
@@ -244,6 +249,8 @@ void vcpu_vgic_free(struct vcpu *v)
struct vgic_cpu *vgic_cpu = &v->arch.vgic;
INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+
+ XFREE(v->arch.vgic.private_irqs);
}
/*
--
2.52.0
On 23/12/2025 18:01, Oleksii Kurochko wrote: > When CONFIG_NEW_VGIC=y and CONFIG_ARM_64=y, the size of struct vcpu > exceeds one page, which requires allocating two pages and led to the > introduction of MAX_PAGES_PER_VCPU. > > To remove the need for MAX_PAGES_PER_VCPU in a follow-up patch, the vgic > member of NEW_VGIC's struct vgic_vcpu member private_irq is changed to a s/vgic_vcpu/vgic_cpu/ s/private_irq/private_irqs/ > pointer to struct vgic_irq. > As a result, the size of struct vcpu for Arm64 is reduced to 2176 bytes, > compared to 3840 bytes (without these changes and with CONFIG_ARM_64=y) > and 4736 bytes (without these changes and with both CONFIG_ARM_64=y and > CONFIG_NEW_VGIC=y). You only touch new vGIC, so there should be no size reduction without it but the paragraph reads as if the change affected both old and new vGIC. Also I would mention that probably you provided the numbers based on a defconfig target. > > Since the private_irqs member is now a pointer, vcpu_vgic_init() and > vcpu_vgic_free() are updated to allocate and free private_irqs instance. > > Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com> > Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> > Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Other than that: Acked-by: Michal Orzel <michal.orzel@amd.com> ~Michal
On 12/29/25 12:08 PM, Orzel, Michal wrote: > > On 23/12/2025 18:01, Oleksii Kurochko wrote: >> When CONFIG_NEW_VGIC=y and CONFIG_ARM_64=y, the size of struct vcpu >> exceeds one page, which requires allocating two pages and led to the >> introduction of MAX_PAGES_PER_VCPU. >> >> To remove the need for MAX_PAGES_PER_VCPU in a follow-up patch, the vgic >> member of NEW_VGIC's struct vgic_vcpu member private_irq is changed to a > s/vgic_vcpu/vgic_cpu/ > s/private_irq/private_irqs/ > >> pointer to struct vgic_irq. >> As a result, the size of struct vcpu for Arm64 is reduced to 2176 bytes, >> compared to 3840 bytes (without these changes and with CONFIG_ARM_64=y) >> and 4736 bytes (without these changes and with both CONFIG_ARM_64=y and >> CONFIG_NEW_VGIC=y). > You only touch new vGIC, so there should be no size reduction without it but the > paragraph reads as if the change affected both old and new vGIC. Also I would > mention that probably you provided the numbers based on a defconfig target. Yes, all the numbers are provided based on defconfig target. I will update this paragraph in the following way to be more clear: As a result, the size of struct vcpu for Arm64 is reduced to 2176 bytes in the case when CONFIG_ARM_64=y and CONFIG_NEW_VGIC=y, compared to 3840 bytes (without these changes and with CONFIG_ARM_64=y) and 4736 bytes (without these changes and with both CONFIG_ARM_64=y and CONFIG_NEW_VGIC=y). Note that all numbers are based on defconfig with the mentioned options enabled or disabled as specified. > >> Since the private_irqs member is now a pointer, vcpu_vgic_init() and >> vcpu_vgic_free() are updated to allocate and free private_irqs instance. >> >> Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com> >> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> >> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> > Other than that: > Acked-by: Michal Orzel <michal.orzel@amd.com> Thanks! ~ Oleksii
On 29/12/2025 12:08, Orzel, Michal wrote: > > > On 23/12/2025 18:01, Oleksii Kurochko wrote: >> When CONFIG_NEW_VGIC=y and CONFIG_ARM_64=y, the size of struct vcpu >> exceeds one page, which requires allocating two pages and led to the >> introduction of MAX_PAGES_PER_VCPU. Also, I think it would be better to drop MAX_PAGES_PER_VCPU in this patch. ~Michal >> >> To remove the need for MAX_PAGES_PER_VCPU in a follow-up patch, the vgic >> member of NEW_VGIC's struct vgic_vcpu member private_irq is changed to a > s/vgic_vcpu/vgic_cpu/ > s/private_irq/private_irqs/ > >> pointer to struct vgic_irq. >> As a result, the size of struct vcpu for Arm64 is reduced to 2176 bytes, >> compared to 3840 bytes (without these changes and with CONFIG_ARM_64=y) >> and 4736 bytes (without these changes and with both CONFIG_ARM_64=y and >> CONFIG_NEW_VGIC=y). > You only touch new vGIC, so there should be no size reduction without it but the > paragraph reads as if the change affected both old and new vGIC. Also I would > mention that probably you provided the numbers based on a defconfig target. > >> >> Since the private_irqs member is now a pointer, vcpu_vgic_init() and >> vcpu_vgic_free() are updated to allocate and free private_irqs instance. >> >> Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com> >> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> >> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> > Other than that: > Acked-by: Michal Orzel <michal.orzel@amd.com> > > ~Michal > >
On 12/29/25 12:10 PM, Orzel, Michal wrote:
>
> On 29/12/2025 12:08, Orzel, Michal wrote:
>>
>> On 23/12/2025 18:01, Oleksii Kurochko wrote:
>>> When CONFIG_NEW_VGIC=y and CONFIG_ARM_64=y, the size of struct vcpu
>>> exceeds one page, which requires allocating two pages and led to the
>>> introduction of MAX_PAGES_PER_VCPU.
> Also, I think it would be better to drop MAX_PAGES_PER_VCPU in this patch.
Then I'll update alloc_vcpu_struct() and free_vcpu_struct() to:
struct vcpu *alloc_vcpu_struct(const struct domain *d)
{
struct vcpu *v;
- BUILD_BUG_ON(sizeof(*v) > MAX_PAGES_PER_VCPU * PAGE_SIZE);
- v = alloc_xenheap_pages(get_order_from_bytes(sizeof(*v)), 0);
+ BUILD_BUG_ON(sizeof(*v) > PAGE_SIZE);
+ v = alloc_xenheap_pages(0, 0);
if ( v != NULL )
- {
- unsigned int i;
-
- for ( i = 0; i < DIV_ROUND_UP(sizeof(*v), PAGE_SIZE); i++ )
- clear_page((void *)v + i * PAGE_SIZE);
- }
+ clear_page(v);
return v;
@@ -503,5 +488,5 @@ struct vcpu *alloc_vcpu_struct(const struct domain *d)
void free_vcpu_struct(struct vcpu *v)
{
- free_xenheap_pages(v, get_order_from_bytes(sizeof(*v)));
+ free_xenheap_page(v);
}
Thanks.
~ Oleksii
On 31.12.2025 09:27, Oleksii Kurochko wrote:
> On 12/29/25 12:10 PM, Orzel, Michal wrote:
>> On 29/12/2025 12:08, Orzel, Michal wrote:
>>> On 23/12/2025 18:01, Oleksii Kurochko wrote:
>>>> When CONFIG_NEW_VGIC=y and CONFIG_ARM_64=y, the size of struct vcpu
>>>> exceeds one page, which requires allocating two pages and led to the
>>>> introduction of MAX_PAGES_PER_VCPU.
>> Also, I think it would be better to drop MAX_PAGES_PER_VCPU in this patch.
>
> Then I'll update alloc_vcpu_struct() and free_vcpu_struct() to:
> struct vcpu *alloc_vcpu_struct(const struct domain *d)
> {
> struct vcpu *v;
>
> - BUILD_BUG_ON(sizeof(*v) > MAX_PAGES_PER_VCPU * PAGE_SIZE);
> - v = alloc_xenheap_pages(get_order_from_bytes(sizeof(*v)), 0);
> + BUILD_BUG_ON(sizeof(*v) > PAGE_SIZE);
> + v = alloc_xenheap_pages(0, 0);
Just one nit here: As (iirc) previously indicated by Andrew, please
avoid open-coding of alloc_xenheap_page().
Jan
On 29/12/2025 11:10 am, Orzel, Michal wrote: > > On 29/12/2025 12:08, Orzel, Michal wrote: >> >> On 23/12/2025 18:01, Oleksii Kurochko wrote: >>> When CONFIG_NEW_VGIC=y and CONFIG_ARM_64=y, the size of struct vcpu >>> exceeds one page, which requires allocating two pages and led to the >>> introduction of MAX_PAGES_PER_VCPU. > Also, I think it would be better to drop MAX_PAGES_PER_VCPU in this patch. Or at least shrink it to just 1, which would be minimal churn. > > ~Michal > >>> To remove the need for MAX_PAGES_PER_VCPU in a follow-up patch, the vgic >>> member of NEW_VGIC's struct vgic_vcpu member private_irq is changed to a >> s/vgic_vcpu/vgic_cpu/ >> s/private_irq/private_irqs/ >> >>> pointer to struct vgic_irq. >>> As a result, the size of struct vcpu for Arm64 is reduced to 2176 bytes, >>> compared to 3840 bytes (without these changes and with CONFIG_ARM_64=y) >>> and 4736 bytes (without these changes and with both CONFIG_ARM_64=y and >>> CONFIG_NEW_VGIC=y). >> You only touch new vGIC, so there should be no size reduction without it but the >> paragraph reads as if the change affected both old and new vGIC. Also I would >> mention that probably you provided the numbers based on a defconfig target. I think that was stale from v1, where this patch was far larger and more invasive. ~Andrew
© 2016 - 2026 Red Hat, Inc.