|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v8 4/8] xen/arm: Use AFF1 when translating ICC_SGI1R_EL1 to cpumask
From: Chen Baozi <baozich@xxxxxxxxx>
The old unsigned long type of vcpu_mask can only express 64 cpus at the
most, which might not be enough for the guest which used vGICv3. We
introduce a new struct sgi_target for the target cpu list of SGI, which
holds the affinity path information (only level 1 at the moment). For
GICv2 that has no affinity level, we can just set the corresponding
fields to be 0.
Signed-off-by: Chen Baozi <baozich@xxxxxxxxx>
---
xen/arch/arm/vgic-v2.c | 7 +++---
xen/arch/arm/vgic-v3.c | 10 +++++----
xen/arch/arm/vgic.c | 45 +++++++++++++++++----------------------
xen/include/asm-arm/gic_v3_defs.h | 3 +++
xen/include/asm-arm/vgic.h | 7 +++++-
5 files changed, 38 insertions(+), 34 deletions(-)
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 3be1a51..5949cf1 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -201,16 +201,17 @@ static int vgic_v2_to_sgi(struct vcpu *v, register_t sgir)
int virq;
int irqmode;
enum gic_sgi_mode sgi_mode;
- unsigned long vcpu_mask = 0;
+ struct sgi_target target;
+ memset(&target, 0, sizeof(struct sgi_target));
irqmode = (sgir & GICD_SGI_TARGET_LIST_MASK) >> GICD_SGI_TARGET_LIST_SHIFT;
virq = (sgir & GICD_SGI_INTID_MASK);
- vcpu_mask = (sgir & GICD_SGI_TARGET_MASK) >> GICD_SGI_TARGET_SHIFT;
/* Map GIC sgi value to enum value */
switch ( irqmode )
{
case GICD_SGI_TARGET_LIST_VAL:
+ target.list = (sgir & GICD_SGI_TARGET_MASK) >> GICD_SGI_TARGET_SHIFT;
sgi_mode = SGI_TARGET_LIST;
break;
case GICD_SGI_TARGET_OTHERS_VAL:
@@ -226,7 +227,7 @@ static int vgic_v2_to_sgi(struct vcpu *v, register_t sgir)
return 0;
}
- return vgic_to_sgi(v, sgir, sgi_mode, virq, vcpu_mask);
+ return vgic_to_sgi(v, sgir, sgi_mode, virq, &target);
}
static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index ef9a71a..93610d0 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -977,17 +977,19 @@ static int vgic_v3_to_sgi(struct vcpu *v, register_t sgir)
int virq;
int irqmode;
enum gic_sgi_mode sgi_mode;
- unsigned long vcpu_mask = 0;
+ struct sgi_target target;
+ memset(&target, 0, sizeof(struct sgi_target));
irqmode = (sgir >> ICH_SGI_IRQMODE_SHIFT) & ICH_SGI_IRQMODE_MASK;
virq = (sgir >> ICH_SGI_IRQ_SHIFT ) & ICH_SGI_IRQ_MASK;
- /* SGI's are injected at Rdist level 0. ignoring affinity 1, 2, 3 */
- vcpu_mask = sgir & ICH_SGI_TARGETLIST_MASK;
/* Map GIC sgi value to enum value */
switch ( irqmode )
{
case ICH_SGI_TARGET_LIST:
+ /* We assume that only AFF1 is used in ICC_SGI1R_EL1. */
+ target.aff1 = (sgir >> ICH_SGI_AFFINITY_LEVEL(1)) & ICH_SGI_AFFx_MASK;
+ target.list = sgir & ICH_SGI_TARGETLIST_MASK;
sgi_mode = SGI_TARGET_LIST;
break;
case ICH_SGI_TARGET_OTHERS:
@@ -998,7 +1000,7 @@ static int vgic_v3_to_sgi(struct vcpu *v, register_t sgir)
return 0;
}
- return vgic_to_sgi(v, sgir, sgi_mode, virq, vcpu_mask);
+ return vgic_to_sgi(v, sgir, sgi_mode, virq, &target);
}
static int vgic_v3_emulate_sysreg(struct cpu_user_regs *regs, union hsr hsr)
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 7b387b7..59bd98a 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -318,15 +318,14 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
}
}
-/* TODO: unsigned long is used to fit vcpu_mask.*/
int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode,
int virq,
- unsigned long vcpu_mask)
+ const struct sgi_target *target)
{
struct domain *d = v->domain;
int vcpuid;
int i;
-
- ASSERT(d->max_vcpus < 8*sizeof(vcpu_mask));
+ unsigned int base;
+ unsigned long int bitmap;
ASSERT( virq < 16 );
@@ -334,29 +333,33 @@ int vgic_to_sgi(struct vcpu *v, register_t sgir, enum
gic_sgi_mode irqmode, int
{
case SGI_TARGET_LIST:
perfc_incr(vgic_sgi_list);
+ base = target->aff1 << 4;
+ bitmap = target->list;
+ for_each_set_bit( i, &bitmap, sizeof(target->list) * 8 )
+ {
+ vcpuid = base + i;
+ if ( d->vcpu[vcpuid] != NULL && !is_vcpu_online(d->vcpu[vcpuid]) )
+ {
+ gprintk(XENLOG_WARNING, "VGIC: write r=%"PRIregister" \
+ target->list=%hx, wrong CPUTargetList \n",
+ sgir, target->list);
+ continue;
+ }
+ vgic_vcpu_inject_irq(d->vcpu[vcpuid], virq);
+ }
break;
case SGI_TARGET_OTHERS:
- /*
- * We expect vcpu_mask to be 0 for SGI_TARGET_OTHERS and
- * SGI_TARGET_SELF mode. So Force vcpu_mask to 0
- */
perfc_incr(vgic_sgi_others);
- vcpu_mask = 0;
for ( i = 0; i < d->max_vcpus; i++ )
{
if ( i != current->vcpu_id && d->vcpu[i] != NULL &&
is_vcpu_online(d->vcpu[i]) )
- set_bit(i, &vcpu_mask);
+ vgic_vcpu_inject_irq(d->vcpu[i], virq);
}
break;
case SGI_TARGET_SELF:
- /*
- * We expect vcpu_mask to be 0 for SGI_TARGET_OTHERS and
- * SGI_TARGET_SELF mode. So Force vcpu_mask to 0
- */
perfc_incr(vgic_sgi_self);
- vcpu_mask = 0;
- set_bit(current->vcpu_id, &vcpu_mask);
+ vgic_vcpu_inject_irq(d->vcpu[current->vcpu_id], virq);
break;
default:
gprintk(XENLOG_WARNING,
@@ -365,16 +368,6 @@ int vgic_to_sgi(struct vcpu *v, register_t sgir, enum
gic_sgi_mode irqmode, int
return 0;
}
- for_each_set_bit( vcpuid, &vcpu_mask, d->max_vcpus )
- {
- if ( d->vcpu[vcpuid] != NULL && !is_vcpu_online(d->vcpu[vcpuid]) )
- {
- gprintk(XENLOG_WARNING, "VGIC: write r=%"PRIregister" \
- vcpu_mask=%lx, wrong CPUTargetList\n", sgir, vcpu_mask);
- continue;
- }
- vgic_vcpu_inject_irq(d->vcpu[vcpuid], virq);
- }
return 1;
}
diff --git a/xen/include/asm-arm/gic_v3_defs.h
b/xen/include/asm-arm/gic_v3_defs.h
index 556f114..960669d 100644
--- a/xen/include/asm-arm/gic_v3_defs.h
+++ b/xen/include/asm-arm/gic_v3_defs.h
@@ -152,6 +152,9 @@
#define ICH_SGI_IRQ_SHIFT 24
#define ICH_SGI_IRQ_MASK 0xf
#define ICH_SGI_TARGETLIST_MASK 0xffff
+#define ICH_SGI_AFFx_MASK 0xff
+#define ICH_SGI_AFFINITY_LEVEL(x) (16 * (x))
+
#endif /* __ASM_ARM_GIC_V3_DEFS_H__ */
/*
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 6dcdf9f..d68539a 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -98,6 +98,11 @@ struct vgic_irq_rank {
};
};
+struct sgi_target {
+ uint8_t aff1;
+ uint16_t list;
+};
+
struct vgic_ops {
/* Initialize vGIC */
int (*vcpu_init)(struct vcpu *v);
@@ -201,7 +206,7 @@ DEFINE_VGIC_OPS(3)
extern int vcpu_vgic_free(struct vcpu *v);
extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
enum gic_sgi_mode irqmode, int virq,
- unsigned long vcpu_mask);
+ const struct sgi_target *target);
extern void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int
irq);
/* Reserve a specific guest vIRQ */
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |