qemu/hw
David Hubbard 53aaa88105 hw/usb/hcd-ohci: Fix ohci_service_td: accept zero-length TDs where CBP=BE+1
This changes the way the ohci emulation handles a Transfer Descriptor
with "Buffer End" set to "Current Buffer Pointer" - 1, specifically
in the case of a zero-length packet.

The OHCI spec 4.3.1.2 Table 4-2 specifies td.cbp to be zero for a
zero-length packet.  Peter Maydell tracked down commit 1328fe0c32
(hw: usb: hcd-ohci: check len and frame_number variables) where qemu
started checking this according to the spec.

What this patch does is loosen the qemu ohci implementation to allow a
zero-length packet if td.be (Buffer End) is set to td.cbp - 1, and with a
non-zero td.cbp value.

The spec is unclear whether this is valid or not -- it is not the
clearly documented way to send a zero length TD (which is CBP=BE=0),
but it isn't specifically forbidden. Actual hw seems to be ok with it.

Does any OS rely on this behavior? There have been no reports to
qemu-devel of this problem.

This is attempting to have qemu behave like actual hardware,
but this is just a minor change.

With a tiny OS[1] that boots and executes a test, the issue can be seen:

* OS that sends USB requests to a USB mass storage device
  but sends td.cbp = td.be + 1
* qemu 4.2
* qemu HEAD (4e66a0854)
* Actual OHCI controller (hardware)

Command line:
qemu-system-x86_64 -m 20 \
 -device pci-ohci,id=ohci \
 -drive if=none,format=raw,id=d,file=testmbr.raw \
 -device usb-storage,bus=ohci.0,drive=d \
 --trace "usb_*" --trace "ohci_*" -D qemu.log

Results are:

 qemu 4.2   | qemu HEAD  | actual HW
 -----------+------------+-----------
 works fine | ohci_die() | works fine

Tip: if the flags "-serial pty -serial stdio" are added to the command line
the test will output USB requests like this:

Testing qemu HEAD:

> Free mem 2M ohci port2 conn FS
> setup { 80 6 0 1 0 0 8 0 }
> ED info=80000 { mps=8 en=0 d=0 } tail=c20920
>   td0 c20880 nxt=c20960 f2000000 setup cbp=c20900 be=c20907
>   td1 c20960 nxt=c20980 f3140000    in cbp=c20908 be=c2090f
>   td2 c20980 nxt=c20920 f3080000   out cbp=c20910 be=c2090f ohci20 host err
> usb stopped

And in qemu.log:

usb_ohci_iso_td_bad_cc_overrun ISO_TD start_offset=0x00c20910 > next_offset=0x00c2090f

Testing qemu 4.2:

> Free mem 2M ohci port2 conn FS
> setup { 80 6 0 1 0 0 8 0 }
> ED info=80000 { mps=8 en=0 d=0 } tail=620920
>   td0 620880 nxt=620960 f2000000 setup cbp=620900 be=620907       cbp=0 be=620907
>   td1 620960 nxt=620980 f3140000    in cbp=620908 be=62090f       cbp=0 be=62090f
>   td2 620980 nxt=620920 f3080000   out cbp=620910 be=62090f       cbp=0 be=62090f
>    rx { 12 1 0 2 0 0 0 8 }
> setup { 0 5 1 0 0 0 0 0 } tx {}
> ED info=80000 { mps=8 en=0 d=0 } tail=620880
>   td0 620920 nxt=620960 f2000000 setup cbp=620900 be=620907       cbp=0 be=620907
>   td1 620960 nxt=620880 f3100000    in cbp=620908 be=620907       cbp=0 be=620907
> setup { 80 6 0 1 0 0 12 0 }
> ED info=80001 { mps=8 en=0 d=1 } tail=620960
>   td0 620880 nxt=6209c0 f2000000 setup cbp=620920 be=620927       cbp=0 be=620927
>   td1 6209c0 nxt=6209e0 f3140000    in cbp=620928 be=620939       cbp=0 be=620939
>   td2 6209e0 nxt=620960 f3080000   out cbp=62093a be=620939       cbp=0 be=620939
>    rx { 12 1 0 2 0 0 0 8 f4 46 1 0 0 0 1 2 3 1 }
> setup { 80 6 0 2 0 0 0 1 }
> ED info=80001 { mps=8 en=0 d=1 } tail=620880
>   td0 620960 nxt=6209a0 f2000000 setup cbp=620a20 be=620a27       cbp=0 be=620a27
>   td1 6209a0 nxt=6209c0 f3140004    in cbp=620a28 be=620b27       cbp=620a48 be=620b27
>   td2 6209c0 nxt=620880 f3080000   out cbp=620b28 be=620b27       cbp=0 be=620b27
>    rx { 9 2 20 0 1 1 4 c0 0 9 4 0 0 2 8 6 50 0 7 5 81 2 40 0 0 7 5 2 2 40 0 0 }
> setup { 0 9 1 0 0 0 0 0 } tx {}
> ED info=80001 { mps=8 en=0 d=1 } tail=620900
>   td0 620880 nxt=620940 f2000000 setup cbp=620a00 be=620a07       cbp=0 be=620a07
>   td1 620940 nxt=620900 f3100000    in cbp=620a08 be=620a07       cbp=0 be=620a07

[1] The OS disk image has been emailed to philmd@linaro.org, mjt@tls.msk.ru,
and kraxel@redhat.com:

* testCbpOffBy1.img.xz
* sha256: f87baddcb86de845de12f002c698670a426affb40946025cc32694f9daa3abed

Signed-off-by: David Hubbard <dmamfmgm@gmail.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2024-06-21 16:20:45 +01:00
..
9pfs hw/xen: Make XenDevOps structures const 2024-06-04 11:53:43 +02:00
acpi hw/acpi/ich9: Remove dead code related to 'acpi_memory_hotplug' 2024-06-19 12:40:49 +02:00
adc hw, target: Add ResetType argument to hold and exit phase methods 2024-04-25 10:21:06 +01:00
alpha alpha: switch boards to "default y" 2024-05-03 15:47:47 +02:00
arm hw/arm/virt: Avoid unexpected warning from Linux guest on host with Fujitsu CPUs 2024-06-21 16:20:45 +01:00
audio hw/audio/virtio-snd: Always use little endian audio format 2024-06-19 12:40:49 +02:00
avr avr: switch boards to "default y" 2024-05-03 15:47:47 +02:00
block virtio-blk: remove SCSI passthrough functionality 2024-06-05 11:01:05 +02:00
char hw: arm: Remove use of tabs in some source files 2024-05-28 14:20:48 +01:00
core hw/intc: Introduce x-query-interrupt-controllers QMP command 2024-06-19 12:40:49 +02:00
cpu hw: Add a Kconfig switch for the TYPE_CPU_CLUSTER device 2024-04-25 12:48:12 +02:00
cris cris: switch boards to "default y" 2024-05-03 15:47:47 +02:00
cxl hw/cxl/cxl-cdat: Make cxl_doe_cdat_init() return boolean 2024-04-25 12:48:12 +02:00
display ui+display: rename is_buffer_shared() -> surface_is_allocated() 2024-06-19 12:42:03 +02:00
dma hw/dma: Add a trace log for a description loading failure 2024-06-18 14:52:00 +02:00
fsi
gpio hw: arm: Remove use of tabs in some source files 2024-05-28 14:20:48 +01:00
hppa hw/hppa/machine: Replace g_memdup() by g_memdup2() 2024-05-08 19:42:45 +02:00
hyperv kvm: move target-dependent interrupt routing out of kvm-all.c 2024-05-03 15:47:48 +02:00
i2c hw, target: Add ResetType argument to hold and exit phase methods 2024-04-25 10:21:06 +01:00
i386 hw/i386/iommu: Constify IOMMUTLBEvent in vtd_page_walk_hook prototype 2024-06-19 12:42:03 +02:00
ide hw/ide/atapi: Use qemu_hexdump_line to avoid sprintf 2024-06-05 12:14:20 -07:00
input hw: arm: Remove use of tabs in some source files 2024-05-28 14:20:48 +01:00
intc hw/intc/arm_gic: Fix deactivation of SPI lines 2024-06-21 14:01:58 +01:00
ipack
ipmi
isa hw/isa/vt82c686: Keep track of PIRQ/PINT pins separately 2024-04-15 13:07:11 +02:00
loongarch hw/mem/pc-dimm: Remove legacy_align argument from pc_dimm_pre_plug() 2024-06-19 12:40:49 +02:00
m68k m68k: switch boards to "default y" 2024-05-03 15:47:47 +02:00
mem hw/mem/memory-device: Remove legacy_align from memory_device_pre_plug() 2024-06-19 12:40:49 +02:00
microblaze microblaze: switch boards to "default y" 2024-05-03 15:47:47 +02:00
mips hw/mips/loongson3_virt: Wire up loongson_ipi device 2024-06-19 12:42:03 +02:00
misc hw/misc: Set valid access size for Exynos4210 RNG 2024-06-21 16:20:45 +01:00
net hw/net/can/xlnx-versal-canfd: Fix sorting of the tx queue 2024-06-21 14:01:58 +01:00
nubus
nvme hw/nvme: fix -Werror=maybe-uninitialized 2024-04-02 16:15:07 +02:00
nvram hw, target: Add ResetType argument to hold and exit phase methods 2024-04-25 10:21:06 +01:00
openrisc kconfig: express dependency of individual boards on libfdt 2024-05-10 15:45:15 +02:00
pci hw, target: Add ResetType argument to hold and exit phase methods 2024-04-25 10:21:06 +01:00
pci-bridge Misc HW patch queue 2024-04-25 09:43:29 -07:00
pci-host hw/ppc: Avoid using Monitor in pnv_phb4_pic_print_info() 2024-06-19 12:40:49 +02:00
pcmcia
ppc ppc/pnv: Introduce pnv_chip_foreach_cpu() 2024-06-19 12:40:49 +02:00
remote hw/remote/vfio-user: Fix config space access byte order 2024-05-08 19:43:15 +02:00
riscv hw/smbios: Remove 'uuid_encoded' argument from smbios_set_defaults() 2024-06-19 12:40:49 +02:00
rtc hw/i386: move rtc-reset-reinjection command out of hw/rtc 2024-05-10 15:45:15 +02:00
rx kconfig: express dependency of individual boards on libfdt 2024-05-10 15:45:15 +02:00
s390x hw/s390x: Introduce s390_skeys_get|set() helpers 2024-06-19 12:42:03 +02:00
scsi scsi-disk: Fix crash for VM configured with USB CDROM after live migration 2024-06-10 19:01:08 +02:00
sd hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT) is set 2024-04-10 09:09:34 +02:00
sensor hw, target: Add ResetType argument to hold and exit phase methods 2024-04-25 10:21:06 +01:00
sh4 hw/sh4: Remove newline character in trace events 2024-06-10 13:05:27 -04:00
smbios hw/smbios: Remove 'smbios_uuid_encoded', simplify smbios_encode_uuid() 2024-06-19 12:40:49 +02:00
sparc sparc: switch boards to "default y" 2024-05-03 15:47:48 +02:00
sparc64 qemu-sparc queue 2024-05-06 10:19:56 -07:00
ssi aspeed/smc: Add AST2700 support 2024-06-16 21:08:54 +02:00
timer hw/timer/a9gtimer: Handle QTest mode in a9_gtimer_get_current_cpu 2024-06-21 14:01:59 +01:00
tpm hw/tpm: Remove HOST_PAGE_ALIGN from tpm_ppi_init 2024-02-29 11:35:36 -10:00
tricore tricore: switch boards to "default y" 2024-05-03 15:47:48 +02:00
ufs hw/ufs: Add support MCQ of UFSHCI 4.0 2024-06-03 16:20:42 +09:00
usb hw/usb/hcd-ohci: Fix ohci_service_td: accept zero-length TDs where CBP=BE+1 2024-06-21 16:20:45 +01:00
vfio hw/vfio: Remove newline character in trace events 2024-06-10 13:05:27 -04:00
virtio hw/mem/memory-device: Remove legacy_align from memory_device_pre_plug() 2024-06-19 12:40:49 +02:00
watchdog aspeed/wdt: Add AST2700 support 2024-06-16 21:08:54 +02:00
xen xen: mapcache: Add support for grant mappings 2024-06-09 20:16:14 +02:00
xenpv hw/xen: Register framebuffer backend via xen_backend_init() 2024-06-04 11:53:43 +02:00
xtensa hw/xtensa: require libfdt 2024-05-10 15:45:15 +02:00
Kconfig hw: Fix problem with the A*MPCORE switches in the Kconfig files 2024-04-25 12:48:12 +02:00
meson.build hw/rdma: Remove deprecated pvrdma device and rdmacm-mux helper 2024-04-24 16:03:38 +02:00