Skip to content

Commit c1bfb57

Browse files
Marc Zyngierchazy
Marc Zyngier
authored andcommitted
arm/arm64: KVM: vgic: switch to dynamic allocation
So far, all the VGIC data structures are statically defined by the *maximum* number of vcpus and interrupts it supports. It means that we always have to oversize it to cater for the worse case. Start by changing the data structures to be dynamically sizeable, and allocate them at runtime. The sizes are still very static though. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
1 parent 71afaba commit c1bfb57

File tree

3 files changed

+269
-53
lines changed

3 files changed

+269
-53
lines changed

arch/arm/kvm/arm.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
161161
kvm->vcpus[i] = NULL;
162162
}
163163
}
164+
165+
kvm_vgic_destroy(kvm);
164166
}
165167

166168
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
@@ -243,6 +245,7 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
243245
{
244246
kvm_mmu_free_memory_caches(vcpu);
245247
kvm_timer_vcpu_terminate(vcpu);
248+
kvm_vgic_vcpu_destroy(vcpu);
246249
kmem_cache_free(kvm_vcpu_cache, vcpu);
247250
}
248251

include/kvm/arm_vgic.h

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,33 @@
5454
* - a bunch of shared interrupts (SPI)
5555
*/
5656
struct vgic_bitmap {
57-
union {
58-
u32 reg[VGIC_NR_PRIVATE_IRQS / 32];
59-
DECLARE_BITMAP(reg_ul, VGIC_NR_PRIVATE_IRQS);
60-
} percpu[VGIC_MAX_CPUS];
61-
union {
62-
u32 reg[VGIC_NR_SHARED_IRQS / 32];
63-
DECLARE_BITMAP(reg_ul, VGIC_NR_SHARED_IRQS);
64-
} shared;
57+
/*
58+
* - One UL per VCPU for private interrupts (assumes UL is at
59+
* least 32 bits)
60+
* - As many UL as necessary for shared interrupts.
61+
*
62+
* The private interrupts are accessed via the "private"
63+
* field, one UL per vcpu (the state for vcpu n is in
64+
* private[n]). The shared interrupts are accessed via the
65+
* "shared" pointer (IRQn state is at bit n-32 in the bitmap).
66+
*/
67+
unsigned long *private;
68+
unsigned long *shared;
6569
};
6670

6771
struct vgic_bytemap {
68-
u32 percpu[VGIC_MAX_CPUS][VGIC_NR_PRIVATE_IRQS / 4];
69-
u32 shared[VGIC_NR_SHARED_IRQS / 4];
72+
/*
73+
* - 8 u32 per VCPU for private interrupts
74+
* - As many u32 as necessary for shared interrupts.
75+
*
76+
* The private interrupts are accessed via the "private"
77+
* field, (the state for vcpu n is in private[n*8] to
78+
* private[n*8 + 7]). The shared interrupts are accessed via
79+
* the "shared" pointer (IRQn state is at byte (n-32)%4 of the
80+
* shared[(n-32)/4] word).
81+
*/
82+
u32 *private;
83+
u32 *shared;
7084
};
7185

7286
struct kvm_vcpu;
@@ -127,6 +141,9 @@ struct vgic_dist {
127141
bool in_kernel;
128142
bool ready;
129143

144+
int nr_cpus;
145+
int nr_irqs;
146+
130147
/* Virtual control interface mapping */
131148
void __iomem *vctrl_base;
132149

@@ -166,15 +183,36 @@ struct vgic_dist {
166183
/* Level/edge triggered */
167184
struct vgic_bitmap irq_cfg;
168185

169-
/* Source CPU per SGI and target CPU */
170-
u8 irq_sgi_sources[VGIC_MAX_CPUS][VGIC_NR_SGIS];
186+
/*
187+
* Source CPU per SGI and target CPU:
188+
*
189+
* Each byte represent a SGI observable on a VCPU, each bit of
190+
* this byte indicating if the corresponding VCPU has
191+
* generated this interrupt. This is a GICv2 feature only.
192+
*
193+
* For VCPUn (n < 8), irq_sgi_sources[n*16] to [n*16 + 15] are
194+
* the SGIs observable on VCPUn.
195+
*/
196+
u8 *irq_sgi_sources;
171197

172-
/* Target CPU for each IRQ */
173-
u8 irq_spi_cpu[VGIC_NR_SHARED_IRQS];
174-
struct vgic_bitmap irq_spi_target[VGIC_MAX_CPUS];
198+
/*
199+
* Target CPU for each SPI:
200+
*
201+
* Array of available SPI, each byte indicating the target
202+
* VCPU for SPI. IRQn (n >=32) is at irq_spi_cpu[n-32].
203+
*/
204+
u8 *irq_spi_cpu;
205+
206+
/*
207+
* Reverse lookup of irq_spi_cpu for faster compute pending:
208+
*
209+
* Array of bitmaps, one per VCPU, describing if IRQn is
210+
* routed to a particular VCPU.
211+
*/
212+
struct vgic_bitmap *irq_spi_target;
175213

176214
/* Bitmap indicating which CPU has something pending */
177-
unsigned long irq_pending_on_cpu;
215+
unsigned long *irq_pending_on_cpu;
178216
#endif
179217
};
180218

@@ -204,11 +242,11 @@ struct vgic_v3_cpu_if {
204242
struct vgic_cpu {
205243
#ifdef CONFIG_KVM_ARM_VGIC
206244
/* per IRQ to LR mapping */
207-
u8 vgic_irq_lr_map[VGIC_NR_IRQS];
245+
u8 *vgic_irq_lr_map;
208246

209247
/* Pending interrupts on this VCPU */
210248
DECLARE_BITMAP( pending_percpu, VGIC_NR_PRIVATE_IRQS);
211-
DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS);
249+
unsigned long *pending_shared;
212250

213251
/* Bitmap of used/free list registers */
214252
DECLARE_BITMAP( lr_used, VGIC_V2_MAX_LRS);
@@ -239,7 +277,9 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
239277
int kvm_vgic_hyp_init(void);
240278
int kvm_vgic_init(struct kvm *kvm);
241279
int kvm_vgic_create(struct kvm *kvm);
280+
void kvm_vgic_destroy(struct kvm *kvm);
242281
int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu);
282+
void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
243283
void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
244284
void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
245285
int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,

0 commit comments

Comments
 (0)