Philippe -
From what I've seen, access size has nothing to do with alignment.

What the code in access_with_adjusted_size() will do is make sure that "size" 
is >= min_access_size and <= max_access_size.

So reading 2-bytes from address 2 turns into reading 4-bytes from address 2: 
xhci_cap_read() is called with reg 2, size 4.

But, due to the fact our change to support reg 2 only returns back 2-bytes, and 
how the loops work in access_with_adjusted_size(), we only call xhci_cap_read() 
once.

It seems like we should also change impl.min_access_size for xhci_cap_ops to be 
2.

But, after that, to support people doing strange things like reading 
traditionally 4-byte values as 2 2-byte values, we probably need to change 
xhci_cap_read() to handle every memory range in steps of 2-bytes.

But I'll defer to Gerd on this...

Cameron Esfahani
di...@apple.com

"Americans are very skilled at creating a custom meaning from something that's 
mass-produced."

Ann Powers


> On Mar 31, 2020, at 12:52 AM, Philippe Mathieu-Daudé <phi...@redhat.com> 
> wrote:
> 
> On 3/30/20 11:44 PM, Cameron Esfahani via wrote:
>> macOS will read HCIVERSION separate from CAPLENGTH.  Add a distinct
>> handler for that register.
> 
> Apparently a fix for https://bugs.launchpad.net/qemu/+bug/1693050.
> 
>> Signed-off-by: Cameron Esfahani <di...@apple.com>
>> ---
>>  hw/usb/hcd-xhci.c | 3 +++
>>  1 file changed, 3 insertions(+)
>> diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
>> index b330e36fe6..061f8438de 100644
>> --- a/hw/usb/hcd-xhci.c
>> +++ b/hw/usb/hcd-xhci.c
>> @@ -2739,6 +2739,9 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, 
>> unsigned size)
>>      case 0x00: /* HCIVERSION, CAPLENGTH */
>>          ret = 0x01000000 | LEN_CAP;
>>          break;
>> +    case 0x02: /* HCIVERSION */
>> +        ret = 0x0100;
>> +        break;
> 
> But we have:
> 
> static const MemoryRegionOps xhci_cap_ops = {
>    .read = xhci_cap_read,
>    .write = xhci_cap_write,
>    .valid.min_access_size = 1,
>    .valid.max_access_size = 4,
>    .impl.min_access_size = 4,
>    .impl.max_access_size = 4,
>    .endianness = DEVICE_LITTLE_ENDIAN,
> };
> 
> IIUC ".impl.min_access_size = 4" means the case 'reg == 2' can not happen. It 
> seems we have a bug in memory.c elsewhere.
> 
> How can we reproduce?
> 
> If not easy, can you share the backtrace of:
> 
> -- >8 --
> diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
> index b330e36fe6..d021129f3f 100644
> --- a/hw/usb/hcd-xhci.c
> +++ b/hw/usb/hcd-xhci.c
> @@ -2735,6 +2735,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, 
> unsigned size)
>     XHCIState *xhci = ptr;
>     uint32_t ret;
> 
> +    assert(reg != 2);
>     switch (reg) {
>     case 0x00: /* HCIVERSION, CAPLENGTH */
>         ret = 0x01000000 | LEN_CAP;
> ---
> 
>>      case 0x04: /* HCSPARAMS 1 */
>>          ret = ((xhci->numports_2+xhci->numports_3)<<24)
>>              | (xhci->numintrs<<8) | xhci->numslots;


Reply via email to