mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
KVM: arm64: gic-v5: Init Private IRQs (PPIs) for GICv5
Initialise the private interrupts (PPIs, only) for GICv5. This means that a GICv5-style intid is generated (which encodes the PPI type in the top bits) instead of the 0-based index that is used for older GICs. Additionally, set all of the GICv5 PPIs to use Level for the handling mode, with the exception of the SW_PPI which uses Edge. This matches the architecturally-defined set in the GICv5 specification (the CTIIRQ handling mode is IMPDEF, so Level has been picked for that). Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Link: https://patch.msgid.link/20260319154937.3619520-22-sascha.bischoff@arm.com Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
4d591252ba
commit
da8d9636be
|
|
@ -250,9 +250,65 @@ int kvm_vgic_vcpu_nv_init(struct kvm_vcpu *vcpu)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void vgic_allocate_private_irq(struct kvm_vcpu *vcpu, int i, u32 type)
|
||||
{
|
||||
struct vgic_irq *irq = &vcpu->arch.vgic_cpu.private_irqs[i];
|
||||
|
||||
INIT_LIST_HEAD(&irq->ap_list);
|
||||
raw_spin_lock_init(&irq->irq_lock);
|
||||
irq->vcpu = NULL;
|
||||
irq->target_vcpu = vcpu;
|
||||
refcount_set(&irq->refcount, 0);
|
||||
|
||||
irq->intid = i;
|
||||
if (vgic_irq_is_sgi(i)) {
|
||||
/* SGIs */
|
||||
irq->enabled = 1;
|
||||
irq->config = VGIC_CONFIG_EDGE;
|
||||
} else {
|
||||
/* PPIs */
|
||||
irq->config = VGIC_CONFIG_LEVEL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case KVM_DEV_TYPE_ARM_VGIC_V3:
|
||||
irq->group = 1;
|
||||
irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
|
||||
break;
|
||||
case KVM_DEV_TYPE_ARM_VGIC_V2:
|
||||
irq->group = 0;
|
||||
irq->targets = BIT(vcpu->vcpu_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void vgic_v5_allocate_private_irq(struct kvm_vcpu *vcpu, int i, u32 type)
|
||||
{
|
||||
struct vgic_irq *irq = &vcpu->arch.vgic_cpu.private_irqs[i];
|
||||
u32 intid = vgic_v5_make_ppi(i);
|
||||
|
||||
INIT_LIST_HEAD(&irq->ap_list);
|
||||
raw_spin_lock_init(&irq->irq_lock);
|
||||
irq->vcpu = NULL;
|
||||
irq->target_vcpu = vcpu;
|
||||
refcount_set(&irq->refcount, 0);
|
||||
|
||||
irq->intid = intid;
|
||||
|
||||
/* The only Edge architected PPI is the SW_PPI */
|
||||
if (i == GICV5_ARCH_PPI_SW_PPI)
|
||||
irq->config = VGIC_CONFIG_EDGE;
|
||||
else
|
||||
irq->config = VGIC_CONFIG_LEVEL;
|
||||
|
||||
/* Register the GICv5-specific PPI ops */
|
||||
vgic_v5_set_ppi_ops(vcpu, intid);
|
||||
}
|
||||
|
||||
static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
|
||||
{
|
||||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||
u32 num_private_irqs;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&vcpu->kvm->arch.config_lock);
|
||||
|
|
@ -260,8 +316,13 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
|
|||
if (vgic_cpu->private_irqs)
|
||||
return 0;
|
||||
|
||||
if (vgic_is_v5(vcpu->kvm))
|
||||
num_private_irqs = VGIC_V5_NR_PRIVATE_IRQS;
|
||||
else
|
||||
num_private_irqs = VGIC_NR_PRIVATE_IRQS;
|
||||
|
||||
vgic_cpu->private_irqs = kzalloc_objs(struct vgic_irq,
|
||||
VGIC_NR_PRIVATE_IRQS,
|
||||
num_private_irqs,
|
||||
GFP_KERNEL_ACCOUNT);
|
||||
|
||||
if (!vgic_cpu->private_irqs)
|
||||
|
|
@ -271,34 +332,11 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
|
|||
* Enable and configure all SGIs to be edge-triggered and
|
||||
* configure all PPIs as level-triggered.
|
||||
*/
|
||||
for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
|
||||
struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
|
||||
|
||||
INIT_LIST_HEAD(&irq->ap_list);
|
||||
raw_spin_lock_init(&irq->irq_lock);
|
||||
irq->intid = i;
|
||||
irq->vcpu = NULL;
|
||||
irq->target_vcpu = vcpu;
|
||||
refcount_set(&irq->refcount, 0);
|
||||
if (vgic_irq_is_sgi(i)) {
|
||||
/* SGIs */
|
||||
irq->enabled = 1;
|
||||
irq->config = VGIC_CONFIG_EDGE;
|
||||
} else {
|
||||
/* PPIs */
|
||||
irq->config = VGIC_CONFIG_LEVEL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case KVM_DEV_TYPE_ARM_VGIC_V3:
|
||||
irq->group = 1;
|
||||
irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
|
||||
break;
|
||||
case KVM_DEV_TYPE_ARM_VGIC_V2:
|
||||
irq->group = 0;
|
||||
irq->targets = BIT(vcpu->vcpu_id);
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < num_private_irqs; i++) {
|
||||
if (vgic_is_v5(vcpu->kvm))
|
||||
vgic_v5_allocate_private_irq(vcpu, i, type);
|
||||
else
|
||||
vgic_allocate_private_irq(vcpu, i, type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user