irq handler get complete CPU state in arguments
This commit is contained in:
parent
d2417ef349
commit
4e14b05f72
@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
|
#include "cpu_context.h"
|
||||||
|
|
||||||
// c.f. intel software-developer-vol-1 6.4.1
|
// c.f. intel software-developer-vol-1 6.4.1
|
||||||
struct interrupt_frame {
|
struct interrupt_frame {
|
||||||
|
/* Stacked by the CPU */
|
||||||
uint32_t eip;
|
uint32_t eip;
|
||||||
uint32_t cs;
|
uint32_t cs;
|
||||||
uint32_t eflags;
|
uint32_t eflags;
|
||||||
|
@ -15,13 +15,13 @@ int irqSetup()
|
|||||||
// Assembly defined array. This is used to wrap C function than cannot:
|
// Assembly defined array. This is used to wrap C function than cannot:
|
||||||
// * get some cpu state
|
// * get some cpu state
|
||||||
// * return using "iret" instead of "ret" without some compiler __attribute__
|
// * return using "iret" instead of "ret" without some compiler __attribute__
|
||||||
extern vaddr_t irq_handler_wrapper_array[IRQ_NUM];
|
extern native_irq_handler irq_handler_wrapper_array[IRQ_NUM];
|
||||||
|
|
||||||
irq_handler irq_handler_array[IRQ_NUM] = {
|
irq_handler irq_handler_array[IRQ_NUM] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
void interrupt_handler_pic(int interrupt, struct interrupt_frame *frame)
|
void interrupt_handler_pic(int interrupt, struct cpu_state *frame)
|
||||||
{
|
{
|
||||||
if (0 > interrupt || IRQ_NUM <= interrupt) {
|
if (0 > interrupt || IRQ_NUM <= interrupt) {
|
||||||
pr_err("Trying to handle unknow interrupt %d\n", interrupt);
|
pr_err("Trying to handle unknow interrupt %d\n", interrupt);
|
||||||
@ -34,7 +34,7 @@ void interrupt_handler_pic(int interrupt, struct interrupt_frame *frame)
|
|||||||
irq_handler_array[interrupt](frame);
|
irq_handler_array[interrupt](frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int irqSetRoutine(int irq, irq_handler handler)
|
int irqSetRoutine(int irq, native_irq_handler handler)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
if ((irq < 0) || irq >= IRQ_NUM)
|
if ((irq < 0) || irq >= IRQ_NUM)
|
||||||
@ -42,11 +42,9 @@ int irqSetRoutine(int irq, irq_handler handler)
|
|||||||
|
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
|
|
||||||
irq_handler_array[irq] = handler;
|
|
||||||
|
|
||||||
if (handler != NULL) {
|
if (handler != NULL) {
|
||||||
int ret = idt_set_handler(IRQ_INTERRUPT_BASE_ADDRESS + irq,
|
int ret = idt_set_handler(IRQ_INTERRUPT_BASE_ADDRESS + irq,
|
||||||
(unsigned int)irq_handler_array[irq], 0);
|
(unsigned int)handler, 0);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
enableIrq(irq);
|
enableIrq(irq);
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,10 @@
|
|||||||
// https://wiki.osdev.org/Interrupt_Service_Routines That's why we use wrapper around them or
|
// https://wiki.osdev.org/Interrupt_Service_Routines That's why we use wrapper around them or
|
||||||
// the gcc interrupt attribut
|
// the gcc interrupt attribut
|
||||||
// __attribute__((interrupt)) void (*irq_handler)(int irq);
|
// __attribute__((interrupt)) void (*irq_handler)(int irq);
|
||||||
typedef void (*irq_handler)(struct interrupt_frame *frame);
|
typedef void (*irq_handler)(struct cpu_state *frame);
|
||||||
|
typedef void (*native_irq_handler)(struct interrupt_frame *frame);
|
||||||
int irqSetup();
|
int irqSetup();
|
||||||
// For C coded handler (The interrupt specific part is managed by a wrapper)
|
// For C coded handler (The interrupt specific part is managed by a wrapper)
|
||||||
int irqSetRoutineWrapped(int irq, irq_handler handler);
|
int irqSetRoutineWrapped(int irq, irq_handler handler);
|
||||||
// For ASM handler taking care of the special instruction needed by an IRQ handler
|
// For ASM handler taking care of the special instruction needed by an IRQ handler
|
||||||
int irqSetRoutine(int irq, irq_handler handler);
|
int irqSetRoutine(int irq, native_irq_handler handler);
|
||||||
|
@ -16,19 +16,54 @@
|
|||||||
/* uint32_t ip */
|
/* uint32_t ip */
|
||||||
/* uint32_t cs; */
|
/* uint32_t cs; */
|
||||||
/* uint32_t flags */
|
/* uint32_t flags */
|
||||||
/* uint32_t sp; */
|
/* Pushes the other reg to save same and look like a struct cpu_state*/
|
||||||
/* uint32_t ss; */
|
/* Fake error code */
|
||||||
/* Pushes the general purpose registers to the stack */
|
pushl $0
|
||||||
pushal
|
|
||||||
/* Interrupt frame end */
|
/* Backup the actual context */
|
||||||
pushl %esp
|
pushl %ebp
|
||||||
|
movl %esp, %ebp
|
||||||
|
|
||||||
|
pushl %edi
|
||||||
|
pushl %esi
|
||||||
|
pushl %edx
|
||||||
|
pushl %ecx
|
||||||
|
pushl %ebx
|
||||||
|
pushl %eax
|
||||||
|
subl $2,%esp
|
||||||
|
pushw %ss
|
||||||
|
pushw %ds
|
||||||
|
pushw %es
|
||||||
|
pushw %fs
|
||||||
|
pushw %gs
|
||||||
|
|
||||||
|
push %esp
|
||||||
pushl $\irq
|
pushl $\irq
|
||||||
call interrupt_handler_pic
|
call interrupt_handler_pic
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
popal
|
|
||||||
|
/* Restore the context */
|
||||||
|
popw %gs
|
||||||
|
popw %fs
|
||||||
|
popw %es
|
||||||
|
popw %ds
|
||||||
|
popw %ss
|
||||||
|
addl $2,%esp
|
||||||
|
popl %eax
|
||||||
|
popl %ebx
|
||||||
|
popl %ecx
|
||||||
|
popl %edx
|
||||||
|
popl %esi
|
||||||
|
popl %edi
|
||||||
|
popl %ebp
|
||||||
|
|
||||||
|
/* Remove fake error code */
|
||||||
|
addl $4, %esp
|
||||||
|
|
||||||
iret
|
iret
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
|
||||||
.set i, 0
|
.set i, 0
|
||||||
.rept 0x10
|
.rept 0x10
|
||||||
interrupt_pic %i
|
interrupt_pic %i
|
||||||
|
@ -48,9 +48,9 @@ void serialPutc(char a)
|
|||||||
outb(PORT, a);
|
outb(PORT, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialDoIrq(struct interrupt_frame *level)
|
void serialDoIrq(struct cpu_state *state)
|
||||||
{
|
{
|
||||||
(void)level;
|
(void)state;
|
||||||
char c = inb(PORT);
|
char c = inb(PORT);
|
||||||
serialPutc(c);
|
serialPutc(c);
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
void serialSetup(int speed);
|
void serialSetup(int speed);
|
||||||
void serialPutc(char a);
|
void serialPutc(char a);
|
||||||
void serialDoIrq(struct interrupt_frame *frame);
|
void serialDoIrq(struct cpu_state *state);
|
||||||
|
Loading…
Reference in New Issue
Block a user