if ( rank == NULL) goto read_as_zero;
vgic_lock_rank(v, rank, flags);
- *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
- DABT_WORD)];
+ *r = rank->ipriorityr[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
+ DABT_WORD)];
if ( dabt.size == DABT_BYTE )
*r = vgic_byte_read(*r, gicd_reg);
vgic_unlock_rank(v, rank, flags);
if ( rank == NULL) goto write_ignore;
vgic_lock_rank(v, rank, flags);
if ( dabt.size == DABT_WORD )
- rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
- DABT_WORD)] = r;
+ rank->ipriorityr[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
+ DABT_WORD)] = r;
else
- vgic_byte_write(&rank->ipriority[REG_RANK_INDEX(8,
+ vgic_byte_write(&rank->ipriorityr[REG_RANK_INDEX(8,
gicd_reg - GICD_IPRIORITYR, DABT_WORD)], r, gicd_reg);
vgic_unlock_rank(v, rank, flags);
return 1;
return v_target;
}
-static int vgic_v2_get_irq_priority(struct vcpu *v, unsigned int irq)
-{
- int priority;
- struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
-
- ASSERT(spin_is_locked(&rank->lock));
- priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8,
- irq, DABT_WORD)], irq & 0x3);
-
- return priority;
-}
-
static int vgic_v2_vcpu_init(struct vcpu *v)
{
int i;
static const struct vgic_ops vgic_v2_ops = {
.vcpu_init = vgic_v2_vcpu_init,
.domain_init = vgic_v2_domain_init,
- .get_irq_priority = vgic_v2_get_irq_priority,
.get_target_vcpu = vgic_v2_get_target_vcpu,
.max_vcpus = 8,
};
if ( rank == NULL ) goto read_as_zero;
vgic_lock_rank(v, rank, flags);
- *r = rank->ipriority[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR,
- DABT_WORD)];
+ *r = rank->ipriorityr[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR,
+ DABT_WORD)];
if ( dabt.size == DABT_BYTE )
*r = vgic_byte_read(*r, reg);
vgic_unlock_rank(v, rank, flags);
if ( rank == NULL ) goto write_ignore;
vgic_lock_rank(v, rank, flags);
if ( dabt.size == DABT_WORD )
- rank->ipriority[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR,
- DABT_WORD)] = r;
+ rank->ipriorityr[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR,
+ DABT_WORD)] = r;
else
- vgic_byte_write(&rank->ipriority[REG_RANK_INDEX(8,
+ vgic_byte_write(&rank->ipriorityr[REG_RANK_INDEX(8,
reg - GICD_IPRIORITYR, DABT_WORD)], r, reg);
vgic_unlock_rank(v, rank, flags);
return 1;
.write = vgic_v3_distr_mmio_write,
};
-static int vgic_v3_get_irq_priority(struct vcpu *v, unsigned int irq)
-{
- int priority;
- struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
-
- ASSERT(spin_is_locked(&rank->lock));
- priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8,
- irq, DABT_WORD)], irq & 0x3);
-
- return priority;
-}
-
static int vgic_v3_vcpu_init(struct vcpu *v)
{
int i;
static const struct vgic_ops v3_ops = {
.vcpu_init = vgic_v3_vcpu_init,
.domain_init = vgic_v3_domain_init,
- .get_irq_priority = vgic_v3_get_irq_priority,
.get_target_vcpu = vgic_v3_get_target_vcpu,
.emulate_sysreg = vgic_v3_emulate_sysreg,
/*
return v_target;
}
+static int vgic_get_virq_priority(struct vcpu *v, unsigned int virq)
+{
+ struct vgic_irq_rank *rank = vgic_rank_irq(v, virq);
+ unsigned long flags;
+ int priority;
+
+ vgic_lock_rank(v, rank, flags);
+ priority = rank->priority[virq & INTERRUPT_RANK_MASK];
+ vgic_unlock_rank(v, rank, flags);
+
+ return priority;
+}
+
void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int irq)
{
unsigned long flags;
void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int virq)
{
uint8_t priority;
- struct vgic_irq_rank *rank = vgic_rank_irq(v, virq);
struct pending_irq *iter, *n = irq_to_pending(v, virq);
unsigned long flags;
bool_t running;
- vgic_lock_rank(v, rank, flags);
- priority = v->domain->arch.vgic.handler->get_irq_priority(v, virq);
- vgic_unlock_rank(v, rank, flags);
+ priority = vgic_get_virq_priority(v, virq);
spin_lock_irqsave(&v->arch.vgic.lock, flags);
struct list_head lr_queue;
};
+#define NR_INTERRUPT_PER_RANK 32
+#define INTERRUPT_RANK_MASK (NR_INTERRUPT_PER_RANK - 1)
+
/* Represents state corresponding to a block of 32 interrupts */
struct vgic_irq_rank {
spinlock_t lock; /* Covers access to all other members of this struct */
uint32_t ienable;
uint32_t icfg[2];
- uint32_t ipriority[8];
+
+ /*
+ * Provide efficient access to the priority of an vIRQ while keeping
+ * the emulation simple.
+ * Note, this is working fine as long as Xen is using little endian.
+ */
+ union {
+ uint8_t priority[32];
+ uint32_t ipriorityr[8];
+ };
+
union {
struct {
uint32_t itargets[8];
int (*vcpu_init)(struct vcpu *v);
/* Domain specific initialization of vGIC */
int (*domain_init)(struct domain *d);
- /* Get priority for a given irq stored in vgic structure */
- int (*get_irq_priority)(struct vcpu *v, unsigned int irq);
/* Get the target vcpu for a given virq. The rank lock is already taken
* when calling this. */
struct vcpu *(*get_target_vcpu)(struct vcpu *v, unsigned int irq);