cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xillybus.rst (18061B)


      1==========================================
      2Xillybus driver for generic FPGA interface
      3==========================================
      4
      5:Author: Eli Billauer, Xillybus Ltd. (http://xillybus.com)
      6:Email:  eli.billauer@gmail.com or as advertised on Xillybus' site.
      7
      8.. Contents:
      9
     10 - Introduction
     11  -- Background
     12  -- Xillybus Overview
     13
     14 - Usage
     15  -- User interface
     16  -- Synchronization
     17  -- Seekable pipes
     18
     19 - Internals
     20  -- Source code organization
     21  -- Pipe attributes
     22  -- Host never reads from the FPGA
     23  -- Channels, pipes, and the message channel
     24  -- Data streaming
     25  -- Data granularity
     26  -- Probing
     27  -- Buffer allocation
     28  -- The "nonempty" message (supporting poll)
     29
     30
     31Introduction
     32============
     33
     34Background
     35----------
     36
     37An FPGA (Field Programmable Gate Array) is a piece of logic hardware, which
     38can be programmed to become virtually anything that is usually found as a
     39dedicated chipset: For instance, a display adapter, network interface card,
     40or even a processor with its peripherals. FPGAs are the LEGO of hardware:
     41Based upon certain building blocks, you make your own toys the way you like
     42them. It's usually pointless to reimplement something that is already
     43available on the market as a chipset, so FPGAs are mostly used when some
     44special functionality is needed, and the production volume is relatively low
     45(hence not justifying the development of an ASIC).
     46
     47The challenge with FPGAs is that everything is implemented at a very low
     48level, even lower than assembly language. In order to allow FPGA designers to
     49focus on their specific project, and not reinvent the wheel over and over
     50again, pre-designed building blocks, IP cores, are often used. These are the
     51FPGA parallels of library functions. IP cores may implement certain
     52mathematical functions, a functional unit (e.g. a USB interface), an entire
     53processor (e.g. ARM) or anything that might come handy. Think of them as a
     54building block, with electrical wires dangling on the sides for connection to
     55other blocks.
     56
     57One of the daunting tasks in FPGA design is communicating with a fullblown
     58operating system (actually, with the processor running it): Implementing the
     59low-level bus protocol and the somewhat higher-level interface with the host
     60(registers, interrupts, DMA etc.) is a project in itself. When the FPGA's
     61function is a well-known one (e.g. a video adapter card, or a NIC), it can
     62make sense to design the FPGA's interface logic specifically for the project.
     63A special driver is then written to present the FPGA as a well-known interface
     64to the kernel and/or user space. In that case, there is no reason to treat the
     65FPGA differently than any device on the bus.
     66
     67It's however common that the desired data communication doesn't fit any well-
     68known peripheral function. Also, the effort of designing an elegant
     69abstraction for the data exchange is often considered too big. In those cases,
     70a quicker and possibly less elegant solution is sought: The driver is
     71effectively written as a user space program, leaving the kernel space part
     72with just elementary data transport. This still requires designing some
     73interface logic for the FPGA, and write a simple ad-hoc driver for the kernel.
     74
     75Xillybus Overview
     76-----------------
     77
     78Xillybus is an IP core and a Linux driver. Together, they form a kit for
     79elementary data transport between an FPGA and the host, providing pipe-like
     80data streams with a straightforward user interface. It's intended as a low-
     81effort solution for mixed FPGA-host projects, for which it makes sense to
     82have the project-specific part of the driver running in a user-space program.
     83
     84Since the communication requirements may vary significantly from one FPGA
     85project to another (the number of data pipes needed in each direction and
     86their attributes), there isn't one specific chunk of logic being the Xillybus
     87IP core. Rather, the IP core is configured and built based upon a
     88specification given by its end user.
     89
     90Xillybus presents independent data streams, which resemble pipes or TCP/IP
     91communication to the user. At the host side, a character device file is used
     92just like any pipe file. On the FPGA side, hardware FIFOs are used to stream
     93the data. This is contrary to a common method of communicating through fixed-
     94sized buffers (even though such buffers are used by Xillybus under the hood).
     95There may be more than a hundred of these streams on a single IP core, but
     96also no more than one, depending on the configuration.
     97
     98In order to ease the deployment of the Xillybus IP core, it contains a simple
     99data structure which completely defines the core's configuration. The Linux
    100driver fetches this data structure during its initialization process, and sets
    101up the DMA buffers and character devices accordingly. As a result, a single
    102driver is used to work out of the box with any Xillybus IP core.
    103
    104The data structure just mentioned should not be confused with PCI's
    105configuration space or the Flattened Device Tree.
    106
    107Usage
    108=====
    109
    110User interface
    111--------------
    112
    113On the host, all interface with Xillybus is done through /dev/xillybus_*
    114device files, which are generated automatically as the drivers loads. The
    115names of these files depend on the IP core that is loaded in the FPGA (see
    116Probing below). To communicate with the FPGA, open the device file that
    117corresponds to the hardware FIFO you want to send data or receive data from,
    118and use plain write() or read() calls, just like with a regular pipe. In
    119particular, it makes perfect sense to go::
    120
    121	$ cat mydata > /dev/xillybus_thisfifo
    122
    123	$ cat /dev/xillybus_thatfifo > hisdata
    124
    125possibly pressing CTRL-C as some stage, even though the xillybus_* pipes have
    126the capability to send an EOF (but may not use it).
    127
    128The driver and hardware are designed to behave sensibly as pipes, including:
    129
    130* Supporting non-blocking I/O (by setting O_NONBLOCK on open() ).
    131
    132* Supporting poll() and select().
    133
    134* Being bandwidth efficient under load (using DMA) but also handle small
    135  pieces of data sent across (like TCP/IP) by autoflushing.
    136
    137A device file can be read only, write only or bidirectional. Bidirectional
    138device files are treated like two independent pipes (except for sharing a
    139"channel" structure in the implementation code).
    140
    141Synchronization
    142---------------
    143
    144Xillybus pipes are configured (on the IP core) to be either synchronous or
    145asynchronous. For a synchronous pipe, write() returns successfully only after
    146some data has been submitted and acknowledged by the FPGA. This slows down
    147bulk data transfers, and is nearly impossible for use with streams that
    148require data at a constant rate: There is no data transmitted to the FPGA
    149between write() calls, in particular when the process loses the CPU.
    150
    151When a pipe is configured asynchronous, write() returns if there was enough
    152room in the buffers to store any of the data in the buffers.
    153
    154For FPGA to host pipes, asynchronous pipes allow data transfer from the FPGA
    155as soon as the respective device file is opened, regardless of if the data
    156has been requested by a read() call. On synchronous pipes, only the amount
    157of data requested by a read() call is transmitted.
    158
    159In summary, for synchronous pipes, data between the host and FPGA is
    160transmitted only to satisfy the read() or write() call currently handled
    161by the driver, and those calls wait for the transmission to complete before
    162returning.
    163
    164Note that the synchronization attribute has nothing to do with the possibility
    165that read() or write() completes less bytes than requested. There is a
    166separate configuration flag ("allowpartial") that determines whether such a
    167partial completion is allowed.
    168
    169Seekable pipes
    170--------------
    171
    172A synchronous pipe can be configured to have the stream's position exposed
    173to the user logic at the FPGA. Such a pipe is also seekable on the host API.
    174With this feature, a memory or register interface can be attached on the
    175FPGA side to the seekable stream. Reading or writing to a certain address in
    176the attached memory is done by seeking to the desired address, and calling
    177read() or write() as required.
    178
    179
    180Internals
    181=========
    182
    183Source code organization
    184------------------------
    185
    186The Xillybus driver consists of a core module, xillybus_core.c, and modules
    187that depend on the specific bus interface (xillybus_of.c and xillybus_pcie.c).
    188
    189The bus specific modules are those probed when a suitable device is found by
    190the kernel. Since the DMA mapping and synchronization functions, which are bus
    191dependent by their nature, are used by the core module, a
    192xilly_endpoint_hardware structure is passed to the core module on
    193initialization. This structure is populated with pointers to wrapper functions
    194which execute the DMA-related operations on the bus.
    195
    196Pipe attributes
    197---------------
    198
    199Each pipe has a number of attributes which are set when the FPGA component
    200(IP core) is built. They are fetched from the IDT (the data structure which
    201defines the core's configuration, see Probing below) by xilly_setupchannels()
    202in xillybus_core.c as follows:
    203
    204* is_writebuf: The pipe's direction. A non-zero value means it's an FPGA to
    205  host pipe (the FPGA "writes").
    206
    207* channelnum: The pipe's identification number in communication between the
    208  host and FPGA.
    209
    210* format: The underlying data width. See Data Granularity below.
    211
    212* allowpartial: A non-zero value means that a read() or write() (whichever
    213  applies) may return with less than the requested number of bytes. The common
    214  choice is a non-zero value, to match standard UNIX behavior.
    215
    216* synchronous: A non-zero value means that the pipe is synchronous. See
    217  Synchronization above.
    218
    219* bufsize: Each DMA buffer's size. Always a power of two.
    220
    221* bufnum: The number of buffers allocated for this pipe. Always a power of two.
    222
    223* exclusive_open: A non-zero value forces exclusive opening of the associated
    224  device file. If the device file is bidirectional, and already opened only in
    225  one direction, the opposite direction may be opened once.
    226
    227* seekable: A non-zero value indicates that the pipe is seekable. See
    228  Seekable pipes above.
    229
    230* supports_nonempty: A non-zero value (which is typical) indicates that the
    231  hardware will send the messages that are necessary to support select() and
    232  poll() for this pipe.
    233
    234Host never reads from the FPGA
    235------------------------------
    236
    237Even though PCI Express is hotpluggable in general, a typical motherboard
    238doesn't expect a card to go away all of the sudden. But since the PCIe card
    239is based upon reprogrammable logic, a sudden disappearance from the bus is
    240quite likely as a result of an accidental reprogramming of the FPGA while the
    241host is up. In practice, nothing happens immediately in such a situation. But
    242if the host attempts to read from an address that is mapped to the PCI Express
    243device, that leads to an immediate freeze of the system on some motherboards,
    244even though the PCIe standard requires a graceful recovery.
    245
    246In order to avoid these freezes, the Xillybus driver refrains completely from
    247reading from the device's register space. All communication from the FPGA to
    248the host is done through DMA. In particular, the Interrupt Service Routine
    249doesn't follow the common practice of checking a status register when it's
    250invoked. Rather, the FPGA prepares a small buffer which contains short
    251messages, which inform the host what the interrupt was about.
    252
    253This mechanism is used on non-PCIe buses as well for the sake of uniformity.
    254
    255
    256Channels, pipes, and the message channel
    257----------------------------------------
    258
    259Each of the (possibly bidirectional) pipes presented to the user is allocated
    260a data channel between the FPGA and the host. The distinction between channels
    261and pipes is necessary only because of channel 0, which is used for interrupt-
    262related messages from the FPGA, and has no pipe attached to it.
    263
    264Data streaming
    265--------------
    266
    267Even though a non-segmented data stream is presented to the user at both
    268sides, the implementation relies on a set of DMA buffers which is allocated
    269for each channel. For the sake of illustration, let's take the FPGA to host
    270direction: As data streams into the respective channel's interface in the
    271FPGA, the Xillybus IP core writes it to one of the DMA buffers. When the
    272buffer is full, the FPGA informs the host about that (appending a
    273XILLYMSG_OPCODE_RELEASEBUF message channel 0 and sending an interrupt if
    274necessary). The host responds by making the data available for reading through
    275the character device. When all data has been read, the host writes on the
    276FPGA's buffer control register, allowing the buffer's overwriting. Flow
    277control mechanisms exist on both sides to prevent underflows and overflows.
    278
    279This is not good enough for creating a TCP/IP-like stream: If the data flow
    280stops momentarily before a DMA buffer is filled, the intuitive expectation is
    281that the partial data in buffer will arrive anyhow, despite the buffer not
    282being completed. This is implemented by adding a field in the
    283XILLYMSG_OPCODE_RELEASEBUF message, through which the FPGA informs not just
    284which buffer is submitted, but how much data it contains.
    285
    286But the FPGA will submit a partially filled buffer only if directed to do so
    287by the host. This situation occurs when the read() method has been blocking
    288for XILLY_RX_TIMEOUT jiffies (currently 10 ms), after which the host commands
    289the FPGA to submit a DMA buffer as soon as it can. This timeout mechanism
    290balances between bus bandwidth efficiency (preventing a lot of partially
    291filled buffers being sent) and a latency held fairly low for tails of data.
    292
    293A similar setting is used in the host to FPGA direction. The handling of
    294partial DMA buffers is somewhat different, though. The user can tell the
    295driver to submit all data it has in the buffers to the FPGA, by issuing a
    296write() with the byte count set to zero. This is similar to a flush request,
    297but it doesn't block. There is also an autoflushing mechanism, which triggers
    298an equivalent flush roughly XILLY_RX_TIMEOUT jiffies after the last write().
    299This allows the user to be oblivious about the underlying buffering mechanism
    300and yet enjoy a stream-like interface.
    301
    302Note that the issue of partial buffer flushing is irrelevant for pipes having
    303the "synchronous" attribute nonzero, since synchronous pipes don't allow data
    304to lay around in the DMA buffers between read() and write() anyhow.
    305
    306Data granularity
    307----------------
    308
    309The data arrives or is sent at the FPGA as 8, 16 or 32 bit wide words, as
    310configured by the "format" attribute. Whenever possible, the driver attempts
    311to hide this when the pipe is accessed differently from its natural alignment.
    312For example, reading single bytes from a pipe with 32 bit granularity works
    313with no issues. Writing single bytes to pipes with 16 or 32 bit granularity
    314will also work, but the driver can't send partially completed words to the
    315FPGA, so the transmission of up to one word may be held until it's fully
    316occupied with user data.
    317
    318This somewhat complicates the handling of host to FPGA streams, because
    319when a buffer is flushed, it may contain up to 3 bytes don't form a word in
    320the FPGA, and hence can't be sent. To prevent loss of data, these leftover
    321bytes need to be moved to the next buffer. The parts in xillybus_core.c
    322that mention "leftovers" in some way are related to this complication.
    323
    324Probing
    325-------
    326
    327As mentioned earlier, the number of pipes that are created when the driver
    328loads and their attributes depend on the Xillybus IP core in the FPGA. During
    329the driver's initialization, a blob containing configuration info, the
    330Interface Description Table (IDT), is sent from the FPGA to the host. The
    331bootstrap process is done in three phases:
    332
    3331. Acquire the length of the IDT, so a buffer can be allocated for it. This
    334   is done by sending a quiesce command to the device, since the acknowledge
    335   for this command contains the IDT's buffer length.
    336
    3372. Acquire the IDT itself.
    338
    3393. Create the interfaces according to the IDT.
    340
    341Buffer allocation
    342-----------------
    343
    344In order to simplify the logic that prevents illegal boundary crossings of
    345PCIe packets, the following rule applies: If a buffer is smaller than 4kB,
    346it must not cross a 4kB boundary. Otherwise, it must be 4kB aligned. The
    347xilly_setupchannels() functions allocates these buffers by requesting whole
    348pages from the kernel, and diving them into DMA buffers as necessary. Since
    349all buffers' sizes are powers of two, it's possible to pack any set of such
    350buffers, with a maximal waste of one page of memory.
    351
    352All buffers are allocated when the driver is loaded. This is necessary,
    353since large continuous physical memory segments are sometimes requested,
    354which are more likely to be available when the system is freshly booted.
    355
    356The allocation of buffer memory takes place in the same order they appear in
    357the IDT. The driver relies on a rule that the pipes are sorted with decreasing
    358buffer size in the IDT. If a requested buffer is larger or equal to a page,
    359the necessary number of pages is requested from the kernel, and these are
    360used for this buffer. If the requested buffer is smaller than a page, one
    361single page is requested from the kernel, and that page is partially used.
    362Or, if there already is a partially used page at hand, the buffer is packed
    363into that page. It can be shown that all pages requested from the kernel
    364(except possibly for the last) are 100% utilized this way.
    365
    366The "nonempty" message (supporting poll)
    367----------------------------------------
    368
    369In order to support the "poll" method (and hence select() ), there is a small
    370catch regarding the FPGA to host direction: The FPGA may have filled a DMA
    371buffer with some data, but not submitted that buffer. If the host waited for
    372the buffer's submission by the FPGA, there would be a possibility that the
    373FPGA side has sent data, but a select() call would still block, because the
    374host has not received any notification about this. This is solved with
    375XILLYMSG_OPCODE_NONEMPTY messages sent by the FPGA when a channel goes from
    376completely empty to containing some data.
    377
    378These messages are used only to support poll() and select(). The IP core can
    379be configured not to send them for a slight reduction of bandwidth.