On Mon, 30 Sept 2024 at 22:28, Strahinja Jankovic
<strahinjapjanko...@gmail.com> wrote:
>
> Hi Peter,
>
> Thank you very much for the review and detailed comments.
>
> I will try to address all comments in the v2 of the patches, but I have some 
> questions I added below.
>
> On Mon, Sep 30, 2024 at 4:45 PM Peter Maydell <peter.mayd...@linaro.org> 
> wrote:
>> > +static uint64_t allwinner_a10_spi_read(void *opaque, hwaddr offset,
>> > +                                       unsigned size)
>> > +{
>> > +    uint32_t value = 0;
>> > +    AWA10SPIState *s = opaque;
>> > +    uint32_t index = offset >> 2;
>>
>> The MemoryRegionOps defines that size == 1 is permitted,
>> but this calculation of index without any validation
>> of offset means that if the guest writes a byte to
>> offset 1 we will treat that identically to writing a byte
>> to offset 0. This probably isn't what the hardware does.
>
> I checked once more the User manual, and it does not mention
> unaligned access (example for RXDATA)
>
> In 8-bits SPI bus width, this register can be accessed in byte,
> half-word or word unit by AHB. In byte accessing method,
> if there are words in RXFIFO, the top word is returned and
> the RXFIFO depth is decreased by 1. In half-word accessing
> method, the two SPI bursts are returned and the RXFIFO
> depth is decrease by 2. In word accessing method, the four
> SPI bursts are returned and the RXFIFO depth is decreased
> by 4.
>
> I chose not to cover the half-word and word access methods,
> since neither Linux kernel nor U-Boot use it
> (both use only byte access).
>
> I guess that I could add `.valid.unaligned = false` when
> initializing `MemoryRegionOps`?

This wouldn't help, because a 2-byte load at offset 2
is not "unaligned" from the memory system's point of view.
(Also, unaligned = false is the default.)

Looking again at your code I see I misread it a bit:
I thought it was doing a switch() on index, but it is on
offset.

Using a switch on offset makes it easy to handle the case
of "bogus write to an offset that isn't the start of a
register":

   switch (offset) {
   case SOME_REG_OFFSET:
       /*
        * handle it; if size 1/2/4 behave differently,
        * then look at 'size' to do the right thing.
        */
       break;
   /* etc */
   default:
       qemu_log_mask(LOG_GUEST_ERROR,
                     "%s: bad offset 0x%x\n", __func__,
                     (uint32_t)offset);
       break;
   }

Then both the "offset that's not a defined register"
and "offset that's not aligned to the start of a register"
go into the default case, we log it as a guest error,
and do nothing.

thanks
-- PMM

Reply via email to