diff options
author | Giacomo Travaglini <giacomo.travaglini@arm.com> | 2019-09-03 12:37:06 +0100 |
---|---|---|
committer | Giacomo Travaglini <giacomo.travaglini@arm.com> | 2019-09-09 08:48:30 +0000 |
commit | 5aa85f38cb15a8bfb76eaed074f892f99dbd1c68 (patch) | |
tree | 4eb50b96828d06ff9a5854ae8ef991585a61be55 /src/dev/arm | |
parent | 37551510ea4b4b4eca16785393f7b17abd50f00e (diff) | |
download | gem5-5aa85f38cb15a8bfb76eaed074f892f99dbd1c68.tar.xz |
dev-arm: Implement message-based SPIs
Change-Id: I35e79dfd572c3e0d9cadc8e0aab01befd6004ece
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20631
Tested-by: kokoro <noreply+kokoro@google.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'src/dev/arm')
-rw-r--r-- | src/dev/arm/gic_v3_distributor.cc | 77 | ||||
-rw-r--r-- | 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<n> 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<n> 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 |