GDT fix for GRUB, IDT revamp, initialize PIC
This commit is contained in:
parent
b987beca85
commit
4b75737ad0
@ -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
|
||||
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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__((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");
|
||||
#define INT_WRAPPER(NUM) __attribute__((interrupt)) void int##NUM##_wrapper(void* frame) { \
|
||||
int_handler(frame, NUM); \
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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)
|
||||
|
||||
__attribute__((aligned(0x10))) idt_entry_t IDT[IDT_ROWS];
|
||||
idtr_t idtptr;
|
||||
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
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
.global idt_load
|
||||
.type idt_load, @function
|
||||
idt_load:
|
||||
lidt (idtptr)
|
||||
sti
|
||||
ret
|
30
kernel/arch/i386/boot/pic.c
Normal file
30
kernel/arch/i386/boot/pic.c
Normal 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);
|
||||
}
|
@ -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
|
@ -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];
|
||||
|
@ -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
|
@ -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
|
51
kernel/include/kernel/pic.h
Normal file
51
kernel/include/kernel/pic.h
Normal 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
|
@ -1,8 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
__attribute__((noreturn))
|
||||
void exception_handler(void);
|
||||
void exception_handler() {
|
||||
printf("Kernel exception!\n");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
@ -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(;;);
|
||||
}
|
@ -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':
|
||||
|
Reference in New Issue
Block a user