Compare commits
2 Commits
64a3f6ee0d
...
8b2d35594d
Author | SHA1 | Date | |
---|---|---|---|
8b2d35594d | |||
a3bbffcfd9 |
@ -30,3 +30,12 @@ void init_gdt();
|
|||||||
#define GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA 0b00000010
|
#define GDT_ACCESS_RW_READABLE_FOR_CODE_WRITABLE_FOR_DATA 0b00000010
|
||||||
#define GDT_ACCESS_A_ACCESSED 0b00000001
|
#define GDT_ACCESS_A_ACCESSED 0b00000001
|
||||||
#define GDT_ACCESS_A_NOT_ACCESSED 0b00000000
|
#define GDT_ACCESS_A_NOT_ACCESSED 0b00000000
|
||||||
|
|
||||||
|
extern uint8_t gdt_entries[GDT_SIZE * 8];
|
||||||
|
|
||||||
|
#define GDT_OFFSET_KERNEL_CODE 0x08
|
||||||
|
#define GDT_OFFSET_KERNEL_DATA 0x10
|
||||||
|
#define GDT_OFFSET_KERNEL_STACK 0x18
|
||||||
|
#define GDT_OFFSET_USER_CODE 0x20
|
||||||
|
#define GDT_OFFSET_USER_DATA 0x28
|
||||||
|
#define GDT_OFFSET_USER_STACK 0x30
|
||||||
|
@ -6,4 +6,15 @@ struct idt_descriptor {
|
|||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct idt_entry {
|
||||||
|
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||||
|
uint16_t kernel_cs; // The GDT segment selector that the CPU will load
|
||||||
|
// into CS before calling the ISR
|
||||||
|
uint8_t reserved; // Set to zero
|
||||||
|
uint8_t attributes; // Type and attributes; see the IDT page
|
||||||
|
uint16_t isr_high; // The higher 16 bits of the ISR's address
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
#define IDT_SIZE 256
|
#define IDT_SIZE 256
|
||||||
|
|
||||||
|
void init_idt(void);
|
@ -42,7 +42,7 @@ void init_gdt(void)
|
|||||||
set_gdt_entry_value(gdt_entries + 0x00, 0, 0, 0, 0); // Null segment
|
set_gdt_entry_value(gdt_entries + 0x00, 0, 0, 0, 0); // Null segment
|
||||||
|
|
||||||
set_gdt_entry_value(
|
set_gdt_entry_value(
|
||||||
gdt_entries + 0x08, 0, 0xFFFFF,
|
gdt_entries + GDT_OFFSET_KERNEL_CODE, 0, 0xFFFFF,
|
||||||
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
|
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
|
||||||
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE |
|
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE |
|
||||||
GDT_ACCESS_DC_NOT_CONFORM |
|
GDT_ACCESS_DC_NOT_CONFORM |
|
||||||
@ -50,7 +50,7 @@ void init_gdt(void)
|
|||||||
GDT_ACCESS_A_ACCESSED,
|
GDT_ACCESS_A_ACCESSED,
|
||||||
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel code
|
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel code
|
||||||
set_gdt_entry_value(
|
set_gdt_entry_value(
|
||||||
gdt_entries + 0x10, 0, 0xFFFFF,
|
gdt_entries + GDT_OFFSET_KERNEL_DATA, 0, 0xFFFFF,
|
||||||
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
|
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
|
||||||
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
|
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
|
||||||
GDT_ACCESS_DC_NOT_CONFORM |
|
GDT_ACCESS_DC_NOT_CONFORM |
|
||||||
@ -58,7 +58,7 @@ void init_gdt(void)
|
|||||||
GDT_ACCESS_A_ACCESSED,
|
GDT_ACCESS_A_ACCESSED,
|
||||||
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel data
|
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel data
|
||||||
set_gdt_entry_value(
|
set_gdt_entry_value(
|
||||||
gdt_entries + 0x18, 0, 0xFFFFF,
|
gdt_entries + GDT_OFFSET_KERNEL_STACK, 0, 0xFFFFF,
|
||||||
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
|
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_KERNEL_MODE |
|
||||||
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
|
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
|
||||||
GDT_ACCESS_DC_CONFORM |
|
GDT_ACCESS_DC_CONFORM |
|
||||||
@ -67,7 +67,7 @@ void init_gdt(void)
|
|||||||
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel stack
|
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // Kernel stack
|
||||||
|
|
||||||
set_gdt_entry_value(
|
set_gdt_entry_value(
|
||||||
gdt_entries + 0x20, 0, 0xFFFFF,
|
gdt_entries + GDT_OFFSET_USER_CODE, 0, 0xFFFFF,
|
||||||
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
|
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
|
||||||
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE |
|
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_EXECUTABLE |
|
||||||
GDT_ACCESS_DC_CONFORM |
|
GDT_ACCESS_DC_CONFORM |
|
||||||
@ -75,7 +75,7 @@ void init_gdt(void)
|
|||||||
GDT_ACCESS_A_ACCESSED,
|
GDT_ACCESS_A_ACCESSED,
|
||||||
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User code
|
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User code
|
||||||
set_gdt_entry_value(
|
set_gdt_entry_value(
|
||||||
gdt_entries + 0x28, 0, 0xFFFFF,
|
gdt_entries + GDT_OFFSET_USER_DATA, 0, 0xFFFFF,
|
||||||
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
|
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
|
||||||
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
|
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
|
||||||
GDT_ACCESS_DC_NOT_CONFORM |
|
GDT_ACCESS_DC_NOT_CONFORM |
|
||||||
@ -83,7 +83,7 @@ void init_gdt(void)
|
|||||||
GDT_ACCESS_A_ACCESSED,
|
GDT_ACCESS_A_ACCESSED,
|
||||||
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User data
|
GDT_FLAG_32BIT_MODE | GDT_FLAG_PAGE_MODE); // User data
|
||||||
set_gdt_entry_value(
|
set_gdt_entry_value(
|
||||||
gdt_entries + 0x30, 0, 0xFFFFF,
|
gdt_entries + GDT_OFFSET_USER_STACK, 0, 0xFFFFF,
|
||||||
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
|
GDT_ACCESS_P_VALID | GDT_ACCESS_DPL_USER_MODE |
|
||||||
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
|
GDT_ACCESS_S_CODE_OR_DATA | GDT_ACCESS_E_NOT_EXECUTABLE |
|
||||||
GDT_ACCESS_DC_CONFORM |
|
GDT_ACCESS_DC_CONFORM |
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void exception_handler(void);
|
||||||
|
|
||||||
void exception_handler(void)
|
void exception_handler(void)
|
||||||
{
|
{
|
||||||
int8_t index = -1;
|
int8_t index = -1;
|
||||||
|
@ -1,36 +1,59 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "gdt.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
|
|
||||||
uint16_t idt_entries[IDT_SIZE * 4];
|
extern void *isr_stub_table[];
|
||||||
struct idt_descriptor idtr;
|
|
||||||
|
|
||||||
|
__attribute__((aligned(0x10))) static struct idt_entry idt_entries[IDT_SIZE];
|
||||||
|
static struct idt_descriptor idtr;
|
||||||
|
/*
|
||||||
static void set_idt_entry_value(uint16_t *target, uint32_t offset,
|
static void set_idt_entry_value(uint16_t *target, uint32_t offset,
|
||||||
uint16_t selector, uint8_t dpl,
|
uint16_t selector, uint8_t dpl,
|
||||||
uint8_t gate_type)
|
uint8_t gate_type)
|
||||||
{
|
{
|
||||||
// Encode the offset
|
// Encode the offset
|
||||||
target[0] = offset & 0xFFFF;
|
target[0] = offset & 0xFFFF; // Low 16 bits
|
||||||
target[3] = (offset >> 16) & 0xFFFF;
|
target[3] = (offset >> 16) & 0xFFFF; // High 16 bits
|
||||||
|
|
||||||
// Encode the presence
|
// Encode the presence (bit 15)
|
||||||
target[1] |= 1 << 15;
|
target[1] |= 1 << 15;
|
||||||
|
|
||||||
// Encode the CPU Privilege Levels
|
// Encode the CPU Privilege Levels (DPL)
|
||||||
target[1] = (0b11 << 13) & dpl;
|
target[1] &= ~(0b11 << 13); // Clear previous DPL
|
||||||
|
target[1] |= (dpl & 0b11) << 13; // Set new DPL
|
||||||
|
|
||||||
|
// Clear bit 12 (always 0 for interrupts)
|
||||||
target[1] &= ~(1 << 12);
|
target[1] &= ~(1 << 12);
|
||||||
|
|
||||||
// Encode Gate Type
|
// Encode Gate Type
|
||||||
target[1] |= gate_type & 0x0F00;
|
target[1] &= ~0x0F00; // Clear previous gate type
|
||||||
|
target[1] |= (gate_type & 0x0F) << 8; // Set new gate type
|
||||||
|
|
||||||
// Encode selector
|
// Encode selector
|
||||||
target[2] = selector;
|
target[2] = selector;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void idt_set_descriptor(uint8_t index, void *isr, uint8_t flags)
|
||||||
|
{
|
||||||
|
struct idt_entry *descriptor = &idt_entries[index];
|
||||||
|
|
||||||
|
descriptor->isr_low = (uint32_t)isr & 0xFFFF;
|
||||||
|
descriptor->kernel_cs = GDT_OFFSET_KERNEL_CODE;
|
||||||
|
descriptor->attributes = flags;
|
||||||
|
descriptor->isr_high = (uint32_t)isr >> 16;
|
||||||
|
descriptor->reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_idt(void)
|
void init_idt(void)
|
||||||
{
|
{
|
||||||
idtr.size = 8 * IDT_SIZE - 1;
|
idtr.offset = (uintptr_t)&idt_entries[0];
|
||||||
idtr.offset = (uint32_t)&idt_entries;
|
idtr.size = (uint16_t)sizeof(struct idt_entry) * IDT_SIZE - 1;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 32; i++)
|
||||||
|
idt_set_descriptor(i, isr_stub_table[i], 0x8E);
|
||||||
|
|
||||||
|
__asm__ volatile("lidt %0" : : "m"(idtr));
|
||||||
|
__asm__ volatile("sti");
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,14 @@
|
|||||||
|
|
||||||
.macro isr_err_stub nb
|
.macro isr_err_stub nb
|
||||||
isr_stub_\nb:
|
isr_stub_\nb:
|
||||||
|
movb bl, \nb
|
||||||
call exception_handler
|
call exception_handler
|
||||||
iret
|
iret
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro isr_no_err_stub nb
|
.macro isr_no_err_stub nb
|
||||||
isr_stub_\nb:
|
isr_stub_\nb:
|
||||||
|
movb bl, \nb
|
||||||
call exception_handler
|
call exception_handler
|
||||||
iret
|
iret
|
||||||
.endm
|
.endm
|
||||||
|
10
src/kernel.c
10
src/kernel.c
@ -1,5 +1,6 @@
|
|||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
|
#include "idt.h"
|
||||||
#include "kpanic.h"
|
#include "kpanic.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@ -27,13 +28,6 @@ void kernel_main(void)
|
|||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
init_gdt();
|
init_gdt();
|
||||||
init_memory();
|
init_memory();
|
||||||
kprintf(KERN_CRIT "KERN_CRIT\n");
|
init_idt();
|
||||||
kprintf(KERN_ALERT "KERN_ALERT\n");
|
|
||||||
kprintf(KERN_WARNING "KERN_WARNING\n");
|
|
||||||
kprintf(KERN_NOTICE "KERN_NOTICE\n");
|
|
||||||
kprintf(KERN_INFO "KERN_INFO\n");
|
|
||||||
kprintf(KERN_DEBUG "KERN_DEBUG\n");
|
|
||||||
void *ptr = vmalloc(100);
|
|
||||||
kprintf("%d\n", ksize(ptr));
|
|
||||||
shell_init();
|
shell_init();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user