Skip to content

target/target: drop the cached value when force-reading a register#25

Open
en-sc wants to merge 1 commit intosyntacorefrom
en-sc/warn-about-reg-invalidation
Open

target/target: drop the cached value when force-reading a register#25
en-sc wants to merge 1 commit intosyntacorefrom
en-sc/warn-about-reg-invalidation

Conversation

@en-sc
Copy link
Collaborator

@en-sc en-sc commented Mar 13, 2026

Consider the write of a GPR (cacheable) that is followed by a force read. After the write the GPR is valid and dirty.
When force reading, before the patch, the valid bit was cleared. This makes the state of the register upon entry to reg->get() nonsensical, i.e.:

  • valid is low, meaning the value in the cache is not the most recent value of the register and needs to be updated.
  • dirty is high, mening the value in the cache is more recent then the value on the target, so the register on the target needs to be updated with the value from the cache.

There are two behaviors possible here:

  1. Update the value on the target, using the value from the cache before reading.
  2. Discard the value in the cache.

(1) is more preferable since it guarantees correctness (i.e. on a propery-working cacheable register reading and force-reading the register will always result in the same value). Unfortunately, it is not readily available, since there needs to be an additional register method: reg->flush(). See [1] for more details.

In the meantime, to avoid this inconsistent state of a cache entry, this patch introduces behavior (2). This will be problematic, e.g. on RISC-V platforms some registers are "saved" using the cache. This works as follows:

  • "Save" the register in the cache, simply marking a valid cache entry as dirty.
  • Performe (possibly multiple) operation that in the process change the value of this register as a side-effect.
  • When needed to update the state of the target (e.g. on resume) the value from the cache will be written to the target, restoring the register value.

Now imagine the user force-reads a "saved" register. The original value will be dorpped and the clobbered value from the target (which depends on the operations and algorithms used) will be read into the cache and marked as valid.

1: https://review.openocd.org/c/openocd/+/8070

Change-Id: I69583a31e930050ec450a9b266a0350828199b47

@en-sc en-sc requested a review from aap-sc March 13, 2026 12:52
@en-sc en-sc self-assigned this Mar 13, 2026
@en-sc en-sc force-pushed the en-sc/warn-about-reg-invalidation branch from e3292c2 to a6f1272 Compare March 13, 2026 13:12
Consider the write of a GPR (cacheable) that is followed by a force read.
After the write the GPR is valid and dirty.
When force reading, before the patch, the valid bit was cleared.
This makes the state of the register upon entry to `reg->get()`
nonsensical, i.e.:
* `valid` is low, meaning the value in the cache is not the most recent
  value of the register and needs to be updated.
* `dirty` is high, mening the value in the cache is more recent then the
  value on the target, so the register on the target needs to be updated
  with the value from the cache.

There are two behaviors possible here:
1. Update the value on the target, using the value from the cache before
   reading.
2. Discard the value in the cache.

(1) is more preferable since it guarantees correctness (i.e. on a
propery-working cacheable register reading and force-reading the
register will always result in the same value). Unfortunately, it is not
readily available, since there needs to be an additional register
method: `reg->flush()`. See [1] for more details.

In the meantime, to avoid this inconsistent state of a cache entry, this
patch introduces behavior (2). This will be problematic, e.g. on RISC-V
platforms some registers are "saved" using the cache. This works as
follows:
- "Save" the register in the cache, simply marking a valid cache entry
  as dirty.
- Performe (possibly multiple) operation that in the process change the
  value of this register as a side-effect.
- When needed to update the state of the target (e.g. on resume) the
  value from the cache will be written to the target, restoring the
  register value.

Now imagine the user force-reads a "saved" register. The original value
will be dorpped and the clobbered value from the target (which depends
on the operations and algorithms used) will be read into the cache and
marked as valid.

1: https://review.openocd.org/c/openocd/+/8070

Change-Id: I69583a31e930050ec450a9b266a0350828199b47
@en-sc en-sc force-pushed the en-sc/warn-about-reg-invalidation branch from a6f1272 to 2b0887c Compare March 13, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants