Writing to counter enable registers

I’m trying to enable mhpmcounter3 and mhpmcounter4, by writing to the corresponding counter enable registers, however, I’m getting illegal instruction exceptions. How do I go about doing this correctly?

Machine registers can only be written in machine mode. They can’t be written from applications running in user mode, or from the linux kernel running in supervisor mode.

The easiest way is probably to use OpenOCD via a jtag connection. This can write to any register. Assuming of course that the unmatched implements these registers. There is no requirement that all hardware implement all CSRs, so no guarantee that any random CSR exists on any particular target.

The proper way would be to add support to OpenSBI which runs in machine mode, and then add interfaces that the linux kernel can call, and then modify the kernel to use them, then add syscalls that user code can call. This is a non-trivial project. There are patches for this floating around, maybe posted to the linux kernel mailing list, but they require the relatively new Sscofpmf extension which adds counter overflow support. The Unmatched does not support this extension as the hardware is too old to have it.

Looks like the new perf support may be upstream now. Maybe it works on qemu.
This would also require the new OpenSBI version 0.2(?)

Hi @japk99 as Jim notes below you might find useful some of the tips at Demystifying OpenOCD in the file fe310-g001.cfg especially the tcl functions asic_reset() and the function overrides jtag_init() and init_reset().

Two high-level functions that tie the whole erasing, writing, and verifying process together are asic_ram_load() and asic_rom_load().

And the ram: and rom: targets with their ifeq…endif blocks in the file my_prog.mk shows how an entire compile-assemble-link-load process might look.

(recent branch “psherman42-openocd-2022032”, has some fixes for recent OpenOCD tcl deprecations).