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

Re: [PATCH v3 10/11] xen/arm: vgic-v3: add emulation of GICv3.1 eSPI registers


  • To: Oleksandr Tyshchenko <olekstysh@xxxxxxxxx>, "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Leonid Komarianskyi <Leonid_Komarianskyi@xxxxxxxx>
  • Date: Wed, 27 Aug 2025 11:13:07 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=epam.com; dmarc=pass action=none header.from=epam.com; dkim=pass header.d=epam.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=cD2i9Yz/SmUHRP653fDciNvSViPIhE06l5qGbcMOs8I=; b=MgFL3XJifisd1fKU9Gao4BaIBaB1mFyFMUIIECysuyivnRSLvy7eXgUvL+gM8OvROFfc6Za3eQgq0Ge+asmiYFRHkezNV9Der3yA8mQ4Pq1rcJy3fjwnfz17xvOqjGfBdCgf80htRlJPn1g6biycafC4SNC7IVA/NOwMClaH0oyrtP+u6kcV2cTYmeLRXhRpmWKSsfobOsyzSN3FgUh0NPAz38SLiUVOJepCZu008duNIM0C1ZzRod1nBEHtVC6F1JgFPfivG0IW7ecB17okkSibMYYo0sGjjRiWFP8CL1u9i9WClbg2B6MXIAlJBiaOQ9uq8g+UIr9eCoi3+6Sk8A==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=l1Tpe0CHLI5xPtommzvMx5SvLEpI7IJU6KeYAkVmtaYlZYb8gHb32WChoTEEmS+Y+iHRKoNO+jJldK7VurK5Ooedc3O1Va2auANa+U8QYdiivwBxtWCIANTR2qce7I7Q0mnl/W4fgZTzzt1Fy9OtSJ0yZIJwbiQMuozgcgpkynaeR9eMBuFHLvF65tO93CBIJvfD70+M2gG8tYu24grEkBYrJhxOpCwNR/PrWzsmMu4Cp6hq8rXk2BTOFuEhMQ7Wqv3hWTcCSarRXRJOOeYqCfMiCAoER4fcO+px6IxMRy/iIhDN1pe5wIR54ZHZvyRSrajspq5Ywr5x67aKf3ty+Q==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=epam.com;
  • Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Wed, 27 Aug 2025 11:13:23 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHcFpKAKCVIbYC3hEGAz+VsUD3/gbR1WjCAgAD/ygA=
  • Thread-topic: [PATCH v3 10/11] xen/arm: vgic-v3: add emulation of GICv3.1 eSPI registers

Hello Oleksandr,

Thank you for your close review.

On 26.08.25 22:57, Oleksandr Tyshchenko wrote:
> 
> 
> On 26.08.25 17:05, Leonid Komarianskyi wrote:
> 
> Hello Leonid
> 
> 
>> Implemented support for GICv3.1 extended SPI registers for vGICv3,
>> allowing the emulation of eSPI-specific behavior for guest domains.
>> The implementation includes read and write emulation for eSPI-related
>> registers (e.g., GICD_ISENABLERnE, GICD_IROUTERnE, and others),
>> following a similar approach to the handling of regular SPIs.
>>
>> The eSPI registers, previously located in reserved address ranges,
>> are now adjusted to support MMIO read and write operations correctly
>> when CONFIG_GICV3_ESPI is enabled.
>>
>> The availability of eSPIs and the number of emulated extended SPIs
>> for guest domains is reported by setting the appropriate bits in the
>> GICD_TYPER register, based on the number of eSPIs requested by the
>> domain and supported by the hardware. In cases where the configuration
>> option is disabled, the hardware does not support eSPIs, or the domain
>> does not request such interrupts, the functionality remains unchanged.
>>
>> Signed-off-by: Leonid Komarianskyi <leonid_komarianskyi@xxxxxxxx>
>>
>> ---
>> Changes in V2:
>> - add missing rank index conversion for pending and inflight irqs
>>
>> Changes in V3:
>> - changed vgic_store_irouter parameters - instead of offset virq is
>>    used, to remove the additional bool espi parameter and simplify
>>    checks. Also, adjusted parameters for regular SPI. Since the offset
>>    parameter was used only for calculating virq number and then reused 
>> for
>>    finding rank offset, it will not affect functionality.
>> - fixed formatting for goto lables - added newlines after condition
>> - fixed logs for GICD_ISACTIVERnE and GICD_ICACTIVERnE handlers
>> - removed #ifdefs in 2 places where they were adjacent and could be 
>> merged
>> ---
>>   xen/arch/arm/vgic-v3.c | 275 +++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 266 insertions(+), 9 deletions(-)
>>
>> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
>> index 4369c55177..56c539bb1b 100644
>> --- a/xen/arch/arm/vgic-v3.c
>> +++ b/xen/arch/arm/vgic-v3.c
>> @@ -111,13 +111,10 @@ static uint64_t vgic_fetch_irouter(struct 
>> vgic_irq_rank *rank,
>>    * Note the offset will be aligned to the appropriate boundary.
>>    */
>>   static void vgic_store_irouter(struct domain *d, struct 
>> vgic_irq_rank *rank,
>> -                               unsigned int offset, uint64_t irouter)
>> +                               unsigned int virq, uint64_t irouter)
>>   {
>>       struct vcpu *new_vcpu, *old_vcpu;
>> -    unsigned int virq;
>> -
>> -    /* There is 1 vIRQ per IROUTER */
>> -    virq = offset / NR_BYTES_PER_IROUTER;
>> +    unsigned int offset;
>>       /*
>>        * The IROUTER0-31, used for SGIs/PPIs, are reserved and should
>> @@ -685,6 +682,9 @@ static int __vgic_v3_distr_common_mmio_read(const 
>> char *name, struct vcpu *v,
>>       {
>>       case VRANGE32(GICD_IGROUPR, GICD_IGROUPRN):
>>       case VRANGE32(GICD_IGRPMODR, GICD_IGRPMODRN):
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(GICD_IGROUPRnE, GICD_IGROUPRnEN):
>> +#endif
>>           /* We do not implement security extensions for guests, read 
>> zero */
>>           if ( dabt.size != DABT_WORD ) goto bad_width;
>>           goto read_as_zero;
>> @@ -710,11 +710,19 @@ static int 
>> __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v,
>>       /* Read the pending status of an IRQ via GICD/GICR is not 
>> supported */
>>       case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN):
>>       case VRANGE32(GICD_ICPENDR, GICD_ICPENDRN):
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(GICD_ISPENDRnE, GICD_ISPENDRnEN):
>> +    case VRANGE32(GICD_ICPENDRnE, GICD_ICPENDRnEN):
>> +#endif
>>           goto read_as_zero;
>>       /* Read the active status of an IRQ via GICD/GICR is not 
>> supported */
>>       case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN):
>>       case VRANGE32(GICD_ICACTIVER, GICD_ICACTIVERN):
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(GICD_ISACTIVERnE, GICD_ISACTIVERnEN):
>> +    case VRANGE32(GICD_ICACTIVERnE, GICD_ICACTIVERnEN):
>> +#endif
>>           goto read_as_zero;
>>       case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN):
>> @@ -752,6 +760,69 @@ static int __vgic_v3_distr_common_mmio_read(const 
>> char *name, struct vcpu *v,
>>           return 1;
>>       }
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(GICD_ISENABLERnE, GICD_ISENABLERnEN):
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 1, reg - GICD_ISENABLERnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto read_as_zero;
>> +        vgic_lock_rank(v, rank, flags);
>> +        *r = vreg_reg32_extract(rank->ienable, info);
>> +        vgic_unlock_rank(v, rank, flags);
>> +        return 1;
>> +
>> +    case VRANGE32(GICD_ICENABLERnE, GICD_ICENABLERnEN):
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 1, reg - GICD_ICENABLERnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto read_as_zero;
>> +        vgic_lock_rank(v, rank, flags);
>> +        *r = vreg_reg32_extract(rank->ienable, info);
>> +        vgic_unlock_rank(v, rank, flags);
>> +        return 1;
>> +
>> +    case VRANGE32(GICD_IPRIORITYRnE, GICD_IPRIORITYRnEN):
>> +    {
>> +        uint32_t ipriorityr;
>> +        uint8_t rank_index;
>> +
>> +        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 8, reg - GICD_IPRIORITYRnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto read_as_zero;
>> +        rank_index = REG_RANK_INDEX(8, reg - GICD_IPRIORITYRnE, 
>> DABT_WORD);
>> +
>> +        vgic_lock_rank(v, rank, flags);
>> +        ipriorityr = ACCESS_ONCE(rank->ipriorityr[rank_index]);
>> +        vgic_unlock_rank(v, rank, flags);
>> +
>> +        *r = vreg_reg32_extract(ipriorityr, info);
>> +
>> +        return 1;
>> +    }
>> +
>> +    case VRANGE32(GICD_ICFGRnE, GICD_ICFGRnEN):
>> +    {
>> +        uint32_t icfgr;
>> +
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 2, reg - GICD_ICFGRnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto read_as_zero;
>> +        vgic_lock_rank(v, rank, flags);
>> +        icfgr = rank->icfg[REG_RANK_INDEX(2, reg - GICD_ICFGRnE, 
>> DABT_WORD)];
>> +        vgic_unlock_rank(v, rank, flags);
>> +
>> +        *r = vreg_reg32_extract(icfgr, info);
>> +
>> +        return 1;
>> +    }
>> +#endif
>> +
>>       default:
>>           printk(XENLOG_G_ERR
>>                  "%pv: %s: unhandled read r%d offset %#08x\n",
>> @@ -782,6 +853,9 @@ static int __vgic_v3_distr_common_mmio_write(const 
>> char *name, struct vcpu *v,
>>       {
>>       case VRANGE32(GICD_IGROUPR, GICD_IGROUPRN):
>>       case VRANGE32(GICD_IGRPMODR, GICD_IGRPMODRN):
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(GICD_IGROUPRnE, GICD_IGROUPRnEN):
>> +#endif
>>           /* We do not implement security extensions for guests, write 
>> ignore */
>>           goto write_ignore_32;
>> @@ -871,6 +945,99 @@ static int 
>> __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v,
>>           vgic_unlock_rank(v, rank, flags);
>>           return 1;
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(GICD_ISENABLERnE, GICD_ISENABLERnEN):
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 1, reg - GICD_ISENABLERnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto write_ignore;
>> +        vgic_lock_rank(v, rank, flags);
>> +        tr = rank->ienable;
>> +        vreg_reg32_setbits(&rank->ienable, r, info);
>> +        vgic_enable_irqs(v, (rank->ienable) & (~tr), 
>> EXT_RANK_IDX2NUM(rank->index));
>> +        vgic_unlock_rank(v, rank, flags);
>> +        return 1;
>> +
>> +    case VRANGE32(GICD_ICENABLERnE, GICD_ICENABLERnEN):
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 1, reg - GICD_ICENABLERnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto write_ignore;
>> +        vgic_lock_rank(v, rank, flags);
>> +        tr = rank->ienable;
>> +        vreg_reg32_clearbits(&rank->ienable, r, info);
>> +        vgic_disable_irqs(v, (~rank->ienable) & tr, 
>> EXT_RANK_IDX2NUM(rank->index));
>> +        vgic_unlock_rank(v, rank, flags);
>> +        return 1;
>> +
>> +    case VRANGE32(GICD_ISPENDRnE, GICD_ISPENDRnEN):
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 1, reg - GICD_ISPENDRnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto write_ignore;
>> +
>> +        vgic_set_irqs_pending(v, r, EXT_RANK_IDX2NUM(rank->index));
>> +
>> +        return 1;
>> +
>> +    case VRANGE32(GICD_ICPENDRnE, GICD_ICPENDRnEN):
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 1, reg - GICD_ICPENDRnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto write_ignore;
>> +
>> +        vgic_check_inflight_irqs_pending(v, EXT_RANK_IDX2NUM(rank- 
>> >index), r);
>> +
>> +        goto write_ignore;
>> +    case VRANGE32(GICD_ISACTIVERnE, GICD_ISACTIVERnEN):
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        printk(XENLOG_G_ERR
>> +               "%pv: %s: unhandled word write %#"PRIregister" to 
>> ISACTIVER%dE\n",
>> +               v, name, r, reg - GICD_ISACTIVERnE);
>> +        return 0;
> 
> Guest write access to GICD_ISACTIVER<n>E will lead to abort. But, I know 
> you just repeated the logic for regular GICD_ISACTIVER<n>.
> 
> 

Could you please clarify the scenario in which it leads to an abort? 
Since it is actually a stub case, it should just print an error message 
and that's it.. Do you mean that, in this case, we need to goto 
write_ignore_32 label instead of returning 0?

>> +
>> +    case VRANGE32(GICD_ICACTIVERnE, GICD_ICACTIVERnEN):
>> +        printk(XENLOG_G_ERR
>> +               "%pv: %s: unhandled word write %#"PRIregister" to 
>> ICACTIVER%dE\n",
>> +               v, name, r, reg - GICD_ICACTIVER);
> 
> s/GICD_ICACTIVER/GICD_ICACTIVERnE
> 
> 

I will fix that in V4.

>> +        goto write_ignore_32;
>> +
>> +    case VRANGE32(GICD_IPRIORITYRnE, GICD_IPRIORITYRnEN):
>> +    {
>> +        uint32_t *ipriorityr, priority;
>> +
>> +        if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 8, reg - GICD_IPRIORITYRnE, 
>> DABT_WORD);
>> +        if ( rank == NULL ) goto write_ignore;
>> +        vgic_lock_rank(v, rank, flags);
>> +        ipriorityr = &rank->ipriorityr[REG_RANK_INDEX(8, reg - 
>> GICD_IPRIORITYRnE,
>> +                                                      DABT_WORD)];
>> +        priority = ACCESS_ONCE(*ipriorityr);
>> +        vreg_reg32_update(&priority, r, info);
>> +        ACCESS_ONCE(*ipriorityr) = priority;
>> +        vgic_unlock_rank(v, rank, flags);
>> +        return 1;
>> +    }
> 
> NIT: emply line please (and in similar places)
> 

I will recheck formatting and fix it in V4.

>> +    case VRANGE32(GICD_ICFGRnE, GICD_ICFGRnEN):
>> +        if ( dabt.size != DABT_WORD )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 2, reg - GICD_ICFGRnE, 
>> DABT_WORD);
>> +        if ( rank == NULL )
>> +            goto write_ignore;
>> +        vgic_lock_rank(v, rank, flags);
>> +        vreg_reg32_update(&rank->icfg[REG_RANK_INDEX(2, reg - 
>> GICD_ICFGRnE,
>> +                                                     DABT_WORD)],
>> +                          r, info);
>> +        vgic_unlock_rank(v, rank, flags);
>> +        return 1;
>> +#endif
>> +
>>       default:
>>           printk(XENLOG_G_ERR
>>                  "%pv: %s: unhandled write r%d=%"PRIregister" offset 
>> %#08x\n",
>> @@ -1129,6 +1296,16 @@ static int vgic_v3_distr_mmio_read(struct vcpu 
>> *v, mmio_info_t *info,
>>               typer |= GICD_TYPE_LPIS;
>>           typer |= (v->domain->arch.vgic.intid_bits - 1) << 
>> GICD_TYPE_ID_BITS_SHIFT;
>> +#ifdef CONFIG_GICV3_ESPI
>> +        if ( v->domain->arch.vgic.nr_espis > 0 )
>> +        {
>> +            /* Set eSPI support bit for the domain */
>> +            typer |= GICD_TYPER_ESPI;
>> +            /* Set ESPI range bits */
>> +            typer |= (DIV_ROUND_UP(v->domain->arch.vgic.nr_espis, 32) 
>> - 1)
>> +                       << GICD_TYPER_ESPI_RANGE_SHIFT;
>> +        }
>> +#endif
>>           *r = vreg_reg32_extract(typer, info);
>> @@ -1194,6 +1371,18 @@ static int vgic_v3_distr_mmio_read(struct vcpu 
>> *v, mmio_info_t *info,
>>       case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN):
>>       case VRANGE32(GICD_ICFGR, GICD_ICFGRN):
>>       case VRANGE32(GICD_IGRPMODR, GICD_IGRPMODRN):
>> +
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(GICD_IGROUPRnE, GICD_IGROUPRnEN):
>> +    case VRANGE32(GICD_ISENABLERnE, GICD_ISENABLERnEN):
>> +    case VRANGE32(GICD_ICENABLERnE, GICD_ICENABLERnEN):
>> +    case VRANGE32(GICD_ISPENDRnE, GICD_ISPENDRnEN):
>> +    case VRANGE32(GICD_ICPENDRnE, GICD_ICPENDRnEN):
>> +    case VRANGE32(GICD_ISACTIVERnE, GICD_ISACTIVERnEN):
>> +    case VRANGE32(GICD_ICACTIVERnE, GICD_ICACTIVERnEN):
>> +    case VRANGE32(GICD_IPRIORITYRnE, GICD_IPRIORITYRnEN):
>> +    case VRANGE32(GICD_ICFGRnE, GICD_ICFGRnEN):
>> +#endif
> 
> GICD_IGRPMODR<n>E is missed? I guess, it should be RAZ as regular 
> GICD_IGRPMODR<n>.
> 
> Also GICD_NSACR<n>E is missed, although the case for regular 
> GICD_NSACR<n> is present (not visible in patch context).
> 

Yes, I missed them, since they are not required for real GIC hardware..
I will update the patch that adds eSPI-specific defines and make the 
appropriate changes in this patch.

>>           /*
>>            * Above all register are common with GICR and GICD
>>            * Manage in common
>> @@ -1216,7 +1405,11 @@ static int vgic_v3_distr_mmio_read(struct vcpu 
>> *v, mmio_info_t *info,
>>           /* Replaced with GICR_ISPENDR0. So ignore write */
>>           goto read_as_zero_32;
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(0x3100, 0x60FC):
>> +#else
>>       case VRANGE32(0x0F30, 0x60FC):
>> +#endif
>>           goto read_reserved;
>>       case VRANGE64(GICD_IROUTER32, GICD_IROUTER1019):
>> @@ -1235,8 +1428,30 @@ static int vgic_v3_distr_mmio_read(struct vcpu 
>> *v, mmio_info_t *info,
>>           return 1;
>>       }
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE64(GICD_IROUTERnE, GICD_IROUTERnEN):
>> +    {
>> +        uint64_t irouter;
>> +
>> +        if ( !vgic_reg64_check_access(dabt) )
>> +            goto bad_width;
>> +        rank = vgic_ext_rank_offset(v, 64, gicd_reg - GICD_IROUTERnE,
>> +                                DABT_DOUBLE_WORD);
>> +        if ( rank == NULL )
>> +            goto read_as_zero;
>> +        vgic_lock_rank(v, rank, flags);
>> +        irouter = vgic_fetch_irouter(rank, gicd_reg - GICD_IROUTERnE);
>> +        vgic_unlock_rank(v, rank, flags);
>> +        *r = vreg_reg64_extract(irouter, info);
>> +
>> +        return 1;
>> +    }
>> +
>> +    case VRANGE32(0xA004, 0xBFFC):
>> +#else
>>       case VRANGE32(0x7FE0, 0xBFFC):
>> +#endif
>>           goto read_reserved;
>>       case VRANGE32(0xC000, 0xFFCC):
>> @@ -1382,6 +1597,18 @@ static int vgic_v3_distr_mmio_write(struct vcpu 
>> *v, mmio_info_t *info,
>>       case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN):
>>       case VRANGE32(GICD_ICFGR, GICD_ICFGRN):
>>       case VRANGE32(GICD_IGRPMODR, GICD_IGRPMODRN):
>> +
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(GICD_IGROUPRnE, GICD_IGROUPRnEN):
>> +    case VRANGE32(GICD_ISENABLERnE, GICD_ISENABLERnEN):
>> +    case VRANGE32(GICD_ICENABLERnE, GICD_ICENABLERnEN):
>> +    case VRANGE32(GICD_ISPENDRnE, GICD_ISPENDRnEN):
>> +    case VRANGE32(GICD_ICPENDRnE, GICD_ICPENDRnEN):
>> +    case VRANGE32(GICD_ISACTIVERnE, GICD_ISACTIVERnEN):
>> +    case VRANGE32(GICD_ICACTIVERnE, GICD_ICACTIVERnEN):
>> +    case VRANGE32(GICD_IPRIORITYRnE, GICD_IPRIORITYRnEN):
>> +    case VRANGE32(GICD_ICFGRnE, GICD_ICFGRnEN):
>> +#endif
> 
> GICD_IGRPMODR<n>E is missed? I guess, it should be WI as regular 
> GICD_IGRPMODR<n>.
> 
> 
> Also GICD_NSACR<n>E is missed, although the case for regular 
> GICD_NSACR<n> is present (not visible in patch context).

I will update the patch that adds eSPI-specific defines and make the 
appropriate changes in this patch.

> 
>>           /* Above registers are common with GICR and GICD
>>            * Manage in common */
>>           return __vgic_v3_distr_common_mmio_write("vGICD", v, info,
>> @@ -1405,26 +1632,56 @@ static int vgic_v3_distr_mmio_write(struct 
>> vcpu *v, mmio_info_t *info,
>>           if ( dabt.size != DABT_WORD ) goto bad_width;
>>           return 0;
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE32(0x3100, 0x60FC):
>> +#else
>>       case VRANGE32(0x0F30, 0x60FC):
>> +#endif
> 
> I wonder, can we have #defines for these magics (at least for the start 
> of the reserved range)?
> 
>>           goto write_reserved;
>>       case VRANGE64(GICD_IROUTER32, GICD_IROUTER1019):
>>       {
>>           uint64_t irouter;
>> +        unsigned int offset, virq;
>>           if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> -        rank = vgic_rank_offset(v, 64, gicd_reg - GICD_IROUTER,
>> -                                DABT_DOUBLE_WORD);
>> +        offset = gicd_reg - GICD_IROUTER;
>> +        rank = vgic_rank_offset(v, 64, offset, DABT_DOUBLE_WORD);
>>           if ( rank == NULL ) goto write_ignore;
>>           vgic_lock_rank(v, rank, flags);
>> -        irouter = vgic_fetch_irouter(rank, gicd_reg - GICD_IROUTER);
>> +        irouter = vgic_fetch_irouter(rank, offset);
>> +        vreg_reg64_update(&irouter, r, info);
>> +        virq = offset / NR_BYTES_PER_IROUTER;
>> +        vgic_store_irouter(v->domain, rank, virq, irouter);
>> +        vgic_unlock_rank(v, rank, flags);
>> +        return 1;
>> +    }
>> +
>> +#ifdef CONFIG_GICV3_ESPI
>> +    case VRANGE64(GICD_IROUTERnE, GICD_IROUTERnEN):
>> +    {
>> +        uint64_t irouter;
>> +        unsigned int offset, virq;
>> +
>> +        if ( !vgic_reg64_check_access(dabt) )
>> +            goto bad_width;
>> +        offset = gicd_reg - GICD_IROUTERnE;
>> +        rank = vgic_ext_rank_offset(v, 64, offset, DABT_DOUBLE_WORD);
>> +        if ( rank == NULL )
>> +            goto write_ignore;
>> +        vgic_lock_rank(v, rank, flags);
>> +        irouter = vgic_fetch_irouter(rank, offset);
>>           vreg_reg64_update(&irouter, r, info);
>> -        vgic_store_irouter(v->domain, rank, gicd_reg - GICD_IROUTER, 
>> irouter);
>> +        virq = ESPI_IDX2INTID(offset / NR_BYTES_PER_IROUTER);
>> +        vgic_store_irouter(v->domain, rank, virq, irouter);
>>           vgic_unlock_rank(v, rank, flags);
>>           return 1;
>>       }
>> +    case VRANGE32(0xA004, 0xBFFC):
>> +#else
>>       case VRANGE32(0x7FE0, 0xBFFC):
>> +#endif
>>           goto write_reserved;
>>       case VRANGE32(0xC000, 0xFFCC):
> 

Best regards,
Leonid.

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.