VFIO updates 2022-05-06

* Defer IRQ routing commits to improve setup and resume latency (Longpeng)
 
  * Fix trace sparse mmap boundary condition (Xiang Chen)
 
  * Quiet misalignment warning from TPM device mapping (Eric Auger)
 
  * Misc cleanups (Yi Liu, Eric Auger)
 -----BEGIN PGP SIGNATURE-----
 
 iQJPBAABCAA5FiEEQvbATlQL0amee4qQI5ubbjuwiyIFAmJ1hm8bHGFsZXgud2ls
 bGlhbXNvbkByZWRoYXQuY29tAAoJECObm247sIsi8cIP+wfOMh9YLAm6NC70Gd9q
 7Z6Z3ql/5SYUF8AmsLZf3UPa1+bVQ4TcsjqN5tiaCx36iDXF39jkHM/w9Cd4sPuB
 7ETmWndj6FwOI9PNpFmVoUrpONyLI3VuCNZqwhV1mlmTEnmCsE1PAvjjjPz51HDd
 +dnkIJsjoKqpzja9zotQnpWtx7O4iKGGAUx3oi4BbF47sG2az2GQnI/5L/Zj8dBO
 G3h+FCavSO6ODmIxX865ndZifN3BV1asazNDjFp7beUNFVrNCpzZkIkFGzhtx8yS
 npxw/27m2s/O+dJZIlWPMCH0H0ItIHpqntBziMopxCG3ELsnhJjAccg5aWi2okXM
 M0rmNu+BH9WKPJoqy8u89gZvebyhvtTuMQ1gDzZWkEe80LLfoB9Re/qvMuw2LBnv
 BSu8hUHCoX3Whnc7PoP11Y97uBW/uaH/LTagrqzIJIBWSniUCZaZUep6Ihg1wFFQ
 oTNKKiaer/jtzmCTFtGKC7dj/gGuKNvAO8l/yqWj3k7ssstllaOLOzjDmoD5bmZD
 jVaaAedOhFme5sGtgqcmFmNXA+r01PoKmopkHku74meCk+RCxV4i8xkVZGlREHpS
 YB7CsA8B8jcLQS9QfguFWreImhstaC0fOKRDXDGMGm9ikPThdtIE5oWt2c4fKz5Y
 Hi6FjfEsDoZNLs64lc4cyMEq
 =ShHn
 -----END PGP SIGNATURE-----

Merge tag 'vfio-updates-20220506.1' of https://gitlab.com/alex.williamson/qemu into staging

VFIO updates 2022-05-06

 * Defer IRQ routing commits to improve setup and resume latency (Longpeng)

 * Fix trace sparse mmap boundary condition (Xiang Chen)

 * Quiet misalignment warning from TPM device mapping (Eric Auger)

 * Misc cleanups (Yi Liu, Eric Auger)

# -----BEGIN PGP SIGNATURE-----
#
# iQJPBAABCAA5FiEEQvbATlQL0amee4qQI5ubbjuwiyIFAmJ1hm8bHGFsZXgud2ls
# bGlhbXNvbkByZWRoYXQuY29tAAoJECObm247sIsi8cIP+wfOMh9YLAm6NC70Gd9q
# 7Z6Z3ql/5SYUF8AmsLZf3UPa1+bVQ4TcsjqN5tiaCx36iDXF39jkHM/w9Cd4sPuB
# 7ETmWndj6FwOI9PNpFmVoUrpONyLI3VuCNZqwhV1mlmTEnmCsE1PAvjjjPz51HDd
# +dnkIJsjoKqpzja9zotQnpWtx7O4iKGGAUx3oi4BbF47sG2az2GQnI/5L/Zj8dBO
# G3h+FCavSO6ODmIxX865ndZifN3BV1asazNDjFp7beUNFVrNCpzZkIkFGzhtx8yS
# npxw/27m2s/O+dJZIlWPMCH0H0ItIHpqntBziMopxCG3ELsnhJjAccg5aWi2okXM
# M0rmNu+BH9WKPJoqy8u89gZvebyhvtTuMQ1gDzZWkEe80LLfoB9Re/qvMuw2LBnv
# BSu8hUHCoX3Whnc7PoP11Y97uBW/uaH/LTagrqzIJIBWSniUCZaZUep6Ihg1wFFQ
# oTNKKiaer/jtzmCTFtGKC7dj/gGuKNvAO8l/yqWj3k7ssstllaOLOzjDmoD5bmZD
# jVaaAedOhFme5sGtgqcmFmNXA+r01PoKmopkHku74meCk+RCxV4i8xkVZGlREHpS
# YB7CsA8B8jcLQS9QfguFWreImhstaC0fOKRDXDGMGm9ikPThdtIE5oWt2c4fKz5Y
# Hi6FjfEsDoZNLs64lc4cyMEq
# =ShHn
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 06 May 2022 03:34:55 PM CDT
# gpg:                using RSA key 42F6C04E540BD1A99E7B8A90239B9B6E3BB08B22
# gpg:                issuer "alex.williamson@redhat.com"
# gpg: Good signature from "Alex Williamson <alex.williamson@redhat.com>" [undefined]
# gpg:                 aka "Alex Williamson <alex@shazbot.org>" [undefined]
# gpg:                 aka "Alex Williamson <alwillia@redhat.com>" [undefined]
# gpg:                 aka "Alex Williamson <alex.l.williamson@gmail.com>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 42F6 C04E 540B D1A9 9E7B  8A90 239B 9B6E 3BB0 8B22

* tag 'vfio-updates-20220506.1' of https://gitlab.com/alex.williamson/qemu:
  vfio/common: Rename VFIOGuestIOMMU::iommu into ::iommu_mr
  vfio/pci: Use vbasedev local variable in vfio_realize()
  hw/vfio/pci: fix vfio_pci_hot_reset_result trace point
  vfio/common: remove spurious tpm-crb-cmd misalignment warning
  sysemu: tpm: Add a stub function for TPM_IS_CRB
  vfio/common: Fix a small boundary issue of a trace
  vfio: defer to commit kvm irq routing when enable msi/msix
  Revert "vfio: Avoid disabling and enabling vectors repeatedly in VFIO migration"
  vfio: simplify the failure path in vfio_msi_enable
  vfio: move re-enabling INTX out of the common helper
  vfio: simplify the conditional statements in vfio_msi_enable

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-05-06 16:18:14 -05:00
commit 13220a46e2
6 changed files with 186 additions and 109 deletions

View File

@ -40,6 +40,7 @@
#include "trace.h"
#include "qapi/error.h"
#include "migration/migration.h"
#include "sysemu/tpm.h"
VFIOGroupList vfio_group_list =
QLIST_HEAD_INITIALIZER(vfio_group_list);
@ -861,6 +862,22 @@ static void vfio_unregister_ram_discard_listener(VFIOContainer *container,
g_free(vrdl);
}
static bool vfio_known_safe_misalignment(MemoryRegionSection *section)
{
MemoryRegion *mr = section->mr;
if (!TPM_IS_CRB(mr->owner)) {
return false;
}
/* this is a known safe misaligned region, just trace for debug purpose */
trace_vfio_known_safe_misalignment(memory_region_name(mr),
section->offset_within_address_space,
section->offset_within_region,
qemu_real_host_page_size());
return true;
}
static void vfio_listener_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
@ -884,7 +901,15 @@ static void vfio_listener_region_add(MemoryListener *listener,
if (unlikely((section->offset_within_address_space &
~qemu_real_host_page_mask()) !=
(section->offset_within_region & ~qemu_real_host_page_mask()))) {
error_report("%s received unaligned region", __func__);
if (!vfio_known_safe_misalignment(section)) {
error_report("%s received unaligned region %s iova=0x%"PRIx64
" offset_within_region=0x%"PRIx64
" qemu_real_host_page_size=0x%"PRIxPTR,
__func__, memory_region_name(section->mr),
section->offset_within_address_space,
section->offset_within_region,
qemu_real_host_page_size());
}
return;
}
@ -992,7 +1017,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
* device emulation the VFIO iommu handles to use).
*/
giommu = g_malloc0(sizeof(*giommu));
giommu->iommu = iommu_mr;
giommu->iommu_mr = iommu_mr;
giommu->iommu_offset = section->offset_within_address_space -
section->offset_within_region;
giommu->container = container;
@ -1007,7 +1032,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
int128_get64(llend),
iommu_idx);
ret = memory_region_iommu_set_page_size_mask(giommu->iommu,
ret = memory_region_iommu_set_page_size_mask(giommu->iommu_mr,
container->pgsizes,
&err);
if (ret) {
@ -1022,7 +1047,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
goto fail;
}
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
memory_region_iommu_replay(giommu->iommu, &giommu->n);
memory_region_iommu_replay(giommu->iommu_mr, &giommu->n);
return;
}
@ -1128,7 +1153,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
VFIOGuestIOMMU *giommu;
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
if (MEMORY_REGION(giommu->iommu) == section->mr &&
if (MEMORY_REGION(giommu->iommu_mr) == section->mr &&
giommu->n.start == section->offset_within_region) {
memory_region_unregister_iommu_notifier(section->mr,
&giommu->n);
@ -1393,11 +1418,11 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container,
VFIOGuestIOMMU *giommu;
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
if (MEMORY_REGION(giommu->iommu) == section->mr &&
if (MEMORY_REGION(giommu->iommu_mr) == section->mr &&
giommu->n.start == section->offset_within_region) {
Int128 llend;
vfio_giommu_dirty_notifier gdn = { .giommu = giommu };
int idx = memory_region_iommu_attrs_to_index(giommu->iommu,
int idx = memory_region_iommu_attrs_to_index(giommu->iommu_mr,
MEMTXATTRS_UNSPECIFIED);
llend = int128_add(int128_make64(section->offset_within_region),
@ -1410,7 +1435,7 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container,
section->offset_within_region,
int128_get64(llend),
idx);
memory_region_iommu_replay(giommu->iommu, &gdn.n);
memory_region_iommu_replay(giommu->iommu_mr, &gdn.n);
break;
}
}
@ -1544,11 +1569,10 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
region->mmaps = g_new0(VFIOMmap, sparse->nr_areas);
for (i = 0, j = 0; i < sparse->nr_areas; i++) {
trace_vfio_region_sparse_mmap_entry(i, sparse->areas[i].offset,
sparse->areas[i].offset +
sparse->areas[i].size);
if (sparse->areas[i].size) {
trace_vfio_region_sparse_mmap_entry(i, sparse->areas[i].offset,
sparse->areas[i].offset +
sparse->areas[i].size - 1);
region->mmaps[j].offset = sparse->areas[i].offset;
region->mmaps[j].size = sparse->areas[i].size;
j++;
@ -2246,7 +2270,7 @@ static void vfio_disconnect_container(VFIOGroup *group)
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
memory_region_unregister_iommu_notifier(
MEMORY_REGION(giommu->iommu), &giommu->n);
MEMORY_REGION(giommu->iommu_mr), &giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
}

View File

@ -45,8 +45,12 @@
#define TYPE_VFIO_PCI_NOHOTPLUG "vfio-pci-nohotplug"
/* Protected by BQL */
static KVMRouteChange vfio_route_change;
static void vfio_disable_interrupts(VFIOPCIDevice *vdev);
static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
static void vfio_msi_disable_common(VFIOPCIDevice *vdev);
/*
* Disabling BAR mmaping can be slow, but toggling it around INTx can
@ -412,33 +416,36 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
static void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
int vector_n, bool msix)
{
KVMRouteChange c;
int virq;
if ((msix && vdev->no_kvm_msix) || (!msix && vdev->no_kvm_msi)) {
return;
}
if (event_notifier_init(&vector->kvm_interrupt, 0)) {
vector->virq = kvm_irqchip_add_msi_route(&vfio_route_change,
vector_n, &vdev->pdev);
}
static void vfio_connect_kvm_msi_virq(VFIOMSIVector *vector)
{
if (vector->virq < 0) {
return;
}
c = kvm_irqchip_begin_route_changes(kvm_state);
virq = kvm_irqchip_add_msi_route(&c, vector_n, &vdev->pdev);
if (virq < 0) {
event_notifier_cleanup(&vector->kvm_interrupt);
return;
if (event_notifier_init(&vector->kvm_interrupt, 0)) {
goto fail_notifier;
}
kvm_irqchip_commit_route_changes(&c);
if (kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &vector->kvm_interrupt,
NULL, virq) < 0) {
kvm_irqchip_release_virq(kvm_state, virq);
event_notifier_cleanup(&vector->kvm_interrupt);
return;
NULL, vector->virq) < 0) {
goto fail_kvm;
}
vector->virq = virq;
return;
fail_kvm:
event_notifier_cleanup(&vector->kvm_interrupt);
fail_notifier:
kvm_irqchip_release_virq(kvm_state, vector->virq);
vector->virq = -1;
}
static void vfio_remove_kvm_msi_virq(VFIOMSIVector *vector)
@ -493,7 +500,14 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
}
} else {
if (msg) {
vfio_add_kvm_msi_virq(vdev, vector, nr, true);
if (vdev->defer_kvm_irq_routing) {
vfio_add_kvm_msi_virq(vdev, vector, nr, true);
} else {
vfio_route_change = kvm_irqchip_begin_route_changes(kvm_state);
vfio_add_kvm_msi_virq(vdev, vector, nr, true);
kvm_irqchip_commit_route_changes(&vfio_route_change);
vfio_connect_kvm_msi_virq(vector);
}
}
}
@ -503,11 +517,13 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
* increase them as needed.
*/
if (vdev->nr_vectors < nr + 1) {
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
vdev->nr_vectors = nr + 1;
ret = vfio_enable_vectors(vdev, true);
if (ret) {
error_report("vfio: failed to enable vectors, %d", ret);
if (!vdev->defer_kvm_irq_routing) {
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
ret = vfio_enable_vectors(vdev, true);
if (ret) {
error_report("vfio: failed to enable vectors, %d", ret);
}
}
} else {
Error *err = NULL;
@ -569,11 +585,29 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
}
}
static void vfio_prepare_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
{
assert(!vdev->defer_kvm_irq_routing);
vdev->defer_kvm_irq_routing = true;
vfio_route_change = kvm_irqchip_begin_route_changes(kvm_state);
}
static void vfio_commit_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
{
int i;
assert(vdev->defer_kvm_irq_routing);
vdev->defer_kvm_irq_routing = false;
kvm_irqchip_commit_route_changes(&vfio_route_change);
for (i = 0; i < vdev->nr_vectors; i++) {
vfio_connect_kvm_msi_virq(&vdev->msi_vectors[i]);
}
}
static void vfio_msix_enable(VFIOPCIDevice *vdev)
{
PCIDevice *pdev = &vdev->pdev;
unsigned int nr, max_vec = 0;
vfio_disable_interrupts(vdev);
vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->msix->entries);
@ -581,37 +615,45 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev)
vdev->interrupt = VFIO_INT_MSIX;
/*
* Some communication channels between VF & PF or PF & fw rely on the
* physical state of the device and expect that enabling MSI-X from the
* guest enables the same on the host. When our guest is Linux, the
* guest driver call to pci_enable_msix() sets the enabling bit in the
* MSI-X capability, but leaves the vector table masked. We therefore
* can't rely on a vector_use callback (from request_irq() in the guest)
* to switch the physical device into MSI-X mode because that may come a
* long time after pci_enable_msix(). This code enables vector 0 with
* triggering to userspace, then immediately release the vector, leaving
* the physical device with no vectors enabled, but MSI-X enabled, just
* like the guest view.
* If there are already unmasked vectors (in migration resume phase and
* some guest startups) which will be enabled soon, we can allocate all
* of them here to avoid inefficiently disabling and enabling vectors
* repeatedly later.
* Setting vector notifiers triggers synchronous vector-use
* callbacks for each active vector. Deferring to commit the KVM
* routes once rather than per vector provides a substantial
* performance improvement.
*/
if (!pdev->msix_function_masked) {
for (nr = 0; nr < msix_nr_vectors_allocated(pdev); nr++) {
if (!msix_is_masked(pdev, nr)) {
max_vec = nr;
}
}
}
vfio_msix_vector_do_use(pdev, max_vec, NULL, NULL);
vfio_msix_vector_release(pdev, max_vec);
vfio_prepare_kvm_msi_virq_batch(vdev);
if (msix_set_vector_notifiers(pdev, vfio_msix_vector_use,
if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use,
vfio_msix_vector_release, NULL)) {
error_report("vfio: msix_set_vector_notifiers failed");
}
vfio_commit_kvm_msi_virq_batch(vdev);
if (vdev->nr_vectors) {
int ret;
ret = vfio_enable_vectors(vdev, true);
if (ret) {
error_report("vfio: failed to enable vectors, %d", ret);
}
} else {
/*
* Some communication channels between VF & PF or PF & fw rely on the
* physical state of the device and expect that enabling MSI-X from the
* guest enables the same on the host. When our guest is Linux, the
* guest driver call to pci_enable_msix() sets the enabling bit in the
* MSI-X capability, but leaves the vector table masked. We therefore
* can't rely on a vector_use callback (from request_irq() in the guest)
* to switch the physical device into MSI-X mode because that may come a
* long time after pci_enable_msix(). This code enables vector 0 with
* triggering to userspace, then immediately release the vector, leaving
* the physical device with no vectors enabled, but MSI-X enabled, just
* like the guest view.
*/
vfio_msix_vector_do_use(&vdev->pdev, 0, NULL, NULL);
vfio_msix_vector_release(&vdev->pdev, 0);
}
trace_vfio_msix_enable(vdev->vbasedev.name);
}
@ -621,6 +663,13 @@ static void vfio_msi_enable(VFIOPCIDevice *vdev)
vfio_disable_interrupts(vdev);
/*
* Setting vector notifiers needs to enable route for each vector.
* Deferring to commit the KVM routes once rather than per vector
* provides a substantial performance improvement.
*/
vfio_prepare_kvm_msi_virq_batch(vdev);
vdev->nr_vectors = msi_nr_vectors_allocated(&vdev->pdev);
retry:
vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->nr_vectors);
@ -646,6 +695,8 @@ retry:
vfio_add_kvm_msi_virq(vdev, vector, i, false);
}
vfio_commit_kvm_msi_virq_batch(vdev);
/* Set interrupt type prior to possible interrupts */
vdev->interrupt = VFIO_INT_MSI;
@ -653,29 +704,17 @@ retry:
if (ret) {
if (ret < 0) {
error_report("vfio: Error: Failed to setup MSI fds: %m");
} else if (ret != vdev->nr_vectors) {
} else {
error_report("vfio: Error: Failed to enable %d "
"MSI vectors, retry with %d", vdev->nr_vectors, ret);
}
for (i = 0; i < vdev->nr_vectors; i++) {
VFIOMSIVector *vector = &vdev->msi_vectors[i];
if (vector->virq >= 0) {
vfio_remove_kvm_msi_virq(vector);
}
qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt),
NULL, NULL, NULL);
event_notifier_cleanup(&vector->interrupt);
}
vfio_msi_disable_common(vdev);
g_free(vdev->msi_vectors);
vdev->msi_vectors = NULL;
if (ret > 0 && ret != vdev->nr_vectors) {
if (ret > 0) {
vdev->nr_vectors = ret;
goto retry;
}
vdev->nr_vectors = 0;
/*
* Failing to setup MSI doesn't really fall within any specification.
@ -683,7 +722,6 @@ retry:
* out to fall back to INTx for this device.
*/
error_report("vfio: Error: Failed to enable MSI");
vdev->interrupt = VFIO_INT_NONE;
return;
}
@ -693,7 +731,6 @@ retry:
static void vfio_msi_disable_common(VFIOPCIDevice *vdev)
{
Error *err = NULL;
int i;
for (i = 0; i < vdev->nr_vectors; i++) {
@ -712,15 +749,11 @@ static void vfio_msi_disable_common(VFIOPCIDevice *vdev)
vdev->msi_vectors = NULL;
vdev->nr_vectors = 0;
vdev->interrupt = VFIO_INT_NONE;
vfio_intx_enable(vdev, &err);
if (err) {
error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
}
}
static void vfio_msix_disable(VFIOPCIDevice *vdev)
{
Error *err = NULL;
int i;
msix_unset_vector_notifiers(&vdev->pdev);
@ -741,6 +774,10 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev)
}
vfio_msi_disable_common(vdev);
vfio_intx_enable(vdev, &err);
if (err) {
error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
}
memset(vdev->msix->pending, 0,
BITS_TO_LONGS(vdev->msix->entries) * sizeof(unsigned long));
@ -750,8 +787,14 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev)
static void vfio_msi_disable(VFIOPCIDevice *vdev)
{
Error *err = NULL;
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSI_IRQ_INDEX);
vfio_msi_disable_common(vdev);
vfio_intx_enable(vdev, &err);
if (err) {
error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
}
trace_vfio_msi_disable(vdev->vbasedev.name);
}
@ -2337,7 +2380,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
g_free(reset);
trace_vfio_pci_hot_reset_result(vdev->vbasedev.name,
ret ? "%m" : "Success");
ret ? strerror(errno) : "Success");
out:
/* Re-enable INTx on affected devices */
@ -2803,6 +2846,7 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev)
static void vfio_realize(PCIDevice *pdev, Error **errp)
{
VFIOPCIDevice *vdev = VFIO_PCI(pdev);
VFIODevice *vbasedev = &vdev->vbasedev;
VFIODevice *vbasedev_iter;
VFIOGroup *group;
char *tmp, *subsys, group_path[PATH_MAX], *group_name;
@ -2813,7 +2857,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
int i, ret;
bool is_mdev;
if (!vdev->vbasedev.sysfsdev) {
if (!vbasedev->sysfsdev) {
if (!(~vdev->host.domain || ~vdev->host.bus ||
~vdev->host.slot || ~vdev->host.function)) {
error_setg(errp, "No provided host device");
@ -2821,24 +2865,24 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
"or -device vfio-pci,sysfsdev=PATH_TO_DEVICE\n");
return;
}
vdev->vbasedev.sysfsdev =
vbasedev->sysfsdev =
g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%01x",
vdev->host.domain, vdev->host.bus,
vdev->host.slot, vdev->host.function);
}
if (stat(vdev->vbasedev.sysfsdev, &st) < 0) {
if (stat(vbasedev->sysfsdev, &st) < 0) {
error_setg_errno(errp, errno, "no such host device");
error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.sysfsdev);
error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->sysfsdev);
return;
}
vdev->vbasedev.name = g_path_get_basename(vdev->vbasedev.sysfsdev);
vdev->vbasedev.ops = &vfio_pci_ops;
vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI;
vdev->vbasedev.dev = DEVICE(vdev);
vbasedev->name = g_path_get_basename(vbasedev->sysfsdev);
vbasedev->ops = &vfio_pci_ops;
vbasedev->type = VFIO_DEVICE_TYPE_PCI;
vbasedev->dev = DEVICE(vdev);
tmp = g_strdup_printf("%s/iommu_group", vdev->vbasedev.sysfsdev);
tmp = g_strdup_printf("%s/iommu_group", vbasedev->sysfsdev);
len = readlink(tmp, group_path, sizeof(group_path));
g_free(tmp);
@ -2856,7 +2900,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
goto error;
}
trace_vfio_realize(vdev->vbasedev.name, groupid);
trace_vfio_realize(vbasedev->name, groupid);
group = vfio_get_group(groupid, pci_device_iommu_address_space(pdev), errp);
if (!group) {
@ -2864,7 +2908,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
}
QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
if (strcmp(vbasedev_iter->name, vdev->vbasedev.name) == 0) {
if (strcmp(vbasedev_iter->name, vbasedev->name) == 0) {
error_setg(errp, "device is already attached");
vfio_put_group(group);
goto error;
@ -2877,22 +2921,22 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
* stays in sync with the active working set of the guest driver. Prevent
* the x-balloon-allowed option unless this is minimally an mdev device.
*/
tmp = g_strdup_printf("%s/subsystem", vdev->vbasedev.sysfsdev);
tmp = g_strdup_printf("%s/subsystem", vbasedev->sysfsdev);
subsys = realpath(tmp, NULL);
g_free(tmp);
is_mdev = subsys && (strcmp(subsys, "/sys/bus/mdev") == 0);
free(subsys);
trace_vfio_mdev(vdev->vbasedev.name, is_mdev);
trace_vfio_mdev(vbasedev->name, is_mdev);
if (vdev->vbasedev.ram_block_discard_allowed && !is_mdev) {
if (vbasedev->ram_block_discard_allowed && !is_mdev) {
error_setg(errp, "x-balloon-allowed only potentially compatible "
"with mdev devices");
vfio_put_group(group);
goto error;
}
ret = vfio_get_device(group, vdev->vbasedev.name, &vdev->vbasedev, errp);
ret = vfio_get_device(group, vbasedev->name, vbasedev, errp);
if (ret) {
vfio_put_group(group);
goto error;
@ -2905,7 +2949,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
}
/* Get a copy of config space */
ret = pread(vdev->vbasedev.fd, vdev->pdev.config,
ret = pread(vbasedev->fd, vdev->pdev.config,
MIN(pci_config_size(&vdev->pdev), vdev->config_size),
vdev->config_offset);
if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) {
@ -2933,7 +2977,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
goto error;
}
vfio_add_emulated_word(vdev, PCI_VENDOR_ID, vdev->vendor_id, ~0);
trace_vfio_pci_emulated_vendor_id(vdev->vbasedev.name, vdev->vendor_id);
trace_vfio_pci_emulated_vendor_id(vbasedev->name, vdev->vendor_id);
} else {
vdev->vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);
}
@ -2944,7 +2988,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
goto error;
}
vfio_add_emulated_word(vdev, PCI_DEVICE_ID, vdev->device_id, ~0);
trace_vfio_pci_emulated_device_id(vdev->vbasedev.name, vdev->device_id);
trace_vfio_pci_emulated_device_id(vbasedev->name, vdev->device_id);
} else {
vdev->device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);
}
@ -2956,7 +3000,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
}
vfio_add_emulated_word(vdev, PCI_SUBSYSTEM_VENDOR_ID,
vdev->sub_vendor_id, ~0);
trace_vfio_pci_emulated_sub_vendor_id(vdev->vbasedev.name,
trace_vfio_pci_emulated_sub_vendor_id(vbasedev->name,
vdev->sub_vendor_id);
}
@ -2966,7 +3010,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
goto error;
}
vfio_add_emulated_word(vdev, PCI_SUBSYSTEM_ID, vdev->sub_device_id, ~0);
trace_vfio_pci_emulated_sub_device_id(vdev->vbasedev.name,
trace_vfio_pci_emulated_sub_device_id(vbasedev->name,
vdev->sub_device_id);
}
@ -3025,7 +3069,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
goto out_teardown;
}
ret = vfio_get_dev_region_info(&vdev->vbasedev,
ret = vfio_get_dev_region_info(vbasedev,
VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
if (ret) {
@ -3101,9 +3145,9 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
}
if (!pdev->failover_pair_id) {
ret = vfio_migration_probe(&vdev->vbasedev, errp);
ret = vfio_migration_probe(vbasedev, errp);
if (ret) {
error_report("%s: Migration disabled", vdev->vbasedev.name);
error_report("%s: Migration disabled", vbasedev->name);
}
}
@ -3120,7 +3164,7 @@ out_teardown:
vfio_teardown_msi(vdev);
vfio_bars_exit(vdev);
error:
error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->name);
}
static void vfio_instance_finalize(Object *obj)

View File

@ -19,6 +19,7 @@
#include "qemu/queue.h"
#include "qemu/timer.h"
#include "qom/object.h"
#include "sysemu/kvm.h"
#define PCI_ANY_ID (~0)
@ -171,6 +172,7 @@ struct VFIOPCIDevice {
bool no_kvm_ioeventfd;
bool no_vfio_ioeventfd;
bool enable_ramfb;
bool defer_kvm_irq_routing;
VFIODisplay *dpy;
Notifier irqchip_change_notifier;
};

View File

@ -100,6 +100,7 @@ vfio_listener_region_add_skip(uint64_t start, uint64_t end) "SKIPPING region_add
vfio_spapr_group_attach(int groupfd, int tablefd) "Attached groupfd %d to liobn fd %d"
vfio_listener_region_add_iommu(uint64_t start, uint64_t end) "region_add [iommu] 0x%"PRIx64" - 0x%"PRIx64
vfio_listener_region_add_ram(uint64_t iova_start, uint64_t iova_end, void *vaddr) "region_add [ram] 0x%"PRIx64" - 0x%"PRIx64" [%p]"
vfio_known_safe_misalignment(const char *name, uint64_t iova, uint64_t offset_within_region, uintptr_t page_size) "Region \"%s\" iova=0x%"PRIx64" offset_within_region=0x%"PRIx64" qemu_real_host_page_size=0x%"PRIxPTR ": cannot be mapped for DMA"
vfio_listener_region_add_no_dma_map(const char *name, uint64_t iova, uint64_t size, uint64_t page_size) "Region \"%s\" 0x%"PRIx64" size=0x%"PRIx64" is not aligned to 0x%"PRIx64" and cannot be mapped for DMA"
vfio_listener_region_del_skip(uint64_t start, uint64_t end) "SKIPPING region_del 0x%"PRIx64" - 0x%"PRIx64
vfio_listener_region_del(uint64_t start, uint64_t end) "region_del 0x%"PRIx64" - 0x%"PRIx64

View File

@ -98,7 +98,7 @@ typedef struct VFIOContainer {
typedef struct VFIOGuestIOMMU {
VFIOContainer *container;
IOMMUMemoryRegion *iommu;
IOMMUMemoryRegion *iommu_mr;
hwaddr iommu_offset;
IOMMUNotifier n;
QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;

View File

@ -80,6 +80,12 @@ static inline TPMVersion tpm_get_version(TPMIf *ti)
#define tpm_init() (0)
#define tpm_cleanup()
/* needed for an alignment check in non-tpm code */
static inline Object *TPM_IS_CRB(Object *obj)
{
return NULL;
}
#endif /* CONFIG_TPM */
#endif /* QEMU_TPM_H */