From 5aa85f38cb15a8bfb76eaed074f892f99dbd1c68 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 3 Sep 2019 12:37:06 +0100 Subject: dev-arm: Implement message-based SPIs Change-Id: I35e79dfd572c3e0d9cadc8e0aab01befd6004ece Signed-off-by: Giacomo Travaglini Reviewed-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20631 Tested-by: kokoro Maintainer: Andreas Sandberg --- src/dev/arm/gic_v3_distributor.cc | 77 +++++++++++++++++++++++++++++++++++++-- src/dev/arm/gic_v3_distributor.hh | 8 ++++ 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/dev/arm/gic_v3_distributor.cc b/src/dev/arm/gic_v3_distributor.cc index a0cebacc7..d007fb31c 100644 --- a/src/dev/arm/gic_v3_distributor.cc +++ b/src/dev/arm/gic_v3_distributor.cc @@ -476,8 +476,8 @@ Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) * injection) * LPIS [17] == 1 * (The implementation does not support LPIs) - * MBIS [16] == 0 - * (The implementation does not support message-based interrupts + * MBIS [16] == 1 + * (The implementation supports message-based interrupts * by writing to Distributor registers) * SecurityExtn [10] == X * (The GIC implementation supports two Security states) @@ -490,7 +490,8 @@ Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) int max_spi_int_id = itLines - 1; int it_lines_number = ceil((max_spi_int_id + 1) / 32.0) - 1; return (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) | - (1 << 17) | (gic->getSystem()->haveSecurity() << 10) | + (1 << 17) | (1 << 16) | + (gic->getSystem()->haveSecurity() << 10) | (it_lines_number << 0); } @@ -940,6 +941,76 @@ Gicv3Distributor::write(Addr addr, uint64_t data, size_t size, // Only if affinity routing is disabled, RES0 break; + case GICD_SETSPI_NSR: { + // Writes to this register have no effect if: + // * The value written specifies an invalid SPI. + // * The SPI is already pending. + // * The value written specifies a Secure SPI, the value is + // written by a Non-secure access, and the value of the + // corresponding GICD_NSACR register is 0. + const uint32_t intid = bits(data, 9, 0); + if (isNotSPI(intid) || irqPending[intid] || + (nsAccessToSecInt(intid, is_secure_access) && + irqNsacr[intid] == 0)) { + return; + } else { + // Valid SPI, set interrupt pending + sendInt(intid); + } + break; + } + + case GICD_CLRSPI_NSR: { + // Writes to this register have no effect if: + // * The value written specifies an invalid SPI. + // * The SPI is not pending. + // * The value written specifies a Secure SPI, the value is + // written by a Non-secure access, and the value of the + // corresponding GICD_NSACR register is less than 0b10. + const uint32_t intid = bits(data, 9, 0); + if (isNotSPI(intid) || !irqPending[intid] || + (nsAccessToSecInt(intid, is_secure_access) && + irqNsacr[intid] < 2)) { + return; + } else { + // Valid SPI, clear interrupt pending + deassertSPI(intid); + } + break; + } + + case GICD_SETSPI_SR: { + // Writes to this register have no effect if: + // * GICD_CTLR.DS = 1 (WI) + // * The value written specifies an invalid SPI. + // * The SPI is already pending. + // * The value is written by a Non-secure access. + const uint32_t intid = bits(data, 9, 0); + if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) { + return; + } else { + // Valid SPI, set interrupt pending + sendInt(intid); + } + break; + } + + case GICD_CLRSPI_SR: { + // Writes to this register have no effect if: + // * GICD_CTLR.DS = 1 (WI) + // * The value written specifies an invalid SPI. + // * The SPI is not pending. + // * The value is written by a Non-secure access. + const uint32_t intid = bits(data, 9, 0); + if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) { + return; + } else { + // Valid SPI, clear interrupt pending + deassertSPI(intid); + } + break; + } + default: panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); break; diff --git a/src/dev/arm/gic_v3_distributor.hh b/src/dev/arm/gic_v3_distributor.hh index df35dafe4..61381efb5 100644 --- a/src/dev/arm/gic_v3_distributor.hh +++ b/src/dev/arm/gic_v3_distributor.hh @@ -69,6 +69,14 @@ class Gicv3Distributor : public Serializable GICD_IIDR = 0x0008, // Error Reporting Status Register GICD_STATUSR = 0x0010, + // Set Non-secure SPI Pending Register + GICD_SETSPI_NSR = 0x0040, + // Clear Non-secure SPI Pending Register + GICD_CLRSPI_NSR = 0x0048, + // Set Secure SPI Pending Register + GICD_SETSPI_SR = 0x0050, + // Clear Secure SPI Pending Register + GICD_CLRSPI_SR = 0x0058, // Software Generated Interrupt Register GICD_SGIR = 0x0f00, // Peripheral ID0 Register -- cgit v1.2.3