Initial commit

This commit is contained in:
2021-01-28 22:59:39 +01:00
commit d7f0e8dd36
30 changed files with 2092 additions and 0 deletions

23
kernel/cpu/idt.c Normal file
View File

@@ -0,0 +1,23 @@
//
// Created by rick on 8/18/19.
//
#include "idt.h"
idt_gate_t idt[IDT_REGISTERS];
idt_register_t idt_reg;
void set_idt_gate(int n, u32 handler) {
idt[n].low_offset = handler & 0xffff;
idt[n].sel = KERNEL_CS;
idt[n].always0 = 0;
idt[n].flags = 0x8E;
idt[n].high_offset = handler >> 16 & 0xFFFF;
}
void set_idt() {
idt_reg.base = (u32) &idt;
idt_reg.limit = IDT_REGISTERS * sizeof(idt_gate_t) - 1;
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
}

35
kernel/cpu/idt.h Normal file
View File

@@ -0,0 +1,35 @@
//
// Created by rick on 8/18/19.
//
#include "../types.h"
#ifndef MY_KERNEL_IDT_H
#define MY_KERNEL_IDT_H
#define KERNEL_CS 0x08
/* How every interrupt gate (handler) is defined */
typedef struct {
u16 low_offset; /* Lower 16 bits of handler function address */
u16 sel; /* Kernel segment selector */
u8 always0;
/* First byte
* Bit 7: "Interrupt is present"
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
* Bit 4: Set to 0 for interrupt gates
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
u8 flags;
u16 high_offset; /* Higher 16 bits of handler function address */
} __attribute__((packed)) idt_gate_t;
typedef struct {
u16 limit;
u32 base;
} __attribute__((packed)) idt_register_t;
#define IDT_REGISTERS 256
void set_idt_gate(int n, u32 handler);
void set_idt();
#endif //MY_KERNEL_IDT_H

426
kernel/cpu/interrupt.S Normal file
View File

@@ -0,0 +1,426 @@
.code32
# Defined in isr.c
#MISMATCH: "[extern isr_handler]"
#MISMATCH: "[extern irq_handler]"
# Common ISR code
isr_common_stub:
# 1. Save CPU state
pusha # Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
movw %ds,%ax # Lower 16-bits of eax = ds.
pushl %eax # save the data segment descriptor
movw $0x10,%ax # kernel data segment descriptor
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
# 2. Call C handler
call isr_handler
# 3. Restore state
popl %eax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
popa
addl $8,%esp # Cleans up the pushed error code and pushed ISR number
sti
iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
# Common IRQ code. Identical to ISR code except for the 'call'
# and the 'pop ebx'
irq_common_stub:
pusha
movw %ds,%ax
pushl %eax
movw $0x10,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
call irq_handler # Different than the ISR code
popl %ebx # Different than the ISR code
movw %bx,%ds
movw %bx,%es
movw %bx,%fs
movw %bx,%gs
popa
addl $8,%esp
sti
iret
# We don't get information about which interrupt was caller
# when the handler is run, so we will need to have a different handler
# for every interrupt.
# Furthermore, some interrupts push an error code onto the stack but others
# don't, so we will push a dummy error code for those which don't, so that
# we have a consistent stack for all of them.
# First make the ISRs global
.global isr0
.global isr1
.global isr2
.global isr3
.global isr4
.global isr5
.global isr6
.global isr7
.global isr8
.global isr9
.global isr10
.global isr11
.global isr12
.global isr13
.global isr14
.global isr15
.global isr16
.global isr17
.global isr18
.global isr19
.global isr20
.global isr21
.global isr22
.global isr23
.global isr24
.global isr25
.global isr26
.global isr27
.global isr28
.global isr29
.global isr30
.global isr31
.global irq0
.global irq1
.global irq2
.global irq3
.global irq4
.global irq5
.global irq6
.global irq7
.global irq8
.global irq9
.global irq10
.global irq11
.global irq12
.global irq13
.global irq14
.global irq15
# 0: Divide By Zero Exception
isr0:
cli
push $0
push $0
jmp isr_common_stub
# 1: Debug Exception
isr1:
cli
push $0
push $1
jmp isr_common_stub
# 2: Non Maskable Interrupt Exception
isr2:
cli
push $0
push $2
jmp isr_common_stub
# 3: Int 3 Exception
isr3:
cli
push $0
push $3
jmp isr_common_stub
# 4: INTO Exception
isr4:
cli
push $0
push $4
jmp isr_common_stub
# 5: Out of Bounds Exception
isr5:
cli
push $0
push $5
jmp isr_common_stub
# 6: Invalid Opcode Exception
isr6:
cli
push $0
push $6
jmp isr_common_stub
# 7: Coprocessor Not Available Exception
isr7:
cli
push $0
push $7
jmp isr_common_stub
# 8: Double Fault Exception (With Error Code!)
isr8:
cli
push $8
jmp isr_common_stub
# 9: Coprocessor Segment Overrun Exception
isr9:
cli
push $0
push $9
jmp isr_common_stub
# 10: Bad TSS Exception (With Error Code!)
isr10:
cli
push $10
jmp isr_common_stub
# 11: Segment Not Present Exception (With Error Code!)
isr11:
cli
push $11
jmp isr_common_stub
# 12: Stack Fault Exception (With Error Code!)
isr12:
cli
push $12
jmp isr_common_stub
# 13: General Protection Fault Exception (With Error Code!)
isr13:
cli
push $13
jmp isr_common_stub
# 14: Page Fault Exception (With Error Code!)
isr14:
cli
push $14
jmp isr_common_stub
# 15: Reserved Exception
isr15:
cli
push $0
push $15
jmp isr_common_stub
# 16: Floating Point Exception
isr16:
cli
push $0
push $16
jmp isr_common_stub
# 17: Alignment Check Exception
isr17:
cli
push $0
push $17
jmp isr_common_stub
# 18: Machine Check Exception
isr18:
cli
push $0
push $18
jmp isr_common_stub
# 19: Reserved
isr19:
cli
push $0
push $19
jmp isr_common_stub
# 20: Reserved
isr20:
cli
push $0
push $20
jmp isr_common_stub
# 21: Reserved
isr21:
cli
push $0
push $21
jmp isr_common_stub
# 22: Reserved
isr22:
cli
push $0
push $22
jmp isr_common_stub
# 23: Reserved
isr23:
cli
push $0
push $23
jmp isr_common_stub
# 24: Reserved
isr24:
cli
push $0
push $24
jmp isr_common_stub
# 25: Reserved
isr25:
cli
push $0
push $25
jmp isr_common_stub
# 26: Reserved
isr26:
cli
push $0
push $26
jmp isr_common_stub
# 27: Reserved
isr27:
cli
push $0
push $27
jmp isr_common_stub
# 28: Reserved
isr28:
cli
push $0
push $28
jmp isr_common_stub
# 29: Reserved
isr29:
cli
push $0
push $29
jmp isr_common_stub
# 30: Reserved
isr30:
cli
push $0
push $30
jmp isr_common_stub
# 31: Reserved
isr31:
cli
push $0
push $31
jmp isr_common_stub
# IRQ handlers
irq0:
cli
push $0
push $32
jmp irq_common_stub
irq1:
cli
push $1
push $33
jmp irq_common_stub
irq2:
cli
push $2
push $34
jmp irq_common_stub
irq3:
cli
push $3
push $35
jmp irq_common_stub
irq4:
cli
push $4
push $36
jmp irq_common_stub
irq5:
cli
push $5
push $37
jmp irq_common_stub
irq6:
cli
push $6
push $38
jmp irq_common_stub
irq7:
cli
push $7
push $39
jmp irq_common_stub
irq8:
cli
push $8
push $40
jmp irq_common_stub
irq9:
cli
push $9
push $41
jmp irq_common_stub
irq10:
cli
push $10
push $42
jmp irq_common_stub
irq11:
cli
push $11
push $43
jmp irq_common_stub
irq12:
cli
push $12
push $44
jmp irq_common_stub
irq13:
cli
push $13
push $45
jmp irq_common_stub
irq14:
cli
push $14
push $46
jmp irq_common_stub
irq15:
cli
push $15
push $47
jmp irq_common_stub

144
kernel/cpu/isr.c Normal file
View File

@@ -0,0 +1,144 @@
//
// Created by rick on 8/18/19.
//
#include "isr.h"
#include <kprint.h>
#include <cpu/idt.h>
#include <libc/libc.h>
#include <drivers/ports.h>
isr_t interrupt_handlers[256];
void isr_install() {
set_idt_gate(0, (u32) isr0);
set_idt_gate(1, (u32) isr1);
set_idt_gate(2, (u32) isr2);
set_idt_gate(3, (u32) isr3);
set_idt_gate(4, (u32) isr4);
set_idt_gate(5, (u32) isr5);
set_idt_gate(6, (u32) isr6);
set_idt_gate(7, (u32) isr7);
set_idt_gate(8, (u32) isr8);
set_idt_gate(9, (u32) isr9);
set_idt_gate(10, (u32) isr10);
set_idt_gate(11, (u32) isr11);
set_idt_gate(12, (u32) isr12);
set_idt_gate(13, (u32) isr13);
set_idt_gate(14, (u32) isr14);
set_idt_gate(15, (u32) isr15);
set_idt_gate(16, (u32) isr16);
set_idt_gate(17, (u32) isr17);
set_idt_gate(18, (u32) isr18);
set_idt_gate(19, (u32) isr19);
set_idt_gate(20, (u32) isr20);
set_idt_gate(21, (u32) isr21);
set_idt_gate(22, (u32) isr22);
set_idt_gate(23, (u32) isr23);
set_idt_gate(24, (u32) isr24);
set_idt_gate(25, (u32) isr25);
set_idt_gate(26, (u32) isr26);
set_idt_gate(27, (u32) isr27);
set_idt_gate(28, (u32) isr28);
set_idt_gate(29, (u32) isr29);
set_idt_gate(30, (u32) isr30);
set_idt_gate(31, (u32) isr31);
// Remap the PIC
port_byte_out(0x20, 0x11);
port_byte_out(0xA0, 0x11);
port_byte_out(0x21, 0x20);
port_byte_out(0xA1, 0x28);
port_byte_out(0x21, 0x04);
port_byte_out(0xA1, 0x02);
port_byte_out(0x21, 0x01);
port_byte_out(0xA1, 0x01);
port_byte_out(0x21, 0x0);
port_byte_out(0xA1, 0x0);
// Install the IRQs
set_idt_gate(32, (u32) irq0);
set_idt_gate(33, (u32) irq1);
set_idt_gate(34, (u32) irq2);
set_idt_gate(35, (u32) irq3);
set_idt_gate(36, (u32) irq4);
set_idt_gate(37, (u32) irq5);
set_idt_gate(38, (u32) irq6);
set_idt_gate(39, (u32) irq7);
set_idt_gate(40, (u32) irq8);
set_idt_gate(41, (u32) irq9);
set_idt_gate(42, (u32) irq10);
set_idt_gate(43, (u32) irq11);
set_idt_gate(44, (u32) irq12);
set_idt_gate(45, (u32) irq13);
set_idt_gate(46, (u32) irq14);
set_idt_gate(47, (u32) irq15);
set_idt(); // Load with ASM
}
char *exception_messages[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
void isr_handler(registers_t r) {
kprint("received interrupt: ");
char s[3];
itoa(r.int_no, s);
kprint(s);
kprint("\n");
kprint(exception_messages[r.int_no]);
kprint("\n");
}
void register_interrupt_handler(u8 n, isr_t handler) {
interrupt_handlers[n] = handler;
}
void irq_handler(registers_t r) {
/* After every interrupt we need to send an EOI to the PICs
* or they will not send another interrupt again */
if (r.int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */
port_byte_out(0x20, 0x20); /* master */
/* Handle the interrupt in a more modular way */
if (interrupt_handlers[r.int_no] != 0) {
isr_t handler = interrupt_handlers[r.int_no];
handler(r);
}
}

140
kernel/cpu/isr.h Normal file
View File

@@ -0,0 +1,140 @@
//
// Created by rick on 8/18/19.
//
#include "../types.h"
#ifndef MY_KERNEL_ISR_H
#define MY_KERNEL_ISR_H
/* ISRs reserved for CPU exceptions */
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
/* IRQ definitions */
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
#define IRQ0 32
#define IRQ1 33
#define IRQ2 34
#define IRQ3 35
#define IRQ4 36
#define IRQ5 37
#define IRQ6 38
#define IRQ7 39
#define IRQ8 40
#define IRQ9 41
#define IRQ10 42
#define IRQ11 43
#define IRQ12 44
#define IRQ13 45
#define IRQ14 46
#define IRQ15 47
typedef struct {
u32 ds;
u32 edi, esi, ebp, esp, ebx, edx, ecx, eax;
u32 int_no, err_code;
u32 eip, cs, eflags, useresp, ss;
} registers_t;
typedef void (*isr_t)(registers_t);
void register_interrupt_handler(u8 n, isr_t handler);
void isr_install();
void isr_handler(registers_t r);
#endif //MY_KERNEL_ISR_H

26
kernel/cpu/timer.c Normal file
View File

@@ -0,0 +1,26 @@
//
// Created by rick on 9/22/19.
//
#include "timer.h"
#include <drivers/ports.h>
#include <cpu/isr.h>
u32 tick = 0;
static void timer_callback(registers_t regs) {
tick++;
}
int init_timer(u32 freq) {
register_interrupt_handler(IRQ0, timer_callback);
u32 divisor = 1193180 / freq;
u8 low = (u8) (divisor & 0xFF);
u8 high = (u8) ((divisor >> 8) & 0xFF);
port_byte_out(PORT_PIT_COMMAND, PIT_MODE_BIN | PIT_MODE_SQUARE_WAVE | PIT_ACCESS_MODE_HL | PIT_CHANNEL_0);
port_byte_out(PORT_PIT_DATA_0, low);
port_byte_out(PORT_PIT_DATA_0, high);
return 0;
}

12
kernel/cpu/timer.h Normal file
View File

@@ -0,0 +1,12 @@
//
// Created by rick on 9/22/19.
//
#ifndef MY_KERNEL_TIMER_H
#define MY_KERNEL_TIMER_H
#include "../types.h"
int init_timer(u32 freq);
#endif //MY_KERNEL_TIMER_H