KVM/arm fixes for 4.17, take #2
- Fix proxying of GICv2 CPU interface accesses - Fix crash when switching to BE - Track source vcpu git GICv2 SGIs - Fix an outdated bit of documentation -----BEGIN PGP SIGNATURE----- iQJJBAABCAAzFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAlrshkYVHG1hcmMuenlu Z2llckBhcm0uY29tAAoJECPQ0LrRPXpDK4sQAMkwRaenPNbph+IdohrZo7Px8HKR bFlz0Qyj4ksy0dNd2jVbCO/s2LgJndYKhuYWx/geVZW0Clx6GiBP53rrXbMhtkRV PvX2g9nk74OHhI80z9iyKmyt7nKOItiZTkKK6UQqXe91oZqiT5jx8G5N6Zv4DUvm +4nyNb7nP1VMimLpa5w5CFjL3nbX/VVSdHNMGmbZwDuQ2wrP3d3mfKEtSRBmIBC+ MTjV1DJxIluiIsg0hQvnnV+rTRScj0y36DzsS0th/c2BmzeYBWN/RKmQHdn1OyFj WGdiDur5vy3/WqDrHh/opFF4a5J7HSHviWGkieUF5fwd7pMsrqzv7rltMrM5rNjm ZdS49r2XRCH+nU9D72FV6N/4VJ5tmAhLjK7T5Ujz2f+fodStePkSEM69QyvhpZAJ 3dAgGiyauFzK0jVdNul3kKivfY7xHMEnYvi3SXOhtfMNl8FNBf6yR/yp9omwaQID Te9aaugLvl0b62gRlfznCCUZ9GWsyU2EjpZqztkFCfuTaokbGRiCEF+X7/Xl7cMq DmvC8T8VvLVNcSP40yJ1peeVap6px6CcQpjNKKKjyDO5ITSEZegYfO1kh8p2YOSr 3Bxd59LMgVkfDLssjMElPoo+nWmfUXxxnWmSO8ehl0/Tgw6H48R5SjoIF0iEnqek P+lMR9H9YOIBUy07 =cO6X -----END PGP SIGNATURE----- Merge tag 'kvmarm-fixes-for-4.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm KVM/arm fixes for 4.17, take #2 - Fix proxying of GICv2 CPU interface accesses - Fix crash when switching to BE - Track source vcpu git GICv2 SGIs - Fix an outdated bit of documentation
This commit is contained in:
commit
f3351c609b
@ -333,7 +333,7 @@ static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
|
|||||||
} else {
|
} else {
|
||||||
u64 sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
|
u64 sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
|
||||||
sctlr |= (1 << 25);
|
sctlr |= (1 << 25);
|
||||||
vcpu_write_sys_reg(vcpu, SCTLR_EL1, sctlr);
|
vcpu_write_sys_reg(vcpu, sctlr, SCTLR_EL1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,11 +18,20 @@
|
|||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/irqchip/arm-gic.h>
|
#include <linux/irqchip/arm-gic.h>
|
||||||
#include <linux/kvm_host.h>
|
#include <linux/kvm_host.h>
|
||||||
|
#include <linux/swab.h>
|
||||||
|
|
||||||
#include <asm/kvm_emulate.h>
|
#include <asm/kvm_emulate.h>
|
||||||
#include <asm/kvm_hyp.h>
|
#include <asm/kvm_hyp.h>
|
||||||
#include <asm/kvm_mmu.h>
|
#include <asm/kvm_mmu.h>
|
||||||
|
|
||||||
|
static bool __hyp_text __is_be(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
if (vcpu_mode_is_32bit(vcpu))
|
||||||
|
return !!(read_sysreg_el2(spsr) & COMPAT_PSR_E_BIT);
|
||||||
|
|
||||||
|
return !!(read_sysreg(SCTLR_EL1) & SCTLR_ELx_EE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
|
* __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
|
||||||
* guest.
|
* guest.
|
||||||
@ -64,14 +73,19 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
|
|||||||
addr += fault_ipa - vgic->vgic_cpu_base;
|
addr += fault_ipa - vgic->vgic_cpu_base;
|
||||||
|
|
||||||
if (kvm_vcpu_dabt_iswrite(vcpu)) {
|
if (kvm_vcpu_dabt_iswrite(vcpu)) {
|
||||||
u32 data = vcpu_data_guest_to_host(vcpu,
|
u32 data = vcpu_get_reg(vcpu, rd);
|
||||||
vcpu_get_reg(vcpu, rd),
|
if (__is_be(vcpu)) {
|
||||||
sizeof(u32));
|
/* guest pre-swabbed data, undo this for writel() */
|
||||||
|
data = swab32(data);
|
||||||
|
}
|
||||||
writel_relaxed(data, addr);
|
writel_relaxed(data, addr);
|
||||||
} else {
|
} else {
|
||||||
u32 data = readl_relaxed(addr);
|
u32 data = readl_relaxed(addr);
|
||||||
vcpu_set_reg(vcpu, rd, vcpu_data_host_to_guest(vcpu, data,
|
if (__is_be(vcpu)) {
|
||||||
sizeof(u32)));
|
/* guest expects swabbed data */
|
||||||
|
data = swab32(data);
|
||||||
|
}
|
||||||
|
vcpu_set_reg(vcpu, rd, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -131,6 +131,7 @@ struct vgic_irq {
|
|||||||
u32 mpidr; /* GICv3 target VCPU */
|
u32 mpidr; /* GICv3 target VCPU */
|
||||||
};
|
};
|
||||||
u8 source; /* GICv2 SGIs only */
|
u8 source; /* GICv2 SGIs only */
|
||||||
|
u8 active_source; /* GICv2 SGIs only */
|
||||||
u8 priority;
|
u8 priority;
|
||||||
enum vgic_irq_config config; /* Level or edge */
|
enum vgic_irq_config config; /* Level or edge */
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
|
|||||||
* We cannot rely on the vgic maintenance interrupt to be
|
* We cannot rely on the vgic maintenance interrupt to be
|
||||||
* delivered synchronously. This means we can only use it to
|
* delivered synchronously. This means we can only use it to
|
||||||
* exit the VM, and we perform the handling of EOIed
|
* exit the VM, and we perform the handling of EOIed
|
||||||
* interrupts on the exit path (see vgic_process_maintenance).
|
* interrupts on the exit path (see vgic_fold_lr_state).
|
||||||
*/
|
*/
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -289,10 +289,16 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
|
|||||||
irq->vcpu->cpu != -1) /* VCPU thread is running */
|
irq->vcpu->cpu != -1) /* VCPU thread is running */
|
||||||
cond_resched_lock(&irq->irq_lock);
|
cond_resched_lock(&irq->irq_lock);
|
||||||
|
|
||||||
if (irq->hw)
|
if (irq->hw) {
|
||||||
vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
|
vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
|
||||||
else
|
} else {
|
||||||
|
u32 model = vcpu->kvm->arch.vgic.vgic_model;
|
||||||
|
|
||||||
irq->active = active;
|
irq->active = active;
|
||||||
|
if (model == KVM_DEV_TYPE_ARM_VGIC_V2 &&
|
||||||
|
active && vgic_irq_is_sgi(irq->intid))
|
||||||
|
irq->active_source = requester_vcpu->vcpu_id;
|
||||||
|
}
|
||||||
|
|
||||||
if (irq->active)
|
if (irq->active)
|
||||||
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
|
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
|
||||||
|
@ -37,13 +37,6 @@ void vgic_v2_init_lrs(void)
|
|||||||
vgic_v2_write_lr(i, 0);
|
vgic_v2_write_lr(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vgic_v2_set_npie(struct kvm_vcpu *vcpu)
|
|
||||||
{
|
|
||||||
struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
|
|
||||||
|
|
||||||
cpuif->vgic_hcr |= GICH_HCR_NPIE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
|
void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
|
struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
|
||||||
@ -71,13 +64,18 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||||||
int lr;
|
int lr;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
cpuif->vgic_hcr &= ~(GICH_HCR_UIE | GICH_HCR_NPIE);
|
cpuif->vgic_hcr &= ~GICH_HCR_UIE;
|
||||||
|
|
||||||
for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
|
for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
|
||||||
u32 val = cpuif->vgic_lr[lr];
|
u32 val = cpuif->vgic_lr[lr];
|
||||||
u32 intid = val & GICH_LR_VIRTUALID;
|
u32 cpuid, intid = val & GICH_LR_VIRTUALID;
|
||||||
struct vgic_irq *irq;
|
struct vgic_irq *irq;
|
||||||
|
|
||||||
|
/* Extract the source vCPU id from the LR */
|
||||||
|
cpuid = val & GICH_LR_PHYSID_CPUID;
|
||||||
|
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
|
||||||
|
cpuid &= 7;
|
||||||
|
|
||||||
/* Notify fds when the guest EOI'ed a level-triggered SPI */
|
/* Notify fds when the guest EOI'ed a level-triggered SPI */
|
||||||
if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
|
if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
|
||||||
kvm_notify_acked_irq(vcpu->kvm, 0,
|
kvm_notify_acked_irq(vcpu->kvm, 0,
|
||||||
@ -90,17 +88,16 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||||||
/* Always preserve the active bit */
|
/* Always preserve the active bit */
|
||||||
irq->active = !!(val & GICH_LR_ACTIVE_BIT);
|
irq->active = !!(val & GICH_LR_ACTIVE_BIT);
|
||||||
|
|
||||||
|
if (irq->active && vgic_irq_is_sgi(intid))
|
||||||
|
irq->active_source = cpuid;
|
||||||
|
|
||||||
/* Edge is the only case where we preserve the pending bit */
|
/* Edge is the only case where we preserve the pending bit */
|
||||||
if (irq->config == VGIC_CONFIG_EDGE &&
|
if (irq->config == VGIC_CONFIG_EDGE &&
|
||||||
(val & GICH_LR_PENDING_BIT)) {
|
(val & GICH_LR_PENDING_BIT)) {
|
||||||
irq->pending_latch = true;
|
irq->pending_latch = true;
|
||||||
|
|
||||||
if (vgic_irq_is_sgi(intid)) {
|
if (vgic_irq_is_sgi(intid))
|
||||||
u32 cpuid = val & GICH_LR_PHYSID_CPUID;
|
|
||||||
|
|
||||||
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
|
|
||||||
irq->source |= (1 << cpuid);
|
irq->source |= (1 << cpuid);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -152,8 +149,15 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
|
|||||||
u32 val = irq->intid;
|
u32 val = irq->intid;
|
||||||
bool allow_pending = true;
|
bool allow_pending = true;
|
||||||
|
|
||||||
if (irq->active)
|
if (irq->active) {
|
||||||
val |= GICH_LR_ACTIVE_BIT;
|
val |= GICH_LR_ACTIVE_BIT;
|
||||||
|
if (vgic_irq_is_sgi(irq->intid))
|
||||||
|
val |= irq->active_source << GICH_LR_PHYSID_CPUID_SHIFT;
|
||||||
|
if (vgic_irq_is_multi_sgi(irq)) {
|
||||||
|
allow_pending = false;
|
||||||
|
val |= GICH_LR_EOI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (irq->hw) {
|
if (irq->hw) {
|
||||||
val |= GICH_LR_HW;
|
val |= GICH_LR_HW;
|
||||||
@ -190,8 +194,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
|
|||||||
BUG_ON(!src);
|
BUG_ON(!src);
|
||||||
val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
|
val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
|
||||||
irq->source &= ~(1 << (src - 1));
|
irq->source &= ~(1 << (src - 1));
|
||||||
if (irq->source)
|
if (irq->source) {
|
||||||
irq->pending_latch = true;
|
irq->pending_latch = true;
|
||||||
|
val |= GICH_LR_EOI;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,13 +27,6 @@ static bool group1_trap;
|
|||||||
static bool common_trap;
|
static bool common_trap;
|
||||||
static bool gicv4_enable;
|
static bool gicv4_enable;
|
||||||
|
|
||||||
void vgic_v3_set_npie(struct kvm_vcpu *vcpu)
|
|
||||||
{
|
|
||||||
struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
|
|
||||||
|
|
||||||
cpuif->vgic_hcr |= ICH_HCR_NPIE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
|
void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
|
struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
|
||||||
@ -55,17 +48,23 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||||||
int lr;
|
int lr;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
cpuif->vgic_hcr &= ~(ICH_HCR_UIE | ICH_HCR_NPIE);
|
cpuif->vgic_hcr &= ~ICH_HCR_UIE;
|
||||||
|
|
||||||
for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
|
for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
|
||||||
u64 val = cpuif->vgic_lr[lr];
|
u64 val = cpuif->vgic_lr[lr];
|
||||||
u32 intid;
|
u32 intid, cpuid;
|
||||||
struct vgic_irq *irq;
|
struct vgic_irq *irq;
|
||||||
|
bool is_v2_sgi = false;
|
||||||
|
|
||||||
if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
|
cpuid = val & GICH_LR_PHYSID_CPUID;
|
||||||
|
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
|
||||||
|
|
||||||
|
if (model == KVM_DEV_TYPE_ARM_VGIC_V3) {
|
||||||
intid = val & ICH_LR_VIRTUAL_ID_MASK;
|
intid = val & ICH_LR_VIRTUAL_ID_MASK;
|
||||||
else
|
} else {
|
||||||
intid = val & GICH_LR_VIRTUALID;
|
intid = val & GICH_LR_VIRTUALID;
|
||||||
|
is_v2_sgi = vgic_irq_is_sgi(intid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Notify fds when the guest EOI'ed a level-triggered IRQ */
|
/* Notify fds when the guest EOI'ed a level-triggered IRQ */
|
||||||
if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
|
if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
|
||||||
@ -81,18 +80,16 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||||||
/* Always preserve the active bit */
|
/* Always preserve the active bit */
|
||||||
irq->active = !!(val & ICH_LR_ACTIVE_BIT);
|
irq->active = !!(val & ICH_LR_ACTIVE_BIT);
|
||||||
|
|
||||||
|
if (irq->active && is_v2_sgi)
|
||||||
|
irq->active_source = cpuid;
|
||||||
|
|
||||||
/* Edge is the only case where we preserve the pending bit */
|
/* Edge is the only case where we preserve the pending bit */
|
||||||
if (irq->config == VGIC_CONFIG_EDGE &&
|
if (irq->config == VGIC_CONFIG_EDGE &&
|
||||||
(val & ICH_LR_PENDING_BIT)) {
|
(val & ICH_LR_PENDING_BIT)) {
|
||||||
irq->pending_latch = true;
|
irq->pending_latch = true;
|
||||||
|
|
||||||
if (vgic_irq_is_sgi(intid) &&
|
if (is_v2_sgi)
|
||||||
model == KVM_DEV_TYPE_ARM_VGIC_V2) {
|
|
||||||
u32 cpuid = val & GICH_LR_PHYSID_CPUID;
|
|
||||||
|
|
||||||
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
|
|
||||||
irq->source |= (1 << cpuid);
|
irq->source |= (1 << cpuid);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -133,10 +130,20 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
|
|||||||
{
|
{
|
||||||
u32 model = vcpu->kvm->arch.vgic.vgic_model;
|
u32 model = vcpu->kvm->arch.vgic.vgic_model;
|
||||||
u64 val = irq->intid;
|
u64 val = irq->intid;
|
||||||
bool allow_pending = true;
|
bool allow_pending = true, is_v2_sgi;
|
||||||
|
|
||||||
if (irq->active)
|
is_v2_sgi = (vgic_irq_is_sgi(irq->intid) &&
|
||||||
|
model == KVM_DEV_TYPE_ARM_VGIC_V2);
|
||||||
|
|
||||||
|
if (irq->active) {
|
||||||
val |= ICH_LR_ACTIVE_BIT;
|
val |= ICH_LR_ACTIVE_BIT;
|
||||||
|
if (is_v2_sgi)
|
||||||
|
val |= irq->active_source << GICH_LR_PHYSID_CPUID_SHIFT;
|
||||||
|
if (vgic_irq_is_multi_sgi(irq)) {
|
||||||
|
allow_pending = false;
|
||||||
|
val |= ICH_LR_EOI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (irq->hw) {
|
if (irq->hw) {
|
||||||
val |= ICH_LR_HW;
|
val |= ICH_LR_HW;
|
||||||
@ -174,8 +181,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
|
|||||||
BUG_ON(!src);
|
BUG_ON(!src);
|
||||||
val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
|
val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
|
||||||
irq->source &= ~(1 << (src - 1));
|
irq->source &= ~(1 << (src - 1));
|
||||||
if (irq->source)
|
if (irq->source) {
|
||||||
irq->pending_latch = true;
|
irq->pending_latch = true;
|
||||||
|
val |= ICH_LR_EOI;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,14 +725,6 @@ static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
|
|||||||
vgic_v3_set_underflow(vcpu);
|
vgic_v3_set_underflow(vcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void vgic_set_npie(struct kvm_vcpu *vcpu)
|
|
||||||
{
|
|
||||||
if (kvm_vgic_global_state.type == VGIC_V2)
|
|
||||||
vgic_v2_set_npie(vcpu);
|
|
||||||
else
|
|
||||||
vgic_v3_set_npie(vcpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Requires the ap_list_lock to be held. */
|
/* Requires the ap_list_lock to be held. */
|
||||||
static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
|
static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
|
||||||
bool *multi_sgi)
|
bool *multi_sgi)
|
||||||
@ -746,17 +738,15 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
|
|||||||
DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
|
DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
|
||||||
|
|
||||||
list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
|
list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
|
||||||
|
int w;
|
||||||
|
|
||||||
spin_lock(&irq->irq_lock);
|
spin_lock(&irq->irq_lock);
|
||||||
/* GICv2 SGIs can count for more than one... */
|
/* GICv2 SGIs can count for more than one... */
|
||||||
if (vgic_irq_is_sgi(irq->intid) && irq->source) {
|
w = vgic_irq_get_lr_count(irq);
|
||||||
int w = hweight8(irq->source);
|
|
||||||
|
|
||||||
count += w;
|
|
||||||
*multi_sgi |= (w > 1);
|
|
||||||
} else {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
spin_unlock(&irq->irq_lock);
|
spin_unlock(&irq->irq_lock);
|
||||||
|
|
||||||
|
count += w;
|
||||||
|
*multi_sgi |= (w > 1);
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -767,7 +757,6 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
|
|||||||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||||
struct vgic_irq *irq;
|
struct vgic_irq *irq;
|
||||||
int count;
|
int count;
|
||||||
bool npie = false;
|
|
||||||
bool multi_sgi;
|
bool multi_sgi;
|
||||||
u8 prio = 0xff;
|
u8 prio = 0xff;
|
||||||
|
|
||||||
@ -797,10 +786,8 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
|
|||||||
if (likely(vgic_target_oracle(irq) == vcpu)) {
|
if (likely(vgic_target_oracle(irq) == vcpu)) {
|
||||||
vgic_populate_lr(vcpu, irq, count++);
|
vgic_populate_lr(vcpu, irq, count++);
|
||||||
|
|
||||||
if (irq->source) {
|
if (irq->source)
|
||||||
npie = true;
|
|
||||||
prio = irq->priority;
|
prio = irq->priority;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&irq->irq_lock);
|
spin_unlock(&irq->irq_lock);
|
||||||
@ -813,9 +800,6 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (npie)
|
|
||||||
vgic_set_npie(vcpu);
|
|
||||||
|
|
||||||
vcpu->arch.vgic_cpu.used_lrs = count;
|
vcpu->arch.vgic_cpu.used_lrs = count;
|
||||||
|
|
||||||
/* Nuke remaining LRs */
|
/* Nuke remaining LRs */
|
||||||
|
@ -110,6 +110,20 @@ static inline bool vgic_irq_is_mapped_level(struct vgic_irq *irq)
|
|||||||
return irq->config == VGIC_CONFIG_LEVEL && irq->hw;
|
return irq->config == VGIC_CONFIG_LEVEL && irq->hw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int vgic_irq_get_lr_count(struct vgic_irq *irq)
|
||||||
|
{
|
||||||
|
/* Account for the active state as an interrupt */
|
||||||
|
if (vgic_irq_is_sgi(irq->intid) && irq->source)
|
||||||
|
return hweight8(irq->source) + irq->active;
|
||||||
|
|
||||||
|
return irq_is_pending(irq) || irq->active;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool vgic_irq_is_multi_sgi(struct vgic_irq *irq)
|
||||||
|
{
|
||||||
|
return vgic_irq_get_lr_count(irq) > 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct provides an intermediate representation of the fields contained
|
* This struct provides an intermediate representation of the fields contained
|
||||||
* in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC
|
* in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC
|
||||||
|
Loading…
Reference in New Issue
Block a user