1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:57:45 +00:00

CPU: Use the new interrupt components

Now we use the GenericInterruptHandler class instead of IRQHandler in
the CPU functions.
This commit adds an include to the ISR stub macros header file.
Also, this commit adds support for IRQ sharing, so when an IRQHandler
will try to register to already-assigned IRQ number, a SharedIRQHandler
will be created to register both IRQHandlers.
This commit is contained in:
Liav A 2020-02-22 20:38:17 +02:00 committed by Andreas Kling
parent 9e66eb160c
commit bb73802b15
2 changed files with 212 additions and 87 deletions

View file

@ -24,14 +24,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "APIC.h"
#include "Assertions.h"
#include "IRQHandler.h"
#include "PIC.h"
#include "Process.h"
#include <AK/Assertions.h>
#include <AK/Types.h>
#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/Arch/i386/ISRStubs.h>
#include <Kernel/Interrupts/APIC.h>
#include <Kernel/Interrupts/GenericInterruptHandler.h>
#include <Kernel/Interrupts/IRQHandler.h>
#include <Kernel/Interrupts/InterruptManagement.h>
#include <Kernel/Interrupts/SharedIRQHandler.h>
#include <Kernel/Interrupts/UnhandledInterruptHandler.h>
#include <Kernel/KSyms.h>
#include <Kernel/Process.h>
#include <Kernel/VM/MemoryManager.h>
#include <LibC/mallocdefs.h>
@ -50,7 +54,7 @@ static DescriptorTablePointer s_gdtr;
static Descriptor s_idt[256];
static Descriptor s_gdt[256];
static IRQHandler* s_irq_handler[16];
static GenericInterruptHandler* s_interrupt_handler[GENERIC_INTERRUPT_HANDLERS_COUNT];
static Vector<u16>* s_gdt_freelist;
@ -68,39 +72,7 @@ void gdt_free_entry(u16 entry)
s_gdt_freelist->append(entry);
}
extern "C" void handle_irq(RegisterState);
extern "C" void irq_common_asm_entry();
#define GENERATE_IRQ_ASM_ENTRY(irq, isr_number) \
extern "C" void irq_##irq##_asm_entry(); \
asm(".globl irq_" #irq "_asm_entry\n" \
"irq_" #irq "_asm_entry:\n" \
" pushw $" #isr_number "\n" \
" pushw $0\n" \
" jmp irq_common_asm_entry\n");
asm(
".globl irq_common_asm_entry\n"
"irq_common_asm_entry: \n"
" pusha\n"
" pushl %ds\n"
" pushl %es\n"
" pushl %fs\n"
" pushl %gs\n"
" pushl %ss\n"
" mov $0x10, %ax\n"
" mov %ax, %ds\n"
" mov %ax, %es\n"
" cld\n"
" call handle_irq\n"
" add $0x4, %esp\n" // "popl %ss"
" popl %gs\n"
" popl %fs\n"
" popl %es\n"
" popl %ds\n"
" popa\n"
" add $0x4, %esp\n"
" iret\n");
extern "C" void handle_interrupt(RegisterState);
#define EH_ENTRY(ec, title) \
extern "C" void title##_asm_entry(); \
@ -444,16 +416,65 @@ static void unimp_trap()
hang();
}
void register_irq_handler(u8 irq, IRQHandler& handler)
GenericInterruptHandler& get_interrupt_handler(u8 interrupt_number)
{
ASSERT(!s_irq_handler[irq]);
s_irq_handler[irq] = &handler;
ASSERT(s_interrupt_handler[interrupt_number] != nullptr);
return *s_interrupt_handler[interrupt_number];
}
void unregister_irq_handler(u8 irq, IRQHandler& handler)
static void revert_to_unused_handler(u8 interrupt_number)
{
ASSERT(s_irq_handler[irq] == &handler);
s_irq_handler[irq] = nullptr;
new UnhandledInterruptHandler(interrupt_number);
}
void register_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler)
{
if (s_interrupt_handler[interrupt_number] != nullptr) {
if (s_interrupt_handler[interrupt_number]->purpose() == HandlerPurpose::UnhandledInterruptHandler) {
s_interrupt_handler[interrupt_number] = &handler;
return;
}
if (s_interrupt_handler[interrupt_number]->is_shared_handler() && !s_interrupt_handler[interrupt_number]->is_sharing_with_others()) {
ASSERT(s_interrupt_handler[interrupt_number]->purpose() == HandlerPurpose::SharedIRQHandler);
static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->register_handler(handler);
return;
}
if (!s_interrupt_handler[interrupt_number]->is_shared_handler()) {
ASSERT(s_interrupt_handler[interrupt_number]->purpose() == HandlerPurpose::IRQHandler);
auto& previous_handler = *s_interrupt_handler[interrupt_number];
s_interrupt_handler[interrupt_number] = nullptr;
SharedIRQHandler::initialize(interrupt_number);
static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->register_handler(previous_handler);
static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->register_handler(handler);
return;
}
ASSERT_NOT_REACHED();
} else {
s_interrupt_handler[interrupt_number] = &handler;
}
}
void unregister_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler)
{
ASSERT(s_interrupt_handler[interrupt_number] != nullptr);
if (s_interrupt_handler[interrupt_number]->purpose() == HandlerPurpose::UnhandledInterruptHandler) {
dbg() << "Trying to unregister unused handler (?)";
return;
}
if (s_interrupt_handler[interrupt_number]->is_shared_handler() && !s_interrupt_handler[interrupt_number]->is_sharing_with_others()) {
ASSERT(s_interrupt_handler[interrupt_number]->purpose() == HandlerPurpose::SharedIRQHandler);
static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->unregister_handler(handler);
if (!static_cast<SharedIRQHandler*>(s_interrupt_handler[interrupt_number])->get_sharing_devices_count()) {
revert_to_unused_handler(interrupt_number);
}
return;
}
if (!s_interrupt_handler[interrupt_number]->is_shared_handler()) {
ASSERT(s_interrupt_handler[interrupt_number]->purpose() == HandlerPurpose::IRQHandler);
revert_to_unused_handler(interrupt_number);
return;
}
ASSERT_NOT_REACHED();
}
void register_interrupt_handler(u8 index, void (*f)())
@ -473,23 +494,6 @@ void flush_idt()
asm("lidt %0" ::"m"(s_idtr));
}
GENERATE_IRQ_ASM_ENTRY(0, 0x50)
GENERATE_IRQ_ASM_ENTRY(1, 0x51)
GENERATE_IRQ_ASM_ENTRY(2, 0x52)
GENERATE_IRQ_ASM_ENTRY(3, 0x53)
GENERATE_IRQ_ASM_ENTRY(4, 0x54)
GENERATE_IRQ_ASM_ENTRY(5, 0x55)
GENERATE_IRQ_ASM_ENTRY(6, 0x56)
GENERATE_IRQ_ASM_ENTRY(7, 0x57)
GENERATE_IRQ_ASM_ENTRY(8, 0x58)
GENERATE_IRQ_ASM_ENTRY(9, 0x59)
GENERATE_IRQ_ASM_ENTRY(10, 0x5a)
GENERATE_IRQ_ASM_ENTRY(11, 0x5b)
GENERATE_IRQ_ASM_ENTRY(12, 0x5c)
GENERATE_IRQ_ASM_ENTRY(13, 0x5d)
GENERATE_IRQ_ASM_ENTRY(14, 0x5e)
GENERATE_IRQ_ASM_ENTRY(15, 0x5f)
void idt_init()
{
s_idtr.address = s_idt;
@ -516,25 +520,137 @@ void idt_init()
register_interrupt_handler(0x0f, _exception15);
register_interrupt_handler(0x10, _exception16);
register_interrupt_handler(0x50, irq_0_asm_entry);
register_interrupt_handler(0x51, irq_1_asm_entry);
register_interrupt_handler(0x52, irq_2_asm_entry);
register_interrupt_handler(0x53, irq_3_asm_entry);
register_interrupt_handler(0x54, irq_4_asm_entry);
register_interrupt_handler(0x55, irq_5_asm_entry);
register_interrupt_handler(0x56, irq_6_asm_entry);
register_interrupt_handler(0x57, irq_7_asm_entry);
register_interrupt_handler(0x58, irq_8_asm_entry);
register_interrupt_handler(0x59, irq_9_asm_entry);
register_interrupt_handler(0x5a, irq_10_asm_entry);
register_interrupt_handler(0x5b, irq_11_asm_entry);
register_interrupt_handler(0x5c, irq_12_asm_entry);
register_interrupt_handler(0x5d, irq_13_asm_entry);
register_interrupt_handler(0x5e, irq_14_asm_entry);
register_interrupt_handler(0x5f, irq_15_asm_entry);
register_interrupt_handler(0x50, interrupt_0_asm_entry);
register_interrupt_handler(0x51, interrupt_1_asm_entry);
register_interrupt_handler(0x52, interrupt_2_asm_entry);
register_interrupt_handler(0x53, interrupt_3_asm_entry);
register_interrupt_handler(0x54, interrupt_4_asm_entry);
register_interrupt_handler(0x55, interrupt_5_asm_entry);
register_interrupt_handler(0x56, interrupt_6_asm_entry);
register_interrupt_handler(0x57, interrupt_7_asm_entry);
register_interrupt_handler(0x58, interrupt_8_asm_entry);
register_interrupt_handler(0x59, interrupt_9_asm_entry);
register_interrupt_handler(0x5a, interrupt_10_asm_entry);
register_interrupt_handler(0x5b, interrupt_11_asm_entry);
register_interrupt_handler(0x5c, interrupt_12_asm_entry);
register_interrupt_handler(0x5d, interrupt_13_asm_entry);
register_interrupt_handler(0x5e, interrupt_14_asm_entry);
register_interrupt_handler(0x5f, interrupt_15_asm_entry);
register_interrupt_handler(0x60, interrupt_16_asm_entry);
register_interrupt_handler(0x61, interrupt_17_asm_entry);
register_interrupt_handler(0x62, interrupt_18_asm_entry);
register_interrupt_handler(0x63, interrupt_19_asm_entry);
register_interrupt_handler(0x64, interrupt_20_asm_entry);
register_interrupt_handler(0x65, interrupt_21_asm_entry);
register_interrupt_handler(0x66, interrupt_22_asm_entry);
register_interrupt_handler(0x67, interrupt_23_asm_entry);
register_interrupt_handler(0x68, interrupt_24_asm_entry);
register_interrupt_handler(0x69, interrupt_25_asm_entry);
register_interrupt_handler(0x6a, interrupt_26_asm_entry);
register_interrupt_handler(0x6b, interrupt_27_asm_entry);
register_interrupt_handler(0x6c, interrupt_28_asm_entry);
register_interrupt_handler(0x6d, interrupt_29_asm_entry);
register_interrupt_handler(0x6e, interrupt_30_asm_entry);
register_interrupt_handler(0x6f, interrupt_31_asm_entry);
register_interrupt_handler(0x70, interrupt_32_asm_entry);
register_interrupt_handler(0x71, interrupt_33_asm_entry);
register_interrupt_handler(0x72, interrupt_34_asm_entry);
register_interrupt_handler(0x73, interrupt_35_asm_entry);
register_interrupt_handler(0x74, interrupt_36_asm_entry);
register_interrupt_handler(0x75, interrupt_37_asm_entry);
register_interrupt_handler(0x76, interrupt_38_asm_entry);
register_interrupt_handler(0x77, interrupt_39_asm_entry);
register_interrupt_handler(0x78, interrupt_40_asm_entry);
register_interrupt_handler(0x79, interrupt_41_asm_entry);
register_interrupt_handler(0x7a, interrupt_42_asm_entry);
register_interrupt_handler(0x7b, interrupt_43_asm_entry);
register_interrupt_handler(0x7c, interrupt_44_asm_entry);
register_interrupt_handler(0x7d, interrupt_45_asm_entry);
register_interrupt_handler(0x7e, interrupt_46_asm_entry);
register_interrupt_handler(0x7f, interrupt_47_asm_entry);
register_interrupt_handler(0x80, interrupt_48_asm_entry);
register_interrupt_handler(0x81, interrupt_49_asm_entry);
register_interrupt_handler(0x82, interrupt_50_asm_entry);
register_interrupt_handler(0x83, interrupt_51_asm_entry);
register_interrupt_handler(0x84, interrupt_52_asm_entry);
register_interrupt_handler(0x85, interrupt_53_asm_entry);
register_interrupt_handler(0x86, interrupt_54_asm_entry);
register_interrupt_handler(0x87, interrupt_55_asm_entry);
register_interrupt_handler(0x88, interrupt_56_asm_entry);
register_interrupt_handler(0x89, interrupt_57_asm_entry);
register_interrupt_handler(0x8a, interrupt_58_asm_entry);
register_interrupt_handler(0x8b, interrupt_59_asm_entry);
register_interrupt_handler(0x8c, interrupt_60_asm_entry);
register_interrupt_handler(0x8d, interrupt_61_asm_entry);
register_interrupt_handler(0x8e, interrupt_62_asm_entry);
register_interrupt_handler(0x8f, interrupt_63_asm_entry);
register_interrupt_handler(0x90, interrupt_64_asm_entry);
register_interrupt_handler(0x91, interrupt_65_asm_entry);
register_interrupt_handler(0x92, interrupt_66_asm_entry);
register_interrupt_handler(0x93, interrupt_67_asm_entry);
register_interrupt_handler(0x94, interrupt_68_asm_entry);
register_interrupt_handler(0x95, interrupt_69_asm_entry);
register_interrupt_handler(0x96, interrupt_70_asm_entry);
register_interrupt_handler(0x97, interrupt_71_asm_entry);
register_interrupt_handler(0x98, interrupt_72_asm_entry);
register_interrupt_handler(0x99, interrupt_73_asm_entry);
register_interrupt_handler(0x9a, interrupt_74_asm_entry);
register_interrupt_handler(0x9b, interrupt_75_asm_entry);
register_interrupt_handler(0x9c, interrupt_76_asm_entry);
register_interrupt_handler(0x9d, interrupt_77_asm_entry);
register_interrupt_handler(0x9e, interrupt_78_asm_entry);
register_interrupt_handler(0x9f, interrupt_79_asm_entry);
register_interrupt_handler(0xa0, interrupt_80_asm_entry);
register_interrupt_handler(0xa1, interrupt_81_asm_entry);
register_interrupt_handler(0xa2, interrupt_82_asm_entry);
register_interrupt_handler(0xa3, interrupt_83_asm_entry);
register_interrupt_handler(0xa4, interrupt_84_asm_entry);
register_interrupt_handler(0xa5, interrupt_85_asm_entry);
register_interrupt_handler(0xa6, interrupt_86_asm_entry);
register_interrupt_handler(0xa7, interrupt_87_asm_entry);
register_interrupt_handler(0xa8, interrupt_88_asm_entry);
register_interrupt_handler(0xa9, interrupt_89_asm_entry);
register_interrupt_handler(0xaa, interrupt_90_asm_entry);
register_interrupt_handler(0xab, interrupt_91_asm_entry);
register_interrupt_handler(0xac, interrupt_92_asm_entry);
register_interrupt_handler(0xad, interrupt_93_asm_entry);
register_interrupt_handler(0xae, interrupt_94_asm_entry);
register_interrupt_handler(0xaf, interrupt_95_asm_entry);
register_interrupt_handler(0xb0, interrupt_96_asm_entry);
register_interrupt_handler(0xb1, interrupt_97_asm_entry);
register_interrupt_handler(0xb2, interrupt_98_asm_entry);
register_interrupt_handler(0xb3, interrupt_99_asm_entry);
register_interrupt_handler(0xb4, interrupt_100_asm_entry);
register_interrupt_handler(0xb5, interrupt_101_asm_entry);
register_interrupt_handler(0xb6, interrupt_102_asm_entry);
register_interrupt_handler(0xb7, interrupt_103_asm_entry);
register_interrupt_handler(0xb8, interrupt_104_asm_entry);
register_interrupt_handler(0xb9, interrupt_105_asm_entry);
register_interrupt_handler(0xba, interrupt_106_asm_entry);
register_interrupt_handler(0xbb, interrupt_107_asm_entry);
register_interrupt_handler(0xbc, interrupt_108_asm_entry);
register_interrupt_handler(0xbd, interrupt_109_asm_entry);
register_interrupt_handler(0xbe, interrupt_110_asm_entry);
register_interrupt_handler(0xbf, interrupt_111_asm_entry);
register_interrupt_handler(0xc0, interrupt_112_asm_entry);
register_interrupt_handler(0xc1, interrupt_113_asm_entry);
register_interrupt_handler(0xc2, interrupt_114_asm_entry);
register_interrupt_handler(0xc3, interrupt_115_asm_entry);
register_interrupt_handler(0xc4, interrupt_116_asm_entry);
register_interrupt_handler(0xc5, interrupt_117_asm_entry);
register_interrupt_handler(0xc6, interrupt_118_asm_entry);
register_interrupt_handler(0xc7, interrupt_119_asm_entry);
register_interrupt_handler(0xc8, interrupt_120_asm_entry);
register_interrupt_handler(0xc9, interrupt_121_asm_entry);
register_interrupt_handler(0xca, interrupt_122_asm_entry);
register_interrupt_handler(0xcb, interrupt_123_asm_entry);
register_interrupt_handler(0xcc, interrupt_124_asm_entry);
register_interrupt_handler(0xcd, interrupt_125_asm_entry);
register_interrupt_handler(0xce, interrupt_126_asm_entry);
register_interrupt_handler(0xcf, interrupt_127_asm_entry);
for (u8 i = 0; i < 16; ++i) {
s_irq_handler[i] = nullptr;
for (u8 i = 0; i < GENERIC_INTERRUPT_HANDLERS_COUNT; ++i) {
new UnhandledInterruptHandler(i);
}
flush_idt();
@ -547,15 +663,20 @@ void load_task_register(u16 selector)
u32 g_in_irq;
void handle_irq(RegisterState regs)
void handle_interrupt(RegisterState regs)
{
clac();
++g_in_irq;
ASSERT(regs.isr_number >= 0x50 && regs.isr_number <= 0x5f);
u8 irq = (u8)(regs.isr_number - 0x50);
if (s_irq_handler[irq])
s_irq_handler[irq]->handle_irq();
PIC::eoi(irq);
if (s_interrupt_handler[irq]) {
s_interrupt_handler[irq]->handle_interrupt(regs);
s_interrupt_handler[irq]->increment_invoking_counter();
s_interrupt_handler[irq]->eoi();
} else {
dbgprintf("No IRQ %d Handler installed!\n", irq);
hang();
}
--g_in_irq;
}