Paging, interrupts

This commit is contained in:
Furkan Mudanyali 2022-07-18 22:37:43 +03:00
parent 2859788682
commit b987beca85
13 changed files with 201 additions and 17 deletions

View File

@ -13,7 +13,7 @@ EXEC_PREFIX?=$(PREFIX)
BOOTDIR?=$(EXEC_PREFIX)/boot
INCLUDEDIR?=$(PREFIX)/include
CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra -fstack-protector
CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra -fstack-protector-strong -mgeneral-regs-only -mno-red-zone
CPPFLAGS:=$(CPPFLAGS) -D__is_kernel -Iinclude
LDFLAGS:=$(LDFLAGS)
LIBS:=$(LIBS) -nostdlib -lk -lgcc

View File

@ -26,7 +26,8 @@ stack_top:
_start:
movl $stack_top, %esp
cli
call gdt_init # call global constructors
call gdt_init # initialize the GDT
call idt_init # initialize the IDT
call kernel_main # transfer control to main kernel
# Hang if kernel_main unexpectedly returns
1: hlt

View File

@ -41,7 +41,7 @@ void gdt_init(void) {
gdt_fill(GDT+i, rows+i);
}
gp.base = (void*) GDT;
gp.base = &GDT;
gp.limit = (GDT_ENTRIES * sizeof(gdt_entry)) - 1;
gdt_load();

View File

@ -0,0 +1,49 @@
#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 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");
}
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;
}
__attribute__((aligned(0x10))) idt_entry_t IDT[IDT_ROWS];
idtr_t idtptr;
void idt_init(void) {
idt rows[] = {
{(uint32_t)hello_interrupt, 0x08, INT_GATE32, 0},
{(uint32_t)hello_interrupt_err, 0x08, INT_GATE32, 0},
};
int valid_rows = sizeof(rows) / sizeof(idt_entry_t);
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();
}

View File

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

View File

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

View File

@ -0,0 +1,22 @@
.text
.globl load_page_dir
load_page_dir:
push %ebp
mov %esp, %ebp
mov 8(%esp), %eax
mov %eax, %cr3
mov %ebp, %esp
pop %ebp
ret
.text
.globl enable_paging
enable_paging:
push %ebp
mov %esp, %ebp
mov %cr0, %eax
or $0x80000000, %eax
mov %eax, %cr0
mov %ebp, %esp
pop %ebp
ret

View File

@ -41,14 +41,20 @@ void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) {
void terminal_putchar(char c) {
unsigned char uc = c;
if (uc == '\n') {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT) {
terminal_row = 0;
}
} else {
terminal_putentryat(uc, terminal_color, terminal_column, terminal_row);
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT) {
terminal_row = 0;
}
}
}
}
void terminal_write(const char* data, size_t size) {

View File

@ -1,5 +1,5 @@
/**
* Referenced from https://tendstofortytwo/clay
* Referenced from https://github.com/tendstofortytwo/clay
* kernel/kernel.c
*/
@ -13,7 +13,7 @@
typedef struct {
uint16_t limit;
uint32_t base;
}__attribute__((packed)) gdt_ptr;
} __attribute__((packed)) gdt_ptr;
typedef struct {
uint16_t limit_lo;
@ -22,14 +22,14 @@ typedef struct {
uint8_t access;
uint8_t limit_hi_flags;
uint8_t base_hi;
}__attribute__((packed)) gdt_entry;
} __attribute__((packed)) gdt_entry;
typedef struct {
uint32_t base;
uint32_t limit;
uint8_t access;
uint8_t flags;
}__attribute__((packed)) gdt;
} __attribute__((packed)) gdt;
void gdt_fill(gdt_entry*, gdt*);
void gdt_init(void);

View File

@ -0,0 +1,53 @@
#ifndef _KERNEL_IDT_H
#define _KERNEL_IDT_H
#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;
typedef struct {
uint16_t isr_low; // lower 16-bits of ISR address
uint16_t kernel_cs; // The GDT selector that the CPU will load into CS before calling ISR
uint8_t reserved; // set to zero
uint8_t flags; // Type and attributes
uint16_t isr_high; // Higher 16-bits of ISR address
} __attribute__((packed)) idt_entry_t;
typedef struct {
uint32_t offset;
uint16_t segment;
uint8_t gate;
uint8_t ring;
} idt;
typedef struct {
uint32_t ip;
uint32_t cs;
uint32_t flags;
uint32_t sp;
uint32_t ss;
} __attribute__((packed)) idt_frame;
typedef struct {
uint32_t err;
uint32_t ip;
uint32_t cs;
uint32_t flags;
uint32_t sp;
uint32_t ss;
} __attribute__((packed)) idt_frame_err;
extern void idt_load();
extern idtr_t idtptr;
#endif

View File

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

View File

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

View File

@ -2,13 +2,42 @@
#include <kernel/tty.h>
#include <kernel/gdt.h>
#include <kernel/paging.h>
#define PAGE_ENTRIES 1024
#define PAGE_SIZE 4 * PAGE_ENTRIES
void paging_init() {
uint32_t page_dir[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
for(int i = 0; i < PAGE_ENTRIES; i++) {
// Supervisor: only kernel-mode can access
// Write Enabled: Can be both read and written to
// Not Present: Page table not present
page_dir[i] = 0x00000002;
}
uint32_t first_page_table[PAGE_ENTRIES] __attribute__((aligned(PAGE_SIZE)));
for(unsigned int i = 0; i < PAGE_ENTRIES; i++) {
// As the address is page aligned, it will leave 12 bits zeroed,
// which are used by the attributes.
first_page_table[i] = (i * 0x1000) | 3; // attr: supervisor, r/w, present
}
page_dir[0] = ((unsigned int)first_page_table) | 3; //attr: supervisor, r/w, present
load_page_dir(page_dir);
enable_paging();
}
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("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");
}