mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-vfio-20240522' of https://github.com/legoater/qemu into staging
vfio queue: * Improvement of error reporting during migration * Removed Vendor Specific Capability check on newer machine * Addition of a VFIO migration QAPI event * Changed prototype of routines using an error parameter to return bool * Several cleanups regarding autofree variables # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmZNwDEACgkQUaNDx8/7 # 7KHaYQ/+MUFOiWEiAwJdP8I1DkY6mJV3ZDixKMHLmr8xH6fAkR2htEw6UUcYijcn # Z0wVvcB7A1wetgIAB2EPc2o6JtRD1uEW2pPq3SVpdWO2rWYa4QLvldOiJ8A+Kvss # 0ZugWirgZsM7+ka9TCuysmqWdQD+P6z2RURMSwiPi6QPHwv1Tt69gLSxFeV5WWai # +mS6wUbaU3LSt6yRhORRvFkCss4je3D3YR73ivholGHANxi/7C5T22KwOHrW6Qzf # uk3W/zq1yL1YLXSu6WoKPw0mMCvNtGyKK2oAlhG3Ln1tPYnctNrlfXlApqxEOGl3 # adGtwd6fyg6UTRR+vOXEy1QPCGcHtKWc5SuV5E677JftARJMwzbXrJw9Y9xS2RCQ # oRYS5814k9RdubTxu+/l8NLICMdox7dNy//QLyrIdD7nJKYhFODkV1giWh4NWkt6 # m0T3PGLlUJ/V2ngWQu9Aw150m3lCPEKt+Nv/mGOEFDRu9dv55Vb7oJwr1dBB/n+e # 1lNNpDmV0YipoKYMzrlBwNwxhXGJOtNPwHtw/vZuiy70CXUwo0t4XLMpWbWasxZc # 0yz4O9RLRJEhPtPqv54aLsE2kNY10I8vwHBlhyNgIEsA7eCDduA+65aPBaqIF7z6 # GjvYdixF+vAZFexn0mDi1gtM3Yh60Hiiq1j7kKyyti/q0WUQzIc= # =awMc # -----END PGP SIGNATURE----- # gpg: Signature made Wed 22 May 2024 02:51:45 AM PDT # 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-20240522' of https://github.com/legoater/qemu: (47 commits) vfio/igd: Use g_autofree in vfio_probe_igd_bar4_quirk() vfio: Use g_autofree in all call site of vfio_get_region_info() vfio/pci-quirks: Make vfio_add_*_cap() return bool vfio/pci-quirks: Make vfio_pci_igd_opregion_init() return bool vfio/pci: Use g_autofree for vfio_region_info pointer vfio/pci: Make capability related functions return bool vfio/pci: Make vfio_populate_vga() return bool vfio/pci: Make vfio_intx_enable() return bool vfio/pci: Make vfio_populate_device() return a bool vfio/pci: Make vfio_pci_relocate_msix() and vfio_msix_early_setup() return a bool vfio/pci: Make vfio_intx_enable_kvm() return a bool vfio/ccw: Make vfio_ccw_get_region() return a bool vfio/platform: Make vfio_populate_device() and vfio_base_device_init() return bool vfio/helpers: Make vfio_device_get_name() return bool vfio/helpers: Make vfio_set_irq_signaling() return bool vfio/helpers: Use g_autofree in vfio_set_irq_signaling() vfio/display: Make vfio_display_*() return bool vfio/display: Fix error path in call site of ramfb_setup() backends/iommufd: Make iommufd_backend_*() return bool vfio/cpr: Make vfio_cpr_register_container() return bool ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -2164,6 +2164,7 @@ F: hw/vfio/*
|
||||
F: include/hw/vfio/
|
||||
F: docs/igd-assign.txt
|
||||
F: docs/devel/migration/vfio.rst
|
||||
F: qapi/vfio.json
|
||||
|
||||
vfio-ccw
|
||||
M: Eric Farman <farman@linux.ibm.com>
|
||||
|
||||
+13
-16
@@ -72,24 +72,22 @@ static void iommufd_backend_class_init(ObjectClass *oc, void *data)
|
||||
object_class_property_add_str(oc, "fd", NULL, iommufd_backend_set_fd);
|
||||
}
|
||||
|
||||
int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
|
||||
bool iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
|
||||
{
|
||||
int fd, ret = 0;
|
||||
int fd;
|
||||
|
||||
if (be->owned && !be->users) {
|
||||
fd = qemu_open_old("/dev/iommu", O_RDWR);
|
||||
if (fd < 0) {
|
||||
error_setg_errno(errp, errno, "/dev/iommu opening failed");
|
||||
ret = fd;
|
||||
goto out;
|
||||
return false;
|
||||
}
|
||||
be->fd = fd;
|
||||
}
|
||||
be->users++;
|
||||
out:
|
||||
trace_iommufd_backend_connect(be->fd, be->owned,
|
||||
be->users, ret);
|
||||
return ret;
|
||||
|
||||
trace_iommufd_backend_connect(be->fd, be->owned, be->users);
|
||||
return true;
|
||||
}
|
||||
|
||||
void iommufd_backend_disconnect(IOMMUFDBackend *be)
|
||||
@@ -106,25 +104,24 @@ out:
|
||||
trace_iommufd_backend_disconnect(be->fd, be->users);
|
||||
}
|
||||
|
||||
int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
|
||||
Error **errp)
|
||||
bool iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
|
||||
Error **errp)
|
||||
{
|
||||
int ret, fd = be->fd;
|
||||
int fd = be->fd;
|
||||
struct iommu_ioas_alloc alloc_data = {
|
||||
.size = sizeof(alloc_data),
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
ret = ioctl(fd, IOMMU_IOAS_ALLOC, &alloc_data);
|
||||
if (ret) {
|
||||
if (ioctl(fd, IOMMU_IOAS_ALLOC, &alloc_data)) {
|
||||
error_setg_errno(errp, errno, "Failed to allocate ioas");
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
*ioas_id = alloc_data.out_ioas_id;
|
||||
trace_iommufd_backend_alloc_ioas(fd, *ioas_id, ret);
|
||||
trace_iommufd_backend_alloc_ioas(fd, *ioas_id);
|
||||
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id)
|
||||
|
||||
@@ -7,11 +7,11 @@ dbus_vmstate_loading(const char *id) "id: %s"
|
||||
dbus_vmstate_saving(const char *id) "id: %s"
|
||||
|
||||
# iommufd.c
|
||||
iommufd_backend_connect(int fd, bool owned, uint32_t users, int ret) "fd=%d owned=%d users=%d (%d)"
|
||||
iommufd_backend_connect(int fd, bool owned, uint32_t users) "fd=%d owned=%d users=%d"
|
||||
iommufd_backend_disconnect(int fd, uint32_t users) "fd=%d users=%d"
|
||||
iommu_backend_set_fd(int fd) "pre-opened /dev/iommu fd=%d"
|
||||
iommufd_backend_map_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, void *vaddr, bool readonly, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" addr=%p readonly=%d (%d)"
|
||||
iommufd_backend_unmap_dma_non_exist(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " Unmap nonexistent mapping: iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)"
|
||||
iommufd_backend_unmap_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)"
|
||||
iommufd_backend_alloc_ioas(int iommufd, uint32_t ioas, int ret) " iommufd=%d ioas=%d (%d)"
|
||||
iommufd_backend_alloc_ioas(int iommufd, uint32_t ioas) " iommufd=%d ioas=%d"
|
||||
iommufd_backend_free_id(int iommufd, uint32_t id, int ret) " iommufd=%d id=%d (%d)"
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
GlobalProperty hw_compat_9_0[] = {
|
||||
{"arm-cpu", "backcompat-cntfrq", "true" },
|
||||
{"vfio-pci", "skip-vsc-check", "false" },
|
||||
};
|
||||
const size_t hw_compat_9_0_len = G_N_ELEMENTS(hw_compat_9_0);
|
||||
|
||||
|
||||
+15
-20
@@ -70,14 +70,14 @@ static void vfio_ap_req_notifier_handler(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
static void vfio_ap_register_irq_notifier(VFIOAPDevice *vapdev,
|
||||
static bool 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;
|
||||
g_autofree struct vfio_irq_info *irq_info = NULL;
|
||||
VFIODevice *vdev = &vapdev->vdev;
|
||||
|
||||
switch (irq) {
|
||||
@@ -87,13 +87,13 @@ static void vfio_ap_register_irq_notifier(VFIOAPDevice *vapdev,
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "vfio: Unsupported device irq(%d)", irq);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vdev->num_irqs < irq + 1) {
|
||||
error_setg(errp, "vfio: IRQ %u not available (number of irqs %u)",
|
||||
irq, vdev->num_irqs);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
argsz = sizeof(*irq_info);
|
||||
@@ -104,28 +104,26 @@ static void vfio_ap_register_irq_notifier(VFIOAPDevice *vapdev,
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
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)) {
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vfio_ap_unregister_irq_notifier(VFIOAPDevice *vapdev,
|
||||
@@ -143,8 +141,8 @@ static void vfio_ap_unregister_irq_notifier(VFIOAPDevice *vapdev,
|
||||
return;
|
||||
}
|
||||
|
||||
if (vfio_set_irq_signaling(&vapdev->vdev, irq, 0,
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -156,23 +154,20 @@ static void vfio_ap_unregister_irq_notifier(VFIOAPDevice *vapdev,
|
||||
static void vfio_ap_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
int ret;
|
||||
Error *err = NULL;
|
||||
VFIOAPDevice *vapdev = VFIO_AP_DEVICE(dev);
|
||||
VFIODevice *vbasedev = &vapdev->vdev;
|
||||
|
||||
if (vfio_device_get_name(vbasedev, errp) < 0) {
|
||||
if (!vfio_device_get_name(vbasedev, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = vfio_attach_device(vbasedev->name, vbasedev,
|
||||
&address_space_memory, errp);
|
||||
if (ret) {
|
||||
if (!vfio_attach_device(vbasedev->name, vbasedev,
|
||||
&address_space_memory, errp)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
vfio_ap_register_irq_notifier(vapdev, VFIO_AP_REQ_IRQ_INDEX, &err);
|
||||
if (err) {
|
||||
if (!vfio_ap_register_irq_notifier(vapdev, VFIO_AP_REQ_IRQ_INDEX, &err)) {
|
||||
/*
|
||||
* Report this error, but do not make it a failing condition.
|
||||
* Lack of this IRQ in the host does not prevent normal operation.
|
||||
|
||||
+25
-31
@@ -379,12 +379,12 @@ read_err:
|
||||
css_inject_io_interrupt(sch);
|
||||
}
|
||||
|
||||
static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev,
|
||||
static bool vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev,
|
||||
unsigned int irq,
|
||||
Error **errp)
|
||||
{
|
||||
VFIODevice *vdev = &vcdev->vdev;
|
||||
struct vfio_irq_info *irq_info;
|
||||
g_autofree struct vfio_irq_info *irq_info = NULL;
|
||||
size_t argsz;
|
||||
int fd;
|
||||
EventNotifier *notifier;
|
||||
@@ -405,13 +405,13 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev,
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "vfio: Unsupported device irq(%d)", irq);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vdev->num_irqs < irq + 1) {
|
||||
error_setg(errp, "vfio: IRQ %u not available (number of irqs %u)",
|
||||
irq, vdev->num_irqs);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
argsz = sizeof(*irq_info);
|
||||
@@ -421,27 +421,26 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev,
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
fd = event_notifier_get_fd(notifier);
|
||||
qemu_set_fd_handler(fd, fd_read, NULL, vcdev);
|
||||
|
||||
if (vfio_set_irq_signaling(vdev, irq, 0,
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) {
|
||||
if (!vfio_set_irq_signaling(vdev, irq, 0,
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) {
|
||||
qemu_set_fd_handler(fd, NULL, NULL, vcdev);
|
||||
event_notifier_cleanup(notifier);
|
||||
}
|
||||
|
||||
out_free_info:
|
||||
g_free(irq_info);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev,
|
||||
@@ -465,8 +464,8 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev,
|
||||
return;
|
||||
}
|
||||
|
||||
if (vfio_set_irq_signaling(&vcdev->vdev, irq, 0,
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) {
|
||||
if (!vfio_set_irq_signaling(&vcdev->vdev, irq, 0,
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) {
|
||||
warn_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name);
|
||||
}
|
||||
|
||||
@@ -475,7 +474,7 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev,
|
||||
event_notifier_cleanup(notifier);
|
||||
}
|
||||
|
||||
static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
|
||||
static bool vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
|
||||
{
|
||||
VFIODevice *vdev = &vcdev->vdev;
|
||||
struct vfio_region_info *info;
|
||||
@@ -484,7 +483,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
|
||||
/* Sanity check device */
|
||||
if (!(vdev->flags & VFIO_DEVICE_FLAGS_CCW)) {
|
||||
error_setg(errp, "vfio: Um, this isn't a vfio-ccw device");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -494,13 +493,13 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
|
||||
if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) {
|
||||
error_setg(errp, "vfio: too few regions (%u), expected at least %u",
|
||||
vdev->num_regions, VFIO_CCW_CONFIG_REGION_INDEX + 1);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = vfio_get_region_info(vdev, VFIO_CCW_CONFIG_REGION_INDEX, &info);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, -ret, "vfio: Error getting config info");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
vcdev->io_region_size = info->size;
|
||||
@@ -554,7 +553,7 @@ static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
|
||||
g_free(info);
|
||||
}
|
||||
|
||||
return;
|
||||
return true;
|
||||
|
||||
out_err:
|
||||
g_free(vcdev->crw_region);
|
||||
@@ -562,7 +561,7 @@ out_err:
|
||||
g_free(vcdev->async_cmd_region);
|
||||
g_free(vcdev->io_region);
|
||||
g_free(info);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
|
||||
@@ -580,7 +579,6 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
|
||||
S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
|
||||
VFIODevice *vbasedev = &vcdev->vdev;
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
|
||||
/* Call the class init function for subchannel. */
|
||||
if (cdc->realize) {
|
||||
@@ -590,35 +588,31 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
if (vfio_device_get_name(vbasedev, errp) < 0) {
|
||||
if (!vfio_device_get_name(vbasedev, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = vfio_attach_device(cdev->mdevid, vbasedev,
|
||||
&address_space_memory, errp);
|
||||
if (ret) {
|
||||
if (!vfio_attach_device(cdev->mdevid, vbasedev,
|
||||
&address_space_memory, errp)) {
|
||||
goto out_attach_dev_err;
|
||||
}
|
||||
|
||||
vfio_ccw_get_region(vcdev, &err);
|
||||
if (err) {
|
||||
if (!vfio_ccw_get_region(vcdev, &err)) {
|
||||
goto out_region_err;
|
||||
}
|
||||
|
||||
vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, &err);
|
||||
if (err) {
|
||||
if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, &err)) {
|
||||
goto out_io_notifier_err;
|
||||
}
|
||||
|
||||
if (vcdev->crw_region) {
|
||||
vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, &err);
|
||||
if (err) {
|
||||
if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX,
|
||||
&err)) {
|
||||
goto out_irq_notifier_err;
|
||||
}
|
||||
}
|
||||
|
||||
vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_REQ_IRQ_INDEX, &err);
|
||||
if (err) {
|
||||
if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_REQ_IRQ_INDEX, &err)) {
|
||||
/*
|
||||
* Report this error, but do not make it a failing condition.
|
||||
* Lack of this IRQ in the host does not prevent normal operation.
|
||||
|
||||
+75
-44
@@ -147,10 +147,10 @@ bool vfio_viommu_preset(VFIODevice *vbasedev)
|
||||
return vbasedev->bcontainer->space->as != &address_space_memory;
|
||||
}
|
||||
|
||||
static void vfio_set_migration_error(int err)
|
||||
static void vfio_set_migration_error(int ret)
|
||||
{
|
||||
if (migration_is_setup_or_active()) {
|
||||
migration_file_set_error(err);
|
||||
migration_file_set_error(ret, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,12 +253,13 @@ static bool vfio_listener_skipped_section(MemoryRegionSection *section)
|
||||
|
||||
/* Called with rcu_read_lock held. */
|
||||
static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
||||
ram_addr_t *ram_addr, bool *read_only)
|
||||
ram_addr_t *ram_addr, bool *read_only,
|
||||
Error **errp)
|
||||
{
|
||||
bool ret, mr_has_discard_manager;
|
||||
|
||||
ret = memory_get_xlat_addr(iotlb, vaddr, ram_addr, read_only,
|
||||
&mr_has_discard_manager);
|
||||
&mr_has_discard_manager, errp);
|
||||
if (ret && mr_has_discard_manager) {
|
||||
/*
|
||||
* Malicious VMs might trigger discarding of IOMMU-mapped memory. The
|
||||
@@ -288,6 +289,7 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||
hwaddr iova = iotlb->iova + giommu->iommu_offset;
|
||||
void *vaddr;
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
||||
trace_vfio_iommu_map_notify(iotlb->perm == IOMMU_NONE ? "UNMAP" : "MAP",
|
||||
iova, iova + iotlb->addr_mask);
|
||||
@@ -304,7 +306,8 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||
if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) {
|
||||
bool read_only;
|
||||
|
||||
if (!vfio_get_xlat_addr(iotlb, &vaddr, NULL, &read_only)) {
|
||||
if (!vfio_get_xlat_addr(iotlb, &vaddr, NULL, &read_only, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
@@ -585,7 +588,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
|
||||
return;
|
||||
}
|
||||
|
||||
if (vfio_container_add_section_window(bcontainer, section, &err)) {
|
||||
if (!vfio_container_add_section_window(bcontainer, section, &err)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -1027,7 +1030,8 @@ static void vfio_device_feature_dma_logging_start_destroy(
|
||||
g_free(feature);
|
||||
}
|
||||
|
||||
static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer)
|
||||
static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer,
|
||||
Error **errp)
|
||||
{
|
||||
struct vfio_device_feature *feature;
|
||||
VFIODirtyRanges ranges;
|
||||
@@ -1038,6 +1042,7 @@ static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer)
|
||||
feature = vfio_device_feature_dma_logging_start_create(bcontainer,
|
||||
&ranges);
|
||||
if (!feature) {
|
||||
error_setg_errno(errp, errno, "Failed to prepare DMA logging");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
@@ -1049,8 +1054,8 @@ static int vfio_devices_dma_logging_start(VFIOContainerBase *bcontainer)
|
||||
ret = ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature);
|
||||
if (ret) {
|
||||
ret = -errno;
|
||||
error_report("%s: Failed to start DMA logging, err %d (%s)",
|
||||
vbasedev->name, ret, strerror(errno));
|
||||
error_setg_errno(errp, errno, "%s: Failed to start DMA logging",
|
||||
vbasedev->name);
|
||||
goto out;
|
||||
}
|
||||
vbasedev->dirty_tracking = true;
|
||||
@@ -1069,20 +1074,19 @@ out:
|
||||
static bool vfio_listener_log_global_start(MemoryListener *listener,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
VFIOContainerBase *bcontainer = container_of(listener, VFIOContainerBase,
|
||||
listener);
|
||||
int ret;
|
||||
|
||||
if (vfio_devices_all_device_dirty_tracking(bcontainer)) {
|
||||
ret = vfio_devices_dma_logging_start(bcontainer);
|
||||
ret = vfio_devices_dma_logging_start(bcontainer, errp);
|
||||
} else {
|
||||
ret = vfio_container_set_dirty_page_tracking(bcontainer, true);
|
||||
ret = vfio_container_set_dirty_page_tracking(bcontainer, true, errp);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
error_report("vfio: Could not start dirty page tracking, err: %d (%s)",
|
||||
ret, strerror(-ret));
|
||||
vfio_set_migration_error(ret);
|
||||
error_prepend(errp, "vfio: Could not start dirty page tracking - ");
|
||||
}
|
||||
return !ret;
|
||||
}
|
||||
@@ -1091,17 +1095,20 @@ static void vfio_listener_log_global_stop(MemoryListener *listener)
|
||||
{
|
||||
VFIOContainerBase *bcontainer = container_of(listener, VFIOContainerBase,
|
||||
listener);
|
||||
Error *local_err = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (vfio_devices_all_device_dirty_tracking(bcontainer)) {
|
||||
vfio_devices_dma_logging_stop(bcontainer);
|
||||
} else {
|
||||
ret = vfio_container_set_dirty_page_tracking(bcontainer, false);
|
||||
ret = vfio_container_set_dirty_page_tracking(bcontainer, false,
|
||||
&local_err);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
error_report("vfio: Could not stop dirty page tracking, err: %d (%s)",
|
||||
ret, strerror(-ret));
|
||||
error_prepend(&local_err,
|
||||
"vfio: Could not stop dirty page tracking - ");
|
||||
error_report_err(local_err);
|
||||
vfio_set_migration_error(ret);
|
||||
}
|
||||
}
|
||||
@@ -1133,8 +1140,7 @@ static int vfio_device_dma_logging_report(VFIODevice *vbasedev, hwaddr iova,
|
||||
}
|
||||
|
||||
int vfio_devices_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
|
||||
VFIOBitmap *vbmap, hwaddr iova,
|
||||
hwaddr size)
|
||||
VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp)
|
||||
{
|
||||
VFIODevice *vbasedev;
|
||||
int ret;
|
||||
@@ -1143,10 +1149,10 @@ int vfio_devices_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
|
||||
ret = vfio_device_dma_logging_report(vbasedev, iova, size,
|
||||
vbmap->bitmap);
|
||||
if (ret) {
|
||||
error_report("%s: Failed to get DMA logging report, iova: "
|
||||
"0x%" HWADDR_PRIx ", size: 0x%" HWADDR_PRIx
|
||||
", err: %d (%s)",
|
||||
vbasedev->name, iova, size, ret, strerror(-ret));
|
||||
error_setg_errno(errp, -ret,
|
||||
"%s: Failed to get DMA logging report, iova: "
|
||||
"0x%" HWADDR_PRIx ", size: 0x%" HWADDR_PRIx,
|
||||
vbasedev->name, iova, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1156,7 +1162,7 @@ int vfio_devices_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
|
||||
}
|
||||
|
||||
int vfio_get_dirty_bitmap(const VFIOContainerBase *bcontainer, uint64_t iova,
|
||||
uint64_t size, ram_addr_t ram_addr)
|
||||
uint64_t size, ram_addr_t ram_addr, Error **errp)
|
||||
{
|
||||
bool all_device_dirty_tracking =
|
||||
vfio_devices_all_device_dirty_tracking(bcontainer);
|
||||
@@ -1173,13 +1179,17 @@ int vfio_get_dirty_bitmap(const VFIOContainerBase *bcontainer, uint64_t iova,
|
||||
|
||||
ret = vfio_bitmap_alloc(&vbmap, size);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, -ret,
|
||||
"Failed to allocate dirty tracking bitmap");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (all_device_dirty_tracking) {
|
||||
ret = vfio_devices_query_dirty_bitmap(bcontainer, &vbmap, iova, size);
|
||||
ret = vfio_devices_query_dirty_bitmap(bcontainer, &vbmap, iova, size,
|
||||
errp);
|
||||
} else {
|
||||
ret = vfio_container_query_dirty_bitmap(bcontainer, &vbmap, iova, size);
|
||||
ret = vfio_container_query_dirty_bitmap(bcontainer, &vbmap, iova, size,
|
||||
errp);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
@@ -1209,6 +1219,7 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||
VFIOContainerBase *bcontainer = giommu->bcontainer;
|
||||
hwaddr iova = iotlb->iova + giommu->iommu_offset;
|
||||
ram_addr_t translated_addr;
|
||||
Error *local_err = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask);
|
||||
@@ -1220,16 +1231,22 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
if (vfio_get_xlat_addr(iotlb, NULL, &translated_addr, NULL)) {
|
||||
ret = vfio_get_dirty_bitmap(bcontainer, iova, iotlb->addr_mask + 1,
|
||||
translated_addr);
|
||||
if (ret) {
|
||||
error_report("vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx", "
|
||||
"0x%"HWADDR_PRIx") = %d (%s)",
|
||||
bcontainer, iova, iotlb->addr_mask + 1, ret,
|
||||
strerror(-ret));
|
||||
}
|
||||
if (!vfio_get_xlat_addr(iotlb, NULL, &translated_addr, NULL, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = vfio_get_dirty_bitmap(bcontainer, iova, iotlb->addr_mask + 1,
|
||||
translated_addr, &local_err);
|
||||
if (ret) {
|
||||
error_prepend(&local_err,
|
||||
"vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx", "
|
||||
"0x%"HWADDR_PRIx") failed - ", bcontainer, iova,
|
||||
iotlb->addr_mask + 1);
|
||||
error_report_err(local_err);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
out:
|
||||
@@ -1246,12 +1263,19 @@ static int vfio_ram_discard_get_dirty_bitmap(MemoryRegionSection *section,
|
||||
const ram_addr_t ram_addr = memory_region_get_ram_addr(section->mr) +
|
||||
section->offset_within_region;
|
||||
VFIORamDiscardListener *vrdl = opaque;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Sync the whole mapped region (spanning multiple individual mappings)
|
||||
* in one go.
|
||||
*/
|
||||
return vfio_get_dirty_bitmap(vrdl->bcontainer, iova, size, ram_addr);
|
||||
ret = vfio_get_dirty_bitmap(vrdl->bcontainer, iova, size, ram_addr,
|
||||
&local_err);
|
||||
if (ret) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1283,7 +1307,7 @@ vfio_sync_ram_discard_listener_dirty_bitmap(VFIOContainerBase *bcontainer,
|
||||
}
|
||||
|
||||
static int vfio_sync_dirty_bitmap(VFIOContainerBase *bcontainer,
|
||||
MemoryRegionSection *section)
|
||||
MemoryRegionSection *section, Error **errp)
|
||||
{
|
||||
ram_addr_t ram_addr;
|
||||
|
||||
@@ -1314,7 +1338,14 @@ static int vfio_sync_dirty_bitmap(VFIOContainerBase *bcontainer,
|
||||
}
|
||||
return 0;
|
||||
} else if (memory_region_has_ram_discard_manager(section->mr)) {
|
||||
return vfio_sync_ram_discard_listener_dirty_bitmap(bcontainer, section);
|
||||
int ret;
|
||||
|
||||
ret = vfio_sync_ram_discard_listener_dirty_bitmap(bcontainer, section);
|
||||
if (ret) {
|
||||
error_setg(errp,
|
||||
"Failed to sync dirty bitmap with RAM discard listener");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ram_addr = memory_region_get_ram_addr(section->mr) +
|
||||
@@ -1322,7 +1353,7 @@ static int vfio_sync_dirty_bitmap(VFIOContainerBase *bcontainer,
|
||||
|
||||
return vfio_get_dirty_bitmap(bcontainer,
|
||||
REAL_HOST_PAGE_ALIGN(section->offset_within_address_space),
|
||||
int128_get64(section->size), ram_addr);
|
||||
int128_get64(section->size), ram_addr, errp);
|
||||
}
|
||||
|
||||
static void vfio_listener_log_sync(MemoryListener *listener,
|
||||
@@ -1331,16 +1362,16 @@ static void vfio_listener_log_sync(MemoryListener *listener,
|
||||
VFIOContainerBase *bcontainer = container_of(listener, VFIOContainerBase,
|
||||
listener);
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (vfio_listener_skipped_section(section)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vfio_devices_all_dirty_tracking(bcontainer)) {
|
||||
ret = vfio_sync_dirty_bitmap(bcontainer, section);
|
||||
ret = vfio_sync_dirty_bitmap(bcontainer, section, &local_err);
|
||||
if (ret) {
|
||||
error_report("vfio: Failed to sync dirty bitmap, err: %d (%s)", ret,
|
||||
strerror(-ret));
|
||||
error_report_err(local_err);
|
||||
vfio_set_migration_error(ret);
|
||||
}
|
||||
}
|
||||
@@ -1492,8 +1523,8 @@ retry:
|
||||
return info;
|
||||
}
|
||||
|
||||
int vfio_attach_device(char *name, VFIODevice *vbasedev,
|
||||
AddressSpace *as, Error **errp)
|
||||
bool vfio_attach_device(char *name, VFIODevice *vbasedev,
|
||||
AddressSpace *as, Error **errp)
|
||||
{
|
||||
const VFIOIOMMUClass *ops =
|
||||
VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_LEGACY));
|
||||
|
||||
@@ -31,12 +31,12 @@ int vfio_container_dma_unmap(VFIOContainerBase *bcontainer,
|
||||
return bcontainer->ops->dma_unmap(bcontainer, iova, size, iotlb);
|
||||
}
|
||||
|
||||
int vfio_container_add_section_window(VFIOContainerBase *bcontainer,
|
||||
MemoryRegionSection *section,
|
||||
Error **errp)
|
||||
bool vfio_container_add_section_window(VFIOContainerBase *bcontainer,
|
||||
MemoryRegionSection *section,
|
||||
Error **errp)
|
||||
{
|
||||
if (!bcontainer->ops->add_window) {
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return bcontainer->ops->add_window(bcontainer, section, errp);
|
||||
@@ -53,22 +53,22 @@ void vfio_container_del_section_window(VFIOContainerBase *bcontainer,
|
||||
}
|
||||
|
||||
int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer,
|
||||
bool start)
|
||||
bool start, Error **errp)
|
||||
{
|
||||
if (!bcontainer->dirty_pages_supported) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_assert(bcontainer->ops->set_dirty_page_tracking);
|
||||
return bcontainer->ops->set_dirty_page_tracking(bcontainer, start);
|
||||
return bcontainer->ops->set_dirty_page_tracking(bcontainer, start, errp);
|
||||
}
|
||||
|
||||
int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
|
||||
VFIOBitmap *vbmap,
|
||||
hwaddr iova, hwaddr size)
|
||||
VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp)
|
||||
{
|
||||
g_assert(bcontainer->ops->query_dirty_bitmap);
|
||||
return bcontainer->ops->query_dirty_bitmap(bcontainer, vbmap, iova, size);
|
||||
return bcontainer->ops->query_dirty_bitmap(bcontainer, vbmap, iova, size,
|
||||
errp);
|
||||
}
|
||||
|
||||
void vfio_container_init(VFIOContainerBase *bcontainer, VFIOAddressSpace *space,
|
||||
|
||||
+47
-54
@@ -130,6 +130,7 @@ static int vfio_legacy_dma_unmap(const VFIOContainerBase *bcontainer,
|
||||
};
|
||||
bool need_dirty_sync = false;
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (iotlb && vfio_devices_all_running_and_mig_active(bcontainer)) {
|
||||
if (!vfio_devices_all_device_dirty_tracking(bcontainer) &&
|
||||
@@ -165,8 +166,9 @@ static int vfio_legacy_dma_unmap(const VFIOContainerBase *bcontainer,
|
||||
|
||||
if (need_dirty_sync) {
|
||||
ret = vfio_get_dirty_bitmap(bcontainer, iova, size,
|
||||
iotlb->translated_addr);
|
||||
iotlb->translated_addr, &local_err);
|
||||
if (ret) {
|
||||
error_report_err(local_err);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -209,7 +211,7 @@ static int vfio_legacy_dma_map(const VFIOContainerBase *bcontainer, hwaddr iova,
|
||||
|
||||
static int
|
||||
vfio_legacy_set_dirty_page_tracking(const VFIOContainerBase *bcontainer,
|
||||
bool start)
|
||||
bool start, Error **errp)
|
||||
{
|
||||
const VFIOContainer *container = container_of(bcontainer, VFIOContainer,
|
||||
bcontainer);
|
||||
@@ -227,16 +229,15 @@ vfio_legacy_set_dirty_page_tracking(const VFIOContainerBase *bcontainer,
|
||||
ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, &dirty);
|
||||
if (ret) {
|
||||
ret = -errno;
|
||||
error_report("Failed to set dirty tracking flag 0x%x errno: %d",
|
||||
dirty.flags, errno);
|
||||
error_setg_errno(errp, errno, "Failed to set dirty tracking flag 0x%x",
|
||||
dirty.flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vfio_legacy_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
|
||||
VFIOBitmap *vbmap,
|
||||
hwaddr iova, hwaddr size)
|
||||
VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp)
|
||||
{
|
||||
const VFIOContainer *container = container_of(bcontainer, VFIOContainer,
|
||||
bcontainer);
|
||||
@@ -264,9 +265,10 @@ static int vfio_legacy_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
|
||||
ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, dbitmap);
|
||||
if (ret) {
|
||||
ret = -errno;
|
||||
error_report("Failed to get dirty bitmap for iova: 0x%"PRIx64
|
||||
" size: 0x%"PRIx64" err: %d", (uint64_t)range->iova,
|
||||
(uint64_t)range->size, errno);
|
||||
error_setg_errno(errp, errno,
|
||||
"Failed to get dirty bitmap for iova: 0x%"PRIx64
|
||||
" size: 0x%"PRIx64, (uint64_t)range->iova,
|
||||
(uint64_t)range->size);
|
||||
}
|
||||
|
||||
g_free(dbitmap);
|
||||
@@ -391,21 +393,20 @@ static const VFIOIOMMUClass *vfio_get_iommu_class(int iommu_type, Error **errp)
|
||||
return VFIO_IOMMU_CLASS(klass);
|
||||
}
|
||||
|
||||
static int vfio_set_iommu(VFIOContainer *container, int group_fd,
|
||||
VFIOAddressSpace *space, Error **errp)
|
||||
static bool vfio_set_iommu(VFIOContainer *container, int group_fd,
|
||||
VFIOAddressSpace *space, Error **errp)
|
||||
{
|
||||
int iommu_type, ret;
|
||||
int iommu_type;
|
||||
const VFIOIOMMUClass *vioc;
|
||||
|
||||
iommu_type = vfio_get_iommu_type(container, errp);
|
||||
if (iommu_type < 0) {
|
||||
return iommu_type;
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = ioctl(group_fd, VFIO_GROUP_SET_CONTAINER, &container->fd);
|
||||
if (ret) {
|
||||
if (ioctl(group_fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) {
|
||||
error_setg_errno(errp, errno, "Failed to set group container");
|
||||
return -errno;
|
||||
return false;
|
||||
}
|
||||
|
||||
while (ioctl(container->fd, VFIO_SET_IOMMU, iommu_type)) {
|
||||
@@ -420,7 +421,7 @@ static int vfio_set_iommu(VFIOContainer *container, int group_fd,
|
||||
continue;
|
||||
}
|
||||
error_setg_errno(errp, errno, "Failed to set iommu for container");
|
||||
return -errno;
|
||||
return false;
|
||||
}
|
||||
|
||||
container->iommu_type = iommu_type;
|
||||
@@ -428,11 +429,11 @@ static int vfio_set_iommu(VFIOContainer *container, int group_fd,
|
||||
vioc = vfio_get_iommu_class(iommu_type, errp);
|
||||
if (!vioc) {
|
||||
error_setg(errp, "No available IOMMU models");
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
vfio_container_init(&container->bcontainer, space, vioc);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int vfio_get_iommu_info(VFIOContainer *container,
|
||||
@@ -505,7 +506,7 @@ static void vfio_get_iommu_info_migration(VFIOContainer *container,
|
||||
}
|
||||
}
|
||||
|
||||
static int vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp)
|
||||
static bool vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp)
|
||||
{
|
||||
VFIOContainer *container = container_of(bcontainer, VFIOContainer,
|
||||
bcontainer);
|
||||
@@ -515,7 +516,7 @@ static int vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp)
|
||||
ret = vfio_get_iommu_info(container, &info);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, -ret, "Failed to get VFIO IOMMU info");
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info->flags & VFIO_IOMMU_INFO_PGSIZES) {
|
||||
@@ -531,11 +532,11 @@ static int vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp)
|
||||
vfio_get_info_iova_range(info, bcontainer);
|
||||
|
||||
vfio_get_iommu_info_migration(container, info);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
Error **errp)
|
||||
static bool vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
Error **errp)
|
||||
{
|
||||
VFIOContainer *container;
|
||||
VFIOContainerBase *bcontainer;
|
||||
@@ -587,19 +588,18 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
error_report("vfio: error disconnecting group %d from"
|
||||
" container", group->groupid);
|
||||
}
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
group->container = container;
|
||||
QLIST_INSERT_HEAD(&container->group_list, group, container_next);
|
||||
vfio_kvm_device_add_group(group);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fd = qemu_open_old("/dev/vfio/vfio", O_RDWR);
|
||||
if (fd < 0) {
|
||||
error_setg_errno(errp, errno, "failed to open /dev/vfio/vfio");
|
||||
ret = -errno;
|
||||
goto put_space_exit;
|
||||
}
|
||||
|
||||
@@ -607,7 +607,6 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
if (ret != VFIO_API_VERSION) {
|
||||
error_setg(errp, "supported vfio version: %d, "
|
||||
"reported version: %d", VFIO_API_VERSION, ret);
|
||||
ret = -EINVAL;
|
||||
goto close_fd_exit;
|
||||
}
|
||||
|
||||
@@ -615,13 +614,11 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
container->fd = fd;
|
||||
bcontainer = &container->bcontainer;
|
||||
|
||||
ret = vfio_set_iommu(container, group->fd, space, errp);
|
||||
if (ret) {
|
||||
if (!vfio_set_iommu(container, group->fd, space, errp)) {
|
||||
goto free_container_exit;
|
||||
}
|
||||
|
||||
ret = vfio_cpr_register_container(bcontainer, errp);
|
||||
if (ret) {
|
||||
if (!vfio_cpr_register_container(bcontainer, errp)) {
|
||||
goto free_container_exit;
|
||||
}
|
||||
|
||||
@@ -633,8 +630,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
|
||||
assert(bcontainer->ops->setup);
|
||||
|
||||
ret = bcontainer->ops->setup(bcontainer, errp);
|
||||
if (ret) {
|
||||
if (!bcontainer->ops->setup(bcontainer, errp)) {
|
||||
goto enable_discards_exit;
|
||||
}
|
||||
|
||||
@@ -650,7 +646,6 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
memory_listener_register(&bcontainer->listener, bcontainer->space->as);
|
||||
|
||||
if (bcontainer->error) {
|
||||
ret = -1;
|
||||
error_propagate_prepend(errp, bcontainer->error,
|
||||
"memory listener initialization failed: ");
|
||||
goto listener_release_exit;
|
||||
@@ -658,7 +653,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
|
||||
|
||||
bcontainer->initialized = true;
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
listener_release_exit:
|
||||
QLIST_REMOVE(group, container_next);
|
||||
QLIST_REMOVE(bcontainer, next);
|
||||
@@ -683,7 +678,7 @@ close_fd_exit:
|
||||
put_space_exit:
|
||||
vfio_put_address_space(space);
|
||||
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void vfio_disconnect_container(VFIOGroup *group)
|
||||
@@ -770,7 +765,7 @@ static VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp)
|
||||
group->groupid = groupid;
|
||||
QLIST_INIT(&group->device_list);
|
||||
|
||||
if (vfio_connect_container(group, as, errp)) {
|
||||
if (!vfio_connect_container(group, as, errp)) {
|
||||
error_prepend(errp, "failed to setup container for group %d: ",
|
||||
groupid);
|
||||
goto close_fd_exit;
|
||||
@@ -806,8 +801,8 @@ static void vfio_put_group(VFIOGroup *group)
|
||||
g_free(group);
|
||||
}
|
||||
|
||||
static int vfio_get_device(VFIOGroup *group, const char *name,
|
||||
VFIODevice *vbasedev, Error **errp)
|
||||
static bool vfio_get_device(VFIOGroup *group, const char *name,
|
||||
VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
g_autofree struct vfio_device_info *info = NULL;
|
||||
int fd;
|
||||
@@ -819,14 +814,14 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
|
||||
error_append_hint(errp,
|
||||
"Verify all devices in group %d are bound to vfio-<bus> "
|
||||
"or pci-stub and not already in use\n", group->groupid);
|
||||
return fd;
|
||||
return false;
|
||||
}
|
||||
|
||||
info = vfio_get_device_info(fd);
|
||||
if (!info) {
|
||||
error_setg_errno(errp, errno, "error getting device info");
|
||||
close(fd);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -841,7 +836,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
|
||||
error_setg(errp, "Inconsistent setting of support for discarding "
|
||||
"RAM (e.g., balloon) within group");
|
||||
close(fd);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!group->ram_block_discard_allowed) {
|
||||
@@ -862,7 +857,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
|
||||
|
||||
vbasedev->reset_works = !!(info->flags & VFIO_DEVICE_FLAGS_RESET);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vfio_put_base_device(VFIODevice *vbasedev)
|
||||
@@ -908,37 +903,35 @@ static int vfio_device_groupid(VFIODevice *vbasedev, Error **errp)
|
||||
* @name and @vbasedev->name are likely to be different depending
|
||||
* on the type of the device, hence the need for passing @name
|
||||
*/
|
||||
static int vfio_legacy_attach_device(const char *name, VFIODevice *vbasedev,
|
||||
AddressSpace *as, Error **errp)
|
||||
static bool vfio_legacy_attach_device(const char *name, VFIODevice *vbasedev,
|
||||
AddressSpace *as, Error **errp)
|
||||
{
|
||||
int groupid = vfio_device_groupid(vbasedev, errp);
|
||||
VFIODevice *vbasedev_iter;
|
||||
VFIOGroup *group;
|
||||
VFIOContainerBase *bcontainer;
|
||||
int ret;
|
||||
|
||||
if (groupid < 0) {
|
||||
return groupid;
|
||||
return false;
|
||||
}
|
||||
|
||||
trace_vfio_attach_device(vbasedev->name, groupid);
|
||||
|
||||
group = vfio_get_group(groupid, as, errp);
|
||||
if (!group) {
|
||||
return -ENOENT;
|
||||
return false;
|
||||
}
|
||||
|
||||
QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
|
||||
if (strcmp(vbasedev_iter->name, vbasedev->name) == 0) {
|
||||
error_setg(errp, "device is already attached");
|
||||
vfio_put_group(group);
|
||||
return -EBUSY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ret = vfio_get_device(group, name, vbasedev, errp);
|
||||
if (ret) {
|
||||
if (!vfio_get_device(group, name, vbasedev, errp)) {
|
||||
vfio_put_group(group);
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
bcontainer = &group->container->bcontainer;
|
||||
@@ -946,7 +939,7 @@ static int vfio_legacy_attach_device(const char *name, VFIODevice *vbasedev,
|
||||
QLIST_INSERT_HEAD(&bcontainer->device_list, vbasedev, container_next);
|
||||
QLIST_INSERT_HEAD(&vfio_device_list, vbasedev, global_next);
|
||||
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vfio_legacy_detach_device(VFIODevice *vbasedev)
|
||||
|
||||
+2
-2
@@ -25,12 +25,12 @@ static int vfio_cpr_reboot_notifier(NotifierWithReturn *notifier,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfio_cpr_register_container(VFIOContainerBase *bcontainer, Error **errp)
|
||||
bool vfio_cpr_register_container(VFIOContainerBase *bcontainer, Error **errp)
|
||||
{
|
||||
migration_add_notifier_mode(&bcontainer->cpr_reboot_notifier,
|
||||
vfio_cpr_reboot_notifier,
|
||||
MIG_MODE_CPR_REBOOT);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void vfio_cpr_unregister_container(VFIOContainerBase *bcontainer)
|
||||
|
||||
+14
-8
@@ -348,11 +348,11 @@ static const GraphicHwOps vfio_display_dmabuf_ops = {
|
||||
.ui_info = vfio_display_edid_ui_info,
|
||||
};
|
||||
|
||||
static int vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
static bool vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
{
|
||||
if (!display_opengl) {
|
||||
error_setg(errp, "vfio-display-dmabuf: opengl not available");
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
vdev->dpy = g_new0(VFIODisplay, 1);
|
||||
@@ -361,9 +361,12 @@ static int vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
vdev);
|
||||
if (vdev->enable_ramfb) {
|
||||
vdev->dpy->ramfb = ramfb_setup(errp);
|
||||
if (!vdev->dpy->ramfb) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
vfio_display_edid_init(vdev);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vfio_display_dmabuf_exit(VFIODisplay *dpy)
|
||||
@@ -480,7 +483,7 @@ static const GraphicHwOps vfio_display_region_ops = {
|
||||
.gfx_update = vfio_display_region_update,
|
||||
};
|
||||
|
||||
static int vfio_display_region_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
static bool vfio_display_region_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
{
|
||||
vdev->dpy = g_new0(VFIODisplay, 1);
|
||||
vdev->dpy->con = graphic_console_init(DEVICE(vdev), 0,
|
||||
@@ -488,8 +491,11 @@ static int vfio_display_region_init(VFIOPCIDevice *vdev, Error **errp)
|
||||
vdev);
|
||||
if (vdev->enable_ramfb) {
|
||||
vdev->dpy->ramfb = ramfb_setup(errp);
|
||||
if (!vdev->dpy->ramfb) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vfio_display_region_exit(VFIODisplay *dpy)
|
||||
@@ -504,7 +510,7 @@ static void vfio_display_region_exit(VFIODisplay *dpy)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int vfio_display_probe(VFIOPCIDevice *vdev, Error **errp)
|
||||
bool vfio_display_probe(VFIOPCIDevice *vdev, Error **errp)
|
||||
{
|
||||
struct vfio_device_gfx_plane_info probe;
|
||||
int ret;
|
||||
@@ -527,11 +533,11 @@ int vfio_display_probe(VFIOPCIDevice *vdev, Error **errp)
|
||||
|
||||
if (vdev->display == ON_OFF_AUTO_AUTO) {
|
||||
/* not an error in automatic mode */
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
error_setg(errp, "vfio: device doesn't support any (known) display method");
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
void vfio_display_finalize(VFIOPCIDevice *vdev)
|
||||
|
||||
+14
-22
@@ -107,12 +107,12 @@ static const char *index_to_str(VFIODevice *vbasedev, int index)
|
||||
}
|
||||
}
|
||||
|
||||
int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex,
|
||||
int action, int fd, Error **errp)
|
||||
bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex,
|
||||
int action, int fd, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
struct vfio_irq_set *irq_set;
|
||||
int argsz, ret = 0;
|
||||
g_autofree struct vfio_irq_set *irq_set = NULL;
|
||||
int argsz;
|
||||
const char *name;
|
||||
int32_t *pfd;
|
||||
|
||||
@@ -127,16 +127,11 @@ int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex,
|
||||
pfd = (int32_t *)&irq_set->data;
|
||||
*pfd = fd;
|
||||
|
||||
if (ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
|
||||
ret = -errno;
|
||||
}
|
||||
g_free(irq_set);
|
||||
|
||||
if (!ret) {
|
||||
return 0;
|
||||
if (!ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
error_setg_errno(errp, -ret, "VFIO_DEVICE_SET_IRQS failure");
|
||||
error_setg_errno(errp, errno, "VFIO_DEVICE_SET_IRQS failure");
|
||||
|
||||
name = index_to_str(vbasedev, index);
|
||||
if (name) {
|
||||
@@ -147,7 +142,7 @@ int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex,
|
||||
error_prepend(errp,
|
||||
"Failed to %s %s eventfd signaling for interrupt ",
|
||||
fd < 0 ? "tear down" : "set up", action_to_str(action));
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -348,7 +343,7 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
|
||||
int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
|
||||
int index, const char *name)
|
||||
{
|
||||
struct vfio_region_info *info;
|
||||
g_autofree struct vfio_region_info *info = NULL;
|
||||
int ret;
|
||||
|
||||
ret = vfio_get_region_info(vbasedev, index, &info);
|
||||
@@ -381,8 +376,6 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
|
||||
}
|
||||
}
|
||||
|
||||
g_free(info);
|
||||
|
||||
trace_vfio_region_setup(vbasedev->name, index, name,
|
||||
region->flags, region->fd_offset, region->size);
|
||||
return 0;
|
||||
@@ -599,20 +592,19 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
|
||||
|
||||
bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type)
|
||||
{
|
||||
struct vfio_region_info *info = NULL;
|
||||
g_autofree struct vfio_region_info *info = NULL;
|
||||
bool ret = false;
|
||||
|
||||
if (!vfio_get_region_info(vbasedev, region, &info)) {
|
||||
if (vfio_get_region_info_cap(info, cap_type)) {
|
||||
ret = true;
|
||||
}
|
||||
g_free(info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfio_device_get_name(VFIODevice *vbasedev, Error **errp)
|
||||
bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
struct stat st;
|
||||
@@ -621,7 +613,7 @@ int vfio_device_get_name(VFIODevice *vbasedev, Error **errp)
|
||||
if (stat(vbasedev->sysfsdev, &st) < 0) {
|
||||
error_setg_errno(errp, errno, "no such host device");
|
||||
error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->sysfsdev);
|
||||
return -errno;
|
||||
return false;
|
||||
}
|
||||
/* User may specify a name, e.g: VFIO platform device */
|
||||
if (!vbasedev->name) {
|
||||
@@ -630,7 +622,7 @@ int vfio_device_get_name(VFIODevice *vbasedev, Error **errp)
|
||||
} else {
|
||||
if (!vbasedev->iommufd) {
|
||||
error_setg(errp, "Use FD passing only with iommufd backend");
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Give a name with fd so any function printing out vbasedev->name
|
||||
@@ -641,7 +633,7 @@ int vfio_device_get_name(VFIODevice *vbasedev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp)
|
||||
|
||||
+15
-20
@@ -367,8 +367,10 @@ static const MemoryRegionOps vfio_igd_index_quirk = {
|
||||
|
||||
void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
{
|
||||
struct vfio_region_info *rom = NULL, *opregion = NULL,
|
||||
*host = NULL, *lpc = NULL;
|
||||
g_autofree struct vfio_region_info *rom = NULL;
|
||||
g_autofree struct vfio_region_info *opregion = NULL;
|
||||
g_autofree struct vfio_region_info *host = NULL;
|
||||
g_autofree struct vfio_region_info *lpc = NULL;
|
||||
VFIOQuirk *quirk;
|
||||
VFIOIGDQuirk *igd;
|
||||
PCIDevice *lpc_bridge;
|
||||
@@ -426,7 +428,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
if ((ret || !rom->size) && !vdev->pdev.romfile) {
|
||||
error_report("IGD device %s has no ROM, legacy mode disabled",
|
||||
vdev->vbasedev.name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -437,7 +439,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
error_report("IGD device %s hotplugged, ROM disabled, "
|
||||
"legacy mode disabled", vdev->vbasedev.name);
|
||||
vdev->rom_read_failed = true;
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -450,7 +452,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
if (ret) {
|
||||
error_report("IGD device %s does not support OpRegion access,"
|
||||
"legacy mode disabled", vdev->vbasedev.name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = vfio_get_dev_region_info(&vdev->vbasedev,
|
||||
@@ -459,7 +461,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
if (ret) {
|
||||
error_report("IGD device %s does not support host bridge access,"
|
||||
"legacy mode disabled", vdev->vbasedev.name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = vfio_get_dev_region_info(&vdev->vbasedev,
|
||||
@@ -468,7 +470,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
if (ret) {
|
||||
error_report("IGD device %s does not support LPC bridge access,"
|
||||
"legacy mode disabled", vdev->vbasedev.name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, 4);
|
||||
@@ -478,11 +480,11 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
* try to enable it. Probably shouldn't be using legacy mode without VGA,
|
||||
* but also no point in us enabling VGA if disabled in hardware.
|
||||
*/
|
||||
if (!(gmch & 0x2) && !vdev->vga && vfio_populate_vga(vdev, &err)) {
|
||||
if (!(gmch & 0x2) && !vdev->vga && !vfio_populate_vga(vdev, &err)) {
|
||||
error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
|
||||
error_report("IGD device %s failed to enable VGA access, "
|
||||
"legacy mode disabled", vdev->vbasedev.name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create our LPC/ISA bridge */
|
||||
@@ -490,7 +492,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
if (ret) {
|
||||
error_report("IGD device %s failed to create LPC bridge, "
|
||||
"legacy mode disabled", vdev->vbasedev.name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stuff some host values into the VM PCI host bridge */
|
||||
@@ -498,15 +500,14 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
if (ret) {
|
||||
error_report("IGD device %s failed to modify host bridge, "
|
||||
"legacy mode disabled", vdev->vbasedev.name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setup OpRegion access */
|
||||
ret = vfio_pci_igd_opregion_init(vdev, opregion, &err);
|
||||
if (ret) {
|
||||
if (!vfio_pci_igd_opregion_init(vdev, opregion, &err)) {
|
||||
error_append_hint(&err, "IGD legacy mode disabled\n");
|
||||
error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setup our quirk to munge GTT addresses to the VM allocated buffer */
|
||||
@@ -608,10 +609,4 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
}
|
||||
|
||||
trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, ggms_mb + gms_mb);
|
||||
|
||||
out:
|
||||
g_free(rom);
|
||||
g_free(opregion);
|
||||
g_free(host);
|
||||
g_free(lpc);
|
||||
}
|
||||
|
||||
+47
-62
@@ -49,9 +49,9 @@ static int iommufd_cdev_unmap(const VFIOContainerBase *bcontainer,
|
||||
container->ioas_id, iova, size);
|
||||
}
|
||||
|
||||
static int iommufd_cdev_kvm_device_add(VFIODevice *vbasedev, Error **errp)
|
||||
static bool iommufd_cdev_kvm_device_add(VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
return vfio_kvm_device_add_fd(vbasedev->fd, errp);
|
||||
return !vfio_kvm_device_add_fd(vbasedev->fd, errp);
|
||||
}
|
||||
|
||||
static void iommufd_cdev_kvm_device_del(VFIODevice *vbasedev)
|
||||
@@ -63,18 +63,16 @@ static void iommufd_cdev_kvm_device_del(VFIODevice *vbasedev)
|
||||
}
|
||||
}
|
||||
|
||||
static int iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp)
|
||||
static bool iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
IOMMUFDBackend *iommufd = vbasedev->iommufd;
|
||||
struct vfio_device_bind_iommufd bind = {
|
||||
.argsz = sizeof(bind),
|
||||
.flags = 0,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = iommufd_backend_connect(iommufd, errp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (!iommufd_backend_connect(iommufd, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -82,15 +80,13 @@ static int iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp)
|
||||
* in KVM. Especially for some emulated devices, it requires
|
||||
* to have kvm information in the device open.
|
||||
*/
|
||||
ret = iommufd_cdev_kvm_device_add(vbasedev, errp);
|
||||
if (ret) {
|
||||
if (!iommufd_cdev_kvm_device_add(vbasedev, errp)) {
|
||||
goto err_kvm_device_add;
|
||||
}
|
||||
|
||||
/* Bind device to iommufd */
|
||||
bind.iommufd = iommufd->fd;
|
||||
ret = ioctl(vbasedev->fd, VFIO_DEVICE_BIND_IOMMUFD, &bind);
|
||||
if (ret) {
|
||||
if (ioctl(vbasedev->fd, VFIO_DEVICE_BIND_IOMMUFD, &bind)) {
|
||||
error_setg_errno(errp, errno, "error bind device fd=%d to iommufd=%d",
|
||||
vbasedev->fd, bind.iommufd);
|
||||
goto err_bind;
|
||||
@@ -99,12 +95,12 @@ static int iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp)
|
||||
vbasedev->devid = bind.out_devid;
|
||||
trace_iommufd_cdev_connect_and_bind(bind.iommufd, vbasedev->name,
|
||||
vbasedev->fd, vbasedev->devid);
|
||||
return ret;
|
||||
return true;
|
||||
err_bind:
|
||||
iommufd_cdev_kvm_device_del(vbasedev);
|
||||
err_kvm_device_add:
|
||||
iommufd_backend_disconnect(iommufd);
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void iommufd_cdev_unbind_and_disconnect(VFIODevice *vbasedev)
|
||||
@@ -176,10 +172,10 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iommufd_cdev_attach_ioas_hwpt(VFIODevice *vbasedev, uint32_t id,
|
||||
static bool iommufd_cdev_attach_ioas_hwpt(VFIODevice *vbasedev, uint32_t id,
|
||||
Error **errp)
|
||||
{
|
||||
int ret, iommufd = vbasedev->iommufd->fd;
|
||||
int iommufd = vbasedev->iommufd->fd;
|
||||
struct vfio_device_attach_iommufd_pt attach_data = {
|
||||
.argsz = sizeof(attach_data),
|
||||
.flags = 0,
|
||||
@@ -187,38 +183,38 @@ static int iommufd_cdev_attach_ioas_hwpt(VFIODevice *vbasedev, uint32_t id,
|
||||
};
|
||||
|
||||
/* Attach device to an IOAS or hwpt within iommufd */
|
||||
ret = ioctl(vbasedev->fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, &attach_data);
|
||||
if (ret) {
|
||||
if (ioctl(vbasedev->fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, &attach_data)) {
|
||||
error_setg_errno(errp, errno,
|
||||
"[iommufd=%d] error attach %s (%d) to id=%d",
|
||||
iommufd, vbasedev->name, vbasedev->fd, id);
|
||||
} else {
|
||||
trace_iommufd_cdev_attach_ioas_hwpt(iommufd, vbasedev->name,
|
||||
vbasedev->fd, id);
|
||||
return false;
|
||||
}
|
||||
return ret;
|
||||
|
||||
trace_iommufd_cdev_attach_ioas_hwpt(iommufd, vbasedev->name,
|
||||
vbasedev->fd, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int iommufd_cdev_detach_ioas_hwpt(VFIODevice *vbasedev, Error **errp)
|
||||
static bool iommufd_cdev_detach_ioas_hwpt(VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
int ret, iommufd = vbasedev->iommufd->fd;
|
||||
int iommufd = vbasedev->iommufd->fd;
|
||||
struct vfio_device_detach_iommufd_pt detach_data = {
|
||||
.argsz = sizeof(detach_data),
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
ret = ioctl(vbasedev->fd, VFIO_DEVICE_DETACH_IOMMUFD_PT, &detach_data);
|
||||
if (ret) {
|
||||
if (ioctl(vbasedev->fd, VFIO_DEVICE_DETACH_IOMMUFD_PT, &detach_data)) {
|
||||
error_setg_errno(errp, errno, "detach %s failed", vbasedev->name);
|
||||
} else {
|
||||
trace_iommufd_cdev_detach_ioas_hwpt(iommufd, vbasedev->name);
|
||||
return false;
|
||||
}
|
||||
return ret;
|
||||
|
||||
trace_iommufd_cdev_detach_ioas_hwpt(iommufd, vbasedev->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int iommufd_cdev_attach_container(VFIODevice *vbasedev,
|
||||
VFIOIOMMUFDContainer *container,
|
||||
Error **errp)
|
||||
static bool iommufd_cdev_attach_container(VFIODevice *vbasedev,
|
||||
VFIOIOMMUFDContainer *container,
|
||||
Error **errp)
|
||||
{
|
||||
return iommufd_cdev_attach_ioas_hwpt(vbasedev, container->ioas_id, errp);
|
||||
}
|
||||
@@ -228,7 +224,7 @@ static void iommufd_cdev_detach_container(VFIODevice *vbasedev,
|
||||
{
|
||||
Error *err = NULL;
|
||||
|
||||
if (iommufd_cdev_detach_ioas_hwpt(vbasedev, &err)) {
|
||||
if (!iommufd_cdev_detach_ioas_hwpt(vbasedev, &err)) {
|
||||
error_report_err(err);
|
||||
}
|
||||
}
|
||||
@@ -254,20 +250,19 @@ static int iommufd_cdev_ram_block_discard_disable(bool state)
|
||||
return ram_block_uncoordinated_discard_disable(state);
|
||||
}
|
||||
|
||||
static int iommufd_cdev_get_info_iova_range(VFIOIOMMUFDContainer *container,
|
||||
uint32_t ioas_id, Error **errp)
|
||||
static bool iommufd_cdev_get_info_iova_range(VFIOIOMMUFDContainer *container,
|
||||
uint32_t ioas_id, Error **errp)
|
||||
{
|
||||
VFIOContainerBase *bcontainer = &container->bcontainer;
|
||||
struct iommu_ioas_iova_ranges *info;
|
||||
g_autofree struct iommu_ioas_iova_ranges *info = NULL;
|
||||
struct iommu_iova_range *iova_ranges;
|
||||
int ret, sz, fd = container->be->fd;
|
||||
int sz, fd = container->be->fd;
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->size = sizeof(*info);
|
||||
info->ioas_id = ioas_id;
|
||||
|
||||
ret = ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info);
|
||||
if (ret && errno != EMSGSIZE) {
|
||||
if (ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info) && errno != EMSGSIZE) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -275,8 +270,7 @@ static int iommufd_cdev_get_info_iova_range(VFIOIOMMUFDContainer *container,
|
||||
info = g_realloc(info, sizeof(*info) + sz);
|
||||
info->allowed_iovas = (uintptr_t)(info + 1);
|
||||
|
||||
ret = ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info);
|
||||
if (ret) {
|
||||
if (ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -291,18 +285,15 @@ static int iommufd_cdev_get_info_iova_range(VFIOIOMMUFDContainer *container,
|
||||
}
|
||||
bcontainer->pgsizes = info->out_iova_alignment;
|
||||
|
||||
g_free(info);
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
error:
|
||||
ret = -errno;
|
||||
g_free(info);
|
||||
error_setg_errno(errp, errno, "Cannot get IOVA ranges");
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
|
||||
AddressSpace *as, Error **errp)
|
||||
static bool iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
|
||||
AddressSpace *as, Error **errp)
|
||||
{
|
||||
VFIOContainerBase *bcontainer;
|
||||
VFIOIOMMUFDContainer *container;
|
||||
@@ -317,15 +308,14 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
|
||||
if (vbasedev->fd < 0) {
|
||||
devfd = iommufd_cdev_getfd(vbasedev->sysfsdev, errp);
|
||||
if (devfd < 0) {
|
||||
return devfd;
|
||||
return false;
|
||||
}
|
||||
vbasedev->fd = devfd;
|
||||
} else {
|
||||
devfd = vbasedev->fd;
|
||||
}
|
||||
|
||||
ret = iommufd_cdev_connect_and_bind(vbasedev, errp);
|
||||
if (ret) {
|
||||
if (!iommufd_cdev_connect_and_bind(vbasedev, errp)) {
|
||||
goto err_connect_bind;
|
||||
}
|
||||
|
||||
@@ -338,7 +328,7 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
|
||||
vbasedev->iommufd != container->be) {
|
||||
continue;
|
||||
}
|
||||
if (iommufd_cdev_attach_container(vbasedev, container, &err)) {
|
||||
if (!iommufd_cdev_attach_container(vbasedev, container, &err)) {
|
||||
const char *msg = error_get_pretty(err);
|
||||
|
||||
trace_iommufd_cdev_fail_attach_existing_container(msg);
|
||||
@@ -356,8 +346,7 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
|
||||
}
|
||||
|
||||
/* Need to allocate a new dedicated container */
|
||||
ret = iommufd_backend_alloc_ioas(vbasedev->iommufd, &ioas_id, errp);
|
||||
if (ret < 0) {
|
||||
if (!iommufd_backend_alloc_ioas(vbasedev->iommufd, &ioas_id, errp)) {
|
||||
goto err_alloc_ioas;
|
||||
}
|
||||
|
||||
@@ -371,8 +360,7 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
|
||||
vfio_container_init(bcontainer, space, iommufd_vioc);
|
||||
QLIST_INSERT_HEAD(&space->containers, bcontainer, next);
|
||||
|
||||
ret = iommufd_cdev_attach_container(vbasedev, container, errp);
|
||||
if (ret) {
|
||||
if (!iommufd_cdev_attach_container(vbasedev, container, errp)) {
|
||||
goto err_attach_container;
|
||||
}
|
||||
|
||||
@@ -381,8 +369,7 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
|
||||
goto err_discard_disable;
|
||||
}
|
||||
|
||||
ret = iommufd_cdev_get_info_iova_range(container, ioas_id, &err);
|
||||
if (ret) {
|
||||
if (!iommufd_cdev_get_info_iova_range(container, ioas_id, &err)) {
|
||||
error_append_hint(&err,
|
||||
"Fallback to default 64bit IOVA range and 4K page size\n");
|
||||
warn_report_err(err);
|
||||
@@ -394,7 +381,6 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
|
||||
memory_listener_register(&bcontainer->listener, bcontainer->space->as);
|
||||
|
||||
if (bcontainer->error) {
|
||||
ret = -1;
|
||||
error_propagate_prepend(errp, bcontainer->error,
|
||||
"memory listener initialization failed: ");
|
||||
goto err_listener_register;
|
||||
@@ -409,8 +395,7 @@ found_container:
|
||||
goto err_listener_register;
|
||||
}
|
||||
|
||||
ret = vfio_cpr_register_container(bcontainer, errp);
|
||||
if (ret) {
|
||||
if (!vfio_cpr_register_container(bcontainer, errp)) {
|
||||
goto err_listener_register;
|
||||
}
|
||||
|
||||
@@ -433,7 +418,7 @@ found_container:
|
||||
|
||||
trace_iommufd_cdev_device_info(vbasedev->name, devfd, vbasedev->num_irqs,
|
||||
vbasedev->num_regions, vbasedev->flags);
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
err_listener_register:
|
||||
iommufd_cdev_ram_block_discard_disable(false);
|
||||
@@ -446,7 +431,7 @@ err_alloc_ioas:
|
||||
iommufd_cdev_unbind_and_disconnect(vbasedev);
|
||||
err_connect_bind:
|
||||
close(vbasedev->fd);
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void iommufd_cdev_detach(VFIODevice *vbasedev)
|
||||
|
||||
+136
-44
@@ -24,6 +24,7 @@
|
||||
#include "migration/register.h"
|
||||
#include "migration/blocker.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-events-vfio.h"
|
||||
#include "exec/ramlist.h"
|
||||
#include "exec/ram_addr.h"
|
||||
#include "pci.h"
|
||||
@@ -80,9 +81,65 @@ static const char *mig_state_to_str(enum vfio_device_mig_state state)
|
||||
}
|
||||
}
|
||||
|
||||
static VfioMigrationState
|
||||
mig_state_to_qapi_state(enum vfio_device_mig_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case VFIO_DEVICE_STATE_STOP:
|
||||
return QAPI_VFIO_MIGRATION_STATE_STOP;
|
||||
case VFIO_DEVICE_STATE_RUNNING:
|
||||
return QAPI_VFIO_MIGRATION_STATE_RUNNING;
|
||||
case VFIO_DEVICE_STATE_STOP_COPY:
|
||||
return QAPI_VFIO_MIGRATION_STATE_STOP_COPY;
|
||||
case VFIO_DEVICE_STATE_RESUMING:
|
||||
return QAPI_VFIO_MIGRATION_STATE_RESUMING;
|
||||
case VFIO_DEVICE_STATE_RUNNING_P2P:
|
||||
return QAPI_VFIO_MIGRATION_STATE_RUNNING_P2P;
|
||||
case VFIO_DEVICE_STATE_PRE_COPY:
|
||||
return QAPI_VFIO_MIGRATION_STATE_PRE_COPY;
|
||||
case VFIO_DEVICE_STATE_PRE_COPY_P2P:
|
||||
return QAPI_VFIO_MIGRATION_STATE_PRE_COPY_P2P;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static void vfio_migration_send_event(VFIODevice *vbasedev)
|
||||
{
|
||||
VFIOMigration *migration = vbasedev->migration;
|
||||
DeviceState *dev = vbasedev->dev;
|
||||
g_autofree char *qom_path = NULL;
|
||||
Object *obj;
|
||||
|
||||
if (!vbasedev->migration_events) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert(vbasedev->ops->vfio_get_object);
|
||||
obj = vbasedev->ops->vfio_get_object(vbasedev);
|
||||
g_assert(obj);
|
||||
qom_path = object_get_canonical_path(obj);
|
||||
|
||||
qapi_event_send_vfio_migration(
|
||||
dev->id, qom_path, mig_state_to_qapi_state(migration->device_state));
|
||||
}
|
||||
|
||||
static void vfio_migration_set_device_state(VFIODevice *vbasedev,
|
||||
enum vfio_device_mig_state state)
|
||||
{
|
||||
VFIOMigration *migration = vbasedev->migration;
|
||||
|
||||
trace_vfio_migration_set_device_state(vbasedev->name,
|
||||
mig_state_to_str(state));
|
||||
|
||||
migration->device_state = state;
|
||||
vfio_migration_send_event(vbasedev);
|
||||
}
|
||||
|
||||
static int vfio_migration_set_state(VFIODevice *vbasedev,
|
||||
enum vfio_device_mig_state new_state,
|
||||
enum vfio_device_mig_state recover_state)
|
||||
enum vfio_device_mig_state recover_state,
|
||||
Error **errp)
|
||||
{
|
||||
VFIOMigration *migration = vbasedev->migration;
|
||||
uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature) +
|
||||
@@ -92,6 +149,16 @@ static int vfio_migration_set_state(VFIODevice *vbasedev,
|
||||
struct vfio_device_feature_mig_state *mig_state =
|
||||
(struct vfio_device_feature_mig_state *)feature->data;
|
||||
int ret;
|
||||
g_autofree char *error_prefix =
|
||||
g_strdup_printf("%s: Failed setting device state to %s.",
|
||||
vbasedev->name, mig_state_to_str(new_state));
|
||||
|
||||
trace_vfio_migration_set_state(vbasedev->name, mig_state_to_str(new_state),
|
||||
mig_state_to_str(recover_state));
|
||||
|
||||
if (new_state == migration->device_state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
feature->argsz = sizeof(buf);
|
||||
feature->flags =
|
||||
@@ -102,22 +169,24 @@ static int vfio_migration_set_state(VFIODevice *vbasedev,
|
||||
ret = -errno;
|
||||
|
||||
if (recover_state == VFIO_DEVICE_STATE_ERROR) {
|
||||
error_report("%s: Failed setting device state to %s, err: %s. "
|
||||
"Recover state is ERROR. Resetting device",
|
||||
vbasedev->name, mig_state_to_str(new_state),
|
||||
strerror(errno));
|
||||
error_setg_errno(errp, errno,
|
||||
"%s Recover state is ERROR. Resetting device",
|
||||
error_prefix);
|
||||
|
||||
goto reset_device;
|
||||
}
|
||||
|
||||
error_report(
|
||||
"%s: Failed setting device state to %s, err: %s. Setting device in recover state %s",
|
||||
vbasedev->name, mig_state_to_str(new_state),
|
||||
strerror(errno), mig_state_to_str(recover_state));
|
||||
error_setg_errno(errp, errno,
|
||||
"%s Setting device in recover state %s",
|
||||
error_prefix, mig_state_to_str(recover_state));
|
||||
|
||||
mig_state->device_state = recover_state;
|
||||
if (ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature)) {
|
||||
ret = -errno;
|
||||
/*
|
||||
* If setting the device in recover state fails, report
|
||||
* the error here and propagate the first error.
|
||||
*/
|
||||
error_report(
|
||||
"%s: Failed setting device in recover state, err: %s. Resetting device",
|
||||
vbasedev->name, strerror(errno));
|
||||
@@ -125,19 +194,19 @@ static int vfio_migration_set_state(VFIODevice *vbasedev,
|
||||
goto reset_device;
|
||||
}
|
||||
|
||||
migration->device_state = recover_state;
|
||||
vfio_migration_set_device_state(vbasedev, recover_state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
migration->device_state = new_state;
|
||||
vfio_migration_set_device_state(vbasedev, new_state);
|
||||
if (mig_state->data_fd != -1) {
|
||||
if (migration->data_fd != -1) {
|
||||
/*
|
||||
* This can happen if the device is asynchronously reset and
|
||||
* terminates a data transfer.
|
||||
*/
|
||||
error_report("%s: data_fd out of sync", vbasedev->name);
|
||||
error_setg(errp, "%s: data_fd out of sync", vbasedev->name);
|
||||
close(mig_state->data_fd);
|
||||
|
||||
return -EBADF;
|
||||
@@ -146,8 +215,6 @@ static int vfio_migration_set_state(VFIODevice *vbasedev,
|
||||
migration->data_fd = mig_state->data_fd;
|
||||
}
|
||||
|
||||
trace_vfio_migration_set_state(vbasedev->name, mig_state_to_str(new_state));
|
||||
|
||||
return 0;
|
||||
|
||||
reset_device:
|
||||
@@ -156,7 +223,7 @@ reset_device:
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
migration->device_state = VFIO_DEVICE_STATE_RUNNING;
|
||||
vfio_migration_set_device_state(vbasedev, VFIO_DEVICE_STATE_RUNNING);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -168,10 +235,11 @@ reset_device:
|
||||
*/
|
||||
static int
|
||||
vfio_migration_set_state_or_reset(VFIODevice *vbasedev,
|
||||
enum vfio_device_mig_state new_state)
|
||||
enum vfio_device_mig_state new_state,
|
||||
Error **errp)
|
||||
{
|
||||
return vfio_migration_set_state(vbasedev, new_state,
|
||||
VFIO_DEVICE_STATE_ERROR);
|
||||
VFIO_DEVICE_STATE_ERROR, errp);
|
||||
}
|
||||
|
||||
static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev,
|
||||
@@ -186,21 +254,30 @@ static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vfio_save_device_config_state(QEMUFile *f, void *opaque)
|
||||
static int vfio_save_device_config_state(QEMUFile *f, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
VFIODevice *vbasedev = opaque;
|
||||
int ret;
|
||||
|
||||
qemu_put_be64(f, VFIO_MIG_FLAG_DEV_CONFIG_STATE);
|
||||
|
||||
if (vbasedev->ops && vbasedev->ops->vfio_save_config) {
|
||||
vbasedev->ops->vfio_save_config(vbasedev, f);
|
||||
ret = vbasedev->ops->vfio_save_config(vbasedev, f, errp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE);
|
||||
|
||||
trace_vfio_save_device_config_state(vbasedev->name);
|
||||
|
||||
return qemu_file_get_error(f);
|
||||
ret = qemu_file_get_error(f);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to save state");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vfio_load_device_config_state(QEMUFile *f, void *opaque)
|
||||
@@ -399,10 +476,8 @@ static int vfio_save_setup(QEMUFile *f, void *opaque, Error **errp)
|
||||
switch (migration->device_state) {
|
||||
case VFIO_DEVICE_STATE_RUNNING:
|
||||
ret = vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_PRE_COPY,
|
||||
VFIO_DEVICE_STATE_RUNNING);
|
||||
VFIO_DEVICE_STATE_RUNNING, errp);
|
||||
if (ret) {
|
||||
error_setg(errp, "%s: Failed to set new PRE_COPY state",
|
||||
vbasedev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -435,13 +510,20 @@ static void vfio_save_cleanup(void *opaque)
|
||||
{
|
||||
VFIODevice *vbasedev = opaque;
|
||||
VFIOMigration *migration = vbasedev->migration;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Changing device state from STOP_COPY to STOP can take time. Do it here,
|
||||
* after migration has completed, so it won't increase downtime.
|
||||
*/
|
||||
if (migration->device_state == VFIO_DEVICE_STATE_STOP_COPY) {
|
||||
vfio_migration_set_state_or_reset(vbasedev, VFIO_DEVICE_STATE_STOP);
|
||||
ret = vfio_migration_set_state_or_reset(vbasedev,
|
||||
VFIO_DEVICE_STATE_STOP,
|
||||
&local_err);
|
||||
if (ret) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(migration->data_buffer);
|
||||
@@ -549,11 +631,13 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque)
|
||||
VFIODevice *vbasedev = opaque;
|
||||
ssize_t data_size;
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
||||
/* We reach here with device state STOP or STOP_COPY only */
|
||||
ret = vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_STOP_COPY,
|
||||
VFIO_DEVICE_STATE_STOP);
|
||||
VFIO_DEVICE_STATE_STOP, &local_err);
|
||||
if (ret) {
|
||||
error_report_err(local_err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -566,9 +650,6 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque)
|
||||
|
||||
qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE);
|
||||
ret = qemu_file_get_error(f);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
trace_vfio_save_complete_precopy(vbasedev->name, ret);
|
||||
|
||||
@@ -578,27 +659,24 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque)
|
||||
static void vfio_save_state(QEMUFile *f, void *opaque)
|
||||
{
|
||||
VFIODevice *vbasedev = opaque;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
ret = vfio_save_device_config_state(f, opaque);
|
||||
ret = vfio_save_device_config_state(f, opaque, &local_err);
|
||||
if (ret) {
|
||||
error_report("%s: Failed to save device config space",
|
||||
vbasedev->name);
|
||||
qemu_file_set_error(f, ret);
|
||||
error_prepend(&local_err,
|
||||
"vfio: Failed to save device config space of %s - ",
|
||||
vbasedev->name);
|
||||
qemu_file_set_error_obj(f, ret, local_err);
|
||||
}
|
||||
}
|
||||
|
||||
static int vfio_load_setup(QEMUFile *f, void *opaque, Error **errp)
|
||||
{
|
||||
VFIODevice *vbasedev = opaque;
|
||||
int ret;
|
||||
|
||||
ret = vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_RESUMING,
|
||||
vbasedev->migration->device_state);
|
||||
if (ret) {
|
||||
error_setg(errp, "%s: Failed to set RESUMING state", vbasedev->name);
|
||||
}
|
||||
return ret;
|
||||
return vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_RESUMING,
|
||||
vbasedev->migration->device_state, errp);
|
||||
}
|
||||
|
||||
static int vfio_load_cleanup(void *opaque)
|
||||
@@ -714,19 +792,20 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running,
|
||||
VFIODevice *vbasedev = opaque;
|
||||
VFIOMigration *migration = vbasedev->migration;
|
||||
enum vfio_device_mig_state new_state;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
new_state = migration->device_state == VFIO_DEVICE_STATE_PRE_COPY ?
|
||||
VFIO_DEVICE_STATE_PRE_COPY_P2P :
|
||||
VFIO_DEVICE_STATE_RUNNING_P2P;
|
||||
|
||||
ret = vfio_migration_set_state_or_reset(vbasedev, new_state);
|
||||
ret = vfio_migration_set_state_or_reset(vbasedev, new_state, &local_err);
|
||||
if (ret) {
|
||||
/*
|
||||
* Migration should be aborted in this case, but vm_state_notify()
|
||||
* currently does not support reporting failures.
|
||||
*/
|
||||
migration_file_set_error(ret);
|
||||
migration_file_set_error(ret, local_err);
|
||||
}
|
||||
|
||||
trace_vfio_vmstate_change_prepare(vbasedev->name, running,
|
||||
@@ -738,6 +817,7 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state)
|
||||
{
|
||||
VFIODevice *vbasedev = opaque;
|
||||
enum vfio_device_mig_state new_state;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
if (running) {
|
||||
@@ -750,13 +830,13 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state)
|
||||
VFIO_DEVICE_STATE_STOP;
|
||||
}
|
||||
|
||||
ret = vfio_migration_set_state_or_reset(vbasedev, new_state);
|
||||
ret = vfio_migration_set_state_or_reset(vbasedev, new_state, &local_err);
|
||||
if (ret) {
|
||||
/*
|
||||
* Migration should be aborted in this case, but vm_state_notify()
|
||||
* currently does not support reporting failures.
|
||||
*/
|
||||
migration_file_set_error(ret);
|
||||
migration_file_set_error(ret, local_err);
|
||||
}
|
||||
|
||||
trace_vfio_vmstate_change(vbasedev->name, running, RunState_str(state),
|
||||
@@ -769,11 +849,23 @@ static int vfio_migration_state_notifier(NotifierWithReturn *notifier,
|
||||
VFIOMigration *migration = container_of(notifier, VFIOMigration,
|
||||
migration_state);
|
||||
VFIODevice *vbasedev = migration->vbasedev;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
trace_vfio_migration_state_notifier(vbasedev->name, e->type);
|
||||
|
||||
if (e->type == MIG_EVENT_PRECOPY_FAILED) {
|
||||
vfio_migration_set_state_or_reset(vbasedev, VFIO_DEVICE_STATE_RUNNING);
|
||||
/*
|
||||
* MigrationNotifyFunc may not return an error code and an Error
|
||||
* object for MIG_EVENT_PRECOPY_FAILED. Hence, report the error
|
||||
* locally and ignore the errp argument.
|
||||
*/
|
||||
ret = vfio_migration_set_state_or_reset(vbasedev,
|
||||
VFIO_DEVICE_STATE_RUNNING,
|
||||
&local_err);
|
||||
if (ret) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+23
-27
@@ -1169,8 +1169,8 @@ static void vfio_probe_rtl8168_bar2_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
* the table and to write the base address of that memory to the ASLS register
|
||||
* of the IGD device.
|
||||
*/
|
||||
int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
|
||||
struct vfio_region_info *info, Error **errp)
|
||||
bool vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
|
||||
struct vfio_region_info *info, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -1181,7 +1181,7 @@ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
|
||||
error_setg(errp, "failed to read IGD OpRegion");
|
||||
g_free(vdev->igd_opregion);
|
||||
vdev->igd_opregion = NULL;
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1206,7 +1206,7 @@ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
|
||||
pci_set_long(vdev->pdev.wmask + IGD_ASLS, ~0);
|
||||
pci_set_long(vdev->emulated_config_bits + IGD_ASLS, ~0);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1536,7 +1536,7 @@ static bool is_valid_std_cap_offset(uint8_t pos)
|
||||
pos <= (PCI_CFG_SPACE_SIZE - PCI_CAP_SIZEOF));
|
||||
}
|
||||
|
||||
static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
static bool vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
PCIDevice *pdev = &vdev->pdev;
|
||||
@@ -1545,18 +1545,18 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
uint8_t tmp;
|
||||
|
||||
if (vdev->nv_gpudirect_clique == 0xFF) {
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID)) {
|
||||
error_setg(errp, "NVIDIA GPUDirect Clique ID: invalid device vendor");
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pci_get_byte(pdev->config + PCI_CLASS_DEVICE + 1) !=
|
||||
PCI_BASE_CLASS_DISPLAY) {
|
||||
error_setg(errp, "NVIDIA GPUDirect Clique ID: unsupported PCI class");
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1572,7 +1572,7 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
vdev->config_offset + PCI_CAPABILITY_LIST);
|
||||
if (ret != 1 || !is_valid_std_cap_offset(tmp)) {
|
||||
error_setg(errp, "NVIDIA GPUDirect Clique ID: error getting cap list");
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
@@ -1590,13 +1590,13 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
pos = 0xD4;
|
||||
} else {
|
||||
error_setg(errp, "NVIDIA GPUDirect Clique ID: invalid config space");
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = pci_add_capability(pdev, PCI_CAP_ID_VNDR, pos, 8, errp);
|
||||
if (ret < 0) {
|
||||
error_prepend(errp, "Failed to add NVIDIA GPUDirect cap: ");
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(vdev->emulated_config_bits + pos, 0xFF, 8);
|
||||
@@ -1608,7 +1608,7 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
pci_set_byte(pdev->config + pos++, vdev->nv_gpudirect_clique << 3);
|
||||
pci_set_byte(pdev->config + pos, 0);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1629,7 +1629,7 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
*/
|
||||
#define VMD_SHADOW_CAP_VER 1
|
||||
#define VMD_SHADOW_CAP_LEN 24
|
||||
static int vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
static bool vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
uint8_t membar_phys[16];
|
||||
@@ -1639,7 +1639,7 @@ static int vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x467F) ||
|
||||
vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x4C3D) ||
|
||||
vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x9A0B))) {
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
ret = pread(vdev->vbasedev.fd, membar_phys, 16,
|
||||
@@ -1647,14 +1647,14 @@ static int vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
if (ret != 16) {
|
||||
error_report("VMD %s cannot read MEMBARs (%d)",
|
||||
vdev->vbasedev.name, ret);
|
||||
return -EFAULT;
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = pci_add_capability(&vdev->pdev, PCI_CAP_ID_VNDR, pos,
|
||||
VMD_SHADOW_CAP_LEN, errp);
|
||||
if (ret < 0) {
|
||||
error_prepend(errp, "Failed to add VMD MEMBAR Shadow cap: ");
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(vdev->emulated_config_bits + pos, 0xFF, VMD_SHADOW_CAP_LEN);
|
||||
@@ -1664,22 +1664,18 @@ static int vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp)
|
||||
pci_set_long(vdev->pdev.config + pos, 0x53484457); /* SHDW */
|
||||
memcpy(vdev->pdev.config + pos + 4, membar_phys, 16);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp)
|
||||
bool vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vfio_add_nv_gpudirect_cap(vdev, errp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (!vfio_add_nv_gpudirect_cap(vdev, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = vfio_add_vmd_shadow_cap(vdev, errp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (!vfio_add_vmd_shadow_cap(vdev, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
+144
-136
File diff suppressed because it is too large
Load Diff
+7
-6
@@ -177,6 +177,7 @@ struct VFIOPCIDevice {
|
||||
OnOffAuto ramfb_migrate;
|
||||
bool defer_kvm_irq_routing;
|
||||
bool clear_parent_atomics_on_exit;
|
||||
bool skip_vsc_check;
|
||||
VFIODisplay *dpy;
|
||||
Notifier irqchip_change_notifier;
|
||||
};
|
||||
@@ -211,7 +212,7 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr);
|
||||
void vfio_bar_quirk_exit(VFIOPCIDevice *vdev, int nr);
|
||||
void vfio_bar_quirk_finalize(VFIOPCIDevice *vdev, int nr);
|
||||
void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev);
|
||||
int vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp);
|
||||
bool vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp);
|
||||
void vfio_quirk_reset(VFIOPCIDevice *vdev);
|
||||
VFIOQuirk *vfio_quirk_alloc(int nr_mem);
|
||||
void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr);
|
||||
@@ -224,14 +225,14 @@ bool vfio_pci_host_match(PCIHostDeviceAddress *addr, const char *name);
|
||||
int vfio_pci_get_pci_hot_reset_info(VFIOPCIDevice *vdev,
|
||||
struct vfio_pci_hot_reset_info **info_p);
|
||||
|
||||
int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp);
|
||||
bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp);
|
||||
|
||||
int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
|
||||
struct vfio_region_info *info,
|
||||
Error **errp);
|
||||
bool vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
|
||||
struct vfio_region_info *info,
|
||||
Error **errp);
|
||||
|
||||
void vfio_display_reset(VFIOPCIDevice *vdev);
|
||||
int vfio_display_probe(VFIOPCIDevice *vdev, Error **errp);
|
||||
bool vfio_display_probe(VFIOPCIDevice *vdev, Error **errp);
|
||||
void vfio_display_finalize(VFIOPCIDevice *vdev);
|
||||
|
||||
extern const VMStateDescription vfio_display_vmstate;
|
||||
|
||||
+28
-38
@@ -115,18 +115,17 @@ static int vfio_set_trigger_eventfd(VFIOINTp *intp,
|
||||
VFIODevice *vbasedev = &intp->vdev->vbasedev;
|
||||
int32_t fd = event_notifier_get_fd(intp->interrupt);
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
|
||||
qemu_set_fd_handler(fd, (IOHandler *)handler, NULL, intp);
|
||||
|
||||
ret = vfio_set_irq_signaling(vbasedev, intp->pin, 0,
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err);
|
||||
if (ret) {
|
||||
if (!vfio_set_irq_signaling(vbasedev, intp->pin, 0,
|
||||
VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
|
||||
error_reportf_err(err, VFIO_MSG_PREFIX, vbasedev->name);
|
||||
qemu_set_fd_handler(fd, NULL, NULL, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -355,15 +354,14 @@ static int vfio_set_resample_eventfd(VFIOINTp *intp)
|
||||
int32_t fd = event_notifier_get_fd(intp->unmask);
|
||||
VFIODevice *vbasedev = &intp->vdev->vbasedev;
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
|
||||
qemu_set_fd_handler(fd, NULL, NULL, NULL);
|
||||
ret = vfio_set_irq_signaling(vbasedev, intp->pin, 0,
|
||||
VFIO_IRQ_SET_ACTION_UNMASK, fd, &err);
|
||||
if (ret) {
|
||||
if (!vfio_set_irq_signaling(vbasedev, intp->pin, 0,
|
||||
VFIO_IRQ_SET_ACTION_UNMASK, fd, &err)) {
|
||||
error_reportf_err(err, VFIO_MSG_PREFIX, vbasedev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,7 +441,7 @@ static int vfio_platform_hot_reset_multi(VFIODevice *vbasedev)
|
||||
* @errp: error object
|
||||
*
|
||||
*/
|
||||
static int vfio_populate_device(VFIODevice *vbasedev, Error **errp)
|
||||
static bool vfio_populate_device(VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
VFIOINTp *intp, *tmp;
|
||||
int i, ret = -1;
|
||||
@@ -452,7 +450,7 @@ static int vfio_populate_device(VFIODevice *vbasedev, Error **errp)
|
||||
|
||||
if (!(vbasedev->flags & VFIO_DEVICE_FLAGS_PLATFORM)) {
|
||||
error_setg(errp, "this isn't a platform device");
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
vdev->regions = g_new0(VFIORegion *, vbasedev->num_regions);
|
||||
@@ -489,12 +487,11 @@ static int vfio_populate_device(VFIODevice *vbasedev, Error **errp)
|
||||
irq.flags);
|
||||
intp = vfio_init_intp(vbasedev, irq, errp);
|
||||
if (!intp) {
|
||||
ret = -1;
|
||||
goto irq_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
irq_err:
|
||||
timer_del(vdev->mmap_timer);
|
||||
QLIST_FOREACH_SAFE(intp, &vdev->intp_list, next, tmp) {
|
||||
@@ -509,7 +506,7 @@ reg_error:
|
||||
g_free(vdev->regions[i]);
|
||||
}
|
||||
g_free(vdev->regions);
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* specialized functions for VFIO Platform devices */
|
||||
@@ -529,10 +526,8 @@ static VFIODeviceOps vfio_platform_ops = {
|
||||
* fd retrieval, resource query.
|
||||
* Precondition: the device name must be initialized
|
||||
*/
|
||||
static int vfio_base_device_init(VFIODevice *vbasedev, Error **errp)
|
||||
static bool vfio_base_device_init(VFIODevice *vbasedev, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* @fd takes precedence over @sysfsdev which takes precedence over @host */
|
||||
if (vbasedev->fd < 0 && vbasedev->sysfsdev) {
|
||||
g_free(vbasedev->name);
|
||||
@@ -540,30 +535,28 @@ static int vfio_base_device_init(VFIODevice *vbasedev, Error **errp)
|
||||
} else if (vbasedev->fd < 0) {
|
||||
if (!vbasedev->name || strchr(vbasedev->name, '/')) {
|
||||
error_setg(errp, "wrong host device name");
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
vbasedev->sysfsdev = g_strdup_printf("/sys/bus/platform/devices/%s",
|
||||
vbasedev->name);
|
||||
}
|
||||
|
||||
ret = vfio_device_get_name(vbasedev, errp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (!vfio_device_get_name(vbasedev, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = vfio_attach_device(vbasedev->name, vbasedev,
|
||||
&address_space_memory, errp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (!vfio_attach_device(vbasedev->name, vbasedev,
|
||||
&address_space_memory, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = vfio_populate_device(vbasedev, errp);
|
||||
if (ret) {
|
||||
vfio_detach_device(vbasedev);
|
||||
if (vfio_populate_device(vbasedev, errp)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
vfio_detach_device(vbasedev);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -580,7 +573,7 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
|
||||
VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
|
||||
SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
|
||||
VFIODevice *vbasedev = &vdev->vbasedev;
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
qemu_mutex_init(&vdev->intp_mutex);
|
||||
|
||||
@@ -588,9 +581,8 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
|
||||
vbasedev->sysfsdev : vbasedev->name,
|
||||
vdev->compat);
|
||||
|
||||
ret = vfio_base_device_init(vbasedev, errp);
|
||||
if (ret) {
|
||||
goto out;
|
||||
if (!vfio_base_device_init(vbasedev, errp)) {
|
||||
goto init_err;
|
||||
}
|
||||
|
||||
if (!vdev->compat) {
|
||||
@@ -622,11 +614,9 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
sysbus_init_mmio(sbdev, vdev->regions[i]->mem);
|
||||
}
|
||||
out:
|
||||
if (!ret) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
init_err:
|
||||
if (vdev->vbasedev.name) {
|
||||
error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
|
||||
} else {
|
||||
|
||||
+13
-15
@@ -323,7 +323,7 @@ static int vfio_spapr_create_window(VFIOContainer *container,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static bool
|
||||
vfio_spapr_container_add_section_window(VFIOContainerBase *bcontainer,
|
||||
MemoryRegionSection *section,
|
||||
Error **errp)
|
||||
@@ -351,13 +351,13 @@ vfio_spapr_container_add_section_window(VFIOContainerBase *bcontainer,
|
||||
error_setg(errp, "Container %p can't map guest IOVA region"
|
||||
" 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, container,
|
||||
iova, end);
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (container->iommu_type != VFIO_SPAPR_TCE_v2_IOMMU) {
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* For now intersections are not allowed, we may relax this later */
|
||||
@@ -373,14 +373,14 @@ vfio_spapr_container_add_section_window(VFIOContainerBase *bcontainer,
|
||||
section->offset_within_address_space +
|
||||
int128_get64(section->size) - 1,
|
||||
hostwin->min_iova, hostwin->max_iova);
|
||||
return -EINVAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = vfio_spapr_create_window(container, section, &pgsize);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, -ret, "Failed to create SPAPR window");
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
vfio_host_win_add(scontainer, section->offset_within_address_space,
|
||||
@@ -406,14 +406,14 @@ vfio_spapr_container_add_section_window(VFIOContainerBase *bcontainer,
|
||||
"vfio: failed GROUP_SET_SPAPR_TCE for "
|
||||
"KVM VFIO device %d and group fd %d",
|
||||
param.tablefd, param.groupfd);
|
||||
return -errno;
|
||||
return false;
|
||||
}
|
||||
trace_vfio_spapr_group_attach(param.groupfd, param.tablefd);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -458,8 +458,8 @@ static void vfio_spapr_container_release(VFIOContainerBase *bcontainer)
|
||||
}
|
||||
}
|
||||
|
||||
static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer,
|
||||
Error **errp)
|
||||
static bool vfio_spapr_container_setup(VFIOContainerBase *bcontainer,
|
||||
Error **errp)
|
||||
{
|
||||
VFIOContainer *container = container_of(bcontainer, VFIOContainer,
|
||||
bcontainer);
|
||||
@@ -480,7 +480,7 @@ static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer,
|
||||
ret = ioctl(fd, VFIO_IOMMU_ENABLE);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, errno, "failed to enable container");
|
||||
return -errno;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
scontainer->prereg_listener = vfio_prereg_listener;
|
||||
@@ -488,7 +488,6 @@ static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer,
|
||||
memory_listener_register(&scontainer->prereg_listener,
|
||||
&address_space_memory);
|
||||
if (bcontainer->error) {
|
||||
ret = -1;
|
||||
error_propagate_prepend(errp, bcontainer->error,
|
||||
"RAM memory listener initialization failed: ");
|
||||
goto listener_unregister_exit;
|
||||
@@ -500,7 +499,6 @@ static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer,
|
||||
if (ret) {
|
||||
error_setg_errno(errp, errno,
|
||||
"VFIO_IOMMU_SPAPR_TCE_GET_INFO failed");
|
||||
ret = -errno;
|
||||
goto listener_unregister_exit;
|
||||
}
|
||||
|
||||
@@ -527,13 +525,13 @@ static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer,
|
||||
0x1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
listener_unregister_exit:
|
||||
if (v2) {
|
||||
memory_listener_unregister(&scontainer->prereg_listener);
|
||||
}
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void vfio_iommu_spapr_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user