diff mbox series

[v2,1/1] tests/qtest/fuzz: Add faster virtio tests

Message ID 20200528165303.1877-2-f4bug@amsat.org (mailing list archive)
State New, archived
Headers show
Series tests/qtest/fuzz: Avoid QTest serialization | expand

Commit Message

Philippe Mathieu-Daudé May 28, 2020, 4:53 p.m. UTC
We don't need to serialize over QTest chardev when we can
directly access the MMIO address space via the first
registered CPU view.
Rename the currents tests as $TEST-qtest, add add faster
tests that don't use the qtest chardev.

virtio-net-socket gets ~50% performance improvement.

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 tests/qtest/fuzz/virtio_net_fuzz.c  | 42 ++++++++++++++++++++---
 tests/qtest/fuzz/virtio_scsi_fuzz.c | 53 +++++++++++++++++++++++++----
 2 files changed, 84 insertions(+), 11 deletions(-)

Comments

Alexander Bulekov May 29, 2020, 5:19 a.m. UTC | #1
On 200528 1853, Philippe Mathieu-Daudé wrote:
> We don't need to serialize over QTest chardev when we can
> directly access the MMIO address space via the first
> registered CPU view.
> Rename the currents tests as $TEST-qtest, add add faster
> tests that don't use the qtest chardev.
> 
> virtio-net-socket gets ~50% performance improvement.
> 
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Alexander Bulekov <alxndr@bu.edu>

Thanks for fixing the spaces in the descriptions, too.

> ---
>  tests/qtest/fuzz/virtio_net_fuzz.c  | 42 ++++++++++++++++++++---
>  tests/qtest/fuzz/virtio_scsi_fuzz.c | 53 +++++++++++++++++++++++++----
>  2 files changed, 84 insertions(+), 11 deletions(-)
> 
> diff --git a/tests/qtest/fuzz/virtio_net_fuzz.c b/tests/qtest/fuzz/virtio_net_fuzz.c
> index d08a47e278..7a39cfbb75 100644
> --- a/tests/qtest/fuzz/virtio_net_fuzz.c
> +++ b/tests/qtest/fuzz/virtio_net_fuzz.c
> @@ -19,6 +19,8 @@
>  #include "fork_fuzz.h"
>  #include "qos_fuzz.h"
>  
> +#include "exec/address-spaces.h"
> +#include "hw/core/cpu.h"
>  
>  #define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000)
>  #define QVIRTIO_RX_VQ 0
> @@ -29,7 +31,9 @@ static int sockfds[2];
>  static bool sockfds_initialized;
>  
>  static void virtio_net_fuzz_multi(QTestState *s,
> -        const unsigned char *Data, size_t Size, bool check_used)
> +                                  const unsigned char *Data, size_t Size,
> +                                  bool check_used, bool use_qtest_chardev)
> +
>  {
>      typedef struct vq_action {
>          uint8_t queue;
> @@ -69,8 +73,13 @@ static void virtio_net_fuzz_multi(QTestState *s,
>               * If checking used ring, ensure that the fuzzer doesn't trigger
>               * trivial asserion failure on zero-zied buffer
>               */
> -            qtest_memwrite(s, req_addr, Data, vqa.length);
> -
> +            if (use_qtest_chardev) {
> +                qtest_memwrite(s, req_addr, Data, vqa.length);
> +            } else {
> +                address_space_write(first_cpu->as, req_addr,
> +                                     MEMTXATTRS_UNSPECIFIED,
> +                                     &Data, vqa.length);
> +            }
>  
>              free_head = qvirtqueue_add(s, q, req_addr, vqa.length,
>                      vqa.write, vqa.next);
> @@ -118,7 +127,20 @@ static void virtio_net_fork_fuzz(QTestState *s,
>          const unsigned char *Data, size_t Size)
>  {
>      if (fork() == 0) {
> -        virtio_net_fuzz_multi(s, Data, Size, false);
> +        virtio_net_fuzz_multi(s, Data, Size, false, false);
> +        flush_events(s);
> +        _Exit(0);
> +    } else {
> +        wait(NULL);
> +    }
> +}
> +
> +static void virtio_net_fork_fuzz_qtest(QTestState *s,
> +                                       const unsigned char *Data,
> +                                       size_t Size)
> +{
> +    if (fork() == 0) {
> +        virtio_net_fuzz_multi(s, Data, Size, false, true);
>          flush_events(s);
>          _Exit(0);
>      } else {
> @@ -130,7 +152,7 @@ static void virtio_net_fork_fuzz_check_used(QTestState *s,
>          const unsigned char *Data, size_t Size)
>  {
>      if (fork() == 0) {
> -        virtio_net_fuzz_multi(s, Data, Size, true);
> +        virtio_net_fuzz_multi(s, Data, Size, true, false);
>          flush_events(s);
>          _Exit(0);
>      } else {
> @@ -173,6 +195,16 @@ static void register_virtio_net_fuzz_targets(void)
>              &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
>              );
>  
> +    fuzz_add_qos_target(&(FuzzTarget){
> +            .name = "virtio-net-socket-qtest",
> +            .description = "Fuzz the virtio-net virtual queues. Fuzz incoming "
> +            "traffic using the socket backend (over a qtest chardev)",
> +            .pre_fuzz = &virtio_net_pre_fuzz,
> +            .fuzz = virtio_net_fork_fuzz_qtest,},
> +            "virtio-net",
> +            &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
> +            );
> +
>      fuzz_add_qos_target(&(FuzzTarget){
>              .name = "virtio-net-socket-check-used",
>              .description = "Fuzz the virtio-net virtual queues. Wait for the "
> diff --git a/tests/qtest/fuzz/virtio_scsi_fuzz.c b/tests/qtest/fuzz/virtio_scsi_fuzz.c
> index 3b95247f12..27b63b2e32 100644
> --- a/tests/qtest/fuzz/virtio_scsi_fuzz.c
> +++ b/tests/qtest/fuzz/virtio_scsi_fuzz.c
> @@ -23,6 +23,9 @@
>  #include "fork_fuzz.h"
>  #include "qos_fuzz.h"
>  
> +#include "exec/address-spaces.h"
> +#include "hw/core/cpu.h"
> +
>  #define PCI_SLOT                0x02
>  #define PCI_FN                  0x00
>  #define QVIRTIO_SCSI_TIMEOUT_US (1 * 1000 * 1000)
> @@ -63,7 +66,8 @@ static QVirtioSCSIQueues *qvirtio_scsi_init(QVirtioDevice *dev, uint64_t mask)
>  }
>  
>  static void virtio_scsi_fuzz(QTestState *s, QVirtioSCSIQueues* queues,
> -        const unsigned char *Data, size_t Size)
> +                             const unsigned char *Data, size_t Size,
> +                             bool use_qtest_chardev)
>  {
>      /*
>       * Data is a sequence of random bytes. We split them up into "actions",
> @@ -108,7 +112,13 @@ static void virtio_scsi_fuzz(QTestState *s, QVirtioSCSIQueues* queues,
>  
>          /* Copy the data into ram, and place it on the virtqueue */
>          uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
> -        qtest_memwrite(s, req_addr, Data, vqa.length);
> +        if (use_qtest_chardev) {
> +            qtest_memwrite(s, req_addr, Data, vqa.length);
> +        } else {
> +            address_space_write(first_cpu->as, req_addr,
> +                                 MEMTXATTRS_UNSPECIFIED,
> +                                 &Data, vqa.length);
> +        }
>          if (vq_touched[vqa.queue] == 0) {
>              vq_touched[vqa.queue] = 1;
>              free_head[vqa.queue] = qvirtqueue_add(s, q, req_addr, vqa.length,
> @@ -141,7 +151,25 @@ static void virtio_scsi_fork_fuzz(QTestState *s,
>          queues = qvirtio_scsi_init(scsi->vdev, 0);
>      }
>      if (fork() == 0) {
> -        virtio_scsi_fuzz(s, queues, Data, Size);
> +        virtio_scsi_fuzz(s, queues, Data, Size, false);
> +        flush_events(s);
> +        _Exit(0);
> +    } else {
> +        wait(NULL);
> +    }
> +}
> +
> +static void virtio_scsi_fork_fuzz_qtest(QTestState *s,
> +                                        const unsigned char *Data,
> +                                        size_t Size)
> +{
> +    QVirtioSCSI *scsi = fuzz_qos_obj;
> +    static QVirtioSCSIQueues *queues;
> +    if (!queues) {
> +        queues = qvirtio_scsi_init(scsi->vdev, 0);
> +    }
> +    if (fork() == 0) {
> +        virtio_scsi_fuzz(s, queues, Data, Size, true);
>          flush_events(s);
>          _Exit(0);
>      } else {
> @@ -159,7 +187,9 @@ static void virtio_scsi_with_flag_fuzz(QTestState *s,
>          if (Size >= sizeof(uint64_t)) {
>              queues = qvirtio_scsi_init(scsi->vdev, *(uint64_t *)Data);
>              virtio_scsi_fuzz(s, queues,
> -                             Data + sizeof(uint64_t), Size - sizeof(uint64_t));
> +                             Data + sizeof(uint64_t),
> +                             Size - sizeof(uint64_t),
> +                             false);
>              flush_events(s);
>          }
>          _Exit(0);
> @@ -189,7 +219,7 @@ static void register_virtio_scsi_fuzz_targets(void)
>  {
>      fuzz_add_qos_target(&(FuzzTarget){
>                  .name = "virtio-scsi-fuzz",
> -                .description = "Fuzz the virtio-scsi virtual queues, forking"
> +                .description = "Fuzz the virtio-scsi virtual queues, forking "
>                                  "for each fuzz run",
>                  .pre_vm_init = &counter_shm_init,
>                  .pre_fuzz = &virtio_scsi_pre_fuzz,
> @@ -198,9 +228,20 @@ static void register_virtio_scsi_fuzz_targets(void)
>                  &(QOSGraphTestOptions){.before = virtio_scsi_test_setup}
>                  );
>  
> +    fuzz_add_qos_target(&(FuzzTarget){
> +                .name = "virtio-scsi-fuzz-qtest",
> +                .description = "Fuzz the virtio-scsi virtual queues, forking "
> +                                "for each fuzz run (over a qtest chardev)",
> +                .pre_vm_init = &counter_shm_init,
> +                .pre_fuzz = &virtio_scsi_pre_fuzz,
> +                .fuzz = virtio_scsi_fork_fuzz_qtest,},
> +                "virtio-scsi",
> +                &(QOSGraphTestOptions){.before = virtio_scsi_test_setup}
> +                );
> +
>      fuzz_add_qos_target(&(FuzzTarget){
>                  .name = "virtio-scsi-flags-fuzz",
> -                .description = "Fuzz the virtio-scsi virtual queues, forking"
> +                .description = "Fuzz the virtio-scsi virtual queues, forking "
>                  "for each fuzz run (also fuzzes the virtio flags)",
>                  .pre_vm_init = &counter_shm_init,
>                  .pre_fuzz = &virtio_scsi_pre_fuzz,
> -- 
> 2.21.3
>
diff mbox series

Patch

diff --git a/tests/qtest/fuzz/virtio_net_fuzz.c b/tests/qtest/fuzz/virtio_net_fuzz.c
index d08a47e278..7a39cfbb75 100644
--- a/tests/qtest/fuzz/virtio_net_fuzz.c
+++ b/tests/qtest/fuzz/virtio_net_fuzz.c
@@ -19,6 +19,8 @@ 
 #include "fork_fuzz.h"
 #include "qos_fuzz.h"
 
+#include "exec/address-spaces.h"
+#include "hw/core/cpu.h"
 
 #define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000)
 #define QVIRTIO_RX_VQ 0
@@ -29,7 +31,9 @@  static int sockfds[2];
 static bool sockfds_initialized;
 
 static void virtio_net_fuzz_multi(QTestState *s,
-        const unsigned char *Data, size_t Size, bool check_used)
+                                  const unsigned char *Data, size_t Size,
+                                  bool check_used, bool use_qtest_chardev)
+
 {
     typedef struct vq_action {
         uint8_t queue;
@@ -69,8 +73,13 @@  static void virtio_net_fuzz_multi(QTestState *s,
              * If checking used ring, ensure that the fuzzer doesn't trigger
              * trivial asserion failure on zero-zied buffer
              */
-            qtest_memwrite(s, req_addr, Data, vqa.length);
-
+            if (use_qtest_chardev) {
+                qtest_memwrite(s, req_addr, Data, vqa.length);
+            } else {
+                address_space_write(first_cpu->as, req_addr,
+                                     MEMTXATTRS_UNSPECIFIED,
+                                     &Data, vqa.length);
+            }
 
             free_head = qvirtqueue_add(s, q, req_addr, vqa.length,
                     vqa.write, vqa.next);
@@ -118,7 +127,20 @@  static void virtio_net_fork_fuzz(QTestState *s,
         const unsigned char *Data, size_t Size)
 {
     if (fork() == 0) {
-        virtio_net_fuzz_multi(s, Data, Size, false);
+        virtio_net_fuzz_multi(s, Data, Size, false, false);
+        flush_events(s);
+        _Exit(0);
+    } else {
+        wait(NULL);
+    }
+}
+
+static void virtio_net_fork_fuzz_qtest(QTestState *s,
+                                       const unsigned char *Data,
+                                       size_t Size)
+{
+    if (fork() == 0) {
+        virtio_net_fuzz_multi(s, Data, Size, false, true);
         flush_events(s);
         _Exit(0);
     } else {
@@ -130,7 +152,7 @@  static void virtio_net_fork_fuzz_check_used(QTestState *s,
         const unsigned char *Data, size_t Size)
 {
     if (fork() == 0) {
-        virtio_net_fuzz_multi(s, Data, Size, true);
+        virtio_net_fuzz_multi(s, Data, Size, true, false);
         flush_events(s);
         _Exit(0);
     } else {
@@ -173,6 +195,16 @@  static void register_virtio_net_fuzz_targets(void)
             &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
             );
 
+    fuzz_add_qos_target(&(FuzzTarget){
+            .name = "virtio-net-socket-qtest",
+            .description = "Fuzz the virtio-net virtual queues. Fuzz incoming "
+            "traffic using the socket backend (over a qtest chardev)",
+            .pre_fuzz = &virtio_net_pre_fuzz,
+            .fuzz = virtio_net_fork_fuzz_qtest,},
+            "virtio-net",
+            &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
+            );
+
     fuzz_add_qos_target(&(FuzzTarget){
             .name = "virtio-net-socket-check-used",
             .description = "Fuzz the virtio-net virtual queues. Wait for the "
diff --git a/tests/qtest/fuzz/virtio_scsi_fuzz.c b/tests/qtest/fuzz/virtio_scsi_fuzz.c
index 3b95247f12..27b63b2e32 100644
--- a/tests/qtest/fuzz/virtio_scsi_fuzz.c
+++ b/tests/qtest/fuzz/virtio_scsi_fuzz.c
@@ -23,6 +23,9 @@ 
 #include "fork_fuzz.h"
 #include "qos_fuzz.h"
 
+#include "exec/address-spaces.h"
+#include "hw/core/cpu.h"
+
 #define PCI_SLOT                0x02
 #define PCI_FN                  0x00
 #define QVIRTIO_SCSI_TIMEOUT_US (1 * 1000 * 1000)
@@ -63,7 +66,8 @@  static QVirtioSCSIQueues *qvirtio_scsi_init(QVirtioDevice *dev, uint64_t mask)
 }
 
 static void virtio_scsi_fuzz(QTestState *s, QVirtioSCSIQueues* queues,
-        const unsigned char *Data, size_t Size)
+                             const unsigned char *Data, size_t Size,
+                             bool use_qtest_chardev)
 {
     /*
      * Data is a sequence of random bytes. We split them up into "actions",
@@ -108,7 +112,13 @@  static void virtio_scsi_fuzz(QTestState *s, QVirtioSCSIQueues* queues,
 
         /* Copy the data into ram, and place it on the virtqueue */
         uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
-        qtest_memwrite(s, req_addr, Data, vqa.length);
+        if (use_qtest_chardev) {
+            qtest_memwrite(s, req_addr, Data, vqa.length);
+        } else {
+            address_space_write(first_cpu->as, req_addr,
+                                 MEMTXATTRS_UNSPECIFIED,
+                                 &Data, vqa.length);
+        }
         if (vq_touched[vqa.queue] == 0) {
             vq_touched[vqa.queue] = 1;
             free_head[vqa.queue] = qvirtqueue_add(s, q, req_addr, vqa.length,
@@ -141,7 +151,25 @@  static void virtio_scsi_fork_fuzz(QTestState *s,
         queues = qvirtio_scsi_init(scsi->vdev, 0);
     }
     if (fork() == 0) {
-        virtio_scsi_fuzz(s, queues, Data, Size);
+        virtio_scsi_fuzz(s, queues, Data, Size, false);
+        flush_events(s);
+        _Exit(0);
+    } else {
+        wait(NULL);
+    }
+}
+
+static void virtio_scsi_fork_fuzz_qtest(QTestState *s,
+                                        const unsigned char *Data,
+                                        size_t Size)
+{
+    QVirtioSCSI *scsi = fuzz_qos_obj;
+    static QVirtioSCSIQueues *queues;
+    if (!queues) {
+        queues = qvirtio_scsi_init(scsi->vdev, 0);
+    }
+    if (fork() == 0) {
+        virtio_scsi_fuzz(s, queues, Data, Size, true);
         flush_events(s);
         _Exit(0);
     } else {
@@ -159,7 +187,9 @@  static void virtio_scsi_with_flag_fuzz(QTestState *s,
         if (Size >= sizeof(uint64_t)) {
             queues = qvirtio_scsi_init(scsi->vdev, *(uint64_t *)Data);
             virtio_scsi_fuzz(s, queues,
-                             Data + sizeof(uint64_t), Size - sizeof(uint64_t));
+                             Data + sizeof(uint64_t),
+                             Size - sizeof(uint64_t),
+                             false);
             flush_events(s);
         }
         _Exit(0);
@@ -189,7 +219,7 @@  static void register_virtio_scsi_fuzz_targets(void)
 {
     fuzz_add_qos_target(&(FuzzTarget){
                 .name = "virtio-scsi-fuzz",
-                .description = "Fuzz the virtio-scsi virtual queues, forking"
+                .description = "Fuzz the virtio-scsi virtual queues, forking "
                                 "for each fuzz run",
                 .pre_vm_init = &counter_shm_init,
                 .pre_fuzz = &virtio_scsi_pre_fuzz,
@@ -198,9 +228,20 @@  static void register_virtio_scsi_fuzz_targets(void)
                 &(QOSGraphTestOptions){.before = virtio_scsi_test_setup}
                 );
 
+    fuzz_add_qos_target(&(FuzzTarget){
+                .name = "virtio-scsi-fuzz-qtest",
+                .description = "Fuzz the virtio-scsi virtual queues, forking "
+                                "for each fuzz run (over a qtest chardev)",
+                .pre_vm_init = &counter_shm_init,
+                .pre_fuzz = &virtio_scsi_pre_fuzz,
+                .fuzz = virtio_scsi_fork_fuzz_qtest,},
+                "virtio-scsi",
+                &(QOSGraphTestOptions){.before = virtio_scsi_test_setup}
+                );
+
     fuzz_add_qos_target(&(FuzzTarget){
                 .name = "virtio-scsi-flags-fuzz",
-                .description = "Fuzz the virtio-scsi virtual queues, forking"
+                .description = "Fuzz the virtio-scsi virtual queues, forking "
                 "for each fuzz run (also fuzzes the virtio flags)",
                 .pre_vm_init = &counter_shm_init,
                 .pre_fuzz = &virtio_scsi_pre_fuzz,