Devel
  Threads by month 
                
            - ----- 2025 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
March 2025
- 46 participants
- 118 discussions
                    
                        From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
Hi,
This patch series offers an out-of-process Remote Desktop Protocol (RDP)
server solution utilizing QEMU's -display dbus interface, offering improved
modularity and potential security benefits compared to built-in server.
This initiative was spearheaded by Mihnea Buzatu during the QEMU Summer of Code
2023. The project's goal was to develop an out-of-process RDP server using the
-display dbus interface, implemented in Rust. Given that the IronRDP crate
lacked some server support at the time, investments in IronRDP were required.
I finally released an initial v0.1 version of qemu-rdp on crates.io
(https://crates.io/crates/qemu-rdp) That should allow more people to review and
evaluate the state of this work.
On unix systems, with cargo/rust toolchain installed, it should be as easy as
running "cargo install qemu-rdp", apply this patch series for libvirt, set the
"rdp_tls_x509_cert_dir" location for your TLS certificates, and configure a VM
with both dbus & rdp graphics (run "virsh domdisplay DOMAIN" to get the display
connection details).
Thanks for the reviews & feedback!
v3: thanks to Martin Kletzander review
- drop "[PATCH v2 05/21] qemu: fall-through for unsupported graphics" patch
- drop extra \n when reporting dbus-daemon log
- check password != NULL or VIR_ERR_INTERNAL_ERROR
- remove some needless #include/leftover
- remove some needless g_auto pointer
- rebased
- add r-b tags
v2: thanks to Daniel review
- drop extra error report from "qemu: report an error for unsupported graphics"
- replace g_return pre-conditions with ATTRIBUTE_NONNULL
- improve "qemu/dbus: keep a connection to the VM D-Bus" to also reconnect
- use domainLogContext for logging (for virtiofs as well)
- check for qemu-rdp availabilty for setting 'rdp' capability
- make dbus-addr qemu-rdp capability mandatory
- rebased
- add r-b tags
Marc-André Lureau (20):
  build-sys: drop -Winline when optimization=g
  build: fix -Werror=maybe-uninitialized
  qemu-slirp: drop unneeded check for OOM
  util: annotate non-null arguments for virGDBusCallMethod()
  qemu: add rdp state directory
  qemu: add qemu RDP configuration
  conf: parse optional RDP username & password
  conf: generalize virDomainDefHasSpiceGraphics
  qemu: use virDomainDefHasGraphics
  qemu: add RDP ports range allocator
  qemu: limit to one <graphics type='rdp'>
  qemu/virtiofs: use domainLogContext
  qemu/dbus: keep a connection to the VM D-Bus
  qemu/dbus: log daemon stdout/err, use domainLogContext
  qemu: validate RDP configuration
  qemu: add qemu-rdp helper unit
  qemu: pass virQEMUDriverConfig to capabilities
  qemu: add 'rdp' capability if qemu-rdp is available
  qemu: add RDP support
  tests: add qemu <graphics type='rdp'/> test
 docs/formatdomain.rst                         |  25 +-
 meson.build                                   |   7 +-
 po/POTFILES                                   |   1 +
 src/conf/domain_conf.c                        |  28 +-
 src/conf/domain_conf.h                        |   5 +-
 src/conf/schemas/domaincommon.rng             |  10 +
 src/libvirt_private.syms                      |   2 +-
 src/qemu/libvirtd_qemu.aug                    |   7 +
 src/qemu/meson.build                          |   1 +
 src/qemu/qemu.conf.in                         |  31 ++
 src/qemu/qemu_capabilities.c                  |  24 +-
 src/qemu/qemu_capabilities.h                  |  12 +-
 src/qemu/qemu_command.c                       |   8 +-
 src/qemu/qemu_conf.c                          |  56 ++-
 src/qemu/qemu_conf.h                          |  13 +
 src/qemu/qemu_dbus.c                          |  69 ++-
 src/qemu/qemu_dbus.h                          |   3 +
 src/qemu/qemu_domain.c                        |   1 +
 src/qemu/qemu_domain.h                        |   4 +
 src/qemu/qemu_driver.c                        |  20 +
 src/qemu/qemu_extdevice.c                     |  46 +-
 src/qemu/qemu_hotplug.c                       |  51 ++-
 src/qemu/qemu_hotplug.h                       |   1 +
 src/qemu/qemu_process.c                       | 169 ++++++-
 src/qemu/qemu_rdp.c                           | 424 ++++++++++++++++++
 src/qemu/qemu_rdp.h                           |  73 +++
 src/qemu/qemu_slirp.c                         |   6 -
 src/qemu/qemu_validate.c                      |  48 +-
 src/qemu/qemu_virtiofs.c                      |  53 +--
 src/qemu/test_libvirtd_qemu.aug.in            |   5 +
 src/util/virgdbus.h                           |  13 +-
 .../qemu_10.0.0-q35.x86_64+amdsev.xml         |   1 +
 .../domaincapsdata/qemu_10.0.0-q35.x86_64.xml |   1 +
 .../qemu_10.0.0-tcg.x86_64+amdsev.xml         |   1 +
 .../domaincapsdata/qemu_10.0.0-tcg.x86_64.xml |   1 +
 tests/domaincapsdata/qemu_10.0.0.s390x.xml    |   1 +
 .../qemu_10.0.0.x86_64+amdsev.xml             |   1 +
 tests/domaincapsdata/qemu_10.0.0.x86_64.xml   |   1 +
 .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml  |   1 +
 .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_7.0.0.x86_64.xml    |   1 +
 .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml  |   1 +
 .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_7.1.0.x86_64.xml    |   1 +
 .../qemu_7.2.0-hvf.x86_64+hvf.xml             |   1 +
 .../domaincapsdata/qemu_7.2.0-q35.x86_64.xml  |   1 +
 .../qemu_7.2.0-tcg.x86_64+hvf.xml             |   1 +
 .../domaincapsdata/qemu_7.2.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_7.2.0.ppc.xml       |   1 +
 tests/domaincapsdata/qemu_7.2.0.x86_64.xml    |   1 +
 .../domaincapsdata/qemu_8.0.0-q35.x86_64.xml  |   1 +
 .../domaincapsdata/qemu_8.0.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_8.0.0.x86_64.xml    |   1 +
 .../domaincapsdata/qemu_8.1.0-q35.x86_64.xml  |   1 +
 .../domaincapsdata/qemu_8.1.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_8.1.0.s390x.xml     |   1 +
 tests/domaincapsdata/qemu_8.1.0.x86_64.xml    |   1 +
 .../domaincapsdata/qemu_8.2.0-q35.x86_64.xml  |   1 +
 .../qemu_8.2.0-tcg-virt.loongarch64.xml       |   1 +
 .../domaincapsdata/qemu_8.2.0-tcg.x86_64.xml  |   1 +
 .../qemu_8.2.0-virt.aarch64.xml               |   1 +
 .../qemu_8.2.0-virt.loongarch64.xml           |   1 +
 tests/domaincapsdata/qemu_8.2.0.aarch64.xml   |   1 +
 tests/domaincapsdata/qemu_8.2.0.armv7l.xml    |   1 +
 tests/domaincapsdata/qemu_8.2.0.s390x.xml     |   1 +
 tests/domaincapsdata/qemu_8.2.0.x86_64.xml    |   1 +
 .../domaincapsdata/qemu_9.0.0-q35.x86_64.xml  |   1 +
 .../domaincapsdata/qemu_9.0.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_9.0.0.sparc.xml     |   1 +
 tests/domaincapsdata/qemu_9.0.0.x86_64.xml    |   1 +
 .../domaincapsdata/qemu_9.1.0-q35.x86_64.xml  |   1 +
 .../qemu_9.1.0-tcg-virt.riscv64.xml           |   1 +
 .../domaincapsdata/qemu_9.1.0-tcg.x86_64.xml  |   1 +
 .../qemu_9.1.0-virt.riscv64.xml               |   1 +
 tests/domaincapsdata/qemu_9.1.0.s390x.xml     |   1 +
 tests/domaincapsdata/qemu_9.1.0.x86_64.xml    |   1 +
 .../qemu_9.2.0-hvf.aarch64+hvf.xml            |   1 +
 .../qemu_9.2.0-q35.x86_64+amdsev.xml          |   1 +
 .../domaincapsdata/qemu_9.2.0-q35.x86_64.xml  |   1 +
 .../qemu_9.2.0-tcg.x86_64+amdsev.xml          |   1 +
 .../domaincapsdata/qemu_9.2.0-tcg.x86_64.xml  |   1 +
 tests/domaincapsdata/qemu_9.2.0.s390x.xml     |   1 +
 .../qemu_9.2.0.x86_64+amdsev.xml              |   1 +
 tests/domaincapsdata/qemu_9.2.0.x86_64.xml    |   1 +
 tests/domaincapstest.c                        |   7 +-
 .../graphics-rdp.x86_64-latest.args           |  35 ++
 .../graphics-rdp.x86_64-latest.xml            |   1 +
 tests/qemuxmlconfdata/graphics-rdp.xml        |  43 ++
 tests/qemuxmlconftest.c                       |   2 +
 tests/testutilsqemu.c                         |  10 +
 tools/nss/libvirt_nss_leases.c                |   2 +-
 tools/nss/libvirt_nss_macs.c                  |   2 +-
 92 files changed, 1234 insertions(+), 137 deletions(-)
 create mode 100644 src/qemu/qemu_rdp.c
 create mode 100644 src/qemu/qemu_rdp.h
 create mode 100644 tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.args
 create mode 120000 tests/qemuxmlconfdata/graphics-rdp.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/graphics-rdp.xml
-- 
2.47.0
                    
                  
                  
                          
                            
                            5
                            
                          
                          
                            
                            26
                            
                          
                          
                            
    
                          
                        
                    
                    
                        Adds support for configuring <hyperv/> flags for domains
running under Xen.
The following flags, making use of QEMU's existing flags, are now
configurable for Xen: vapic, synic, stimer, frequencies, tlbflush and
ipi
Tests have been added validating translation to libxl's viridian flags
Updated docs section on <hyperv/> flags to note support and to specify
which flags work with Xen
Signed-off-by: Will <tcosprojects(a)gmail.com>
---
 NEWS.rst                                      |   5 +
 docs/formatdomain.rst                         |  20 +--
 src/libxl/libxl_conf.c                        |  90 ++++++++++
 .../viridian-hvm-full.json                    | 101 ++++++++++++
 .../viridian-hvm-full.xml                     |  45 +++++
 .../viridian-hvm-none.json                    |  89 ++++++++++
 .../viridian-hvm-none.xml                     |  36 ++++
 .../libxlxml2domconfigdata/viridian-hvm.json  |  99 +++++++++++
 tests/libxlxml2domconfigdata/viridian-hvm.xml |  42 +++++
 .../viridian-passthrough.json                 | 155 ++++++++++++++++++
 .../viridian-passthrough.xml                  |  37 +++++
 tests/libxlxml2domconfigtest.c                |   9 +
 12 files changed, 718 insertions(+), 10 deletions(-)
 create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm-full.json
 create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm-full.xml
 create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm-none.json
 create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm-none.xml
 create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm.json
 create mode 100644 tests/libxlxml2domconfigdata/viridian-hvm.xml
 create mode 100644 tests/libxlxml2domconfigdata/viridian-passthrough.json
 create mode 100644 tests/libxlxml2domconfigdata/viridian-passthrough.xml
diff --git a/NEWS.rst b/NEWS.rst
index 9c940b1a81..d6ad961f56 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -17,6 +17,11 @@ v11.2.0 (unreleased)
 
 * **New features**
 
+  * Support for configuration of ``<hyperv/>`` flags for Xen domains.
+
+    The following flags are now configurable for Xen: ``vapic``, ``synic``,
+    ``stimer``, ``frequencies``, ``tlbflush`` and ``ipi``.
+
 * **Improvements**
 
 * **Bug fixes**
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index cbe378e61d..4162ae7930 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -2084,31 +2084,31 @@ are:
    based virtualization drivers, such as LXC.
 ``hyperv``
    Enable various features improving behavior of guests running Microsoft
-   Windows.
+   Windows. :since:`Since 11.2.0` some of these flags are also available for Xen domains running Microsoft Windows.
 
    =============== ====================================================================== ============================================ ========================================================================
    Feature         Description                                                            Value                                        Since
    =============== ====================================================================== ============================================ ========================================================================
-   relaxed         Relax constraints on timers                                            on, off                                      :since:`1.0.0 (QEMU 2.0)`
-   vapic           Enable virtual APIC                                                    on, off                                      :since:`1.1.0 (QEMU 2.0)`
+   relaxed         Relax constraints on timers                                            on, off                                      :since:`1.0.0 (QEMU 2.0), 11.2.0 (Xen, always on)`
+   vapic           Enable virtual APIC                                                    on, off                                      :since:`1.1.0 (QEMU 2.0), 11.2.0 (Xen)`
    spinlocks       Enable spinlock support                                                on, off; retries - at least 4095             :since:`1.1.0 (QEMU 2.0)`
-   vpindex         Virtual processor index                                                on, off                                      :since:`1.3.3 (QEMU 2.5)`
+   vpindex         Virtual processor index                                                on, off                                      :since:`1.3.3 (QEMU 2.5), 11.2.0 (Xen, always on)`
    runtime         Processor time spent on running guest code and on behalf of guest code on, off                                      :since:`1.3.3 (QEMU 2.5)`
-   synic           Enable Synthetic Interrupt Controller (SynIC)                          on, off                                      :since:`1.3.3 (QEMU 2.6)`
-   stimer          Enable SynIC timers, optionally with Direct Mode support               on, off; direct - on,off                     :since:`1.3.3 (QEMU 2.6), direct mode 5.7.0 (QEMU 4.1)`
+   synic           Enable Synthetic Interrupt Controller (SynIC)                          on, off                                      :since:`1.3.3 (QEMU 2.6), 11.2.0 (Xen)`
+   stimer          Enable SynIC timers, optionally with Direct Mode support               on, off; direct - on,off                     :since:`1.3.3 (QEMU 2.6), direct mode 5.7.0 (QEMU 4.1), 11.2.0 (Xen, on/off only)`
    reset           Enable hypervisor reset                                                on, off                                      :since:`1.3.3 (QEMU 2.5)`
    vendor_id       Set hypervisor vendor id                                               on, off; value - string, up to 12 characters :since:`1.3.3 (QEMU 2.5)`
-   frequencies     Expose frequency MSRs                                                  on, off                                      :since:`4.7.0 (QEMU 2.12)`
+   frequencies     Expose frequency MSRs                                                  on, off                                      :since:`4.7.0 (QEMU 2.12), 11.2.0 (Xen)`
    reenlightenment Enable re-enlightenment notification on migration                      on, off                                      :since:`4.7.0 (QEMU 3.0)`
-   tlbflush        Enable PV TLB flush support                                            on, off; direct - on,off; extended - on,off  :since:`4.7.0 (QEMU 3.0), direct and extended modes 11.0.0 (QEMU 7.1.0)`
-   ipi             Enable PV IPI support                                                  on, off                                      :since:`4.10.0 (QEMU 3.1)`
+   tlbflush        Enable PV TLB flush support                                            on, off; direct - on,off; extended - on,off  :since:`4.7.0 (QEMU 3.0), direct and extended modes 11.0.0 (QEMU 7.1.0), 11.2.0 (Xen, on/off only)`
+   ipi             Enable PV IPI support                                                  on, off                                      :since:`4.10.0 (QEMU 3.1), 11.2.0 (Xen)`
    evmcs           Enable Enlightened VMCS                                                on, off                                      :since:`4.10.0 (QEMU 3.1)`
    avic            Enable use Hyper-V SynIC with hardware APICv/AVIC                      on, off                                      :since:`8.10.0 (QEMU 6.2)`
    emsr_bitmap     Avoid unnecessary updates to L2 MSR Bitmap upon vmexits.               on, off                                      :since:`10.7.0 (QEMU 7.1)`
    xmm_input       Enable XMM Fast Hypercall Input                                        on, off                                      :since:`10.7.0 (QEMU 7.1)`
    =============== ====================================================================== ============================================ ========================================================================
 
-   :since:`Since 8.0.0`, the hypervisor can be configured further by setting
+   :since:`Since 8.0.0 (QEMU) Since 11.2.0 (Xen)`, the hypervisor can be configured further by setting
    the ``mode`` attribute to one of the following values:
 
    ``custom``
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index c404226e43..d79cf93573 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -582,6 +582,96 @@ libxlMakeDomBuildInfo(virDomainDef *def,
                           VIR_TRISTATE_SWITCH_ON);
 #endif
 
+#ifdef LIBXL_HAVE_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE
+        if (def->features[VIR_DOMAIN_FEATURE_HYPERV] != VIR_DOMAIN_HYPERV_MODE_NONE) {
+            libxl_bitmap_alloc(ctx, &b_info->u.hvm.viridian_enable,
+                               LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH);
+
+            switch ((virDomainHyperVMode) def->features[VIR_DOMAIN_FEATURE_HYPERV]) {
+            case VIR_DOMAIN_HYPERV_MODE_CUSTOM:
+                // Base is required by Xen to enable any other flag
+                libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_BASE);
+                // Enable crash ctl register by default to allow guest logs to reach Xen
+                libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_CRASH_CTL);
+                break;
+            case VIR_DOMAIN_HYPERV_MODE_PASSTHROUGH:
+                libxl_bitmap_set_any(&b_info->u.hvm.viridian_enable);
+                break;
+            case VIR_DOMAIN_HYPERV_MODE_NONE:
+            case VIR_DOMAIN_HYPERV_MODE_LAST:
+            default:
+                virReportEnumRangeError(virDomainHyperVMode,
+                                        def->features[VIR_DOMAIN_FEATURE_HYPERV]);
+                return -1;
+            }
+
+            for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
+                switch ((virDomainHyperv) i) {
+                case VIR_DOMAIN_HYPERV_VPINDEX:
+                case VIR_DOMAIN_HYPERV_RELAXED:
+                    // Already set by base flag
+                    break;
+                case VIR_DOMAIN_HYPERV_SYNIC:
+                    if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC);
+                    }
+                    break;
+                case VIR_DOMAIN_HYPERV_STIMER:
+                    if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+                        // STIMER implies synic and clock features
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_STIMER);
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_SYNIC);
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT);
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC);
+                    }
+                    break;
+                case VIR_DOMAIN_HYPERV_VAPIC:
+                    if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_APIC_ASSIST);
+                    }
+                    break;
+                case VIR_DOMAIN_HYPERV_FREQUENCIES:
+                    if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_FREQ);
+                    }
+                    break;
+                case VIR_DOMAIN_HYPERV_TLBFLUSH:
+                    if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_REMOTE_TLB_FLUSH);
+                    }
+                    break;
+                case VIR_DOMAIN_HYPERV_IPI:
+                    if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+                        libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_IPI);
+                    }
+                    break;
+                case VIR_DOMAIN_HYPERV_SPINLOCKS:
+                case VIR_DOMAIN_HYPERV_VENDOR_ID:
+                    if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+                        const char *name = virDomainHypervTypeToString(i);
+                        VIR_WARN("Hyper-v flag '%s' is specified per-domain but is a global Xen setting and will be ignored.", name);
+                    }
+                    break;
+                case VIR_DOMAIN_HYPERV_RUNTIME:
+                case VIR_DOMAIN_HYPERV_RESET:
+                case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
+                case VIR_DOMAIN_HYPERV_EVMCS:
+                case VIR_DOMAIN_HYPERV_AVIC:
+                case VIR_DOMAIN_HYPERV_EMSR_BITMAP:
+                case VIR_DOMAIN_HYPERV_XMM_INPUT:
+                    if (def->hyperv_features[i] == VIR_TRISTATE_SWITCH_ON) {
+                        const char *name = virDomainHypervTypeToString(i);
+                        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                            _("Hyper-v enlightenment feature '%1$s' is not supported for Xen domains."), name);
+                    }
+                    break;
+                case VIR_DOMAIN_HYPERV_LAST:
+                    break;
+                }
+            }
+        }
+#endif
+
         /* copy SLIC table path to acpi_firmware */
         b_info->u.hvm.acpi_firmware = g_strdup(def->os.slic_table);
 
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm-full.json b/tests/libxlxml2domconfigdata/viridian-hvm-full.json
new file mode 100644
index 0000000000..5cb69f7b5d
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm-full.json
@@ -0,0 +1,101 @@
+{
+    "c_info": {
+        "type": "hvm",
+        "name": "test-hvm",
+        "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "max_memkb": 1048576,
+        "target_memkb": 1048576,
+        "video_memkb": 8192,
+        "shadow_memkb": 1234,
+        "device_model_version": "qemu_xen",
+        "device_model": "/bin/true",
+        "sched_params": {
+
+        },
+        "apic": "True",
+        "acpi": "True",
+        "type.hvm": {
+            "pae": "True",
+            "viridian_enable": [
+                0,
+                1,
+                2,
+                3,
+                4,
+                5,
+                6,
+                7,
+                8,
+                9
+            ],
+            "vga": {
+                "kind": "cirrus"
+            },
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            },
+            "spice": {
+
+            },
+            "boot": "c",
+            "rdm": {
+
+            }
+        },
+        "arch_arm": {
+
+        }
+    },
+    "disks": [
+        {
+            "pdev_path": "/var/lib/xen/images/test-hvm.img",
+            "vdev": "hda",
+            "backend": "qdisk",
+            "format": "raw",
+            "removable": 1,
+            "readwrite": 1
+        }
+    ],
+    "nics": [
+        {
+            "devid": 0,
+            "mac": "00:16:3e:66:12:b4",
+            "bridge": "br0",
+            "script": "/etc/xen/scripts/vif-bridge",
+            "nictype": "vif_ioemu"
+        }
+    ],
+    "vfbs": [
+        {
+	    "devid": -1,
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            }
+        }
+    ],
+    "vkbs": [
+        {
+            "devid": -1
+        }
+    ],
+    "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm-full.xml b/tests/libxlxml2domconfigdata/viridian-hvm-full.xml
new file mode 100644
index 0000000000..17f5ed5209
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm-full.xml
@@ -0,0 +1,45 @@
+<domain type='xen'>
+  <name>test-hvm</name>
+  <description>None</description>
+  <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+  <memory>1048576</memory>
+  <currentMemory>1048576</currentMemory>
+  <vcpu>4</vcpu>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <clock offset='utc'/>
+  <os>
+    <type>hvm</type>
+    <loader>/usr/lib/xen/boot/hvmloader</loader>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <apic/>
+    <acpi/>
+    <pae/>
+    <hyperv>
+      <vapic state='on'/>
+      <vpindex state='on'/>
+      <synic state='on'/>
+      <stimer state='on'/>
+      <frequencies state='on'/>
+      <tlbflush state='on'/>
+      <ipi state='on'/>
+    </hyperv>
+  </features>
+  <devices>
+    <emulator>/bin/true</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu'/>
+      <source file='/var/lib/xen/images/test-hvm.img'/>
+      <target dev='hda'/>
+    </disk>
+    <interface type='bridge'>
+      <source bridge='br0'/>
+      <mac address='00:16:3e:66:12:b4'/>
+      <script path='/etc/xen/scripts/vif-bridge'/>
+    </interface>
+    <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+  </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm-none.json b/tests/libxlxml2domconfigdata/viridian-hvm-none.json
new file mode 100644
index 0000000000..d30875420d
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm-none.json
@@ -0,0 +1,89 @@
+{
+    "c_info": {
+        "type": "hvm",
+        "name": "test-hvm",
+        "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "max_memkb": 1048576,
+        "target_memkb": 1048576,
+        "video_memkb": 8192,
+        "shadow_memkb": 1234,
+        "device_model_version": "qemu_xen",
+        "device_model": "/bin/true",
+        "sched_params": {
+
+        },
+        "apic": "True",
+        "acpi": "True",
+        "type.hvm": {
+            "pae": "True",
+            "vga": {
+                "kind": "cirrus"
+            },
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            },
+            "spice": {
+
+            },
+            "boot": "c",
+            "rdm": {
+
+            }
+        },
+        "arch_arm": {
+
+        }
+    },
+    "disks": [
+        {
+            "pdev_path": "/var/lib/xen/images/test-hvm.img",
+            "vdev": "hda",
+            "backend": "qdisk",
+            "format": "raw",
+            "removable": 1,
+            "readwrite": 1
+        }
+    ],
+    "nics": [
+        {
+            "devid": 0,
+            "mac": "00:16:3e:66:12:b4",
+            "bridge": "br0",
+            "script": "/etc/xen/scripts/vif-bridge",
+            "nictype": "vif_ioemu"
+        }
+    ],
+    "vfbs": [
+        {
+	    "devid": -1,
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            }
+        }
+    ],
+    "vkbs": [
+        {
+            "devid": -1
+        }
+    ],
+    "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm-none.xml b/tests/libxlxml2domconfigdata/viridian-hvm-none.xml
new file mode 100644
index 0000000000..68c2ef08af
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm-none.xml
@@ -0,0 +1,36 @@
+<domain type='xen'>
+  <name>test-hvm</name>
+  <description>None</description>
+  <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+  <memory>1048576</memory>
+  <currentMemory>1048576</currentMemory>
+  <vcpu>4</vcpu>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <clock offset='utc'/>
+  <os>
+    <type>hvm</type>
+    <loader>/usr/lib/xen/boot/hvmloader</loader>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <apic/>
+    <acpi/>
+    <pae/>
+  </features>
+  <devices>
+    <emulator>/bin/true</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu'/>
+      <source file='/var/lib/xen/images/test-hvm.img'/>
+      <target dev='hda'/>
+    </disk>
+    <interface type='bridge'>
+      <source bridge='br0'/>
+      <mac address='00:16:3e:66:12:b4'/>
+      <script path='/etc/xen/scripts/vif-bridge'/>
+    </interface>
+    <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+  </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm.json b/tests/libxlxml2domconfigdata/viridian-hvm.json
new file mode 100644
index 0000000000..4f9a52ed89
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm.json
@@ -0,0 +1,99 @@
+{
+    "c_info": {
+        "type": "hvm",
+        "name": "test-hvm",
+        "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "max_memkb": 1048576,
+        "target_memkb": 1048576,
+        "video_memkb": 8192,
+        "shadow_memkb": 1234,
+        "device_model_version": "qemu_xen",
+        "device_model": "/bin/true",
+        "sched_params": {
+
+        },
+        "apic": "True",
+        "acpi": "True",
+        "type.hvm": {
+            "pae": "True",
+            "viridian_enable": [
+                0,
+                2,
+                3,
+                4,
+                6,
+                7,
+                8,
+                9
+            ],
+            "vga": {
+                "kind": "cirrus"
+            },
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            },
+            "spice": {
+
+            },
+            "boot": "c",
+            "rdm": {
+
+            }
+        },
+        "arch_arm": {
+
+        }
+    },
+    "disks": [
+        {
+            "pdev_path": "/var/lib/xen/images/test-hvm.img",
+            "vdev": "hda",
+            "backend": "qdisk",
+            "format": "raw",
+            "removable": 1,
+            "readwrite": 1
+        }
+    ],
+    "nics": [
+        {
+            "devid": 0,
+            "mac": "00:16:3e:66:12:b4",
+            "bridge": "br0",
+            "script": "/etc/xen/scripts/vif-bridge",
+            "nictype": "vif_ioemu"
+        }
+    ],
+    "vfbs": [
+        {
+	    "devid": -1,
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            }
+        }
+    ],
+    "vkbs": [
+        {
+            "devid": -1
+        }
+    ],
+    "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/viridian-hvm.xml b/tests/libxlxml2domconfigdata/viridian-hvm.xml
new file mode 100644
index 0000000000..c6139885aa
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-hvm.xml
@@ -0,0 +1,42 @@
+<domain type='xen'>
+  <name>test-hvm</name>
+  <description>None</description>
+  <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+  <memory>1048576</memory>
+  <currentMemory>1048576</currentMemory>
+  <vcpu>4</vcpu>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <clock offset='utc'/>
+  <os>
+    <type>hvm</type>
+    <loader>/usr/lib/xen/boot/hvmloader</loader>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <apic/>
+    <acpi/>
+    <pae/>
+    <hyperv mode="custom">
+      <synic state='on'/>
+      <stimer state='on'/>
+      <tlbflush state='on'/>
+      <ipi state='on'/>
+    </hyperv>
+  </features>
+  <devices>
+    <emulator>/bin/true</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu'/>
+      <source file='/var/lib/xen/images/test-hvm.img'/>
+      <target dev='hda'/>
+    </disk>
+    <interface type='bridge'>
+      <source bridge='br0'/>
+      <mac address='00:16:3e:66:12:b4'/>
+      <script path='/etc/xen/scripts/vif-bridge'/>
+    </interface>
+    <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+  </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigdata/viridian-passthrough.json b/tests/libxlxml2domconfigdata/viridian-passthrough.json
new file mode 100644
index 0000000000..66069931f6
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-passthrough.json
@@ -0,0 +1,155 @@
+{
+    "c_info": {
+        "type": "hvm",
+        "name": "test-hvm",
+        "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "max_memkb": 1048576,
+        "target_memkb": 1048576,
+        "video_memkb": 8192,
+        "shadow_memkb": 1234,
+        "device_model_version": "qemu_xen",
+        "device_model": "/bin/true",
+        "sched_params": {
+
+        },
+        "apic": "True",
+        "acpi": "True",
+        "type.hvm": {
+            "pae": "True",
+            "viridian_enable": [
+                0,
+                1,
+                2,
+                3,
+                4,
+                5,
+                6,
+                7,
+                8,
+                9,
+                10,
+                11,
+                12,
+                13,
+                14,
+                15,
+                16,
+                17,
+                18,
+                19,
+                20,
+                21,
+                22,
+                23,
+                24,
+                25,
+                26,
+                27,
+                28,
+                29,
+                30,
+                31,
+                32,
+                33,
+                34,
+                35,
+                36,
+                37,
+                38,
+                39,
+                40,
+                41,
+                42,
+                43,
+                44,
+                45,
+                46,
+                47,
+                48,
+                49,
+                50,
+                51,
+                52,
+                53,
+                54,
+                55,
+                56,
+                57,
+                58,
+                59,
+                60,
+                61,
+                62,
+                63
+            ],
+            "vga": {
+                "kind": "cirrus"
+            },
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            },
+            "spice": {
+
+            },
+            "boot": "c",
+            "rdm": {
+
+            }
+        },
+        "arch_arm": {
+
+        }
+    },
+    "disks": [
+        {
+            "pdev_path": "/var/lib/xen/images/test-hvm.img",
+            "vdev": "hda",
+            "backend": "qdisk",
+            "format": "raw",
+            "removable": 1,
+            "readwrite": 1
+        }
+    ],
+    "nics": [
+        {
+            "devid": 0,
+            "mac": "00:16:3e:66:12:b4",
+            "bridge": "br0",
+            "script": "/etc/xen/scripts/vif-bridge",
+            "nictype": "vif_ioemu"
+        }
+    ],
+    "vfbs": [
+        {
+	    "devid": -1,
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            }
+        }
+    ],
+    "vkbs": [
+        {
+            "devid": -1
+        }
+    ],
+    "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/viridian-passthrough.xml b/tests/libxlxml2domconfigdata/viridian-passthrough.xml
new file mode 100644
index 0000000000..6d6b7d22cd
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/viridian-passthrough.xml
@@ -0,0 +1,37 @@
+<domain type='xen'>
+  <name>test-hvm</name>
+  <description>None</description>
+  <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+  <memory>1048576</memory>
+  <currentMemory>1048576</currentMemory>
+  <vcpu>4</vcpu>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <clock offset='utc'/>
+  <os>
+    <type>hvm</type>
+    <loader>/usr/lib/xen/boot/hvmloader</loader>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <apic/>
+    <acpi/>
+    <pae/>
+    <hyperv mode="passthrough"/>
+  </features>
+  <devices>
+    <emulator>/bin/true</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu'/>
+      <source file='/var/lib/xen/images/test-hvm.img'/>
+      <target dev='hda'/>
+    </disk>
+    <interface type='bridge'>
+      <source bridge='br0'/>
+      <mac address='00:16:3e:66:12:b4'/>
+      <script path='/etc/xen/scripts/vif-bridge'/>
+    </interface>
+    <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+  </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigtest.c b/tests/libxlxml2domconfigtest.c
index 255855b156..4654821c3f 100644
--- a/tests/libxlxml2domconfigtest.c
+++ b/tests/libxlxml2domconfigtest.c
@@ -211,6 +211,15 @@ mymain(void)
     DO_TEST("single-serial");
     DO_TEST("multiple-serial");
 
+#ifdef LIBXL_HAVE_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE
+    DO_TEST("viridian-hvm");
+    DO_TEST("viridian-hvm-full");
+    DO_TEST("viridian-hvm-none");
+#if LIBXL_BUILDINFO_HVM_VIRIDIAN_ENABLE_DISABLE_WIDTH == 64
+    DO_TEST("viridian-passthrough");
+#endif
+#endif
+
     unlink("libxl-driver.log");
 
     testXLFreeDriver(driver);
-- 
2.48.1
                    
                  
                  
                          
                            
                            2
                            
                          
                          
                            
                            6
                            
                          
                          
                            
    
                          
                        
                     
                        
                    
                        
                            
                                
                            
                            [PATCH 0/3] ch: monitor daemonization, sync after reboot, and shutdown fixes
                        
                        
by Kirill Shchetiniuk 03 Apr '25
                    by Kirill Shchetiniuk 03 Apr '25
03 Apr '25
                    
                        1. Run CH monitor as a daemon
Made the monitor process daemonized to prevent VM termination if
the CH driver crashes. Added pidfile for daemon's pid aquiring and tracking
as well as its init.
2. Update domain info after reboot
Fixed an issue where domain properties (e.g., serial console path)
were not updated after VM reboot. Added VIR_CH_EVENT_VM_REBOOTED
handling to keep the transient domain definition consistent.
3. Update VM shutdown event handler
VM monitor was still up even if VM was shut off, which led to an
inability to start the domain again.
virsh # shutdown ch-test
Domain 'ch-test' is being shutdown
virsh # list
 Id       Name      State
 ------------------------------
 722117   ch-test   shut off
Ensured the CH monitor process terminates along with the
VM shutdown (e.g., executed using virsh). Updated
virCHEventStopProcess to have proper job type.
Kirill Shchetiniuk (3):
  ch: virCHMonitorNew() run new CH monitor daemonized
  ch: virCHProcessEvent() update domain info after reboot
  ch: virCHProcessEvent() vm shutdown event handler fix
 src/ch/ch_domain.c  |  1 +
 src/ch/ch_domain.h  |  1 +
 src/ch/ch_events.c  |  8 ++++----
 src/ch/ch_monitor.c | 24 ++++++++++++++++++++++--
 src/ch/ch_process.c | 18 +++++++++++++++++-
 src/ch/ch_process.h |  2 ++
 6 files changed, 47 insertions(+), 7 deletions(-)
--
2.48.1
                    
                  
                  
                          
                            
                            3
                            
                          
                          
                            
                            8
                            
                          
                          
                            
    
                          
                        
                     
                        
                    03 Apr '25
                    
                        The current virpci code uses the Linux-specific sysfs subsystem, which makes
it impossible to use on other Unix-like systems. The libpciaccess library
provides a cross-platform API for accessing the PCI bus. Employ it to make
the code portable.
This makes libpciaccess a non-optional dependency of libvirt.
Signed-off-by: Alexander Shursha <kekek2(a)ya.ru>
---
 meson.build        |  11 +-
 meson_options.txt  |   4 +-
 src/meson.build    |   1 +
 src/util/virpci.c  | 465 +++++++++++----------------------------------
 tests/virpcimock.c |  22 ++-
 5 files changed, 139 insertions(+), 364 deletions(-)
diff --git a/meson.build b/meson.build
index 2d76a0846c..85bd882406 100644
--- a/meson.build
+++ b/meson.build
@@ -1207,7 +1207,10 @@ parallels_sdk_version = '7.0.22'
 parallels_sdk_dep = dependency('parallels-sdk', version: '>=' + parallels_sdk_version, required: false)
 
 pciaccess_version = '0.10.0'
-pciaccess_dep = dependency('pciaccess', version: '>=' + pciaccess_version, required: get_option('pciaccess'))
+pciaccess_dep = dependency('pciaccess', version: '>=' + pciaccess_version)
+if not pciaccess_dep.found()
+  error('pciaccess is required to build libvirt')
+endif
 
 rbd_dep = cc.find_library('rbd', required: get_option('storage_rbd'))
 rados_dep = cc.find_library('rados', required: get_option('storage_rbd'))
@@ -1461,11 +1464,6 @@ if not get_option('polkit').disabled()
   endif
 endif
 
-if udev_dep.found() and not pciaccess_dep.found()
-  error('You must install the pciaccess module to build with udev')
-endif
-
-
 # build driver options
 
 remote_default_mode = get_option('remote_default_mode')
@@ -2341,7 +2339,6 @@ libs_summary = {
   'numactl': numactl_dep.found(),
   'openwsman': openwsman_dep.found(),
   'parallels-sdk': parallels_sdk_dep.found(),
-  'pciaccess': pciaccess_dep.found(),
   'polkit': conf.has('WITH_POLKIT'),
   'rbd': rbd_dep.found(),
   'readline': readline_dep.found(),
diff --git a/meson_options.txt b/meson_options.txt
index 3dc3e8667b..69605238ba 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -38,7 +38,6 @@ option('netcf', type: 'feature', value: 'auto', description: 'netcf support')
 option('nls', type: 'feature', value: 'auto', description: 'nls support')
 option('numactl', type: 'feature', value: 'auto', description: 'numactl support')
 option('openwsman', type: 'feature', value: 'auto', description: 'openwsman support')
-option('pciaccess', type: 'feature', value: 'auto', description: 'pciaccess support')
 option('polkit', type: 'feature', value: 'auto', description: 'use PolicyKit for UNIX socket access checks')
 option('readline', type: 'feature', value: 'auto', description: 'readline support')
 option('sanlock', type: 'feature', value: 'auto', description: 'sanlock support')
@@ -46,7 +45,6 @@ option('sasl', type: 'feature', value: 'auto', description: 'sasl support')
 option('selinux', type: 'feature', value: 'auto', description: 'selinux support')
 option('selinux_mount', type: 'string', value: '', description: 'set SELinux mount point')
 option('sshconfdir', type: 'string', value: '', description: 'directory for SSH client configuration')
-# dep:pciaccess
 option('udev', type: 'feature', value: 'auto', description: 'udev support')
 # dep:driver_remote
 option('wireshark_dissector', type: 'feature', value: 'auto', description: 'wireshark support')
@@ -59,7 +57,7 @@ option('driver_bhyve', type: 'feature', value: 'auto', description: 'bhyve drive
 option('driver_esx', type: 'feature', value: 'auto', description: 'esx driver')
 # dep:openwsman
 option('driver_hyperv', type: 'feature', value: 'auto', description: 'Hyper-V driver')
-# dep:pciaccess dep:udev dep:driver_remote dep:driver_libvirtd
+# dep:udev dep:driver_remote dep:driver_libvirtd
 option('driver_interface', type: 'feature', value: 'auto', description: 'host interface driver')
 # dep:driver_remote
 option('driver_libvirtd', type: 'feature', value: 'auto', description: 'libvirtd driver')
diff --git a/src/meson.build b/src/meson.build
index 9413192a55..39788ac4d7 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -411,6 +411,7 @@ libvirt_lib = shared_library(
   dtrace_gen_objects,
   dependencies: [
     src_dep,
+    pciaccess_dep
   ],
   link_args: libvirt_link_args,
   link_whole: [
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 90617e69c6..b5bbe73ece 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -2,6 +2,7 @@
  * virpci.c: helper APIs for managing host PCI devices
  *
  * Copyright (C) 2009-2015 Red Hat, Inc.
+ * Copyright (C) 2024-2025 Future Crew, LLC
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -29,6 +30,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <pciaccess.h>
 
 #ifdef __linux__
 # include <sys/utsname.h>
@@ -72,7 +74,7 @@ struct _virPCIDevice {
 
     char          *name;              /* domain:bus:slot.function */
     char          id[PCI_ID_LEN];     /* product vendor */
-    char          *path;
+    struct pci_device *device;
 
     /* The driver:domain which uses the device */
     char          *used_by_drvname;
@@ -359,121 +361,6 @@ virPCIDeviceGetCurrentDriverNameAndType(virPCIDevice *dev,
 }
 
 
-static int
-virPCIDeviceConfigOpenInternal(virPCIDevice *dev, bool readonly, bool fatal)
-{
-    int fd;
-
-    fd = open(dev->path, readonly ? O_RDONLY : O_RDWR);
-
-    if (fd < 0) {
-        if (fatal) {
-            virReportSystemError(errno,
-                                 _("Failed to open config space file '%1$s'"),
-                                 dev->path);
-        } else {
-            VIR_WARN("Failed to open config space file '%s': %s",
-                     dev->path, g_strerror(errno));
-        }
-        return -1;
-    }
-
-    VIR_DEBUG("%s %s: opened %s", dev->id, dev->name, dev->path);
-    return fd;
-}
-
-static int
-virPCIDeviceConfigOpen(virPCIDevice *dev)
-{
-    return virPCIDeviceConfigOpenInternal(dev, true, true);
-}
-
-static int
-virPCIDeviceConfigOpenTry(virPCIDevice *dev)
-{
-    return virPCIDeviceConfigOpenInternal(dev, true, false);
-}
-
-static int
-virPCIDeviceConfigOpenWrite(virPCIDevice *dev)
-{
-    return virPCIDeviceConfigOpenInternal(dev, false, true);
-}
-
-static void
-virPCIDeviceConfigClose(virPCIDevice *dev, int cfgfd)
-{
-    if (VIR_CLOSE(cfgfd) < 0) {
-        VIR_WARN("Failed to close config space file '%s': %s",
-                 dev->path, g_strerror(errno));
-    }
-}
-
-
-static int
-virPCIDeviceRead(virPCIDevice *dev,
-                 int cfgfd,
-                 unsigned int pos,
-                 uint8_t *buf,
-                 unsigned int buflen)
-{
-    memset(buf, 0, buflen);
-    errno = 0;
-
-    if (lseek(cfgfd, pos, SEEK_SET) != pos ||
-        saferead(cfgfd, buf, buflen) != buflen) {
-        VIR_DEBUG("Failed to read %u bytes at %u from '%s' : %s",
-                 buflen, pos, dev->path, g_strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
-
-/**
- * virPCIDeviceReadN:
- * @dev: virPCIDevice object (used only to log name of config file)
- * @cfgfd: open file descriptor for device config file in sysfs
- * @pos: byte offset in the file to read from
- *
- * read "N" (where "N" is "8", "16", or "32", and appears at the end
- * of the function name) bytes from a PCI device's already-opened
- * sysfs config file and return them as the return value from the
- * function.
- *
- * Returns the value at @pos in the file, or 0 if there was an
- * error. NB: since 0 could be a valid value, occurrence of an error
- * must be determined by examining errno. errno is always reset to 0
- * before the seek/read is attempted (see virPCIDeviceRead()), so if
- * errno != 0 on return from one of these functions, then either the
- * seek or the read operation failed for some reason. If errno == 0
- * and the return value is 0, then the config file really does contain
- * the value 0 at @pos.
- */
-static uint8_t
-virPCIDeviceRead8(virPCIDevice *dev, int cfgfd, unsigned int pos)
-{
-    uint8_t buf;
-    virPCIDeviceRead(dev, cfgfd, pos, &buf, sizeof(buf));
-    return buf;
-}
-
-static uint16_t
-virPCIDeviceRead16(virPCIDevice *dev, int cfgfd, unsigned int pos)
-{
-    uint8_t buf[2];
-    virPCIDeviceRead(dev, cfgfd, pos, &buf[0], sizeof(buf));
-    return (buf[0] << 0) | (buf[1] << 8);
-}
-
-static uint32_t
-virPCIDeviceRead32(virPCIDevice *dev, int cfgfd, unsigned int pos)
-{
-    uint8_t buf[4];
-    virPCIDeviceRead(dev, cfgfd, pos, &buf[0], sizeof(buf));
-    return (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
-}
-
 static int
 virPCIDeviceReadClass(virPCIDevice *dev, uint16_t *device_class)
 {
@@ -499,36 +386,6 @@ virPCIDeviceReadClass(virPCIDevice *dev, uint16_t *device_class)
     return 0;
 }
 
-static int
-virPCIDeviceWrite(virPCIDevice *dev,
-                  int cfgfd,
-                  unsigned int pos,
-                  uint8_t *buf,
-                  unsigned int buflen)
-{
-    if (lseek(cfgfd, pos, SEEK_SET) != pos ||
-        safewrite(cfgfd, buf, buflen) != buflen) {
-        VIR_WARN("Failed to write to '%s' : %s", dev->path,
-                 g_strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
-static void
-virPCIDeviceWrite16(virPCIDevice *dev, int cfgfd, unsigned int pos, uint16_t val)
-{
-    uint8_t buf[2] = { (val >> 0), (val >> 8) };
-    virPCIDeviceWrite(dev, cfgfd, pos, &buf[0], sizeof(buf));
-}
-
-static void
-virPCIDeviceWrite32(virPCIDevice *dev, int cfgfd, unsigned int pos, uint32_t val)
-{
-    uint8_t buf[4] = { (val >> 0), (val >> 8), (val >> 16), (val >> 24) };
-    virPCIDeviceWrite(dev, cfgfd, pos, &buf[0], sizeof(buf));
-}
-
 typedef int (*virPCIDeviceIterPredicate)(virPCIDevice *, virPCIDevice *,
                                          void *);
 
@@ -610,7 +467,6 @@ virPCIDeviceIterDevices(virPCIDeviceIterPredicate predicate,
  */
 static int
 virPCIDeviceFindCapabilityOffset(virPCIDevice *dev,
-                                 int cfgfd,
                                  unsigned int capability,
                                  unsigned int *offset)
 {
@@ -619,11 +475,13 @@ virPCIDeviceFindCapabilityOffset(virPCIDevice *dev,
 
     *offset = 0; /* assume failure (*nothing* can be at offset 0) */
 
-    status = virPCIDeviceRead16(dev, cfgfd, PCI_STATUS);
+    pci_device_cfg_read_u16(dev->device, &status, PCI_STATUS);
+
     if (errno != 0 || !(status & PCI_STATUS_CAP_LIST))
         goto error;
 
-    pos = virPCIDeviceRead8(dev, cfgfd, PCI_CAPABILITY_LIST);
+    pci_device_cfg_read_u8(dev->device, &pos, PCI_CAPABILITY_LIST);
+
     if (errno != 0)
         goto error;
 
@@ -635,7 +493,9 @@ virPCIDeviceFindCapabilityOffset(virPCIDevice *dev,
      * capabilities here.
      */
     while (pos >= PCI_CONF_HEADER_LEN && pos != 0xff) {
-        uint8_t capid = virPCIDeviceRead8(dev, cfgfd, pos);
+        uint8_t capid;
+        pci_device_cfg_read_u8(dev->device, &capid, pos);
+
         if (errno != 0)
             goto error;
 
@@ -646,7 +506,8 @@ virPCIDeviceFindCapabilityOffset(virPCIDevice *dev,
             return 0;
         }
 
-        pos = virPCIDeviceRead8(dev, cfgfd, pos + 1);
+        pci_device_cfg_read_u8(dev->device, &pos, pos + 1);
+
         if (errno != 0)
             goto error;
     }
@@ -665,7 +526,6 @@ virPCIDeviceFindCapabilityOffset(virPCIDevice *dev,
 
 static unsigned int
 virPCIDeviceFindExtendedCapabilityOffset(virPCIDevice *dev,
-                                         int cfgfd,
                                          unsigned int capability)
 {
     int ttl;
@@ -677,7 +537,7 @@ virPCIDeviceFindExtendedCapabilityOffset(virPCIDevice *dev,
     pos = PCI_EXT_CAP_BASE;
 
     while (ttl > 0 && pos >= PCI_EXT_CAP_BASE) {
-        header = virPCIDeviceRead32(dev, cfgfd, pos);
+        header = pci_device_cfg_read_u32(dev->device, &header, pos);
 
         if ((header & PCI_EXT_CAP_ID_MASK) == capability)
             return pos;
@@ -693,7 +553,7 @@ virPCIDeviceFindExtendedCapabilityOffset(virPCIDevice *dev,
  * not have FLR, 1 if it does, and -1 on error
  */
 static bool
-virPCIDeviceDetectFunctionLevelReset(virPCIDevice *dev, int cfgfd)
+virPCIDeviceDetectFunctionLevelReset(virPCIDevice *dev)
 {
     uint32_t caps;
     unsigned int pos;
@@ -707,7 +567,7 @@ virPCIDeviceDetectFunctionLevelReset(virPCIDevice *dev, int cfgfd)
      * on SR-IOV NICs at the moment.
      */
     if (dev->pcie_cap_pos) {
-        caps = virPCIDeviceRead32(dev, cfgfd, dev->pcie_cap_pos + PCI_EXP_DEVCAP);
+        pci_device_cfg_read_u32(dev->device, &caps, dev->pcie_cap_pos + PCI_EXP_DEVCAP);
         if (caps & PCI_EXP_DEVCAP_FLR) {
             VIR_DEBUG("%s %s: detected PCIe FLR capability", dev->id, dev->name);
             return true;
@@ -718,11 +578,13 @@ virPCIDeviceDetectFunctionLevelReset(virPCIDevice *dev, int cfgfd)
      * the same thing, except for conventional PCI
      * devices. This is not common yet.
      */
-    if (virPCIDeviceFindCapabilityOffset(dev, cfgfd, PCI_CAP_ID_AF, &pos) < 0)
+    if (virPCIDeviceFindCapabilityOffset(dev, PCI_CAP_ID_AF, &pos) < 0)
         goto error;
 
     if (pos) {
-        caps = virPCIDeviceRead16(dev, cfgfd, pos + PCI_AF_CAP);
+        uint16_t caps16;
+        pci_device_cfg_read_u16(dev->device, &caps16, pos + PCI_AF_CAP);
+        caps = caps16;
         if (caps & PCI_AF_CAP_FLR) {
             VIR_DEBUG("%s %s: detected PCI FLR capability", dev->id, dev->name);
             return true;
@@ -754,13 +616,13 @@ virPCIDeviceDetectFunctionLevelReset(virPCIDevice *dev, int cfgfd)
  * internal reset, not just a soft reset.
  */
 static bool
-virPCIDeviceDetectPowerManagementReset(virPCIDevice *dev, int cfgfd)
+virPCIDeviceDetectPowerManagementReset(virPCIDevice *dev)
 {
     if (dev->pci_pm_cap_pos) {
         uint32_t ctl;
 
         /* require the NO_SOFT_RESET bit is clear */
-        ctl = virPCIDeviceRead32(dev, cfgfd, dev->pci_pm_cap_pos + PCI_PM_CTRL);
+        pci_device_cfg_read_u32(dev->device, &ctl, dev->pci_pm_cap_pos + PCI_PM_CTRL);
         if (!(ctl & PCI_PM_CTRL_NO_SOFT_RESET)) {
             VIR_DEBUG("%s %s: detected PM reset capability", dev->id, dev->name);
             return true;
@@ -811,26 +673,22 @@ virPCIDeviceIsParent(virPCIDevice *dev, virPCIDevice *check, void *data)
     uint8_t header_type, secondary, subordinate;
     virPCIDevice **best = data;
     int ret = 0;
-    int fd;
 
     if (dev->address.domain != check->address.domain)
         return 0;
 
-    if ((fd = virPCIDeviceConfigOpenTry(check)) < 0)
-        return 0;
-
     /* Is it a bridge? */
     ret = virPCIDeviceReadClass(check, &device_class);
     if (ret < 0 || device_class != PCI_CLASS_BRIDGE_PCI)
-        goto cleanup;
+        return ret;
 
     /* Is it a plane? */
-    header_type = virPCIDeviceRead8(check, fd, PCI_HEADER_TYPE);
+    pci_device_cfg_read_u8(check->device, &header_type, PCI_HEADER_TYPE);
     if ((header_type & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_BRIDGE)
-        goto cleanup;
+        return ret;
 
-    secondary   = virPCIDeviceRead8(check, fd, PCI_SECONDARY_BUS);
-    subordinate = virPCIDeviceRead8(check, fd, PCI_SUBORDINATE_BUS);
+    pci_device_cfg_read_u8(check->device, &secondary, PCI_SECONDARY_BUS);
+    pci_device_cfg_read_u8(check->device, &subordinate, PCI_SUBORDINATE_BUS);
 
     VIR_DEBUG("%s %s: found parent device %s", dev->id, dev->name, check->name);
 
@@ -838,8 +696,7 @@ virPCIDeviceIsParent(virPCIDevice *dev, virPCIDevice *check, void *data)
      * the direct parent.  No further work is necessary
      */
     if (dev->address.bus == secondary) {
-        ret = 1;
-        goto cleanup;
+        return 1;
     }
 
     /* otherwise, SRIOV allows VFs to be on different buses than their PFs.
@@ -850,35 +707,26 @@ virPCIDeviceIsParent(virPCIDevice *dev, virPCIDevice *check, void *data)
         if (*best == NULL) {
             *best = virPCIDeviceNew(&check->address);
             if (*best == NULL) {
-                ret = -1;
-                goto cleanup;
+                return -1;
             }
         } else {
             /* OK, we had already recorded a previous "best" match for the
              * parent.  See if the current device is more restrictive than the
              * best, and if so, make it the new best
              */
-            int bestfd;
             uint8_t best_secondary;
 
-            if ((bestfd = virPCIDeviceConfigOpenTry(*best)) < 0)
-                goto cleanup;
-            best_secondary = virPCIDeviceRead8(*best, bestfd, PCI_SECONDARY_BUS);
-            virPCIDeviceConfigClose(*best, bestfd);
+            pci_device_cfg_read_u8((*best)->device, &best_secondary, PCI_SECONDARY_BUS);
 
             if (secondary > best_secondary) {
                 virPCIDeviceFree(*best);
                 *best = virPCIDeviceNew(&check->address);
                 if (*best == NULL) {
-                    ret = -1;
-                    goto cleanup;
+                    return -1;
                 }
             }
         }
     }
-
- cleanup:
-    virPCIDeviceConfigClose(check, fd);
     return ret;
 }
 
@@ -902,15 +750,14 @@ virPCIDeviceGetParent(virPCIDevice *dev, virPCIDevice **parent)
  */
 static int
 virPCIDeviceTrySecondaryBusReset(virPCIDevice *dev,
-                                 int cfgfd,
                                  virPCIDeviceList *inactiveDevs)
 {
     g_autoptr(virPCIDevice) parent = NULL;
     g_autoptr(virPCIDevice) conflict = NULL;
     uint8_t config_space[PCI_CONF_LEN];
     uint16_t ctl;
-    int ret = -1;
-    int parentfd;
+    pciaddr_t bytes_read;
+    pciaddr_t bytes_written;
 
     /* Refuse to do a secondary bus reset if there are other
      * devices/functions behind the bus are used by the host
@@ -932,8 +779,6 @@ virPCIDeviceTrySecondaryBusReset(virPCIDevice *dev,
                        dev->name);
         return -1;
     }
-    if ((parentfd = virPCIDeviceConfigOpenWrite(parent)) < 0)
-        goto out;
 
     VIR_DEBUG("%s %s: doing a secondary bus reset", dev->id, dev->name);
 
@@ -941,38 +786,37 @@ virPCIDeviceTrySecondaryBusReset(virPCIDevice *dev,
      * for the supplied device since we refuse to do a reset if there
      * are multiple devices/functions
      */
-    if (virPCIDeviceRead(dev, cfgfd, 0, config_space, PCI_CONF_LEN) < 0) {
+    pci_device_cfg_read(dev->device, config_space, 0, PCI_CONF_LEN, &bytes_read);
+    if (bytes_read < PCI_CONF_LEN) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Failed to read PCI config space for %1$s"),
                        dev->name);
-        goto out;
+        return -1;
     }
 
     /* Read the control register, set the reset flag, wait 200ms,
      * unset the reset flag and wait 200ms.
      */
-    ctl = virPCIDeviceRead16(dev, parentfd, PCI_BRIDGE_CONTROL);
 
-    virPCIDeviceWrite16(parent, parentfd, PCI_BRIDGE_CONTROL,
-                        ctl | PCI_BRIDGE_CTL_RESET);
+    pci_device_cfg_read_u16(parent->device, &ctl, PCI_BRIDGE_CONTROL);
+
+    pci_device_cfg_write_u16(parent->device, ctl | PCI_BRIDGE_CTL_RESET, PCI_BRIDGE_CONTROL);
 
     g_usleep(200 * 1000); /* sleep 200ms */
 
-    virPCIDeviceWrite16(parent, parentfd, PCI_BRIDGE_CONTROL, ctl);
+    pci_device_cfg_write_u16(parent->device, ctl, PCI_BRIDGE_CONTROL);
 
     g_usleep(200 * 1000); /* sleep 200ms */
 
-    if (virPCIDeviceWrite(dev, cfgfd, 0, config_space, PCI_CONF_LEN) < 0) {
+    pci_device_cfg_write(dev->device, config_space, 0, PCI_CONF_LEN, &bytes_written);
+    if (bytes_written < PCI_CONF_LEN) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Failed to restore PCI config space for %1$s"),
                        dev->name);
-        goto out;
+        return -1;
     }
-    ret = 0;
 
- out:
-    virPCIDeviceConfigClose(parent, parentfd);
-    return ret;
+    return 0;
 }
 
 /* Power management reset attempts to reset a device using a
@@ -980,16 +824,19 @@ virPCIDeviceTrySecondaryBusReset(virPCIDevice *dev,
  * above we require the device supports a full internal reset.
  */
 static int
-virPCIDeviceTryPowerManagementReset(virPCIDevice *dev, int cfgfd)
+virPCIDeviceTryPowerManagementReset(virPCIDevice *dev)
 {
     uint8_t config_space[PCI_CONF_LEN];
     uint32_t ctl;
+    pciaddr_t bytes_read;
+    pciaddr_t bytes_written;
 
     if (!dev->pci_pm_cap_pos)
         return -1;
 
     /* Save and restore the device's config space. */
-    if (virPCIDeviceRead(dev, cfgfd, 0, &config_space[0], PCI_CONF_LEN) < 0) {
+    pci_device_cfg_read(dev->device, config_space, 0, PCI_CONF_LEN, &bytes_read);
+    if (bytes_read < PCI_CONF_LEN) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Failed to read PCI config space for %1$s"),
                        dev->name);
@@ -998,20 +845,19 @@ virPCIDeviceTryPowerManagementReset(virPCIDevice *dev, int cfgfd)
 
     VIR_DEBUG("%s %s: doing a power management reset", dev->id, dev->name);
 
-    ctl = virPCIDeviceRead32(dev, cfgfd, dev->pci_pm_cap_pos + PCI_PM_CTRL);
+    pci_device_cfg_read_u32(dev->device, &ctl, dev->pci_pm_cap_pos + PCI_PM_CTRL);
     ctl &= ~PCI_PM_CTRL_STATE_MASK;
 
-    virPCIDeviceWrite32(dev, cfgfd, dev->pci_pm_cap_pos + PCI_PM_CTRL,
-                        ctl | PCI_PM_CTRL_STATE_D3hot);
+    pci_device_cfg_write_u32(dev->device, ctl | PCI_PM_CTRL_STATE_D3hot, dev->pci_pm_cap_pos + PCI_PM_CTRL);
 
     g_usleep(10 * 1000); /* sleep 10ms */
 
-    virPCIDeviceWrite32(dev, cfgfd, dev->pci_pm_cap_pos + PCI_PM_CTRL,
-                        ctl | PCI_PM_CTRL_STATE_D0);
+    pci_device_cfg_write_u32(dev->device, ctl | PCI_PM_CTRL_STATE_D0, dev->pci_pm_cap_pos + PCI_PM_CTRL);
 
     g_usleep(10 * 1000); /* sleep 10ms */
 
-    if (virPCIDeviceWrite(dev, cfgfd, 0, &config_space[0], PCI_CONF_LEN) < 0) {
+    pci_device_cfg_write(dev->device, config_space, 0, PCI_CONF_LEN, &bytes_written);
+    if (bytes_written < PCI_CONF_LEN) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Failed to restore PCI config space for %1$s"),
                        dev->name);
@@ -1046,10 +892,10 @@ virPCIDeviceTryPowerManagementReset(virPCIDevice *dev, int cfgfd)
  * Always returns success (0) (for now)
  */
 static int
-virPCIDeviceInit(virPCIDevice *dev, int cfgfd)
+virPCIDeviceInit(virPCIDevice *dev)
 {
     dev->is_pcie = false;
-    if (virPCIDeviceFindCapabilityOffset(dev, cfgfd, PCI_CAP_ID_EXP, &dev->pcie_cap_pos) < 0) {
+    if (virPCIDeviceFindCapabilityOffset(dev, PCI_CAP_ID_EXP, &dev->pcie_cap_pos) < 0) {
         /* an unprivileged process is unable to read *all* of a
          * device's PCI config (it can only read the first 64
          * bytes, which isn't enough for see the Express
@@ -1065,18 +911,13 @@ virPCIDeviceInit(virPCIDevice *dev, int cfgfd)
          * -1), then we blindly assume the most likely outcome -
          * PCIe.
          */
-        off_t configLen = virFileLength(virPCIDeviceGetConfigPath(dev), -1);
-
-        if (configLen != 256)
-            dev->is_pcie = true;
-
     } else {
         dev->is_pcie = (dev->pcie_cap_pos != 0);
     }
 
-    virPCIDeviceFindCapabilityOffset(dev, cfgfd, PCI_CAP_ID_PM, &dev->pci_pm_cap_pos);
-    dev->has_flr = virPCIDeviceDetectFunctionLevelReset(dev, cfgfd);
-    dev->has_pm_reset = virPCIDeviceDetectPowerManagementReset(dev, cfgfd);
+    virPCIDeviceFindCapabilityOffset(dev, PCI_CAP_ID_PM, &dev->pci_pm_cap_pos);
+    dev->has_flr = virPCIDeviceDetectFunctionLevelReset(dev);
+    dev->has_pm_reset = virPCIDeviceDetectPowerManagementReset(dev);
 
     return 0;
 }
@@ -1089,7 +930,6 @@ virPCIDeviceReset(virPCIDevice *dev,
     g_autofree char *drvName = NULL;
     virPCIStubDriver drvType;
     int ret = -1;
-    int fd = -1;
     int hdrType = -1;
 
     if (virPCIGetHeaderType(dev, &hdrType) < 0)
@@ -1114,29 +954,26 @@ virPCIDeviceReset(virPCIDevice *dev,
      * be redundant.
      */
     if (virPCIDeviceGetCurrentDriverNameAndType(dev, &drvName, &drvType) < 0)
-        goto cleanup;
+        return -1;
 
     if (drvType == VIR_PCI_STUB_DRIVER_VFIO) {
 
         VIR_DEBUG("Device %s is bound to %s - skip reset", dev->name, drvName);
         ret = 0;
-        goto cleanup;
+        return 0;
     }
 
     VIR_DEBUG("Resetting device %s", dev->name);
 
-    if ((fd = virPCIDeviceConfigOpenWrite(dev)) < 0)
-        goto cleanup;
-
-    if (virPCIDeviceInit(dev, fd) < 0)
-        goto cleanup;
+    if (virPCIDeviceInit(dev) < 0)
+        return -1;
 
     /* KVM will perform FLR when starting and stopping
      * a guest, so there is no need for us to do it here.
      */
     if (dev->has_flr) {
         ret = 0;
-        goto cleanup;
+        return 0;
     }
 
     /* If the device supports PCI power management reset,
@@ -1144,11 +981,11 @@ virPCIDeviceReset(virPCIDevice *dev,
      * the function, not the whole device.
      */
     if (dev->has_pm_reset)
-        ret = virPCIDeviceTryPowerManagementReset(dev, fd);
+        ret = virPCIDeviceTryPowerManagementReset(dev);
 
     /* Bus reset is not an option with the root bus */
     if (ret < 0 && dev->address.bus != 0)
-        ret = virPCIDeviceTrySecondaryBusReset(dev, fd, inactiveDevs);
+        ret = virPCIDeviceTrySecondaryBusReset(dev, inactiveDevs);
 
     if (ret < 0) {
         virErrorPtr err = virGetLastError();
@@ -1159,8 +996,6 @@ virPCIDeviceReset(virPCIDevice *dev,
                        _("no FLR, PM reset or bus reset available"));
     }
 
- cleanup:
-    virPCIDeviceConfigClose(dev, fd);
     return ret;
 }
 
@@ -1756,28 +1591,6 @@ virPCIDeviceReattach(virPCIDevice *dev,
     return 0;
 }
 
-static char *
-virPCIDeviceReadID(virPCIDevice *dev, const char *id_name)
-{
-    g_autofree char *path = NULL;
-    g_autofree char *id_str = NULL;
-
-    path = virPCIFile(dev->name, id_name);
-
-    /* ID string is '0xNNNN\n' ... i.e. 7 bytes */
-    if (virFileReadAll(path, 7, &id_str) < 0)
-        return NULL;
-
-    /* Check for 0x suffix */
-    if (id_str[0] != '0' || id_str[1] != 'x')
-        return NULL;
-
-    /* Chop off the newline; we know the string is 7 bytes */
-    id_str[6] = '\0';
-
-    return g_steal_pointer(&id_str);
-}
-
 bool
 virPCIDeviceAddressIsValid(virPCIDeviceAddress *addr,
                            bool report)
@@ -1865,9 +1678,9 @@ virPCIDeviceExists(const virPCIDeviceAddress *addr)
 virPCIDevice *
 virPCIDeviceNew(const virPCIDeviceAddress *address)
 {
+    struct pci_device * device;
+
     g_autoptr(virPCIDevice) dev = NULL;
-    g_autofree char *vendor = NULL;
-    g_autofree char *product = NULL;
 
     dev = g_new0(virPCIDevice, 1);
 
@@ -1875,31 +1688,21 @@ virPCIDeviceNew(const virPCIDeviceAddress *address)
 
     dev->name = virPCIDeviceAddressAsString(&dev->address);
 
-    dev->path = g_strdup_printf(PCI_SYSFS "devices/%s/config", dev->name);
-
-    if (!virFileExists(dev->path)) {
-        virReportSystemError(errno,
-                             _("Device %1$s not found: could not access %2$s"),
-                             dev->name, dev->path);
+    pci_system_init();
+    device = pci_device_find_by_slot(address->domain, address->bus, address->slot, address->function);
+    if (!device)
         return NULL;
-    }
-
-    vendor  = virPCIDeviceReadID(dev, "vendor");
-    product = virPCIDeviceReadID(dev, "device");
-
-    if (!vendor || !product) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Failed to read product/vendor ID for %1$s"),
-                       dev->name);
+    dev->device = g_memdup(device, sizeof(*dev->device));
+    if (!dev->device) {
+        virReportSystemError(errno,
+                             _("Not found device domain: %1$d, bus: %2$d, slot: %3$d, function: %4$d"),
+                             address->domain, address->bus, address->slot, address->function);
         return NULL;
     }
-
-    /* strings contain '0x' prefix */
-    if (g_snprintf(dev->id, sizeof(dev->id), "%s %s", &vendor[2],
-                   &product[2]) >= sizeof(dev->id)) {
+    if (g_snprintf(dev->id, sizeof(dev->id), "%x %x", dev->device->vendor_id, dev->device->device_id) >= sizeof(dev->id)) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("dev->id buffer overflow: %1$s %2$s"),
-                       &vendor[2], &product[2]);
+                       _("dev->id buffer overflow: %1$d %2$d"),
+                       dev->device->vendor_id, dev->device->device_id);
         return NULL;
     }
 
@@ -1918,10 +1721,10 @@ virPCIDeviceCopy(virPCIDevice *dev)
 
     /* shallow copy to take care of most attributes */
     *copy = *dev;
-    copy->path = NULL;
-    copy->used_by_drvname = copy->used_by_domname = NULL;
+    copy->device = NULL;
+    copy->device = g_memdup(dev->device, sizeof(*dev->device));
+    copy->name = copy->used_by_drvname = copy->used_by_domname = copy->stubDriverName = NULL;
     copy->name = g_strdup(dev->name);
-    copy->path = g_strdup(dev->path);
     copy->used_by_drvname = g_strdup(dev->used_by_drvname);
     copy->used_by_domname = g_strdup(dev->used_by_domname);
     copy->stubDriverName = g_strdup(dev->stubDriverName);
@@ -1936,10 +1739,11 @@ virPCIDeviceFree(virPCIDevice *dev)
         return;
     VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
     g_free(dev->name);
-    g_free(dev->path);
     g_free(dev->used_by_drvname);
     g_free(dev->used_by_domname);
     g_free(dev->stubDriverName);
+    if (dev->device)
+        g_free(dev->device);
     g_free(dev);
 }
 
@@ -1971,9 +1775,9 @@ virPCIDeviceGetName(virPCIDevice *dev)
  * config file.
  */
 const char *
-virPCIDeviceGetConfigPath(virPCIDevice *dev)
+virPCIDeviceGetConfigPath(virPCIDevice *dev G_GNUC_UNUSED)
 {
-    return dev->path;
+    return NULL;
 }
 
 void virPCIDeviceSetManaged(virPCIDevice *dev, bool managed)
@@ -2484,47 +2288,37 @@ virPCIDeviceDownstreamLacksACS(virPCIDevice *dev)
     uint16_t flags;
     uint16_t ctrl;
     unsigned int pos;
-    int fd;
-    int ret = 0;
     uint16_t device_class;
 
-    if ((fd = virPCIDeviceConfigOpen(dev)) < 0)
+    if (virPCIDeviceInit(dev) < 0) {
         return -1;
-
-    if (virPCIDeviceInit(dev, fd) < 0) {
-        ret = -1;
-        goto cleanup;
     }
 
     if (virPCIDeviceReadClass(dev, &device_class) < 0)
-        goto cleanup;
+        return 0;
 
     pos = dev->pcie_cap_pos;
     if (!pos || device_class != PCI_CLASS_BRIDGE_PCI)
-        goto cleanup;
+        return 0;
 
-    flags = virPCIDeviceRead16(dev, fd, pos + PCI_EXP_FLAGS);
+    pci_device_cfg_read_u16(dev->device, &flags, pos + PCI_EXP_FLAGS);
     if (((flags & PCI_EXP_FLAGS_TYPE) >> 4) != PCI_EXP_TYPE_DOWNSTREAM)
-        goto cleanup;
+        return 0;
 
-    pos = virPCIDeviceFindExtendedCapabilityOffset(dev, fd, PCI_EXT_CAP_ID_ACS);
+    pos = virPCIDeviceFindExtendedCapabilityOffset(dev, PCI_EXT_CAP_ID_ACS);
     if (!pos) {
         VIR_DEBUG("%s %s: downstream port lacks ACS", dev->id, dev->name);
-        ret = 1;
-        goto cleanup;
+        return 1;
     }
 
-    ctrl = virPCIDeviceRead16(dev, fd, pos + PCI_EXT_ACS_CTRL);
+    pci_device_cfg_read_u16(dev->device, &ctrl, pos + PCI_EXT_ACS_CTRL);
     if ((ctrl & PCI_EXT_CAP_ACS_ENABLED) != PCI_EXT_CAP_ACS_ENABLED) {
         VIR_DEBUG("%s %s: downstream port has ACS disabled",
                   dev->id, dev->name);
-        ret = 1;
-        goto cleanup;
+        return 1;
     }
 
- cleanup:
-    virPCIDeviceConfigClose(dev, fd);
-    return ret;
+    return 0;
 }
 
 static int
@@ -3189,48 +2983,27 @@ virPCIDeviceGetVPD(virPCIDevice *dev G_GNUC_UNUSED)
 int
 virPCIDeviceIsPCIExpress(virPCIDevice *dev)
 {
-    int fd;
-    int ret = -1;
-
-    if ((fd = virPCIDeviceConfigOpen(dev)) < 0)
-        return ret;
-
-    if (virPCIDeviceInit(dev, fd) < 0)
-        goto cleanup;
-
-    ret = dev->is_pcie;
+    if (virPCIDeviceInit(dev) < 0)
+        return -1;
 
- cleanup:
-    virPCIDeviceConfigClose(dev, fd);
-    return ret;
+    return dev->is_pcie;
 }
 
 int
 virPCIDeviceHasPCIExpressLink(virPCIDevice *dev)
 {
-    int fd;
-    int ret = -1;
     uint16_t cap, type;
-
-    if ((fd = virPCIDeviceConfigOpen(dev)) < 0)
-        return ret;
-
-    if (virPCIDeviceInit(dev, fd) < 0)
-        goto cleanup;
+    if (virPCIDeviceInit(dev) < 0)
+        return -1;
 
     if (dev->pcie_cap_pos == 0) {
-        ret = 0;
-        goto cleanup;
+        return 0;
     }
 
-    cap = virPCIDeviceRead16(dev, fd, dev->pcie_cap_pos + PCI_CAP_FLAGS);
+    pci_device_cfg_read_u16(dev->device, &cap, dev->pcie_cap_pos + PCI_CAP_FLAGS);
     type = (cap & PCI_EXP_FLAGS_TYPE) >> 4;
 
-    ret = type != PCI_EXP_TYPE_ROOT_INT_EP && type != PCI_EXP_TYPE_ROOT_EC;
-
- cleanup:
-    virPCIDeviceConfigClose(dev, fd);
-    return ret;
+    return type != PCI_EXP_TYPE_ROOT_INT_EP && type != PCI_EXP_TYPE_ROOT_EC;
 }
 
 int
@@ -3242,53 +3015,39 @@ virPCIDeviceGetLinkCapSta(virPCIDevice *dev,
                           unsigned int *sta_width)
 {
     uint32_t t;
-    int fd;
-    int ret = -1;
-
-    if ((fd = virPCIDeviceConfigOpen(dev)) < 0)
-        return ret;
-
-    if (virPCIDeviceInit(dev, fd) < 0)
-        goto cleanup;
+    uint16_t t16;
+    if (virPCIDeviceInit(dev) < 0)
+        return -1;
 
     if (!dev->pcie_cap_pos) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("pci device %1$s is not a PCI-Express device"),
                        dev->name);
-        goto cleanup;
+        return -1;
     }
 
-    t = virPCIDeviceRead32(dev, fd, dev->pcie_cap_pos + PCI_EXP_LNKCAP);
+    pci_device_cfg_read_u32(dev->device, &t, dev->pcie_cap_pos + PCI_EXP_LNKCAP);
 
     *cap_port = t >> 24;
     *cap_speed = t & PCI_EXP_LNKCAP_SPEED;
     *cap_width = (t & PCI_EXP_LNKCAP_WIDTH) >> 4;
 
-    t = virPCIDeviceRead16(dev, fd, dev->pcie_cap_pos + PCI_EXP_LNKSTA);
+    pci_device_cfg_read_u16(dev->device, &t16, dev->pcie_cap_pos + PCI_EXP_LNKSTA);
+    t = t16;
 
     *sta_speed = t & PCI_EXP_LNKSTA_SPEED;
     *sta_width = (t & PCI_EXP_LNKSTA_WIDTH) >> 4;
-    ret = 0;
-
- cleanup:
-    virPCIDeviceConfigClose(dev, fd);
-    return ret;
+    return 0;
 }
 
 
 int virPCIGetHeaderType(virPCIDevice *dev, int *hdrType)
 {
-    int fd;
     uint8_t type;
 
     *hdrType = -1;
 
-    if ((fd = virPCIDeviceConfigOpen(dev)) < 0)
-        return -1;
-
-    type = virPCIDeviceRead8(dev, fd, PCI_HEADER_TYPE);
-
-    virPCIDeviceConfigClose(dev, fd);
+    pci_device_cfg_read_u8(dev->device, &type, PCI_HEADER_TYPE);
 
     type &= PCI_HEADER_TYPE_MASK;
     if (type >= VIR_PCI_HEADER_LAST) {
diff --git a/tests/virpcimock.c b/tests/virpcimock.c
index 5b923c63ce..36bb57edb0 100644
--- a/tests/virpcimock.c
+++ b/tests/virpcimock.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (C) 2024-2025 Future Crew, LLC
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,7 +23,7 @@
 
 #include "virpcivpdpriv.h"
 
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
+#if defined(__linux__) || defined(__APPLE__)
 # define VIR_MOCK_LOOKUP_MAIN
 # include "virmock.h"
 # include "virpci.h"
@@ -42,6 +43,10 @@ static int (*real___open_2)(const char *path, int flags);
 static int (*real_close)(int fd);
 static DIR * (*real_opendir)(const char *name);
 static char *(*real_virFileCanonicalizePath)(const char *path);
+static int (*real_scandir)(const char *restrict dirp,
+            struct dirent ***restrict namelist,
+            typeof(int(const struct dirent *)) *filter,
+            typeof(int(const struct dirent **, const struct dirent **)) *compar);
 
 static char *fakerootdir;
 
@@ -955,6 +960,7 @@ init_syms(void)
     VIR_MOCK_REAL_INIT(opendir);
 # endif
     VIR_MOCK_REAL_INIT(virFileCanonicalizePath);
+    VIR_MOCK_REAL_INIT(scandir);
 }
 
 static void
@@ -1172,6 +1178,20 @@ virFileCanonicalizePath(const char *path)
     return real_virFileCanonicalizePath(newpath);
 }
 
+int scandir(const char *restrict dirp, struct dirent ***restrict namelist,
+            typeof(int(const struct dirent *)) *filter,
+            typeof(int(const struct dirent **, const struct dirent **)) *compar)
+{
+    g_autofree char *newpath = NULL;
+
+    init_syms();
+
+    if (getrealpath(&newpath, dirp) < 0)
+        return -1;
+
+    return real_scandir(newpath, namelist, filter, compar);
+}
+
 # include "virmockstathelpers.c"
 
 #else
-- 
2.46.1
                    
                  
                  
                          
                            
                            2
                            
                          
                          
                            
                            9
                            
                          
                          
                            
    
                          
                        
                     
                        
                    
                        
                            
                                
                            
                            [libvirt PATCH] tools: virsh: metadata: do not report error on missing metadata
                        
                        
by Ján Tomko 02 Apr '25
                    by Ján Tomko 02 Apr '25
02 Apr '25
                    
                        Similarly to `desc` and `net-desc`, return an empty string if
there is no metadata to be returned.
https://issues.redhat.com/browse/RHEL-27172
Signed-off-by: Ján Tomko <jtomko(a)redhat.com>
---
 tools/virsh-domain.c  | 10 ++++++++--
 tools/virsh-network.c | 10 ++++++++--
 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index f3da2f903f..e104aa909a 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -8480,8 +8480,14 @@ cmdMetadata(vshControl *ctl, const vshCmd *cmd)
         g_autofree char *data = NULL;
         /* get */
         if (!(data = virDomainGetMetadata(dom, VIR_DOMAIN_METADATA_ELEMENT,
-                                          uri, flags)))
-            return false;
+                                          uri, flags))) {
+            if (virGetLastErrorCode() == VIR_ERR_NO_DOMAIN_METADATA) {
+                virResetLastError();
+                data = g_strdup("");
+            } else {
+                return false;
+            }
+        }
 
         vshPrint(ctl, "%s\n", data);
     }
diff --git a/tools/virsh-network.c b/tools/virsh-network.c
index 6fcc7fd8ee..bcdb76ae36 100644
--- a/tools/virsh-network.c
+++ b/tools/virsh-network.c
@@ -604,8 +604,14 @@ cmdNetworkMetadata(vshControl *ctl, const vshCmd *cmd)
 
         /* get */
         if (!(data = virNetworkGetMetadata(net, VIR_NETWORK_METADATA_ELEMENT,
-                                           uri, flags)))
-            return false;
+                                           uri, flags))) {
+            if (virGetLastErrorCode() == VIR_ERR_NO_NETWORK_METADATA) {
+                virResetLastError();
+                data = g_strdup("");
+            } else {
+                return false;
+            }
+        }
 
         vshPrint(ctl, "%s\n", data);
     }
-- 
2.48.1
                    
                  
                  
                          
                            
                            4
                            
                          
                          
                            
                            4
                            
                          
                          
                            
    
                          
                        
                    
                    
                        Hi,
This series brings libvirt the x86 TDX support.
* What's TDX?
TDX stands for Trust Domain Extensions which isolates VMs from
the virtual-machine manager (VMM)/hypervisor and any other software on
the platform.
To support TDX, multiple software components, not only KVM but also QEMU,
guest Linux and virtual bios, need to be updated. For more details, please
check link[1].
This patchset is another software component to extend libvirt to support TDX,
with which one can start a TDX guest from high level rather than running qemu
directly.
* Misc
As QEMU use a software emulated way to reset guest which isn't supported by TDX
guest for security reason. We simulate reboot for TDX guest by kill and create a
new one in FakeReboot framework.
Complete code can be found at [2], matching qemu code can be found at [3].
There is a 'debug' property for tdx-guest object which isn't in matching qemu[3]
yet. I keep them intentionally as they will be implemented in qemu as extention
series of [3].
* Test
start/stop/reboot with virsh
stop/reboot trigger in guest
stop with on_poweroff=destroy/restart
reboot with on_reboot=destroy/restart
* Patch organization
- patch 1-4:   Support query of TDX capabilities.
- patch 5-8:   Add TDX type to launchsecurity framework.
- patch 9-11:  Add reboot support to TDX guest
- patch 12-13: Add test and docs
TODO:
- update QEMU capabilities data in tests, depending on qemu TDX merged beforehand
- add reconnect logic in virsh command
[1] https://lore.kernel.org/kvm/cover.1708933498.git.isaku.yamahata@intel.com
[2] https://github.com/intel/libvirt-tdx/commits/tdx_for_upstream_rfcv4
[3] https://github.com/intel/qemu-tdx/tree/tdx-qemu-upstream-v5
Thanks
Zhenzhong
Changelog:
rfcv4:
- add a check to tools/virt-host-validate-qemu.c (Daniel)
- remove check of q35 (Daniel)
- model 'SocktetAddress' QAPI in xml schema (Daniel)
- s/Quote-Generation-Service/quoteGenerationService/ (Daniel)
- define bits in tdx->policy and add validating logic (Daniel)
- presume QEMU choose split kernel irqchip for TDX guest by default (Daniel)
- utilize existing FakeReboot framework to do reboot for TDX guest (Daniel)
- drop patch11 'conf: Add support to keep same domid for hard reboot' (Daniel)
- add test in tests/ to validate parsing and formatting logic (Daniel)
- add doc in docs/formatdomain.rst (Daniel)
- add R-B
rfcv3:
- Change to generate qemu cmdline with -bios
- drop firmware auto match as -bios is used
- add a hard reboot method to reboot TDX guest
rfcv3: https://www.mail-archive.com/devel@lists.libvirt.org/msg00385.html
rfcv2:
- give up using qmp cmd and check TDX directly on host for TDX capabilities.
- use launchsecurity framework to support TDX
- use <os>.<loader> for general loader
- add auto firmware match feature for TDX
A example TDVF fimware description file 70-edk2-x86_64-tdx.json:
{
    "description": "UEFI firmware for x86_64, supporting Intel TDX",
    "interface-types": [
        "uefi"
    ],
    "mapping": {
        "device": "generic",
        "filename": "/usr/share/OVMF/OVMF_CODE-tdx.fd"
    },
    "targets": [
        {
            "architecture": "x86_64",
            "machines": [
                "pc-q35-*"
            ]
        }
    ],
    "features": [
        "intel-tdx",
        "verbose-dynamic"
    ],
    "tags": [
    ]
}
rfcv2: https://www.mail-archive.com/libvir-list@redhat.com/msg219378.html
Zhenzhong Duan (13):
  tools: Secure guest check for Intel in virt-host-validate
  qemu: Check if INTEL Trust Domain Extention support is enabled
  qemu: Add TDX capability
  conf: expose TDX feature in domain capabilities
  conf: add tdx as launch security type
  qemu: Add command line and validation for TDX type
  qemu: force special parameters enabled for TDX guest
  Add Intel TDX Quote Generation Service(QGS) support
  qemu: add FakeReboot support for TDX guest
  qemu: Support reboot command in guest
  qemu: Avoid duplicate FakeReboot for secure guest
  Add test cases for Intel TDX
  docs: domain: Add documentation for Intel TDX guest
 docs/formatdomain.rst                         |  68 ++++
 docs/formatdomaincaps.rst                     |   1 +
 src/conf/domain_capabilities.c                |   1 +
 src/conf/domain_capabilities.h                |   1 +
 src/conf/domain_conf.c                        | 312 ++++++++++++++++++
 src/conf/domain_conf.h                        |  75 +++++
 src/conf/schemas/domaincaps.rng               |   9 +
 src/conf/schemas/domaincommon.rng             | 135 ++++++++
 src/conf/virconftypes.h                       |   2 +
 src/qemu/qemu_capabilities.c                  |  36 +-
 src/qemu/qemu_capabilities.h                  |   1 +
 src/qemu/qemu_command.c                       | 139 ++++++++
 src/qemu/qemu_firmware.c                      |   1 +
 src/qemu/qemu_monitor.c                       |  28 +-
 src/qemu/qemu_monitor.h                       |   2 +-
 src/qemu/qemu_monitor_json.c                  |   6 +-
 src/qemu/qemu_namespace.c                     |   1 +
 src/qemu/qemu_process.c                       |  75 +++++
 src/qemu/qemu_validate.c                      |  44 +++
 ...unch-security-tdx-qgs-fd.x86_64-latest.xml |  77 +++++
 .../launch-security-tdx-qgs-fd.xml            |  30 ++
 ...ch-security-tdx-qgs-inet.x86_64-latest.xml |  77 +++++
 .../launch-security-tdx-qgs-inet.xml          |  30 ++
 ...ch-security-tdx-qgs-unix.x86_64-latest.xml |  77 +++++
 .../launch-security-tdx-qgs-unix.xml          |  30 ++
 ...h-security-tdx-qgs-vsock.x86_64-latest.xml |  77 +++++
 .../launch-security-tdx-qgs-vsock.xml         |  30 ++
 tests/qemuxmlconftest.c                       |  24 ++
 tools/virt-host-validate-common.c             |  22 +-
 tools/virt-host-validate-common.h             |   1 +
 30 files changed, 1407 insertions(+), 5 deletions(-)
 create mode 100644 tests/qemuxmlconfdata/launch-security-tdx-qgs-fd.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/launch-security-tdx-qgs-fd.xml
 create mode 100644 tests/qemuxmlconfdata/launch-security-tdx-qgs-inet.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/launch-security-tdx-qgs-inet.xml
 create mode 100644 tests/qemuxmlconfdata/launch-security-tdx-qgs-unix.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/launch-security-tdx-qgs-unix.xml
 create mode 100644 tests/qemuxmlconfdata/launch-security-tdx-qgs-vsock.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/launch-security-tdx-qgs-vsock.xml
-- 
2.34.1
                    
                  
                  
                          
                            
                            6
                            
                          
                          
                            
                            45
                            
                          
                          
                            
    
                          
                        
                    
                    
                        We attempted multiple ways to clean up dynamic files; however, we must
preserve user overrides, which requires keeping the file
/etc/apparmor.d/libvirt/libvirt-uuid
This commit proposes to move user overrides into
/etc/apparmor.d/libvirt/libvirt-uuid.local and include it, if present,
unconditionally. When we stop the domain, we remove libvirt.uuid and
libvirt-uuid.files, whereas we preserve libvirt-uuid.local if present.
Applying the patch, it produces the following:
root@virt-hv-lab002:/etc/apparmor.d/libvirt# ls -1 libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033*
libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033
libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033.files
root@virt-hv-lab002:/etc/apparmor.d/libvirt# cat libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033
profile libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033 flags=(attach_disconnected) {
  #include <abstractions/libvirt-qemu>
  #include if exists <libvirt/libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033.files>
  #include if exists <libvirt/libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033.local>
}
root@virt-hv-lab002:/etc/apparmor.d/libvirt# cat libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033.files
  "/var/log/libvirt/**/testing-9a4be628.log" w,
  "/var/lib/libvirt/qemu/domain-testing-9a4be628/monitor.sock" rw,
  "/var/lib/libvirt/qemu/domain-4-testing-9a4be628/*" rw,
  "/var/run/libvirt/**/testing-9a4be628.pid" rwk,
  "/var/run/libvirt/**/*.tunnelmigrate.dest.testing-9a4be628" rw,
  "/var/lib/libvirt/images/testing-9a4be628.qcow2" rwk,
  "/var/lib/libvirt/images/noble-server-cloudimg-amd64.img" rk,
  # don't audit writes to readonly files
  deny "/var/lib/libvirt/images/noble-server-cloudimg-amd64.img" w,
  "/var/lib/libvirt/images/testing-9a4be628-ds.qcow2" rwk,
  "/usr/share/OVMF/OVMF_CODE_4M.fd" rk,
  # don't audit writes to readonly files
  deny "/usr/share/OVMF/OVMF_CODE_4M.fd" w,
  "/var/lib/libvirt/qemu/nvram/testing-9a4be628_VARS.fd" rwk,
  "/dev/vhost-net" rw,
  "/var/lib/libvirt/qemu/domain-4-testing-9a4be628/{,**}" rwk,
  "/run/libvirt/qemu/channel/4-testing-9a4be628/{,**}" rwk,
  "/var/lib/libvirt/qemu/domain-4-testing-9a4be628/master-key.aes" rwk,
  "/dev/net/tun" rwk,
  "/dev/userfaultfd" rwk,
Fixes: https://gitlab.com/libvirt/libvirt/-/issues/451
Signed-off-by: Alessandro <alessandro(a)0x65c.net>
---
 src/security/virt-aa-helper.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 034c042..6a1fb85 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -1495,8 +1495,10 @@ main(int argc, char **argv)
         rc = parserLoad(ctl->uuid);
     } else if (ctl->cmd == 'R' || ctl->cmd == 'D') {
         rc = parserRemove(ctl->uuid);
-        if (ctl->cmd == 'D')
+        if (ctl->cmd == 'D') {
             unlink(include_file);
+            unlink(profile);
+        }
     } else if (ctl->cmd == 'c' || ctl->cmd == 'r') {
         g_autofree char *included_files = NULL;
         g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
@@ -1561,12 +1563,18 @@ main(int argc, char **argv)
         /* create the profile from TEMPLATE */
         if (ctl->cmd == 'c' || purged) {
             g_autofree char *tmp = NULL;
+            g_autofree char *tmp_local = NULL;
+            char *new_tmp = NULL;
 #if defined(WITH_APPARMOR_3)
             const char *ifexists = "if exists ";
 #else
             const char *ifexists = "";
 #endif
             tmp = g_strdup_printf("  #include %s<libvirt/%s.files>\n", ifexists, ctl->uuid);
+            tmp_local = g_strdup_printf("  #include %s<libvirt/%s.local>\n", ifexists, ctl->uuid);
+            new_tmp = g_strconcat(tmp, tmp_local, NULL);
+            g_free(tmp);
+            tmp = g_steal_pointer(&new_tmp);
 
             if (ctl->dryrun) {
                 vah_info(profile);
-- 
2.49.0
                    
                  
                  
                          
                            
                            3
                            
                          
                          
                            
                            9
                            
                          
                          
                            
    
                          
                        
                     
                        
                    01 Apr '25
                    
                        See 6/8 for justification.
Peter Krempa (8):
  virDomainStorageNetworkParseHost: Remove unpopulated 'transport'
    variable
  virDomainStorageNetworkParseHost: Refactor cleanup
  conf: Introduce VIR_STORAGE_NET_HOST_TRANS_FD
  virStorageNetHostDefClear: Move into virStorageNetHostDefFree
  qemu: monitor: Support FD passing of sockets to
    'qemuMonitorJSONNBDServerStart'
  backup: Add support for passing server socket file descriptor to
    backup NBD server
  tests: domainbackupxml2xml: Add test case for pull-mode backup with
    NBD transport='fd'
  qemu: monitor: Improve field annotations in QEMU_CHECK_MONITOR
 docs/formatbackup.rst                         | 21 +++++
 src/conf/backup_conf.c                        |  3 +-
 src/conf/domain_conf.c                        | 93 ++++++++++++-------
 src/conf/domain_conf.h                        |  3 +-
 src/conf/schemas/domainbackup.rng             |  6 ++
 src/conf/storage_source_conf.c                | 20 ++--
 src/conf/storage_source_conf.h                |  7 +-
 src/libvirt_private.syms                      |  1 -
 src/qemu/qemu_backup.c                        | 28 ++++++
 src/qemu/qemu_block.c                         |  1 +
 src/qemu/qemu_monitor.c                       |  2 +-
 src/qemu/qemu_monitor_json.c                  | 21 +++++
 .../storage_file_backend_gluster.c            |  1 +
 .../domainbackupxml2xmlin/backup-pull-fd.xml  | 22 +++++
 .../domainbackupxml2xmlout/backup-pull-fd.xml | 23 +++++
 tests/genericxml2xmltest.c                    |  1 +
 16 files changed, 198 insertions(+), 55 deletions(-)
 create mode 100644 tests/domainbackupxml2xmlin/backup-pull-fd.xml
 create mode 100644 tests/domainbackupxml2xmlout/backup-pull-fd.xml
-- 
2.49.0
                    
                  
                  
                          
                            
                            2
                            
                          
                          
                            
                            12
                            
                          
                          
                            
    
                          
                        
                     
                        
                    
                        
                            
                                
                            
                            Re: [PATCH RESEND 0/6] Add support for configuring PCI high memory
 MMIO size
                        
                        
by Matt Ochs 31 Mar '25
                    by Matt Ochs 31 Mar '25
31 Mar '25
                    
                        Gentle ping. Is there any feedback, comment, or suggestion about this series?
-matt
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        We attempted multiple ways to clean up dynamic files; however, we must
preserve user overrides, which requires keeping the file
/etc/apparmor.d/libvirt/libvirt-uuid
This commit proposes to move user overrides into
/etc/apparmor.d/libvirt/libvirt-uuid.local and include it, if present,
unconditionally. When we stop the domain, we remove libvirt.uuid and
libvirt-uuid.files, whereas we preserve libvirt-uuid.local if present.
Applying the patch, it produces the following:
root@virt-hv-lab002:/etc/apparmor.d/libvirt# ls -1 libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033*
libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033
libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033.files
root@virt-hv-lab002:/etc/apparmor.d/libvirt# cat libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033
profile libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033 flags=(attach_disconnected) {
  #include <abstractions/libvirt-qemu>
  #include if exists <libvirt/libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033.files>
  #include if exists <libvirt/libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033.local>
}
root@virt-hv-lab002:/etc/apparmor.d/libvirt# cat libvirt-e7424556-ffc1-4f6e-bafa-84e66c4dc033.files
  "/var/log/libvirt/**/testing-9a4be628.log" w,
  "/var/lib/libvirt/qemu/domain-testing-9a4be628/monitor.sock" rw,
  "/var/lib/libvirt/qemu/domain-4-testing-9a4be628/*" rw,
  "/var/run/libvirt/**/testing-9a4be628.pid" rwk,
  "/var/run/libvirt/**/*.tunnelmigrate.dest.testing-9a4be628" rw,
  "/var/lib/libvirt/images/testing-9a4be628.qcow2" rwk,
  "/var/lib/libvirt/images/noble-server-cloudimg-amd64.img" rk,
  # don't audit writes to readonly files
  deny "/var/lib/libvirt/images/noble-server-cloudimg-amd64.img" w,
  "/var/lib/libvirt/images/testing-9a4be628-ds.qcow2" rwk,
  "/usr/share/OVMF/OVMF_CODE_4M.fd" rk,
  # don't audit writes to readonly files
  deny "/usr/share/OVMF/OVMF_CODE_4M.fd" w,
  "/var/lib/libvirt/qemu/nvram/testing-9a4be628_VARS.fd" rwk,
  "/dev/vhost-net" rw,
  "/var/lib/libvirt/qemu/domain-4-testing-9a4be628/{,**}" rwk,
  "/run/libvirt/qemu/channel/4-testing-9a4be628/{,**}" rwk,
  "/var/lib/libvirt/qemu/domain-4-testing-9a4be628/master-key.aes" rwk,
  "/dev/net/tun" rwk,
  "/dev/userfaultfd" rwk,
Fixes: https://gitlab.com/libvirt/libvirt/-/issues/451
Signed-off-by: Alessandro <alessandro(a)0x65c.net>
---
 src/security/virt-aa-helper.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 034c042..8f044a1 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -1495,8 +1495,10 @@ main(int argc, char **argv)
         rc = parserLoad(ctl->uuid);
     } else if (ctl->cmd == 'R' || ctl->cmd == 'D') {
         rc = parserRemove(ctl->uuid);
-        if (ctl->cmd == 'D')
+        if (ctl->cmd == 'D'){
             unlink(include_file);
+            unlink(profile);
+        }
     } else if (ctl->cmd == 'c' || ctl->cmd == 'r') {
         g_autofree char *included_files = NULL;
         g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
@@ -1561,12 +1563,15 @@ main(int argc, char **argv)
         /* create the profile from TEMPLATE */
         if (ctl->cmd == 'c' || purged) {
             g_autofree char *tmp = NULL;
+            g_autofree char *tmp_local = NULL:
 #if defined(WITH_APPARMOR_3)
             const char *ifexists = "if exists ";
 #else
             const char *ifexists = "";
 #endif
             tmp = g_strdup_printf("  #include %s<libvirt/%s.files>\n", ifexists, ctl->uuid);
+            tmp_local = g_strdup_printf("  #include %s<libvirt/%s.local>\n", ifexists, ctl->uuid);
+            tmp = g_strconcat(tmp,tmp_local, NULL);
 
             if (ctl->dryrun) {
                 vah_info(profile);
-- 
2.49.0
                    
                  
                  
                          
                            
                            2
                            
                          
                          
                            
                            2
                            
                          
                          
                            
    
                          
                        
                     
                        
                     
                        
                     
                        
                    