interrupt behaviour on 6502 - emulation

A quick and stupid question about 6502. For example, the instruction NOP takes 2 cycles. If an interrupt occurs on 6502, can it occur in between the 2 cycles of the NOP?
So, is this a possible scenario:
NOP cycle 1
[ INTERRUPT ]
NOP cycle 2
Of course this question extends for other instructions. Will interrupt "wait" for the whole instruction to finish or can it disrupt the instruction itself?

Rounding up the comments as a Community Wiki:
The current instruction finishes first: "When a peripheral device needs service and pulls the interrupt request (IRQ) line low, the currently executing machine-language instruction is allowed to finish, and the 7-clock interrupt sequence is started. This sequence is like the execution of an instruction that was not written into the program, but implicitly inserted by the fact that the IRQ line was pulled down to a logic-low level."
Interrupt status is checked only on the penultimate cycle of an instruction; therefore if an interrupt request is ongoing but the interrupt disable flag is set before the sequence:
CLI
SEI
Then the following will occur:
one cycle before the end of CLI, the interrupt disable flag is still set so nothing happens after CLI;
one cycle before the end of SEI, the interrupt disable flag is now disabled so an interrupt is scheduled;
the SEI sets the interrupt disable flag; and
the interrupt request is then honoured, resulting in a P on the stack with the interrupt disable flag set.

Related

Interrupt handle

In <<understanding Linux kernel>>, it mentions that while interrupt handler is running, the corresponding IRQ line are temporarily ignored. So I want to know why IRQ line need to be ignored, what to be protected? Thanks.
in other words, why "there should be no occurrence of an interrupt until the corresponding interrupt handler has terminated".
If it's a level triggered interrupt, it got to be ignored at least until its source has been cleared by the handler, otherwise the interrupt would occur repeatedly until the stack overflows. And regardless of level or edge triggering, it usually does no good to re-enter a specific interrupt handler while it still processes the interrupt; the actual interrupt routine (top half) should be quite short anyway. See also Top halves and bottom halves concept clarification.

kernel entry points on ARM

I was reading through the ARM kernel source code in order to better my understanding and came across something interesting.
Inside arch/arm/kernel/entry-armv.S there is a macro named vector_stub, that generates a small chunk of assembly followed by a jump table for various ARM modes. For instance, there is a call to vector_stub irq, IRQ_MODE, 4 which causes the macro to be expanded to a body with label vector_irq; and the same occurs for vector_dabt, vector_pabt, vector_und, and vector_fiq.
Inside each of these vector_* jump tables, there is exactly 1 DWORD with the address of a label with a _usr suffix.
I'd like to confirm that my understanding is accurate, please see below.
Does this mean that labels with the _usr suffix are executed, only if the interrupt arises when the kernel thread executing on that CPU is in userspace context? For instance, irq_usr is executed if the interrupt occurs when the kernel thread is in userspace context, dabt_usr is executed if the interrupt occurs when the kernel thread is in userspace context, and so on.
If [1] is true, then which kernel threads are responsible for handling, say irqs, with a different suffix such as irq_svc. I am assuming that this is the handler for an interrupt request that happens in SVC mode. If so, which kernel thread handles this? The kernel thread currently in SVC mode, on whichever CPU receives the interrupt?
If [2] is true, then at what point does the kernel thread finish processing the second interrupt, and return to where it had left off(also in SVC mode)? Is it ret_from_intr?
Inside each of these vector_* jump tables, there is exactly 1 DWORD with the address of a label with a _usr suffix.
This is correct. The table in indexed by the current mode. For instance, irq only has three entries; irq_usr, irq_svc, and irq_invalid. Irq's should be disabled during data aborts, FIQ and other modes. Linux will always transfer to svc mode after this brief 'vector stub' code. It is accomplished with,
#
# Prepare for SVC32 mode. IRQs remain disabled.
#
mrs r0, cpsr
eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
msr spsr_cxsf, r0
### ... other unrelated code
movs pc, lr # branch to handler in SVC mode
This is why irq_invalid is used for all other modes. Exceptions should never happen when this vector stub code is executing.
Does this mean that labels with the _usr suffix are executed, only if the interrupt arises when the kernel thread executing on that CPU is in userspace context? For instance, irq_usr is executed if the interrupt occurs when the kernel thread is in userspace context, dabt_usr is executed if the interrupt occurs when the kernel thread is in userspace context, and so on.
Yes, the spsr is the interrupted mode and the table indexes by these mode bits.
If 1 is true, then which kernel threads are responsible for handling, say irqs, with a different suffix such as irq_svc. I am assuming that this is the handler for an interrupt request that happens in SVC mode. If so, which kernel thread handles this? The kernel thread currently in SVC mode, on whichever CPU receives the interrupt?
I think you have some misunderstanding here. There is a 'kernel thread' for user space processes. The irq_usr is responsible for storing the user mode registers as a reschedule might take place. The context is different for irq_svc as a kernel stack was in use and it is the same one the IRQ code will use. What happens when a user task calls read()? It uses a system call and code executes in a kernel context. Each process has both a user and svc/kernel stack (and thread info). A kernel thread is a process without any user space stack.
If 2 is true, then at what point does the kernel thread finish processing the second interrupt, and return to where it had left off(also in SVC mode)? Is it ret_from_intr?
Generally Linux returns to the kernel thread that was interrupted so it can finish it's work. However, there is a configuration option for pre-empting svc threads/contexts. If the interrupt resulted in a reschedule event, then a process/context switch may result if CONFIG_PREEMPT is active. See svc_preempt for this code.
See also:
Linux kernel arm exception stack init
Arm specific irq initialization

Why do we need to disable interrupt before WFI in ARM Linux cpu_idle

The Linux kernel for ARM basically does CPU_idle in a loop:
while (1) {
disalbe_irq
wfi
enable_irq
}
I can understand that this logic works because "wfi" wakes up ARM regardless of IRQ/FIQ status. However, why "wfi" has to be bracketed by disable_irq and eanble_irq in the first place?
The source code /arch/arm/process.c has the following commends:
* We need to disable interrupts here
* to ensure we don't miss a wakeup call.
But I can't make sense of it. Can someone enlighten me in which scenario we would miss a wakeup call ?
The whole 'going to sleep' sequence in the main loop is split into two steps:
Realize that you don't have work to do;
Try to sleep (i.e. WFI)
The WFI instruction will act as a NOP if there are some interrupt flags still set, which allows the main loop to go back running the required tasks. So far so good.
There's a problem though if an interrupt occurs right after step 1 and before step 2. If that happens then the interrupt flags will be cleared upon exiting the ISR, and when control goes back to the main loop it will hit the WFI instruction with all interrupt flags cleared, causing the CPU to go into sleep before the main loop has had a chance to execute whatever tasks were required by the ISR.
<< Cortex-A Series Programmers Guide >>:
ARM recommends the use of a Data Synchronization Barrier (DSB) instruction
before WFI or WFE, to ensure that pending memory transactions complete before changing state.
If interrupt is enabled, we maybe see this:
DSB
interrupt handler
WFI
But we can not assume that we do not need DSB after interrupt handler. So, we need disable interrupt.

ARM9 Kernel 2.6.10 GPIO pin interrupts return IRQ_HANDLED

I'm trying to better understand the interaction between the "return IRQ_HANDLED" statement used in a GPIO pin-based interrupt handler (top-half) and the GPIO pin hardware. In particular, consider the hypothetical situation wherein a device has pulled a GPIO pin low to indicate that it needs attention. This causes the associated (top half) interrupt handler to be invoked. Now assume that the top-half handler queues up some work and then returns with "return IRQ_HANDLED" but that for whatever reason the interrupt has not been cleared on the device that generated it (i.e. the device is holding the GPIO pin in the low state). Does invocation of "return IRQ_HANDLED" cause the interrupt to be regenerated? I ask this in the context of the following article:
http://www.makelinux.net/books/lkd2/ch06lev1sec4
"Reentrancy and Interrupt Handlers
Interrupt handlers in Linux need not be reentrant. When a given interrupt handler is executing, the corresponding interrupt line is masked out on all processors, preventing another interrupt on the same line from being received. Normally all other interrupts are enabled, so other interrupts are serviced, but the current line is always disabled. Consequently, the same interrupt handler is never invoked concurrently to service a nested interrupt. This greatly simplifies writing your interrupt handler."
The above comment indicates that upon invocation of an interrupt handler, the interrupt line for that interrupt is masked. I'm trying to figure out if the invocation of "return IRQ_HANDLED" is what unmasks the interrupt line. And, with respect to the hypothetical case described above, what would happen if I "return IRQ_HANDLED" yet the device has not really had its interrupt cleared and hence is still holding the GPIO pin in a low (triggered) state. More specifically, will this cause the interrupt to be generated again such that the processor never has a chance to do the work queued when the interrupt first occurred. I.e., would this lead to an interrupt storm wherein the processor could be interrupted endlessly thus not allowing any useful processing to occur. I should add that I ask this question in the context of a single CPU linux ARM9 system (Phytec LPC3180) running kernel 2.6.10.
Thanks in advance,
Jim
PS: I'm not clear as to the difference between enabling/disabling an interrupt (in particular, an interrupt associated with a particular GPIO pin) and masking/unmasking the same GPIO interrupt.

Must IRET be used when returning from an interrupt?

IRET can restore the registers from the stack,including EFLAGS, ESP, EIP and so on, but we can also restore the registers all by ourselves. For example, "movl" can be used to restore the %esp register, "jmp" can jump the address pointed to EIP which is stored on the stack.
The linux kernel returns from all interrupts by IRET, which is a weight instruction.
Some kernel operations (like context switches) happen frequently.
Isn't IRET a waste?
Besides all the heavy stuff IRET can and often should do in addition to a mere blend of POPF+RETF, there's one more thing that it does. It has a special function related to non-maskable interrupts (NMIs).
Concurrent NMIs are delivered to the CPU one by one. IRET signals to the NMI circuitry that another NMI can now be delivered. No other instruction can do this signalling.
If NMIs could preempt execution of other NMI ISRs, they would be able to cause a stack overflow, which rarely is a good thing. Unless we're talking about this wonderful website. :)
So, all in all, IRET is not a waste.
Probably because doing all that manually would need even more CPU clocks.
From wikipedija:
The actual code that is invoked when an interrupt occurs is called the
Interrupt Service Routine (ISR). When an exception occurs, a program
invokes an interrupt, or the hardware raises an interrupt, the
processor uses one of several methods (to be discussed) to transfer
control to the ISR, whilst allowing the ISR to safely return control
to whatever it interrupted after execution is complete. At minimum,
FLAGS and CS:IP are saved and the ISR's CS:IP loaded; however, some
mechanisms cause a full task switch to occur before the ISR begins
(and another task switch when it ends).
So IRET isn't waste, it is minimum (and the fastest way) to return from ISR. Also all other CPU registers used in ISR must be preserved at begining and restored before IRET exsecution!

Resources