On Thu, 28 Aug 2025, dmuk...@xen.org wrote:
> From: Denis Mukhin <dmuk...@ford.com> 
> 
> Make sure that NS16550 emulator does not share virtual device IRQ with the
> physical one. This is needed for enabling NS16550 emulator for PVH hwdom
> (dom0).
> 
> To do that, move per-domain interrupt rangeset allocation before arch-specific
> code. Add irqs_setup_access() to setup the initial rangeset.
> 
> Signed-off-by: Denis Mukhin <dmuk...@ford.com>
> ---
> Changes since v4:
> - new patch
> - Link to original patch in v4: 
> https://lore.kernel.org/xen-devel/20250731192130.3948419-4-dmuk...@ford.com/
> ---
>  xen/arch/x86/dom0_build.c       | 1 -
>  xen/arch/x86/hvm/dom0_build.c   | 7 +++++++
>  xen/arch/x86/include/asm/irq.h  | 2 ++
>  xen/arch/x86/irq.c              | 8 ++++++++
>  xen/arch/x86/pv/dom0_build.c    | 3 +++
>  xen/common/domain.c             | 8 ++++++--
>  xen/common/emul/vuart/ns16x50.c | 9 +++++++++
>  7 files changed, 35 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
> index 26202b33345c..9dc87efbf3e8 100644
> --- a/xen/arch/x86/dom0_build.c
> +++ b/xen/arch/x86/dom0_build.c
> @@ -442,7 +442,6 @@ int __init dom0_setup_permissions(struct domain *d)
>  
>      rc |= iomem_permit_access(d, 0UL,
>                                PFN_DOWN(1UL << domain_max_paddr_bits(d)) - 1);
> -    rc |= irqs_permit_access(d, 1, nr_irqs_gsi - 1);
>  
>      /* Local APIC. */
>      if ( mp_lapic_addr != 0 )
> diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c
> index 5551f9044836..245a42dec9aa 100644
> --- a/xen/arch/x86/hvm/dom0_build.c
> +++ b/xen/arch/x86/hvm/dom0_build.c
> @@ -1348,6 +1348,13 @@ int __init dom0_construct_pvh(const struct boot_domain 
> *bd)
>           */
>          pvh_setup_mmcfg(d);
>  
> +        rc = irqs_setup_access(d);
> +        if ( rc )
> +        {
> +            printk("%pd unable to setup IRQ rangeset: %d\n", d, rc);
> +            return rc;
> +        }
> +
>          /*
>           * Setup permissions early so that calls to add MMIO regions to the
>           * p2m as part of vPCI setup don't fail due to permission checks.
> diff --git a/xen/arch/x86/include/asm/irq.h b/xen/arch/x86/include/asm/irq.h
> index 8c81f66434a8..8bffec3bbfee 100644
> --- a/xen/arch/x86/include/asm/irq.h
> +++ b/xen/arch/x86/include/asm/irq.h
> @@ -231,4 +231,6 @@ int allocate_and_map_gsi_pirq(struct domain *d, int 
> index, int *pirq_p);
>  int allocate_and_map_msi_pirq(struct domain *d, int index, int *pirq_p,
>                                int type, struct msi_info *msi);
>  
> +int irqs_setup_access(struct domain *d);
> +
>  #endif /* _ASM_HW_IRQ_H */
> diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
> index 556134f85aa0..079277be719d 100644
> --- a/xen/arch/x86/irq.c
> +++ b/xen/arch/x86/irq.c
> @@ -3046,3 +3046,11 @@ int allocate_and_map_msi_pirq(struct domain *d, int 
> index, int *pirq_p,
>  
>      return ret;
>  }
> +
> +int irqs_setup_access(struct domain *d)
> +{
> +    if ( is_hardware_domain(d) )
> +        return irqs_permit_access(d, 1, nr_irqs_gsi - 1);
> +
> +    return 0;
> +}
> diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
> index 2b8b4d869ee7..1a092b802833 100644
> --- a/xen/arch/x86/pv/dom0_build.c
> +++ b/xen/arch/x86/pv/dom0_build.c
> @@ -1037,6 +1037,9 @@ static int __init dom0_construct(const struct 
> boot_domain *bd)
>      rc = ioports_setup_access(d);
>      BUG_ON(rc != 0);
>  
> +    rc = irqs_setup_access(d);
> +    BUG_ON(rc != 0);
> +
>      rc = dom0_setup_permissions(d);
>      BUG_ON(rc != 0);
>  
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index 104e917f07e3..eb83e3198f37 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -950,6 +950,11 @@ struct domain *domain_create(domid_t domid,
>      radix_tree_init(&d->pirq_tree);
>  #endif
>  
> +    err = -ENOMEM;
> +    d->irq_caps = rangeset_new(d, "Interrupts", 0);
> +    if ( !d->irq_caps )
> +        goto fail;
> +
>      if ( (err = arch_domain_create(d, config, flags)) != 0 )
>          goto fail;
>      init_status |= INIT_arch;
> @@ -959,8 +964,7 @@ struct domain *domain_create(domid_t domid,
>  
>      err = -ENOMEM;
>      d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex);
> -    d->irq_caps   = rangeset_new(d, "Interrupts", 0);
> -    if ( !d->iomem_caps || !d->irq_caps )
> +    if ( !d->iomem_caps )
>          goto fail;
>  
>      if ( (err = xsm_domain_create(XSM_HOOK, d, config->ssidref)) != 0 )
> diff --git a/xen/common/emul/vuart/ns16x50.c b/xen/common/emul/vuart/ns16x50.c
> index 8860f25ffdeb..aea38304b60c 100644
> --- a/xen/common/emul/vuart/ns16x50.c
> +++ b/xen/common/emul/vuart/ns16x50.c
> @@ -794,6 +794,15 @@ static int ns16x50_init(void *arg)
>          return rc;
>      }
>  
> +    /* Disallow sharing physical IRQ */
> +    rc = irq_deny_access(d, info->irq);
> +    if ( rc )
> +    {
> +        ns16x50_err(info, "virtual IRQ#%d: conflict w/ physical IRQ: %d\n",
> +                    info->irq, rc);
> +        return rc;
> +    }

Also this one I wonder if it could be in hvm_domain_initialise, it would
make more sense to keep the irq_deny_access there, compared to here
which is supposed to be a generic emulator


>      /* NB: report 115200 baud rate. */
>      vdev->regs[NS16X50_REGS_NUM + UART_DLL] = divisor & 0xff;
>      vdev->regs[NS16X50_REGS_NUM + UART_DLM] = (divisor >> 8) & 0xff;
> -- 
> 2.51.0
> 

Reply via email to