|
|
Subscribe / Log in / New account

Juggling software interrupts and realtime tasks

Juggling software interrupts and realtime tasks

Posted Dec 6, 2022 3:48 UTC (Tue) by willy (subscriber, #9762)
In reply to: Juggling software interrupts and realtime tasks by willy
Parent article: Juggling software interrupts and realtime tasks

Oh, what I meant to say is that traditional Unix didn't need to distinguish between hard and soft interrupt context. That very document talks about the priority level of interrupts (spl4() thought spl7()). That meant that higher priority interrupts could interrupt lower priority interrupts. As far as I know, x86 didn't (and maybe still doesn't) support that. So Linux disables all interrupts while processing any interrupt, which means that all interrupt routines must be fast and defer anything time-consuming to softirq context (which can be interrupted by hardirqs)


to post comments

Juggling software interrupts and realtime tasks

Posted Dec 19, 2022 18:48 UTC (Mon) by calumapplepie (guest, #143655) [Link] (5 responses)

Interrupt priority levels aren't supported in x86??
That's an interesting choice, given that I've been working with the decade-old PIC32MX processor, which support 7 levels of interrupts-interrupting-interrupts (ie, a handler for priority-1 interrupts can be interrupted by one for priority-2, so on and so forth).

On reflection, the answer to the issue seems clear; while some PIC32 processsors have a second set of registers for holding the interrupted execution context, most don't. That means all interrupts need to save and load every CPU register to memory when starting and stopping; which is a pretty significant chunk of overhead. Having multiple interrupt levels isn't much of a cost on top of that, then.

But I'll bet money that x86 doesn't make that 'shadow register set' optional. And while the simplest AMD64 processor is miles ahead of the most sophisticated PIC32, a complete set of registers is still not a small addition; and why bother having multiple extra sets if one will do?

Juggling software interrupts and realtime tasks

Posted Dec 20, 2022 11:32 UTC (Tue) by Wol (subscriber, #4433) [Link] (3 responses)

Sounds like a feature I believe the 68000 had would not go amiss here ...

I seem to remember it stored its registers in main ram, with a register that specified the base address. Surely it must have cached them in the cpu for speed, but changing that base register would have done a "flush and restore", so you could simply assign a block of ram as a register stack.

Cheers,
Wol

Juggling software interrupts and realtime tasks

Posted Dec 20, 2022 20:00 UTC (Tue) by mpr22 (subscriber, #60784) [Link] (2 responses)

That's very definitely not the Motorola 68000 (the A24D16-bussed 32-bit microprocessor from 1979 with three zeroes in its model number).

It sounds like the Motorola 6809, an enhanced version of the Motorola 6800 (the A16D8-bussed 8-bit microprocessor from 1974 with two zeroes in its model number).

The 6800's actual registers (8-bit accumulators A and B; 16-bit index register X; 16-bit stack pointer SP; 16-bit program counter PC; 8-bit status register with the two high bits hard-wired to 1) were on-chip. However, it had a "zero page" addressing mode for memory access, which took an 8-bit address and zero-extended it to 16 bits. The speed penalty for going to RAM was a lot lower then than it would be today, so you could use the zero page as "pseudoregisters".

Among other enhancements, the 6809 relabelled the "Zero Page" addressing mode as "Direct Page" and added an 8-bit Direct Page register that controlled the high eight bits of the address presented on the bus when using that addressing mode.

Juggling software interrupts and realtime tasks

Posted Dec 21, 2022 8:15 UTC (Wed) by jem (subscriber, #24231) [Link]

The Motorola 68k has the MOVEM instruction which takes a list of registers (a bitmap) to copy to/from consecutive memory locations. The same mnemonic is used for both directions; the assembler determines the variant based on the operands. The instruction does not use a dedicated base register for this, but you can choose from a range of addressing modes for the memory operand. The 68000 is a CISC processor, after all.

Juggling software interrupts and realtime tasks

Posted Dec 21, 2022 10:30 UTC (Wed) by farnz (subscriber, #17727) [Link]

The TMS9900 has only three on-chip registers: Program Counter (PC), Status Register (SR), and Workspace Pointer (WP). It then has instructions that operate on 16-bit registers, which are memory relative to the address in WP - so R0 is actually the two bytes at WP and WP + 1, while R12 is the two bytes at WP + 24 and WP + 25. All ALU operations work on numbered registers, not on the three internal registers, and indirect addressing is also relative to the WP relative registers, not one of the internal three. PC and SR work like in other processors; WP has a dedicated load-immediate and store to register instruction pair, plus can be modified by BLWP (branch and load workspace pointer) and RTWP (return with workspace pointer)

An equivalent behaviour on a modified 6809 would be if changing the Direct Page register also changed D, X, Y, U and S - i.e. changing DP changes all but PC and condition code registers in the 6809.

Juggling software interrupts and realtime tasks

Posted Dec 21, 2022 16:54 UTC (Wed) by excors (subscriber, #95769) [Link]

> Interrupt priority levels aren't supported in x86??

I'm not an expert but after reading a bit, I think it's roughly:

They are supported by the hardware, but Linux doesn't make much use of them.

On x86-64, there is TPR (task-priority register; writeable) and PPR (processor-priority register; read-only; basically the max of TPR and the currently-active interrupt's priority). An interrupt's 8-bit vector number is used as its priority. The top 4 bits are the priority class. The CPU will only handle an interrupt with a priority class higher than PPR. That means an interrupt can only be preempted by one of higher priority than itself, and TPR can be used to mask all interrupts up to a given priority (e.g. a kernel critical section can disable most interrupts, but still allow preemption by the highest-priority ones to meet certain real-time requirements).

As far as I can tell, x86-64 made TPR more easily accessible (through the CR8 register) but the basic functionality is the same as any x86 since Pentium (specifically ones with APIC).

When an interrupt occurs, the CPU will push EIP/EFLAGS/etc to the stack and clear the IF flag (to disable all interrupts) before running the handler. The handler obviously needs to preserve any other registers on the stack before clobbering them. The handler may do some work and then choose to set IF, to allow itself to be preempted by a higher-priority interrupt. Or it may choose not to. It sounds like Linux used to support nested interrupts but removed it in 2010, because of the complexity of preventing stack overflows: https://lwn.net/Articles/380931/ . (...except the posts in that article make it sound like interrupts on the same vector can nest, and I thought PPR would prevent that? I'm probably confused about something.)

For comparison, I think ARMv7-A/ARMv8-A are similar to x86, except the CPU does not push anything onto the stack - it just copies PC and status register (CPSR/PSTATE) into some special registers. The handler must preserve those on the stack before allowing preemption.

ARMv6/7/8-M are different: they don't disable interrupts before running the handler, so all handlers are preemptible by default. The CPU pushes several registers onto the stack on exception entry, and it can even be preempted in the middle of that entry sequence. That allows lower-latency handling of high-priority interrupts.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds