- Single-step restrictions
- Hard vs. soft hangs (CPU core availability)
- Hardware vs. software breakpoints
- Application of breakpoints after reset, SMM entry, etc.
- Memory access restrictions (speed and stability)
It's not possible to step when the target is stopped at a HLT instruction. Set a breakpoint after the HLT and run to it instead.
Software debug over JTAG uses the CPU as a "debug agent" that acts under control of the debugger. This means the CPU must be able to fetch code and execute it, and communication with other system agents (e.g. memory controller, IO devices) must be possible. If there is a hard-hang on the CPU or any required resource then the debugger capabilities will degrade or simply not function.
Hardware vs. Software Breakpoints
The debugger can use both hardware and software breakpoints, each of these has strengths and weaknesses:
- Hardware Breakpoints are implemented using the DRx architectural breakpoint registers described in the Intel SDM. They have the advantage of being usable directly at reset, being non-volatile, and being usable with flash or other read-only memory. The downside is that they are a finite resource.
- Software Breakpoints require modifying system memory as they are implemented by replacing the opcode at the desired location with a special instruction. This makes them an unlimited resource, but the memory dependency mean you cannot install them prior to a module being loaded in memory, and if the target software overwrites that memory then they will become invalid.
In general, any debug feature that must be enabled by the debugger does not persist after a reset, and may be impacted after other architectural mode transitions such as SMM entry/exit or VM entry/exit. Specific examples include:
- CPU Reset will clear all debug features, except for reset break. This means for example that user-specified breakpoints will be invalid until the target halts once after reset. Note that this halt can be due to either a reset-break, or due to a user-initiated halt. In either case the debugger will restore the necessary debug features.
- SMM Entry/exit will disable/re-enable breakpoints, this means you cannot specify a breakpoint in SMRAM while halted outside of SMRAM. If you wish the break within SMRAM, you must first halt at the SMM entry-break and manually apply the breakpoint. Alternatively you can patch the BIOS to re-enable breakpoints when entering SMM, but this requires the ability to modify the BIOS which cannot be used in production code. See also Retaining Breakpoints Set Before SSM Entry.
Memory Access Restrictions
In general the JTAG debugger can access any valid address in the system, however there are two fundamental limitations:
- Access to invalid memory addresses will crash the target. This includes both explicit reads by the user, and implicit reads as part of some debugger function (such as call stack unwinding). If such problems are suspected then the user should close all un-needed windows to minimize the chances of a failure. Note that some debugger algorithms are dependent on target hardware/software state, and if that state is invalid then the debugger has no protection against this.
- Memory access over JTAG is slow, and using multiple debugger features which are memory intensive can slow down the overall debugger responsiveness. Examples including opening many windows simultaneously, or using large trace buffers.
Determinism in reset is a fundamental requirement for a stable debug session, the problem is that each platform can implement reset slightly differently. If the debugger is not working properly and the target is also showing reset instability then the user should consider the following topics:
- Debugger-initiated reset is the case where the debugger issues a command via the debug port to reset the target. The conventional Intel method via JTAG is to toggle the reset pin on the debug port, but other methods include a TAP-based reset, issuing IO writes to the south complex, and also toggling the power-good line on the debug port. The debugger provides options to select the best method for the target.
- Target initiated reset, includes both software flows that reset the target, as well as the user simply power-cycling the target. Detection of these conditions are generally dependent on the power and reset sideband signals on the debug port. If a target does not implement these sideband signals then the debugger may not function as expected.
- Multiple Resets are implemented on some targets due to platform initialization requirements, to the debugger this appears as multiple back to back target-initiated resets. In some cases the debugger may lose sync with the target, in particular around application of breakpoints.
Watchdog Timers can be implemented in the platform, the firmware/OS, or some combination of the two.
- Platform Watchdog Timers are implemented by a non-CPU device that can reset the platform if a heartbeat condition is not seen. If the heartbeat is implemented in software then halting the target via JTAG can result in spontaneous resets, either while the target is halted, or immediately after resuming execution.
- Firmware/OS Watchdog Timers are implemented entirely in software, but may rely on hardware resources such as the TSC to detect hangs on a CPU. If the debugger does not control the simultaneous run/stop of all threads properly then the OS may detect this as an error condition.