3

I'm reading the Intel documentation on control registers, but I'm struggling to understand how CR8 register is used. To quote the docs (2-18 Vol. 3A):

Task Priority Level (bit 3:0 of CR8) — This sets the threshold value corresponding to the highest- priority interrupt to be blocked. A value of 0 means all interrupts are enabled. This field is available in 64- bit mode. A value of 15 means all interrupts will be disabled.

I have 3 quick questions, if you don't mind:

  1. So bits 3 thru 0 of CR8 make up those 16 levels of priority values. But priority of what? A running "thread", I assume, correct?

  2. But what is that priority value in CR8 compared to when an interrupt is received to see if it has to be blocked or not?

  3. When an interrupt is blocked, what does it mean? Is it "delayed" until later time, or is it just discarded, i.e. lost?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
MikeF
  • 1,021
  • 9
  • 29

3 Answers3

5

CR8 indicates the current priority of the CPU. When an interrupt is pending, bits 7:4 of the interrupt vector number is compared to CR8. If the vector is greater, it is serviced, otherwise it is held pending until CR8 is set to a lower value.

Assuming the APIC is in use, it has an IRR (Interrupt Request Register) with one bit per interrupt vector number. When that bit is set, the interrupt is pending. It can stay that way forever.

When an interrupt arrives, it is ORed into the IRR. If the interrupt is already pending (that is, the IRR bit for that vector is already set), the new interrupt is merged with the prior one. (You could say it is dropped, but I don't think of it that way; instead, I say the two are combined into one.) Because of this merging, interrupt service routines must be designed to process all the work that is ready, rather than expecting a distinct interrupt for each unit of work.

prl
  • 11,716
  • 2
  • 13
  • 31
  • Hmm. Thanks. How long is an interrupt held pending? What if CR8 is always kept at the maximum level. Is there a buffer where those interrupts are collected before they are processed in that case? – MikeF Jul 24 '18 at 08:39
  • @MikeF: presumably it's exactly the same as when you run `cli` and don't `sti` for a long time. Yes, interrupts can be lost; my understanding is that there's only one bit of buffer state (pending or not) per IRQ line. – Peter Cordes Jul 24 '18 at 13:16
  • 1
    I updated the answer with more information about pending interrupts. @Peter – prl Jul 24 '18 at 17:59
  • @PeterCordes: That is interesting. I can't seem to find that the high 4-bits of the interrupt vector are used as its priority anywhere in the Intel documentation. Only AMD briefly states that it is implementation dependent. Also, prl, I believe your rule should say that only if CR8 is not 0, right? Otherwise, if it is 0, if I'm not mistaking interrupts 0 thru 31 are system interrupts, and half of them will be permanently blocked (since its priority will be 0 which is not > CR8 that is also 0.) Am I reading it correctly? – MikeF Jul 25 '18 at 03:15
  • 3
    Volume 3A, Section 10.8.3 – prl Jul 25 '18 at 04:44
  • 1
    Vectors 0 through 31 are not interrupts, they are exceptions. The task priority doesn’t affect delivery of exceptions. (Actually it is possible to use vectors 16 - 31 as interrupts, even though they are reserved.) – prl Jul 25 '18 at 04:47
0

Another related point is that Windows (and I assume Linux) tries to keep the IRQ level of a CPU as low as possible at all times. Interrupt service routines do as little work as possible at their elevated hardware interrupt level and then cue a deferred procedure call to do the rest of their work at DPC IRQ level. The DPC will normally be serviced immediately unless another IRQ has arrived because they are at a higher priority than normal processes.

Once a CPU starts executing a DPC it will then execute all the DPC's in its per CPU DPC cue before returning the CPU IRQL to zero to allow normal threads to resume.

The advantage of doing it this way is that an incoming hardware IRQ of any priority can interrupt a DPC and get its own DPC on the cue almost immediately, so it never gets missed.

  • 1
    Yes, Linux also has what it calls "top half" interrupt handlers that just do as little as possible and queue work for "bottom half" tasks, like you describe. – Peter Cordes May 17 '20 at 21:07
0

I should also try and explain ( as I think it is ) the difference between the IRQ level of a CPU and the priority of an IRQ .

Before Control Register 8 became available with x64 the CPU had no notion of an IRQ level.

The designers of windows NT decided that every logical processor in a system should have a NOTIONAL IRQ Level that would be stored in a data structure called a processor control block for each CPU. They decided there should be 32 levels for no reason I know of .

Software and hardware interrupts are also assigned a level so if they are above the level that the CPU has assigned then they are allowed to continue.

Windows does NOT make use of the interrupt priority assigned by the PIC/APIC hardware, instead it uses the interrupt mask bits in them. The various pins are assigned a vector number and then they get a level.

When Windows raises the LRQL of a CPU in its PCB it also reprograms the interrupt mask of the PIC/APIC. But not straight away.

Every interrupt that occurs causes the Windows trap dispatcher to execute and compare the IRQ level with the CPU IRQL and if the IRQ level is higher the interrupt goes ahead, if not THEN Windows reprograms the mask and returns to the executing thread instead.

The reason for that is that reprogramming the PIC takes time and if no lower level IRQ comes in then windows can save its self a job.

On x64 there IS CR8 and I am still looking at how that works.

  • 3
    This doesn't look like it belongs in a separate answer. It should be an edit to your earlier answer. You should probably merge your accounts (or just go log into your original account) and edit that existing answer. (And delete this answer so there's only one more-complete answer.) – Peter Cordes Jun 12 '20 at 23:20
  • Your earlier answer (from May) seemed fine; I thought it was interesting so I upvoted it. This also seems fine. Don't expect a lot of attention for answers to relatively obscure old questions (more than a day or two old) in tags that are a lot less popular than C++. I think only a few people (like me) monitor any activity (not just *new questions*) in x86 / asm tags. – Peter Cordes Jun 12 '20 at 23:57
  • OR Move it yourself, make it look pretty. – Graham Dearsley Jun 13 '20 at 00:03
  • Well pete I went for an older question when this site still had interesting questions. – Graham Dearsley Jun 13 '20 at 00:07
  • Sorry Pete. Just venting off. Fed up with form over usefulness – Graham Dearsley Jun 13 '20 at 00:14