GDT fix for GRUB, IDT revamp, initialize PIC

This commit is contained in:
Furkan Mudanyali 2022-07-19 10:45:38 +03:00
parent b987beca85
commit 4b75737ad0
15 changed files with 268 additions and 101 deletions

View File

@ -24,10 +24,12 @@ stack_top:
.global _start
.type _start, @function
_start:
movl $stack_top, %esp
cli
call gdt_init # initialize the GDT
movl $stack_top, %esp
call terminal_initialize
call idt_init # initialize the IDT
call PIC_remap
call kernel_main # transfer control to main kernel
# Hang if kernel_main unexpectedly returns
1: hlt

View File

@ -41,8 +41,18 @@ void gdt_init(void) {
gdt_fill(GDT+i, rows+i);
}
gp.base = &GDT;
gp.limit = (GDT_ENTRIES * sizeof(gdt_entry)) - 1;
gp.base = (uintptr_t)&GDT[0];
gp.limit = sizeof(gdt_entry) * GDT_ENTRIES - 1;
gdt_load();
__asm__ volatile("lgdt %0" : : "m"(gp)); // Load new GDT
__asm__ volatile(
"jmp $0x0008, $fix_cs\n"
"fix_cs:\n"
"mov $0x0010, %ax\n"
"mov %ax, %ds\n"
"mov %ax, %es\n"
"mov %ax, %fs\n"
"mov %ax, %gs\n"
"mov %ax, %ss"
);
}

View File

@ -1,20 +0,0 @@
# Referenced from https://github.com/tendstofortytwo/clay
# kernel/boot/gdt.s
.global gdt_load
.type gdt_load, @function
gdt_load:
lgdt (gp)
mov %cr0, %eax
or $0x1, %eax
mov %eax, %cr0
jmp $0x08, $reload
reload:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
ret

View File

@ -1,49 +1,169 @@
#include <kernel/idt.h>
#include <stdio.h>
__attribute__((interrupt)) void hello_interrupt(idt_frame* frame) {
printf("Hello from interrupt!\n");
printf("ip=0x%x, cs=0x%x, flags=0b%b\n", frame->ip, frame->cs, frame->flags);
__attribute__((interrupt)) void int_handler(void* frame, unsigned int number) {
unsigned int err = 0;
idt_frame* idt_ptr;
idt_frame_err* idt_ptr_e;
switch(number) {
case 8:
case 10:
case 11:
case 12:
case 13:
case 14:
case 17:
case 21:
idt_ptr_e = (idt_frame_err*)frame;
err = 1;
break;
default:
idt_ptr = (idt_frame*)frame;
break;
}
__attribute__((interrupt)) void hello_interrupt_err(idt_frame_err* frame) {
printf("Hello from error interrupt!\n");
printf("ip=0x%x, cs=0x%x, flags=0b%b, err=0x%x\n", frame->ip, frame->cs, frame->flags, frame->err);
asm volatile("cli; hlt");
switch(number) {
case 0:
printf("#DE Divide Error!\n");
break;
case 1:
printf("#DB Debug Exception!\n");
break;
case 2:
printf("NMI Interrupt!\n");
break;
case 3:
printf("#BP Breakpoint!\n");
break;
case 4:
printf("#OF Overflow!\n");
break;
case 5:
printf("#BR Bound Range Exceeded!\n");
break;
case 6:
printf("#Invalid Opcode (Undefined Opcode)!\n");
break;
case 7:
printf("#NM Device Not Available (No Math Coprocessor)!\n");
break;
case 9:
printf("Coprocessor Segment Overrun (reserved)!\n");
break;
case 16:
printf("#MF x87 FPU Floating-Point Error (Math Fault)!\n");
break;
case 18:
printf("#MC Machine Check!\n");
break;
case 19:
printf("#XM SIMD Floating-Point Exception!\n");
break;
case 20:
printf("#VE Virtualization Exception!\n");
break;
////////
case 8:
printf("#DF Double Fault!\n");
break;
case 10:
printf("#TS Invalid TSS!\n");
break;
case 11:
printf("#NP Segment Not Present!\n");
break;
case 12:
printf("#SS Stack-Segment Fault!\n");
break;
case 13:
printf("#GP General Protection!\n");
break;
case 14:
printf("#PF Page Fault!\n");
break;
case 17:
printf("#AC Alignment Check!\n");
break;
case 21:
printf("#CP Control Protection Exception!\n");
break;
}
void idt_fill_row(idt_entry_t* target, idt* source) {
target->isr_low = source->offset & 0xFFFF;
target->isr_high = (source->offset >> 16) & 0xFFFF;
target->kernel_cs = source->segment;
target->flags = 0x80;
target->flags |= (source->ring & 0x3) << 5;
target->flags |= (source->gate & 0xF);
target->reserved = 0;
if(err){
printf("err: 0x%X, ip: 0x%X, cs: 0x%X, flags: 0x%X, sp: 0x%X, ss: 0x%X\n",
idt_ptr_e->err, idt_ptr_e->ip, idt_ptr_e->cs, idt_ptr_e->flags, idt_ptr_e->sp, idt_ptr_e->ss);
} else {
printf("ip: 0x%X, cs: 0x%X, flags: 0x%X, sp: 0x%X, ss: 0x%X\n",
idt_ptr->ip, idt_ptr->cs, idt_ptr->flags, idt_ptr->sp, idt_ptr->ss);
}
return;
}
__attribute__((aligned(0x10))) idt_entry_t IDT[IDT_ROWS];
idtr_t idtptr;
#define INT_WRAPPER(NUM) __attribute__((interrupt)) void int##NUM##_wrapper(void* frame) { \
int_handler(frame, NUM); \
}
INT_WRAPPER(0)
INT_WRAPPER(1)
INT_WRAPPER(2)
INT_WRAPPER(3)
INT_WRAPPER(4)
INT_WRAPPER(5)
INT_WRAPPER(6)
INT_WRAPPER(7)
INT_WRAPPER(8)
INT_WRAPPER(9)
INT_WRAPPER(10)
INT_WRAPPER(11)
INT_WRAPPER(12)
INT_WRAPPER(13)
INT_WRAPPER(14)
INT_WRAPPER(16)
INT_WRAPPER(17)
INT_WRAPPER(18)
INT_WRAPPER(19)
INT_WRAPPER(20)
INT_WRAPPER(21)
static __attribute__((aligned(0x10))) idt_entry_t idt[IDT_MAX_DESCRIPTORS];
static idtr_t idtptr;
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags) {
idt_entry_t* descriptor = &idt[vector];
descriptor->isr_low = (uint32_t)isr & 0xFFFF;
descriptor->kernel_cs = 0x08; // Whatever offset kernel code selector is in GDT
descriptor->flags = flags;
descriptor->isr_high = (uint32_t)isr >> 16;
descriptor->reserved = 0;
}
void idt_init(void) {
idt rows[] = {
{(uint32_t)hello_interrupt, 0x08, INT_GATE32, 0},
{(uint32_t)hello_interrupt_err, 0x08, INT_GATE32, 0},
};
idtptr.base = (uintptr_t)&idt[0];
idtptr.limit = (uint16_t)sizeof(idt_entry_t) * IDT_MAX_DESCRIPTORS - 1;
int valid_rows = sizeof(rows) / sizeof(idt_entry_t);
idt_set_descriptor(0, int0_wrapper, 0x8E);
idt_set_descriptor(0, int0_wrapper, 0x8E);
idt_set_descriptor(1, int1_wrapper, 0x8E);
idt_set_descriptor(2, int2_wrapper, 0x8E);
idt_set_descriptor(3, int3_wrapper, 0x8E);
idt_set_descriptor(4, int4_wrapper, 0x8E);
idt_set_descriptor(5, int5_wrapper, 0x8E);
idt_set_descriptor(6, int6_wrapper, 0x8E);
idt_set_descriptor(7, int7_wrapper, 0x8E);
idt_set_descriptor(8, int8_wrapper, 0x8E);
idt_set_descriptor(9, int9_wrapper, 0x8E);
idt_set_descriptor(10, int10_wrapper, 0x8E);
idt_set_descriptor(11, int11_wrapper, 0x8E);
idt_set_descriptor(12, int12_wrapper, 0x8E);
idt_set_descriptor(13, int13_wrapper, 0x8E);
idt_set_descriptor(14, int14_wrapper, 0x8E);
idt_set_descriptor(16, int16_wrapper, 0x8E);
idt_set_descriptor(17, int17_wrapper, 0x8E);
idt_set_descriptor(18, int18_wrapper, 0x8E);
idt_set_descriptor(19, int19_wrapper, 0x8E);
idt_set_descriptor(20, int20_wrapper, 0x8E);
idt_set_descriptor(21, int21_wrapper, 0x8E);
for(int i = 0; i < valid_rows; ++i) {
idt_fill_row(IDT+i, rows+i);
}
idt blank_row = {0, 0, 0, 0};
for(int i = valid_rows; i < IDT_ROWS; ++i) {
idt_fill_row(IDT+i, &blank_row);
}
idtptr.base = &IDT;
idtptr.limit = (IDT_ROWS * sizeof(idt_entry_t)) - 1;
idt_load();
__asm__ volatile("lidt %0" : : "m"(idtptr)); // Load new IDT
__asm__ volatile("sti"); // Set interrupt flag
}

View File

@ -1,6 +0,0 @@
.global idt_load
.type idt_load, @function
idt_load:
lidt (idtptr)
sti
ret

View File

@ -0,0 +1,30 @@
#include <kernel/pic.h>
void PIC_remap() {
unsigned char a1, a2;
a1 = inb(PIC1_DATA); // save masks
a2 = inb(PIC2_DATA);
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // Start init sequence in cascade mode
io_wait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC1_DATA, PIC1_OFFSET); // ICW2: Master PIC vector offset
io_wait();
outb(PIC2_DATA, PIC2_OFFSET); // ICW2: Slave PIC vector offset
io_wait();
outb(PIC1_DATA, 4); // ICW3: tell Master PIC that theres a slave PIC at IRQ2 (0000 0100)
io_wait();
outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
io_wait();
outb(PIC1_DATA, ICW4_8086);
io_wait();
outb(PIC2_DATA, ICW4_8086);
io_wait();
outb(PIC1_DATA, a1); // restore saved masks
outb(PIC2_DATA, a2);
}

View File

@ -7,7 +7,6 @@ KERNEL_ARCH_OBJS=\
$(ARCHDIR)/boot/boot.o \
$(ARCHDIR)/vga/tty.o \
$(ARCHDIR)/boot/gdt.o \
$(ARCHDIR)/boot/gdt_load.o \
$(ARCHDIR)/paging/paging.o \
$(ARCHDIR)/boot/idt.o \
$(ARCHDIR)/boot/idt_load.o
$(ARCHDIR)/boot/pic.o

View File

@ -33,7 +33,6 @@ typedef struct {
void gdt_fill(gdt_entry*, gdt*);
void gdt_init(void);
extern void gdt_load();
extern uint32_t TSS[32];
extern gdt_entry GDT[GDT_ENTRIES];

View File

@ -3,17 +3,7 @@
#include <stdint.h>
#define IDT_ROWS 256
#define TASK_GATE 0x5
#define INT_GATE16 0x6
#define TRAP_GATE16 0x7
#define INT_GATE32 0xE
#define TRAP_GATE32 0xF
typedef struct {
uint16_t limit;
uint32_t base;
} __attribute__((packed)) idtr_t;
#define IDT_MAX_DESCRIPTORS 256
typedef struct {
uint16_t isr_low; // lower 16-bits of ISR address
@ -24,11 +14,9 @@ typedef struct {
} __attribute__((packed)) idt_entry_t;
typedef struct {
uint32_t offset;
uint16_t segment;
uint8_t gate;
uint8_t ring;
} idt;
uint16_t limit;
uint32_t base;
} __attribute__((packed)) idtr_t;
typedef struct {
uint32_t ip;
@ -47,7 +35,6 @@ typedef struct {
uint32_t ss;
} __attribute__((packed)) idt_frame_err;
extern void idt_load();
extern idtr_t idtptr;
static idtr_t idtptr;
#endif

View File

@ -1,7 +1,7 @@
#ifndef _KERNEL_PAGING_H
#define _KERNEL_PAGING_H
extern void load_page_dir(unsigned int*);
extern void load_page_dir(uint32_t*);
extern void enable_paging();
#endif

View File

@ -0,0 +1,51 @@
#ifndef _KERNEL_PIC_H
#define _KERNEL_PIC_H
#include <stdint.h>
#define PIC1 0x20
#define PIC1_COMMAND PIC1
#define PIC1_DATA PIC1+1
#define PIC1_OFFSET 0x20
#define PIC2 0xA0
#define PIC2_COMMAND PIC2
#define PIC2_DATA PIC2+1
#define PIC2_OFFSET 0x28
#define PIC_EOI 0x20
#define ICW1_ICW4 0x01 // ICW4 (not) needed
#define ICW1_SINGLE 0X02 // Single (cascade) mode
#define ICW1_INTERVAL4 0x04 // Call address interval 4 (8)
#define ICW1_LEVEL 0x08 // Level triggered (edge) mode
#define ICW1_INIT 0x10 // Initialization - required
#define ICW4_8086 0x01 // 8086/88 (MCS-80/85) mode
#define ICW4_AUTO 0x02 // Auto (normal) EDI
#define ICW4_BUF_SLAVE 0x08 // Buffered mode/slave
#define ICW4_BUF_MASTER 0x0C // Buffered mode/master
#define ICW4_SFNM 0x10 // Special fully nested (not)
static inline void outb(uint16_t port, uint8_t val) {
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline void io_wait() {
outb(0x80, 0);
}
static inline void pic_eoi(uint8_t irq) {
if (irq >= 8) {
outb(PIC2_COMMAND, PIC_EOI);
}
outb(PIC1_COMMAND, PIC_EOI);
}
#endif

View File

@ -1,8 +0,0 @@
#include <stdio.h>
__attribute__((noreturn))
void exception_handler(void);
void exception_handler() {
printf("Kernel exception!\n");
__asm__ volatile ("cli; hlt");
}

View File

@ -31,13 +31,11 @@ void paging_init() {
void kernel_main(void) {
paging_init();
terminal_initialize();
printf("Hello, kernel World!\n");
printf("String test: %s\n", "HELLOOOOO");
printf("Float test: %.10f\n", 0.123456789);
printf("Int test: %d\n", 747474);
printf("Hex test: 0x%x\n", 0xDEADBEEF);
printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2);
asm("int $0");
asm("cli");
asm("cli; hlt");
}

View File

@ -1,6 +1,7 @@
#include <ssp.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#if UINT32_MAX == UINTPTR_MAX
#define STACK_CHK_GUARD 0x74316974
@ -17,4 +18,6 @@ void __stack_chk_fail(void){
#elif __is_rockos_kernel
panic("Stack smashing detected!");
#endif
printf("Stack smashing detected!");
for(;;);
}

View File

@ -190,11 +190,13 @@ int vprintf(const char* format, va_list list) {
switch (specifier) {
case 'X':
base = 16;
// fall through
case 'x':
base = base == 10 ? 17 : base;
if (altForm) {
displayString("0x", &chars);
}
// fall through
case 'u':
{
switch (length) {
@ -383,7 +385,7 @@ int vprintf(const char* format, va_list list) {
case 'e':
case 'E':
emode = true;
// fall through
case 'f':
case 'F':
case 'g':