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:
commit
13220a46e2
@ -40,6 +40,7 @@
|
|||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "migration/migration.h"
|
#include "migration/migration.h"
|
||||||
|
#include "sysemu/tpm.h"
|
||||||
|
|
||||||
VFIOGroupList vfio_group_list =
|
VFIOGroupList vfio_group_list =
|
||||||
QLIST_HEAD_INITIALIZER(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);
|
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,
|
static void vfio_listener_region_add(MemoryListener *listener,
|
||||||
MemoryRegionSection *section)
|
MemoryRegionSection *section)
|
||||||
{
|
{
|
||||||
@ -884,7 +901,15 @@ static void vfio_listener_region_add(MemoryListener *listener,
|
|||||||
if (unlikely((section->offset_within_address_space &
|
if (unlikely((section->offset_within_address_space &
|
||||||
~qemu_real_host_page_mask()) !=
|
~qemu_real_host_page_mask()) !=
|
||||||
(section->offset_within_region & ~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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,7 +1017,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
|
|||||||
* device emulation the VFIO iommu handles to use).
|
* device emulation the VFIO iommu handles to use).
|
||||||
*/
|
*/
|
||||||
giommu = g_malloc0(sizeof(*giommu));
|
giommu = g_malloc0(sizeof(*giommu));
|
||||||
giommu->iommu = iommu_mr;
|
giommu->iommu_mr = iommu_mr;
|
||||||
giommu->iommu_offset = section->offset_within_address_space -
|
giommu->iommu_offset = section->offset_within_address_space -
|
||||||
section->offset_within_region;
|
section->offset_within_region;
|
||||||
giommu->container = container;
|
giommu->container = container;
|
||||||
@ -1007,7 +1032,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
|
|||||||
int128_get64(llend),
|
int128_get64(llend),
|
||||||
iommu_idx);
|
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,
|
container->pgsizes,
|
||||||
&err);
|
&err);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -1022,7 +1047,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -1128,7 +1153,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
|
|||||||
VFIOGuestIOMMU *giommu;
|
VFIOGuestIOMMU *giommu;
|
||||||
|
|
||||||
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
|
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) {
|
giommu->n.start == section->offset_within_region) {
|
||||||
memory_region_unregister_iommu_notifier(section->mr,
|
memory_region_unregister_iommu_notifier(section->mr,
|
||||||
&giommu->n);
|
&giommu->n);
|
||||||
@ -1393,11 +1418,11 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container,
|
|||||||
VFIOGuestIOMMU *giommu;
|
VFIOGuestIOMMU *giommu;
|
||||||
|
|
||||||
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
|
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) {
|
giommu->n.start == section->offset_within_region) {
|
||||||
Int128 llend;
|
Int128 llend;
|
||||||
vfio_giommu_dirty_notifier gdn = { .giommu = giommu };
|
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);
|
MEMTXATTRS_UNSPECIFIED);
|
||||||
|
|
||||||
llend = int128_add(int128_make64(section->offset_within_region),
|
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,
|
section->offset_within_region,
|
||||||
int128_get64(llend),
|
int128_get64(llend),
|
||||||
idx);
|
idx);
|
||||||
memory_region_iommu_replay(giommu->iommu, &gdn.n);
|
memory_region_iommu_replay(giommu->iommu_mr, &gdn.n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1544,11 +1569,10 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
|
|||||||
region->mmaps = g_new0(VFIOMmap, sparse->nr_areas);
|
region->mmaps = g_new0(VFIOMmap, sparse->nr_areas);
|
||||||
|
|
||||||
for (i = 0, j = 0; i < sparse->nr_areas; i++) {
|
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) {
|
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].offset = sparse->areas[i].offset;
|
||||||
region->mmaps[j].size = sparse->areas[i].size;
|
region->mmaps[j].size = sparse->areas[i].size;
|
||||||
j++;
|
j++;
|
||||||
@ -2246,7 +2270,7 @@ static void vfio_disconnect_container(VFIOGroup *group)
|
|||||||
|
|
||||||
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
|
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
|
||||||
memory_region_unregister_iommu_notifier(
|
memory_region_unregister_iommu_notifier(
|
||||||
MEMORY_REGION(giommu->iommu), &giommu->n);
|
MEMORY_REGION(giommu->iommu_mr), &giommu->n);
|
||||||
QLIST_REMOVE(giommu, giommu_next);
|
QLIST_REMOVE(giommu, giommu_next);
|
||||||
g_free(giommu);
|
g_free(giommu);
|
||||||
}
|
}
|
||||||
|
234
hw/vfio/pci.c
234
hw/vfio/pci.c
@ -45,8 +45,12 @@
|
|||||||
|
|
||||||
#define TYPE_VFIO_PCI_NOHOTPLUG "vfio-pci-nohotplug"
|
#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_disable_interrupts(VFIOPCIDevice *vdev);
|
||||||
static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
|
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
|
* 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,
|
static void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
|
||||||
int vector_n, bool msix)
|
int vector_n, bool msix)
|
||||||
{
|
{
|
||||||
KVMRouteChange c;
|
|
||||||
int virq;
|
|
||||||
|
|
||||||
if ((msix && vdev->no_kvm_msix) || (!msix && vdev->no_kvm_msi)) {
|
if ((msix && vdev->no_kvm_msix) || (!msix && vdev->no_kvm_msi)) {
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = kvm_irqchip_begin_route_changes(kvm_state);
|
if (event_notifier_init(&vector->kvm_interrupt, 0)) {
|
||||||
virq = kvm_irqchip_add_msi_route(&c, vector_n, &vdev->pdev);
|
goto fail_notifier;
|
||||||
if (virq < 0) {
|
|
||||||
event_notifier_cleanup(&vector->kvm_interrupt);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
kvm_irqchip_commit_route_changes(&c);
|
|
||||||
|
|
||||||
if (kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &vector->kvm_interrupt,
|
if (kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &vector->kvm_interrupt,
|
||||||
NULL, virq) < 0) {
|
NULL, vector->virq) < 0) {
|
||||||
kvm_irqchip_release_virq(kvm_state, virq);
|
goto fail_kvm;
|
||||||
event_notifier_cleanup(&vector->kvm_interrupt);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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 {
|
} else {
|
||||||
if (msg) {
|
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.
|
* increase them as needed.
|
||||||
*/
|
*/
|
||||||
if (vdev->nr_vectors < nr + 1) {
|
if (vdev->nr_vectors < nr + 1) {
|
||||||
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
|
|
||||||
vdev->nr_vectors = nr + 1;
|
vdev->nr_vectors = nr + 1;
|
||||||
ret = vfio_enable_vectors(vdev, true);
|
if (!vdev->defer_kvm_irq_routing) {
|
||||||
if (ret) {
|
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
|
||||||
error_report("vfio: failed to enable vectors, %d", ret);
|
ret = vfio_enable_vectors(vdev, true);
|
||||||
|
if (ret) {
|
||||||
|
error_report("vfio: failed to enable vectors, %d", ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Error *err = NULL;
|
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)
|
static void vfio_msix_enable(VFIOPCIDevice *vdev)
|
||||||
{
|
{
|
||||||
PCIDevice *pdev = &vdev->pdev;
|
|
||||||
unsigned int nr, max_vec = 0;
|
|
||||||
|
|
||||||
vfio_disable_interrupts(vdev);
|
vfio_disable_interrupts(vdev);
|
||||||
|
|
||||||
vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->msix->entries);
|
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;
|
vdev->interrupt = VFIO_INT_MSIX;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some communication channels between VF & PF or PF & fw rely on the
|
* Setting vector notifiers triggers synchronous vector-use
|
||||||
* physical state of the device and expect that enabling MSI-X from the
|
* callbacks for each active vector. Deferring to commit the KVM
|
||||||
* guest enables the same on the host. When our guest is Linux, the
|
* routes once rather than per vector provides a substantial
|
||||||
* guest driver call to pci_enable_msix() sets the enabling bit in the
|
* performance improvement.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
if (!pdev->msix_function_masked) {
|
vfio_prepare_kvm_msi_virq_batch(vdev);
|
||||||
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);
|
|
||||||
|
|
||||||
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)) {
|
vfio_msix_vector_release, NULL)) {
|
||||||
error_report("vfio: msix_set_vector_notifiers failed");
|
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);
|
trace_vfio_msix_enable(vdev->vbasedev.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,6 +663,13 @@ static void vfio_msi_enable(VFIOPCIDevice *vdev)
|
|||||||
|
|
||||||
vfio_disable_interrupts(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);
|
vdev->nr_vectors = msi_nr_vectors_allocated(&vdev->pdev);
|
||||||
retry:
|
retry:
|
||||||
vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->nr_vectors);
|
vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->nr_vectors);
|
||||||
@ -646,6 +695,8 @@ retry:
|
|||||||
vfio_add_kvm_msi_virq(vdev, vector, i, false);
|
vfio_add_kvm_msi_virq(vdev, vector, i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vfio_commit_kvm_msi_virq_batch(vdev);
|
||||||
|
|
||||||
/* Set interrupt type prior to possible interrupts */
|
/* Set interrupt type prior to possible interrupts */
|
||||||
vdev->interrupt = VFIO_INT_MSI;
|
vdev->interrupt = VFIO_INT_MSI;
|
||||||
|
|
||||||
@ -653,29 +704,17 @@ retry:
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("vfio: Error: Failed to setup MSI fds: %m");
|
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 "
|
error_report("vfio: Error: Failed to enable %d "
|
||||||
"MSI vectors, retry with %d", vdev->nr_vectors, ret);
|
"MSI vectors, retry with %d", vdev->nr_vectors, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < vdev->nr_vectors; i++) {
|
vfio_msi_disable_common(vdev);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free(vdev->msi_vectors);
|
if (ret > 0) {
|
||||||
vdev->msi_vectors = NULL;
|
|
||||||
|
|
||||||
if (ret > 0 && ret != vdev->nr_vectors) {
|
|
||||||
vdev->nr_vectors = ret;
|
vdev->nr_vectors = ret;
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
vdev->nr_vectors = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Failing to setup MSI doesn't really fall within any specification.
|
* 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.
|
* out to fall back to INTx for this device.
|
||||||
*/
|
*/
|
||||||
error_report("vfio: Error: Failed to enable MSI");
|
error_report("vfio: Error: Failed to enable MSI");
|
||||||
vdev->interrupt = VFIO_INT_NONE;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -693,7 +731,6 @@ retry:
|
|||||||
|
|
||||||
static void vfio_msi_disable_common(VFIOPCIDevice *vdev)
|
static void vfio_msi_disable_common(VFIOPCIDevice *vdev)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < vdev->nr_vectors; 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->msi_vectors = NULL;
|
||||||
vdev->nr_vectors = 0;
|
vdev->nr_vectors = 0;
|
||||||
vdev->interrupt = VFIO_INT_NONE;
|
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)
|
static void vfio_msix_disable(VFIOPCIDevice *vdev)
|
||||||
{
|
{
|
||||||
|
Error *err = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
msix_unset_vector_notifiers(&vdev->pdev);
|
msix_unset_vector_notifiers(&vdev->pdev);
|
||||||
@ -741,6 +774,10 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
vfio_msi_disable_common(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,
|
memset(vdev->msix->pending, 0,
|
||||||
BITS_TO_LONGS(vdev->msix->entries) * sizeof(unsigned long));
|
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)
|
static void vfio_msi_disable(VFIOPCIDevice *vdev)
|
||||||
{
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSI_IRQ_INDEX);
|
vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSI_IRQ_INDEX);
|
||||||
vfio_msi_disable_common(vdev);
|
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);
|
trace_vfio_msi_disable(vdev->vbasedev.name);
|
||||||
}
|
}
|
||||||
@ -2337,7 +2380,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
|
|||||||
g_free(reset);
|
g_free(reset);
|
||||||
|
|
||||||
trace_vfio_pci_hot_reset_result(vdev->vbasedev.name,
|
trace_vfio_pci_hot_reset_result(vdev->vbasedev.name,
|
||||||
ret ? "%m" : "Success");
|
ret ? strerror(errno) : "Success");
|
||||||
|
|
||||||
out:
|
out:
|
||||||
/* Re-enable INTx on affected devices */
|
/* 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)
|
static void vfio_realize(PCIDevice *pdev, Error **errp)
|
||||||
{
|
{
|
||||||
VFIOPCIDevice *vdev = VFIO_PCI(pdev);
|
VFIOPCIDevice *vdev = VFIO_PCI(pdev);
|
||||||
|
VFIODevice *vbasedev = &vdev->vbasedev;
|
||||||
VFIODevice *vbasedev_iter;
|
VFIODevice *vbasedev_iter;
|
||||||
VFIOGroup *group;
|
VFIOGroup *group;
|
||||||
char *tmp, *subsys, group_path[PATH_MAX], *group_name;
|
char *tmp, *subsys, group_path[PATH_MAX], *group_name;
|
||||||
@ -2813,7 +2857,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
|||||||
int i, ret;
|
int i, ret;
|
||||||
bool is_mdev;
|
bool is_mdev;
|
||||||
|
|
||||||
if (!vdev->vbasedev.sysfsdev) {
|
if (!vbasedev->sysfsdev) {
|
||||||
if (!(~vdev->host.domain || ~vdev->host.bus ||
|
if (!(~vdev->host.domain || ~vdev->host.bus ||
|
||||||
~vdev->host.slot || ~vdev->host.function)) {
|
~vdev->host.slot || ~vdev->host.function)) {
|
||||||
error_setg(errp, "No provided host device");
|
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");
|
"or -device vfio-pci,sysfsdev=PATH_TO_DEVICE\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vdev->vbasedev.sysfsdev =
|
vbasedev->sysfsdev =
|
||||||
g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%01x",
|
g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%01x",
|
||||||
vdev->host.domain, vdev->host.bus,
|
vdev->host.domain, vdev->host.bus,
|
||||||
vdev->host.slot, vdev->host.function);
|
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_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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vdev->vbasedev.name = g_path_get_basename(vdev->vbasedev.sysfsdev);
|
vbasedev->name = g_path_get_basename(vbasedev->sysfsdev);
|
||||||
vdev->vbasedev.ops = &vfio_pci_ops;
|
vbasedev->ops = &vfio_pci_ops;
|
||||||
vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI;
|
vbasedev->type = VFIO_DEVICE_TYPE_PCI;
|
||||||
vdev->vbasedev.dev = DEVICE(vdev);
|
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));
|
len = readlink(tmp, group_path, sizeof(group_path));
|
||||||
g_free(tmp);
|
g_free(tmp);
|
||||||
|
|
||||||
@ -2856,7 +2900,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
|||||||
goto error;
|
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);
|
group = vfio_get_group(groupid, pci_device_iommu_address_space(pdev), errp);
|
||||||
if (!group) {
|
if (!group) {
|
||||||
@ -2864,7 +2908,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
|
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");
|
error_setg(errp, "device is already attached");
|
||||||
vfio_put_group(group);
|
vfio_put_group(group);
|
||||||
goto error;
|
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
|
* 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.
|
* 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);
|
subsys = realpath(tmp, NULL);
|
||||||
g_free(tmp);
|
g_free(tmp);
|
||||||
is_mdev = subsys && (strcmp(subsys, "/sys/bus/mdev") == 0);
|
is_mdev = subsys && (strcmp(subsys, "/sys/bus/mdev") == 0);
|
||||||
free(subsys);
|
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 "
|
error_setg(errp, "x-balloon-allowed only potentially compatible "
|
||||||
"with mdev devices");
|
"with mdev devices");
|
||||||
vfio_put_group(group);
|
vfio_put_group(group);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = vfio_get_device(group, vdev->vbasedev.name, &vdev->vbasedev, errp);
|
ret = vfio_get_device(group, vbasedev->name, vbasedev, errp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
vfio_put_group(group);
|
vfio_put_group(group);
|
||||||
goto error;
|
goto error;
|
||||||
@ -2905,7 +2949,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get a copy of config space */
|
/* 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),
|
MIN(pci_config_size(&vdev->pdev), vdev->config_size),
|
||||||
vdev->config_offset);
|
vdev->config_offset);
|
||||||
if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) {
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
vfio_add_emulated_word(vdev, PCI_VENDOR_ID, vdev->vendor_id, ~0);
|
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 {
|
} else {
|
||||||
vdev->vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
vfio_add_emulated_word(vdev, PCI_DEVICE_ID, vdev->device_id, ~0);
|
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 {
|
} else {
|
||||||
vdev->device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);
|
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,
|
vfio_add_emulated_word(vdev, PCI_SUBSYSTEM_VENDOR_ID,
|
||||||
vdev->sub_vendor_id, ~0);
|
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);
|
vdev->sub_vendor_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2966,7 +3010,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
vfio_add_emulated_word(vdev, PCI_SUBSYSTEM_ID, vdev->sub_device_id, ~0);
|
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);
|
vdev->sub_device_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3025,7 +3069,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
|||||||
goto out_teardown;
|
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_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
|
||||||
VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
|
VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -3101,9 +3145,9 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pdev->failover_pair_id) {
|
if (!pdev->failover_pair_id) {
|
||||||
ret = vfio_migration_probe(&vdev->vbasedev, errp);
|
ret = vfio_migration_probe(vbasedev, errp);
|
||||||
if (ret) {
|
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_teardown_msi(vdev);
|
||||||
vfio_bars_exit(vdev);
|
vfio_bars_exit(vdev);
|
||||||
error:
|
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)
|
static void vfio_instance_finalize(Object *obj)
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
|
#include "sysemu/kvm.h"
|
||||||
|
|
||||||
#define PCI_ANY_ID (~0)
|
#define PCI_ANY_ID (~0)
|
||||||
|
|
||||||
@ -171,6 +172,7 @@ struct VFIOPCIDevice {
|
|||||||
bool no_kvm_ioeventfd;
|
bool no_kvm_ioeventfd;
|
||||||
bool no_vfio_ioeventfd;
|
bool no_vfio_ioeventfd;
|
||||||
bool enable_ramfb;
|
bool enable_ramfb;
|
||||||
|
bool defer_kvm_irq_routing;
|
||||||
VFIODisplay *dpy;
|
VFIODisplay *dpy;
|
||||||
Notifier irqchip_change_notifier;
|
Notifier irqchip_change_notifier;
|
||||||
};
|
};
|
||||||
|
@ -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_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_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_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_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_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
|
vfio_listener_region_del(uint64_t start, uint64_t end) "region_del 0x%"PRIx64" - 0x%"PRIx64
|
||||||
|
@ -98,7 +98,7 @@ typedef struct VFIOContainer {
|
|||||||
|
|
||||||
typedef struct VFIOGuestIOMMU {
|
typedef struct VFIOGuestIOMMU {
|
||||||
VFIOContainer *container;
|
VFIOContainer *container;
|
||||||
IOMMUMemoryRegion *iommu;
|
IOMMUMemoryRegion *iommu_mr;
|
||||||
hwaddr iommu_offset;
|
hwaddr iommu_offset;
|
||||||
IOMMUNotifier n;
|
IOMMUNotifier n;
|
||||||
QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;
|
QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;
|
||||||
|
@ -80,6 +80,12 @@ static inline TPMVersion tpm_get_version(TPMIf *ti)
|
|||||||
#define tpm_init() (0)
|
#define tpm_init() (0)
|
||||||
#define tpm_cleanup()
|
#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 /* CONFIG_TPM */
|
||||||
|
|
||||||
#endif /* QEMU_TPM_H */
|
#endif /* QEMU_TPM_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user