/* * GeekOS interrupt handling data structures and functions * Copyright (c) 2001, David H. Hovemeyer * $Revision: 1.1 $ * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". */ /* * This module describes the C interface which must be implemented * by interrupt handlers, and has the initialization function * for the interrupt system as a whole. */ #ifndef GEEKOS_INT_H #define GEEKOS_INT_H #include #include #include /* * This struct reflects the contents of the stack when * a C interrupt handler function is called. * It must be kept up to date with the code in "lowlevel.asm". */ struct Interrupt_State { /* * The register contents at the time of the exception. * We save these explicitly. */ uint_t gs; uint_t fs; uint_t es; uint_t ds; uint_t ebp; uint_t edi; uint_t esi; uint_t edx; uint_t ecx; uint_t ebx; uint_t eax; /* * We explicitly push the interrupt number. * This makes it easy for the handler function to determine * which interrupt occurred. */ uint_t intNum; /* * This may be pushed by the processor; if not, we push * a dummy error code, so the stack layout is the same * for every type of interrupt. */ uint_t errorCode; /* These are always pushed on the stack by the processor. */ uint_t eip; uint_t cs; uint_t eflags; }; /* * An interrupt that occurred in user mode. * If Is_User_Interrupt(state) returns true, then the * Interrupt_State object may be cast to this kind of struct. */ struct User_Interrupt_State { struct Interrupt_State state; uint_t espUser; uint_t ssUser; }; static __inline__ bool Is_User_Interrupt(struct Interrupt_State *state) { return (state->cs & 3) == USER_PRIVILEGE; } /* * The signature of an interrupt handler. */ typedef void (*Interrupt_Handler)(struct Interrupt_State* state); /* * Perform all low- and high-level initialization of the * interrupt system. */ void Init_Interrupts(void); /* * Query whether or not interrupts are currently enabled. */ bool Interrupts_Enabled(void); /* * Block interrupts. */ static __inline__ void __Disable_Interrupts(void) { __asm__ __volatile__ ("cli"); } #define Disable_Interrupts() \ do { \ KASSERT(Interrupts_Enabled()); \ __Disable_Interrupts(); \ } while (0) /* * Unblock interrupts. */ static __inline__ void __Enable_Interrupts(void) { __asm__ __volatile__ ("sti"); } #define Enable_Interrupts() \ do { \ KASSERT(!Interrupts_Enabled()); \ __Enable_Interrupts(); \ } while (0) /* * Dump interrupt state struct to screen */ void Dump_Interrupt_State(struct Interrupt_State* state); /** * Start interrupt-atomic region. * @return true if interrupts were enabled at beginning of call, * false otherwise. */ static __inline__ bool Begin_Int_Atomic(void) { bool enabled = Interrupts_Enabled(); if (enabled) Disable_Interrupts(); return enabled; } /** * End interrupt-atomic region. * @param iflag the value returned from the original Begin_Int_Atomic() call. */ static __inline__ void End_Int_Atomic(bool iflag) { KASSERT(!Interrupts_Enabled()); if (iflag) { /* Interrupts were originally enabled, so turn them back on */ Enable_Interrupts(); } } #define EXCEPTION_DE 0 // Divide by zero #define EXCEPTION_DB 1 // reserved #define EXCEPTION_NMI 2 // NMI #define EXCEPTION_BP 3 // Breakpoint #define EXCEPTION_OF 4 // Overflow #define EXCEPTION_BR 5 // Bound range exceeded #define EXCEPTION_UD 6 // Undefined opcode #define EXCEPTION_NM 7 // Math coprocessor gone missing #define EXCEPTION_DF 8 // Double fault #define EXCEPTION_CO 9 // Coprocessor segment overrrun #define EXCEPTION_TS 10 // Invalid TSS #define EXCEPTION_NP 11 // Segment not present #define EXCEPTION_SS 12 // Stack segment fault #define EXCEPTION_GP 13 // General Protection fault #define EXCEPTION_PF 14 // Page Fault #define EXCEPTION_RES 15 // reserved #define EXCEPTION_MF 16 // Math fault #define EXCEPTION_AC 17 // Alignment check #define EXCEPTION_MC 18 // Machine check #define EXCEPTION_XF 19 // SIMD FP exception // 20+ are reserved #endif /* GEEKOS_INT_H */