Debugging Cortex-M7 with data cache
The Cortex-M7 processor has internal flag that identifies debugger accesses as either cacheable, or non-cacheable. Non-cacheable is the default, and it causes all requests to bypass the data cache.
Openocd tries to set the flag in stm32h7x.cfg, but that only works for low-level access debuggers. ST-Link is a high-level debugger (you can check with monitor using_hla in gdb). That means it should handle setting that flag automatically.
Turns out that the solution is simple: upgrade ST-Link firmware. I'm not sure what firmware version introduces data cache support, but V2J37S0 worked for me.