All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fabiano Rosas <farosas@suse.de>
To: Nicholas Piggin <npiggin@gmail.com>, qemu-devel@nongnu.org
Cc: Nicholas Piggin <npiggin@gmail.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	Marcel Apfelbaum <marcel.apfelbaum@gmail.com>,
	Laurent Vivier <lvivier@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [RFC PATCH 4/5] qtest/xhci: Add controller and device setup and ring tests
Date: Mon, 11 Nov 2024 11:32:15 -0300	[thread overview]
Message-ID: <87msi5j0y8.fsf@suse.de> (raw)
In-Reply-To: <20241108154229.263097-5-npiggin@gmail.com>

Nicholas Piggin <npiggin@gmail.com> writes:

> Add tests which init the host controller registers to the point
> where command and event rings, irqs are operational. Enumerate
> ports and set up an attached device context that enables device
> transfer ring to be set up and tested.
>
> This test does a bunch of things at once and is yet well
> librified, but it allows testing basic mechanisms and gives a
> starting point for further work.

Please give it a pass through checkpatch when you get the chance.

>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
>  tests/qtest/usb-hcd-xhci-test.h | 232 +++++++++++++++
>  tests/qtest/usb-hcd-xhci-test.c | 506 +++++++++++++++++++++++++++++++-
>  2 files changed, 732 insertions(+), 6 deletions(-)
>  create mode 100644 tests/qtest/usb-hcd-xhci-test.h
>

<snip>

> +static void pci_xhci_stress_rings(void)
> +{
> +    XHCIQState *s;
> +    uint32_t value;
> +    uint64_t input_context;
> +    XHCIEvRingSeg ev_seg;
> +    XHCITRB trb;
> +    uint32_t hcsparams1;
> +    uint32_t slotid;
> +    void *mem;
> +    int i;
> +
> +    mem = g_malloc(0x1000);

This is leaking.

> +    memset(mem, 0, 0x1000);
> +
> +    s = xhci_boot("-M q35 "
> +            "-device nec-usb-xhci,id=xhci,bus=pcie.0,addr=1d.0 "
> +            "-device usb-storage,bus=xhci.0,drive=drive0 "
> +            "-drive id=drive0,if=none,file=null-co://,"
> +                "file.read-zeroes=on,format=raw "
> +            );
> +//            "-d trace:*xhci*,trace:*usb*,trace:*msi*");
> +
> +    hcsparams1 = xhci_cap_readl(s, 0x4); /* HCSPARAMS1 */
> +    s->maxports = (hcsparams1 >> 24) & 0xff;
> +    s->maxintrs = (hcsparams1 >> 8) & 0x3ff;
> +    s->maxslots = hcsparams1 & 0xff;
> +
> +    s->dboff = xhci_cap_readl(s, 0x14); /* DBOFF */
> +    s->rtoff = xhci_cap_readl(s, 0x18); /* RTOFF */
> +
> +    s->dc_base_array = xhci_guest_zalloc(s, 0x800);
> +    s->command_ring = xhci_guest_zalloc(s, 0x1000);
> +    s->event_ring = xhci_guest_zalloc(s, 0x1000);
> +    s->event_ring_seg = xhci_guest_zalloc(s, 0x100);
> +
> +    /* Arbitrary small sizes so we can make them wrap */
> +    s->cr_trb_entries = 0x20;
> +    s->cr_trb_c = 1;
> +    s->er_trb_entries = 0x10;
> +    s->er_trb_c = 1;
> +
> +    ev_seg.addr_low = cpu_to_le32(s->event_ring & 0xffffffff);
> +    ev_seg.addr_high = cpu_to_le32(s->event_ring >> 32);
> +    ev_seg.size = cpu_to_le32(0x10);
> +    ev_seg.rsvd = 0;
> +    qtest_memwrite(s->parent->qts, s->event_ring_seg, &ev_seg, sizeof(ev_seg));
> +
> +    xhci_op_writel(s, 0x0, USBCMD_HCRST); /* USBCMD */
> +    do {
> +        value = xhci_op_readl(s, 0x4); /* USBSTS */
> +    } while (value & (1 << 11)); /* CNR */
> +
> +    xhci_op_writel(s, 0x38, s->maxslots); /* CONFIG */
> +
> +    /* DCBAAP */
> +    xhci_op_writel(s, 0x30, s->dc_base_array & 0xffffffff);
> +    xhci_op_writel(s, 0x34, s->dc_base_array >> 32);
> +
> +    /* CRCR */
> +    xhci_op_writel(s, 0x18, (s->command_ring & 0xffffffff) | s->cr_trb_c);
> +    xhci_op_writel(s, 0x1c, s->command_ring >> 32);
> +
> +    xhci_rt_writel(s, 0x28, 1); /* ERSTSZ */
> +
> +    /* ERSTBA */
> +    xhci_rt_writel(s, 0x30, s->event_ring_seg & 0xffffffff);
> +    xhci_rt_writel(s, 0x34, s->event_ring_seg >> 32);
> +
> +    /* ERDP */
> +    xhci_rt_writel(s, 0x38, s->event_ring & 0xffffffff);
> +    xhci_rt_writel(s, 0x3c, s->event_ring >> 32);
> +
> +    qpci_msix_enable(s->dev);
> +    xhci_op_writel(s, 0x0, USBCMD_RS | USBCMD_INTE); /* RUN + INTE */
> +
> +    /* Enable interrupts on ER IMAN */
> +    xhci_rt_writel(s, 0x20, IMAN_IE);
> +
> +    assert(!qpci_msix_pending(s->dev, 0));
> +
> +    /* Wrap the command and event rings with no-ops a few times */
> +    for (i = 0; i < 100; i++) {
> +        /* Issue a command ring no-op */
> +        memset(&trb, 0, sizeof(trb));
> +        trb.control |= CR_NOOP << TRB_TYPE_SHIFT;
> +        trb.control |= TRB_TR_IOC;
> +        submit_cr_trb(s, &trb);
> +        wait_event_trb(s, &trb);
> +    }
> +
> +    /* Query ports */
> +    for (i = 0; i < s->maxports; i++) {
> +        value = xhci_port_readl(s, i, 0); /* PORTSC */
> +
> +        /* Only first port should be attached and enabled */
> +        if (i == 0) {
> +            g_assert(value & PORTSC_CCS);
> +            g_assert(value & PORTSC_PED);
> +	    /* Port Speed must be identified */
> +	    g_assert(((value >> PORTSC_SPEED_SHIFT) & PORTSC_SPEED_MASK) != 0);
> +        } else {
> +            g_assert(!(value & PORTSC_CCS));
> +            g_assert(!(value & PORTSC_PED));
> +            g_assert(((value >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK) == 5);
> +        }
> +    }
> +
> +    /* Issue a command ring enable slot */
> +    memset(&trb, 0, sizeof(trb));
> +    trb.control |= CR_ENABLE_SLOT << TRB_TYPE_SHIFT;
> +    trb.control |= TRB_TR_IOC;
> +    submit_cr_trb(s, &trb);
> +    wait_event_trb(s, &trb);
> +    slotid = (trb.control >> TRB_CR_SLOTID_SHIFT) & 0xff;
> +
> +    s->slots[slotid].transfer_ring = xhci_guest_zalloc(s, 0x1000);
> +    s->slots[slotid].tr_trb_entries = 0x10;
> +    s->slots[slotid].tr_trb_c = 1;
> +
> +    /* 32-byte input context size, should check HCCPARAMS1 for 64-byte size */
> +    input_context = xhci_guest_zalloc(s, 0x420);
> +
> +    /* Set input control context */
> +    ((uint32_t *)mem)[1] = cpu_to_le32(0x3); /* Add device contexts 0 and 1 */
> +    ((uint32_t *)mem)[8] = cpu_to_le32(1 << 27); /* 1 context entry */
> +    ((uint32_t *)mem)[9] = cpu_to_le32(1 << 16); /* 1 port number */
> +
> +    /* Set endpoint 0 context */
> +    ((uint32_t *)mem)[16] = 0;
> +    ((uint32_t *)mem)[17] = cpu_to_le32((ET_CONTROL << EP_TYPE_SHIFT) |
> +                                        (0x200 << 16)); /* max packet sz XXX? */
> +    ((uint32_t *)mem)[18] = cpu_to_le32((s->slots[slotid].transfer_ring & 0xffffffff) | 1); /* DCS=1 */
> +    ((uint32_t *)mem)[19] = cpu_to_le32(s->slots[slotid].transfer_ring >> 32);
> +    ((uint32_t *)mem)[20] = cpu_to_le32(0x200); /* Average TRB length */
> +    qtest_memwrite(s->parent->qts, input_context, mem, 0x420);
> +
> +    s->slots[slotid].device_context = xhci_guest_zalloc(s, 0x400);
> +
> +    ((uint64_t *)mem)[0] = cpu_to_le64(s->slots[slotid].device_context);
> +    qtest_memwrite(s->parent->qts, s->dc_base_array + 8*slotid, mem, 8);
> +
> +    /* Issue a command ring address device */
> +    memset(&trb, 0, sizeof(trb));
> +    trb.parameter = input_context;
> +    trb.control |= CR_ADDRESS_DEVICE << TRB_TYPE_SHIFT;
> +    trb.control |= slotid << TRB_CR_SLOTID_SHIFT;
> +    submit_cr_trb(s, &trb);
> +    wait_event_trb(s, &trb);
> +
> +    /* XXX: Check EP state is running? */
> +
> +    /* Shut it down */
> +    qpci_msix_disable(s->dev);
> +
> +    guest_free(&s->parent->alloc, s->slots[slotid].device_context);
> +    guest_free(&s->parent->alloc, s->slots[slotid].transfer_ring);
> +    guest_free(&s->parent->alloc, input_context);
> +    guest_free(&s->parent->alloc, s->event_ring);
> +    guest_free(&s->parent->alloc, s->event_ring_seg);
> +    guest_free(&s->parent->alloc, s->command_ring);
> +    guest_free(&s->parent->alloc, s->dc_base_array);
> +
> +    xhci_shutdown(s);
> +}
> +
> +/* tests */
>  int main(int argc, char **argv)
>  {
>      int ret;
> +    const char *arch;
>  
>      g_test_init(&argc, &argv, NULL);
>  
> +    /* Check architecture */
> +    arch = qtest_get_arch();
> +    if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
> +        g_test_message("Skipping test for non-x86");
> +        return 0;
> +    }
> +
> +    if (!qtest_has_device("nec-usb-xhci")) {
> +        return 0;
> +    }
> +
>      qtest_add_func("/xhci/pci/hotplug", test_xhci_hotplug);
>      if (qtest_has_device("usb-uas")) {
>          qtest_add_func("/xhci/pci/hotplug/usb-uas", test_usb_uas_hotplug);
> @@ -56,11 +549,12 @@ int main(int argc, char **argv)
>      if (qtest_has_device("usb-ccid")) {
>          qtest_add_func("/xhci/pci/hotplug/usb-ccid", test_usb_ccid_hotplug);
>      }
> +    if (qtest_has_device("usb-storage")) {
> +        qtest_add_func("/xhci/pci/xhci-stress-rings", pci_xhci_stress_rings);
> +    }
>  
> -    qtest_start("-device nec-usb-xhci,id=xhci"
> -                " -drive id=drive0,if=none,file=null-co://,"
> -                "file.read-zeroes=on,format=raw");
>      ret = g_test_run();
> +
>      qtest_end();
>  
>      return ret;


  reply	other threads:[~2024-11-11 14:32 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-08 15:42 [RFC PATCH 0/5] Add XHCI TR NOOP support, plus PCI, MSIX changes Nicholas Piggin
2024-11-08 15:42 ` [RFC PATCH 1/5] qtest/pci: Enforce balanced iomap/unmap Nicholas Piggin
2024-11-11 14:09   ` Fabiano Rosas
2024-11-08 15:42 ` [RFC PATCH 2/5] qtest/libqos/pci: Fix msix_enable sharing bar0 Nicholas Piggin
2024-11-13 22:14   ` Fabiano Rosas
2024-11-08 15:42 ` [RFC PATCH 3/5] pci/msix: Implement PBA writes Nicholas Piggin
2024-11-08 15:42 ` [RFC PATCH 4/5] qtest/xhci: Add controller and device setup and ring tests Nicholas Piggin
2024-11-11 14:32   ` Fabiano Rosas [this message]
2024-11-27  1:46     ` Nicholas Piggin
2024-11-08 15:42 ` [RFC PATCH 5/5] hw/usb: Support XHCI TR NOOP commands Nicholas Piggin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87msi5j0y8.fsf@suse.de \
    --to=farosas@suse.de \
    --cc=kraxel@redhat.com \
    --cc=lvivier@redhat.com \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=mst@redhat.com \
    --cc=npiggin@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.