All of lore.kernel.org
 help / color / mirror / Atom feed
From: dmukhin@xen.org
To: xen-devel@lists.xenproject.org
Cc: andrew.cooper3@citrix.com, anthony.perard@vates.tech,
	jbeulich@suse.com, julien@xen.org, michal.orzel@amd.com,
	roger.pau@citrix.com, sstabellini@kernel.org, dmukhin@ford.com
Subject: [PATCH v7 14/16] x86/domain: enable per-domain I/O port bitmaps
Date: Mon,  8 Sep 2025 14:11:47 -0700	[thread overview]
Message-ID: <20250908211149.279143-15-dmukhin@ford.com> (raw)
In-Reply-To: <20250908211149.279143-1-dmukhin@ford.com>

From: Denis Mukhin <dmukhin@ford.com> 

Current design enables all HVM domains share the same I/O port bitmap.

It is necessary for domains crafting its own I/O port address space depending
on the user configuration.

Ensure NS16550 emulator does not share I/O ports with the physical I/O ports,
which is essential for emulation in PVH hwdom case (dom0).

Not a functional change.

Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
Changes since v6:
- n/a
---
 xen/arch/x86/Makefile                    |   1 +
 xen/arch/x86/dom0_build.c                | 111 +--------------
 xen/arch/x86/hvm/hvm.c                   |  35 +----
 xen/arch/x86/hvm/nestedhvm.c             |   8 +-
 xen/arch/x86/hvm/quirks.c                |   3 -
 xen/arch/x86/hvm/svm/nestedsvm.c         |   2 +-
 xen/arch/x86/hvm/vmx/vvmx.c              |   4 +-
 xen/arch/x86/include/asm/hvm/nestedhvm.h |   3 +-
 xen/arch/x86/include/asm/hvm/support.h   |   2 -
 xen/arch/x86/include/asm/iocap.h         |   2 +
 xen/arch/x86/ioport.c                    | 163 +++++++++++++++++++++++
 xen/arch/x86/pv/dom0_build.c             |   4 +
 xen/common/emul/vuart/ns16x50.c          |  11 ++
 13 files changed, 200 insertions(+), 149 deletions(-)
 create mode 100644 xen/arch/x86/ioport.c

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index d7aed7d92c15..85a8475e126c 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -44,6 +44,7 @@ obj-y += msi.o
 obj-y += msr.o
 obj-$(CONFIG_INDIRECT_THUNK) += indirect-thunk.o
 obj-$(CONFIG_RETURN_THUNK) += indirect-thunk.o
+obj-y += ioport.o
 obj-$(CONFIG_PV) += ioport_emulate.o
 obj-y += irq.o
 obj-$(CONFIG_KEXEC) += machine_kexec.o
diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
index 0b467fd4a4fc..26202b33345c 100644
--- a/xen/arch/x86/dom0_build.c
+++ b/xen/arch/x86/dom0_build.c
@@ -298,9 +298,6 @@ int __init parse_arch_dom0_param(const char *s, const char *e)
     return 0;
 }
 
-static char __initdata opt_dom0_ioports_disable[200] = "";
-string_param("dom0_ioports_disable", opt_dom0_ioports_disable);
-
 static bool __initdata ro_hpet = true;
 boolean_param("ro-hpet", ro_hpet);
 
@@ -433,122 +430,20 @@ unsigned long __init dom0_compute_nr_pages(
     return nr_pages;
 }
 
-static void __init process_dom0_ioports_disable(struct domain *dom0)
-{
-    unsigned long io_from, io_to;
-    char *t, *s = opt_dom0_ioports_disable;
-    const char *u;
-
-    if ( *s == '\0' )
-        return;
-
-    while ( (t = strsep(&s, ",")) != NULL )
-    {
-        io_from = simple_strtoul(t, &u, 16);
-        if ( u == t )
-        {
-        parse_error:
-            printk("Invalid ioport range <%s> "
-                   "in dom0_ioports_disable, skipping\n", t);
-            continue;
-        }
-
-        if ( *u == '\0' )
-            io_to = io_from;
-        else if ( *u == '-' )
-            io_to = simple_strtoul(u + 1, &u, 16);
-        else
-            goto parse_error;
-
-        if ( (*u != '\0') || (io_to < io_from) || (io_to >= 65536) )
-            goto parse_error;
-
-        printk("Disabling dom0 access to ioport range %04lx-%04lx\n",
-            io_from, io_to);
-
-        if ( ioports_deny_access(dom0, io_from, io_to) != 0 )
-            BUG();
-    }
-}
-
+/* Modify I/O memory access permissions. */
 int __init dom0_setup_permissions(struct domain *d)
 {
     unsigned long mfn;
-    unsigned int i, offs;
-    int rc;
+    unsigned int i;
+    int rc = 0;
 
     if ( pv_shim )
         return 0;
 
-    /* The hardware domain is initially permitted full I/O capabilities. */
-    rc = ioports_permit_access(d, 0, 0xFFFF);
     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);
 
-    /* Modify I/O port access permissions. */
-
-    for ( offs = 0, i = ISOLATE_LSB(i8259A_alias_mask) ?: 2;
-          offs <= i8259A_alias_mask; offs += i )
-    {
-        if ( offs & ~i8259A_alias_mask )
-            continue;
-        /* Master Interrupt Controller (PIC). */
-        rc |= ioports_deny_access(d, 0x20 + offs, 0x21 + offs);
-        /* Slave Interrupt Controller (PIC). */
-        rc |= ioports_deny_access(d, 0xA0 + offs, 0xA1 + offs);
-    }
-
-    /* ELCR of both PICs. */
-    rc |= ioports_deny_access(d, 0x4D0, 0x4D1);
-
-    /* Interval Timer (PIT). */
-    for ( offs = 0, i = ISOLATE_LSB(pit_alias_mask) ?: 4;
-          offs <= pit_alias_mask; offs += i )
-        if ( !(offs & ~pit_alias_mask) )
-            rc |= ioports_deny_access(d, PIT_CH0 + offs, PIT_MODE + offs);
-
-    /* PIT Channel 2 / PC Speaker Control. */
-    rc |= ioports_deny_access(d, 0x61, 0x61);
-
-    /* INIT# and alternative A20M# control. */
-    rc |= ioports_deny_access(d, 0x92, 0x92);
-
-    /* IGNNE# control. */
-    rc |= ioports_deny_access(d, 0xF0, 0xF0);
-
-    /* ACPI PM Timer. */
-    if ( pmtmr_ioport )
-        rc |= ioports_deny_access(d, pmtmr_ioport, pmtmr_ioport + 3);
-
-    /* Reset control. */
-    rc |= ioports_deny_access(d, 0xCF9, 0xCF9);
-
-    /* PCI configuration space (NB. 0xCF8 has special treatment). */
-    rc |= ioports_deny_access(d, 0xCFC, 0xCFF);
-
-#ifdef CONFIG_HVM
-    if ( is_hvm_domain(d) )
-    {
-        /* ISA DMA controller, channels 0-3 (incl possible aliases). */
-        rc |= ioports_deny_access(d, 0x00, 0x1F);
-        /* ISA DMA controller, page registers (incl various reserved ones). */
-        rc |= ioports_deny_access(d, 0x80 + !!hvm_port80_allowed, 0x8F);
-        /* ISA DMA controller, channels 4-7 (incl usual aliases). */
-        rc |= ioports_deny_access(d, 0xC0, 0xDF);
-
-        /* HVM debug console IO port. */
-        rc |= ioports_deny_access(d, XEN_HVM_DEBUGCONS_IOPORT,
-                                  XEN_HVM_DEBUGCONS_IOPORT);
-        if ( amd_acpi_c1e_quirk )
-            rc |= ioports_deny_access(d, acpi_smi_cmd, acpi_smi_cmd);
-    }
-#endif
-    /* Command-line I/O ranges. */
-    process_dom0_ioports_disable(d);
-
-    /* Modify I/O memory access permissions. */
-
     /* Local APIC. */
     if ( mp_lapic_addr != 0 )
     {
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 363c010f8dcc..1fc16a22e157 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -51,6 +51,7 @@
 #include <asm/hvm/vm_event.h>
 #include <asm/hvm/vpt.h>
 #include <asm/i387.h>
+#include <asm/iocap.h>
 #include <asm/mc146818rtc.h>
 #include <asm/mce.h>
 #include <asm/monitor.h>
@@ -81,14 +82,6 @@ integer_param("hvm_debug", opt_hvm_debug_level);
 
 struct hvm_function_table __ro_after_init hvm_funcs;
 
-/*
- * The I/O permission bitmap is globally shared by all HVM guests except
- * the hardware domain which needs a more permissive one.
- */
-#define HVM_IOBITMAP_SIZE (3 * PAGE_SIZE)
-unsigned long __section(".bss.page_aligned") __aligned(PAGE_SIZE)
-    hvm_io_bitmap[HVM_IOBITMAP_SIZE / BYTES_PER_LONG];
-
 /* Xen command-line option to enable HAP */
 static bool __initdata opt_hap_enabled = true;
 boolean_param("hap", opt_hap_enabled);
@@ -266,15 +259,6 @@ static int __init cf_check hvm_enable(void)
     if ( opt_hvm_fep )
         warning_add(warning_hvm_fep);
 
-    /*
-     * Allow direct access to the PC debug ports 0x80 and 0xed (they are
-     * often used for I/O delays, but the vmexits simply slow things down).
-     */
-    memset(hvm_io_bitmap, ~0, sizeof(hvm_io_bitmap));
-    if ( hvm_port80_allowed )
-        __clear_bit(0x80, hvm_io_bitmap);
-    __clear_bit(0xed, hvm_io_bitmap);
-
     register_cpu_notifier(&cpu_nfb);
 
     return 0;
@@ -706,19 +690,12 @@ int hvm_domain_initialise(struct domain *d,
 
     rwlock_init(&d->arch.hvm.pl_time->pt_migrate);
 
-    /* Set the default IO Bitmap. */
-    if ( is_hardware_domain(d) )
+    rc = ioports_setup_access(d);
+    if ( rc )
     {
-        d->arch.hvm.io_bitmap = _xmalloc(HVM_IOBITMAP_SIZE, PAGE_SIZE);
-        if ( d->arch.hvm.io_bitmap == NULL )
-        {
-            rc = -ENOMEM;
-            goto fail1;
-        }
-        memset(d->arch.hvm.io_bitmap, ~0, HVM_IOBITMAP_SIZE);
+        printk("%pd failed to setup I/O bitmap: %d\n", d, rc);
+        goto fail1;
     }
-    else
-        d->arch.hvm.io_bitmap = hvm_io_bitmap;
 
     register_g2m_portio_handler(d);
     register_vpci_portio_handler(d);
@@ -745,6 +722,8 @@ int hvm_domain_initialise(struct domain *d,
         break;
     }
 
+    BUG_ON(!d->arch.ioport_caps);
+
     vpic_init(d);
 
     rc = vioapic_init(d);
diff --git a/xen/arch/x86/hvm/nestedhvm.c b/xen/arch/x86/hvm/nestedhvm.c
index bddd77d8109b..d4e03123d910 100644
--- a/xen/arch/x86/hvm/nestedhvm.c
+++ b/xen/arch/x86/hvm/nestedhvm.c
@@ -107,7 +107,7 @@ nestedhvm_vmcx_flushtlb(struct p2m_domain *p2m)
  * The users of the bitmap patterns are in SVM/VMX specific code.
  *
  * bitmap        port 0x80  port 0xed
- * hvm_io_bitmap cleared    cleared
+ * hvm.io_bitmap cleared    cleared
  * iomap[0]      cleared    set
  * iomap[1]      set        cleared
  * iomap[2]      set        set
@@ -115,7 +115,7 @@ nestedhvm_vmcx_flushtlb(struct p2m_domain *p2m)
 
 static int __init cf_check nestedhvm_setup(void)
 {
-    /* Same format and size as hvm_io_bitmap (Intel needs only 2 pages). */
+    /* Same format and size as hvm.io_bitmap (Intel needs only 2 pages). */
     unsigned nr = cpu_has_vmx ? 2 : 3;
     unsigned int i, order = get_order_from_pages(nr);
 
@@ -165,7 +165,7 @@ static int __init cf_check nestedhvm_setup(void)
 __initcall(nestedhvm_setup);
 
 unsigned long *
-nestedhvm_vcpu_iomap_get(bool ioport_80, bool ioport_ed)
+nestedhvm_vcpu_iomap_get(struct vcpu *v, bool ioport_80, bool ioport_ed)
 {
     int i;
 
@@ -174,7 +174,7 @@ nestedhvm_vcpu_iomap_get(bool ioport_80, bool ioport_ed)
 
     if (ioport_80 == 0) {
         if (ioport_ed == 0)
-            return hvm_io_bitmap;
+            return v->domain->arch.hvm.io_bitmap;
         i = 0;
     } else {
         if (ioport_ed == 0)
diff --git a/xen/arch/x86/hvm/quirks.c b/xen/arch/x86/hvm/quirks.c
index 9202f5a47fe9..f4d95441fcff 100644
--- a/xen/arch/x86/hvm/quirks.c
+++ b/xen/arch/x86/hvm/quirks.c
@@ -73,9 +73,6 @@ static int __init cf_check check_port80(void)
 
     dmi_check_system(hvm_no_port80_dmi_table);
 
-    if ( !hvm_port80_allowed )
-        __set_bit(0x80, hvm_io_bitmap);
-
     return 0;
 }
 __initcall(check_port80);
diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c
index dc2b6a42534a..cc8500b61665 100644
--- a/xen/arch/x86/hvm/svm/nestedsvm.c
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c
@@ -381,7 +381,7 @@ static int nsvm_vmrun_permissionmap(struct vcpu *v, bool viopm)
         hvm_unmap_guest_frame(ns_viomap, 0);
     }
 
-    svm->ns_iomap = nestedhvm_vcpu_iomap_get(ioport_80, ioport_ed);
+    svm->ns_iomap = nestedhvm_vcpu_iomap_get(v, ioport_80, ioport_ed);
 
     nv->nv_ioport80 = ioport_80;
     nv->nv_ioportED = ioport_ed;
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index e4f3a5fe4c71..4da3e6e90e6c 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -554,7 +554,7 @@ unsigned long *_shadow_io_bitmap(struct vcpu *v)
     port80 = bitmap[0x80 >> 3] & (1 << (0x80 & 0x7)) ? 1 : 0;
     portED = bitmap[0xed >> 3] & (1 << (0xed & 0x7)) ? 1 : 0;
 
-    return nestedhvm_vcpu_iomap_get(port80, portED);
+    return nestedhvm_vcpu_iomap_get(v, port80, portED);
 }
 
 static void update_msrbitmap(struct vcpu *v, uint32_t shadow_ctrl)
@@ -622,7 +622,7 @@ void nvmx_update_exec_control(struct vcpu *v, u32 host_cntrl)
              * L1 VMM doesn't intercept IO instruction.
              * Use host configuration and reset IO_BITMAP
              */
-            bitmap = hvm_io_bitmap;
+            bitmap = v->domain->arch.hvm.io_bitmap;
         }
         else {
             /* use IO bitmap */
diff --git a/xen/arch/x86/include/asm/hvm/nestedhvm.h b/xen/arch/x86/include/asm/hvm/nestedhvm.h
index ea2c1bc328c7..d691ccb07dd6 100644
--- a/xen/arch/x86/include/asm/hvm/nestedhvm.h
+++ b/xen/arch/x86/include/asm/hvm/nestedhvm.h
@@ -50,7 +50,8 @@ int nestedhvm_hap_nested_page_fault(struct vcpu *v, paddr_t *L2_gpa,
                                     struct npfec npfec);
 
 /* IO permission map */
-unsigned long *nestedhvm_vcpu_iomap_get(bool ioport_80, bool ioport_ed);
+unsigned long *nestedhvm_vcpu_iomap_get(struct vcpu *v,
+                                        bool ioport_80, bool ioport_ed);
 
 /* Misc */
 #define nestedhvm_paging_mode_hap(v) (!!nhvm_vmcx_hap_enabled(v))
diff --git a/xen/arch/x86/include/asm/hvm/support.h b/xen/arch/x86/include/asm/hvm/support.h
index 2a7ba36af06f..7e36d00cc188 100644
--- a/xen/arch/x86/include/asm/hvm/support.h
+++ b/xen/arch/x86/include/asm/hvm/support.h
@@ -41,8 +41,6 @@ extern unsigned int opt_hvm_debug_level;
 #define HVM_DBG_LOG(level, _f, _a...) do {} while (0)
 #endif
 
-extern unsigned long hvm_io_bitmap[];
-
 enum hvm_translation_result {
     HVMTRANS_okay,
     HVMTRANS_bad_linear_to_gfn,
diff --git a/xen/arch/x86/include/asm/iocap.h b/xen/arch/x86/include/asm/iocap.h
index f948b7186e95..1083f6171cf7 100644
--- a/xen/arch/x86/include/asm/iocap.h
+++ b/xen/arch/x86/include/asm/iocap.h
@@ -22,6 +22,8 @@
 #define cache_flush_permitted(d) \
     (has_arch_io_resources(d) || has_arch_pdevs(d))
 
+int ioports_setup_access(struct domain *d);
+
 static inline int ioports_permit_access(struct domain *d, unsigned long s,
                                         unsigned long e)
 {
diff --git a/xen/arch/x86/ioport.c b/xen/arch/x86/ioport.c
new file mode 100644
index 000000000000..dbcd52d37a4f
--- /dev/null
+++ b/xen/arch/x86/ioport.c
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Guest I/O port address space configuration.
+ *
+ * Copyright 2025 Ford Motor Company
+ */
+
+#include <xen/domain.h>
+#include <xen/param.h>
+
+#include <asm/amd.h>
+#include <asm/acpi.h>
+#include <asm/io-ports.h>
+#include <asm/iocap.h>
+#include <asm/pv/shim.h>
+#include <asm/setup.h>
+
+static char __initdata opt_dom0_ioports_disable[200] = "";
+string_param("dom0_ioports_disable", opt_dom0_ioports_disable);
+
+/*
+ * The I/O permission bitmap size.
+ * See: comment in nestedhvm_setup()
+ */
+#define HVM_IOBITMAP_SIZE (3 * PAGE_SIZE)
+
+/* Hide user-defined I/O ports from the guest OS. */
+static void process_dom0_ioports_disable(struct domain *dom0)
+{
+    unsigned long io_from, io_to;
+    char *t, *s = opt_dom0_ioports_disable;
+    const char *u;
+
+    if ( *s == '\0' )
+        return;
+
+    while ( (t = strsep(&s, ",")) != NULL )
+    {
+        io_from = simple_strtoul(t, &u, 16);
+        if ( u == t )
+        {
+        parse_error:
+            printk("Invalid ioport range <%s> "
+                   "in dom0_ioports_disable, skipping\n", t);
+            continue;
+        }
+
+        if ( *u == '\0' )
+            io_to = io_from;
+        else if ( *u == '-' )
+            io_to = simple_strtoul(u + 1, &u, 16);
+        else
+            goto parse_error;
+
+        if ( (*u != '\0') || (io_to < io_from) || (io_to >= 65536) )
+            goto parse_error;
+
+        printk("Disabling dom0 access to ioport range %04lx-%04lx\n",
+            io_from, io_to);
+
+        if ( ioports_deny_access(dom0, io_from, io_to) != 0 )
+            BUG();
+    }
+}
+
+/* Set the default IO Bitmap. */
+int ioports_setup_access(struct domain *d)
+{
+    unsigned int i, offs;
+    int rc;
+
+    if ( pv_shim )
+        return 0;
+
+#ifdef CONFIG_HVM
+    d->arch.hvm.io_bitmap = _xmalloc(HVM_IOBITMAP_SIZE, PAGE_SIZE);
+    if ( d->arch.hvm.io_bitmap == NULL )
+        return -ENOMEM;
+
+    memset(d->arch.hvm.io_bitmap, ~0, HVM_IOBITMAP_SIZE);
+
+    if ( !is_hardware_domain(d) )
+    {
+        /*
+         * Allow direct access to the PC debug ports 0x80 and 0xed (they are
+         * often used for I/O delays, but the vmexits simply slow things down).
+         */
+        if ( hvm_port80_allowed )
+            __clear_bit(0x80, d->arch.hvm.io_bitmap);
+
+        __clear_bit(0xed, d->arch.hvm.io_bitmap);
+
+        return 0;
+    }
+#endif
+
+    /* The hardware domain is initially permitted full I/O capabilities. */
+    rc = ioports_permit_access(d, 0, 0xFFFF);
+
+    /* Modify I/O port access permissions. */
+
+    for ( offs = 0, i = ISOLATE_LSB(i8259A_alias_mask) ?: 2;
+          offs <= i8259A_alias_mask; offs += i )
+    {
+        if ( offs & ~i8259A_alias_mask )
+            continue;
+        /* Master Interrupt Controller (PIC). */
+        rc |= ioports_deny_access(d, 0x20 + offs, 0x21 + offs);
+        /* Slave Interrupt Controller (PIC). */
+        rc |= ioports_deny_access(d, 0xA0 + offs, 0xA1 + offs);
+    }
+
+    /* ELCR of both PICs. */
+    rc |= ioports_deny_access(d, 0x4D0, 0x4D1);
+
+    /* Interval Timer (PIT). */
+    for ( offs = 0, i = ISOLATE_LSB(pit_alias_mask) ?: 4;
+          offs <= pit_alias_mask; offs += i )
+        if ( !(offs & ~pit_alias_mask) )
+            rc |= ioports_deny_access(d, PIT_CH0 + offs, PIT_MODE + offs);
+
+    /* PIT Channel 2 / PC Speaker Control. */
+    rc |= ioports_deny_access(d, 0x61, 0x61);
+
+    /* INIT# and alternative A20M# control. */
+    rc |= ioports_deny_access(d, 0x92, 0x92);
+
+    /* IGNNE# control. */
+    rc |= ioports_deny_access(d, 0xF0, 0xF0);
+
+    /* ACPI PM Timer. */
+    if ( pmtmr_ioport )
+        rc |= ioports_deny_access(d, pmtmr_ioport, pmtmr_ioport + 3);
+
+    /* Reset control. */
+    rc |= ioports_deny_access(d, 0xCF9, 0xCF9);
+
+    /* PCI configuration space (NB. 0xCF8 has special treatment). */
+    rc |= ioports_deny_access(d, 0xCFC, 0xCFF);
+
+#ifdef CONFIG_HVM
+    if ( is_hvm_domain(d) )
+    {
+        /* ISA DMA controller, channels 0-3 (incl possible aliases). */
+        rc |= ioports_deny_access(d, 0x00, 0x1F);
+        /* ISA DMA controller, page registers (incl various reserved ones). */
+        rc |= ioports_deny_access(d, 0x80 + !!hvm_port80_allowed, 0x8F);
+        /* ISA DMA controller, channels 4-7 (incl usual aliases). */
+        rc |= ioports_deny_access(d, 0xC0, 0xDF);
+
+        /* HVM debug console IO port. */
+        rc |= ioports_deny_access(d, XEN_HVM_DEBUGCONS_IOPORT,
+                                  XEN_HVM_DEBUGCONS_IOPORT);
+        if ( amd_acpi_c1e_quirk )
+            rc |= ioports_deny_access(d, acpi_smi_cmd, acpi_smi_cmd);
+    }
+#endif
+
+    /* Command-line I/O ranges. */
+    process_dom0_ioports_disable(d);
+
+    return rc;
+}
diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
index 21158ce1812e..2b8b4d869ee7 100644
--- a/xen/arch/x86/pv/dom0_build.c
+++ b/xen/arch/x86/pv/dom0_build.c
@@ -17,6 +17,7 @@
 #include <asm/bootinfo.h>
 #include <asm/bzimage.h>
 #include <asm/dom0_build.h>
+#include <asm/iocap.h>
 #include <asm/guest.h>
 #include <asm/page.h>
 #include <asm/pv/mm.h>
@@ -1033,6 +1034,9 @@ static int __init dom0_construct(const struct boot_domain *bd)
     if ( test_bit(XENFEAT_supervisor_mode_kernel, parms.f_required) )
         panic("Dom0 requires supervisor-mode execution\n");
 
+    rc = ioports_setup_access(d);
+    BUG_ON(rc != 0);
+
     rc = dom0_setup_permissions(d);
     BUG_ON(rc != 0);
 
diff --git a/xen/common/emul/vuart/ns16x50.c b/xen/common/emul/vuart/ns16x50.c
index c341f012d005..ea34c3ae598a 100644
--- a/xen/common/emul/vuart/ns16x50.c
+++ b/xen/common/emul/vuart/ns16x50.c
@@ -783,9 +783,20 @@ static int ns16x50_init(void *arg)
     struct vuart_ns16x50 *vdev = arg;
     const struct vuart_info *info = vdev->info;
     struct domain *d = vdev->owner;
+    int rc;
 
     ASSERT(vdev);
 
+    /* Disallow sharing physical I/O port */
+    rc = ioports_deny_access(d, info->base_addr,
+                             info->base_addr + info->size - 1);
+    if ( rc )
+    {
+        ns16x50_err(info, " virtual I/O port range [0x%04lx..0x%04lx]: conflict w/ physical range\n",
+                    info->base_addr, info->base_addr + info->size - 1);
+        return rc;
+    }
+
     /* NB: report 115200 baud rate. */
     vdev->regs[NS16X50_REGS_NUM + UART_DLL] = divisor & UINT8_MAX;
     vdev->regs[NS16X50_REGS_NUM + UART_DLM] = (divisor >> 8) & UINT8_MAX;
-- 
2.51.0



  parent reply	other threads:[~2025-09-08 21:12 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-08 21:11 [PATCH v7 00/16] x86: introduce NS16550-compatible UART emulator dmukhin
2025-09-08 21:11 ` [PATCH v7 01/16] emul/vuart: introduce framework for UART emulators dmukhin
2025-09-10  7:57   ` Mykola Kvach
2025-09-13 18:09     ` dmukhin
2025-09-08 21:11 ` [PATCH v7 02/16] xen/8250-uart: update definitions dmukhin
2025-09-09 10:05   ` Jan Beulich
2025-09-09 19:42     ` dmukhin
2025-09-10  8:39     ` Mykola Kvach
2025-09-13 17:50       ` dmukhin
2025-09-08 21:11 ` [PATCH v7 03/16] emul/ns16x50: implement emulator stub dmukhin
2025-09-10 10:05   ` Mykola Kvach
2025-09-13 17:29     ` dmukhin
2025-11-14  5:19     ` dmukhin
2025-09-15 10:16   ` Mykola Kvach
2025-11-14  5:28     ` dmukhin
2025-09-08 21:11 ` [PATCH v7 04/16] emul/ns16x50: implement DLL/DLM registers dmukhin
2025-09-10 10:16   ` Mykola Kvach
2025-09-08 21:11 ` [PATCH v7 05/16] emul/ns16x50: implement SCR register dmukhin
2025-09-12  7:23   ` Mykola Kvach
2025-09-08 21:11 ` [PATCH v7 06/16] emul/ns16x50: implement IER/IIR registers dmukhin
2025-09-15  6:00   ` Mykola Kvach
2025-09-08 21:11 ` [PATCH v7 07/16] emul/ns16x50: implement LCR/LSR registers dmukhin
2025-09-15  6:00   ` Mykola Kvach
2025-09-08 21:11 ` [PATCH v7 08/16] emul/ns16x50: implement MCR/MSR registers dmukhin
2025-09-15  6:00   ` Mykola Kvach
2025-09-15 14:49     ` Jan Beulich
2025-09-16  8:00       ` Mykola Kvach
2025-09-16 14:13         ` Jan Beulich
2025-09-08 21:11 ` [PATCH v7 09/16] emul/ns16x50: implement RBR register dmukhin
2025-11-18  6:00   ` Mykola Kvach
2025-09-08 21:11 ` [PATCH v7 10/16] emul/ns16x50: implement THR register dmukhin
2025-11-18  6:00   ` Mykola Kvach
2026-05-14 23:23     ` dmukhin
2025-09-08 21:11 ` [PATCH v7 11/16] emul/ns16x50: implement FCR register (write-only) dmukhin
2025-11-18  6:00   ` Mykola Kvach
2025-09-08 21:11 ` [PATCH v7 12/16] emul/ns16550: implement dump_state() hook dmukhin
2025-11-18  6:00   ` Mykola Kvach
2026-05-14 23:35     ` dmukhin
2025-09-08 21:11 ` [PATCH v7 13/16] emul/ns16x50: add Kconfig options dmukhin
2025-11-18  6:00   ` Mykola Kvach
2025-09-08 21:11 ` dmukhin [this message]
2025-11-18  6:00   ` [PATCH v7 14/16] x86/domain: enable per-domain I/O port bitmaps Mykola Kvach
2026-05-14 23:52     ` dmukhin
2025-09-08 21:11 ` [PATCH v7 15/16] xen/domain: allocate d->irq_caps before arch-specific initialization dmukhin
2025-11-18  6:00   ` Mykola Kvach
2025-09-08 21:11 ` [PATCH v7 16/16] emul/ns16x50: implement IRQ emulation via vIOAPIC dmukhin

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=20250908211149.279143-15-dmukhin@ford.com \
    --to=dmukhin@xen.org \
    --cc=andrew.cooper3@citrix.com \
    --cc=anthony.perard@vates.tech \
    --cc=dmukhin@ford.com \
    --cc=jbeulich@suse.com \
    --cc=julien@xen.org \
    --cc=michal.orzel@amd.com \
    --cc=roger.pau@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.