Fast Debug Channel

From LinuxMIPS
Jump to: navigation, search

The Fast Debug Channel (FDC) is a CDMM device for transferring data to a debugger via an EJTAG probe. It consists of two 32-bit wide FIFOs (one for each direction) with a 4-bit channel number associated with each entry, and has an interrupt which can be used to notify of incoming data.

As a CDMM device it is instantiated per-VPE, so the total number of channels is 16 * number of VPEs.

Character Stream Encoding

The FIFOs are conventionally used to implement 16 separate byte streams using the following encoding of between 1 and 4 bytes in each 32-bit word. Every 1 byte, 2 byte, and 3 byte sequence can be encoded in a single word, as well as the majority of 4 byte sequences (including all ASCII and common binary data).

Encoding of bytes in FDC word
FDC Word Bits Bytes
31..24 23..16 15..8 7..0
0x80 0x80 0x80 W W
0x81 0x81 X W W X
0x82 Y X W W X Y
Z Y X W W X Y Z

Note that the 4 byte encoding can only be used where none of the other 3 encodings match, otherwise it must fall back to only encoding the first 3 bytes in that FDC word.

Linux Support

Linux support for the FDC is implemented as a TTY driver with Console and KGDB transport. It depends on CDMM bus support and some internal IRQ patches. The patches have been merged for v4.1.

TTY Driver

Enable the TTY driver by first enabling the MIPS Common Device Memory Map (CDMM) Driver (CONFIG_MIPS_CDMM), and then enabling the MIPS EJTAG Fast Debug Channel TTY driver (CONFIG_MIPS_EJTAG_FDC_TTY).

A TTY driver is instantiated for each FDC (i.e. per linux CPU / VPE), and exposes a TTY device for each FDC channel on that CPU. The driver takes care of outputting the data from the appropriate CPU (so the TTYs corresponding to offline CPUs won't be usable). The TTY devices are named /dev/ttyFDC<cpu>c<channel>, for example /dev/ttyFDC1c2.

These can be used for various purposes including:

  • getty, to get a login prompt on that FDC channel (usually by way of an entry in /etc/inittab and /etc/securetty).
  • gdbserver, to use the FDC channel as a transport for the GDB remote protocol.
  • Whatever else you'd normally use a serial port or pseudo-TTY for.

Console

The TTY driver must be enabled for the console to work.

To enable the console on an FDC channel, pass the kernel argument console=fdc<channel>. Kernel log output will be sent to the specified channel of whichever CPU is executing, so it may be split between VPEs on SMP systems. It is up to external software to combine these together.

The console TTY (/dev/console) will be attached to the corresponding channel on CPU 0, i.e. /dev/ttyFDC0c1 for console=fdc1.

Early Boot Console

A non-configurable early boot console will be registered automatically by enabling the TTY driver, and then enabling the Early FDC console (CONFIG_MIPS_EJTAG_FDC_EARLYCON). It is fixed to channel 1 and will set up the CDMM and FDC very early during boot to allow log output to be accessible during platform bring-up.

KGDB Transport

To register KGDB operations for the FDC, first enable KGDB: Kernel Debugger (CONFIG_KGDB) and the FDC TTY driver, and then enable Use KGDB over an FDC channel (CONFIG_MIPS_EJTAG_FDC_KGDB). The channel to use can be configured with KGDB FDC channel (CONFIG_MIPS_EJTAG_FDC_KGDB_CHAN). Also check Enable magic SysRq key functions by default (CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE) is set appropriately (as of v4.10 it defaults to 0 on pistachio_defconfig, which requires /proc/sys/kernel/sysrq to be written before KGDB can be triggered via magic sysrq, whereas setting to 1 is more convenient).

Like the consoles, the KGDB transport uses whichever FDC is accessible from the CPU for which KGDB has been invoked. This can sometimes make it a little tricky to find the right CPU when KGDB is started.

Note that when KGDB attempts to read data from the remote debugger, any incoming data on other channels is discarded (since there is only a single shared FIFO between all channels).

The TTY driver invokes magic sysrq G (KGDB) when Ctrl+C is received on the KGDB channel. This is so GDB will be able to interrupt it out of the box, as there is no way to send a BREAK like you can on a serial port. You may need to run the GDB command "set remote interrupt-on-connect".

The TTY driver treats Ctrl+O as a magic sysrq for the console channel, so you can also invoke KGDB with Ctrl+O, G on the console channel.

Enabling in New Platforms

Please first ensure that you have followed the steps to enable the CDMM bus in new platforms.

The Fast Debug Channel driver doesn't absolutely require any platform specific code. It can work without an interrupt by polling for incoming data with a timer, in which case you should see a message in your boot log.

To enable FDC interrupts, your platform must implement the weak function get_c0_fdc_int() (see arch/mips/mti-malta/malta-time.c for an example) so that the driver knows which interrupt it should use. At some point this requirement will hopefully go away.

Once you've got rid of the warning about polling in the log, use /proc/interrupts to check you're receiving interrupts when data is sent to the target.

There are a couple of core specific workarounds that you should be aware of, in case you hit a similar problem on another core:

(Malta bitstreams) interAptiv, proAptiv
There is a workaround in drivers/irqchip/irq-mips-gic.c in gic_get_c0_fdc_int() to disable the interrupt so that it can be polled, as it doesn't seem to be routed correctly in Malta bitstreams. That workaround needs moving to Malta platform code.
proAptiv, P5600
There is a workaround in arch/mips/kernel/idle.c in check_wait() (search for FDC), to avoid using the wait instruction for idle when the FDC driver is enabled, as incoming FDC data can cause the wait not to complete.

Cores with FDC

The following cores are known to have Fast Debug Channel hardware:

See Also