|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] xen/arm: vgic: Optimize the way to store GICD_IPRIORITYR in the rank
commit f699fd55e9860aa207945abbaadac44855caf6e5
Author: Julien Grall <julien.grall@xxxxxxxxxx>
AuthorDate: Wed Oct 7 15:41:07 2015 +0100
Commit: Ian Campbell <ian.campbell@xxxxxxxxxx>
CommitDate: Thu Oct 8 12:22:46 2015 +0100
xen/arm: vgic: Optimize the way to store GICD_IPRIORITYR in the rank
Xen is currently directly storing the value of GICD_IPRIORITYR register
in the rank. This makes emulation of the register access very simple
but makes the code to get the priority for a given vIRQ more complex.
While the priority of an vIRQ is retrieved every time an vIRQ is injected
to the guest, the access to register occurs less often.
Each GICD_IPRIORITYR register stores 4 priorities associated for 4 vIRQs
(see 4.3.11 in IHI 0048B). As Xen is using little endian, we can use
an union to access directly a register or a priority for a given IRQ.
Note that the field "ipriority" has been renamed to "ipriorityr" to
match the name of the register in the GIC spec.
Finally, the implementation of the callback get_irq_priority is exactly
the same for both vGIC drivers. Consolidate the implementation in the
common vGIC code and drop the callback.
Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
xen/arch/arm/vgic-v2.c | 23 +++++------------------
xen/arch/arm/vgic-v3.c | 23 +++++------------------
xen/arch/arm/vgic.c | 18 ++++++++++++++----
xen/include/asm-arm/vgic.h | 17 ++++++++++++++---
4 files changed, 38 insertions(+), 43 deletions(-)
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index dcbba0f..ad1bb15 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -139,8 +139,8 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v,
mmio_info_t *info,
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);
@@ -405,10 +405,10 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v,
mmio_info_t *info,
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;
@@ -514,18 +514,6 @@ static struct vcpu *vgic_v2_get_target_vcpu(struct vcpu
*v, unsigned int irq)
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;
@@ -597,7 +585,6 @@ static int vgic_v2_domain_init(struct domain *d)
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,
};
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 6de7f00..92a3ccf 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -333,8 +333,8 @@ static int __vgic_v3_distr_common_mmio_read(const char
*name, struct vcpu *v,
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);
@@ -435,10 +435,10 @@ static int __vgic_v3_distr_common_mmio_write(const char
*name, struct vcpu *v,
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;
@@ -1035,18 +1035,6 @@ static const struct mmio_handler_ops
vgic_distr_mmio_handler = {
.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;
@@ -1196,7 +1184,6 @@ static int vgic_v3_domain_init(struct domain *d)
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,
/*
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index a6835a8..2128d29 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -204,6 +204,19 @@ struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned
int irq)
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;
@@ -407,14 +420,11 @@ void vgic_clear_pending_irqs(struct vcpu *v)
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);
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 354c0d4..ff98913 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -82,12 +82,25 @@ struct pending_irq
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];
@@ -114,8 +127,6 @@ struct vgic_ops {
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);
--
generated by git-patchbot for /home/xen/git/xen.git#master
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |