mirror of
https://github.com/qemu/qemu.git
synced 2025-01-22 21:44:07 +08:00
hw/intc/arm_gic: Make ICDDCR/GICD_CTLR banked
ICDDCR/GICD_CTLR is banked if the GIC has the security extensions, and the S (or only) copy has separate enable bits for Group0 and Group1 enable if the GIC implements interrupt groups. EnableGroup0 (Bit [1]) in GICv1 is architecturally IMPDEF. Since this bit (Enable Non-secure) is present in the integrated GIC of the Cortex-A9 MPCore, we support this bit in our GICv1 implementation too. Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch> Signed-off-by: Greg Bellows <greg.bellows@linaro.org> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1430502643-25909-7-git-send-email-peter.maydell@linaro.org Message-id: 1429113742-8371-8-git-send-email-greg.bellows@linaro.org [PMM: rewritten to store the state in a single s->ctlr uint32, with the NS register handled as an alias of bit 1 in that value; added vmstate version bump] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
eb8b9530b0
commit
679aa175e8
@ -67,7 +67,8 @@ void gic_update(GICState *s)
|
||||
for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
|
||||
cm = 1 << cpu;
|
||||
s->current_pending[cpu] = 1023;
|
||||
if (!s->enabled || !s->cpu_enabled[cpu]) {
|
||||
if (!(s->ctlr & (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1))
|
||||
|| !s->cpu_enabled[cpu]) {
|
||||
qemu_irq_lower(s->parent_irq[cpu]);
|
||||
return;
|
||||
}
|
||||
@ -303,8 +304,16 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
||||
cpu = gic_get_current_cpu(s);
|
||||
cm = 1 << cpu;
|
||||
if (offset < 0x100) {
|
||||
if (offset == 0)
|
||||
return s->enabled;
|
||||
if (offset == 0) { /* GICD_CTLR */
|
||||
if (s->security_extn && !attrs.secure) {
|
||||
/* The NS bank of this register is just an alias of the
|
||||
* EnableGrp1 bit in the S bank version.
|
||||
*/
|
||||
return extract32(s->ctlr, 1, 1);
|
||||
} else {
|
||||
return s->ctlr;
|
||||
}
|
||||
}
|
||||
if (offset == 4)
|
||||
/* Interrupt Controller Type Register */
|
||||
return ((s->num_irq / 32) - 1)
|
||||
@ -475,8 +484,17 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
||||
cpu = gic_get_current_cpu(s);
|
||||
if (offset < 0x100) {
|
||||
if (offset == 0) {
|
||||
s->enabled = (value & 1);
|
||||
DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
|
||||
if (s->security_extn && !attrs.secure) {
|
||||
/* NS version is just an alias of the S version's bit 1 */
|
||||
s->ctlr = deposit32(s->ctlr, 1, 1, value);
|
||||
} else if (gic_has_groups(s)) {
|
||||
s->ctlr = value & (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1);
|
||||
} else {
|
||||
s->ctlr = value & GICD_CTLR_EN_GRP0;
|
||||
}
|
||||
DPRINTF("Distributor: Group0 %sabled; Group 1 %sabled\n",
|
||||
s->ctlr & GICD_CTLR_EN_GRP0 ? "En" : "Dis",
|
||||
s->ctlr & GICD_CTLR_EN_GRP1 ? "En" : "Dis");
|
||||
} else if (offset < 4) {
|
||||
/* ignored. */
|
||||
} else if (offset >= 0x80) {
|
||||
|
@ -59,12 +59,12 @@ static const VMStateDescription vmstate_gic_irq_state = {
|
||||
|
||||
static const VMStateDescription vmstate_gic = {
|
||||
.name = "arm_gic",
|
||||
.version_id = 8,
|
||||
.minimum_version_id = 8,
|
||||
.version_id = 9,
|
||||
.minimum_version_id = 9,
|
||||
.pre_save = gic_pre_save,
|
||||
.post_load = gic_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_BOOL(enabled, GICState),
|
||||
VMSTATE_UINT32(ctlr, GICState),
|
||||
VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU),
|
||||
VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
|
||||
vmstate_gic_irq_state, gic_irq_state),
|
||||
@ -146,7 +146,7 @@ static void arm_gic_common_reset(DeviceState *dev)
|
||||
s->irq_target[i] = 1;
|
||||
}
|
||||
}
|
||||
s->enabled = false;
|
||||
s->ctlr = 0;
|
||||
}
|
||||
|
||||
static Property arm_gic_common_properties[] = {
|
||||
|
@ -353,8 +353,8 @@ static void kvm_arm_gic_put(GICState *s)
|
||||
* Distributor State
|
||||
*/
|
||||
|
||||
/* s->enabled -> GICD_CTLR */
|
||||
reg = s->enabled;
|
||||
/* s->ctlr -> GICD_CTLR */
|
||||
reg = s->ctlr;
|
||||
kvm_gicd_access(s, 0x0, 0, ®, true);
|
||||
|
||||
/* Sanity checking on GICD_TYPER and s->num_irq, s->num_cpu */
|
||||
@ -453,9 +453,9 @@ static void kvm_arm_gic_get(GICState *s)
|
||||
* Distributor State
|
||||
*/
|
||||
|
||||
/* GICD_CTLR -> s->enabled */
|
||||
/* GICD_CTLR -> s->ctlr */
|
||||
kvm_gicd_access(s, 0x0, 0, ®, false);
|
||||
s->enabled = reg & 1;
|
||||
s->ctlr = reg;
|
||||
|
||||
/* Sanity checking on GICD_TYPER -> s->num_irq, s->num_cpu */
|
||||
kvm_gicd_access(s, 0x4, 0, ®, false);
|
||||
|
@ -477,7 +477,7 @@ static void armv7m_nvic_reset(DeviceState *dev)
|
||||
s->gic.cpu_enabled[0] = true;
|
||||
s->gic.priority_mask[0] = 0x100;
|
||||
/* The NVIC as a whole is always enabled. */
|
||||
s->gic.enabled = true;
|
||||
s->gic.ctlr = 1;
|
||||
systick_reset(s);
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,8 @@
|
||||
#define GIC_SET_GROUP(irq, cm) (s->irq_state[irq].group |= (cm))
|
||||
#define GIC_TEST_GROUP(irq, cm) ((s->irq_state[irq].group & (cm)) != 0)
|
||||
|
||||
#define GICD_CTLR_EN_GRP0 (1U << 0)
|
||||
#define GICD_CTLR_EN_GRP1 (1U << 1)
|
||||
|
||||
/* The special cases for the revision property: */
|
||||
#define REV_11MPCORE 0
|
||||
|
@ -52,7 +52,10 @@ typedef struct GICState {
|
||||
|
||||
qemu_irq parent_irq[GIC_NCPU];
|
||||
qemu_irq parent_fiq[GIC_NCPU];
|
||||
bool enabled;
|
||||
/* GICD_CTLR; for a GIC with the security extensions the NS banked version
|
||||
* of this register is just an alias of bit 1 of the S banked version.
|
||||
*/
|
||||
uint32_t ctlr;
|
||||
bool cpu_enabled[GIC_NCPU];
|
||||
|
||||
gic_irq_state irq_state[GIC_MAXIRQ];
|
||||
|
Loading…
Reference in New Issue
Block a user