1

I have in the code reading of clear-on-read register (mapped to memory, not part of the CPU) in place that may be interrupted, but the interrupt will always return to the same context.

I was thinking that if the CPU pipeline reads the clear-on-read register, but before executing the instruction the CPU will be interrupted, when it will return it will re-read the clear-on-read register which is now cleared due to the previous read that was interrupted.

Is this scenario is valid? if yes, how it should be handled?

arye
  • 458
  • 3
  • 15
  • CPU's don't interrupt in the middle of one instruction. – tkausl Jul 31 '23 at 05:47
  • @tkausl If I understand correctly, in instruction pipelining instruction may be interrupted in the middle. See in Wikipedia 'Instruction pipelining' that there are just few instructions that are 'Uninterruptible instructions' (there is section there on them) – arye Jul 31 '23 at 05:52
  • @tkausl: ARM LDM, STM, PUSH, and POP instructions are interruptible. Intel REP-string instructions are interruptible. VAX character-string instructions are interruptible. – Eric Postpischil Jul 31 '23 at 10:53
  • 1
    What CPU are you using? Some CPUs may prefetch data from memory in anticipation of load instructions, but this is generally controllable by marking regions of memory not to be prefetched. Similarly, there must be some way of preventing speculative loads of clear-on-read memory before a processor commits to instruction execution. Details depend on processor model. – Eric Postpischil Jul 31 '23 at 11:08
  • I prefer not to add to the question here specific CPU, as it a specific ASIC and not some known one. So I want to know at least for the common CPU's what is tha answer and what should be done. – arye Jul 31 '23 at 12:07

2 Answers2

2

If you have memory-mapped I/O registers where reading them has side effects (such as clearing), then you need to indicate to the CPU that this range of addresses is "volatile". Accesses to such addresses must not be cached, loaded speculatively, reordered with other side effects, etc.

How you do this is CPU-dependent. For instance, on ARMv8, there is a bit in each page table entry that can be set to designate it as "device" memory, which is uncached and so on. x86 has page attribute tables which replace the earlier feature of memory type range registers. For other CPUs, you will need to refer to the vendor's documentation.

Once you have done so, then interrupts are not a concern. When an interrupt occurs, either your load has completed, in which case the loaded value is already in the destination CPU register and the load will not be repeated after the interrupt is handled, or else it has not taken place at all and will begin after the interrupt handler returns.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • This is cool information, thank you. Can you please give link that with the solutions you described `When an interrupt occurs, either your load has completed...or else it has not taken place at all and will begin after the interrupt handler returns` ? – arye Aug 01 '23 at 06:11
  • @arye: The link would be to the architecture specification for the specific CPU, and you said above that you are not interested in CPU-specific answers. Some architecture specs might not state it so explicitly. But usually the "starting point" is to assume that the machine behaves like a primitive scalar, in-order, non-prefetching, cacheless CPU, for which that sentence would certainly be true, and that any deviations from that model will be documented. – Nate Eldredge Aug 01 '23 at 17:29
  • I agree I will need to talk about it with my ASIC people, I was just searching to see if in the examples you gave, ARMv8 and x86, it is written explicitly. – arye Aug 01 '23 at 18:18
  • @arye: See the ARMv8-A Architecture Reference Manual section B2.7.2 for info about Device memory. For instance: "Speculative data accesses are not permitted to any memory location with any Device memory attribute. This means that each memory access to any Device memory type must be one that would be generated by a simple sequential execution of the program." Then see D1.3.1 for exception handling. Exceptions are *precise* except for SError which is for catastrophes like memory parity errors. – Nate Eldredge Aug 02 '23 at 00:14
  • "An exception is precise if on taking the exception, the PE state and the memory system state is consistent with the PE having executed all of the instructions up to but not including the point in the instruction stream where the exception was taken from, and none afterwards." – Nate Eldredge Aug 02 '23 at 00:14
-1

This problem can be solved probably by preventing interrupts explicitly while the pipeline is processing the instruction:

DISABLE_INTERRUPTS
NOP
NOP
NOP
<Read the memory>
ENABLE_INTERRUPTS

This is not very nice solution, as need to detect each such register read and wrap it and need privilege to disable interrupts, but it is generic solution.

arye
  • 458
  • 3
  • 15