Paging, interrupts
This commit is contained in:
parent
2859788682
commit
b987beca85
@ -13,7 +13,7 @@ EXEC_PREFIX?=$(PREFIX)
|
|||||||
BOOTDIR?=$(EXEC_PREFIX)/boot
|
BOOTDIR?=$(EXEC_PREFIX)/boot
|
||||||
INCLUDEDIR?=$(PREFIX)/include
|
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
|
CPPFLAGS:=$(CPPFLAGS) -D__is_kernel -Iinclude
|
||||||
LDFLAGS:=$(LDFLAGS)
|
LDFLAGS:=$(LDFLAGS)
|
||||||
LIBS:=$(LIBS) -nostdlib -lk -lgcc
|
LIBS:=$(LIBS) -nostdlib -lk -lgcc
|
||||||
|
@ -26,8 +26,9 @@ stack_top:
|
|||||||
_start:
|
_start:
|
||||||
movl $stack_top, %esp
|
movl $stack_top, %esp
|
||||||
cli
|
cli
|
||||||
call gdt_init # call global constructors
|
call gdt_init # initialize the GDT
|
||||||
call kernel_main # transfer control to main kernel
|
call idt_init # initialize the IDT
|
||||||
|
call kernel_main # transfer control to main kernel
|
||||||
# Hang if kernel_main unexpectedly returns
|
# Hang if kernel_main unexpectedly returns
|
||||||
1: hlt
|
1: hlt
|
||||||
jmp 1b
|
jmp 1b
|
||||||
|
@ -41,7 +41,7 @@ void gdt_init(void) {
|
|||||||
gdt_fill(GDT+i, rows+i);
|
gdt_fill(GDT+i, rows+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
gp.base = (void*) GDT;
|
gp.base = &GDT;
|
||||||
gp.limit = (GDT_ENTRIES * sizeof(gdt_entry)) - 1;
|
gp.limit = (GDT_ENTRIES * sizeof(gdt_entry)) - 1;
|
||||||
|
|
||||||
gdt_load();
|
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)/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)/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,13 +41,19 @@ void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) {
|
|||||||
void terminal_putchar(char c) {
|
void terminal_putchar(char c) {
|
||||||
unsigned char uc = c;
|
unsigned char uc = c;
|
||||||
|
|
||||||
terminal_putentryat(uc, terminal_color, terminal_column, terminal_row);
|
if (uc == '\n') {
|
||||||
|
|
||||||
if (++terminal_column == VGA_WIDTH) {
|
|
||||||
terminal_column = 0;
|
terminal_column = 0;
|
||||||
if (++terminal_row == VGA_HEIGHT) {
|
if (++terminal_row == VGA_HEIGHT) {
|
||||||
terminal_row = 0;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Referenced from https://tendstofortytwo/clay
|
* Referenced from https://github.com/tendstofortytwo/clay
|
||||||
* kernel/kernel.c
|
* kernel/kernel.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -13,7 +13,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t limit;
|
uint16_t limit;
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
}__attribute__((packed)) gdt_ptr;
|
} __attribute__((packed)) gdt_ptr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t limit_lo;
|
uint16_t limit_lo;
|
||||||
@ -22,14 +22,14 @@ typedef struct {
|
|||||||
uint8_t access;
|
uint8_t access;
|
||||||
uint8_t limit_hi_flags;
|
uint8_t limit_hi_flags;
|
||||||
uint8_t base_hi;
|
uint8_t base_hi;
|
||||||
}__attribute__((packed)) gdt_entry;
|
} __attribute__((packed)) gdt_entry;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
uint32_t limit;
|
uint32_t limit;
|
||||||
uint8_t access;
|
uint8_t access;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
}__attribute__((packed)) gdt;
|
} __attribute__((packed)) gdt;
|
||||||
|
|
||||||
void gdt_fill(gdt_entry*, gdt*);
|
void gdt_fill(gdt_entry*, gdt*);
|
||||||
void gdt_init(void);
|
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/tty.h>
|
||||||
#include <kernel/gdt.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) {
|
void kernel_main(void) {
|
||||||
|
paging_init();
|
||||||
terminal_initialize();
|
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");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user