Message ID | 1433783045-8002-5-git-send-email-marc.zyngier@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Marc Zyngier <marc.zyngier@arm.com> writes: > Now that struct vgic_lr supports the LR_HW bit and carries a hwirq > field, we can encode that information into the list registers. > > This patch provides implementations for both GICv2 and GICv3. > > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> > --- > include/linux/irqchip/arm-gic-v3.h | 3 +++ > include/linux/irqchip/arm-gic.h | 3 ++- > virt/kvm/arm/vgic-v2.c | 16 +++++++++++++++- > virt/kvm/arm/vgic-v3.c | 21 ++++++++++++++++++--- > 4 files changed, 38 insertions(+), 5 deletions(-) > > diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h > index ffbc034..cf637d6 100644 <snip> > @@ -84,10 +88,17 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, > * Eventually we want to make this configurable, so we may revisit > * this in the future. > */ > - if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) > + switch (vcpu->kvm->arch.vgic.vgic_model) { > + case KVM_DEV_TYPE_ARM_VGIC_V3: > lr_val |= ICH_LR_GROUP; > - else > - lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; > + break; > + case KVM_DEV_TYPE_ARM_VGIC_V2: > + if (lr_desc.irq < VGIC_NR_SGIS) > + lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; > + break; > + default: > + BUG(); > + } > > if (lr_desc.state & LR_STATE_PENDING) > lr_val |= ICH_LR_PENDING_BIT; > @@ -95,6 +106,10 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, > lr_val |= ICH_LR_ACTIVE_BIT; > if (lr_desc.state & LR_EOI_INT) > lr_val |= ICH_LR_EOI; > + if (lr_desc.state & LR_HW) { > + lr_val |= ICH_LR_HW; > + lr_val |= ((u64)lr_desc.hwirq) << ICH_LR_PHYS_ID_SHIFT; > + } > Why is the bracketing different for the casting of lr_desc.hwirq compared to lr_desc.source. Surely the precedence of up-casting before the shift is the same in both cases? > vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val; > }
On 09/06/15 14:21, Alex Bennée wrote: > > Marc Zyngier <marc.zyngier@arm.com> writes: > >> Now that struct vgic_lr supports the LR_HW bit and carries a hwirq >> field, we can encode that information into the list registers. >> >> This patch provides implementations for both GICv2 and GICv3. >> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> >> --- >> include/linux/irqchip/arm-gic-v3.h | 3 +++ >> include/linux/irqchip/arm-gic.h | 3 ++- >> virt/kvm/arm/vgic-v2.c | 16 +++++++++++++++- >> virt/kvm/arm/vgic-v3.c | 21 ++++++++++++++++++--- >> 4 files changed, 38 insertions(+), 5 deletions(-) >> >> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h >> index ffbc034..cf637d6 100644 > <snip> >> @@ -84,10 +88,17 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, >> * Eventually we want to make this configurable, so we may revisit >> * this in the future. >> */ >> - if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) >> + switch (vcpu->kvm->arch.vgic.vgic_model) { >> + case KVM_DEV_TYPE_ARM_VGIC_V3: >> lr_val |= ICH_LR_GROUP; >> - else >> - lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; >> + break; >> + case KVM_DEV_TYPE_ARM_VGIC_V2: >> + if (lr_desc.irq < VGIC_NR_SGIS) >> + lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; >> + break; >> + default: >> + BUG(); >> + } >> >> if (lr_desc.state & LR_STATE_PENDING) >> lr_val |= ICH_LR_PENDING_BIT; >> @@ -95,6 +106,10 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, >> lr_val |= ICH_LR_ACTIVE_BIT; >> if (lr_desc.state & LR_EOI_INT) >> lr_val |= ICH_LR_EOI; >> + if (lr_desc.state & LR_HW) { >> + lr_val |= ICH_LR_HW; >> + lr_val |= ((u64)lr_desc.hwirq) << ICH_LR_PHYS_ID_SHIFT; >> + } >> > > Why is the bracketing different for the casting of lr_desc.hwirq > compared to lr_desc.source. Surely the precedence of up-casting before > the shift is the same in both cases? Probably a leftover from a previous refactor... Thanks, M.
On 06/08/2015 07:03 PM, Marc Zyngier wrote: > Now that struct vgic_lr supports the LR_HW bit and carries a hwirq > field, we can encode that information into the list registers. > > This patch provides implementations for both GICv2 and GICv3. > > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> > --- > include/linux/irqchip/arm-gic-v3.h | 3 +++ > include/linux/irqchip/arm-gic.h | 3 ++- > virt/kvm/arm/vgic-v2.c | 16 +++++++++++++++- > virt/kvm/arm/vgic-v3.c | 21 ++++++++++++++++++--- > 4 files changed, 38 insertions(+), 5 deletions(-) > > diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h > index ffbc034..cf637d6 100644 > --- a/include/linux/irqchip/arm-gic-v3.h > +++ b/include/linux/irqchip/arm-gic-v3.h > @@ -268,9 +268,12 @@ > > #define ICH_LR_EOI (1UL << 41) > #define ICH_LR_GROUP (1UL << 60) > +#define ICH_LR_HW (1UL << 61) > #define ICH_LR_STATE (3UL << 62) > #define ICH_LR_PENDING_BIT (1UL << 62) > #define ICH_LR_ACTIVE_BIT (1UL << 63) > +#define ICH_LR_PHYS_ID_SHIFT 32 > +#define ICH_LR_PHYS_ID_MASK (0x3ffUL << ICH_LR_PHYS_ID_SHIFT) > > #define ICH_MISR_EOI (1 << 0) > #define ICH_MISR_U (1 << 1) > diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h > index 9de976b..ca88dad 100644 > --- a/include/linux/irqchip/arm-gic.h > +++ b/include/linux/irqchip/arm-gic.h > @@ -71,11 +71,12 @@ > > #define GICH_LR_VIRTUALID (0x3ff << 0) > #define GICH_LR_PHYSID_CPUID_SHIFT (10) > -#define GICH_LR_PHYSID_CPUID (7 << GICH_LR_PHYSID_CPUID_SHIFT) > +#define GICH_LR_PHYSID_CPUID (0x3ff << GICH_LR_PHYSID_CPUID_SHIFT) > #define GICH_LR_STATE (3 << 28) > #define GICH_LR_PENDING_BIT (1 << 28) > #define GICH_LR_ACTIVE_BIT (1 << 29) > #define GICH_LR_EOI (1 << 19) > +#define GICH_LR_HW (1 << 31) > > #define GICH_VMCR_CTRL_SHIFT 0 > #define GICH_VMCR_CTRL_MASK (0x21f << GICH_VMCR_CTRL_SHIFT) > diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c > index f9b9c7c..8d7b04d 100644 > --- a/virt/kvm/arm/vgic-v2.c > +++ b/virt/kvm/arm/vgic-v2.c > @@ -48,6 +48,10 @@ static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) > lr_desc.state |= LR_STATE_ACTIVE; > if (val & GICH_LR_EOI) > lr_desc.state |= LR_EOI_INT; > + if (val & GICH_LR_HW) { > + lr_desc.state |= LR_HW; > + lr_desc.hwirq = (val & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT; > + } > > return lr_desc; > } > @@ -55,7 +59,9 @@ static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) > static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, > struct vgic_lr lr_desc) > { > - u32 lr_val = (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) | lr_desc.irq; > + u32 lr_val; > + > + lr_val = lr_desc.irq; > > if (lr_desc.state & LR_STATE_PENDING) > lr_val |= GICH_LR_PENDING_BIT; > @@ -64,6 +70,14 @@ static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, > if (lr_desc.state & LR_EOI_INT) > lr_val |= GICH_LR_EOI; > > + if (lr_desc.state & LR_HW) { > + lr_val |= GICH_LR_HW; > + lr_val |= (u32)lr_desc.hwirq << GICH_LR_PHYSID_CPUID_SHIFT; shouldn't we test somewhere that the hwirq is between 16 and 1019. Else behavior is unpredictable according to v2 spec. when queuing into the LR we currently check the linux irq vlr.irq >= VGIC_NR_SGIS if I am not wrong. besides Reviewed-by: Eric Auger <eric.auger@linaro.org> Eric > + } > + > + if (lr_desc.irq < VGIC_NR_SGIS) > + lr_val |= (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT); > + > vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = lr_val; > } > > diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c > index dff0602..afbf925 100644 > --- a/virt/kvm/arm/vgic-v3.c > +++ b/virt/kvm/arm/vgic-v3.c > @@ -67,6 +67,10 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr) > lr_desc.state |= LR_STATE_ACTIVE; > if (val & ICH_LR_EOI) > lr_desc.state |= LR_EOI_INT; > + if (val & ICH_LR_HW) { > + lr_desc.state |= LR_HW; > + lr_desc.hwirq = (val >> ICH_LR_PHYS_ID_SHIFT) & GENMASK(9, 0); > + } > > return lr_desc; > } > @@ -84,10 +88,17 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, > * Eventually we want to make this configurable, so we may revisit > * this in the future. > */ > - if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) > + switch (vcpu->kvm->arch.vgic.vgic_model) { > + case KVM_DEV_TYPE_ARM_VGIC_V3: > lr_val |= ICH_LR_GROUP; not related to that patch but why LR_GROUP setting does depend on guest view? Why isn'it always set to 1? > - else > - lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; > + break; > + case KVM_DEV_TYPE_ARM_VGIC_V2: > + if (lr_desc.irq < VGIC_NR_SGIS) > + lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; > + break; > + default: > + BUG(); > + } > > if (lr_desc.state & LR_STATE_PENDING) > lr_val |= ICH_LR_PENDING_BIT; > @@ -95,6 +106,10 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, > lr_val |= ICH_LR_ACTIVE_BIT; > if (lr_desc.state & LR_EOI_INT) > lr_val |= ICH_LR_EOI; > + if (lr_desc.state & LR_HW) { > + lr_val |= ICH_LR_HW; > + lr_val |= ((u64)lr_desc.hwirq) << ICH_LR_PHYS_ID_SHIFT; > + } > > vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val; > } > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 17/06/15 12:53, Eric Auger wrote: > On 06/08/2015 07:03 PM, Marc Zyngier wrote: >> Now that struct vgic_lr supports the LR_HW bit and carries a hwirq >> field, we can encode that information into the list registers. >> >> This patch provides implementations for both GICv2 and GICv3. >> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> >> --- >> include/linux/irqchip/arm-gic-v3.h | 3 +++ >> include/linux/irqchip/arm-gic.h | 3 ++- >> virt/kvm/arm/vgic-v2.c | 16 +++++++++++++++- >> virt/kvm/arm/vgic-v3.c | 21 ++++++++++++++++++--- >> 4 files changed, 38 insertions(+), 5 deletions(-) >> >> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h >> index ffbc034..cf637d6 100644 >> --- a/include/linux/irqchip/arm-gic-v3.h >> +++ b/include/linux/irqchip/arm-gic-v3.h >> @@ -268,9 +268,12 @@ >> >> #define ICH_LR_EOI (1UL << 41) >> #define ICH_LR_GROUP (1UL << 60) >> +#define ICH_LR_HW (1UL << 61) >> #define ICH_LR_STATE (3UL << 62) >> #define ICH_LR_PENDING_BIT (1UL << 62) >> #define ICH_LR_ACTIVE_BIT (1UL << 63) >> +#define ICH_LR_PHYS_ID_SHIFT 32 >> +#define ICH_LR_PHYS_ID_MASK (0x3ffUL << ICH_LR_PHYS_ID_SHIFT) >> >> #define ICH_MISR_EOI (1 << 0) >> #define ICH_MISR_U (1 << 1) >> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h >> index 9de976b..ca88dad 100644 >> --- a/include/linux/irqchip/arm-gic.h >> +++ b/include/linux/irqchip/arm-gic.h >> @@ -71,11 +71,12 @@ >> >> #define GICH_LR_VIRTUALID (0x3ff << 0) >> #define GICH_LR_PHYSID_CPUID_SHIFT (10) >> -#define GICH_LR_PHYSID_CPUID (7 << GICH_LR_PHYSID_CPUID_SHIFT) >> +#define GICH_LR_PHYSID_CPUID (0x3ff << GICH_LR_PHYSID_CPUID_SHIFT) >> #define GICH_LR_STATE (3 << 28) >> #define GICH_LR_PENDING_BIT (1 << 28) >> #define GICH_LR_ACTIVE_BIT (1 << 29) >> #define GICH_LR_EOI (1 << 19) >> +#define GICH_LR_HW (1 << 31) >> >> #define GICH_VMCR_CTRL_SHIFT 0 >> #define GICH_VMCR_CTRL_MASK (0x21f << GICH_VMCR_CTRL_SHIFT) >> diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c >> index f9b9c7c..8d7b04d 100644 >> --- a/virt/kvm/arm/vgic-v2.c >> +++ b/virt/kvm/arm/vgic-v2.c >> @@ -48,6 +48,10 @@ static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) >> lr_desc.state |= LR_STATE_ACTIVE; >> if (val & GICH_LR_EOI) >> lr_desc.state |= LR_EOI_INT; >> + if (val & GICH_LR_HW) { >> + lr_desc.state |= LR_HW; >> + lr_desc.hwirq = (val & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT; >> + } >> >> return lr_desc; >> } >> @@ -55,7 +59,9 @@ static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) >> static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, >> struct vgic_lr lr_desc) >> { >> - u32 lr_val = (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) | lr_desc.irq; >> + u32 lr_val; >> + >> + lr_val = lr_desc.irq; >> >> if (lr_desc.state & LR_STATE_PENDING) >> lr_val |= GICH_LR_PENDING_BIT; >> @@ -64,6 +70,14 @@ static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, >> if (lr_desc.state & LR_EOI_INT) >> lr_val |= GICH_LR_EOI; >> >> + if (lr_desc.state & LR_HW) { >> + lr_val |= GICH_LR_HW; >> + lr_val |= (u32)lr_desc.hwirq << GICH_LR_PHYSID_CPUID_SHIFT; > > shouldn't we test somewhere that the hwirq is between 16 and 1019. Else > behavior is unpredictable according to v2 spec. when queuing into the LR > we currently check the linux irq vlr.irq >= VGIC_NR_SGIS if I am not wrong. This is actually implicit. vgic_map_phys_irq() takes a parameter (irq) that is the Linux view of the hwirq we're dealing with (we fetch this hwirq by traversing the irq_data list associated with irq). SGIs are not part of the set of interrupts that can be mapped to a Linux irq (their usage is completely private to the two GIC drivers). Note that GICv3 allows SGIs to be set as a physical interrupt in an LR though, but this is not a feature we use so far. > besides Reviewed-by: Eric Auger <eric.auger@linaro.org> Thanks! M.
On 17 June 2015 at 12:53, Eric Auger <eric.auger@linaro.org> wrote:
> shouldn't we test somewhere that the hwirq is between 16 and 1019.
Not directly related, but that reminds me that I noticed the
other day that we have VGIC_MAX_IRQS = 1024 (and use that as a
guard on how many irqs we let userspace configure and ask us
to deliver), but that doesn't account for the couple of magic
numbers at the top of the range. I think that lets userspace
cause us to do UNPREDICTABLE things to the GIC...
-- PMM
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index ffbc034..cf637d6 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -268,9 +268,12 @@ #define ICH_LR_EOI (1UL << 41) #define ICH_LR_GROUP (1UL << 60) +#define ICH_LR_HW (1UL << 61) #define ICH_LR_STATE (3UL << 62) #define ICH_LR_PENDING_BIT (1UL << 62) #define ICH_LR_ACTIVE_BIT (1UL << 63) +#define ICH_LR_PHYS_ID_SHIFT 32 +#define ICH_LR_PHYS_ID_MASK (0x3ffUL << ICH_LR_PHYS_ID_SHIFT) #define ICH_MISR_EOI (1 << 0) #define ICH_MISR_U (1 << 1) diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 9de976b..ca88dad 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -71,11 +71,12 @@ #define GICH_LR_VIRTUALID (0x3ff << 0) #define GICH_LR_PHYSID_CPUID_SHIFT (10) -#define GICH_LR_PHYSID_CPUID (7 << GICH_LR_PHYSID_CPUID_SHIFT) +#define GICH_LR_PHYSID_CPUID (0x3ff << GICH_LR_PHYSID_CPUID_SHIFT) #define GICH_LR_STATE (3 << 28) #define GICH_LR_PENDING_BIT (1 << 28) #define GICH_LR_ACTIVE_BIT (1 << 29) #define GICH_LR_EOI (1 << 19) +#define GICH_LR_HW (1 << 31) #define GICH_VMCR_CTRL_SHIFT 0 #define GICH_VMCR_CTRL_MASK (0x21f << GICH_VMCR_CTRL_SHIFT) diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c index f9b9c7c..8d7b04d 100644 --- a/virt/kvm/arm/vgic-v2.c +++ b/virt/kvm/arm/vgic-v2.c @@ -48,6 +48,10 @@ static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) lr_desc.state |= LR_STATE_ACTIVE; if (val & GICH_LR_EOI) lr_desc.state |= LR_EOI_INT; + if (val & GICH_LR_HW) { + lr_desc.state |= LR_HW; + lr_desc.hwirq = (val & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT; + } return lr_desc; } @@ -55,7 +59,9 @@ static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, struct vgic_lr lr_desc) { - u32 lr_val = (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) | lr_desc.irq; + u32 lr_val; + + lr_val = lr_desc.irq; if (lr_desc.state & LR_STATE_PENDING) lr_val |= GICH_LR_PENDING_BIT; @@ -64,6 +70,14 @@ static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, if (lr_desc.state & LR_EOI_INT) lr_val |= GICH_LR_EOI; + if (lr_desc.state & LR_HW) { + lr_val |= GICH_LR_HW; + lr_val |= (u32)lr_desc.hwirq << GICH_LR_PHYSID_CPUID_SHIFT; + } + + if (lr_desc.irq < VGIC_NR_SGIS) + lr_val |= (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT); + vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = lr_val; } diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index dff0602..afbf925 100644 --- a/virt/kvm/arm/vgic-v3.c +++ b/virt/kvm/arm/vgic-v3.c @@ -67,6 +67,10 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr) lr_desc.state |= LR_STATE_ACTIVE; if (val & ICH_LR_EOI) lr_desc.state |= LR_EOI_INT; + if (val & ICH_LR_HW) { + lr_desc.state |= LR_HW; + lr_desc.hwirq = (val >> ICH_LR_PHYS_ID_SHIFT) & GENMASK(9, 0); + } return lr_desc; } @@ -84,10 +88,17 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, * Eventually we want to make this configurable, so we may revisit * this in the future. */ - if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) + switch (vcpu->kvm->arch.vgic.vgic_model) { + case KVM_DEV_TYPE_ARM_VGIC_V3: lr_val |= ICH_LR_GROUP; - else - lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; + break; + case KVM_DEV_TYPE_ARM_VGIC_V2: + if (lr_desc.irq < VGIC_NR_SGIS) + lr_val |= (u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT; + break; + default: + BUG(); + } if (lr_desc.state & LR_STATE_PENDING) lr_val |= ICH_LR_PENDING_BIT; @@ -95,6 +106,10 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, lr_val |= ICH_LR_ACTIVE_BIT; if (lr_desc.state & LR_EOI_INT) lr_val |= ICH_LR_EOI; + if (lr_desc.state & LR_HW) { + lr_val |= ICH_LR_HW; + lr_val |= ((u64)lr_desc.hwirq) << ICH_LR_PHYS_ID_SHIFT; + } vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val; }
Now that struct vgic_lr supports the LR_HW bit and carries a hwirq field, we can encode that information into the list registers. This patch provides implementations for both GICv2 and GICv3. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> --- include/linux/irqchip/arm-gic-v3.h | 3 +++ include/linux/irqchip/arm-gic.h | 3 ++- virt/kvm/arm/vgic-v2.c | 16 +++++++++++++++- virt/kvm/arm/vgic-v3.c | 21 ++++++++++++++++++--- 4 files changed, 38 insertions(+), 5 deletions(-)