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 .global _start
.type _start, @function .type _start, @function
_start: _start:
movl $stack_top, %esp
cli cli
call gdt_init # initialize the GDT call gdt_init # initialize the GDT
movl $stack_top, %esp
call terminal_initialize
call idt_init # initialize the IDT call idt_init # initialize the IDT
call PIC_remap
call kernel_main # transfer control to main kernel call kernel_main # transfer control to main kernel
# Hang if kernel_main unexpectedly returns # Hang if kernel_main unexpectedly returns
1: hlt 1: hlt

View File

@ -41,8 +41,18 @@ void gdt_init(void) {
gdt_fill(GDT+i, rows+i); gdt_fill(GDT+i, rows+i);
} }
gp.base = &GDT; gp.base = (uintptr_t)&GDT[0];
gp.limit = (GDT_ENTRIES * sizeof(gdt_entry)) - 1; 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 <kernel/idt.h>
#include <stdio.h> #include <stdio.h>
__attribute__((interrupt)) void hello_interrupt(idt_frame* frame) { __attribute__((interrupt)) void int_handler(void* frame, unsigned int number) {
printf("Hello from interrupt!\n"); unsigned int err = 0;
printf("ip=0x%x, cs=0x%x, flags=0b%b\n", frame->ip, frame->cs, frame->flags); 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) { switch(number) {
printf("Hello from error interrupt!\n"); case 0:
printf("ip=0x%x, cs=0x%x, flags=0b%b, err=0x%x\n", frame->ip, frame->cs, frame->flags, frame->err); printf("#DE Divide Error!\n");
asm volatile("cli; hlt"); 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) { if(err){
target->isr_low = source->offset & 0xFFFF; printf("err: 0x%X, ip: 0x%X, cs: 0x%X, flags: 0x%X, sp: 0x%X, ss: 0x%X\n",
target->isr_high = (source->offset >> 16) & 0xFFFF; idt_ptr_e->err, idt_ptr_e->ip, idt_ptr_e->cs, idt_ptr_e->flags, idt_ptr_e->sp, idt_ptr_e->ss);
target->kernel_cs = source->segment; } else {
target->flags = 0x80; printf("ip: 0x%X, cs: 0x%X, flags: 0x%X, sp: 0x%X, ss: 0x%X\n",
target->flags |= (source->ring & 0x3) << 5; idt_ptr->ip, idt_ptr->cs, idt_ptr->flags, idt_ptr->sp, idt_ptr->ss);
target->flags |= (source->gate & 0xF); }
target->reserved = 0; return;
} }
__attribute__((aligned(0x10))) idt_entry_t IDT[IDT_ROWS]; #define INT_WRAPPER(NUM) __attribute__((interrupt)) void int##NUM##_wrapper(void* frame) { \
idtr_t idtptr; 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) { void idt_init(void) {
idt rows[] = { idtptr.base = (uintptr_t)&idt[0];
{(uint32_t)hello_interrupt, 0x08, INT_GATE32, 0}, idtptr.limit = (uint16_t)sizeof(idt_entry_t) * IDT_MAX_DESCRIPTORS - 1;
{(uint32_t)hello_interrupt_err, 0x08, INT_GATE32, 0},
};
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) { __asm__ volatile("lidt %0" : : "m"(idtptr)); // Load new IDT
idt_fill_row(IDT+i, rows+i); __asm__ volatile("sti"); // Set interrupt flag
}
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();
} }

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)/boot/boot.o \
$(ARCHDIR)/vga/tty.o \ $(ARCHDIR)/vga/tty.o \
$(ARCHDIR)/boot/gdt.o \ $(ARCHDIR)/boot/gdt.o \
$(ARCHDIR)/boot/gdt_load.o \
$(ARCHDIR)/paging/paging.o \ $(ARCHDIR)/paging/paging.o \
$(ARCHDIR)/boot/idt.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_fill(gdt_entry*, gdt*);
void gdt_init(void); void gdt_init(void);
extern void gdt_load();
extern uint32_t TSS[32]; extern uint32_t TSS[32];
extern gdt_entry GDT[GDT_ENTRIES]; extern gdt_entry GDT[GDT_ENTRIES];

View File

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

View File

@ -1,7 +1,7 @@
#ifndef _KERNEL_PAGING_H #ifndef _KERNEL_PAGING_H
#define _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(); extern void enable_paging();
#endif #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) { void kernel_main(void) {
paging_init(); paging_init();
terminal_initialize();
printf("Hello, kernel World!\n"); printf("Hello, kernel World!\n");
printf("String test: %s\n", "HELLOOOOO"); printf("String test: %s\n", "HELLOOOOO");
printf("Float test: %.10f\n", 0.123456789); printf("Float test: %.10f\n", 0.123456789);
printf("Int test: %d\n", 747474); printf("Int test: %d\n", 747474);
printf("Hex test: 0x%x\n", 0xDEADBEEF); printf("Hex test: 0x%x\n", 0xDEADBEEF);
printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2); printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2);
asm("int $0"); asm("cli; hlt");
asm("cli");
} }

View File

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

View File

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