[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PULL 38/96] hw/ssi: Extend SPI model
From: |
Peter Maydell |
Subject: |
Re: [PULL 38/96] hw/ssi: Extend SPI model |
Date: |
Mon, 29 Jul 2024 14:16:33 +0100 |
On Mon, 29 Jul 2024 at 11:33, Cédric Le Goater <clg@kaod.org> wrote:
>
> On 7/26/24 01:53, Nicholas Piggin wrote:
> > From: Chalapathi V <chalapathi.v@linux.ibm.com>
> >
> > In this commit SPI shift engine and sequencer logic is implemented.
> > Shift engine performs serialization and de-serialization according to the
> > control by the sequencer and according to the setup defined in the
> > configuration registers. Sequencer implements the main control logic and
> > FSM to handle data transmit and data receive control of the shift engine.
> > +static inline uint8_t get_seq_index(PnvSpi *s)
> > +{
> > + return GETFIELD(SPI_STS_SEQ_INDEX, s->status);
> > +}
>
> Coverity reports :
>
> >>> CID 1558827: (OVERRUN)
> >>> Overrunning array "s->seq_op" of 8 bytes at byte offset 16 using
> >>> index "get_seq_index(s) + 1" (which evaluates to 16).
>
>
> get_seq_index() can return a value between 0 and 15 and it is used in a couple
> of places to index array s->seq_op[] which is an 8 bytes array.
>
> Should we increase the size of the seq_op array ?
I think in most places this can't happen, because:
> > + /*
> > + * There are only 8 possible operation IDs to iterate through though
> > + * some operations may cause more than one frame to be sequenced.
> > + */
> > + while (get_seq_index(s) < NUM_SEQ_OPS) {
The loop condition enforces that the sequence index is < 8.
> > + opcode = s->seq_op[get_seq_index(s)];
Coverity isn't smart enough to be able to tell that this
call to get_seq_index() must return the same value as the
previous one and so be in bounds for the array, which is why it's
complaining.
On the other hand:
* this is also not totally obvious to humans
* it means we're doing the shift-and-mask ops to get the
sequence index out every time
Maybe we should keep it in a variable? (Depends whether there's
a bunch of places in the loop that want to update the index, or
if we just do that at the end of the loop.)
Another option would be to have a version of get_seq_index() that
asserts that the index is valid.
The other design approach available here is to have the device
state struct hold the underlying information in a split-out way
(so e.g s->seq_index and other fields), and then assemble those
into a 32-bit value for the status register in the "guest reads/writes
the register codepath).
That said, there is also a case which I suspect really is an
overrun bug:
> > + case SEQ_OP_SHIFT_N1:
> > + s->status = SETFIELD(SPI_STS_SEQ_FSM, s->status,
> > SEQ_STATE_EXECUTE);
> > + trace_pnv_spi_sequencer_op("SHIFT_N1", get_seq_index(s));
> > + /*
> > + * Only allow a shift_n1 when the state is not IDLE or DONE.
> > + * In either of those two cases the sequencer is not in a
> > proper
> > + * state to perform shift operations because the sequencer has:
> > + * - processed a responder deselect (DONE)
> > + * - processed a stop opcode (IDLE)
> > + * - encountered an error (IDLE)
> > + */
> > + if ((GETFIELD(SPI_STS_SHIFTER_FSM, s->status) == FSM_IDLE) ||
> > + (GETFIELD(SPI_STS_SHIFTER_FSM, s->status) == FSM_DONE)) {
> > + qemu_log_mask(LOG_GUEST_ERROR, "Shift_N1 not allowed in "
> > + "shifter state = 0x%llx", GETFIELD(
> > + SPI_STS_SHIFTER_FSM, s->status));
> > + /*
> > + * Set sequencer FSM error bit 3 (general_SPI_status[3])
> > + * in status reg.
> > + */
> > + s->status = SETFIELD(SPI_STS_GEN_STATUS_B3, s->status, 1);
> > + trace_pnv_spi_sequencer_stop_requested("invalid shifter
> > state");
> > + stop = true;
> > + } else {
> > + /*
> > + * Look for the special case where there is a shift_n1 set
> > for
> > + * transmit and it is followed by a shift_n2 set for
> > transmit
> > + * AND the combined transmit length of the two operations
> > is
> > + * less than or equal to the size of the TDR register. In
> > this
> > + * case we want to use both this current shift_n1 opcode
> > and the
> > + * following shift_n2 opcode to assemble the frame for
> > + * transmission to the responder without requiring a
> > refill of
> > + * the TDR between the two operations.
> > + */
> > + if (PNV_SPI_MASKED_OPCODE(s->seq_op[get_seq_index(s) + 1])
> > + == SEQ_OP_SHIFT_N2) {
Here we look at the seq_op[] array for get_seq_index(s) + 1,
so if we're on the last iteration of the loop because the seq
index is 7 we'll read off the end of the array at index 8.
(Presumably the correct behaviour if the shift_n1 is the last
operation is that it's not this special case.)
> > + send_n1_alone = false;
> > + }
> > + s->status = SETFIELD(SPI_STS_SHIFTER_FSM, s->status,
> > + FSM_SHIFT_N1);
thanks
-- PMM
- [PULL 30/96] ppc/pnv: Implement Power9 CPU core thread state indirect register, (continued)
- [PULL 30/96] ppc/pnv: Implement Power9 CPU core thread state indirect register, Nicholas Piggin, 2024/07/25
- [PULL 31/96] ppc/pnv: Add POWER10 ChipTOD quirk for big-core, Nicholas Piggin, 2024/07/25
- [PULL 32/96] ppc/pnv: Add big-core machine property, Nicholas Piggin, 2024/07/25
- [PULL 33/96] ppc/pnv: Add a CPU nmi and resume function, Nicholas Piggin, 2024/07/25
- [PULL 35/96] ppc/pnv: Add an LPAR per core machine option, Nicholas Piggin, 2024/07/25
- [PULL 34/96] ppc/pnv: Implement POWER10 PC xscom registers for direct controls, Nicholas Piggin, 2024/07/25
- [PULL 36/96] ppc/pnv: Remove ppc target dependency from pnv_xscom.h, Nicholas Piggin, 2024/07/25
- [PULL 37/96] hw/ssi: Add SPI model, Nicholas Piggin, 2024/07/25
- [PULL 38/96] hw/ssi: Extend SPI model, Nicholas Piggin, 2024/07/25
- [PULL 39/96] hw/block: Add Microchip's 25CSM04 to m25p80, Nicholas Piggin, 2024/07/25
- [PULL 41/96] tests/qtest: Add pnv-spi-seeprom qtest, Nicholas Piggin, 2024/07/25
- [PULL 42/96] pnv/xive2: XIVE2 Cache Watch, Cache Flush and Sync Injection support, Nicholas Piggin, 2024/07/25
- [PULL 47/96] pnv/xive2: Enable VST NVG and NVC index compression, Nicholas Piggin, 2024/07/25
- [PULL 40/96] hw/ppc: SPI controller wiring to P10 chip, Nicholas Piggin, 2024/07/25
- [PULL 43/96] pnv/xive2: Structure/define alignment changes, Nicholas Piggin, 2024/07/25
- [PULL 44/96] pnv/xive: Support cache flush and queue sync inject with notifications, Nicholas Piggin, 2024/07/25