Cord Amfmgm <dmamf...@gmail.com> writes:

> On Wed, Jun 12, 2024 at 9:21 AM Alex Bennée <alex.ben...@linaro.org> wrote:
>
>  David Hubbard <dmamf...@gmail.com> writes:
>
>  > From: Cord Amfmgm <dmamf...@gmail.com>
>  >
>  > This changes the way the ohci emulation handles a Transfer Descriptor with
>  > "Current Buffer Pointer" set to "Buffer End" + 1.
>  >
>  > The OHCI spec 4.3.1.2 Table 4-2 allows td.cbp to be one byte more than 
> td.be
>  > to signal the buffer has zero length. Currently qemu only accepts 
> zero-length
>  > Transfer Descriptors if the td.cbp is equal to 0, while actual OHCI 
> hardware
>  > accepts both cases.
>  >
>  > The qemu ohci emulation has a regression in ohci_service_td. Version 4.2
>  > and earlier matched the spec. (I haven't taken the time to bisect exactly
>  > where the logic was changed.)
>
>  I find it hard to characterise this as a regression because we've
>  basically gone from no checks to actually doing bounds checks:
>
>    1328fe0c32 (hw: usb: hcd-ohci: check len and frame_number variables)
>
>  The argument here seems to be that real hardware is laxer than the specs
>  in what it accepts.
>
<snip>
>
>  With the updated commit message:
>
>  Reviewed-by: Alex Bennée <alex.ben...@linaro.org>
>
> Please forgive my lack of experience on this mailing list. I don't see a 
> suggested commit message from Alex but in case that
> was what is being considered, here is one. Feedback welcome, also if this is 
> not what is wanted, please just say it.
>

Something along the lines of what you suggest here (where did this come
from?)

>> From: Cord Amfmgm <dmamf...@gmail.com>
>>
>> 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.
>>
>> Is this correct? It appears to not follow the spec, so no. But 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 behavior is
>> reproducible:
>>
>> * OS that sends USB requests to a USB mass storage device
>>   but sends td.be = td.cbp - 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 phi...@linaro.org, m...@tls.msk.ru,
>> and kra...@redhat.com:
>>
>> * testCbpOffBy1.img.xz
>> * sha256:
>> f87baddcb86de845de12f002c698670a426affb40946025cc32694f9daa3abed
>>
>> Signed-off-by: Cord Amfmgm <dmamf...@gmail.com>

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro

Reply via email to