Hi Cédric, Philippe
> Subject: Re: [PATCH v6 00/11] hw/usb/ehci: Add 64-bit descriptor addressing
> support
>
> On 7/9/26 23:09, Philippe Mathieu-Daudé wrote:
> > On 12/5/26 16:47, Cédric Le Goater wrote:
> >> + Gerd, Marc-André,
> >>
> >> May be they can provide some more feedback.
> >>
> >> On 5/11/26 08:13, Cédric Le Goater wrote:
> >>> On 5/4/26 07:27, Cédric Le Goater wrote:
> >>>> On 5/4/26 04:53, Jamin Lin wrote:
> >>>>> EHCI supports 64-bit addressing through the CTRLDSSEGMENT
> >>>>> register, which provides the upper 32 bits of descriptor addresses
> >>>>> when the controller advertises 64-bit capability.
> >>>>>
> >>>>> Currently QEMU EHCI model only partially supports this
> >>>>> functionality and descriptor addresses are effectively treated as
> >>>>> 32-bit. This becomes problematic on systems where system memory is
> >>>>> located above the 4GB boundary.
> >>>>>
> >>>>> The Linux EHCI driver enables 64-bit addressing if the controller
> >>>>> advertises the capability. During initialization it programs the
> >>>>> segment register to zero:
> >>>>>
> >>>>> https://github.com/torvalds/linux/blob/master/drivers/usb/host/
> >>>>> ehci-hcd.c#L600
> >>>>>
> >>>>> The driver also notes that descriptor structures allocated from
> >>>>> the DMA pool use segment zero semantics. Descriptor memory is
> >>>>> allocated using the DMA API and platforms may configure a 64-bit
> >>>>> DMA mask, allowing descriptor memory to be placed above 4GB.
> >>>>>
> >>>>> On AST2700 platforms, system DRAM is mapped at 0x400000000. As a
> >>>>> result, descriptor addresses constructed directly from the EHCI
> >>>>> registers do not match the actual system addresses used by the
> >>>>> controller when accessing queue heads (QH) and queue element
> >>>>> transfer descriptors (qTD).
> >>>>>
> >>>>> This patch series implements full 64-bit descriptor addressing
> >>>>> support in the EHCI emulation. Descriptor address handling is
> >>>>> updated to use 64-bit values and the descriptor structures (QH,
> >>>>> qTD, iTD and siTD) are extended to support the upper address bits
> >>>>> provided by the segment register.
> >>>>>
> >>>>> Add a ctrldssegment-default property so platforms can provide a
> >>>>> descriptor address offset when constructing descriptor addresses.
> >>>>> This allows systems where DRAM resides above 4GB to access EHCI
> >>>>> descriptors correctly.
> >>>>>
> >>>>> The AST2700 machine uses this property to account for its DRAM
> >>>>> mapping at 0x400000000 and enables 64-bit EHCI DMA addressing.
> >>>>>
> >>>>> Test Result:
> >>>>> 1. EHCI 32bits with ast2600-evb machine Command line:
> >>>>> ./build/qemu-system-arm \
> >>>>> -machine ast2600-evb \
> >>>>> -m 1G \
> >>>>> -drive file=image-bmc,if=mtd,format=raw \
> >>>>> -nographic \
> >>>>> -device usb-kbd,bus=usb-bus.1,id=mykbd \
> >>>>> -drive id=usbdisk,if=none,file=image0.ext4,format=raw \
> >>>>> -device usb-storage,bus=usb-bus.1,id=mystorage,drive=usbdisk
> >>>>> -snapshot \
> >>>>> -nographic
> >>>>> Result:
> >>>>> unable to initialize usb specBus 001 Device 001: ID 1d6b:0002
> >>>>> Linux 6.18.3-v00.08.01-g172b7e27a30d ehci_hcd EHCI Host Controller
> >>>>> Bus 001 Device 002: ID 0627:0001 QEMU QEMU USB Keyboard Bus 001
> >>>>> Device 003: ID 46f4:0001 QEMU QEMU USB HARDDRIVE Bus 002
> Device
> >>>>> 001: ID 1d6b:0001 Linux 6.18.3-v00.08.01- g172b7e27a30d uhci_hcd
> >>>>> Generic UHCI Host Controller
> >>>>>
> >>>>> 2. EHCI 64bits with ast2700a2-evb machine Command line:
> >>>>> ./build/qemu-system-aarch64 -M ast2700a2-evb -nographic\
> >>>>> -bios ast27x0_bootrom.bin \
> >>>>> -drive file=image-bmc,format=raw,if=mtd \
> >>>>> -snapshot \
> >>>>> -device usb-kbd,bus=usb-bus.3,id=mykbd \
> >>>>> -drive id=usbdisk,if=none,file=image0.ext4,format=raw \
> >>>>> -device usb-storage,bus=usb-bus.3,id=mystorage,drive=usbdisk
> >>>>> Result:
> >>>>> root@ast2700-default:~# lsusb
> >>>>> unable to initialize usb specBus 001 Device 001: ID 1d6b:0001
> >>>>> Linux 6.18.3-v00.08.01-g172b7e27a30d uhci_hcd Generic UHCI Host
> >>>>> Controller Bus 002 Device 001: ID 1d6b:0002 Linux
> >>>>> 6.18.3-v00.08.01- g172b7e27a30d ehci_hcd EHCI Host Controller Bus
> >>>>> 002 Device 002: ID 0627:0001 QEMU QEMU USB Keyboard Bus 002
> Device
> >>>>> 003: ID 46f4:0001 QEMU QEMU USB HARDDRIVE
> >>>>> v1
> >>>>> 1. Fix checkpatch coding style issues
> >>>>> 2. Implement 64-bit addressing for QH/qTD/iTD/siTD descriptors
> >>>>> 3. Add descriptor address offset property
> >>>>> 4. Enable 64-bit EHCI DMA addressing on AST2700
> >>>>> 5. Configure descriptor address offset for AST2700
> >>>>>
> >>>>> v2
> >>>>> 1. Remove unused EHCIfstn structure and dead code
> >>>>> 2. Replace fprintf(stderr, ...) with
> >>>>> qemu_log_mask(LOG_GUEST_ERROR)
> >>>>> 3. Replace DPRINTF debug logs with trace events
> >>>>> 4. Add functional tests for USB EHCI on AST2600 and AST2700
> >>>>> A1/A2
> >>>>> 5. Fix review issue
> >>>>>
> >>>>> v3:
> >>>>> 1. Add Migration version test function
> >>>>> 2. Add EHCI 64-bit buffer pointer fields description in commit
> >>>>> log
> >>>>>
> >>>>> v4:
> >>>>> 1. Reorder patches in the series
> >>>>> 2. Fix EHCI migration issues
> >>>>> 3. Introduce a common properties macro for both sysbus and PCI
> >>>>> 4. Drop the descriptor address offset property
> >>>>> 5. Add ctrldssegment-default property
> >>>>> 6. Address review comments
> >>>>>
> >>>>> v5:
> >>>>> 1. Add 11.0 machine compatibility properties
> >>>>>
> >>>>> v6:
> >>>>> 1. Update reviewer suggested improvements.
> >>>>> Jamin Lin (11):
> >>>>> tests/functional/arm/test_aspeed_ast2600_sdk: Add USB EHCI test
> >>>>> for
> >>>>> AST2600 SDK
> >>>>> hw/usb/hcd-ehci: Change descriptor addresses to 64-bit with
> >>>>> migration
> >>>>> compatibility
> >>>>> hw/usb/hcd-ehci: Add property to advertise 64-bit addressing
> >>>>> capability
> >>>>> hw/usb/hcd-ehci: Implement 64-bit QH descriptor addressing
> >>>>> hw/usb/hcd-ehci: Implement 64-bit qTD descriptor addressing
> >>>>> hw/usb/hcd-ehci: Implement 64-bit iTD descriptor addressing
> >>>>> hw/usb/hcd-ehci: Implement 64-bit siTD descriptor addressing
> >>>>> hw/usb/hcd-ehci: Add ctrldssegment-default property
> >>>>> hw/arm/aspeed_ast27x0: Set EHCI ctrldssegment-default
> >>>>> hw/arm/aspeed_ast27x0: Enable 64-bit EHCI DMA addressing
> >>>>> tests/functional/aarch64/test_aspeed_ast2700: Add USB EHCI test
> >>>>> for
> >>>>> AST2700 A1/A2
> >>>>>
> >>>>> hw/usb/hcd-ehci.h | 2
> 9 +++-
> >>>>> hw/arm/aspeed_ast27x0.c | 5
> +
> >>>>> hw/core/machine.c |
> 5 +-
> >>>>> hw/usb/hcd-ehci.c | 162
> ++++++++++++
> >>>>> +-----
> >>>>> hw/usb/trace-events | 26
> +--
> >>>>> .../aarch64/test_aspeed_ast2700a1.py | 7 +
> >>>>> .../aarch64/test_aspeed_ast2700a2.py | 7 +
> >>>>> .../functional/arm/test_aspeed_ast2600_sdk.py | 7 +
> >>>>> 8 files changed, 185 insertions(+), 63 deletions(-)
> >>>>>
> >>>>
> >>>> Applied to
> >>>>
> >>>> https://github.com/legoater/qemu aspeed-next
> >>>
> >>> Jamin,
> >>>
> >>> I dropped the series from aspeed-next and kept :
> >>>
> >>> tests/functional/arm/test_aspeed_ast2600_sdk: Add USB EHCI test
> >>> for AST2600 SDK
> >>>
> >>> The USB subsystem is orphan but it is still used in the virt world.
> >>> This series is modifying the EHCI internals in such way that
> >>> migration is impacted and the CTRLDSSEGMENT (Control Data Structure
> >>> Segment
> >>> Register) implementation is incomplete AFAICT. From EHCI specs :
> >>>
> >>> This register allows the host software to locate all control
> >>> data
> >>> structures within the *same 4 Gigabyte memory segment*.
> >>>
> >>> Linux driver seems buggy too.
> >>>
> >>> Overall, the risk of regression is too high given the time I can
> >>> dedicate to this topic.
> >>>
> >>> Thanks for all the good work you done there, specially for migration.
> >>> If someone can Ack the series and step forward to become USB
> >>> maintainer, then I will reconsider.
> >
> > I'm not an USB expert / maintainer but FWIW this series looked good
> > enough to me when I looked at it. Maybe consider to merge after the
> > 11.1 release?
>
> Yes. I would like to too but ...
>
> The change in size of the EHCIqh and EHCIitd descriptors is a bit worrying since
> these are used for guest DMA, see ehci_flush_qh(), or compare, see
> ehci_verify_qh().
>
> This should be fine for Linux, which has support since day one. Other older
> guest OSes may not allocate the extra space. This is a 20+ year old spec so the
> risk is probably low but I don't have the expertise to assess the impact tbh.
>
> Anyhow if we want the model to be correct, we should not write beyond
> spec-defined descriptor boundaries when in 32-bit mode.
>
> More work ...
>
> Thanks,
>
> C.
Thanks for pointing this out.
I agree that even though the QEMU internal EHCIqh, EHCIqtd, and EHCIitd structures include the extended high buffer pointer fields, we must not access those fields in guest memory when 64-bit addressing capability is not advertised.
I have updated the patch accordingly.
The descriptor DMA size is now selected based on caps_64bit_addr:
When 64-bit addressing is supported and advertised, the complete descriptor, including the high buffer pointer fields, is transferred.
In 32-bit mode, DMA reads and writes stop at the beginning of bufptr_hi, so QEMU does not access memory beyond the descriptor layout defined for 32-bit addressing.
I also clear the local descriptor structures before partial DMA reads. Therefore, the high buffer pointer fields remain zero in 32-bit mode rather than containing stale or uninitialized values.
This has been applied to:
QH fetching, verification, and writeback
qTD fetching and verification
iTD fetching and writeback
For example:
/*
* EHCIqh / EHCIqtd / EHCIitd are sized to always include the extended
* high buffer pointer fields from EHCI 1.0 Appendix B. When 64-bit
* addressing capability is not advertised to the guest, the descriptors
* in guest memory only have the classic 32-bit layout, so DMA transfers
* must not read or write past that boundary.
*/
#define EHCI_QH_DWORDS_32 (offsetof(EHCIqh, bufptr_hi) / sizeof(uint32_t))
#define EHCI_QTD_DWORDS_32 (offsetof(EHCIqtd, bufptr_hi) / sizeof(uint32_t))
#define EHCI_ITD_DWORDS_32 (offsetof(EHCIitd, bufptr_hi) / sizeof(uint32_t))
#define EHCI_QH_DWORDS_32 \
(offsetof(EHCIqh, bufptr_hi) / sizeof(uint32_t))
static uint32_t ehci_qh_dwords(const EHCIState *s)
{
return s->caps_64bit_addr ?
(sizeof(EHCIqh) >> 2) : EHCI_QH_DWORDS_32;
}
ehci_flush_qh() now uses this selected size, so in 32-bit mode it will not write the extended high buffer pointer fields back to guest memory.
Similarly, ehci_state_fetchqtd() only reads qtd.bufptr_hi when caps_64bit_addr is enabled:
memset(qtd.bufptr_hi, 0, sizeof(qtd.bufptr_hi));
if (... ||
(q->ehci->caps_64bit_addr &&
get_dwords(q->ehci, addr + offsetof(EHCIqtd, bufptr_hi),
qtd.bufptr_hi, ARRAY_SIZE(qtd.bufptr_hi)) < 0)) { return 0;
}
This should preserve compatibility with guests that allocate only the original 32-bit EHCI descriptor size, while still allowing the model to support the extended 64-bit descriptor layout.
If you think this approach looks OK, I'll include it in the next revision (v7).
Thanks,
Jamin
+ Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> Subject: RE: [PATCH v6 00/11] hw/usb/ehci: Add 64-bit descriptor addressing
> support
>
> Hi Cédric, Philippe
>
> > Subject: Re: [PATCH v6 00/11] hw/usb/ehci: Add 64-bit descriptor
> > addressing support
> >
> > On 7/9/26 23:09, Philippe Mathieu-Daudé wrote:
> > > On 12/5/26 16:47, Cédric Le Goater wrote:
> > >> + Gerd, Marc-André,
> > >>
> > >> May be they can provide some more feedback.
> > >>
> > >> On 5/11/26 08:13, Cédric Le Goater wrote:
> > >>> On 5/4/26 07:27, Cédric Le Goater wrote:
> > >>>> On 5/4/26 04:53, Jamin Lin wrote:
> > >>>>> EHCI supports 64-bit addressing through the CTRLDSSEGMENT
> > >>>>> register, which provides the upper 32 bits of descriptor
> > >>>>> addresses when the controller advertises 64-bit capability.
> > >>>>>
> > >>>>> Currently QEMU EHCI model only partially supports this
> > >>>>> functionality and descriptor addresses are effectively treated
> > >>>>> as 32-bit. This becomes problematic on systems where system
> > >>>>> memory is located above the 4GB boundary.
> > >>>>>
> > >>>>> The Linux EHCI driver enables 64-bit addressing if the
> > >>>>> controller advertises the capability. During initialization it
> > >>>>> programs the segment register to zero:
> > >>>>>
> > >>>>>
> > >>>>> https://github.com/torvalds/linux/blob/master/drivers/usb/host/
> > >>>>> ehci-hcd.c#L600
> > >>>>>
> > >>>>> The driver also notes that descriptor structures allocated from
> > >>>>> the DMA pool use segment zero semantics. Descriptor memory is
> > >>>>> allocated using the DMA API and platforms may configure a 64-bit
> > >>>>> DMA mask, allowing descriptor memory to be placed above 4GB.
> > >>>>>
> > >>>>> On AST2700 platforms, system DRAM is mapped at 0x400000000. As
> a
> > >>>>> result, descriptor addresses constructed directly from the EHCI
> > >>>>> registers do not match the actual system addresses used by the
> > >>>>> controller when accessing queue heads (QH) and queue element
> > >>>>> transfer descriptors (qTD).
> > >>>>>
> > >>>>> This patch series implements full 64-bit descriptor addressing
> > >>>>> support in the EHCI emulation. Descriptor address handling is
> > >>>>> updated to use 64-bit values and the descriptor structures (QH,
> > >>>>> qTD, iTD and siTD) are extended to support the upper address
> > >>>>> bits provided by the segment register.
> > >>>>>
> > >>>>> Add a ctrldssegment-default property so platforms can provide a
> > >>>>> descriptor address offset when constructing descriptor addresses.
> > >>>>> This allows systems where DRAM resides above 4GB to access EHCI
> > >>>>> descriptors correctly.
> > >>>>>
> > >>>>> The AST2700 machine uses this property to account for its DRAM
> > >>>>> mapping at 0x400000000 and enables 64-bit EHCI DMA addressing.
> > >>>>>
> > >>>>> Test Result:
> > >>>>> 1. EHCI 32bits with ast2600-evb machine Command line:
> > >>>>> ./build/qemu-system-arm \
> > >>>>> -machine ast2600-evb \
> > >>>>> -m 1G \
> > >>>>> -drive file=image-bmc,if=mtd,format=raw \
> > >>>>> -nographic \
> > >>>>> -device usb-kbd,bus=usb-bus.1,id=mykbd \
> > >>>>> -drive id=usbdisk,if=none,file=image0.ext4,format=raw \
> > >>>>> -device usb-storage,bus=usb-bus.1,id=mystorage,drive=usbdisk
> > >>>>> -snapshot \
> > >>>>> -nographic
> > >>>>> Result:
> > >>>>> unable to initialize usb specBus 001 Device 001: ID 1d6b:0002
> > >>>>> Linux 6.18.3-v00.08.01-g172b7e27a30d ehci_hcd EHCI Host
> > >>>>> Controller Bus 001 Device 002: ID 0627:0001 QEMU QEMU USB
> > >>>>> Keyboard Bus 001 Device 003: ID 46f4:0001 QEMU QEMU USB
> > >>>>> HARDDRIVE Bus 002
> > Device
> > >>>>> 001: ID 1d6b:0001 Linux 6.18.3-v00.08.01- g172b7e27a30d uhci_hcd
> > >>>>> Generic UHCI Host Controller
> > >>>>>
> > >>>>> 2. EHCI 64bits with ast2700a2-evb machine Command line:
> > >>>>> ./build/qemu-system-aarch64 -M ast2700a2-evb -nographic\
> > >>>>> -bios ast27x0_bootrom.bin \
> > >>>>> -drive file=image-bmc,format=raw,if=mtd \
> > >>>>> -snapshot \
> > >>>>> -device usb-kbd,bus=usb-bus.3,id=mykbd \
> > >>>>> -drive id=usbdisk,if=none,file=image0.ext4,format=raw \
> > >>>>> -device usb-storage,bus=usb-bus.3,id=mystorage,drive=usbdisk
> > >>>>> Result:
> > >>>>> root@ast2700-default:~# lsusb
> > >>>>> unable to initialize usb specBus 001 Device 001: ID 1d6b:0001
> > >>>>> Linux 6.18.3-v00.08.01-g172b7e27a30d uhci_hcd Generic UHCI Host
> > >>>>> Controller Bus 002 Device 001: ID 1d6b:0002 Linux
> > >>>>> 6.18.3-v00.08.01- g172b7e27a30d ehci_hcd EHCI Host Controller
> > >>>>> Bus
> > >>>>> 002 Device 002: ID 0627:0001 QEMU QEMU USB Keyboard Bus 002
> > Device
> > >>>>> 003: ID 46f4:0001 QEMU QEMU USB HARDDRIVE
> > >>>>> v1
> > >>>>> 1. Fix checkpatch coding style issues
> > >>>>> 2. Implement 64-bit addressing for QH/qTD/iTD/siTD descriptors
> > >>>>> 3. Add descriptor address offset property
> > >>>>> 4. Enable 64-bit EHCI DMA addressing on AST2700
> > >>>>> 5. Configure descriptor address offset for AST2700
> > >>>>>
> > >>>>> v2
> > >>>>> 1. Remove unused EHCIfstn structure and dead code
> > >>>>> 2. Replace fprintf(stderr, ...) with
> > >>>>> qemu_log_mask(LOG_GUEST_ERROR)
> > >>>>> 3. Replace DPRINTF debug logs with trace events
> > >>>>> 4. Add functional tests for USB EHCI on AST2600 and AST2700
> > >>>>> A1/A2
> > >>>>> 5. Fix review issue
> > >>>>>
> > >>>>> v3:
> > >>>>> 1. Add Migration version test function
> > >>>>> 2. Add EHCI 64-bit buffer pointer fields description in commit
> > >>>>> log
> > >>>>>
> > >>>>> v4:
> > >>>>> 1. Reorder patches in the series
> > >>>>> 2. Fix EHCI migration issues
> > >>>>> 3. Introduce a common properties macro for both sysbus and PCI
> > >>>>> 4. Drop the descriptor address offset property
> > >>>>> 5. Add ctrldssegment-default property
> > >>>>> 6. Address review comments
> > >>>>>
> > >>>>> v5:
> > >>>>> 1. Add 11.0 machine compatibility properties
> > >>>>>
> > >>>>> v6:
> > >>>>> 1. Update reviewer suggested improvements.
> > >>>>> Jamin Lin (11):
> > >>>>> tests/functional/arm/test_aspeed_ast2600_sdk: Add USB EHCI
> > >>>>> test for
> > >>>>> AST2600 SDK
> > >>>>> hw/usb/hcd-ehci: Change descriptor addresses to 64-bit with
> > >>>>> migration
> > >>>>> compatibility
> > >>>>> hw/usb/hcd-ehci: Add property to advertise 64-bit addressing
> > >>>>> capability
> > >>>>> hw/usb/hcd-ehci: Implement 64-bit QH descriptor addressing
> > >>>>> hw/usb/hcd-ehci: Implement 64-bit qTD descriptor addressing
> > >>>>> hw/usb/hcd-ehci: Implement 64-bit iTD descriptor addressing
> > >>>>> hw/usb/hcd-ehci: Implement 64-bit siTD descriptor addressing
> > >>>>> hw/usb/hcd-ehci: Add ctrldssegment-default property
> > >>>>> hw/arm/aspeed_ast27x0: Set EHCI ctrldssegment-default
> > >>>>> hw/arm/aspeed_ast27x0: Enable 64-bit EHCI DMA addressing
> > >>>>> tests/functional/aarch64/test_aspeed_ast2700: Add USB EHCI
> > >>>>> test for
> > >>>>> AST2700 A1/A2
> > >>>>>
> >
> >>>>> hw/usb/hcd-ehci.h | 2
> > 9 +++-
> >
> >>>>> hw/arm/aspeed_ast27x0.c | 5
> > +
> > >>>>> hw/core/machine.c |
> > 5 +-
> > >>>>> hw/usb/hcd-ehci.c |
> 162
> > ++++++++++++
> > >>>>> +-----
> >
> >>>>> hw/usb/trace-events | 26
> > +--
> > >>>>> .../aarch64/test_aspeed_ast2700a1.py | 7 +
> > >>>>> .../aarch64/test_aspeed_ast2700a2.py | 7 +
> > >>>>> .../functional/arm/test_aspeed_ast2600_sdk.py | 7 +
> > >>>>> 8 files changed, 185 insertions(+), 63 deletions(-)
> > >>>>>
> > >>>>
> > >>>> Applied to
> > >>>>
> > >>>> https://github.com/legoater/qemu aspeed-next
> > >>>
> > >>> Jamin,
> > >>>
> > >>> I dropped the series from aspeed-next and kept :
> > >>>
> > >>> tests/functional/arm/test_aspeed_ast2600_sdk: Add USB EHCI test
> > >>> for AST2600 SDK
> > >>>
> > >>> The USB subsystem is orphan but it is still used in the virt world.
> > >>> This series is modifying the EHCI internals in such way that
> > >>> migration is impacted and the CTRLDSSEGMENT (Control Data
> > >>> Structure Segment
> > >>> Register) implementation is incomplete AFAICT. From EHCI specs :
> > >>>
> > >>> This register allows the host software to locate all control
> > >>> data
> > >>> structures within the *same 4 Gigabyte memory segment*.
> > >>>
> > >>> Linux driver seems buggy too.
> > >>>
> > >>> Overall, the risk of regression is too high given the time I can
> > >>> dedicate to this topic.
> > >>>
> > >>> Thanks for all the good work you done there, specially for migration.
> > >>> If someone can Ack the series and step forward to become USB
> > >>> maintainer, then I will reconsider.
> > >
> > > I'm not an USB expert / maintainer but FWIW this series looked good
> > > enough to me when I looked at it. Maybe consider to merge after the
> > > 11.1 release?
> >
> > Yes. I would like to too but ...
> >
> > The change in size of the EHCIqh and EHCIitd descriptors is a bit
> > worrying since these are used for guest DMA, see ehci_flush_qh(), or
> > compare, see ehci_verify_qh().
> >
> > This should be fine for Linux, which has support since day one. Other
> > older guest OSes may not allocate the extra space. This is a 20+ year
> > old spec so the risk is probably low but I don't have the expertise to assess
> the impact tbh.
> >
> > Anyhow if we want the model to be correct, we should not write beyond
> > spec-defined descriptor boundaries when in 32-bit mode.
> >
> > More work ...
> >
> > Thanks,
> >
> > C.
>
> Thanks for pointing this out.
>
> I agree that even though the QEMU internal EHCIqh, EHCIqtd, and EHCIitd
> structures include the extended high buffer pointer fields, we must not access
> those fields in guest memory when 64-bit addressing capability is not
> advertised.
>
> I have updated the patch accordingly.
>
> The descriptor DMA size is now selected based on caps_64bit_addr:
>
> When 64-bit addressing is supported and advertised, the complete descriptor,
> including the high buffer pointer fields, is transferred.
> In 32-bit mode, DMA reads and writes stop at the beginning of bufptr_hi, so
> QEMU does not access memory beyond the descriptor layout defined for
> 32-bit addressing.
>
> I also clear the local descriptor structures before partial DMA reads. Therefore,
> the high buffer pointer fields remain zero in 32-bit mode rather than
> containing stale or uninitialized values.
>
> This has been applied to:
>
> QH fetching, verification, and writeback qTD fetching and verification iTD
> fetching and writeback
>
> For example:
> /*
> * EHCIqh / EHCIqtd / EHCIitd are sized to always include the extended
> * high buffer pointer fields from EHCI 1.0 Appendix B. When 64-bit
> * addressing capability is not advertised to the guest, the descriptors
> * in guest memory only have the classic 32-bit layout, so DMA transfers
> * must not read or write past that boundary.
> */
> #define EHCI_QH_DWORDS_32 (offsetof(EHCIqh, bufptr_hi) /
> sizeof(uint32_t))
> #define EHCI_QTD_DWORDS_32 (offsetof(EHCIqtd, bufptr_hi) /
> sizeof(uint32_t)) #define EHCI_ITD_DWORDS_32 (offsetof(EHCIitd, bufptr_hi)
> / sizeof(uint32_t))
>
> #define EHCI_QH_DWORDS_32 \
> (offsetof(EHCIqh, bufptr_hi) / sizeof(uint32_t))
>
> static uint32_t ehci_qh_dwords(const EHCIState *s) {
> return s->caps_64bit_addr ?
> (sizeof(EHCIqh) >> 2) : EHCI_QH_DWORDS_32; }
>
> ehci_flush_qh() now uses this selected size, so in 32-bit mode it will not write
> the extended high buffer pointer fields back to guest memory.
>
> Similarly, ehci_state_fetchqtd() only reads qtd.bufptr_hi when caps_64bit_addr
> is enabled:
>
> memset(qtd.bufptr_hi, 0, sizeof(qtd.bufptr_hi));
>
> if (... ||
> (q->ehci->caps_64bit_addr &&
> get_dwords(q->ehci, addr + offsetof(EHCIqtd, bufptr_hi),
> qtd.bufptr_hi, ARRAY_SIZE(qtd.bufptr_hi)) < 0))
> { return 0;
> }
>
> This should preserve compatibility with guests that allocate only the original
> 32-bit EHCI descriptor size, while still allowing the model to support the
> extended 64-bit descriptor layout.
> If you think this approach looks OK, I'll include it in the next revision (v7).
>
> Thanks,
> Jamin
Hi Cédric, Philippe
> Subject: RE: [PATCH v6 00/11] hw/usb/ehci: Add 64-bit descriptor addressing
> support
>
> + Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
>
> > Subject: RE: [PATCH v6 00/11] hw/usb/ehci: Add 64-bit descriptor
> > addressing support
> >
> > Hi Cédric, Philippe
> >
> > > Subject: Re: [PATCH v6 00/11] hw/usb/ehci: Add 64-bit descriptor
> > > addressing support
> > >
> > > On 7/9/26 23:09, Philippe Mathieu-Daudé wrote:
> > > > On 12/5/26 16:47, Cédric Le Goater wrote:
> > > >> + Gerd, Marc-André,
> > > >>
> > > >> May be they can provide some more feedback.
> > > >>
> > > >> On 5/11/26 08:13, Cédric Le Goater wrote:
> > > >>> On 5/4/26 07:27, Cédric Le Goater wrote:
> > > >>>> On 5/4/26 04:53, Jamin Lin wrote:
> > > >>>>> EHCI supports 64-bit addressing through the CTRLDSSEGMENT
> > > >>>>> register, which provides the upper 32 bits of descriptor
> > > >>>>> addresses when the controller advertises 64-bit capability.
> > > >>>>>
> > > >>>>> Currently QEMU EHCI model only partially supports this
> > > >>>>> functionality and descriptor addresses are effectively treated
> > > >>>>> as 32-bit. This becomes problematic on systems where system
> > > >>>>> memory is located above the 4GB boundary.
> > > >>>>>
> > > >>>>> The Linux EHCI driver enables 64-bit addressing if the
> > > >>>>> controller advertises the capability. During initialization it
> > > >>>>> programs the segment register to zero:
> > > >>>>>
> > > >>>>>
> > > >>>>> https://github.com/torvalds/linux/blob/master/drivers/usb/host
> > > >>>>> /
> > > >>>>> ehci-hcd.c#L600
> > > >>>>>
> > > >>>>> The driver also notes that descriptor structures allocated
> > > >>>>> from the DMA pool use segment zero semantics. Descriptor
> > > >>>>> memory is allocated using the DMA API and platforms may
> > > >>>>> configure a 64-bit DMA mask, allowing descriptor memory to be
> placed above 4GB.
> > > >>>>>
> > > >>>>> On AST2700 platforms, system DRAM is mapped at 0x400000000.
> As
> > a
> > > >>>>> result, descriptor addresses constructed directly from the
> > > >>>>> EHCI registers do not match the actual system addresses used
> > > >>>>> by the controller when accessing queue heads (QH) and queue
> > > >>>>> element transfer descriptors (qTD).
> > > >>>>>
> > > >>>>> This patch series implements full 64-bit descriptor addressing
> > > >>>>> support in the EHCI emulation. Descriptor address handling is
> > > >>>>> updated to use 64-bit values and the descriptor structures
> > > >>>>> (QH, qTD, iTD and siTD) are extended to support the upper
> > > >>>>> address bits provided by the segment register.
> > > >>>>>
> > > >>>>> Add a ctrldssegment-default property so platforms can provide
> > > >>>>> a descriptor address offset when constructing descriptor addresses.
> > > >>>>> This allows systems where DRAM resides above 4GB to access
> > > >>>>> EHCI descriptors correctly.
> > > >>>>>
> > > >>>>> The AST2700 machine uses this property to account for its DRAM
> > > >>>>> mapping at 0x400000000 and enables 64-bit EHCI DMA addressing.
> > > >>>>>
> > > >>>>> Test Result:
> > > >>>>> 1. EHCI 32bits with ast2600-evb machine Command line:
> > > >>>>> ./build/qemu-system-arm \
> > > >>>>> -machine ast2600-evb \
> > > >>>>> -m 1G \
> > > >>>>> -drive file=image-bmc,if=mtd,format=raw \
> > > >>>>> -nographic \
> > > >>>>> -device usb-kbd,bus=usb-bus.1,id=mykbd \
> > > >>>>> -drive id=usbdisk,if=none,file=image0.ext4,format=raw \
> > > >>>>> -device
> > > >>>>> usb-storage,bus=usb-bus.1,id=mystorage,drive=usbdisk
> > > >>>>> -snapshot \
> > > >>>>> -nographic
> > > >>>>> Result:
> > > >>>>> unable to initialize usb specBus 001 Device 001: ID 1d6b:0002
> > > >>>>> Linux 6.18.3-v00.08.01-g172b7e27a30d ehci_hcd EHCI Host
> > > >>>>> Controller Bus 001 Device 002: ID 0627:0001 QEMU QEMU USB
> > > >>>>> Keyboard Bus 001 Device 003: ID 46f4:0001 QEMU QEMU USB
> > > >>>>> HARDDRIVE Bus 002
> > > Device
> > > >>>>> 001: ID 1d6b:0001 Linux 6.18.3-v00.08.01- g172b7e27a30d
> > > >>>>> uhci_hcd Generic UHCI Host Controller
> > > >>>>>
> > > >>>>> 2. EHCI 64bits with ast2700a2-evb machine Command line:
> > > >>>>> ./build/qemu-system-aarch64 -M ast2700a2-evb -nographic\
> > > >>>>> -bios ast27x0_bootrom.bin \
> > > >>>>> -drive file=image-bmc,format=raw,if=mtd \
> > > >>>>> -snapshot \
> > > >>>>> -device usb-kbd,bus=usb-bus.3,id=mykbd \
> > > >>>>> -drive id=usbdisk,if=none,file=image0.ext4,format=raw \
> > > >>>>> -device usb-storage,bus=usb-bus.3,id=mystorage,drive=usbdisk
> > > >>>>> Result:
> > > >>>>> root@ast2700-default:~# lsusb
> > > >>>>> unable to initialize usb specBus 001 Device 001: ID 1d6b:0001
> > > >>>>> Linux 6.18.3-v00.08.01-g172b7e27a30d uhci_hcd Generic UHCI
> > > >>>>> Host Controller Bus 002 Device 001: ID 1d6b:0002 Linux
> > > >>>>> 6.18.3-v00.08.01- g172b7e27a30d ehci_hcd EHCI Host Controller
> > > >>>>> Bus
> > > >>>>> 002 Device 002: ID 0627:0001 QEMU QEMU USB Keyboard Bus 002
> > > Device
> > > >>>>> 003: ID 46f4:0001 QEMU QEMU USB HARDDRIVE
> > > >>>>> v1
> > > >>>>> 1. Fix checkpatch coding style issues
> > > >>>>> 2. Implement 64-bit addressing for QH/qTD/iTD/siTD
> > > >>>>> descriptors
> > > >>>>> 3. Add descriptor address offset property
> > > >>>>> 4. Enable 64-bit EHCI DMA addressing on AST2700
> > > >>>>> 5. Configure descriptor address offset for AST2700
> > > >>>>>
> > > >>>>> v2
> > > >>>>> 1. Remove unused EHCIfstn structure and dead code
> > > >>>>> 2. Replace fprintf(stderr, ...) with
> > > >>>>> qemu_log_mask(LOG_GUEST_ERROR)
> > > >>>>> 3. Replace DPRINTF debug logs with trace events
> > > >>>>> 4. Add functional tests for USB EHCI on AST2600 and AST2700
> > > >>>>> A1/A2
> > > >>>>> 5. Fix review issue
> > > >>>>>
> > > >>>>> v3:
> > > >>>>> 1. Add Migration version test function
> > > >>>>> 2. Add EHCI 64-bit buffer pointer fields description in
> > > >>>>> commit log
> > > >>>>>
> > > >>>>> v4:
> > > >>>>> 1. Reorder patches in the series
> > > >>>>> 2. Fix EHCI migration issues
> > > >>>>> 3. Introduce a common properties macro for both sysbus and
> > > >>>>> PCI
> > > >>>>> 4. Drop the descriptor address offset property
> > > >>>>> 5. Add ctrldssegment-default property
> > > >>>>> 6. Address review comments
> > > >>>>>
> > > >>>>> v5:
> > > >>>>> 1. Add 11.0 machine compatibility properties
> > > >>>>>
> > > >>>>> v6:
> > > >>>>> 1. Update reviewer suggested improvements.
> > > >>>>> Jamin Lin (11):
> > > >>>>> tests/functional/arm/test_aspeed_ast2600_sdk: Add USB EHCI
> > > >>>>> test for
> > > >>>>> AST2600 SDK
> > > >>>>> hw/usb/hcd-ehci: Change descriptor addresses to 64-bit with
> > > >>>>> migration
> > > >>>>> compatibility
> > > >>>>> hw/usb/hcd-ehci: Add property to advertise 64-bit
> > > >>>>> addressing
> > > >>>>> capability
> > > >>>>> hw/usb/hcd-ehci: Implement 64-bit QH descriptor addressing
> > > >>>>> hw/usb/hcd-ehci: Implement 64-bit qTD descriptor addressing
> > > >>>>> hw/usb/hcd-ehci: Implement 64-bit iTD descriptor addressing
> > > >>>>> hw/usb/hcd-ehci: Implement 64-bit siTD descriptor
> > > >>>>> addressing
> > > >>>>> hw/usb/hcd-ehci: Add ctrldssegment-default property
> > > >>>>> hw/arm/aspeed_ast27x0: Set EHCI ctrldssegment-default
> > > >>>>> hw/arm/aspeed_ast27x0: Enable 64-bit EHCI DMA addressing
> > > >>>>> tests/functional/aarch64/test_aspeed_ast2700: Add USB EHCI
> > > >>>>> test for
> > > >>>>> AST2700 A1/A2
> > > >>>>>
> > >
> >
> >>>>> hw/usb/hcd-ehci.h | 2
> > > 9 +++-
> > >
> >
> >>>>> hw/arm/aspeed_ast27x0.c | 5
> > > +
> > > >>>>> hw/core/machine.c |
> > > 5 +-
> > > >>>>> hw/usb/hcd-ehci.c |
> > 162
> > > ++++++++++++
> > > >>>>> +-----
> > >
> >
> >>>>> hw/usb/trace-events | 26
> > > +--
> > > >>>>> .../aarch64/test_aspeed_ast2700a1.py | 7 +
> > > >>>>> .../aarch64/test_aspeed_ast2700a2.py | 7 +
> > > >>>>> .../functional/arm/test_aspeed_ast2600_sdk.py | 7 +
> > > >>>>> 8 files changed, 185 insertions(+), 63 deletions(-)
> > > >>>>>
> > > >>>>
> > > >>>> Applied to
> > > >>>>
> > > >>>> https://github.com/legoater/qemu aspeed-next
> > > >>>
> > > >>> Jamin,
> > > >>>
> > > >>> I dropped the series from aspeed-next and kept :
> > > >>>
> > > >>> tests/functional/arm/test_aspeed_ast2600_sdk: Add USB EHCI
> > > >>> test for AST2600 SDK
> > > >>>
> > > >>> The USB subsystem is orphan but it is still used in the virt world.
> > > >>> This series is modifying the EHCI internals in such way that
> > > >>> migration is impacted and the CTRLDSSEGMENT (Control Data
> > > >>> Structure Segment
> > > >>> Register) implementation is incomplete AFAICT. From EHCI specs :
> > > >>>
> > > >>> This register allows the host software to locate all control
> > > >>> data
> > > >>> structures within the *same 4 Gigabyte memory segment*.
> > > >>>
> > > >>> Linux driver seems buggy too.
> > > >>>
> > > >>> Overall, the risk of regression is too high given the time I can
> > > >>> dedicate to this topic.
> > > >>>
> > > >>> Thanks for all the good work you done there, specially for migration.
> > > >>> If someone can Ack the series and step forward to become USB
> > > >>> maintainer, then I will reconsider.
> > > >
> > > > I'm not an USB expert / maintainer but FWIW this series looked
> > > > good enough to me when I looked at it. Maybe consider to merge
> > > > after the
> > > > 11.1 release?
> > >
> > > Yes. I would like to too but ...
> > >
> > > The change in size of the EHCIqh and EHCIitd descriptors is a bit
> > > worrying since these are used for guest DMA, see ehci_flush_qh(), or
> > > compare, see ehci_verify_qh().
> > >
> > > This should be fine for Linux, which has support since day one.
> > > Other older guest OSes may not allocate the extra space. This is a
> > > 20+ year old spec so the risk is probably low but I don't have the
> > > expertise to assess
> > the impact tbh.
> > >
> > > Anyhow if we want the model to be correct, we should not write
> > > beyond spec-defined descriptor boundaries when in 32-bit mode.
> > >
> > > More work ...
> > >
> > > Thanks,
> > >
> > > C.
> >
> > Thanks for pointing this out.
> >
> > I agree that even though the QEMU internal EHCIqh, EHCIqtd, and
> > EHCIitd structures include the extended high buffer pointer fields, we
> > must not access those fields in guest memory when 64-bit addressing
> > capability is not advertised.
> >
> > I have updated the patch accordingly.
> >
> > The descriptor DMA size is now selected based on caps_64bit_addr:
> >
> > When 64-bit addressing is supported and advertised, the complete
> > descriptor, including the high buffer pointer fields, is transferred.
> > In 32-bit mode, DMA reads and writes stop at the beginning of
> > bufptr_hi, so QEMU does not access memory beyond the descriptor layout
> > defined for 32-bit addressing.
> >
> > I also clear the local descriptor structures before partial DMA reads.
> > Therefore, the high buffer pointer fields remain zero in 32-bit mode
> > rather than containing stale or uninitialized values.
> >
> > This has been applied to:
> >
> > QH fetching, verification, and writeback qTD fetching and verification
> > iTD fetching and writeback
> >
> > For example:
> > /*
> > * EHCIqh / EHCIqtd / EHCIitd are sized to always include the extended
> > * high buffer pointer fields from EHCI 1.0 Appendix B. When 64-bit
> > * addressing capability is not advertised to the guest, the
> > descriptors
> > * in guest memory only have the classic 32-bit layout, so DMA
> > transfers
> > * must not read or write past that boundary.
> > */
> > #define EHCI_QH_DWORDS_32 (offsetof(EHCIqh, bufptr_hi) /
> > sizeof(uint32_t))
> > #define EHCI_QTD_DWORDS_32 (offsetof(EHCIqtd, bufptr_hi) /
> > sizeof(uint32_t)) #define EHCI_ITD_DWORDS_32 (offsetof(EHCIitd,
> > bufptr_hi) / sizeof(uint32_t))
> >
> > #define EHCI_QH_DWORDS_32 \
> > (offsetof(EHCIqh, bufptr_hi) / sizeof(uint32_t))
> >
> > static uint32_t ehci_qh_dwords(const EHCIState *s) {
> > return s->caps_64bit_addr ?
> > (sizeof(EHCIqh) >> 2) : EHCI_QH_DWORDS_32; }
> >
> > ehci_flush_qh() now uses this selected size, so in 32-bit mode it will
> > not write the extended high buffer pointer fields back to guest memory.
> >
> > Similarly, ehci_state_fetchqtd() only reads qtd.bufptr_hi when
> > caps_64bit_addr is enabled:
> >
> > memset(qtd.bufptr_hi, 0, sizeof(qtd.bufptr_hi));
> >
> > if (... ||
> > (q->ehci->caps_64bit_addr &&
> > get_dwords(q->ehci, addr + offsetof(EHCIqtd, bufptr_hi),
> > qtd.bufptr_hi, ARRAY_SIZE(qtd.bufptr_hi)) < 0))
> > { return 0;
> > }
> >
> > This should preserve compatibility with guests that allocate only the
> > original 32-bit EHCI descriptor size, while still allowing the model
> > to support the extended 64-bit descriptor layout.
> > If you think this approach looks OK, I'll include it in the next revision (v7).
> >
> > Thanks,
> > Jamin
I sent v7 here, https://patchwork.kernel.org/project/qemu-devel/cover/20260713032704.3583103-1-jamin_lin@aspeedtech.com/
Thanks,
Jamin
© 2016 - 2026 Red Hat, Inc.