qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 14/16] hw/intc/arm_gic: Restrict priority vie


From: Peter Maydell
Subject: Re: [Qemu-devel] [PATCH v2 14/16] hw/intc/arm_gic: Restrict priority view
Date: Tue, 14 Apr 2015 20:32:11 +0100

On 30 October 2014 at 22:12, Greg Bellows <address@hidden> wrote:
> From: Fabian Aggeler <address@hidden>
>
> GICs with Security Extensions restrict the non-secure view of the
> interrupt priority and priority mask registers.
>
> Signed-off-by: Fabian Aggeler <address@hidden>
> ---
>  hw/intc/arm_gic.c      | 66 
> +++++++++++++++++++++++++++++++++++++++++++++-----
>  hw/intc/gic_internal.h |  3 +++
>  2 files changed, 63 insertions(+), 6 deletions(-)
>
> diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
> index 7eb72df..e01cfdc 100644
> --- a/hw/intc/arm_gic.c
> +++ b/hw/intc/arm_gic.c
> @@ -258,11 +258,66 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu)
>
>  void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val)
>  {
> +    uint8_t prio = val;
> +
> +    if (s->security_extn && ns_access()) {
> +        if (GIC_TEST_GROUP0(irq, (1 << cpu))) {
> +            return; /* Ignore Non-secure access of Group0 IRQ */
> +        }
> +        prio = 0x80 | (prio >> 1); /* Non-secure view */
> +    }
> +
>      if (irq < GIC_INTERNAL) {
> -        s->priority1[irq][cpu] = val;
> +        s->priority1[irq][cpu] = prio;
>      } else {
> -        s->priority2[(irq) - GIC_INTERNAL] = val;
> +        s->priority2[(irq) - GIC_INTERNAL] = prio;
> +    }
> +}
> +
> +uint32_t gic_get_priority(GICState *s, int cpu, int irq)
> +{
> +    uint32_t prio = GIC_GET_PRIORITY(irq, cpu);
> +
> +    if (s->security_extn && ns_access()) {
> +        if (GIC_TEST_GROUP0(irq, (1 << cpu))) {
> +            return 0; /* Non-secure access cannot read priority of Group0 
> IRQ */
> +        }
> +        prio = (prio << 1); /* Non-secure view */
>      }
> +    return prio;
> +}
> +
> +void gic_set_priority_mask(GICState *s, int cpu, uint8_t val)
> +{
> +    uint8_t pmask = (val & 0xff);
> +
> +    if (s->security_extn && ns_access()) {
> +        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;
> +}
> +
> +uint32_t gic_get_priority_mask(GICState *s, int cpu)
> +{
> +    uint32_t pmask = s->priority_mask[cpu];
> +
> +    if (s->security_extn && ns_access()) {
> +        if (pmask & 0x80) {
> +            /* Priority Mask in upper half, return Non-secure view */
> +            pmask = (pmask << 1);
> +        } else {
> +            /* Priority Mask in lower half, RAZ */
> +            pmask = 0;
> +        }
> +    }
> +    return pmask;
> +
>  }
>
>  uint32_t gic_get_cpu_control(GICState *s, int cpu)
> @@ -556,7 +611,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr 
> offset)
>          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);
>      } else if (offset < 0xc00) {
>          /* Interrupt CPU Target.  */
>          if (s->num_cpu == 1 && s->revision != REV_11MPCORE) {
> @@ -920,7 +975,7 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int 
> offset)
>      case 0x00: /* Control */
>          return gic_get_cpu_control(s, cpu);
>      case 0x04: /* Priority mask */
> -        return s->priority_mask[cpu];
> +        return gic_get_priority_mask(s, cpu);
>      case 0x08: /* Binary Point */
>          if (s->security_extn && ns_access()) {
>              /* BPR is banked. Non-secure copy stored in ABPR. */
> @@ -958,8 +1013,7 @@ static void gic_cpu_write(GICState *s, int cpu, int 
> offset, uint32_t value)
>      case 0x00: /* Control */
>          return gic_set_cpu_control(s, cpu, value);
>      case 0x04: /* Priority mask */
> -        s->priority_mask[cpu] = (value & 0xff);
> -        break;
> +        return gic_set_priority_mask(s, cpu, value);

'return some_function_returning_void()' again.

>      case 0x08: /* Binary Point */
>          if (s->security_extn && ns_access()) {
>              /* BPR is banked. Non-secure copy stored in ABPR. */
> diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
> index fbb1f66..13fe5a6 100644
> --- a/hw/intc/gic_internal.h
> +++ b/hw/intc/gic_internal.h
> @@ -76,6 +76,9 @@ 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);
> +uint32_t gic_get_priority(GICState *s, int cpu, int irq);
> +void gic_set_priority_mask(GICState *s, int cpu, uint8_t val);
> +uint32_t gic_get_priority_mask(GICState *s, int cpu);
>  uint32_t gic_get_cpu_control(GICState *s, int cpu);
>  void gic_set_cpu_control(GICState *s, int cpu, uint32_t value);
>  uint8_t gic_get_running_priority(GICState *s, int cpu);
> --
> 1.8.3.2
>

-- PMM



reply via email to

[Prev in Thread] Current Thread [Next in Thread]