riscv-collab / riscv-openocd

Fork of OpenOCD that has RISC-V support
Other
452 stars 328 forks source link

Failed to write to memory, connecting to spike #1066

Closed TimMThomas closed 6 months ago

TimMThomas commented 6 months ago

Hey everyone, I hope this is the right place for this, if not i will probably create soonish a WIP pull request for Zephyr. Im in the process of porting Zephyr to Spike. That was thankfully relatively easy, and im able to run sample applications with no problems. I am also able to connect with openocd (both this one, and the upstream one) and then use gdb.

Single stepping, changing local variables etc. with gdb works, but as soon as i try to add a breakpoint, openocd reports that it fails to write to memory (for both upstream and this one).

The example application from spike's readme works, so my guess is it is either a misconfiguration of openocd from my side or of spike. Has anyone an idea why this is happening?

Spike commandline (running the zephyr synchronization example):

(.venv) isnogud% spike --isa=rv64imac -m0x80000000:0x100000000 --rbb-port=9824 build/zephyr/zephyr.elf
Listening for remote bitbang connection on port 9824.
warning: tohost and fromhost symbols not in ELF; can't communicate with target
*** Booting Zephyr OS build v3.6.0-2970-g92417967cfc5 ***
thread_a: Hello World from cpu 0 on spike_riscv64!
thread_b: Hello World from cpu 0 on spike_riscv64!
thread_a: Hello World from cpu 0 on spike_riscv64!
thread_b: Hello World from cpu 0 on spike_riscv64!
…

openocd config file. I also tried to add a $_TARGETNAME configure -work-area-virt 0x80000000 but the results are the same with it:

isnogud% cat ~/spike.cfg       
adapter driver remote_bitbang
remote_bitbang host localhost
remote_bitbang port 9824

set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0xdeadbeef

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME

gdb_report_data_abort enable

init
halt

openocd log, after just opening gdb, adding a breakpoint and continuing:

isnogud% openocd -f ~/spike.cfg 
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
debug_level: 2

Info : only one transport option; autoselect 'jtag'
Warn : An adapter speed is not selected in the init scripts. OpenOCD will try to run the adapter at the low speed (100 kHz)
Warn : To remove this warnings and achieve reasonable communication speed with the target, set "adapter speed" or "jtag_rclk" in the init scripts.
Info : Initializing remote_bitbang driver
Info : Connecting to localhost:9824
Info : remote_bitbang driver initialized
Info : This adapter doesn't support configurable speed
Info : JTAG tap: riscv.cpu tap/device found: 0xdeadbeef (mfg: 0x777 (<unknown>), part: 0xeadb, ver: 0xd)
Info : datacount=2 progbufsize=2
Info : Examined RISC-V core; found 1 harts
Info :  hart 0: XLEN=64, misa=0x8000000000141105
Info : starting gdb server for riscv.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : accepting 'gdb' connection on tcp/3333
Warn : Failed to write memory via program buffer.
Error: Failed write (NOP) at 0x7; status=2
Error: Failed write (NOP) at 0x6; status=2
Warn : Failed to write memory via abstract access.
Error: Target riscv.cpu: Failed to write memory (addr=0x800003b8)
Error:   progbuf=failed, sysbus=skipped (unsupported size), abstract=failed
Error: Failed write (NOP) at 0x7; status=2
Error: Failed write (NOP) at 0x6; status=2
Error: Target riscv.cpu: Failed to write memory (addr=0x800003b8)
Error:   progbuf=failed, sysbus=skipped (unsupported size), abstract=failed
Error: Failed write (NOP) at 0x7; status=2
Error: Failed write (NOP) at 0x6; status=2
Error: Target riscv.cpu: Failed to write memory (addr=0x800003b8)
Error:   progbuf=failed, sysbus=skipped (unsupported size), abstract=failed
Error: Failed write (NOP) at 0x7; status=2
Error: Failed write (NOP) at 0x6; status=2
Error: Target riscv.cpu: Failed to write memory (addr=0x800003b8)
Error:   progbuf=failed, sysbus=skipped (unsupported size), abstract=failed
Error: Failed to write 2-byte breakpoint instruction at 0x800003b8
Error: can't add breakpoint: unknown reason
aap-sc commented 6 months ago
  1. @TimMThomas could you please run OpenOCD with -d3 parameter passed? This enables verbose logging. It will help us to identify the problem.
  2. You can also pass an extra -l command line option to redirect logs to file.
  3. Please, avoid using work-area-virt for now.

The resulting log file may be quite large. Please, zip/tar it.

aap-sc commented 6 months ago

Also if it is possible - would you kindly attach the binary of you application (presuming there is no IP-sensitive information there). This may help too (though, not strictly required).

TimMThomas commented 6 months ago
  1. @TimMThomas could you please run OpenOCD with -d3 parameter passed? This enables verbose logging. It will help us to identify the problem.

Sure, here you go, a run without the work-area-virt: openocd_log.zip

Also if it is possible - would you kindly attach the binary of you application (presuming there is no IP-sensitive information there). This may help too (though, not strictly required).

That is no problem, it is for the time being simply one of the sample applications provided by zephyr. zephyr_elf.zip

aap-sc commented 6 months ago

@TimMThomas that's a peculiarity of your application (zephyr).

It seems that at the startup zephyr configures memory regions and forbids writes to text section (or whatever memory region where the code resides). For example once code reaches 0x800003b2 the memory becomes non-writable.

When you ask gdb to set a breakpoint, it tries to set "software breakpoint" by attempting to re-write memory of application and injecting ebreak instruction. Since memory is not writable - this operation fails.

You have several options here:

  1. Configure zephyr to avoid locking of memory (I assume this is done via pmp mechanism).
  2. Use hw breakpoints instead of SW ones. In GDB this corresponds to hbreak command.
aap-sc commented 6 months ago

@TimMThomas oh, and I've almost forgot! You have a third option, actually. You can enable "system bus" access for spike, by passing this argument: --dm-sba=32 (to spike). This way if accessing via abstract command/progbuf fails, OpenOCD will try to set breakpoints via sysbus access which seems to be excluded from pmp checks.

TimMThomas commented 6 months ago

@aap-sc thanks for your help! Yes, i based my kconfig files on the qemu part of zephyr and i oversaw that pmp was enabled. The `--dm-sba=32' argument works flawlessly. Interestingly enough, hardware breakpoints do not work on my end when pmp is enabled.

TommyMurphyTM1234 commented 6 months ago

Interestingly enough, hardware breakpoints do not work on my end when pmp is enabled.

A verbose openocd -d3 log might shed some light on why that is.