Skip to content

Commit

Permalink
KVM: arm/arm64: vgic-new: Add PRIORITY registers handlers
Browse files Browse the repository at this point in the history
The priority register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
There is a corner case when we change the priority of a pending
interrupt which we don't handle at the moment.

Signed-off-by: Andre Przywara <[email protected]>
Reviewed-by: Christoffer Dall <[email protected]>
  • Loading branch information
Andre-ARM authored and chazy committed May 20, 2016
1 parent 69b6fe0 commit 055658b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 1 deletion.
2 changes: 1 addition & 1 deletion virt/kvm/arm/vgic/vgic-mmio-v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
Expand Down
40 changes: 40 additions & 0 deletions virt/kvm/arm/vgic/vgic-mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,46 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
}
}

unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len)
{
u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
int i;
u64 val = 0;

for (i = 0; i < len; i++) {
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);

val |= (u64)irq->priority << (i * 8);
}

return val;
}

/*
* We currently don't handle changing the priority of an interrupt that
* is already pending on a VCPU. If there is a need for this, we would
* need to make this VCPU exit and re-evaluate the priorities, potentially
* leading to this interrupt getting presented now to the guest (if it has
* been masked by the priority mask before).
*/
void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val)
{
u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
int i;

for (i = 0; i < len; i++) {
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);

spin_lock(&irq->irq_lock);
/* Narrow the priority range to what we actually support */
irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
spin_unlock(&irq->irq_lock);
}
}

static int match_region(const void *key, const void *elt)
{
const unsigned int offset = (unsigned long)key;
Expand Down
7 changes: 7 additions & 0 deletions virt/kvm/arm/vgic/vgic-mmio.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val);

unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len);

void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val);

unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);

#endif
2 changes: 2 additions & 0 deletions virt/kvm/arm/vgic/vgic.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#define PRODUCT_ID_KVM 0x4b /* ASCII code K */
#define IMPLEMENTER_ARM 0x43b

#define VGIC_PRI_BITS 5

#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)

struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
Expand Down

0 comments on commit 055658b

Please sign in to comment.