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 <[email protected]>
---
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