CeDOS - Commit f4f6f7b3

Fixed INT 20h issue Turns out I forgot the 0x prefix of the number of IDT entries... So there were 31 entries, which does not include INT 20h. Now there are 0x31 entries, like there should be.
Celina Sophie Kalus
Mon, 08 Jan 2018 16:53:42 +0100
10 files changed, 110 insertions(+), 26 deletions(-)
M include/assembly.hinclude/assembly.h

@@ -48,6 +48,34 @@ __asm__ volatile ("sti");

} /*! + * Pushes the contents of the EFLAGS register onto the stack. + */ +__attribute__((always_inline)) inline void pushf(void) { + __asm__ volatile ("pushf"); +} + +/*! + * Pops the contents of the EFLAGS register from the top of the stack. + */ +__attribute__((always_inline)) inline void popf(void) { + __asm__ volatile ("popf"); +} + +/*! + * Pushes the contents of the general purpose registers onto the stack. + */ +__attribute__((always_inline)) inline void pusha(void) { + __asm__ volatile ("pusha"); +} + +/*! + * Pops the contents of the general purpose registers off the top of the stack. + */ +__attribute__((always_inline)) inline void popa(void) { + __asm__ volatile ("popa"); +} + +/*! * CPUID */ __attribute__((always_inline)) inline void cpuid(uint32_t eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
M include/cedos/interrupts.hinclude/cedos/interrupts.h

@@ -7,8 +7,14 @@ #define OS_INTERRUPTS_H

#include <stdint.h> -#define INTERRUPT(name, frame) __attribute__((interrupt)) void name(INTERRUPT_FRAME *frame) -#define EXCEPTION(name, frame, err_code) __attribute__((interrupt)) void name(INTERRUPT_FRAME *frame, uword_t err_code) +#define INTERRUPT(name, frame) __attribute__((interrupt, optimize("O0"))) void name(INTERRUPT_FRAME *frame) +#define EXCEPTION(name, frame, err_code) __attribute__((interrupt, optimize("O0"))) void name(INTERRUPT_FRAME *frame, uword_t err_code) + +#define INT_GATE (0b10001110) +#define TRAP_GATE (0b10001111) +#define SYSCALL_INTERRUPT (0b11101110) + +#define INTERRUPT_COUNT 0x31 /*! * Represents a single entry of the IDT.

@@ -30,5 +36,6 @@

typedef uint32_t uword_t; int interrupts_init(void); +void install_interrupt(int num, void* func, uint16_t selector, uint8_t type); #endif
M include/cedos/pic.hinclude/cedos/pic.h

@@ -39,11 +39,11 @@

/*! * Sends an end-of-interrupt-signal to the corresponding PIC. */ -inline void pic1_eoi(void) { +__attribute__((always_inline)) inline void pic1_eoi(void) { outb(PIC_END_OF_INTERRUPT, PIC1_COMMAND); } -inline void pic2_eoi(void) { +__attribute__((always_inline)) inline void pic2_eoi(void) { outb(PIC_END_OF_INTERRUPT, PIC2_COMMAND); outb(PIC_END_OF_INTERRUPT, PIC1_COMMAND); }
M include/cedos/pit.hinclude/cedos/pit.h

@@ -36,4 +36,6 @@ * \param freq_div Desired frequency divider.

*/ void pit_setup_channel(PIT_CHANNEL channel, PIT_MODE mode, uint16_t freq_div); +void pit_init(void); + #endif
M include/cedos/scheduler.hinclude/cedos/scheduler.h

@@ -19,4 +19,9 @@ * Initializes the scheduler.

*/ int sched_init(void); +/*! + * Starts the scheduler. + */ +int sched_start(void); + #endif
M kernel/interrupts.ckernel/interrupts.c

@@ -1,10 +1,8 @@

#include "cedos/interrupts.h" #include "cedos/drivers/console.h" #include "cedos/pic.h" - -#define INT_GATE (0b10001110) -#define TRAP_GATE (0b10001111) -#define SYSCALL_INTERRUPT (0b11101110) +#include "cedos/core.h" +#include "cedos/pit.h" #define array_sizeof(array) (sizeof(array)/sizeof(array[0]))

@@ -50,14 +48,15 @@ printk("PIC2 INTERRUPT\n");

pic2_eoi(); } -IDT_ENTRY IDT[31]; +IDT_ENTRY IDT[INTERRUPT_COUNT]; +void (*INT_HANDLERS[INTERRUPT_COUNT])(void); -void install_interrupt(int index, void* func, uint16_t selector, uint8_t type) { - IDT[index].offset_0 = (uint16_t)((uint32_t)func); - IDT[index].selector = selector; - IDT[index].__zero = 0; - IDT[index].type_attr = type; - IDT[index].offset_16 = (uint16_t)((uint32_t)(func) >> 16); +void install_interrupt(int num, void* func, uint16_t selector, uint8_t type) { + IDT[num].offset_0 = (uint16_t)((uint32_t)func); + IDT[num].selector = selector; + IDT[num].__zero = 0; + IDT[num].type_attr = type; + IDT[num].offset_16 = (uint16_t)((uint32_t)(func) >> 16); } struct {

@@ -69,7 +68,7 @@ IDT

}; int interrupts_init(void) { - for (uint32_t i = 0; i < array_sizeof(IDT); i++) { + for (uint32_t i = 0; i < INTERRUPT_COUNT; i++) { if (i == 0x03) { install_interrupt(i, breakpoint_isr, 0x08, INT_GATE); } else if (i == 0x08) {
M kernel/main.ckernel/main.c

@@ -1,6 +1,7 @@

#include "cedos/drivers/console.h" #include "cedos/interrupts.h" #include "cedos/pic.h" +#include "cedos/pit.h" #include "cedos/scheduler.h" #include "cedos/mm/paging.h" #include "cedos/core.h"

@@ -12,13 +13,17 @@ printk("Core functions initialized.\n");

printk("Initializing PIC..."); pic_init(); + printk("done.\n"); + + printk("Initializing PIT..."); + pit_init(); printk("done.\n"); printk("Initializing interrupts..."); interrupts_init(); printk("done.\n"); - printk("Activating interrupts..."); + printk("Setting up timer interrupts..."); sti(); printk("done.\n");

@@ -37,13 +42,19 @@ cpuid(0, &res[0], &res[2], &res[1]);

res[3] = 0; printk("CPU manufacturer: %s\n", res); } + +extern uint8_t* IDT; int os_main(void) { + //pic_unmask_interrupt(0); infodump(); - kpanic("SIMULATED KERNEL PANIC"); + printk("Starting scheduler."); + sched_start(); + + //kpanic("SIMULATED KERNEL PANIC"); // won't be executed - printk("Main procedure terminating.\n"); + //printk("Main procedure terminating.\n"); return 0; }
M kernel/pic.ckernel/pic.c

@@ -27,7 +27,7 @@ outb(0x01, PIC1_DATA);

outb(0x01, PIC2_DATA); nop(); nop(); nop(); nop(); - // clear interrupt masks + // mask all interrupts outb(0xff, PIC1_DATA); outb(0xff, PIC2_DATA);

@@ -42,7 +42,7 @@ */

int pic_unmask_interrupt(int irq) { uint16_t port; - if (irq >= 8) { + if (irq < 8) { port = PIC1_DATA; } else { port = PIC2_DATA;

@@ -64,7 +64,7 @@ */

int pic_mask_interrupt(int irq) { uint16_t port; - if (irq >= 8) { + if (irq < 8) { port = PIC1_DATA; } else { port = PIC2_DATA;
M kernel/pit.ckernel/pit.c

@@ -1,10 +1,12 @@

#include "cedos/pit.h" #include "assembly.h" +#include "cedos/pic.h" #define PIT_ACCESS_MODE_LO_HI (0b11 << 4) #define PIT_COMMAND_PORT ((uint16_t)0x43) void pit_setup_channel(PIT_CHANNEL channel, PIT_MODE mode, uint16_t freq_div) { + pushf(); cli(); outb(((uint8_t)channel << 6) | PIT_ACCESS_MODE_LO_HI | (uint8_t)mode, PIT_COMMAND_PORT); nop(); nop(); nop(); nop();

@@ -13,5 +15,10 @@ outb((uint8_t)(freq_div & 0xFF), 0x40 + (uint16_t)channel);

nop(); nop(); nop(); nop(); outb((uint8_t)(freq_div >> 8), 0x40 + (uint16_t)channel); - sti(); + popf(); +} + +void pit_init(void) { + pic_unmask_interrupt(0); + return 1; }
M kernel/scheduler.ckernel/scheduler.c

@@ -3,6 +3,11 @@ #include "cedos/process.h"

#include "cedos/mm/paging.h" #include "cedos/drivers/console.h" #include "cedos/core.h" +#include "cedos/interrupts.h" +#include "cedos/pit.h" +#include "cedos/pic.h" +#include "assembly.h" +#include "cedos/drivers/speaker.h" PROCESS* get_slot(void) { static PROCESS free_slots[4];

@@ -27,17 +32,37 @@

return add_process(p); } +INTERRUPT(sched_interrupt, frame) { + printk("--#"); + + // reset the timer + pit_setup_channel(PIT_CHANNEL_0, PIT_MODE_0, 0xFFFF); + + uint32_t big_ben[] = { 415, 330, 370, 247, 247, 370, 415, 330 }; + static int i = 0; + + bios_sp.make_sound(big_ben[(i / 8) % (sizeof(big_ben)/sizeof(big_ben[0]))], 1); + i++; + + pic1_eoi(); +} + int sched_init(void) { // TODO: create and start idle process //sched_exec(create_empty_page_dir(), (void*)0, (void*)0); + + // install timer interrupt + install_interrupt(0x20, sched_interrupt, 0x08, INT_GATE); + return 1; } -int sched_dispatcher(void) { - +int sched_start(void) { + // perform the first timer interrupt manually + INT(0x20); } -INTERRUPT(sched_interrupt, frame) { +int sched_dispatcher(void) { }