hw/intc/gic: RAZ/WI non-sec access to sec interrupts
Treat non-secure accesses to registers and bits in registers of secure interrupts as RAZ/WI. Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org> Message-id: 1464273945-2055-1-git-send-email-jens.wiklander@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									e40c3d2e7f
								
							
						
					
					
						commit
						fea8a08e16
					
				| 
						 | 
				
			
			@ -661,6 +661,11 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
 | 
			
		|||
            goto bad_reg;
 | 
			
		||||
        res = 0;
 | 
			
		||||
        for (i = 0; i < 8; i++) {
 | 
			
		||||
            if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (GIC_TEST_ENABLED(irq + i, cm)) {
 | 
			
		||||
                res |= (1 << i);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -677,6 +682,11 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
 | 
			
		|||
        res = 0;
 | 
			
		||||
        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
 | 
			
		||||
        for (i = 0; i < 8; i++) {
 | 
			
		||||
            if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (gic_test_pending(s, irq + i, mask)) {
 | 
			
		||||
                res |= (1 << i);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -689,6 +699,11 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
 | 
			
		|||
        res = 0;
 | 
			
		||||
        mask = (irq < GIC_INTERNAL) ?  cm : ALL_CPU_MASK;
 | 
			
		||||
        for (i = 0; i < 8; i++) {
 | 
			
		||||
            if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (GIC_TEST_ACTIVE(irq + i, mask)) {
 | 
			
		||||
                res |= (1 << i);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -722,6 +737,11 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
 | 
			
		|||
            goto bad_reg;
 | 
			
		||||
        res = 0;
 | 
			
		||||
        for (i = 0; i < 4; i++) {
 | 
			
		||||
            if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (GIC_TEST_MODEL(irq + i))
 | 
			
		||||
                res |= (1 << (i * 2));
 | 
			
		||||
            if (GIC_TEST_EDGE_TRIGGER(irq + i))
 | 
			
		||||
| 
						 | 
				
			
			@ -742,7 +762,12 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
 | 
			
		|||
            /* GICD_SPENDSGIRn */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        res = s->sgi_pending[irq][cpu];
 | 
			
		||||
        if (s->security_extn && !attrs.secure &&
 | 
			
		||||
            !GIC_TEST_GROUP(irq, 1 << cpu)) {
 | 
			
		||||
            res = 0; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
        } else {
 | 
			
		||||
            res = s->sgi_pending[irq][cpu];
 | 
			
		||||
        }
 | 
			
		||||
    } else if (offset < 0xfd0) {
 | 
			
		||||
        goto bad_reg;
 | 
			
		||||
    } else if (offset < 0x1000) {
 | 
			
		||||
| 
						 | 
				
			
			@ -862,6 +887,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
 | 
			
		|||
                    (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq + i);
 | 
			
		||||
                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 | 
			
		||||
 | 
			
		||||
                if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                    !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                    continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!GIC_TEST_ENABLED(irq + i, cm)) {
 | 
			
		||||
                    DPRINTF("Enabled IRQ %d\n", irq + i);
 | 
			
		||||
                    trace_gic_enable_irq(irq + i);
 | 
			
		||||
| 
						 | 
				
			
			@ -889,6 +919,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
 | 
			
		|||
            if (value & (1 << i)) {
 | 
			
		||||
                int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
 | 
			
		||||
 | 
			
		||||
                if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                    !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                    continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (GIC_TEST_ENABLED(irq + i, cm)) {
 | 
			
		||||
                    DPRINTF("Disabled IRQ %d\n", irq + i);
 | 
			
		||||
                    trace_gic_disable_irq(irq + i);
 | 
			
		||||
| 
						 | 
				
			
			@ -907,6 +942,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
 | 
			
		|||
 | 
			
		||||
        for (i = 0; i < 8; i++) {
 | 
			
		||||
            if (value & (1 << i)) {
 | 
			
		||||
                if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                    !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                    continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                GIC_SET_PENDING(irq + i, GIC_TARGET(irq + i));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -920,6 +960,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < 8; i++) {
 | 
			
		||||
            if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* ??? This currently clears the pending bit for all CPUs, even
 | 
			
		||||
               for per-CPU interrupts.  It's unclear whether this is the
 | 
			
		||||
               corect behavior.  */
 | 
			
		||||
| 
						 | 
				
			
			@ -960,6 +1005,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
 | 
			
		|||
        if (irq < GIC_NR_SGIS)
 | 
			
		||||
            value |= 0xaa;
 | 
			
		||||
        for (i = 0; i < 4; i++) {
 | 
			
		||||
            if (s->security_extn && !attrs.secure &&
 | 
			
		||||
                !GIC_TEST_GROUP(irq + i, 1 << cpu)) {
 | 
			
		||||
                continue; /* Ignore Non-secure access of Group0 IRQ */
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
 | 
			
		||||
                if (value & (1 << (i * 2))) {
 | 
			
		||||
                    GIC_SET_MODEL(irq + i);
 | 
			
		||||
| 
						 | 
				
			
			@ -983,9 +1033,12 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
 | 
			
		|||
        }
 | 
			
		||||
        irq = (offset - 0xf10);
 | 
			
		||||
 | 
			
		||||
        s->sgi_pending[irq][cpu] &= ~value;
 | 
			
		||||
        if (s->sgi_pending[irq][cpu] == 0) {
 | 
			
		||||
            GIC_CLEAR_PENDING(irq, 1 << cpu);
 | 
			
		||||
        if (!s->security_extn || attrs.secure ||
 | 
			
		||||
            GIC_TEST_GROUP(irq, 1 << cpu)) {
 | 
			
		||||
            s->sgi_pending[irq][cpu] &= ~value;
 | 
			
		||||
            if (s->sgi_pending[irq][cpu] == 0) {
 | 
			
		||||
                GIC_CLEAR_PENDING(irq, 1 << cpu);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else if (offset < 0xf30) {
 | 
			
		||||
        /* GICD_SPENDSGIRn */
 | 
			
		||||
| 
						 | 
				
			
			@ -994,8 +1047,11 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
 | 
			
		|||
        }
 | 
			
		||||
        irq = (offset - 0xf20);
 | 
			
		||||
 | 
			
		||||
        GIC_SET_PENDING(irq, 1 << cpu);
 | 
			
		||||
        s->sgi_pending[irq][cpu] |= value;
 | 
			
		||||
        if (!s->security_extn || attrs.secure ||
 | 
			
		||||
            GIC_TEST_GROUP(irq, 1 << cpu)) {
 | 
			
		||||
            GIC_SET_PENDING(irq, 1 << cpu);
 | 
			
		||||
            s->sgi_pending[irq][cpu] |= value;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        goto bad_reg;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue