[PATCH 0/3] ch: Misc fixes
by Michal Privoznik
*** BLURB HERE ***
Michal Prívozník (3):
ch: Use CH_DOMAIN_PRIVATE() more
ch: Drop pid from monitor
ch: Fix printf format strings wrt size_t argument
src/ch/ch_events.c | 4 ++--
src/ch/ch_monitor.c | 14 ++++----------
src/ch/ch_monitor.h | 2 --
src/ch/ch_process.c | 11 +++++------
4 files changed, 11 insertions(+), 20 deletions(-)
--
2.49.0
2 months, 1 week
[PATCH] libxl_conf: Implement hyperv domain flags for Xen
by Will
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 months, 1 week
[PATCH 0/3] ch: monitor daemonization, sync after reboot, and shutdown fixes
by Kirill Shchetiniuk
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
2 months, 1 week
[PATCH 1/5] virpci: Switch to an implementation using libpciaccess
by Alexander Shursha
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 months, 1 week
[libvirt PATCH] tools: virsh: metadata: do not report error on missing metadata
by Ján Tomko
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
2 months, 1 week
[PATCH 0/4] Allow xml-configured coredump format on VM crash
by Nikolai Barybin
When libvirt processes VM crash event it always dumps core in raw
format.
This series makes it possible to configure dump format via domain xml.
This would be especcialy helpful for Windows guests, because it requires
a lot effort to convert raw dump into wingdb.
Nikolai Barybin (4):
conf: schemas: add coredump_format element to events section
src: conf: add parsing/formatting for 'coredump_format' value
qemu: use configurable dump format in doCoreDumpToAutoDumpPath()
docs: formatdomain: document 'coredump_format' element
docs/formatdomain.rst | 9 +++++
src/conf/domain_conf.c | 64 +++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 2 +
src/conf/schemas/domaincommon.rng | 19 +++++++++
src/libvirt_private.syms | 2 +
src/qemu/qemu_driver.c | 2 +-
6 files changed, 97 insertions(+), 1 deletion(-)
--
2.43.5
2 months, 1 week
[PATCH 0/6] qemu: Remove last HMP commands
by Peter Krempa
RIP HMP use in libvirt:
2007-02-14 [1] - 2025-04-02
[1] 23ad665cb05ef9ce7d298cc34bff5efb95ef6948
Peter Krempa (6):
qemu: domain: Don't check return value of 'virCPUDefCopy'
qemuSnapshotCreateActiveInternal: Fix error logic
qemu: snapshot: Always assume support for
QEMU_CAPS_SNAPSHOT_INTERNAL_QMP
qemu: Always revert internal snapshots via QMP rather than '-loadvm'
qemu: monitor: Remove HMP monitor code
qemu: capabilities: Retire QEMU_CAPS_SNAPSHOT_INTERNAL_QMP
po/POTFILES | 1 -
src/qemu/meson.build | 1 -
src/qemu/qemu_capabilities.c | 3 +-
src/qemu/qemu_capabilities.h | 2 +-
src/qemu/qemu_command.c | 6 --
src/qemu/qemu_domain.c | 7 +-
src/qemu/qemu_monitor.c | 25 ------
src/qemu/qemu_monitor.h | 3 -
src/qemu/qemu_monitor_text.c | 88 -------------------
src/qemu/qemu_monitor_text.h | 29 ------
src/qemu/qemu_process.c | 3 +-
src/qemu/qemu_snapshot.c | 49 ++---------
.../caps_10.0.0_s390x.xml | 1 -
.../caps_10.0.0_x86_64+amdsev.xml | 1 -
.../caps_10.0.0_x86_64.xml | 1 -
.../qemucapabilitiesdata/caps_6.2.0_ppc64.xml | 1 -
.../caps_6.2.0_x86_64.xml | 1 -
.../qemucapabilitiesdata/caps_7.0.0_ppc64.xml | 1 -
.../caps_7.0.0_x86_64.xml | 1 -
.../qemucapabilitiesdata/caps_7.1.0_ppc64.xml | 1 -
.../caps_7.1.0_x86_64.xml | 1 -
tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml | 1 -
.../caps_7.2.0_x86_64+hvf.xml | 1 -
.../caps_7.2.0_x86_64.xml | 1 -
.../caps_8.0.0_x86_64.xml | 1 -
.../qemucapabilitiesdata/caps_8.1.0_s390x.xml | 1 -
.../caps_8.1.0_x86_64.xml | 1 -
.../caps_8.2.0_aarch64.xml | 1 -
.../caps_8.2.0_armv7l.xml | 1 -
.../caps_8.2.0_loongarch64.xml | 1 -
.../qemucapabilitiesdata/caps_8.2.0_s390x.xml | 1 -
.../caps_8.2.0_x86_64.xml | 1 -
.../qemucapabilitiesdata/caps_9.0.0_sparc.xml | 1 -
.../caps_9.0.0_x86_64.xml | 1 -
.../caps_9.1.0_riscv64.xml | 1 -
.../qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 -
.../caps_9.1.0_x86_64.xml | 1 -
.../caps_9.2.0_aarch64+hvf.xml | 1 -
.../qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 -
.../caps_9.2.0_x86_64+amdsev.xml | 1 -
.../caps_9.2.0_x86_64.xml | 1 -
41 files changed, 15 insertions(+), 231 deletions(-)
delete mode 100644 src/qemu/qemu_monitor_text.c
delete mode 100644 src/qemu/qemu_monitor_text.h
--
2.49.0
2 months, 1 week
[PATCH] meson: Add back prefix path for runstatedir
by Zhenzhong Duan
Currently libvirt favors /run instead of /var/run, but for local build
run test, a prefix path is still needed to avoid interoperating with OS
vendor provided binaries.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan(a)intel.com>
---
meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meson.build b/meson.build
index bf4a245dd3..84c9796c2f 100644
--- a/meson.build
+++ b/meson.build
@@ -82,7 +82,7 @@ endif
runstatedir = get_option('runstatedir')
if runstatedir == ''
- runstatedir = '/run'
+ runstatedir = prefix / 'run'
endif
initconfdir = get_option('initconfdir')
--
2.34.1
2 months, 1 week
Report a build issue
by Duan, Zhenzhong
Hi,
When -Dlibnl=disabled, build failed as below:
../src/util/virnetdevbridge.c: In function 'virNetDevBridgeSetupVlans':
../src/util/virnetdevbridge.c:326:9: error: implicit declaration of function 'virNetlinkBridgeVlanFilterSet'; did you mean 'virNetDevBridgeGetVlanFiltering'? [-Werror=implicit-function-declaration]
326 | if (virNetlinkBridgeVlanFilterSet(ifname, RTM_DELLINK, 0, 1, &error) < 0) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| virNetDevBridgeGetVlanFiltering
../src/util/virnetdevbridge.c:326:9: error: nested extern declaration of 'virNetlinkBridgeVlanFilterSet' [-Werror=nested-externs]
../src/util/virnetdevbridge.c:326:47: error: 'RTM_DELLINK' undeclared (first use in this function)
326 | if (virNetlinkBridgeVlanFilterSet(ifname, RTM_DELLINK, 0, 1, &error) < 0) {
| ^~~~~~~~~~~
../src/util/virnetdevbridge.c:326:47: note: each undeclared identifier is reported only once for each function it appears in
../src/util/virnetdevbridge.c:346:55: error: 'RTM_SETLINK' undeclared (first use in this function)
346 | if (virNetlinkBridgeVlanFilterSet(ifname, RTM_SETLINK, flags,
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
Thanks
Zhenzhong
2 months, 1 week
[PATCH rfcv4 00/13] LIBVIRT: X86: TDX support
by Zhenzhong Duan
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
2 months, 1 week