From baa4b6cf54364d0333ece9539d9cd8cd66b23a39 Mon Sep 17 00:00:00 2001 From: the lemons Date: Sat, 10 Apr 2021 01:59:09 -0500 Subject: refactor interrupt handling (and do other things) --- kernel.bin | Bin 89932 -> 95156 bytes linker.ld | 4 +++ os.iso | Bin 19892224 -> 19898368 bytes src/interrupt.c | 68 ++++++++++++++++++++++++++++----------------------- src/interrupt.h | 16 +++++++++++- src/interrupt_stub.s | 48 ++++++++++++++++++++---------------- src/irq_handlers.c | 26 ++++++++++++++++++++ src/main.c | 20 +++++++++++---- src/memory.c | 60 +++++++++++++++++++++++++++++++++++++++++---- src/memory.h | 44 +++++++++++++++++++++++---------- src/misc.h | 6 +++++ 11 files changed, 217 insertions(+), 75 deletions(-) create mode 100644 src/irq_handlers.c create mode 100644 src/misc.h diff --git a/kernel.bin b/kernel.bin index 8c58cab..cd32d5b 100755 Binary files a/kernel.bin and b/kernel.bin differ diff --git a/linker.ld b/linker.ld index cd22338..22a3ab1 100644 --- a/linker.ld +++ b/linker.ld @@ -6,6 +6,8 @@ SECTIONS /* Begin at 1 MiB */ . = 1M; + __kernel_start = .; + /* Multiboot header */ .text BLOCK(4K) : ALIGN(4K) { @@ -23,4 +25,6 @@ SECTIONS *(COMMON) *(.bss) } + + __kernel_end = .; } diff --git a/os.iso b/os.iso index 190667f..74e73b0 100644 Binary files a/os.iso and b/os.iso differ diff --git a/src/interrupt.c b/src/interrupt.c index c417117..98ac2fb 100644 --- a/src/interrupt.c +++ b/src/interrupt.c @@ -1,43 +1,33 @@ #include "interrupt.h" #include "string.h" -#include "vga.h" -#include "bees.h" -#include "printf.h" -#include "keyboard.h" struct port pic_master_command = {0x20, port8bit_slow}; struct port pic_master_data = {0x21, port8bit_slow}; struct port pic_slave_command = {0xA0, port8bit_slow}; struct port pic_slave_data = {0xA1, port8bit_slow}; -struct port ps2_port = {0x60, port8bit}; - struct gate_desc idt[256] = {0}; -#define PIC_EOI 0x20 - void irq_end(uint8_t int_number) { if (int_number >= 0x28) port_write(pic_slave_command, PIC_EOI); port_write(pic_master_command, PIC_EOI); } -uint8_t ps2_read() { - return port_read(ps2_port); -} -uint32_t handle_int(uint8_t int_number, uint32_t idk, uint32_t esp) { - switch (int_number) { - case 0x0D: - // bye - bees("general protection fault"); - break; - case 0x21: - keyboard_event(&ps2_read); - irq_end(int_number); - break; - } +uint32_t handle_int(irqh_t *int_handler, uint8_t int_number, uint32_t esp) { + + port_write(pic_master_data, 0xFF); // mask all IRQs + start_interrupts(); // reenable interrupts + + if (int_handler != NULL) (*int_handler)(); + irq_end(int_number); + + // call event loop here + + clear_interrupts(); + port_write(pic_master_data, INT_MASK); // restore normal interrupt mask return esp; } @@ -61,16 +51,30 @@ void interrupt_init() { for (uint16_t i = 0; i < 256; i++) set_int_desc_entry(i, code_seg, &int_ignore, 0, IDT_INTERRUPT_GATE); - // Put the interrupt handlers in the IDT - set_int_desc_entry(0x20, code_seg, &handle_irq0x00, 0, IDT_INTERRUPT_GATE); - set_int_desc_entry(0x21, code_seg, &handle_irq0x01, 0, IDT_INTERRUPT_GATE); - set_int_desc_entry(0x0D, code_seg, &handle_irq0x0D, 0, IDT_INTERRUPT_GATE); +#define IRQH(IRQ) \ + set_int_desc_entry( \ + IRQ + 0x20, code_seg, &handle_irq ## IRQ, 0, IDT_INTERRUPT_GATE) + +#define EXCH(IRQ) \ + set_int_desc_entry( \ + IRQ, code_seg, &handle_exception ## IRQ, 0, IDT_INTERRUPT_GATE) + + IRQH(0x00); + IRQH(0x01); + + EXCH(0x00); + EXCH(0x01); + EXCH(0x02); + EXCH(0x03); + EXCH(0x06); + EXCH(0x07); + EXCH(0x08); + EXCH(0x0D); port_write(pic_master_command, 0x11); port_write(pic_slave_command, 0x11); - // (I actually don't understand how this works) - // Remap the PIC + // remap the PIC port_write(pic_master_data, 0x20); // Interrupt vector offsets port_write(pic_slave_data, 0x28); @@ -80,7 +84,7 @@ void interrupt_init() { port_write(pic_master_data, 0x01); port_write(pic_slave_data, 0x01); - port_write(pic_master_data, 0xFD); + port_write(pic_master_data, INT_MASK); port_write(pic_slave_data, 0xFF); // Load the IDT @@ -92,5 +96,9 @@ void interrupt_init() { } void start_interrupts() { - asm("sti"); + asm volatile("sti"); +} + +void clear_interrupts() { + asm volatile("cli"); } diff --git a/src/interrupt.h b/src/interrupt.h index 5e0112b..b308a0c 100644 --- a/src/interrupt.h +++ b/src/interrupt.h @@ -31,10 +31,18 @@ void set_int_desc_entry(uint8_t int_number, uint16_t gdt_code_seg, void interrupt_init(); void start_interrupts(); +void clear_interrupts(); void handle_irq0x00(); void handle_irq0x01(); -void handle_irq0x0D(); +void handle_exception0x00(); +void handle_exception0x01(); +void handle_exception0x02(); +void handle_exception0x03(); +void handle_exception0x06(); +void handle_exception0x07(); +void handle_exception0x08(); +void handle_exception0x0D(); void int_ignore(); @@ -43,4 +51,10 @@ struct port pic_master_data; struct port pic_slave_command; struct port pic_slave_data; +typedef void irqh_t(); + +#define INT_MASK 0x00 + +#define PIC_EOI 0x20 + #endif diff --git a/src/interrupt_stub.s b/src/interrupt_stub.s index 3d2ba53..3838048 100644 --- a/src/interrupt_stub.s +++ b/src/interrupt_stub.s @@ -8,9 +8,10 @@ .macro handle_exception num -.global handle_irq\num -handle_irq\num: +.global handle_exception\num +handle_exception\num: movb $\num, (int_number) + movl $exch_\num, (int_handler) jmp int_bottom .endm @@ -18,40 +19,45 @@ handle_irq\num: .global handle_irq\num handle_irq\num: movb $\num + IRQ_BASE, (int_number) + movl $irqh_\num, (int_handler) jmp int_bottom .endm handle_irq 0x00 handle_irq 0x01 +handle_exception 0x00 +handle_exception 0x01 +handle_exception 0x02 +handle_exception 0x03 +handle_exception 0x06 +handle_exception 0x07 +handle_exception 0x08 handle_exception 0x0D +int_ignore: + + movb $0xFF, (int_number) + movl $0x00, (int_handler) + int_bottom: - pop %eax - push int_bottom - pusha - pushl %ds - pushl %es - pushl %fs - pushl %gs - + + cli + pushl %esp - pushl %eax push (int_number) + pushl (int_handler) call handle_int movl %eax, %esp // Set the stack pointer to the return value of handle_int - popl %gs - popl %fs - popl %es - popl %ds - popa - - iret - -int_ignore: pop %eax + pop %eax + pop %eax + pop %eax + + sti - iret + hlt .data int_number: .byte 0 + int_handler: .int 0 diff --git a/src/irq_handlers.c b/src/irq_handlers.c new file mode 100644 index 0000000..19db144 --- /dev/null +++ b/src/irq_handlers.c @@ -0,0 +1,26 @@ + +#include "interrupt.h" +#include "port.h" +#include "bees.h" +#include "keyboard.h" +#include + +uint8_t ps2_read() { + const struct port ps2_port = {0x60, port8bit}; + return port_read(ps2_port); +} + +#define IRQH(I) void irqh_ ## I () +#define EXCH(I) void exch_ ## I () + +IRQH(0x00) {return;} +IRQH(0x01) {keyboard_event(&ps2_read);} + +EXCH(0x00) {bees("division by zero (this is weird!)");} +EXCH(0x01) {bees("values of beta may give rise to dom!");} +EXCH(0x02) {bees("lp0 on fire");} +EXCH(0x03) {bees("values of beta may give rise to dom!");} +EXCH(0x06) {bees("invalid opcode (bad!)");} +EXCH(0x07) {bees("values of beta may give rise to dom!");} +EXCH(0x08) {bees("double fault");} +EXCH(0x0D) {bees("general protection fault");} diff --git a/src/main.c b/src/main.c index 382abe7..9bc98ae 100644 --- a/src/main.c +++ b/src/main.c @@ -19,7 +19,9 @@ const char *pope = "loosing\", naming him as the \"rock\" upon which the church would be built. \n" "Since 1929, the pope has official residence in the Apostolic Palace in the \n" "Vatican City, a city-state enclaved within Rome, Italy.[6] The current pope is \n" -"Francis, who was elected on 13 March 2013, succeeding Benedict XVI.[7] \n" +"Francis, who was elected on 13 March 2013, succeeding Benedict XVI.[7] \n"; + +/* "While his office is called the papacy, the jurisdiction of the episcopal see is\n" "called the Holy See.[8] It is the Holy See that is the sovereign entity by \n" "international law headquartered in the distinctively independent Vatican City \n" @@ -28,15 +30,12 @@ const char *pope = "recognized by its adherence at various levels to international organization and\n" "by means of its diplomatic relations and political accords with many \n" "independent states.\n"; +*/ void kernel_main(multiboot_info_t *mb) { vsetcolor(vga_color(vga_black, vga_white)); vclear(); interrupt_init(); - start_interrupts(); - init_memory(mb); - - printf("%u MB memory available\n", memory_available / 1000000); vprint(" _ _ \n"); vprint(" ___(_) |_ _ __ ___ _ __ ___ ___ ___ \n"); @@ -46,5 +45,16 @@ void kernel_main(multiboot_info_t *mb) { vprint(pope); +// init_memory(mb); + +// printf("%u MB memory available\n", memory_available / 1000000); + +// printf("I will now exhaust a lot of memory\n"); +// for (int i=0;i<250000000;i++) alloc_cell(0); +// +// printf("%u MB memory available\n", memory_available / 1000000); + + start_interrupts(); + while (1) asm volatile("hlt"); } diff --git a/src/memory.c b/src/memory.c index bc65311..e5e215c 100644 --- a/src/memory.c +++ b/src/memory.c @@ -4,19 +4,29 @@ #include #include "memory.h" #include "multiboot.h" +#include "bees.h" +#include "misc.h" #include "printf.h" struct memory_area { uint32_t len; struct memory_area *next; + struct memory_area *prev; }; -struct memory_area *first = NULL; - uint32_t memory_available = 0; +uint32_t total_memory = 0; +struct memory_area *first_area = NULL; + +struct cell *first_free = NULL; + +extern mem_t __kernel_start; +extern mem_t __kernel_end; void init_memory(multiboot_info_t *mb) { struct memory_area *prev = NULL; + struct cell *prev_cell = NULL; + for ( multiboot_memory_map_t *e = (multiboot_memory_map_t *) mb->mmap_addr; (unsigned int) e < mb->mmap_addr + mb->mmap_length; @@ -24,7 +34,7 @@ void init_memory(multiboot_info_t *mb) { ) { if (e->type != MULTIBOOT_MEMORY_AVAILABLE) continue; // memory below 1MB is not safe to use. - if (e->addr < 1000000) continue; + if (e->addr < __kernel_start) continue; // memory above UINT_MAX is unusable. if (e->addr > UINT_MAX) continue; @@ -34,14 +44,54 @@ void init_memory(multiboot_info_t *mb) { length = UINT_MAX - e->addr; else length = e->len; - memory_available += length; + // free memory comes after the kernel + uint32_t addr = e->addr; + if (addr < (uint32_t) __kernel_end) { + addr = (uint32_t) __kernel_end; + length -= addr - e->addr; + } + + memory_available += length - sizeof(struct memory_area); - struct memory_area *cur = (struct memory_area *) e->addr; + // join memory area to linked list + struct memory_area *cur = (struct memory_area *) addr; cur->len = length; + cur->next = NULL; + cur->prev = prev; if (prev != NULL) prev->next = (struct memory_area *) e->addr; prev = cur; + + if (first_area == NULL) first_area = cur; + + unsigned char *after = (unsigned char*) (cur + 1); + + // link memory into free list + for ( + // cells start after memory area struct; they must be aligned. + struct cell *c = (struct cell *) + (after + ((uint32_t) after % sizeof(struct cell))); + // no part of the cell can be outside of the memory area + (uint32_t) (c + 1) < (uint32_t) cur + cur->len; + c++ + ) { + if (first_free == NULL) first_free = c; + c->type = FREE_CELL; + set_cdr(c, 0); + if (prev_cell != NULL) set_cdr(prev_cell, (uint32_t) c); + prev_cell = c; + } } + total_memory = memory_available; +} + +struct cell *alloc_cell(enum cell_type t) { + if (first_free == NULL) return NULL; // GC should be invoked here somehow + if (first_free->type != FREE_CELL) bees("heap corruption has occurred"); + first_free = cdr_cell(first_free); + first_free->type = t; + memory_available -= sizeof(struct cell); + return first_free; } diff --git a/src/memory.h b/src/memory.h index c5b6367..f780034 100644 --- a/src/memory.h +++ b/src/memory.h @@ -2,36 +2,54 @@ #define __MEMORY_H #include -#include "redacted.h" #include "multiboot.h" enum cell_type { FREE_CELL, CONS_CELL, INT_CELL, + BIGINT_CELL, CHAR_CELL, FLOAT_CELL, + VIRTUAL_CELL, + SYMBOL_CELL, ARRAY_CELL, ARRAY_MEMBER, + SYS_ARRAY, APIOFORM }; struct cell { - uint8_t type; - union { - struct cell *free; - struct cell *cons; - struct {int type : 8; int size : 24;} array_cell; - uint32_t int_; - uint32_t char_; - float float_; - REDACTED_t apioform; - } car; - struct cell *cdr; -}; + int car : 29; + int cdr : 29; + int type : 4; + int gc_mark : 1; +} __attribute((packed)); uint32_t memory_available; void init_memory(multiboot_info_t *mb); +struct cell *alloc_cell(enum cell_type t); +enum cell_type get_cell_type(const struct cell *c); +void set_cell_type(struct cell *c, enum cell_type t); + +static inline uint32_t car(struct cell *c) { + return c->car << 3; +} +static inline uint32_t cdr(struct cell *c) { + return c->cdr << 3; +} +static inline struct cell *car_cell(struct cell *c) { + return (struct cell *) car(c); +} +static inline struct cell *cdr_cell(struct cell *c) { + return (struct cell *) cdr(c); +} +static inline void set_car(struct cell *c, uint32_t val) { + c->car = val >> 3; +} +static inline void set_cdr(struct cell *c, uint32_t val) { + c->cdr = val >> 3; +} #endif diff --git a/src/misc.h b/src/misc.h new file mode 100644 index 0000000..93b3117 --- /dev/null +++ b/src/misc.h @@ -0,0 +1,6 @@ +#ifndef __MISC_H +#define __MISC_H + +typedef unsigned char mem_t[]; + +#endif -- cgit v1.2.3