WAIT instruction

From LinuxMIPS
Jump to: navigation, search

Older MIPS CPUs don't have a WAIT instruction. WAIT was introduced as an implementation-specific feature for some MIPS III CPUs, initially for the R4600 before it eventually became a standard feature of the MIPS architecture.

The R10000 like many of the older MIPS CPU took a hardware-only approach to low-power operation, that is there are no knobs, no instructions for software to optimize the power consumption. That also means, no WAIT instruction. Other bits of low-power support in R4x00-processors are fake also, for example the c0_status.rp "reduced power" bit is documented but fairly hidden erratas say it's not implemented.

WAIT uses major opcode COP0 which has bits 31..27 = 010000. Traditionally MIPS doesn't fully decode the minor opcodes, so an unsupported WAIT instruction will not cause an Reserved Instruction exception anyway because the COP0 opcode does exist.

So one could basically pretend WAIT did exist on all MIPS CPUs, even R2000 even though it doesn't - but check_wait is paranoid and really avoids WAIT unless it's officially supported and useful.

Another complexity is that WAIT instruction was defined for many years to leave it to an implementation if the pipeline would ever restart after a WAIT instruction was executed with interrupts disabled. This is a problem because in a typical idle loop of an OS such as Linux

        for (;;) {
                if (wait_available && !need_resched())
                        asm("wait");
                schedule();
        }

there is the race condition between checking need_resched() and actually executing WAIT that need_resched() might change, so WAIT-mode might be entered falsely causing a scheduling delay of up to one tick. The solution is to disable interrupts like:

        for (;;) {
                disable_irq();
                if (wait_available && !need_resched())
                        asm("wait");
                enable_irq();
                schedule();
        }

But some MIPS CPUs might lockup for good if this is attempted. Linux solves the issue by checking in an interrupt handler if it going to resume execution at a WAIT-instruction the modifying the EPC to resume execution at in a way suitable to avoid the issue.