KVM: ARM: vgic: abstract access to the ELRSR bitmap
Move the GICH_ELRSR access to its own functions, and add them to the vgic_ops structure. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
8d5c6b06a5
commit
69bb2c9fbc
2 changed files with 43 additions and 5 deletions
|
@ -84,6 +84,8 @@ struct vgic_lr {
|
|||
struct vgic_ops {
|
||||
struct vgic_lr (*get_lr)(const struct kvm_vcpu *, int);
|
||||
void (*set_lr)(struct kvm_vcpu *, int, struct vgic_lr);
|
||||
void (*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr);
|
||||
u64 (*get_elrsr)(const struct kvm_vcpu *vcpu);
|
||||
};
|
||||
|
||||
struct vgic_dist {
|
||||
|
|
|
@ -1015,9 +1015,32 @@ static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr,
|
|||
vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = lr_val;
|
||||
}
|
||||
|
||||
static void vgic_v2_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
|
||||
struct vgic_lr lr_desc)
|
||||
{
|
||||
if (!(lr_desc.state & LR_STATE_MASK))
|
||||
set_bit(lr, (unsigned long *)vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr);
|
||||
}
|
||||
|
||||
static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 val;
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
val = vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr[1];
|
||||
val <<= 32;
|
||||
val |= vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr[0];
|
||||
#else
|
||||
val = *(u64 *)vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr;
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
|
||||
static const struct vgic_ops vgic_ops = {
|
||||
.get_lr = vgic_v2_get_lr,
|
||||
.set_lr = vgic_v2_set_lr,
|
||||
.sync_lr_elrsr = vgic_v2_sync_lr_elrsr,
|
||||
.get_elrsr = vgic_v2_get_elrsr,
|
||||
};
|
||||
|
||||
static struct vgic_lr vgic_get_lr(const struct kvm_vcpu *vcpu, int lr)
|
||||
|
@ -1031,6 +1054,17 @@ static void vgic_set_lr(struct kvm_vcpu *vcpu, int lr,
|
|||
vgic_ops.set_lr(vcpu, lr, vlr);
|
||||
}
|
||||
|
||||
static void vgic_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
|
||||
struct vgic_lr vlr)
|
||||
{
|
||||
vgic_ops.sync_lr_elrsr(vcpu, lr, vlr);
|
||||
}
|
||||
|
||||
static inline u64 vgic_get_elrsr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return vgic_ops.get_elrsr(vcpu);
|
||||
}
|
||||
|
||||
static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||
|
@ -1260,7 +1294,7 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
|
|||
* Despite being EOIed, the LR may not have
|
||||
* been marked as empty.
|
||||
*/
|
||||
set_bit(lr, (unsigned long *)vgic_cpu->vgic_v2.vgic_elrsr);
|
||||
vgic_sync_lr_elrsr(vcpu, lr, vlr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1278,14 +1312,17 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||
struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
|
||||
u64 elrsr;
|
||||
unsigned long *elrsr_ptr;
|
||||
int lr, pending;
|
||||
bool level_pending;
|
||||
|
||||
level_pending = vgic_process_maintenance(vcpu);
|
||||
elrsr = vgic_get_elrsr(vcpu);
|
||||
elrsr_ptr = (unsigned long *)&elrsr;
|
||||
|
||||
/* Clear mappings for empty LRs */
|
||||
for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_v2.vgic_elrsr,
|
||||
vgic_cpu->nr_lr) {
|
||||
for_each_set_bit(lr, elrsr_ptr, vgic_cpu->nr_lr) {
|
||||
struct vgic_lr vlr;
|
||||
|
||||
if (!test_and_clear_bit(lr, vgic_cpu->lr_used))
|
||||
|
@ -1298,8 +1335,7 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
|
||||
/* Check if we still have something up our sleeve... */
|
||||
pending = find_first_zero_bit((unsigned long *)vgic_cpu->vgic_v2.vgic_elrsr,
|
||||
vgic_cpu->nr_lr);
|
||||
pending = find_first_zero_bit(elrsr_ptr, vgic_cpu->nr_lr);
|
||||
if (level_pending || pending < vgic_cpu->nr_lr)
|
||||
set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue