On Fri, May 01, 2015 at 06:50:36PM +0100, Peter Maydell wrote: > From: Fabian Aggeler <aggel...@ethz.ch> > > GICs with Security Extensions restrict the non-secure view of the > interrupt priority and priority mask registers. > > Signed-off-by: Fabian Aggeler <aggel...@ethz.ch> > Signed-off-by: Greg Bellows <greg.bell...@linaro.org> > Message-id: 1429113742-8371-15-git-send-email-greg.bell...@linaro.org > [PMM: minor code tweaks; fixed missing masking in gic_set_priority_mask > and gic_set_priority] > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.igles...@xilinx.com> > --- > hw/intc/arm_gic.c | 63 > ++++++++++++++++++++++++++++++++++++++++++++++---- > hw/intc/arm_gic_kvm.c | 2 +- > hw/intc/gic_internal.h | 3 ++- > 3 files changed, 61 insertions(+), 7 deletions(-) > > diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c > index e3bbe9e..7c0ddc8 100644 > --- a/hw/intc/arm_gic.c > +++ b/hw/intc/arm_gic.c > @@ -233,8 +233,16 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu) > return ret; > } > > -void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val) > +void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val, > + MemTxAttrs attrs) > { > + if (s->security_extn && !attrs.secure) { > + if (!GIC_TEST_GROUP(irq, (1 << cpu))) { > + return; /* Ignore Non-secure access of Group0 IRQ */ > + } > + val = 0x80 | (val >> 1); /* Non-secure view */ > + } > + > if (irq < GIC_INTERNAL) { > s->priority1[irq][cpu] = val; > } else { > @@ -242,6 +250,51 @@ void gic_set_priority(GICState *s, int cpu, int irq, > uint8_t val) > } > } > > +static uint32_t gic_get_priority(GICState *s, int cpu, int irq, > + MemTxAttrs attrs) > +{ > + uint32_t prio = GIC_GET_PRIORITY(irq, cpu); > + > + if (s->security_extn && !attrs.secure) { > + if (!GIC_TEST_GROUP(irq, (1 << cpu))) { > + return 0; /* Non-secure access cannot read priority of Group0 > IRQ */ > + } > + prio = (prio << 1) & 0xff; /* Non-secure view */ > + } > + return prio; > +} > + > +static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask, > + MemTxAttrs attrs) > +{ > + if (s->security_extn && !attrs.secure) { > + if (s->priority_mask[cpu] & 0x80) { > + /* Priority Mask in upper half */ > + pmask = 0x80 | (pmask >> 1); > + } else { > + /* Non-secure write ignored if priority mask is in lower half */ > + return; > + } > + } > + s->priority_mask[cpu] = pmask; > +} > + > +static uint32_t gic_get_priority_mask(GICState *s, int cpu, MemTxAttrs attrs) > +{ > + uint32_t pmask = s->priority_mask[cpu]; > + > + if (s->security_extn && !attrs.secure) { > + if (pmask & 0x80) { > + /* Priority Mask in upper half, return Non-secure view */ > + pmask = (pmask << 1) & 0xff; > + } else { > + /* Priority Mask in lower half, RAZ */ > + pmask = 0; > + } > + } > + return pmask; > +} > + > static uint32_t gic_get_cpu_control(GICState *s, int cpu, MemTxAttrs attrs) > { > uint32_t ret = s->cpu_ctlr[cpu]; > @@ -451,7 +504,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr > offset, MemTxAttrs attrs) > irq = (offset - 0x400) + GIC_BASE_IRQ; > if (irq >= s->num_irq) > goto bad_reg; > - res = GIC_GET_PRIORITY(irq, cpu); > + res = gic_get_priority(s, cpu, irq, attrs); > } else if (offset < 0xc00) { > /* Interrupt CPU Target. */ > if (s->num_cpu == 1 && s->revision != REV_11MPCORE) { > @@ -669,7 +722,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, > irq = (offset - 0x400) + GIC_BASE_IRQ; > if (irq >= s->num_irq) > goto bad_reg; > - gic_set_priority(s, cpu, irq, value); > + gic_set_priority(s, cpu, irq, value, attrs); > } else if (offset < 0xc00) { > /* Interrupt CPU Target. RAZ/WI on uniprocessor GICs, with the > * annoying exception of the 11MPCore's GIC. > @@ -820,7 +873,7 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int > offset, > *data = gic_get_cpu_control(s, cpu, attrs); > break; > case 0x04: /* Priority mask */ > - *data = s->priority_mask[cpu]; > + *data = gic_get_priority_mask(s, cpu, attrs); > break; > case 0x08: /* Binary Point */ > if (s->security_extn && !attrs.secure) { > @@ -870,7 +923,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, > int offset, > gic_set_cpu_control(s, cpu, value, attrs); > break; > case 0x04: /* Priority mask */ > - s->priority_mask[cpu] = (value & 0xff); > + gic_set_priority_mask(s, cpu, value, attrs); > break; > case 0x08: /* Binary Point */ > if (s->security_extn && !attrs.secure) { > diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c > index c5a2f81..54f18df 100644 > --- a/hw/intc/arm_gic_kvm.c > +++ b/hw/intc/arm_gic_kvm.c > @@ -251,7 +251,7 @@ static void translate_priority(GICState *s, int irq, int > cpu, > if (to_kernel) { > *field = GIC_GET_PRIORITY(irq, cpu) & 0xff; > } else { > - gic_set_priority(s, cpu, irq, *field & 0xff); > + gic_set_priority(s, cpu, irq, *field & 0xff, MEMTXATTRS_UNSPECIFIED); > } > } > > diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h > index 81c764c..119fb81 100644 > --- a/hw/intc/gic_internal.h > +++ b/hw/intc/gic_internal.h > @@ -82,7 +82,8 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu); > void gic_complete_irq(GICState *s, int cpu, int irq); > void gic_update(GICState *s); > void gic_init_irqs_and_distributor(GICState *s); > -void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val); > +void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val, > + MemTxAttrs attrs); > > static inline bool gic_test_pending(GICState *s, int irq, int cm) > { > -- > 1.9.1 >