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, the vgic member of NEW_VGIC's struct vgic_cpu member private_irqs is changed to a pointer to struct vgic_irq. 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. As struct vcpu now fits into one page, drop MAX_PAGES_PER_VCPU. Suggested-by: Andrew Cooper <[email protected]> Signed-off-by: Oleksii Kurochko <[email protected]> Reviewed-by: Andrew Cooper <[email protected]> --- Michal gave his: Acked-by: Michal Orzel <[email protected]> But wrote to MAX_PAGES_PER_VCPU in this patch, so probably he would like to look at how it was done. --- Change in v5: - Correct the commit message: - s/vgic_vcpu/vgic_cpu/ - s/private_irq/private_irqs/ - Drop MAX_PAGES_PER_VCPU. --- Change in v4: - Add Reviewed-by: Andrew Cooper <[email protected]>. --- 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/domain.c | 23 ++++------------------- xen/arch/arm/include/asm/new_vgic.h | 2 +- xen/arch/arm/vgic/vgic-init.c | 7 +++++++ 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 47973f99d935..64b935b68000 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -473,36 +473,21 @@ void dump_pageframe_info(struct domain *d) } -/* - * The new VGIC has a bigger per-IRQ structure, so we need more than one - * page on ARM64. Cowardly increase the limit in this case. - */ -#if defined(CONFIG_NEW_VGIC) && defined(CONFIG_ARM_64) -#define MAX_PAGES_PER_VCPU 2 -#else -#define MAX_PAGES_PER_VCPU 1 -#endif - 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_page(); 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; } void free_vcpu_struct(struct vcpu *v) { - free_xenheap_pages(v, get_order_from_bytes(sizeof(*v))); + free_xenheap_page(v); } int arch_vcpu_create(struct vcpu *v) 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
