@samitouri / QOSamiQemu / commits / 7e6c5727e1

hw/usb/hcd-ehci: Add property to advertise 64-bit addressing capability

Introduce a new boolean property, "caps-64bit-addr", to control HCCPARAMS[0] (64-bit Addressing Capability). When enabled, the EHCI controller advertises support for 64-bit address memory pointers as defined in the EHCI specification (Table 2-7, HCCPARAMS). This allows software to use the 64-bit data structure formats described in Appendix B. When disabled (default), the controller reports 32-bit addressing capability and uses the standard 32-bit data structures. The EHCI CTRLDSSEGMENT register provides the upper 32 bits [63:32] used to form 64-bit addresses for EHCI control data structures. Per EHCI 1.0 spec section 2.3.5, when the HCCPARAMS 64-bit Addressing Capability bit is zero, CTRLDSSEGMENT is not used: software cannot write it and reads must return zero. Add a capability check in the operational register write handler and reject guest writes to CTRLDSSEGMENT when 64-bit addressing is not enabled. Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Link: https://lore.kernel.org/qemu-devel/20260713032704.3583103-3-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater <clg@redhat.com>

Jamin Lin committed Jul 13, 2026 at 03:27 UTC 7e6c5727e16fca59af7a681716d25aabc1892f96
2 files changed +17 -2
hw/usb/hcd-ehci.c
+13 -1
@@ -1109,6 +1109,15 @@ static void ehci_opreg_write(void *ptr, hwaddr addr,
1109 }
1110 break;
1111
1112 + case CTRLDSSEGMENT:
1113 + if (!s->caps_64bit_addr) {
1114 + qemu_log_mask(LOG_GUEST_ERROR,
1115 + "ehci: write to CTRLDSSEGMENT while "
1116 + "64-bit addressing capability is disabled\n");
1117 + return;
1118 + }
1119 + break;
1120 +
1121 case ASYNCLISTADDR:
1122 if (ehci_async_enabled(s)) {
1123 qemu_log_mask(LOG_GUEST_ERROR,
@@ -2554,6 +2563,9 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp)
2563 s->maxframes);
2564 return;
2565 }
2566 + if (s->caps_64bit_addr) {
2567 + s->caps[0x08] |= BIT(0);
2568 + }
2569
2570 memory_region_add_subregion(&s->mem, s->capsbase, &s->mem_caps);
2571 memory_region_add_subregion(&s->mem, s->opregbase, &s->mem_opreg);
@@ -2613,7 +2625,7 @@ void usb_ehci_init(EHCIState *s, DeviceState *dev)
2625 s->caps[0x05] = 0x00; /* No companion ports at present */
2626 s->caps[0x06] = 0x00;
2627 s->caps[0x07] = 0x00;
2616 - s->caps[0x08] = 0x80; /* We can cache whole frame, no 64-bit */
2628 + s->caps[0x08] = 0x80; /* We can cache whole frame */
2629 s->caps[0x0a] = 0x00;
2630 s->caps[0x0b] = 0x00;
2631
hw/usb/hcd-ehci.h
+4 -1
@@ -261,6 +261,7 @@ struct EHCIState {
261 * Old machine types only transfer 32-bit fetch addresses.
262 */
263 bool migrate_fetch_addr_64bit;
264 + bool caps_64bit_addr;
265
266 /*
267 * EHCI spec version 1.0 Section 2.3
@@ -324,7 +325,9 @@ struct EHCIState {
325 #define DEFINE_EHCI_COMMON_PROPERTIES(_state) \
326 DEFINE_PROP_UINT32("maxframes", _state, ehci.maxframes, 128), \
327 DEFINE_PROP_BOOL("x-migrate-fetch-addr-64bit", _state, \
327 - ehci.migrate_fetch_addr_64bit, true)
328 + ehci.migrate_fetch_addr_64bit, true), \
329 + DEFINE_PROP_BOOL("caps-64bit-addr", _state, \
330 + ehci.caps_64bit_addr, false)
331
332 extern const VMStateDescription vmstate_ehci;
333