diff --git a/include/jinue/shared/asm/i686.h b/include/jinue/shared/asm/i686.h index 0de55296..81c07044 100644 --- a/include/jinue/shared/asm/i686.h +++ b/include/jinue/shared/asm/i686.h @@ -57,7 +57,7 @@ #define JINUE_KLIMIT 0xc0000000 /** interrupt vector for system call software interrupt */ -#define JINUE_I686_SYSCALL_IRQ 0x80 +#define JINUE_I686_SYSCALL_INTERRUPT 0x80 /** slow/safe interrupt-based system call implementation */ #define JINUE_I686_HOWSYSCALL_INTERRUPT 0 diff --git a/include/kernel/application/asm/ticks.h b/include/kernel/application/asm/ticks.h new file mode 100644 index 00000000..04bcbaa2 --- /dev/null +++ b/include/kernel/application/asm/ticks.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JINUE_KERNEL_APPLICATION_ASM_TICKS_H +#define JINUE_KERNEL_APPLICATION_ASM_TICKS_H + +#define TICKS_PER_SECOND 100 + +#endif diff --git a/include/kernel/application/interrupts.h b/include/kernel/application/interrupts.h new file mode 100644 index 00000000..55135757 --- /dev/null +++ b/include/kernel/application/interrupts.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JINUE_KERNEL_APPLICATION_INTERRUPTS_H +#define JINUE_KERNEL_APPLICATION_INTERRUPTS_H + +void hardware_interrupt(int irq); + +void spurious_interrupt(void); + +void tick_interrupt(void); + +#endif diff --git a/include/kernel/infrastructure/i686/asm/eflags.h b/include/kernel/infrastructure/i686/asm/eflags.h index fbfb5301..3b55beba 100644 --- a/include/kernel/infrastructure/i686/asm/eflags.h +++ b/include/kernel/infrastructure/i686/asm/eflags.h @@ -34,6 +34,8 @@ #define EFLAGS_ALWAYS_1 (1<<1) +#define EFLAGS_IF (1<<9) + #define EFLAGS_ID (1<<21) #endif diff --git a/include/kernel/infrastructure/i686/drivers/asm/pic8259.h b/include/kernel/infrastructure/i686/drivers/asm/pic8259.h index a83488e2..23581b56 100644 --- a/include/kernel/infrastructure/i686/drivers/asm/pic8259.h +++ b/include/kernel/infrastructure/i686/drivers/asm/pic8259.h @@ -59,10 +59,25 @@ /** ICW4 bit 0: 8086/8088 mode (1) or MCS-80/85 mode (0) */ #define PIC8259_ICW4_UPM (1<<0) -/** ICW4 bit 1: Auto EOI*/ +/** ICW4 bit 1: Auto EOI */ #define PIC8259_ICW4_AEOI (1<<1) +/** ICW4 bit 4: special (1) or "regular" (0) fully nested mode */ +#define PIC8259_ICW4_SFNM (1<<4) + /** OCW2: non-specific EOI command */ -#define PIC8259_EOI 0x20 +#define PIC8259_OCW2_EOI 0x20 + +/** OCW3: read ISR (1) or IRR (0) when RR is also set */ +#define PIC8259_OCW3_RIS (1<<0) + +/** OCW3: read register command when set */ +#define PIC8259_OCW3_RR (1<<1) + +/** OCW3: always 1 to select OCW3, otherwise it's OCW2 */ +#define PIC8259_OCW3_1 (1<<3) + +/** OCW3: read Interrupt Service Register (ISR) */ +#define PIC8259_OCW3_READ_ISR (PIC8259_OCW3_1 | PIC8259_OCW3_RR | PIC8259_OCW3_RIS) #endif diff --git a/include/kernel/infrastructure/i686/drivers/asm/pit8253.h b/include/kernel/infrastructure/i686/drivers/asm/pit8253.h new file mode 100644 index 00000000..0e41b2e5 --- /dev/null +++ b/include/kernel/infrastructure/i686/drivers/asm/pit8253.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ASM_PIT8253_H +#define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_ASM_PIT8253_H + +/* I/O addresses */ + +#define PIT8253_IO_BASE 0x40 + +#define PIT8253_IO_COUNTER0 (PIT8253_IO_BASE + 0) + +#define PIT8253_IO_COUNTER1 (PIT8253_IO_BASE + 1) + +#define PIT8253_IO_COUNTER2 (PIT8253_IO_BASE + 2) + +#define PIT8253_IO_CW_REG (PIT8253_IO_BASE + 3) + +/* Individual flag definitions */ + +/** BCD (1) or binary (0) counter selection */ +#define PIT8253_CW_BCD (1<<0) + +#define PIT8253_CW_M0 (1<<1) + +#define PIT8253_CW_M1 (1<<2) + +#define PIT8253_CW_M2 (1<<3) + +#define PIT8253_CW_RL0 (1<<4) + +#define PIT8253_CW_RL1 (1<<5) + +#define PIT8253_CW_SC0 (1<<6) + +#define PIT8253_CW_SC1 (1<<7) + +/* Combined flags - select counter */ + +#define PIT8253_CW_COUNTER0 0 + +#define PIT8253_CW_COUNTER1 PIT8253_CW_SC0 + +#define PIT8253_CW_COUNTER2 PIT8253_CW_SC1 + +/* Combined flags - read/load */ + +#define PIT8253_CW_LOAD_LSB_MSB (PIT8253_CW_RL1 | PIT8253_CW_RL0) + +/* Combined flags - mode */ + +/** Mode 0: interrupt on terminal count */ +#define PIT8253_CW_MODE0 0 + +/** Mode 1: programmable one-shot */ +#define PIT8253_CW_MODE1 PIT8253_CW_M0 + +/** Mode 2: rate generator */ +#define PIT8253_CW_MODE2 PIT8253_CW_M1 + +/** Mode 3: square wave rate generator */ +#define PIT8253_CW_MODE3 (PIT8253_CW_M1 | PIT8253_CW_M0) + +/** Mode 4: software-triggered strobe */ +#define PIT8253_CW_MODE4 PIT8253_CW_M2 + +/** Mode 5: hardware-triggered strobe */ +#define PIT8253_CW_MODE5 (PIT8253_CW_M2 | PIT8253_CW_M0) + +/* Frequency parameters */ + +/** Numerator of input frequency in MHz */ +#define PIT8253_FREQ_N 105 + +/** Denominator of input frequency in MHz */ +#define PIT8253_FREQ_D 88 + +#endif diff --git a/include/kernel/infrastructure/i686/iodelay.h b/include/kernel/infrastructure/i686/drivers/iodelay.h similarity index 93% rename from include/kernel/infrastructure/i686/iodelay.h rename to include/kernel/infrastructure/i686/drivers/iodelay.h index fb4a9fee..76c74f3e 100644 --- a/include/kernel/infrastructure/i686/iodelay.h +++ b/include/kernel/infrastructure/i686/drivers/iodelay.h @@ -29,8 +29,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_IODELAY_H -#define JINUE_KERNEL_INFRASTRUCTURE_I686_IODELAY_H +#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_IODELAY_H +#define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_IODELAY_H void iodelay(void); diff --git a/include/kernel/infrastructure/i686/drivers/pic8259.h b/include/kernel/infrastructure/i686/drivers/pic8259.h index 06e61ce3..ac643630 100644 --- a/include/kernel/infrastructure/i686/drivers/pic8259.h +++ b/include/kernel/infrastructure/i686/drivers/pic8259.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Philippe Aubertin. + * Copyright (C) 2019-2024 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ #define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_PIC8259_H #include +#include void pic8259_init(); @@ -40,6 +41,8 @@ void pic8259_mask(int irq); void pic8259_unmask(int irq); -void pic8259_ack(int irq); +void pic8259_eoi(int irq); + +bool pic8259_is_spurious(int irq); #endif diff --git a/include/kernel/infrastructure/i686/drivers/pit8253.h b/include/kernel/infrastructure/i686/drivers/pit8253.h new file mode 100644 index 00000000..9ef186a6 --- /dev/null +++ b/include/kernel/infrastructure/i686/drivers/pit8253.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_PIT8253_H +#define JINUE_KERNEL_INFRASTRUCTURE_I686_DRIVERS_PIT8253_H + +#include + +void pit8253_init(void); + +#endif diff --git a/include/kernel/interface/i686/asm/exceptions.h b/include/kernel/interface/i686/asm/exceptions.h new file mode 100755 index 00000000..90d36859 --- /dev/null +++ b/include/kernel/interface/i686/asm/exceptions.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2019-2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JINUE_KERNEL_INTERFACE_I686_ASM_EXCEPTIONS_H +#define JINUE_KERNEL_INTERFACE_I686_ASM_EXCEPTIONS_H + +/** Divide Error */ +#define EXCEPTION_DIV_ZERO 0 + +/** NMI Interrupt */ +#define EXCEPTION_NMI 2 + +/** Breakpoint */ +#define EXCEPTION_BREAK 3 + +/** Overflow */ +#define EXCEPTION_OVERFLOW 4 + +/** BOUND Range Exceeded */ +#define EXCEPTION_BOUND 5 + +/** Invalid Opcode (Undefined Opcode) */ +#define EXCEPTION_INVALID_OP 6 + +/** Device Not Available (No Math Coprocessor) */ +#define EXCEPTION_NO_COPROC 7 + +/** Double Fault */ +#define EXCEPTION_DOUBLE_FAULT 8 + +/** Invalid TSS */ +#define EXCEPTION_INVALID_TSS 10 + +/** Segment Not Present */ +#define EXCEPTION_SEGMENT_NOT_PRESENT 11 + +/** Stack-Segment Fault */ +#define EXCEPTION_STACK_SEGMENT 12 + +/** General Protection */ +#define EXCEPTION_GENERAL_PROTECTION 13 + +/** Page Fault */ +#define EXCEPTION_PAGE_FAULT 14 + +/** x87 FPU Floating-Point Error (Math Fault) */ +#define EXCEPTION_MATH 16 + +/** Alignment Check */ +#define EXCEPTION_ALIGNMENT 17 + +/** Machine Check */ +#define EXCEPTION_MACHINE_CHECK 18 + +/** SIMD Floating-Point Exception */ +#define EXCEPTION_SIMD 19 + +#define EXCEPTION_HAS_ERRCODE(x) \ + (\ + (x) == EXCEPTION_DOUBLE_FAULT \ + || (x) == EXCEPTION_ALIGNMENT \ + || (x) >= EXCEPTION_INVALID_TSS && (x) <= EXCEPTION_PAGE_FAULT \ + ) + +#endif diff --git a/include/kernel/interface/i686/asm/idt.h b/include/kernel/interface/i686/asm/idt.h new file mode 100755 index 00000000..33bfe85e --- /dev/null +++ b/include/kernel/interface/i686/asm/idt.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019-2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JINUE_KERNEL_INTERFACE_I686_ASM_IDT_H +#define JINUE_KERNEL_INTERFACE_I686_ASM_IDT_H + +#define IDT_VECTOR_COUNT 256 + +#define IDT_LAST_EXCEPTION 31 + +#define IDT_PIC8259_BASE (IDT_LAST_EXCEPTION + 1) + +#endif diff --git a/include/kernel/interface/i686/asm/irq.h b/include/kernel/interface/i686/asm/irq.h index 9fde2ae2..e2285ab6 100755 --- a/include/kernel/interface/i686/asm/irq.h +++ b/include/kernel/interface/i686/asm/irq.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Philippe Aubertin. + * Copyright (C) 2024 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -32,65 +32,12 @@ #ifndef JINUE_KERNEL_INTERFACE_I686_ASM_IRQ_H #define JINUE_KERNEL_INTERFACE_I686_ASM_IRQ_H -#define IDT_VECTOR_COUNT 256 +#define IRQ_TIMER 0 -#define IDT_LAST_EXCEPTION 31 +#define IRQ_SPURIOUS 7 -#define IDT_PIC8259_BASE (IDT_LAST_EXCEPTION + 1) - -/** Divide Error */ -#define EXCEPTION_DIV_ZERO 0 - -/** NMI Interrupt */ -#define EXCEPTION_NMI 2 - -/** Breakpoint */ -#define EXCEPTION_BREAK 3 - -/** Overflow */ -#define EXCEPTION_OVERFLOW 4 - -/** BOUND Range Exceeded */ -#define EXCEPTION_BOUND 5 - -/** Invalid Opcode (Undefined Opcode) */ -#define EXCEPTION_INVALID_OP 6 - -/** Device Not Available (No Math Coprocessor) */ -#define EXCEPTION_NO_COPROC 7 - -/** Double Fault */ -#define EXCEPTION_DOUBLE_FAULT 8 - -/** Invalid TSS */ -#define EXCEPTION_INVALID_TSS 10 - -/** Segment Not Present */ -#define EXCEPTION_SEGMENT_NOT_PRESENT 11 - -/** Stack-Segment Fault */ -#define EXCEPTION_STACK_SEGMENT 12 - -/** General Protection */ -#define EXCEPTION_GENERAL_PROTECTION 13 - -/** Page Fault */ -#define EXCEPTION_PAGE_FAULT 14 - -/** x87 FPU Floating-Point Error (Math Fault) */ -#define EXCEPTION_MATH 16 - -/** Alignment Check */ -#define EXCEPTION_ALIGNMENT 17 - -/** Machine Check */ -#define EXCEPTION_MACHINE_CHECK 18 - -/** SIMD Floating-Point Exception */ -#define EXCEPTION_SIMD 19 - -#define HAS_ERRCODE(x) ((x) == EXCEPTION_DOUBLE_FAULT || (x) == EXCEPTION_ALIGNMENT || ((x) >= EXCEPTION_INVALID_TSS && (x) <= EXCEPTION_PAGE_FAULT)) +#define IRQ_PROXIED_FIRST 8 +#define IRQ_PROXIED_SPURIOUS 15 #endif - diff --git a/include/kernel/utils/asm/utils.h b/include/kernel/utils/asm/utils.h index e0bfc2dc..1261285a 100644 --- a/include/kernel/utils/asm/utils.h +++ b/include/kernel/utils/asm/utils.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Philippe Aubertin. + * Copyright (C) 2019-2024 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -32,10 +32,16 @@ #ifndef JINUE_KERNEL_UTILS_ASM_UTILS_H #define JINUE_KERNEL_UTILS_ASM_UTILS_H -#define KB (1024) +#define KB (1024) -#define MB (1024 * KB) +#define MB (1024 * KB) -#define GB (1024 * MB) +#define GB (1024 * MB) + +#define ROUND_DIVIDE(n, d) (((n) + (d)/2) / (d)) + +#define ALIGN_START(x, s) ( (x) & ~((s)-1) ) + +#define ALIGN_END(x, s) ( ALIGN_START((x) + s - 1, (s)) ) #endif diff --git a/include/kernel/utils/utils.h b/include/kernel/utils/utils.h index b7b07455..361c2cb4 100644 --- a/include/kernel/utils/utils.h +++ b/include/kernel/utils/utils.h @@ -32,14 +32,11 @@ #ifndef JINUE_KERNEL_UTILS_UTILS_H #define JINUE_KERNEL_UTILS_UTILS_H +#include #include #define OFFSET_OF(type, member) ((uintptr_t)(&((type *)0)->member)) -#define ALIGN_START(x, s) ( (x) & ~((s)-1) ) - -#define ALIGN_END(x, s) ( ALIGN_START((x) + s - 1, (s)) ) - #define OFFSET_OF_PTR(x, s) ( (uintptr_t)(x) & ((s)-1) ) #define ALIGN_START_PTR(x, s) ( (void *)ALIGN_START((uintptr_t)(x), (s)) ) diff --git a/kernel/Makefile b/kernel/Makefile index f3201d36..28f083fd 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -60,6 +60,9 @@ unclean.extra = \ $(stripped) sources.kernel.c = \ + application/interrupts/hardware.c \ + application/interrupts/spurious.c \ + application/interrupts/tick.c \ application/syscalls/close.c \ application/syscalls/create_endpoint.c \ application/syscalls/create_process.c \ @@ -98,6 +101,7 @@ sources.kernel.c = \ domain/config.c \ infrastructure/i686/drivers/vga.c \ infrastructure/i686/drivers/pic8259.c \ + infrastructure/i686/drivers/pit8253.c \ infrastructure/i686/drivers/uart16550a.c \ infrastructure/i686/pmap/nopae.c \ infrastructure/i686/pmap/pmap.c \ @@ -122,12 +126,12 @@ sources.kernel.c = \ sources.kernel.nasm = \ infrastructure/i686/atomic/atomic.asm \ infrastructure/i686/atomic/spinlock.asm \ + infrastructure/i686/drivers/iodelay.asm \ infrastructure/i686/isa/abi.asm \ infrastructure/i686/isa/instrs.asm \ infrastructure/i686/isa/io.asm \ infrastructure/i686/isa/regs.asm \ infrastructure/i686/pmap/init.asm \ - infrastructure/i686/iodelay.asm \ infrastructure/i686/thread.asm \ interface/i686/crt.asm \ interface/i686/trap.asm diff --git a/kernel/application/interrupts/hardware.c b/kernel/application/interrupts/hardware.c new file mode 100644 index 00000000..90e268e7 --- /dev/null +++ b/kernel/application/interrupts/hardware.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void hardware_interrupt(int irq) { + /* TODO implement something here */ +} diff --git a/kernel/application/interrupts/spurious.c b/kernel/application/interrupts/spurious.c new file mode 100644 index 00000000..09a3530e --- /dev/null +++ b/kernel/application/interrupts/spurious.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void spurious_interrupt(void) { + /* TODO implement something here */ +} diff --git a/kernel/application/interrupts/tick.c b/kernel/application/interrupts/tick.c new file mode 100644 index 00000000..80842499 --- /dev/null +++ b/kernel/application/interrupts/tick.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void tick_interrupt(void) { + /* TODO implement something here */ +} diff --git a/kernel/infrastructure/i686/iodelay.asm b/kernel/infrastructure/i686/drivers/iodelay.asm similarity index 100% rename from kernel/infrastructure/i686/iodelay.asm rename to kernel/infrastructure/i686/drivers/iodelay.asm diff --git a/kernel/infrastructure/i686/drivers/pic8259.c b/kernel/infrastructure/i686/drivers/pic8259.c index fba594ea..730c0256 100644 --- a/kernel/infrastructure/i686/drivers/pic8259.c +++ b/kernel/infrastructure/i686/drivers/pic8259.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 Philippe Aubertin. + * Copyright (C) 2019-2024 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -30,8 +30,9 @@ */ #include +#include #include -#include +#include #include #include @@ -52,7 +53,7 @@ static pic8259_t main_pic8259 = { static pic8259_t proxied_pic8259 = { .is_proxied = true, .io_base = PIC8259_PROXIED_IO_BASE, - .irq_base = IDT_PIC8259_BASE + 8, + .irq_base = IDT_PIC8259_BASE + IRQ_PROXIED_FIRST, .mask = 0xff }; @@ -80,19 +81,35 @@ static void initialize(const pic8259_t *pic8259) { iodelay(); /* ICW4: Use 8088/8086 mode */ - outb(pic8259->io_base + 1, PIC8259_ICW4_UPM); + value = PIC8259_ICW4_UPM; + + if(!pic8259->is_proxied) { + /* special fully nested mode for main */ + value |= PIC8259_ICW4_SFNM; + } + + outb(pic8259->io_base + 1, value); iodelay(); /* Set interrupt mask */ outb(pic8259->io_base + 1, pic8259->mask); iodelay(); + + /* We are only ever going to read the ISR, never the IRR, so let's + * enable this once here and not have to do it for each read. */ + outb(pic8259->io_base + 0, PIC8259_OCW3_READ_ISR); + iodelay(); } -static void ack_eoi(pic8259_t *pic8259) { - outb(pic8259->io_base + 0, PIC8259_EOI); +static void eoi(pic8259_t *pic8259) { + outb(pic8259->io_base + 0, PIC8259_OCW2_EOI); iodelay(); } +static uint8_t read_isr(pic8259_t *pic8259) { + return inb(pic8259->io_base + 0); +} + void pic8259_init() { initialize(&main_pic8259); initialize(&proxied_pic8259); @@ -111,30 +128,83 @@ static void unmask_irqs(pic8259_t *pic8259, int mask) { } void pic8259_mask(int irq) { - if(irq < 8) { - if(irq != PIC8259_CASCADE_INPUT) { - mask_irqs(&main_pic8259, 1 << irq); - } + if(irq == PIC8259_CASCADE_INPUT) { + return; } - else { - mask_irqs(&proxied_pic8259, 1 << (irq - 8)); + + pic8259_t *pic = &main_pic8259; + + if(irq >= IRQ_PROXIED_FIRST) { + irq -= IRQ_PROXIED_FIRST; + pic = &proxied_pic8259; } + + mask_irqs(pic, 1 << irq); } void pic8259_unmask(int irq) { - if(irq < 8) { - unmask_irqs(&main_pic8259, 1 << irq); + pic8259_t *pic = &main_pic8259; + + if(irq >= IRQ_PROXIED_FIRST) { + irq -= IRQ_PROXIED_FIRST; + pic = &proxied_pic8259; } - else { - unmask_irqs(&proxied_pic8259, 1 << (irq - 8)); + + unmask_irqs(pic, 1 << irq); +} + +void pic8259_eoi(int irq) { + if(irq >= IRQ_PROXIED_FIRST) { + eoi(&proxied_pic8259); + iodelay(); + + /* Special fully nested mode: do not send EIO to main controller if + * interrupts are still being serviced on the proxied one. */ + uint8_t isr = read_isr(&proxied_pic8259); + + if(isr != 0) { + return; + } } + + eoi(&main_pic8259); } -void pic8259_ack(int irq) { - if(irq >= 8) { - ack_eoi(&proxied_pic8259); +bool pic8259_is_spurious(int irq) { + if(irq != IRQ_SPURIOUS && irq != IRQ_PROXIED_SPURIOUS) { + return false; + } + + const uint8_t mask = (1 << IRQ_SPURIOUS); + + if(irq == IRQ_SPURIOUS) { + /* If we got interrupted for IRQ 7 but IRQ 7 isn't actually being + * serviced by the main PIC, then this is a spurious interrupt. + * + * Don't send a EOI either way: + * - In the case of a spurious interrupt, no IRQ 7 is in service, so no + * EOI should be sent. + * - In the case of an actual interrupt, the handler will handle it as + * any other hardware interrupt and will call pic8259_eoi() later. */ + uint8_t isr = read_isr(&main_pic8259); + return (isr & mask) == 0; + } + + uint8_t isr = read_isr(&proxied_pic8259); + + if((isr & mask) != 0) { + return false; + } + + /* Spurious interrupt on the proxied PIC: we must not send a EOI to the + * proxied PIC, but we must send it to the main PIC that got interrupted + * by the proxied PIC. + * + * This is true unless another interrupt is in service on the proxied PIC + * (special fully nested mode). */ + if(isr == 0) { + eoi(&main_pic8259); } - ack_eoi(&main_pic8259); - pic8259_unmask(irq); + return true; } diff --git a/kernel/infrastructure/i686/drivers/pit8253.c b/kernel/infrastructure/i686/drivers/pit8253.c new file mode 100644 index 00000000..22d8eae4 --- /dev/null +++ b/kernel/infrastructure/i686/drivers/pit8253.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 Philippe Aubertin. + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +void pit8253_init(void) { + outb(PIT8253_IO_CW_REG, PIT8253_CW_COUNTER0 | PIT8253_CW_MODE2 | PIT8253_CW_LOAD_LSB_MSB); + iodelay(); + + int divider = ROUND_DIVIDE(PIT8253_FREQ_N * 1000000, PIT8253_FREQ_D * TICKS_PER_SECOND); + outb(PIT8253_IO_COUNTER0, divider & 0xff); + iodelay(); + + outb(PIT8253_IO_COUNTER0, divider >> 8); + iodelay(); +} diff --git a/kernel/infrastructure/i686/init.c b/kernel/infrastructure/i686/init.c index c648e5a3..f445a668 100644 --- a/kernel/infrastructure/i686/init.c +++ b/kernel/infrastructure/i686/init.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Philippe Aubertin. + * Copyright (C) 2019-2024 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -129,10 +131,19 @@ static void init_idt(void) { /* get address, which is already stored in the IDT entry */ addr_t addr = (addr_t)(uintptr_t)idt[idx]; - /* set interrupt gate flags */ + /* Set interrupt gate flags. + * + * Because we are using an interrupt gate, the IF flag is cleared when + * the interrupt routine is entered, which means interrupts are + * disabled. + * + * See Intel 64 and IA-32 Architectures Software Developer’s Manual + * Volume 3 section 7.12.1.3 "Flag Usage By Exception- or Interrupt- + * Handler Procedure". + */ unsigned int flags = SEG_TYPE_INTERRUPT_GATE | SEG_FLAG_NORMAL_GATE; - if(idx == JINUE_I686_SYSCALL_IRQ) { + if(idx == JINUE_I686_SYSCALL_INTERRUPT) { flags |= SEG_FLAG_USER; } else { @@ -216,8 +227,7 @@ static void initialize_page_allocator(boot_alloc_t *boot_alloc) { page_free(boot_page_alloc(boot_alloc)); } - info( - "%u kilobytes available for allocation by the kernel", + info( "%u kilobytes available for allocation by the kernel", get_page_count() * PAGE_SIZE / (1 * KB)); } @@ -356,6 +366,13 @@ void machine_init(const config_t *config) { /* Initialize programmable interrupt_controller. */ pic8259_init(); + /* Initialize programmable interval timer and enable timer interrupt. + * + * Interrupts are disabled during initialization so the CPU won't actually + * be interrupted until the first user space thread starts. */ + pit8253_init(); + pic8259_unmask(IRQ_TIMER); + exec_file_t kernel; get_kernel_exec_file(&kernel, bootinfo); diff --git a/kernel/infrastructure/i686/thread.c b/kernel/infrastructure/i686/thread.c index de4d7dca..7fb64a4c 100644 --- a/kernel/infrastructure/i686/thread.c +++ b/kernel/infrastructure/i686/thread.c @@ -109,7 +109,7 @@ void machine_prepare_thread(thread_t *thread, const thread_params_t *params) { trapframe->eip = (uint32_t)params->entry; trapframe->esp = (uint32_t)params->stack_addr; - trapframe->eflags = EFLAGS_ALWAYS_1; + trapframe->eflags = EFLAGS_ALWAYS_1 | EFLAGS_IF; trapframe->cs = SEG_SELECTOR(GDT_USER_CODE, RPL_USER); trapframe->ss = SEG_SELECTOR(GDT_USER_DATA, RPL_USER); trapframe->ds = SEG_SELECTOR(GDT_USER_DATA, RPL_USER); diff --git a/kernel/interface/i686/interrupts.c b/kernel/interface/i686/interrupts.c index 70a9642f..e741c85d 100644 --- a/kernel/interface/i686/interrupts.c +++ b/kernel/interface/i686/interrupts.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Philippe Aubertin. + * Copyright (C) 2019-2024 Philippe Aubertin. * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -29,46 +29,67 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include #include -#include #include +#include +#include #include #include #include -#include #include -void handle_interrupt(trapframe_t *trapframe) { - unsigned int ivt = trapframe->ivt; - uintptr_t eip = trapframe->eip; - uint32_t errcode = trapframe->errcode; - - /* exceptions */ - if(ivt <= IDT_LAST_EXCEPTION) { - info( - "EXCEPT: %u cr2=%#" PRIx32 " errcode=%#" PRIx32 " eip=%#" PRIxPTR, - ivt, - get_cr2(), - errcode, - eip); - - /* never returns */ - panic("caught exception"); - } +static void handle_exception(unsigned int ivt, uintptr_t eip, uint32_t errcode) { + info( "EXCEPT: %u cr2=%#" PRIx32 " errcode=%#" PRIx32 " eip=%#" PRIxPTR, + ivt, + get_cr2(), + errcode, + eip); - if(ivt == JINUE_I686_SYSCALL_IRQ) { - /* interrupt-based system call implementation */ - handle_syscall((jinue_syscall_args_t *)&trapframe->msg_arg0); + panic("caught exception"); +} + +static void handle_hardware_interrupt(unsigned int ivt) { + int irq = ivt - IDT_PIC8259_BASE; + + if(pic8259_is_spurious(irq)) { + spurious_interrupt(); + return; } - else if(ivt >= IDT_PIC8259_BASE && ivt < IDT_PIC8259_BASE + PIC8259_IRQ_COUNT) { - int irq = ivt - IDT_PIC8259_BASE; - info("IRQ: %i (vector %u)", irq, ivt); - pic8259_ack(irq); + + /* For all hardware interrupts except the timer, we mask the interrupt and + * let the driver handling it unmask it when it's done. This prevents us + * from being repeatedly interrupted by level-triggered interrupts in the + * meantime. We never mask the timer interrupt. */ + if(irq == IRQ_TIMER) { + tick_interrupt(); + } else { + pic8259_mask(irq); } - else { - info("INTR: vector %u", ivt); + + hardware_interrupt(irq); + pic8259_eoi(irq); +} + +static void handle_unexpected_interrupt(unsigned int ivt) { + info("INTR: vector %u", ivt); +} + +void handle_interrupt(trapframe_t *trapframe) { + unsigned int ivt = trapframe->ivt; + + if(ivt == JINUE_I686_SYSCALL_INTERRUPT) { + jinue_syscall_args_t *args = (jinue_syscall_args_t *)&trapframe->msg_arg0; + handle_syscall(args); + } else if(ivt <= IDT_LAST_EXCEPTION) { + handle_exception(ivt, trapframe->eip, trapframe->errcode); + } else if(ivt >= IDT_PIC8259_BASE && ivt < IDT_PIC8259_BASE + PIC8259_IRQ_COUNT) { + handle_hardware_interrupt(ivt); + } else { + handle_unexpected_interrupt(ivt); } } diff --git a/kernel/interface/i686/trap.asm b/kernel/interface/i686/trap.asm index a14ec632..9d1c8b2a 100644 --- a/kernel/interface/i686/trap.asm +++ b/kernel/interface/i686/trap.asm @@ -30,7 +30,8 @@ #include #include #include -#include +#include +#include #include bits 32 @@ -241,6 +242,13 @@ fast_intel_entry: pop ecx ; 64 user stack pointer ; no action needed ; 68 skip user stack segment + ; When we saved EFLAGS, IF was already cleared, so we need to explicitly + ; re-enable interrupts. + ; + ; The sti instruction takes effect after the *next* instruction, so after + ; sysexit here, which is what we want. For this reason, it must be the last + ; instruction before sysexit. + sti sysexit .end: @@ -332,6 +340,13 @@ fast_amd_entry: pop esp ; 64 user stack pointer ; no action needed ; 68 skip user stack segment + ; When we saved EFLAGS, IF was already cleared, so we need to explicitly + ; re-enable interrupts. + ; + ; The sti instruction takes effect after the *next* instruction, so after + ; sysret here, which is what we want. For this reason, it must be the last + ; instruction before sysret. + sti sysret .end: @@ -376,7 +391,7 @@ trampoline: ; Push a null DWORD in lieu of the error code for interrupts ; that do not have one (only some CPU exceptions have an error ; code). We do this to maintain a consistent stack frame layout. - %if ! HAS_ERRCODE(ivt) + %if ! EXCEPTION_HAS_ERRCODE(ivt) push byte NULL_ERRCODE %endif diff --git a/userspace/lib/jinue/i686/stubs.asm b/userspace/lib/jinue/i686/stubs.asm index c28d2945..85f8004d 100644 --- a/userspace/lib/jinue/i686/stubs.asm +++ b/userspace/lib/jinue/i686/stubs.asm @@ -180,7 +180,7 @@ jinue_syscall_intr: mov esi, [edi+ 8] ; arg2 (message pointer) mov edi, [edi+12] ; arg3 (message size) - int JINUE_I686_SYSCALL_IRQ + int JINUE_I686_SYSCALL_INTERRUPT ; restore arguments structure pointer mov ebp, [esp+20]