Five EmbedDev logo Five EmbedDev

An Embedded RISC-V Blog
RISC-V External Debug Support

Access Register

[acAccessregister]

This command gives the debugger access to CPU registers and allows it to execute the Program Buffer. It performs the following sequence of operations:

If is clear and is set, then copy data from the register specified by into the arg0 region of data, and perform any side effects that occur when this register is read from M-mode.

If is set and is set, then copy data from the arg0 region of data into the register specified by , and perform any side effects that occur when this register is written from M-mode.

If is set, increment .

Execute the Program Buffer, if is set.

If any of these operations fail, is set and none of the remaining steps are executed. An implementation may detect an upcoming failure early, and fail the overall command before it reaches the step that would cause failure. If the failure is that the requested register does not exist in the hart, must be set to 3 (exception).

Debug Modules must implement this command and must support read and write access to all GPRs when the selected hart is halted. Debug Modules may optionally support accessing other registers, or accessing registers when the hart is running. It is recommended that if one register in a group is accessible, then all registers in that group are accessible, but each individual register (aside from GPRs) may be supported differently across read, write, and halt status.

Registers might not be accessible if they wouldn’t be accessible by M mode code currently running. (E.g. fflags may not be accessible when mstatus.|FS| is 0.) If this is the case, the debugger is responsible for changing state to make the registers accessible. The Core Debug Registers (Section [debreg]) should be accessible if abstract CSR access is implemented.

|r|l| Numbers & Group Description
0x0000 – 0x0fff & CSRs. The “PC” can be accessed here through .
0x1000 – 0x101f & GPRs
0x1020 – 0x103f & Floating point registers
0xc000 – 0xffff & Reserved for non-standard extensions and internal use.

The encoding of was chosen to match in .

This command modifies arg0 only when a register is read. The other data registers are not changed.

image

image

Field Description
[acAccessregisterCmdtype] |cmdtype| This is 0 to indicate Access Register Command.
[acAccessregisterAarsize] |aarsize|

2: Access the lowest 32 bits of the register.

3: Access the lowest 64 bits of the register.

4: Access the lowest 128 bits of the register.

If specifies a size larger than the register’s actual size, then the access must fail. If a register is accessible, then reads of less than or equal to the register’s actual size must be supported.

This field controls the Argument Width as referenced in Table [tab:datareg].

[acAccessregisterAarpostincrement] |aarpostincrement|

0: No effect. This variant must be supported.

1: After a successful register access, is incremented (wrapping around to 0). Supporting this variant is optional. It is undefined whether the increment happens when is 0.

[acAccessregisterPostexec] |postexec|

0: No effect. This variant must be supported, and is the only supported one if is 0.

1: Execute the program in the Program Buffer exactly once after performing the transfer, if any. Supporting this variant is optional.

[acAccessregisterTransfer] |transfer|

0: Don’t do the operation specified by .

1: Do the operation specified by .

This bit can be used to just execute the Program Buffer without having to worry about placing valid values into or .

[acAccessregisterWrite] |write|

When is set: 0: Copy data from the specified register into arg0 portion of data.

1: Copy data from arg0 portion of data into the specified register.

[acAccessregisterRegno] |regno| Number of the register to access, as described in Table [tab:regno]. may be used as an alias for PC if this command is supported on a non-halted hart.

Quick Access

[acQuickaccess]

Perform the following sequence of operations:

If the hart is halted, the command sets to “halt/resume” and does not continue.

Halt the hart. If the hart halts for some other reason (e.g. breakpoint), the command sets to “halt/resume” and does not continue.

Execute the Program Buffer. If an exception occurs, is set to “exception” and the program buffer execution ends, but the quick access command continues.

Resume the hart.

Implementing this command is optional.

This command does not touch the data registers.

image

Field Description
[acQuickaccessCmdtype] |cmdtype| This is 1 to indicate Quick Access command.

Access Memory

[acAccessmemory]

This command lets the debugger perform memory accesses, with the exact same memory view and permissions as the selected hart has. This includes access to hart-local memory-mapped registers, etc. The command performs the following sequence of operations:

Copy data from the memory location specified in arg1 into the arg0 portion of data, if is clear.

Copy data from the arg0 portion of data into the memory location specified in arg1, if is set.

If is set, increment arg1.

If any of these operations fail, is set and none of the remaining steps are executed. An access may only fail if the hart, running M-mode code, might encounter that same failure when it attempts the same access. An implementation may detect an upcoming failure early, and fail the overall command before it reaches the step that would cause failure.

Debug Modules may optionally implement this command and may support read and write access to memory locations when the selected hart is running or halted. If this command supports memory accesses while the hart is running, it must also support memory accesses while the hart is halted.

The encoding of was chosen to match in .

This command modifies arg0 only when memory is read. It modifies arg1 only if is set. The other data registers are not changed.

image

image

Field Description
[acAccessmemoryCmdtype] |cmdtype| This is 2 to indicate Access Memory Command.
[acAccessmemoryAamvirtual] |aamvirtual|

An implementation does not have to implement both virtual and physical accesses, but it must fail accesses that it doesn’t support.

0: Addresses are physical (to the hart they are performed on).

1: Addresses are virtual, and translated the way they would be from M-mode, with set.

[acAccessmemoryAamsize] |aamsize|

0: Access the lowest 8 bits of the memory location.

1: Access the lowest 16 bits of the memory location.

2: Access the lowest 32 bits of the memory location.

3: Access the lowest 64 bits of the memory location.

4: Access the lowest 128 bits of the memory location.

[acAccessmemoryAampostincrement] |aampostincrement| After a memory access has completed, if this bit is 1, increment arg1 (which contains the address used) by the number of bytes encoded in .
[acAccessmemoryWrite] |write|

0: Copy data from the memory location specified in arg1 into the low bits of arg0. Any remaining bits of arg0 now have an undefined value.

1: Copy data from the low bits of arg0 into the memory location specified in arg1.

[acAccessmemoryTargetspecific] |target-specific| These bits are reserved for target-specific uses.