aboutsummaryrefslogtreecommitdiff
path: root/test/unit-tests.c
diff options
context:
space:
mode:
authorJohn Levon <john.levon@nutanix.com>2021-03-10 10:37:59 +0000
committerGitHub <noreply@github.com>2021-03-10 10:37:59 +0000
commit052d709d0cfd77c36f5b31402c3cc1c3d868d618 (patch)
tree29f6fbba5fa94e80e7c53bbc2fdde474ae16a1b0 /test/unit-tests.c
parent997536eee6609827b5053afef497f94bc6f6dbf4 (diff)
downloadlibvfio-user-052d709d0cfd77c36f5b31402c3cc1c3d868d618.zip
libvfio-user-052d709d0cfd77c36f5b31402c3cc1c3d868d618.tar.gz
libvfio-user-052d709d0cfd77c36f5b31402c3cc1c3d868d618.tar.bz2
fix IRQ disable path (#386)
Properly fix IRQ disabling: Allow count == 0 to mean "disable all IRQS of the given type". On our side, disabling an IRQ means forgetting about the eventfd that was previously passed over the socket. Allow individual IRQs to be disabled, by means of a VFIO_IRQ_SET_DATA_EVENTFD message with no file descriptors passed. In vfio, this is done via setting "-1" in the fd slots; which isn't possible via auxiliary data. Thus, only one IRQ can be disabled a a time in vfio-user. Clean up "->type": this is never set, so wasn't having any effect. Follow up changes will likely re-introduce this in some form. Signed-off-by: John Levon <john.levon@nutanix.com> Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'test/unit-tests.c')
-rw-r--r--test/unit-tests.c168
1 files changed, 167 insertions, 1 deletions
diff --git a/test/unit-tests.c b/test/unit-tests.c
index 25cba6c..929b83a 100644
--- a/test/unit-tests.c
+++ b/test/unit-tests.c
@@ -1684,7 +1684,172 @@ test_dirty_pages_without_dma(UNUSED void **state)
assert_int_equal(0xabcd, r);
}
-int main(void)
+static void
+test_device_set_irqs(UNUSED void **state)
+{
+ vfu_irqs_t *irqs = alloca(sizeof (*irqs) + sizeof (int));
+ struct vfio_irq_set irq_set = { 0, };
+ vfu_ctx_t vfu_ctx = { 0, };
+ int fd = 0xdead;
+ int ret;
+
+ vfu_ctx.irq_count[VFU_DEV_MSIX_IRQ] = 2048;
+ vfu_ctx.irq_count[VFU_DEV_ERR_IRQ] = 1;
+ vfu_ctx.irq_count[VFU_DEV_REQ_IRQ] = 1;
+ vfu_ctx.irqs = irqs;
+
+ /* validation tests */
+
+ irq_set.argsz = sizeof (irq_set);
+
+ ret = handle_device_set_irqs(&vfu_ctx, 0, NULL, 0, &irq_set);
+ /* bad message size */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.argsz = 3;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad .argsz */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.argsz = sizeof (irq_set);
+ irq_set.index = VFU_DEV_NUM_IRQS;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad .index */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.index = VFU_DEV_MSIX_IRQ;
+ irq_set.flags = VFIO_IRQ_SET_ACTION_MASK | VFIO_IRQ_SET_ACTION_UNMASK;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad flags, MASK and UNMASK */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.flags = VFIO_IRQ_SET_ACTION_MASK | VFIO_IRQ_SET_DATA_NONE |
+ VFIO_IRQ_SET_DATA_BOOL;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad flags, DATA_NONE and DATA_BOOL */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.flags = VFIO_IRQ_SET_ACTION_MASK | VFIO_IRQ_SET_DATA_NONE;
+ irq_set.start = 2047;
+ irq_set.count = 2;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad start, count range */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.start = 2049;
+ irq_set.count = 1;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad start, count range */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.start = 0;
+ irq_set.count = 1;
+ irq_set.index = VFU_DEV_ERR_IRQ;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad action for err irq */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.index = VFU_DEV_REQ_IRQ;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad action for req irq */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.start = 1;
+ irq_set.count = 0;
+ irq_set.index = VFU_DEV_MSIX_IRQ;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad start for count == 0 */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.flags = VFIO_IRQ_SET_ACTION_MASK | VFIO_IRQ_SET_DATA_NONE;
+ irq_set.count = 0;
+ irq_set.start = 0;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad action for count == 0 */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.flags = VFIO_IRQ_SET_ACTION_TRIGGER | VFIO_IRQ_SET_DATA_BOOL;
+ irq_set.count = 0;
+ irq_set.start = 0;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ /* bad action and data type for count == 0 */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.flags = VFIO_IRQ_SET_ACTION_TRIGGER | VFIO_IRQ_SET_DATA_BOOL;
+ irq_set.count = 1;
+ irq_set.start = 0;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), &fd, 1, &irq_set);
+ /* bad fds for DATA_BOOL */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.flags = VFIO_IRQ_SET_ACTION_TRIGGER | VFIO_IRQ_SET_DATA_NONE;
+ irq_set.count = 1;
+ irq_set.start = 0;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), &fd, 1, &irq_set);
+ /* bad fds for DATA_NONE */
+ assert_int_equal(-EINVAL, ret);
+
+ irq_set.flags = VFIO_IRQ_SET_ACTION_TRIGGER | VFIO_IRQ_SET_DATA_EVENTFD;
+ irq_set.count = 2;
+ irq_set.start = 0;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), &fd, 1, &irq_set);
+ /* bad fds for count == 2 */
+ assert_int_equal(-EINVAL, ret);
+
+ irqs->err_efd = irqs->req_efd = -1;
+
+ /* Basic disable functionality. */
+
+ irq_set.index = VFU_DEV_REQ_IRQ;
+ irq_set.flags = VFIO_IRQ_SET_ACTION_TRIGGER | VFIO_IRQ_SET_DATA_NONE;
+ irq_set.count = 0;
+ irq_set.start = 0;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ assert_int_equal(0, ret);
+
+ irq_set.index = VFU_DEV_REQ_IRQ;
+ irq_set.flags = VFIO_IRQ_SET_ACTION_TRIGGER | VFIO_IRQ_SET_DATA_EVENTFD;
+ irq_set.count = 1;
+ irq_set.start = 0;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), NULL, 0, &irq_set);
+ assert_int_equal(0, ret);
+
+ /* Basic enable. */
+
+ irq_set.index = VFU_DEV_MSIX_IRQ;
+ vfu_ctx.irq_count[VFU_DEV_MSIX_IRQ] = 1;
+ irqs->efds[0] = -1;
+ fd = 0xbeef;
+
+ irq_set.index = VFU_DEV_MSIX_IRQ;
+ irq_set.flags = VFIO_IRQ_SET_ACTION_TRIGGER | VFIO_IRQ_SET_DATA_EVENTFD;
+ irq_set.count = 1;
+ irq_set.start = 0;
+
+ ret = handle_device_set_irqs(&vfu_ctx, sizeof (irq_set), &fd, 1, &irq_set);
+ assert_int_equal(0, ret);
+ assert_int_equal(0xbeef, irqs->efds[0]);
+
+}
+
+int
+main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup(test_dma_map_without_dma, setup),
@@ -1741,6 +1906,7 @@ int main(void)
cmocka_unit_test_setup(test_should_exec_command, setup),
cmocka_unit_test_setup(test_exec_command, setup),
cmocka_unit_test_setup(test_dirty_pages_without_dma, setup),
+ cmocka_unit_test_setup(test_device_set_irqs, setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);