x86: prevent IRQs from firing during init

main
anna 3 years ago
parent 3fee893f21
commit d464135ff4
Signed by: fef
GPG Key ID: EC22E476DC2D3D84

@ -12,15 +12,16 @@
.extern irq_table
/* there is probably a fancy CPU feature for this, but idk */
_in_irq:
irq_count:
.byte 0
.text
/* bool in_irq(void); */
/* bool in_irq(void); */
ASM_ENTRY(in_irq)
xor %eax, %eax
movb _in_irq, %al
cmpb $0, irq_count
setne %al
ret
ASM_END(in_irq)
@ -29,7 +30,7 @@ ASM_ENTRY(_x86_isr_irq\num )
push %eax
push %ecx
push %edx
movb $1, _in_irq
incb irq_count
#if CFG_DEBUG_IRQ
pushl $\num
#endif
@ -37,12 +38,7 @@ ASM_ENTRY(_x86_isr_irq\num )
#if CFG_DEBUG_IRQ
add $4, %esp
#endif
movb $0x20, %al /* PIC End Of Interrupt command code */
.if \num >= 8
jmp leave_irq_pic2
.else
jmp leave_irq_pic1
.endif
jmp leave_irq
ASM_END(_x86_isr_irq\num )
.endm
@ -63,16 +59,16 @@ ASM_END(_x86_isr_irq\num )
gen_irq 14
gen_irq 15
leave_irq_pic2:
outb %al, $X86_PORT_PIC2_CMD /* send End Of Interrupt to PIC2 */
leave_irq_pic1:
outb %al, $X86_PORT_PIC1_CMD /* send End Of Interrupt to PIC1 */
movb $0, _in_irq
.align 4
leave_irq:
decb irq_count
pop %edx
pop %ecx
pop %eax
iret
.size leave_irq, . - leave_irq
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.

@ -39,6 +39,13 @@ void arch_irq_init(void)
x86_set_intr_gate(X86_VECT_IRQ(14), _x86_isr_irq14);
x86_set_intr_gate(X86_VECT_IRQ(15), _x86_isr_irq15);
/*
* disable interrupts to prevent IRQs from being fired
* immediately after the initialization sequence is complete
* (we need time to mask all IRQs again first)
*/
disable_intr();
/* begin initialization sequence in cascade mode */
x86_outb_wait(X86_PORT_PIC1_CMD, ICW1_INIT | ICW1_ICW4);
x86_outb_wait(X86_PORT_PIC2_CMD, ICW1_INIT | ICW1_ICW4);
@ -57,9 +64,15 @@ void arch_irq_init(void)
x86_outb_wait(X86_PORT_PIC1_DATA, ICW4_8086);
x86_outb_wait(X86_PORT_PIC2_DATA, ICW4_8086);
/* mask all IRQs */
/*
* The initialization sequence is finished now, meaning all IRQ masks
* have been cleared (they are all enabled). Disable them again.
*/
x86_outb_wait(X86_PORT_PIC1_DATA, 0xff);
x86_outb(X86_PORT_PIC2_DATA, 0xff);
x86_outb_wait(X86_PORT_PIC2_DATA, 0xff);
/* it's safe to turn interrupts back on now */
enable_intr();
}
void arch_irq_enable(unsigned int number)
@ -92,6 +105,13 @@ void arch_irq_disable(unsigned int number)
x86_outb(port, mask);
}
void x86_irq_ack(unsigned int number)
{
if (number >= 8)
x86_outb(X86_PORT_PIC2_CMD, 0x20);
x86_outb(X86_PORT_PIC1_CMD, 0x20);
}
/*
* This file is part of GayBSD.
* Copyright (c) 2021 fef <owo@fef.moe>.

Loading…
Cancel
Save