intc/arm_gic: Implement virtualization extensions in gic_(activate_irq|drop_prio)
Implement virtualization extensions in gic_activate_irq() and gic_drop_prio() and in gic_get_prio_from_apr_bits() called by gic_drop_prio(). When the current CPU is a vCPU: - Use GIC_VIRT_MIN_BPR and GIC_VIRT_NR_APRS instead of their non-virt counterparts, - the vCPU APR is stored in the virtual interface, in h_apr. Signed-off-by: Luc Michel <luc.michel@greensocs.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20180727095421.386-11-luc.michel@greensocs.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
86b350f0d0
commit
a1d7b8d896
@ -276,16 +276,23 @@ static void gic_activate_irq(GICState *s, int cpu, int irq)
|
||||
* and update the running priority.
|
||||
*/
|
||||
int prio = gic_get_group_priority(s, cpu, irq);
|
||||
int preemption_level = prio >> (GIC_MIN_BPR + 1);
|
||||
int min_bpr = gic_is_vcpu(cpu) ? GIC_VIRT_MIN_BPR : GIC_MIN_BPR;
|
||||
int preemption_level = prio >> (min_bpr + 1);
|
||||
int regno = preemption_level / 32;
|
||||
int bitno = preemption_level % 32;
|
||||
uint32_t *papr = NULL;
|
||||
|
||||
if (gic_has_groups(s) && gic_test_group(s, irq, cpu)) {
|
||||
s->nsapr[regno][cpu] |= (1 << bitno);
|
||||
if (gic_is_vcpu(cpu)) {
|
||||
assert(regno == 0);
|
||||
papr = &s->h_apr[gic_get_vcpu_real_id(cpu)];
|
||||
} else if (gic_has_groups(s) && gic_test_group(s, irq, cpu)) {
|
||||
papr = &s->nsapr[regno][cpu];
|
||||
} else {
|
||||
s->apr[regno][cpu] |= (1 << bitno);
|
||||
papr = &s->apr[regno][cpu];
|
||||
}
|
||||
|
||||
*papr |= (1 << bitno);
|
||||
|
||||
s->running_priority[cpu] = prio;
|
||||
gic_set_active(s, irq, cpu);
|
||||
}
|
||||
@ -296,6 +303,16 @@ static int gic_get_prio_from_apr_bits(GICState *s, int cpu)
|
||||
* on the set bits in the Active Priority Registers.
|
||||
*/
|
||||
int i;
|
||||
|
||||
if (gic_is_vcpu(cpu)) {
|
||||
uint32_t apr = s->h_apr[gic_get_vcpu_real_id(cpu)];
|
||||
if (apr) {
|
||||
return ctz32(apr) << (GIC_VIRT_MIN_BPR + 1);
|
||||
} else {
|
||||
return 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < GIC_NR_APRS; i++) {
|
||||
uint32_t apr = s->apr[i][cpu] | s->nsapr[i][cpu];
|
||||
if (!apr) {
|
||||
@ -324,16 +341,25 @@ static void gic_drop_prio(GICState *s, int cpu, int group)
|
||||
* running priority will be wrong, so interrupts that should preempt
|
||||
* might not do so, and interrupts that should not preempt might do so.
|
||||
*/
|
||||
int i;
|
||||
if (gic_is_vcpu(cpu)) {
|
||||
int rcpu = gic_get_vcpu_real_id(cpu);
|
||||
|
||||
for (i = 0; i < GIC_NR_APRS; i++) {
|
||||
uint32_t *papr = group ? &s->nsapr[i][cpu] : &s->apr[i][cpu];
|
||||
if (!*papr) {
|
||||
continue;
|
||||
if (s->h_apr[rcpu]) {
|
||||
/* Clear lowest set bit */
|
||||
s->h_apr[rcpu] &= s->h_apr[rcpu] - 1;
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GIC_NR_APRS; i++) {
|
||||
uint32_t *papr = group ? &s->nsapr[i][cpu] : &s->apr[i][cpu];
|
||||
if (!*papr) {
|
||||
continue;
|
||||
}
|
||||
/* Clear lowest set bit */
|
||||
*papr &= *papr - 1;
|
||||
break;
|
||||
}
|
||||
/* Clear lowest set bit */
|
||||
*papr &= *papr - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
s->running_priority[cpu] = gic_get_prio_from_apr_bits(s, cpu);
|
||||
|
Loading…
Reference in New Issue
Block a user