On 2018-Sep-21, at 12:21 PM, Warner Losh <imp at bsdimp.com> wrote:

>> On Fri, Sep 21, 2018 at 12:35 PM Mark Millard via freebsd-hackers 
>> <freebsd-hack...@freebsd.org> wrote:
>> [I decided that freebsd-hackers might be better for this,
>> under a different wording.]
>> 
>> sys/dev/fxp/if_fxp.c uses the statement:
>> 
>> cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16);
>> 
>> But sys/dev/fxp/if_fxpreg.h has the types involved as:
>> 
>> struct fxp_cb_tx {
>>       uint16_t cb_status;
>>       uint16_t cb_command;
>>       uint32_t link_addr;
>>       uint32_t tbd_array_addr;
>>       uint16_t byte_count;
>>       uint8_t tx_threshold;
>>       uint8_t tbd_number;
>> 
>>       /*
>>        * The following structure isn't actually part of the TxCB,
>>        * unless the extended TxCB feature is being used.  In this
>>        * case, the first two elements of the structure below are
>>        * fetched along with the TxCB.
>>        */
>>       union {
>>               struct fxp_ipcb ipcb;
>>               struct fxp_tbd tbd[FXP_NTXSEG + 1];
>>       } tx_cb_u;
>> };
>> 
>> So cbp->tbd is not pointing into the middle of an array.
>> Thus the cbp->tbd[-1].tb_size = . . . assignment trashes memory
>> from what I can tell.
>> 
>> /usr/src/sys/dev/fxp/if_fxp.c has the [-1] assignment in:
>> 
>>       /* Configure TSO. */
>>       if (m->m_pkthdr.csum_flags & CSUM_TSO) {
>>               cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16);
>>               cbp->tbd[1].tb_size |= htole32(tcp_payload << 16);
>>               cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE |
>>                   FXP_IPCB_IP_CHECKSUM_ENABLE |
>>                   FXP_IPCB_TCP_PACKET |
>>                   FXP_IPCB_TCPUDP_CHECKSUM_ENABLE;
>>       }
>> 
>> This cbp->tbd[-1].tb_size use goes back to -r185330 in 2008-Nov-26.
>> 
>> This is also when the "+ 1" was added to the:
>> 
>> struct fxp_tbd tbd[FXP_NTXSEG + 1]
>> 
>> above.
>> 
>> clang 7 via xtoolchain-llvm70 reported:
>> 
>> --- if_fxp.o ---
>> /usr/src/sys/dev/fxp/if_fxp.c:1630:3: error: array index -1 is before the 
>> beginning of the array [-Werror,-Warray-bounds]
>>               cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16);
>>               ^        ~~
>> /usr/src/sys/dev/fxp/if_fxpreg.h:297:3: note: array 'tbd' declared here
>>               struct fxp_tbd tbd[FXP_NTXSEG + 1];
>>               ^
>> 1 error generated.
>> *** [if_fxp.o] Error code 1
>> 
>> It does look odd to me.
>> 
> So I did some digging into this a few months ago.
> 
> It turns out the code is right, kinda.
> 
> So, what's it's doing with the [-1] is as follows:
> 
> the sizeof tbd is 8 bytes long. So, we're dereferencing 8 before the array, 
> which points to tbd_array_addr. However tb_size is the second element of 
> that, so that points us at count + tx_threshold + tbd_number. So, this code 
> is setting count = 0 and tx_threshold to the low order bits of the segment 
> size and tbd_number to the high order bits. We set the count = 0 later 
> anyway, so that part of it isn't so bad.
> 
> Since this is in hardware, it may be special meanings for these bits, and 
> this 'trick' is used to just do one write rather than two. I've not looked 
> for the hardware manual to see if this is kosher, but that's what we're 
> doing. It's not as crazy stupid as it sounds at first blush.

Thanks for the explanation. Too bad the code does not document the hack.

Looks like xtoolchain-llvm70 use will require avoiding reporting this as
an error that stops buildkernel, a change for the build environment. Of
course, that may well wait for head to be 13 instead of 12.


===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)

_______________________________________________
freebsd-toolchain@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"

Reply via email to