From: Eric Auger <eauger@redhat.com>
To: Shashi Mallela <shashi.mallela@linaro.org>,
peter.maydell@linaro.org, leif@nuviainc.com, rad@semihalf.com
Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org
Subject: Re: [PATCH v4 6/8] hw/intc: GICv3 redistributor ITS processing
Date: Sun, 13 Jun 2021 18:26:26 +0200 [thread overview]
Message-ID: <1c9344ff-287b-6b95-06fe-e246cc0ace1a@redhat.com> (raw)
In-Reply-To: <20210602180042.111347-7-shashi.mallela@linaro.org>
Hi Shashi,
On 6/2/21 8:00 PM, Shashi Mallela wrote:
> Implemented lpi processing at redistributor to get lpi config info
s/Implemented/Implement here are elsewhere.
> from lpi configuration table,determine priority,set pending state in
> lpi pending table and forward the lpi to cpuif.Added logic to invoke
> redistributor lpi processing with translated LPI which set/clear LPI
> from ITS device as part of ITS INT,CLEAR,DISCARD command and
> GITS_TRANSLATER processing.
>
> Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
> ---
> hw/intc/arm_gicv3.c | 9 ++
> hw/intc/arm_gicv3_common.c | 1 +
> hw/intc/arm_gicv3_cpuif.c | 7 +-
> hw/intc/arm_gicv3_its.c | 14 ++-
> hw/intc/arm_gicv3_redist.c | 145 +++++++++++++++++++++++++++++
> hw/intc/gicv3_internal.h | 10 ++
> include/hw/intc/arm_gicv3_common.h | 10 ++
> 7 files changed, 190 insertions(+), 6 deletions(-)
>
> diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
> index d63f8af604..4d19190b9c 100644
> --- a/hw/intc/arm_gicv3.c
> +++ b/hw/intc/arm_gicv3.c
> @@ -165,6 +165,15 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
> cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
> }
>
> + if (cs->gic->lpi_enable && cs->lpivalid) {
> + if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
> + cs->hppi.irq = cs->hpplpi.irq;
> + cs->hppi.prio = cs->hpplpi.prio;
> + cs->hppi.grp = cs->hpplpi.grp;
> + seenbetter = true;
> + }
> + }
> +
> /* If the best interrupt we just found would preempt whatever
> * was the previous best interrupt before this update, then
> * we know it's definitely the best one now.
> diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
> index 53dea2a775..223db16fec 100644
> --- a/hw/intc/arm_gicv3_common.c
> +++ b/hw/intc/arm_gicv3_common.c
> @@ -435,6 +435,7 @@ static void arm_gicv3_common_reset(DeviceState *dev)
> memset(cs->gicr_ipriorityr, 0, sizeof(cs->gicr_ipriorityr));
>
> cs->hppi.prio = 0xff;
> + cs->hpplpi.prio = 0xff;
>
> /* State in the CPU interface must *not* be reset here, because it
> * is part of the CPU's reset domain, not the GIC device's.
> diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
> index 81f94c7f4a..5be3efaa3f 100644
> --- a/hw/intc/arm_gicv3_cpuif.c
> +++ b/hw/intc/arm_gicv3_cpuif.c
> @@ -898,10 +898,12 @@ static void icc_activate_irq(GICv3CPUState *cs, int irq)
> cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 1);
> cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0);
> gicv3_redist_update(cs);
> - } else {
> + } else if (irq < GICV3_LPI_INTID_START) {
> gicv3_gicd_active_set(cs->gic, irq);
> gicv3_gicd_pending_clear(cs->gic, irq);
> gicv3_update(cs->gic, irq, 1);
> + } else {
> + gicv3_redist_lpi_pending(cs, irq, 0);
> }
> }
>
> @@ -1317,7 +1319,8 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
> trace_gicv3_icc_eoir_write(is_eoir0 ? 0 : 1,
> gicv3_redist_affid(cs), value);
>
> - if (irq >= cs->gic->num_irq) {
> + if ((irq >= cs->gic->num_irq) && (!(cs->gic->lpi_enable &&
> + (irq >= GICV3_LPI_INTID_START)))) {
> /* This handles two cases:
> * 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
> * to the GICC_EOIR, the GIC ignores that write.
> diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> index 0a978cf55b..e0fbd4041f 100644
> --- a/hw/intc/arm_gicv3_its.c
> +++ b/hw/intc/arm_gicv3_its.c
> @@ -211,6 +211,7 @@ static MemTxResult process_int(GICv3ITSState *s, uint64_t value,
> bool ite_valid = false;
> uint64_t cte = 0;
> bool cte_valid = false;
> + uint64_t rdbase;
> uint64_t itel = 0;
> uint32_t iteh = 0;
>
> @@ -267,10 +268,15 @@ static MemTxResult process_int(GICv3ITSState *s, uint64_t value,
> * command in the queue
> */
> } else {
> - /*
> - * Current implementation only supports rdbase == procnum
> - * Hence rdbase physical address is ignored
> - */
> + rdbase = (cte >> 1U) & RDBASE_PROCNUM_MASK;
> + assert(rdbase <= s->gicv3->num_cpu);
> +
> + if ((cmd == CLEAR) || (cmd == DISCARD)) {
> + gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
> + } else {
> + gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
> + }
> +
> if (cmd == DISCARD) {
> /* remove mapping from interrupt translation table */
> res = update_ite(s, eventid, dte, itel, iteh);
> diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
> index fb9a4ee3cc..bfc6e4e9b9 100644
> --- a/hw/intc/arm_gicv3_redist.c
> +++ b/hw/intc/arm_gicv3_redist.c
> @@ -255,6 +255,11 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
> if (cs->gicr_typer & GICR_TYPER_PLPIS) {
> if (value & GICR_CTLR_ENABLE_LPIS) {
> cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
> + /* Check for any pending interr in pending table */
> + cs->lpivalid = false;
> + cs->hpplpi.prio = 0xff;
> + gicv3_redist_update_lpi(cs);
> + gicv3_redist_update(cs);
> } else {
> cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
> }
> @@ -534,6 +539,146 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
> return r;
> }
>
> +void gicv3_redist_update_lpi(GICv3CPUState *cs)
> +{
> + /*
> + * This function scans the LPI pending table and for each pending
> + * LPI, reads the corresponding entry from LPI configuration table
> + * to extract the priority info and determine if the LPI priority
> + * is lower than the current high priority interrupt.If yes, update> + * high priority pending interrupt to that of LPI.
"update high priority pending interrupt to that of LPI" may need some
rewording
> + */
> + AddressSpace *as = &cs->gic->dma_as;
> + uint64_t lpict_baddr, lpipt_baddr;
> + uint32_t pendt_size = 0;
> + uint8_t lpite;
> + uint8_t prio, pend;
> + int i;
> + uint64_t idbits;
> +
> + idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS),
> + GICD_TYPER_IDBITS);
> +
> + if ((!cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser ||
> + !cs->gicr_pendbaser || (idbits < GICR_PROPBASER_IDBITS_THRESHOLD)) {
> + return;
> + }
> +
> + lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
> +
> + lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
> +
> + /* Determine the highest priority pending interrupt among LPIs */
> + pendt_size = (1ULL << (idbits + 1));
> +
> + for (i = 0; i < pendt_size / 8; i++) {
> + address_space_read(as, lpipt_baddr +
> + (((GICV3_LPI_INTID_START + i) / 8) * sizeof(pend)),
> + MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
> +
> + if ((1 << ((GICV3_LPI_INTID_START + i) % 8)) & pend) {
> + address_space_read(as, lpict_baddr + (i * sizeof(lpite)),
> + MEMTXATTRS_UNSPECIFIED, &lpite, sizeof(lpite));
> +
> + if (!(lpite & LPI_CTE_ENABLED)) {
> + continue;
> + }
> +
> + if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
> + prio = lpite & LPI_PRIORITY_MASK;
> + } else {
> + prio = lpite & LPI_SPRIORITY_MASK;
> + }
> +
> + if (prio <= cs->hpplpi.prio) {
> + cs->hpplpi.irq = GICV3_LPI_INTID_START + i;
> + cs->hpplpi.prio = prio;
> + /* LPIs are always non-secure Grp1 interrupts */
> + cs->hpplpi.grp = GICV3_G1NS;
> + cs->lpivalid = true;
> + }
> + }
> + }
> +}
> +
nit: add a comment to explain what the function does, that's not
straightforward gievn its name.
> +void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level)
> +{
> + AddressSpace *as = &cs->gic->dma_as;
> + uint64_t lpipt_baddr;
> + bool ispend = false;
> + uint8_t pend;
> +
> + /*
> + * get the bit value corresponding to this irq in the
> + * lpi pending table
> + */
> + lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
> +
> + address_space_read(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
> + MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
> + ispend = ((pend >> (irq % 8)) & 0x1);
> +
> + if (ispend) {
> + if (!level) {
> + /*
> + * clear the pending bit and update the lpi pending table
> + */
> + pend &= ~(1 << (irq % 8));
> +
> + address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
> + MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
> + }
> + } else {
> + if (level) {
> + /*
> + * if pending bit is not already set for this irq,turn-on the
> + * pending bit and update the lpi pending table
> + */
> + pend |= (1 << (irq % 8));
> +
> + address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
> + MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
> + }
> + }
> + cs->lpivalid = false;
> + cs->hpplpi.prio = 0xff;
> + gicv3_redist_update_lpi(cs);
> +}
> +
> +void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level)
> +{
> + AddressSpace *as = &cs->gic->dma_as;
> + uint64_t lpict_baddr;
> + uint8_t lpite;
> + uint64_t idbits;
> +
> + idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS),
> + GICD_TYPER_IDBITS);
> +
> + if ((!cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser ||
> + !cs->gicr_pendbaser || (idbits < GICR_PROPBASER_IDBITS_THRESHOLD) ||
> + (irq > (1ULL << (idbits + 1)))) {
> + return;
> + }
> +
> + lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
> +
> + /* get the lpi config table entry corresponding to this irq */
> + address_space_read(as, lpict_baddr + ((irq - GICV3_LPI_INTID_START) *
> + sizeof(lpite)), MEMTXATTRS_UNSPECIFIED,
> + &lpite, sizeof(lpite));
> +
> + /* check if this irq is enabled before proceeding further */
> + if (!(lpite & LPI_CTE_ENABLED)) {
> + return;
> + }
> +
> + /* set/clear the pending bit for this irq */
> + gicv3_redist_lpi_pending(cs, irq, level);
> +
> + gicv3_redist_update(cs);
> +}
> +
> void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
> {
> /* Update redistributor state for a change in an external PPI input line */
> diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
> index 91dbe01176..bcbccba573 100644
> --- a/hw/intc/gicv3_internal.h
> +++ b/hw/intc/gicv3_internal.h
> @@ -308,6 +308,13 @@ FIELD(GITS_TYPER, CIL, 36, 1)
>
> #define L1TABLE_ENTRY_SIZE 8
>
> +#define LPI_CTE_ENABLE_OFFSET 0
> +#define LPI_CTE_ENABLED VALID_MASK
> +#define LPI_CTE_PRIORITY_OFFSET 2
> +#define LPI_CTE_PRIORITY_MASK ((1U << 6) - 1)
> +#define LPI_PRIORITY_MASK 0xfc
> +#define LPI_SPRIORITY_MASK 0x7e
> +
> #define GITS_CMDQ_ENTRY_SIZE 32
> #define NUM_BYTES_IN_DW 8
>
> @@ -452,6 +459,9 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
> unsigned size, MemTxAttrs attrs);
> void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
> void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
> +void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level);
> +void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level);
> +void gicv3_redist_update_lpi(GICv3CPUState *cs);
> void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
> void gicv3_init_cpuif(GICv3State *s);
>
> diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
> index c1348cc60a..5d839da9c9 100644
> --- a/include/hw/intc/arm_gicv3_common.h
> +++ b/include/hw/intc/arm_gicv3_common.h
> @@ -204,6 +204,16 @@ struct GICv3CPUState {
> * real state above; it doesn't need to be migrated.
> */
> PendingIrq hppi;
> +
> + /*
> + * Current highest priority pending lpi for this CPU.
> + * This is cached information that can be recalculated from the
> + * real state above; it doesn't need to be migrated.
> + */
> + PendingIrq hpplpi;
> +
> + bool lpivalid; /* current highest priority lpi validity status */
> +
> /* This is temporary working state, to avoid a malloc in gicv3_update() */
> bool seenbetter;
> };>
Thanks
Eric
next prev parent reply other threads:[~2021-06-13 16:27 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-02 18:00 [PATCH v4 0/8] GICv3 LPI and ITS feature implementation Shashi Mallela
2021-06-02 18:00 ` [PATCH v4 1/8] hw/intc: GICv3 ITS initial framework Shashi Mallela
2021-06-08 10:02 ` Peter Maydell
2021-06-11 16:21 ` Eric Auger
2021-06-11 17:23 ` Shashi Mallela
2021-07-06 7:38 ` Eric Auger
2021-07-06 13:24 ` shashi.mallela
2021-07-06 14:04 ` Eric Auger
2021-07-06 14:18 ` shashi.mallela
2021-06-12 6:52 ` Eric Auger
2021-07-06 7:29 ` Eric Auger
2021-06-02 18:00 ` [PATCH v4 2/8] hw/intc: GICv3 ITS register definitions added Shashi Mallela
2021-06-08 10:31 ` Peter Maydell
2021-06-12 6:08 ` Eric Auger
2021-06-16 21:02 ` shashi.mallela
2021-06-21 9:51 ` Eric Auger
2021-06-28 21:51 ` shashi.mallela
2021-06-02 18:00 ` [PATCH v4 3/8] hw/intc: GICv3 ITS command queue framework Shashi Mallela
2021-06-08 10:38 ` Peter Maydell
2021-06-13 14:13 ` Eric Auger
2021-06-16 21:02 ` shashi.mallela
2021-06-21 10:03 ` Eric Auger
2021-06-28 21:58 ` shashi.mallela
2021-06-13 14:39 ` Eric Auger
2021-06-28 15:55 ` shashi.mallela
2021-06-02 18:00 ` [PATCH v4 4/8] hw/intc: GICv3 ITS Command processing Shashi Mallela
2021-06-08 10:45 ` Peter Maydell
2021-06-13 15:55 ` Eric Auger
2021-06-16 21:02 ` shashi.mallela
2021-06-21 10:13 ` Eric Auger
2021-06-28 22:04 ` shashi.mallela
2021-06-02 18:00 ` [PATCH v4 5/8] hw/intc: GICv3 ITS Feature enablement Shashi Mallela
2021-06-08 10:57 ` Peter Maydell
2021-06-02 18:00 ` [PATCH v4 6/8] hw/intc: GICv3 redistributor ITS processing Shashi Mallela
2021-06-08 13:57 ` Peter Maydell
2021-06-10 23:39 ` Shashi Mallela
2021-06-11 8:30 ` Peter Maydell
2021-06-15 2:23 ` Shashi Mallela
2021-06-13 16:26 ` Eric Auger [this message]
2021-06-16 21:02 ` shashi.mallela
2021-06-02 18:00 ` [PATCH v4 7/8] hw/arm/sbsa-ref: add ITS support in SBSA GIC Shashi Mallela
2021-06-03 11:42 ` Leif Lindholm
2021-06-03 15:31 ` shashi.mallela
2021-06-04 10:42 ` Leif Lindholm
2021-06-04 15:36 ` shashi.mallela
2021-07-08 19:40 ` Leif Lindholm
2021-07-08 20:05 ` Peter Maydell
2021-07-08 22:05 ` Leif Lindholm
2021-08-05 20:10 ` shashi.mallela
2021-06-02 18:00 ` [PATCH v4 8/8] hw/arm/virt: add ITS support in virt GIC Shashi Mallela
2021-06-08 11:00 ` Peter Maydell
2021-06-08 10:00 ` [PATCH v4 0/8] GICv3 LPI and ITS feature implementation Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1c9344ff-287b-6b95-06fe-e246cc0ace1a@redhat.com \
--to=eauger@redhat.com \
--cc=leif@nuviainc.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=rad@semihalf.com \
--cc=shashi.mallela@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).