an issue about isr stack

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
orighost
Posts: 17
Joined: Sun May 27, 2012 8:38 pm

an issue about isr stack

Post by orighost »

a issue ablout Bran's Kernel Development tutorial
--------------------------
...
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax ;???
mov eax, _irq_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret

-------------------------------------
struct regs
{
unsigned int gs, fs, es, ds; /* pushed the segs last */
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */
unsigned int int_no, err_code; /* our 'push byte #' and ecodes do this */
unsigned int eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */
};

-------------------------------------------
I am confused why push esp into stack, and in the regs struct has no correspondence variable?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: an issue about isr stack

Post by Brendan »

Hi,
orighost wrote:I am confused why push esp into stack, and in the regs struct has no correspondence variable?
I'd assume that the interrupt handler uses a prototype like this:

Code: Select all

void _irq_handler(struct regs * registers);
C passes parameters on the stack. The "push %eax" puts the "struct regs *registers" parameter on the stack.

If you used this instead:

Code: Select all

_irq_handler(struct regs registers);
Then the compiler would need to create a copy of the structure (which would be slower and consume more stack space), and your interrupt handler couldn't modify anything in the original structure as it'd only be modifying a copy and not the original (note: this isn't very important for IRQs, but is important for exceptions and kernel APIs).

However, an IRQ handler should never trash the interrupted code's registers, so a more correct function prototype would be:

Code: Select all

void _irq_handler(struct regs const * const registers);
However, an IRQ handler probably doesn't need to care what values were in the interrupted code's registers either, so it'd probably make more sense to forget about "struct regs" entirely and do:

Code: Select all

void _irq_handler(unsigned int int_no);
Exceptions and software interrupts are very different to IRQs. For these I'd want a separate stub for each exception and software interrupt, with a prototype like:

Code: Select all

void _whatever_handler(struct regs * registers);
Note: I hope you understand that for exceptions and software interrupts, then idea of having a generic handler that does nothing more than "switch(int_no) { .... }" is silly (or excessively lazy).

For "different stub for each exception and software interrupt", there's no need for "struct regs" to have an "unsigned int int_no" field (e.g. the general protection fault handler already knows that it is "interrupt 0x0D"); and half the exception/software interrupt handlers won't need "error code", and some exception handlers may need a slightly different "struct regs" structure (e.g. for the page fault handler it's a good idea to have a "CR2" field and save CR2 in the stub), and some (double fault, NMI, machine check) might be task gates that need a radically different structure.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: an issue about isr stack

Post by bluemoon »

A "faster" method is:

Code: Select all

push edi
push esi
...
push ebx
push eax
call handler
add esp, 4
pop ebx
pop ...


struct {
   uint32_t eax, ebx, ...;
} reg;
int handler(const struct reg registers) {
...
}
Since the stub already "copied" the parameter on stack.
orighost
Posts: 17
Joined: Sun May 27, 2012 8:38 pm

Re: an issue about isr stack

Post by orighost »

Thanks Brendan.
I know that the process 's argument is a pointer, not a value. So push the the address of struct(or stack top) .
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: an issue about isr stack

Post by Combuster »

Brendan wrote:However, an IRQ handler should never trash the interrupted code's registers, so a more correct function prototype would be:

Code: Select all

void _irq_handler(struct regs const * const registers);
However, an IRQ handler is a typical cause for a task switch - especially in microkernels. So you want to make sure that's still possible.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply