Paging, interrupts
This commit is contained in:
parent
2859788682
commit
b987beca85
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
49
kernel/arch/i386/boot/idt.c
Normal file
49
kernel/arch/i386/boot/idt.c
Normal 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();
|
||||
}
|
6
kernel/arch/i386/boot/idt_load.S
Normal file
6
kernel/arch/i386/boot/idt_load.S
Normal file
@ -0,0 +1,6 @@
|
||||
.global idt_load
|
||||
.type idt_load, @function
|
||||
idt_load:
|
||||
lidt (idtptr)
|
||||
sti
|
||||
ret
|
@ -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
|
22
kernel/arch/i386/paging/paging.S
Normal file
22
kernel/arch/i386/paging/paging.S
Normal 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
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
53
kernel/include/kernel/idt.h
Normal file
53
kernel/include/kernel/idt.h
Normal 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
|
7
kernel/include/kernel/paging.h
Normal file
7
kernel/include/kernel/paging.h
Normal 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
|
8
kernel/kernel/exception.c
Normal file
8
kernel/kernel/exception.c
Normal 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");
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
Reference in New Issue
Block a user