mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-vfio-20230710' of https://github.com/legoater/qemu into staging
vfio queue: * Fixes in error handling paths of VFIO PCI devices * Improvements of reported errors for VFIO migration * Linux header update * Enablement of AtomicOps completers on root ports * Fix for unplug of passthrough AP devices # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmSrug0ACgkQUaNDx8/7 # 7KHYCRAAt6UeZi8nKPlN+cs6guOagCcAJOu13nm7XN0bFxjYf/Q2t618cpM7PLSk # h+4VGsMUVJ1dumcCkBmv7LAn0G6CpVR3VDi5QuGfMODRhpWfSoaypPIizRgrbarL # lSyaVaPIaddlDZ4AIfFA9Ebnytvm5/ecsyTr0cv7OejVKWI/jN6bC/v36AmNQKKQ # J5RCDpQ6fOsdqf0Dzvn7xjuHRE4DYtsWkVoslDoBQMgPWHLF8UwRu/OPD6cBQYAR # /fmgoOkkNDMdN3laqwAyfAUjKfOFpLuZzJ5KNFjtkBiktm66dw4Y8/lWoChVR+S6 # PRZ3nk0HxyzB96zCytfggBX905PBD54LIuockRaYKTlTxT19C3fDjDz5tsjKNhLR # aFec4KiJaUJj0fa/Vw8DB/WUbCgbOXGHiWhY8vNdpVoc9AZe8xj9z4nB3hmzx1i/ # lZhsM/s3kTNHpVGlW7vTfbToFBmt1eoglu+ILe/HeHLi8LjzCsHy+wR5c0n0/HVI # fLUuUS1AGQvi8+HCCUi7gwzpJkl4rPJsPx51wfXJk+q/3GQ8g9Mg9qotHNHm4N60 # zq/I5VqqEkJzdaMjup04ZqsMAWqGrnU2f4aNPvBhgaeO9CQE/buIsA34buQRwiG4 # wTodqm0jrkx0Z59jliZ0mFU/LxMvhMaQCEh+OdyZ9vRtfLBjF4c= # =U2Hc # -----END PGP SIGNATURE----- # gpg: Signature made Mon 10 Jul 2023 08:58:05 AM BST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [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: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-vfio-20230710' of https://github.com/legoater/qemu: vfio/pci: Enable AtomicOps completers on root ports pcie: Add a PCIe capability version helper s390x/ap: Wire up the device request notifier interface linux-headers: update to v6.5-rc1 vfio: Fix null pointer dereference bug in vfio_bars_finalize() vfio/migration: Return bool type for vfio_migration_realize() vfio/migration: Remove print of "Migration disabled" vfio/migration: Free resources when vfio_migration_realize fails vfio/migration: Change vIOMMU blocker from global to per device vfio/pci: Disable INTx in vfio_realize error path hw/vfio/pci-quirks: Sanitize capability pointer Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -274,6 +274,13 @@ uint8_t pcie_cap_get_type(const PCIDevice *dev)
|
||||
PCI_EXP_FLAGS_TYPE) >> PCI_EXP_FLAGS_TYPE_SHIFT;
|
||||
}
|
||||
|
||||
uint8_t pcie_cap_get_version(const PCIDevice *dev)
|
||||
{
|
||||
uint32_t pos = dev->exp.exp_cap;
|
||||
assert(pos > 0);
|
||||
return pci_get_word(dev->config + pos + PCI_EXP_FLAGS) & PCI_EXP_FLAGS_VERS;
|
||||
}
|
||||
|
||||
/* MSI/MSI-X */
|
||||
/* pci express interrupt message number */
|
||||
/* 7.8.2 PCI Express Capabilities Register: Interrupt Message Number */
|
||||
|
||||
+113
@@ -18,6 +18,8 @@
|
||||
#include "hw/vfio/vfio-common.h"
|
||||
#include "hw/s390x/ap-device.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/event_notifier.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
@@ -33,6 +35,7 @@
|
||||
struct VFIOAPDevice {
|
||||
APDevice apdev;
|
||||
VFIODevice vdev;
|
||||
EventNotifier req_notifier;
|
||||
};
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(VFIOAPDevice, VFIO_AP_DEVICE)
|
||||
@@ -84,10 +87,110 @@ static VFIOGroup *vfio_ap_get_group(VFIOAPDevice *vapdev, Error **errp)
|
||||
return vfio_get_group(groupid, &address_space_memory, errp);
|
||||
}
|
||||
|
||||
static void vfio_ap_req_notifier_handler(void *opaque)
|
||||
{
|
||||
VFIOAPDevice *vapdev = opaque;
|
||||
Error *err = NULL;
|
||||
|
||||
if (!event_notifier_test_and_clear(&vapdev->req_notifier)) {
|
||||
return;
|
||||
}
|
||||
|
||||
qdev_unplug(DEVICE(vapdev), &err);
|
||||
|
||||
if (err) {
|
||||
warn_reportf_err(err, VFIO_MSG_PREFIX, vapdev->vdev.name);
|
||||
}
|
||||
}
|
||||
|
||||
static void vfio_ap_register_irq_notifier(VFIOAPDevice *vapdev,
|
||||
unsigned int irq, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
size_t argsz;
|
||||
IOHandler *fd_read;
|
||||
EventNotifier *notifier;
|
||||
struct vfio_irq_info *irq_info;
|
||||
VFIODevice *vdev = &vapdev->vdev;
|
||||
|
||||
switch (irq) {
|
||||
case VFIO_AP_REQ_IRQ_INDEX:
|
||||
notifier = &vapdev->req_notifier;
|
||||
fd_read = vfio_ap_req_notifier_handler;
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "vfio: Unsupported device irq(%d)", irq);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vdev->num_irqs < irq + 1) {
|
||||
error_setg(errp, "vfio: IRQ %u not available (number of irqs %u)",
|
||||
irq, vdev->num_irqs);
|
||||
return;
|
||||
}
|
||||
|
||||
argsz = sizeof(*irq_info);
|
||||
irq_info = g_malloc0(argsz);
|
||||
irq_info->index = irq;
|
||||
irq_info->argsz = argsz;
|
||||
|
||||
if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO,
|
||||
irq_info) < 0 || irq_info->count < 1) {
|
||||
error_setg_errno(errp, errno, "vfio: Error getting irq info");
|
||||
goto out_free_info;
|
||||
}
|
||||
|
||||
if (event_notifier_init(notifier, 0)) {
|
||||
error_setg_errno(errp, errno,
|
||||
"vfio: Unable to init event notifier for irq (%d)",
|
||||
irq);
|
||||
goto out_free_info;
|
||||
}
|
||||
|
||||
fd = event_notifier_get_fd(notifier);
|
||||
qemu_set_fd_handler(fd, fd_read, NULL, vapdev);
|
||||
|
||||
if (vfio_set_irq_signaling(vdev, irq, 0, VFIO_IRQ_SET_ACTION_TRIGGER, fd,
|
||||
errp)) {
|
||||
qemu_set_fd_handler(fd, NULL, NULL, vapdev);
|
||||
event_notifier_cleanup(notifier);
|
||||
}
|
||||
|
||||
out_free_info:
|
||||
g_free(irq_info);
|
||||
|
||||
}
|
||||
|
||||
static void vfio_ap_unregister_irq_notifier(VFIOAPDevice *vapdev,
|
||||
unsigned int irq)
|
||||
{
|
||||
Error *err = NULL;
|
||||
EventNotifier *notifier;
|
||||
|
||||
switch (irq) {
|
||||
case VFIO_AP_REQ_IRQ_INDEX:
|
||||
notifier = &vapdev->req_notifier;
|
||||
break;
|
||||
default:
|
||||
error_report("vfio: Unsupported device irq(%d)", irq);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vfio_set_irq_signaling(&vapdev->vdev, irq, 0,
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) {
|
||||
warn_reportf_err(err, VFIO_MSG_PREFIX, vapdev->vdev.name);
|
||||
}
|
||||
|
||||
qemu_set_fd_handler(event_notifier_get_fd(notifier),
|
||||
NULL, NULL, vapdev);
|
||||
event_notifier_cleanup(notifier);
|
||||
}
|
||||
|
||||
static void vfio_ap_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
char *mdevid;
|
||||
Error *err = NULL;
|
||||
VFIOGroup *vfio_group;
|
||||
APDevice *apdev = AP_DEVICE(dev);
|
||||
VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
|
||||
@@ -116,6 +219,15 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp)
|
||||
goto out_get_dev_err;
|
||||
}
|
||||
|
||||
vfio_ap_register_irq_notifier(vapdev, VFIO_AP_REQ_IRQ_INDEX, &err);
|
||||
if (err) {
|
||||
/*
|
||||
* Report this error, but do not make it a failing condition.
|
||||
* Lack of this IRQ in the host does not prevent normal operation.
|
||||
*/
|
||||
error_report_err(err);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out_get_dev_err:
|
||||
@@ -129,6 +241,7 @@ static void vfio_ap_unrealize(DeviceState *dev)
|
||||
VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
|
||||
VFIOGroup *group = vapdev->vdev.group;
|
||||
|
||||
vfio_ap_unregister_irq_notifier(vapdev, VFIO_AP_REQ_IRQ_INDEX);
|
||||
vfio_ap_put_device(vapdev);
|
||||
vfio_put_group(group);
|
||||
}
|
||||
|
||||
+2
-49
@@ -362,7 +362,6 @@ bool vfio_mig_active(void)
|
||||
}
|
||||
|
||||
static Error *multiple_devices_migration_blocker;
|
||||
static Error *giommu_migration_blocker;
|
||||
|
||||
static unsigned int vfio_migratable_device_num(void)
|
||||
{
|
||||
@@ -420,55 +419,9 @@ void vfio_unblock_multiple_devices_migration(void)
|
||||
multiple_devices_migration_blocker = NULL;
|
||||
}
|
||||
|
||||
static bool vfio_viommu_preset(void)
|
||||
bool vfio_viommu_preset(VFIODevice *vbasedev)
|
||||
{
|
||||
VFIOAddressSpace *space;
|
||||
|
||||
QLIST_FOREACH(space, &vfio_address_spaces, list) {
|
||||
if (space->as != &address_space_memory) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int vfio_block_giommu_migration(VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (giommu_migration_blocker ||
|
||||
!vfio_viommu_preset()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vbasedev->enable_migration == ON_OFF_AUTO_ON) {
|
||||
error_setg(errp,
|
||||
"Migration is currently not supported with vIOMMU enabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
error_setg(&giommu_migration_blocker,
|
||||
"Migration is currently not supported with vIOMMU enabled");
|
||||
ret = migrate_add_blocker(giommu_migration_blocker, errp);
|
||||
if (ret < 0) {
|
||||
error_free(giommu_migration_blocker);
|
||||
giommu_migration_blocker = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vfio_migration_finalize(void)
|
||||
{
|
||||
if (!giommu_migration_blocker ||
|
||||
vfio_viommu_preset()) {
|
||||
return;
|
||||
}
|
||||
|
||||
migrate_del_blocker(giommu_migration_blocker);
|
||||
error_free(giommu_migration_blocker);
|
||||
giommu_migration_blocker = NULL;
|
||||
return vbasedev->group->container->space->as != &address_space_memory;
|
||||
}
|
||||
|
||||
static void vfio_set_migration_error(int err)
|
||||
|
||||
+35
-16
@@ -802,6 +802,17 @@ static int vfio_migration_init(VFIODevice *vbasedev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vfio_migration_deinit(VFIODevice *vbasedev)
|
||||
{
|
||||
VFIOMigration *migration = vbasedev->migration;
|
||||
|
||||
remove_migration_state_change_notifier(&migration->migration_state);
|
||||
qemu_del_vm_change_state_handler(migration->vm_state);
|
||||
unregister_savevm(VMSTATE_IF(vbasedev->dev), "vfio", vbasedev);
|
||||
vfio_migration_free(vbasedev);
|
||||
vfio_unblock_multiple_devices_migration();
|
||||
}
|
||||
|
||||
static int vfio_block_migration(VFIODevice *vbasedev, Error *err, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
@@ -835,7 +846,12 @@ void vfio_reset_bytes_transferred(void)
|
||||
bytes_transferred = 0;
|
||||
}
|
||||
|
||||
int vfio_migration_realize(VFIODevice *vbasedev, Error **errp)
|
||||
/*
|
||||
* Return true when either migration initialized or blocker registered.
|
||||
* Currently only return false when adding blocker fails which will
|
||||
* de-register vfio device.
|
||||
*/
|
||||
bool vfio_migration_realize(VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
@@ -843,7 +859,7 @@ int vfio_migration_realize(VFIODevice *vbasedev, Error **errp)
|
||||
if (vbasedev->enable_migration == ON_OFF_AUTO_OFF) {
|
||||
error_setg(&err, "%s: Migration is disabled for VFIO device",
|
||||
vbasedev->name);
|
||||
return vfio_block_migration(vbasedev, err, errp);
|
||||
return !vfio_block_migration(vbasedev, err, errp);
|
||||
}
|
||||
|
||||
ret = vfio_migration_init(vbasedev);
|
||||
@@ -858,7 +874,7 @@ int vfio_migration_realize(VFIODevice *vbasedev, Error **errp)
|
||||
vbasedev->name, ret, strerror(-ret));
|
||||
}
|
||||
|
||||
return vfio_block_migration(vbasedev, err, errp);
|
||||
return !vfio_block_migration(vbasedev, err, errp);
|
||||
}
|
||||
|
||||
if (!vbasedev->dirty_pages_supported) {
|
||||
@@ -866,7 +882,7 @@ int vfio_migration_realize(VFIODevice *vbasedev, Error **errp)
|
||||
error_setg(&err,
|
||||
"%s: VFIO device doesn't support device dirty tracking",
|
||||
vbasedev->name);
|
||||
return vfio_block_migration(vbasedev, err, errp);
|
||||
goto add_blocker;
|
||||
}
|
||||
|
||||
warn_report("%s: VFIO device doesn't support device dirty tracking",
|
||||
@@ -875,28 +891,31 @@ int vfio_migration_realize(VFIODevice *vbasedev, Error **errp)
|
||||
|
||||
ret = vfio_block_multiple_devices_migration(vbasedev, errp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
goto out_deinit;
|
||||
}
|
||||
|
||||
ret = vfio_block_giommu_migration(vbasedev, errp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (vfio_viommu_preset(vbasedev)) {
|
||||
error_setg(&err, "%s: Migration is currently not supported "
|
||||
"with vIOMMU enabled", vbasedev->name);
|
||||
goto add_blocker;
|
||||
}
|
||||
|
||||
trace_vfio_migration_realize(vbasedev->name);
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
add_blocker:
|
||||
ret = vfio_block_migration(vbasedev, err, errp);
|
||||
out_deinit:
|
||||
if (ret) {
|
||||
vfio_migration_deinit(vbasedev);
|
||||
}
|
||||
return !ret;
|
||||
}
|
||||
|
||||
void vfio_migration_exit(VFIODevice *vbasedev)
|
||||
{
|
||||
if (vbasedev->migration) {
|
||||
VFIOMigration *migration = vbasedev->migration;
|
||||
|
||||
remove_migration_state_change_notifier(&migration->migration_state);
|
||||
qemu_del_vm_change_state_handler(migration->vm_state);
|
||||
unregister_savevm(VMSTATE_IF(vbasedev->dev), "vfio", vbasedev);
|
||||
vfio_migration_free(vbasedev);
|
||||
vfio_unblock_multiple_devices_migration();
|
||||
vfio_migration_deinit(vbasedev);
|
||||
}
|
||||
|
||||
if (vbasedev->migration_blocker) {
|
||||
|
||||
@@ -1530,6 +1530,12 @@ const PropertyInfo qdev_prop_nv_gpudirect_clique = {
|
||||
.set = set_nv_gpudirect_clique_id,
|
||||
};
|
||||
|
||||
static bool is_valid_std_cap_offset(uint8_t pos)
|
||||
{
|
||||
return (pos >= PCI_STD_HEADER_SIZEOF &&
|
||||
pos <= (PCI_CFG_SPACE_SIZE - PCI_CAP_SIZEOF));
|
||||
}
|
||||
|
||||
static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
{
|
||||
PCIDevice *pdev = &vdev->pdev;
|
||||
@@ -1563,7 +1569,7 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
*/
|
||||
ret = pread(vdev->vbasedev.fd, &tmp, 1,
|
||||
vdev->config_offset + PCI_CAPABILITY_LIST);
|
||||
if (ret != 1 || !tmp) {
|
||||
if (ret != 1 || !is_valid_std_cap_offset(tmp)) {
|
||||
error_setg(errp, "NVIDIA GPUDirect Clique ID: error getting cap list");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1575,7 +1581,7 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
d4_conflict = true;
|
||||
}
|
||||
tmp = pdev->config[tmp + PCI_CAP_LIST_NEXT];
|
||||
} while (tmp);
|
||||
} while (is_valid_std_cap_offset(tmp));
|
||||
|
||||
if (!c8_conflict) {
|
||||
pos = 0xC8;
|
||||
|
||||
+86
-5
@@ -1752,9 +1752,11 @@ static void vfio_bars_finalize(VFIOPCIDevice *vdev)
|
||||
|
||||
vfio_bar_quirk_finalize(vdev, i);
|
||||
vfio_region_finalize(&bar->region);
|
||||
if (bar->size) {
|
||||
if (bar->mr) {
|
||||
assert(bar->size);
|
||||
object_unparent(OBJECT(bar->mr));
|
||||
g_free(bar->mr);
|
||||
bar->mr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1826,6 +1828,81 @@ static void vfio_add_emulated_long(VFIOPCIDevice *vdev, int pos,
|
||||
vfio_set_long_bits(vdev->emulated_config_bits + pos, mask, mask);
|
||||
}
|
||||
|
||||
static void vfio_pci_enable_rp_atomics(VFIOPCIDevice *vdev)
|
||||
{
|
||||
struct vfio_device_info_cap_pci_atomic_comp *cap;
|
||||
g_autofree struct vfio_device_info *info = NULL;
|
||||
PCIBus *bus = pci_get_bus(&vdev->pdev);
|
||||
PCIDevice *parent = bus->parent_dev;
|
||||
struct vfio_info_cap_header *hdr;
|
||||
uint32_t mask = 0;
|
||||
uint8_t *pos;
|
||||
|
||||
/*
|
||||
* PCIe Atomic Ops completer support is only added automatically for single
|
||||
* function devices downstream of a root port supporting DEVCAP2. Support
|
||||
* is added during realize and, if added, removed during device exit. The
|
||||
* single function requirement avoids conflicting requirements should a
|
||||
* slot be composed of multiple devices with differing capabilities.
|
||||
*/
|
||||
if (pci_bus_is_root(bus) || !parent || !parent->exp.exp_cap ||
|
||||
pcie_cap_get_type(parent) != PCI_EXP_TYPE_ROOT_PORT ||
|
||||
pcie_cap_get_version(parent) != PCI_EXP_FLAGS_VER2 ||
|
||||
vdev->pdev.devfn ||
|
||||
vdev->pdev.cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
pos = parent->config + parent->exp.exp_cap + PCI_EXP_DEVCAP2;
|
||||
|
||||
/* Abort if there'a already an Atomic Ops configuration on the root port */
|
||||
if (pci_get_long(pos) & (PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
|
||||
PCI_EXP_DEVCAP2_ATOMIC_COMP64 |
|
||||
PCI_EXP_DEVCAP2_ATOMIC_COMP128)) {
|
||||
return;
|
||||
}
|
||||
|
||||
info = vfio_get_device_info(vdev->vbasedev.fd);
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_PCI_ATOMIC_COMP);
|
||||
if (!hdr) {
|
||||
return;
|
||||
}
|
||||
|
||||
cap = (void *)hdr;
|
||||
if (cap->flags & VFIO_PCI_ATOMIC_COMP32) {
|
||||
mask |= PCI_EXP_DEVCAP2_ATOMIC_COMP32;
|
||||
}
|
||||
if (cap->flags & VFIO_PCI_ATOMIC_COMP64) {
|
||||
mask |= PCI_EXP_DEVCAP2_ATOMIC_COMP64;
|
||||
}
|
||||
if (cap->flags & VFIO_PCI_ATOMIC_COMP128) {
|
||||
mask |= PCI_EXP_DEVCAP2_ATOMIC_COMP128;
|
||||
}
|
||||
|
||||
if (!mask) {
|
||||
return;
|
||||
}
|
||||
|
||||
pci_long_test_and_set_mask(pos, mask);
|
||||
vdev->clear_parent_atomics_on_exit = true;
|
||||
}
|
||||
|
||||
static void vfio_pci_disable_rp_atomics(VFIOPCIDevice *vdev)
|
||||
{
|
||||
if (vdev->clear_parent_atomics_on_exit) {
|
||||
PCIDevice *parent = pci_get_bus(&vdev->pdev)->parent_dev;
|
||||
uint8_t *pos = parent->config + parent->exp.exp_cap + PCI_EXP_DEVCAP2;
|
||||
|
||||
pci_long_test_and_clear_mask(pos, PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
|
||||
PCI_EXP_DEVCAP2_ATOMIC_COMP64 |
|
||||
PCI_EXP_DEVCAP2_ATOMIC_COMP128);
|
||||
}
|
||||
}
|
||||
|
||||
static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
|
||||
Error **errp)
|
||||
{
|
||||
@@ -1929,6 +2006,8 @@ static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
|
||||
QEMU_PCI_EXP_LNKCAP_MLS(QEMU_PCI_EXP_LNK_2_5GT), ~0);
|
||||
vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
|
||||
}
|
||||
|
||||
vfio_pci_enable_rp_atomics(vdev);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3207,9 +3286,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
||||
}
|
||||
|
||||
if (!pdev->failover_pair_id) {
|
||||
ret = vfio_migration_realize(vbasedev, errp);
|
||||
if (ret) {
|
||||
error_report("%s: Migration disabled", vbasedev->name);
|
||||
if (!vfio_migration_realize(vbasedev, errp)) {
|
||||
goto out_deregister;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3220,6 +3298,9 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
|
||||
return;
|
||||
|
||||
out_deregister:
|
||||
if (vdev->interrupt == VFIO_INT_INTx) {
|
||||
vfio_intx_disable(vdev);
|
||||
}
|
||||
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
|
||||
if (vdev->irqchip_change_notifier.notify) {
|
||||
kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier);
|
||||
@@ -3252,7 +3333,6 @@ static void vfio_instance_finalize(Object *obj)
|
||||
*/
|
||||
vfio_put_device(vdev);
|
||||
vfio_put_group(group);
|
||||
vfio_migration_finalize();
|
||||
}
|
||||
|
||||
static void vfio_exitfn(PCIDevice *pdev)
|
||||
@@ -3270,6 +3350,7 @@ static void vfio_exitfn(PCIDevice *pdev)
|
||||
timer_free(vdev->intx.mmap_timer);
|
||||
}
|
||||
vfio_teardown_msi(vdev);
|
||||
vfio_pci_disable_rp_atomics(vdev);
|
||||
vfio_bars_exit(vdev);
|
||||
vfio_migration_exit(&vdev->vbasedev);
|
||||
}
|
||||
|
||||
@@ -174,6 +174,7 @@ struct VFIOPCIDevice {
|
||||
bool no_vfio_ioeventfd;
|
||||
bool enable_ramfb;
|
||||
bool defer_kvm_irq_routing;
|
||||
bool clear_parent_atomics_on_exit;
|
||||
VFIODisplay *dpy;
|
||||
Notifier irqchip_change_notifier;
|
||||
};
|
||||
|
||||
@@ -93,6 +93,7 @@ void pcie_cap_exit(PCIDevice *dev);
|
||||
int pcie_endpoint_cap_v1_init(PCIDevice *dev, uint8_t offset);
|
||||
void pcie_cap_v1_exit(PCIDevice *dev);
|
||||
uint8_t pcie_cap_get_type(const PCIDevice *dev);
|
||||
uint8_t pcie_cap_get_version(const PCIDevice *dev);
|
||||
void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector);
|
||||
uint8_t pcie_cap_flags_get_vector(PCIDevice *dev);
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ extern VFIOGroupList vfio_group_list;
|
||||
bool vfio_mig_active(void);
|
||||
int vfio_block_multiple_devices_migration(VFIODevice *vbasedev, Error **errp);
|
||||
void vfio_unblock_multiple_devices_migration(void);
|
||||
int vfio_block_giommu_migration(VFIODevice *vbasedev, Error **errp);
|
||||
bool vfio_viommu_preset(VFIODevice *vbasedev);
|
||||
int64_t vfio_mig_bytes_transferred(void);
|
||||
void vfio_reset_bytes_transferred(void);
|
||||
|
||||
@@ -252,8 +252,7 @@ int vfio_spapr_create_window(VFIOContainer *container,
|
||||
int vfio_spapr_remove_window(VFIOContainer *container,
|
||||
hwaddr offset_within_address_space);
|
||||
|
||||
int vfio_migration_realize(VFIODevice *vbasedev, Error **errp);
|
||||
bool vfio_migration_realize(VFIODevice *vbasedev, Error **errp);
|
||||
void vfio_migration_exit(VFIODevice *vbasedev);
|
||||
void vfio_migration_finalize(void);
|
||||
|
||||
#endif /* HW_VFIO_VFIO_COMMON_H */
|
||||
|
||||
@@ -656,6 +656,49 @@ extern "C" {
|
||||
*/
|
||||
#define I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC fourcc_mod_code(INTEL, 12)
|
||||
|
||||
/*
|
||||
* Intel Color Control Surfaces (CCS) for display ver. 14 render compression.
|
||||
*
|
||||
* The main surface is tile4 and at plane index 0, the CCS is linear and
|
||||
* at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in
|
||||
* main surface. In other words, 4 bits in CCS map to a main surface cache
|
||||
* line pair. The main surface pitch is required to be a multiple of four
|
||||
* tile4 widths.
|
||||
*/
|
||||
#define I915_FORMAT_MOD_4_TILED_MTL_RC_CCS fourcc_mod_code(INTEL, 13)
|
||||
|
||||
/*
|
||||
* Intel Color Control Surfaces (CCS) for display ver. 14 media compression
|
||||
*
|
||||
* The main surface is tile4 and at plane index 0, the CCS is linear and
|
||||
* at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in
|
||||
* main surface. In other words, 4 bits in CCS map to a main surface cache
|
||||
* line pair. The main surface pitch is required to be a multiple of four
|
||||
* tile4 widths. For semi-planar formats like NV12, CCS planes follow the
|
||||
* Y and UV planes i.e., planes 0 and 1 are used for Y and UV surfaces,
|
||||
* planes 2 and 3 for the respective CCS.
|
||||
*/
|
||||
#define I915_FORMAT_MOD_4_TILED_MTL_MC_CCS fourcc_mod_code(INTEL, 14)
|
||||
|
||||
/*
|
||||
* Intel Color Control Surface with Clear Color (CCS) for display ver. 14 render
|
||||
* compression.
|
||||
*
|
||||
* The main surface is tile4 and is at plane index 0 whereas CCS is linear
|
||||
* and at index 1. The clear color is stored at index 2, and the pitch should
|
||||
* be ignored. The clear color structure is 256 bits. The first 128 bits
|
||||
* represents Raw Clear Color Red, Green, Blue and Alpha color each represented
|
||||
* by 32 bits. The raw clear color is consumed by the 3d engine and generates
|
||||
* the converted clear color of size 64 bits. The first 32 bits store the Lower
|
||||
* Converted Clear Color value and the next 32 bits store the Higher Converted
|
||||
* Clear Color value when applicable. The Converted Clear Color values are
|
||||
* consumed by the DE. The last 64 bits are used to store Color Discard Enable
|
||||
* and Depth Clear Value Valid which are ignored by the DE. A CCS cache line
|
||||
* corresponds to an area of 4x1 tiles in the main surface. The main surface
|
||||
* pitch is required to be a multiple of 4 tile widths.
|
||||
*/
|
||||
#define I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC fourcc_mod_code(INTEL, 15)
|
||||
|
||||
/*
|
||||
* Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks
|
||||
*
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#define _BITUL(x) (_UL(1) << (x))
|
||||
#define _BITULL(x) (_ULL(1) << (x))
|
||||
|
||||
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
|
||||
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
|
||||
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
||||
|
||||
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
||||
|
||||
@@ -738,6 +738,7 @@
|
||||
#define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */
|
||||
#define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */
|
||||
#define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */
|
||||
#define PCI_EXT_CAP_ID_PL_32GT 0x2A /* Physical Layer 32.0 GT/s */
|
||||
#define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */
|
||||
#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DOE
|
||||
|
||||
|
||||
@@ -47,6 +47,22 @@ struct vhost_vring_addr {
|
||||
uint64_t log_guest_addr;
|
||||
};
|
||||
|
||||
struct vhost_worker_state {
|
||||
/*
|
||||
* For VHOST_NEW_WORKER the kernel will return the new vhost_worker id.
|
||||
* For VHOST_FREE_WORKER this must be set to the id of the vhost_worker
|
||||
* to free.
|
||||
*/
|
||||
unsigned int worker_id;
|
||||
};
|
||||
|
||||
struct vhost_vring_worker {
|
||||
/* vring index */
|
||||
unsigned int index;
|
||||
/* The id of the vhost_worker returned from VHOST_NEW_WORKER */
|
||||
unsigned int worker_id;
|
||||
};
|
||||
|
||||
/* no alignment requirement */
|
||||
struct vhost_iotlb_msg {
|
||||
uint64_t iova;
|
||||
|
||||
@@ -138,11 +138,11 @@ struct virtio_blk_config {
|
||||
|
||||
/* Zoned block device characteristics (if VIRTIO_BLK_F_ZONED) */
|
||||
struct virtio_blk_zoned_characteristics {
|
||||
uint32_t zone_sectors;
|
||||
uint32_t max_open_zones;
|
||||
uint32_t max_active_zones;
|
||||
uint32_t max_append_sectors;
|
||||
uint32_t write_granularity;
|
||||
__virtio32 zone_sectors;
|
||||
__virtio32 max_open_zones;
|
||||
__virtio32 max_active_zones;
|
||||
__virtio32 max_append_sectors;
|
||||
__virtio32 write_granularity;
|
||||
uint8_t model;
|
||||
uint8_t unused2[3];
|
||||
} zoned;
|
||||
@@ -239,11 +239,11 @@ struct virtio_blk_outhdr {
|
||||
*/
|
||||
struct virtio_blk_zone_descriptor {
|
||||
/* Zone capacity */
|
||||
uint64_t z_cap;
|
||||
__virtio64 z_cap;
|
||||
/* The starting sector of the zone */
|
||||
uint64_t z_start;
|
||||
__virtio64 z_start;
|
||||
/* Zone write pointer position in sectors */
|
||||
uint64_t z_wp;
|
||||
__virtio64 z_wp;
|
||||
/* Zone type */
|
||||
uint8_t z_type;
|
||||
/* Zone state */
|
||||
@@ -252,7 +252,7 @@ struct virtio_blk_zone_descriptor {
|
||||
};
|
||||
|
||||
struct virtio_blk_zone_report {
|
||||
uint64_t nr_zones;
|
||||
__virtio64 nr_zones;
|
||||
uint8_t reserved[56];
|
||||
struct virtio_blk_zone_descriptor zones[];
|
||||
};
|
||||
|
||||
@@ -97,6 +97,12 @@
|
||||
*/
|
||||
#define VIRTIO_F_SR_IOV 37
|
||||
|
||||
/*
|
||||
* This feature indicates that the driver passes extra data (besides
|
||||
* identifying the virtqueue) in its device notifications.
|
||||
*/
|
||||
#define VIRTIO_F_NOTIFICATION_DATA 38
|
||||
|
||||
/*
|
||||
* This feature indicates that the driver can reset a queue individually.
|
||||
*/
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#define VIRTIO_NET_F_GUEST_USO6 55 /* Guest can handle USOv6 in. */
|
||||
#define VIRTIO_NET_F_HOST_USO 56 /* Host can handle USO in. */
|
||||
#define VIRTIO_NET_F_HASH_REPORT 57 /* Supports hash report */
|
||||
#define VIRTIO_NET_F_GUEST_HDRLEN 59 /* Guest provides the exact hdr_len value. */
|
||||
#define VIRTIO_NET_F_RSS 60 /* Supports RSS RX steering */
|
||||
#define VIRTIO_NET_F_RSC_EXT 61 /* extended coalescing info */
|
||||
#define VIRTIO_NET_F_STANDBY 62 /* Act as standby for another device
|
||||
|
||||
@@ -1,24 +1 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (C) 2012 ARM Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __ASM_BITSPERLONG_H
|
||||
#define __ASM_BITSPERLONG_H
|
||||
|
||||
#define __BITS_PER_LONG 64
|
||||
|
||||
#include <asm-generic/bitsperlong.h>
|
||||
|
||||
#endif /* __ASM_BITSPERLONG_H */
|
||||
|
||||
@@ -198,6 +198,15 @@ struct kvm_arm_copy_mte_tags {
|
||||
__u64 reserved[2];
|
||||
};
|
||||
|
||||
/*
|
||||
* Counter/Timer offset structure. Describe the virtual/physical offset.
|
||||
* To be used with KVM_ARM_SET_COUNTER_OFFSET.
|
||||
*/
|
||||
struct kvm_arm_counter_offset {
|
||||
__u64 counter_offset;
|
||||
__u64 reserved;
|
||||
};
|
||||
|
||||
#define KVM_ARM_TAGS_TO_GUEST 0
|
||||
#define KVM_ARM_TAGS_FROM_GUEST 1
|
||||
|
||||
@@ -363,6 +372,10 @@ enum {
|
||||
KVM_REG_ARM_VENDOR_HYP_BIT_PTP = 1,
|
||||
};
|
||||
|
||||
/* Device Control API on vm fd */
|
||||
#define KVM_ARM_VM_SMCCC_CTRL 0
|
||||
#define KVM_ARM_VM_SMCCC_FILTER 0
|
||||
|
||||
/* Device Control API: ARM VGIC */
|
||||
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
|
||||
#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
|
||||
@@ -402,6 +415,8 @@ enum {
|
||||
#define KVM_ARM_VCPU_TIMER_CTRL 1
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_HVTIMER 2
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_HPTIMER 3
|
||||
#define KVM_ARM_VCPU_PVTIME_CTRL 2
|
||||
#define KVM_ARM_VCPU_PVTIME_IPA 0
|
||||
|
||||
@@ -458,6 +473,24 @@ enum {
|
||||
/* run->fail_entry.hardware_entry_failure_reason codes. */
|
||||
#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED (1ULL << 0)
|
||||
|
||||
enum kvm_smccc_filter_action {
|
||||
KVM_SMCCC_FILTER_HANDLE = 0,
|
||||
KVM_SMCCC_FILTER_DENY,
|
||||
KVM_SMCCC_FILTER_FWD_TO_USER,
|
||||
|
||||
};
|
||||
|
||||
struct kvm_smccc_filter {
|
||||
__u32 base;
|
||||
__u32 nr_functions;
|
||||
__u8 action;
|
||||
__u8 pad[15];
|
||||
};
|
||||
|
||||
/* arm64-specific KVM_EXIT_HYPERCALL flags */
|
||||
#define KVM_HYPERCALL_EXIT_SMC (1U << 0)
|
||||
#define KVM_HYPERCALL_EXIT_16BIT (1U << 1)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_KVM_H__ */
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
#ifndef __ASM_GENERIC_BITS_PER_LONG
|
||||
#define __ASM_GENERIC_BITS_PER_LONG
|
||||
|
||||
#ifndef __BITS_PER_LONG
|
||||
/*
|
||||
* In order to keep safe and avoid regression, only unify uapi
|
||||
* bitsperlong.h for some archs which are using newer toolchains
|
||||
* that have the definitions of __CHAR_BIT__ and __SIZEOF_LONG__.
|
||||
* See the following link for more info:
|
||||
* https://lore.kernel.org/linux-arch/b9624545-2c80-49a1-ac3c-39264a591f7b@app.fastmail.com/
|
||||
*/
|
||||
#if defined(__CHAR_BIT__) && defined(__SIZEOF_LONG__)
|
||||
#define __BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__)
|
||||
#else
|
||||
/*
|
||||
* There seems to be no way of detecting this automatically from user
|
||||
* space, so 64 bit architectures should override this in their
|
||||
@@ -9,8 +20,8 @@
|
||||
* both 32 and 64 bit user space must not rely on CONFIG_64BIT
|
||||
* to decide it, but rather check a compiler provided macro.
|
||||
*/
|
||||
#ifndef __BITS_PER_LONG
|
||||
#define __BITS_PER_LONG 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_GENERIC_BITS_PER_LONG */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user