public inbox for qemu-arm@nongnu.org
 help / color / mirror / Atom feed
From: Jamin Lin <jamin_lin@aspeedtech.com>
To: "Cédric Le Goater" <clg@kaod.org>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	"Steven Lee" <steven_lee@aspeedtech.com>,
	"Troy Lee" <leetroy@gmail.com>,
	"Andrew Jeffery" <andrew@codeconstruct.com.au>,
	"Joel Stanley" <joel@jms.id.au>,
	"open list:ASPEED BMCs" <qemu-arm@nongnu.org>,
	"open list:All patches CC here" <qemu-devel@nongnu.org>
Cc: Jamin Lin <jamin_lin@aspeedtech.com>,
	Troy Lee <troy_lee@aspeedtech.com>,
	 Kane Chen <kane_chen@aspeedtech.com>,
	"flwu@google.com" <flwu@google.com>,
	 "nabihestefan@google.com" <nabihestefan@google.com>
Subject: [PATCH v1 03/13] hw/usb/hcd-ehci: Change descriptor addresses to 64-bit
Date: Wed, 11 Mar 2026 07:26:19 +0000	[thread overview]
Message-ID: <20260311072614.1095587-4-jamin_lin@aspeedtech.com> (raw)
In-Reply-To: <20260311072614.1095587-1-jamin_lin@aspeedtech.com>

Change internal EHCI descriptor addresses from uint32_t to uint64_t.

The following fields are updated:
- EHCIPacket::qtdaddr
- EHCIQueue::{qhaddr, qtdaddr}
- EHCIState::{a_fetch_addr, p_fetch_addr}

Update get_dwords() and put_dwords() to take 64-bit addresses and
propagate the type change through the descriptor traversal paths.

Adjust NLPTR_GET() to operate on 64-bit values:

    #define NLPTR_GET(x) ((x) & ~(uint64_t)0x1f)

so that link pointer masking works correctly when descriptor
addresses exceed 32-bit space. The previous mask (0xffffffe0)
implicitly truncated addresses to 32 bits.

This patch does not change the on-wire descriptor layout yet.
It only removes the internal 32-bit address limit and prepares
for later patches that will add full 64-bit QH/qTD/iTD/siTD support.

Since the type of fetch_addr changes from 32-bit to 64-bit,
bump the VMState version.

No functional change.

Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
 hw/usb/hcd-ehci.h | 10 +++----
 hw/usb/hcd-ehci.c | 67 +++++++++++++++++++++++++----------------------
 2 files changed, 41 insertions(+), 36 deletions(-)

diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index ed44935302..df87f8145f 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -226,7 +226,7 @@ struct EHCIPacket {
     QTAILQ_ENTRY(EHCIPacket) next;
 
     EHCIqtd qtd;           /* copy of current QTD (being worked on) */
-    uint32_t qtdaddr;      /* address QTD read from                 */
+    uint64_t qtdaddr;      /* address QTD read from                 */
 
     USBPacket packet;
     QEMUSGList sgl;
@@ -247,8 +247,8 @@ struct EHCIQueue {
      * when guest removes an entry (doorbell, handshake sequence)
      */
     EHCIqh qh;             /* copy of current QH (being worked on) */
-    uint32_t qhaddr;       /* address QH read from                 */
-    uint32_t qtdaddr;      /* address QTD read from                */
+    uint64_t qhaddr;       /* address QH read from                 */
+    uint64_t qtdaddr;      /* address QTD read from                */
     int last_pid;          /* pid of last packet executed          */
     USBDevice *dev;
     QTAILQ_HEAD(, EHCIPacket) packets;
@@ -312,8 +312,8 @@ struct EHCIState {
     EHCIQueueHead pqueues;
 
     /* which address to look at next */
-    uint32_t a_fetch_addr;
-    uint32_t p_fetch_addr;
+    uint64_t a_fetch_addr;
+    uint64_t p_fetch_addr;
 
     USBPacket ipacket;
     QEMUSGList isgl;
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index e2ff0f5874..87c3991313 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -71,7 +71,7 @@ typedef enum {
 } EHCI_STATES;
 
 /* macros for accessing fields within next link pointer entry */
-#define NLPTR_GET(x)             ((x) & 0xffffffe0)
+#define NLPTR_GET(x)             ((x) & ~(uint64_t)0x1f)
 #define NLPTR_TYPE_GET(x)        (((x) >> 1) & 3)
 #define NLPTR_TBIT(x)            ((x) & 1)  /* 1=invalid, 0=valid */
 
@@ -286,7 +286,7 @@ static int ehci_get_state(EHCIState *s, int async)
     return async ? s->astate : s->pstate;
 }
 
-static void ehci_set_fetch_addr(EHCIState *s, int async, uint32_t addr)
+static void ehci_set_fetch_addr(EHCIState *s, int async, uint64_t addr)
 {
     if (async) {
         s->a_fetch_addr = addr;
@@ -295,7 +295,7 @@ static void ehci_set_fetch_addr(EHCIState *s, int async, uint32_t addr)
     }
 }
 
-static int ehci_get_fetch_addr(EHCIState *s, int async)
+static uint64_t ehci_get_fetch_addr(EHCIState *s, int async)
 {
     return async ? s->a_fetch_addr : s->p_fetch_addr;
 }
@@ -372,7 +372,7 @@ static inline bool ehci_periodic_enabled(EHCIState *s)
 }
 
 /* Get an array of dwords from main memory */
-static inline int get_dwords(EHCIState *ehci, uint32_t addr,
+static inline int get_dwords(EHCIState *ehci, uint64_t addr,
                              uint32_t *buf, int num)
 {
     int i;
@@ -394,7 +394,7 @@ static inline int get_dwords(EHCIState *ehci, uint32_t addr,
 }
 
 /* Put an array of dwords in to main memory */
-static inline int put_dwords(EHCIState *ehci, uint32_t addr,
+static inline int put_dwords(EHCIState *ehci, uint64_t addr,
                              uint32_t *buf, int num)
 {
     int i;
@@ -548,7 +548,7 @@ static void ehci_free_packet(EHCIPacket *p)
 
 /* queue management */
 
-static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
+static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint64_t addr, int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q;
@@ -621,7 +621,7 @@ static void ehci_free_queue(EHCIQueue *q, const char *warn)
     g_free(q);
 }
 
-static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
+static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint64_t addr,
                                         int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
@@ -1133,7 +1133,7 @@ static void ehci_flush_qh(EHCIQueue *q)
 {
     uint32_t *qh = (uint32_t *) &q->qh;
     uint32_t dwords = sizeof(EHCIqh) >> 2;
-    uint32_t addr = NLPTR_GET(q->qhaddr);
+    uint64_t addr = NLPTR_GET(q->qhaddr);
 
     put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
 }
@@ -1279,8 +1279,8 @@ static void ehci_execute_complete(EHCIQueue *q)
     assert(p->async == EHCI_ASYNC_INITIALIZED ||
            p->async == EHCI_ASYNC_FINISHED);
 
-    DPRINTF("execute_complete: qhaddr 0x%x, next 0x%x, qtdaddr 0x%x, "
-            "status %d, actual_length %d\n",
+    DPRINTF("execute_complete: qhaddr 0x%" PRIx64 ", next 0x%x, "
+            "qtdaddr 0x%" PRIx64 ", status %d, actual_length %d\n",
             q->qhaddr, q->qh.next, q->qtdaddr,
             p->packet.status, p->packet.actual_length);
 
@@ -1389,9 +1389,10 @@ static int ehci_execute(EHCIPacket *p, const char *action)
 
     trace_usb_ehci_packet_action(p->queue, p, action);
     usb_handle_packet(p->queue->dev, &p->packet);
-    DPRINTF("submit: qh 0x%x next 0x%x qtd 0x%x pid 0x%x len %zd endp 0x%x "
-            "status %d actual_length %d\n", p->queue->qhaddr, p->qtd.next,
-            p->qtdaddr, p->pid, p->packet.iov.size, endp, p->packet.status,
+    DPRINTF("submit: qh 0x%" PRIx64 " next 0x%x qtd 0x%" PRIx64
+            " pid 0x%x len %zd endp 0x%x status %d actual_length %d\n",
+            p->queue->qhaddr, p->qtd.next, p->qtdaddr, p->pid,
+            p->packet.iov.size, endp, p->packet.status,
             p->packet.actual_length);
 
     if (p->packet.actual_length > BUFF_SIZE) {
@@ -1405,12 +1406,13 @@ static int ehci_execute(EHCIPacket *p, const char *action)
 /* 4.7.2 */
 static int ehci_process_itd(EHCIState *ehci,
                             EHCIitd *itd,
-                            uint32_t addr)
+                            uint64_t addr)
 {
     USBDevice *dev;
     USBEndpoint *ep;
     uint32_t i, len, pid, dir, devaddr, endp;
-    uint32_t pg, off, ptr1, ptr2, max, mult;
+    uint32_t pg, off, max, mult;
+    uint64_t ptr1, ptr2;
 
     ehci->periodic_sched_active = PERIODIC_ACTIVE;
 
@@ -1525,7 +1527,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
     EHCIqh qh;
     int i = 0;
     int again = 0;
-    uint32_t entry = ehci->asynclistaddr;
+    uint64_t entry = ehci->asynclistaddr;
 
     /* set reclamation flag at start event (4.8.6) */
     if (async) {
@@ -1575,7 +1577,7 @@ out:
 static int ehci_state_fetchentry(EHCIState *ehci, int async)
 {
     int again = 0;
-    uint32_t entry = ehci_get_fetch_addr(ehci, async);
+    uint64_t entry = ehci_get_fetch_addr(ehci, async);
 
     if (NLPTR_TBIT(entry)) {
         ehci_set_state(ehci, async, EST_ACTIVE);
@@ -1606,7 +1608,7 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async)
 
     default:
         /* TODO: handle FSTN type */
-        fprintf(stderr, "FETCHENTRY: entry at %X is of type %u "
+        fprintf(stderr, "FETCHENTRY: entry at %" PRIx64 "is of type %" PRIu64
                 "which is not supported yet\n", entry, NLPTR_TYPE_GET(entry));
         return -1;
     }
@@ -1617,7 +1619,7 @@ out:
 
 static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
 {
-    uint32_t entry;
+    uint64_t entry;
     EHCIQueue *q;
     EHCIqh qh;
 
@@ -1669,8 +1671,9 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
         if (ehci->usbsts & USBSTS_REC) {
             ehci_clear_usbsts(ehci, USBSTS_REC);
         } else {
-            DPRINTF("FETCHQH:  QH 0x%08x. H-bit set, reclamation status reset"
-                       " - done processing\n", q->qhaddr);
+            DPRINTF("FETCHQH:  QH 0x%" PRIx64
+                    ". H-bit set, reclamation status reset - "
+                    "done processing\n", q->qhaddr);
             ehci_set_state(ehci, async, EST_ACTIVE);
             q = NULL;
             goto out;
@@ -1679,7 +1682,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
 
 #if EHCI_DEBUG
     if (q->qhaddr != q->qh.next) {
-        DPRINTF("FETCHQH:  QH 0x%08x (h %x halt %x active %x) next 0x%08x\n",
+        DPRINTF("FETCHQH:  QH 0x%" PRIx64
+                " (h %x halt %x active %x) next 0x%08x\n",
                q->qhaddr,
                q->qh.epchar & QH_EPCHAR_H,
                q->qh.token & QTD_TOKEN_HALT,
@@ -1708,7 +1712,7 @@ out:
 
 static int ehci_state_fetchitd(EHCIState *ehci, int async)
 {
-    uint32_t entry;
+    uint64_t entry;
     EHCIitd itd;
 
     assert(!async);
@@ -1734,7 +1738,7 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async)
 
 static int ehci_state_fetchsitd(EHCIState *ehci, int async)
 {
-    uint32_t entry;
+    uint64_t entry;
     EHCIsitd sitd;
 
     assert(!async);
@@ -1804,7 +1808,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
     EHCIqtd qtd;
     EHCIPacket *p;
     int again = 1;
-    uint32_t addr;
+    uint64_t addr;
 
     addr = NLPTR_GET(q->qtdaddr);
     if (get_dwords(q->ehci, addr +  8, &qtd.token,   1) < 0) {
@@ -1887,7 +1891,7 @@ static int ehci_fill_queue(EHCIPacket *p)
     USBEndpoint *ep = p->packet.ep;
     EHCIQueue *q = p->queue;
     EHCIqtd qtd = p->qtd;
-    uint32_t qtdaddr;
+    uint64_t qtdaddr;
 
     for (;;) {
         if (NLPTR_TBIT(qtd.next) != 0) {
@@ -2010,7 +2014,8 @@ static int ehci_state_executing(EHCIQueue *q)
 static int ehci_state_writeback(EHCIQueue *q)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
-    uint32_t *qtd, addr;
+    uint32_t *qtd;
+    uint64_t addr;
     int again = 0;
 
     /*  Write back the QTD from the QH area */
@@ -2484,8 +2489,8 @@ static void usb_ehci_vm_state_change(void *opaque, bool running, RunState state)
 
 const VMStateDescription vmstate_ehci = {
     .name        = "ehci-core",
-    .version_id  = 2,
-    .minimum_version_id  = 1,
+    .version_id  = 3,
+    .minimum_version_id  = 2,
     .pre_save    = usb_ehci_pre_save,
     .post_load   = usb_ehci_post_load,
     .fields = (const VMStateField[]) {
@@ -2513,8 +2518,8 @@ const VMStateDescription vmstate_ehci = {
         /* schedule state */
         VMSTATE_UINT32(astate, EHCIState),
         VMSTATE_UINT32(pstate, EHCIState),
-        VMSTATE_UINT32(a_fetch_addr, EHCIState),
-        VMSTATE_UINT32(p_fetch_addr, EHCIState),
+        VMSTATE_UINT64(a_fetch_addr, EHCIState),
+        VMSTATE_UINT64(p_fetch_addr, EHCIState),
         VMSTATE_END_OF_LIST()
     }
 };
-- 
2.43.0


  parent reply	other threads:[~2026-03-11  7:28 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-11  7:26 [PATCH v1 00/13] hw/usb/ehci: Add 64-bit descriptor addressing support Jamin Lin
2026-03-11  7:26 ` [PATCH v1 01/13] hw/usb/hcd-ehci.h: Fix coding style issues reported by checkpatch Jamin Lin
2026-03-11  7:26 ` [PATCH v1 02/13] hw/usb/hcd-ehci.c: " Jamin Lin
2026-03-11  7:26 ` Jamin Lin [this message]
2026-03-11  7:26 ` [PATCH v1 04/13] hw/usb/trace-events: Print EHCI queue and transfer addresses as 64-bit Jamin Lin
2026-03-11  7:26 ` [PATCH v1 05/13] hw/usb/hcd-ehci: Add property to advertise 64-bit addressing capability Jamin Lin
2026-03-11  7:26 ` [PATCH v1 06/13] hw/usb/hcd-ehci: Reject CTRLDSSEGMENT writes without 64-bit capability Jamin Lin
2026-03-11  7:26 ` [PATCH v1 07/13] hw/usb/hcd-ehci: Implement 64-bit QH descriptor addressing Jamin Lin
2026-03-11  7:26 ` [PATCH v1 08/13] hw/usb/hcd-ehci: Implement 64-bit qTD " Jamin Lin
2026-03-11  7:26 ` [PATCH v1 09/13] hw/usb/hcd-ehci: Implement 64-bit iTD " Jamin Lin
2026-03-11  7:26 ` [PATCH v1 10/13] hw/usb/hcd-ehci: Implement 64-bit siTD " Jamin Lin
2026-03-11  7:26 ` [PATCH v1 11/13] hw/usb/hcd-ehci: Add descriptor address offset property Jamin Lin
2026-03-11  7:26 ` [PATCH v1 12/13] hw/arm/aspeed_ast27x0: Enable 64-bit EHCI DMA addressing Jamin Lin
2026-03-11  7:26 ` [PATCH v1 13/13] hw/arm/aspeed_ast27x0: Set EHCI descriptor address offset Jamin Lin

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=20260311072614.1095587-4-jamin_lin@aspeedtech.com \
    --to=jamin_lin@aspeedtech.com \
    --cc=andrew@codeconstruct.com.au \
    --cc=clg@kaod.org \
    --cc=flwu@google.com \
    --cc=joel@jms.id.au \
    --cc=kane_chen@aspeedtech.com \
    --cc=leetroy@gmail.com \
    --cc=nabihestefan@google.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=steven_lee@aspeedtech.com \
    --cc=troy_lee@aspeedtech.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox