Added sequence to remap PIC
Wrote GDT code in C Added routines to initialize GDT and IDT
This commit is contained in:
@@ -1,12 +1,34 @@
|
|||||||
#include "mmgr.h"
|
#include "mmgr.h"
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
#include "msr.h"
|
#include "msr.h"
|
||||||
|
#include "stdio.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
extern int _kernel_end;
|
extern int _kernel_end;
|
||||||
|
|
||||||
void apic_enable(struct page_stact_t *page_stack)
|
void apic_enable(struct page_stact_t *page_stack)
|
||||||
{
|
{
|
||||||
|
// Remap and mask 8259 PIC
|
||||||
|
asm volatile(
|
||||||
|
"mov $0x11, %%al;"
|
||||||
|
"outb %%al, $0x20;"
|
||||||
|
"outb %%al, $0xA0;"
|
||||||
|
"mov $0x20, %%al;"
|
||||||
|
"outb %%al, $0x21;"
|
||||||
|
"mov $0x28, %%al;"
|
||||||
|
"outb %%al, $0xA1;"
|
||||||
|
"mov $4, %%al;"
|
||||||
|
"outb %%al, $0x21;"
|
||||||
|
"mov $2, %%al;"
|
||||||
|
"outb %%al, $0xA1;"
|
||||||
|
"mov $0x01, %%al;"
|
||||||
|
"outb %%al, $0x21;"
|
||||||
|
"outb %%al, $0xA1;"
|
||||||
|
"mov $0xFF, %%al;"
|
||||||
|
"outb %%al, $0xA1;"
|
||||||
|
"outb %%al, $0x21;"
|
||||||
|
::: "al"
|
||||||
|
);
|
||||||
struct msr_apic_base_t msr;
|
struct msr_apic_base_t msr;
|
||||||
read_msr(MSR_APIC_BASE, (uint64_t*)&msr);
|
read_msr(MSR_APIC_BASE, (uint64_t*)&msr);
|
||||||
map_page(page_stack, &_kernel_end, msr.apic_base << 12, 0);
|
map_page(page_stack, &_kernel_end, msr.apic_base << 12, 0);
|
||||||
|
|||||||
@@ -93,23 +93,6 @@ _multibootInfoTagEnd:
|
|||||||
.long 8
|
.long 8
|
||||||
|
|
||||||
_multibootHeaderEnd:
|
_multibootHeaderEnd:
|
||||||
|
|
||||||
.section .rodata
|
|
||||||
|
|
||||||
gdt:
|
|
||||||
.long 0, 0
|
|
||||||
.short 0xFFFF
|
|
||||||
.short 0x0000
|
|
||||||
.short 0x9A00
|
|
||||||
.short 0x00CF
|
|
||||||
.short 0xFFFF
|
|
||||||
.short 0x0000
|
|
||||||
.short 0x9200
|
|
||||||
.short 0x00CF
|
|
||||||
|
|
||||||
gdt_info:
|
|
||||||
.short 23
|
|
||||||
.long gdt
|
|
||||||
|
|
||||||
.section .bss
|
.section .bss
|
||||||
|
|
||||||
@@ -170,7 +153,7 @@ _start:
|
|||||||
push %eax
|
push %eax
|
||||||
|
|
||||||
# Load physical address of startPaging()
|
# Load physical address of startPaging()
|
||||||
mov $startPaging, %eax
|
mov $start_paging, %eax
|
||||||
sub $BASE_DIFF, %eax
|
sub $BASE_DIFF, %eax
|
||||||
|
|
||||||
# Initialize paging
|
# Initialize paging
|
||||||
@@ -180,8 +163,6 @@ _start:
|
|||||||
lea 1f, %eax
|
lea 1f, %eax
|
||||||
jmp *%eax
|
jmp *%eax
|
||||||
1:
|
1:
|
||||||
# Delete PDE corresponding to identity map. We shouldn't need it anymore.
|
|
||||||
movl $0, (_tempIdentityMap)
|
|
||||||
|
|
||||||
# Flush TLB
|
# Flush TLB
|
||||||
mov %cr3, %eax
|
mov %cr3, %eax
|
||||||
@@ -190,19 +171,6 @@ _start:
|
|||||||
# Initialize stack in virtual memory
|
# Initialize stack in virtual memory
|
||||||
mov $stackTop, %esp
|
mov $stackTop, %esp
|
||||||
|
|
||||||
# Load GPT
|
|
||||||
lgdt gdt_info
|
|
||||||
|
|
||||||
# Load segment registers
|
|
||||||
jmp $8, $.ldcs
|
|
||||||
.ldcs:
|
|
||||||
mov $16, %ax
|
|
||||||
mov %ax, %ds
|
|
||||||
mov %ax, %es
|
|
||||||
mov %ax, %gs
|
|
||||||
mov %ax, %fs
|
|
||||||
mov %ax, %ss
|
|
||||||
|
|
||||||
# Change EBX to point to the virtual address of the multiboot info
|
# Change EBX to point to the virtual address of the multiboot info
|
||||||
# If the new pointer is out-of-bounds, error
|
# If the new pointer is out-of-bounds, error
|
||||||
add $0xFF800000, %ebx
|
add $0xFF800000, %ebx
|
||||||
|
|||||||
@@ -1,14 +1,85 @@
|
|||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
|
#include "isr.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
struct idt_info_t
|
#define idt_size 256
|
||||||
|
#define gdt_size 6
|
||||||
|
|
||||||
|
enum segment_type_t
|
||||||
|
{
|
||||||
|
SEGMENT_KERNEL_CODE,
|
||||||
|
SEGMENT_KERNEL_DATA,
|
||||||
|
SEGMENT_USER_CODE,
|
||||||
|
SEGMENT_USER_DATA,
|
||||||
|
SEGMENT_TSS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gdt_entry_t
|
||||||
|
{
|
||||||
|
unsigned int limit_low : 16;
|
||||||
|
unsigned int base_low : 24;
|
||||||
|
unsigned int accessed : 1;
|
||||||
|
unsigned int read_write : 1;
|
||||||
|
unsigned int conforming_expand_down : 1;
|
||||||
|
unsigned int code : 1;
|
||||||
|
unsigned int code_data_segment : 1;
|
||||||
|
unsigned int dpl : 2;
|
||||||
|
unsigned int present : 1;
|
||||||
|
unsigned int limit_high : 4;
|
||||||
|
unsigned int available : 1;
|
||||||
|
unsigned int long_mode : 1;
|
||||||
|
unsigned int big : 1;
|
||||||
|
unsigned int gran : 1;
|
||||||
|
unsigned int base_high : 8;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct tss_t
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct interrupt_descriptor_t
|
||||||
|
{
|
||||||
|
uint16_t offset_1;
|
||||||
|
uint16_t selector;
|
||||||
|
uint16_t zero : 8;
|
||||||
|
uint16_t type : 4;
|
||||||
|
uint16_t storage : 1;
|
||||||
|
uint16_t dpl : 2;
|
||||||
|
uint16_t present : 1;
|
||||||
|
uint16_t offset_2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct descriptor_table_info_t
|
||||||
{
|
{
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
void *location;
|
void *location;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
void lidt(struct interrupt_descriptor_t *idt)
|
struct tss_t tss;
|
||||||
|
|
||||||
|
void load_gdt(struct gdt_entry_t *gdt)
|
||||||
{
|
{
|
||||||
struct idt_info_t idt_info;
|
struct descriptor_table_info_t gdt_info;
|
||||||
|
gdt_info.size = sizeof(struct gdt_entry_t) * 6 - 1;
|
||||||
|
gdt_info.location = (void *)gdt;
|
||||||
|
asm("lgdt (%0);"
|
||||||
|
"jmp $8, $.ldcs;"
|
||||||
|
".ldcs:;"
|
||||||
|
"mov $16, %%ax;"
|
||||||
|
"mov %%ax, %%ds;"
|
||||||
|
"mov %%ax, %%es;"
|
||||||
|
"mov %%ax, %%gs;"
|
||||||
|
"mov %%ax, %%fs;"
|
||||||
|
"mov %%ax, %%ss;"
|
||||||
|
:
|
||||||
|
: "r"(&gdt_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_idt(struct interrupt_descriptor_t *idt)
|
||||||
|
{
|
||||||
|
struct descriptor_table_info_t idt_info;
|
||||||
idt_info.size = sizeof(struct interrupt_descriptor_t) * 256 - 1;
|
idt_info.size = sizeof(struct interrupt_descriptor_t) * 256 - 1;
|
||||||
idt_info.location = (void *)idt;
|
idt_info.location = (void *)idt;
|
||||||
asm("lidt (%0)"
|
asm("lidt (%0)"
|
||||||
@@ -27,3 +98,104 @@ void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void
|
|||||||
descriptor->dpl = privilage;
|
descriptor->dpl = privilage;
|
||||||
descriptor->present = 1;
|
descriptor->present = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size_t limit, enum segment_type_t type)
|
||||||
|
{
|
||||||
|
descriptor->limit_low = limit;
|
||||||
|
descriptor->limit_high = (limit & (0xf << 16)) >> 16;
|
||||||
|
descriptor->base_low = base;
|
||||||
|
descriptor->base_high = (base & (0xff << 24)) >> 24;
|
||||||
|
descriptor->present = 1;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case SEGMENT_KERNEL_CODE:
|
||||||
|
descriptor->accessed = 0;
|
||||||
|
descriptor->read_write = 1;
|
||||||
|
descriptor->conforming_expand_down = 0;
|
||||||
|
descriptor->code = 1;
|
||||||
|
descriptor->code_data_segment = 1;
|
||||||
|
descriptor->dpl = 0;
|
||||||
|
descriptor->available = 0;
|
||||||
|
descriptor->long_mode = 0;
|
||||||
|
descriptor->big = 1;
|
||||||
|
descriptor->gran = 1;
|
||||||
|
break;
|
||||||
|
case SEGMENT_KERNEL_DATA:
|
||||||
|
descriptor->accessed = 0;
|
||||||
|
descriptor->read_write = 1;
|
||||||
|
descriptor->conforming_expand_down = 0;
|
||||||
|
descriptor->code = 0;
|
||||||
|
descriptor->code_data_segment = 1;
|
||||||
|
descriptor->dpl = 0;
|
||||||
|
descriptor->available = 0;
|
||||||
|
descriptor->long_mode = 0;
|
||||||
|
descriptor->big = 1;
|
||||||
|
descriptor->gran = 1;
|
||||||
|
break;
|
||||||
|
case SEGMENT_USER_CODE:
|
||||||
|
descriptor->accessed = 0;
|
||||||
|
descriptor->read_write = 1;
|
||||||
|
descriptor->conforming_expand_down = 0;
|
||||||
|
descriptor->code = 1;
|
||||||
|
descriptor->code_data_segment = 1;
|
||||||
|
descriptor->dpl = 3;
|
||||||
|
descriptor->available = 0;
|
||||||
|
descriptor->long_mode = 0;
|
||||||
|
descriptor->big = 1;
|
||||||
|
descriptor->gran = 1;
|
||||||
|
break;
|
||||||
|
case SEGMENT_USER_DATA:
|
||||||
|
descriptor->accessed = 0;
|
||||||
|
descriptor->read_write = 1;
|
||||||
|
descriptor->conforming_expand_down = 0;
|
||||||
|
descriptor->code = 0;
|
||||||
|
descriptor->code_data_segment = 1;
|
||||||
|
descriptor->dpl = 3;
|
||||||
|
descriptor->available = 0;
|
||||||
|
descriptor->long_mode = 0;
|
||||||
|
descriptor->big = 1;
|
||||||
|
descriptor->gran = 1;
|
||||||
|
break;
|
||||||
|
case SEGMENT_TSS:
|
||||||
|
descriptor->accessed = 1;
|
||||||
|
descriptor->read_write = 0;
|
||||||
|
descriptor->conforming_expand_down = 0;
|
||||||
|
descriptor->code = 1;
|
||||||
|
descriptor->code_data_segment = 0;
|
||||||
|
descriptor->dpl = 3;
|
||||||
|
descriptor->available = 0;
|
||||||
|
descriptor->long_mode = 0;
|
||||||
|
descriptor->big = 0;
|
||||||
|
descriptor->gran = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize_gdt()
|
||||||
|
{
|
||||||
|
static struct gdt_entry_t gdt[gdt_size];
|
||||||
|
memset(gdt, 0, sizeof(struct gdt_entry_t) * gdt_size);
|
||||||
|
create_segment_descriptor(&gdt[1], 0, 0xFFFFF, SEGMENT_KERNEL_CODE);
|
||||||
|
create_segment_descriptor(&gdt[2], 0, 0xFFFFF, SEGMENT_KERNEL_DATA);
|
||||||
|
create_segment_descriptor(&gdt[3], 0, 0xFFFFF, SEGMENT_USER_CODE);
|
||||||
|
create_segment_descriptor(&gdt[4], 0, 0xFFFFF, SEGMENT_USER_DATA);
|
||||||
|
//create_segment_descriptor(&gdt[5], (size_t)&tss, sizeof(struct tss_t), SEGMENT_TSS);
|
||||||
|
load_gdt(gdt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize_idt()
|
||||||
|
{
|
||||||
|
static struct interrupt_descriptor_t idt[idt_size];
|
||||||
|
memset(idt, 0, sizeof(struct interrupt_descriptor_t) * idt_size);
|
||||||
|
for(int i = 0; i < idt_size; i++)
|
||||||
|
{
|
||||||
|
create_interrupt_descriptor(&idt[i], (void*)isr_generic, INTERRPUT_INT32, 0);
|
||||||
|
}
|
||||||
|
create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0);
|
||||||
|
create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0);
|
||||||
|
create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0);
|
||||||
|
create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0);
|
||||||
|
create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0);
|
||||||
|
create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0);
|
||||||
|
create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0);
|
||||||
|
load_idt(idt);
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,18 +38,6 @@ enum isr_type_t
|
|||||||
INTERRPUT_INT16 = 6
|
INTERRPUT_INT16 = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
struct interrupt_descriptor_t
|
void initialize_gdt();
|
||||||
{
|
|
||||||
uint16_t offset_1;
|
|
||||||
uint16_t selector;
|
|
||||||
uint16_t zero : 8;
|
|
||||||
uint16_t type : 4;
|
|
||||||
uint16_t storage : 1;
|
|
||||||
uint16_t dpl : 2;
|
|
||||||
uint16_t present : 1;
|
|
||||||
uint16_t offset_2;
|
|
||||||
};
|
|
||||||
|
|
||||||
void lidt(struct interrupt_descriptor_t *idt);
|
void initialize_idt();
|
||||||
|
|
||||||
void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage);
|
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_generic(void* frame)
|
||||||
|
{
|
||||||
|
printf("Generic interrupt.\n");
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
__attribute__ ((interrupt))
|
||||||
void isr_division_by_zero(void* frame)
|
void isr_division_by_zero(void* frame)
|
||||||
{
|
{
|
||||||
@@ -11,18 +17,22 @@ void isr_division_by_zero(void* frame)
|
|||||||
__attribute__ ((interrupt))
|
__attribute__ ((interrupt))
|
||||||
void isr_gp_fault(void* frame, unsigned int error)
|
void isr_gp_fault(void* frame, unsigned int error)
|
||||||
{
|
{
|
||||||
|
asm("cli");
|
||||||
|
printf("Exception: GP fault, code %08x\n", error);
|
||||||
|
asm("hlt");
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
__attribute__ ((interrupt))
|
||||||
void isr_page_fault(void* frame, unsigned int error)
|
void isr_page_fault(void* frame, unsigned int error)
|
||||||
{
|
{
|
||||||
|
printf("Exception: Page fault\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
__attribute__ ((interrupt))
|
||||||
void isr_double_fault(void* frame, unsigned int error)
|
void isr_double_fault(void* frame, unsigned int error)
|
||||||
{
|
{
|
||||||
|
asm("cli");
|
||||||
|
printf("Exception: Double fault (!!), code %08x\n", error);
|
||||||
asm("hlt");
|
asm("hlt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_generic(void* frame);
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
__attribute__ ((interrupt))
|
||||||
void isr_division_by_zero(void* frame);
|
void isr_division_by_zero(void* frame);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ extern int _kernel_end;
|
|||||||
|
|
||||||
struct apic_registers_t volatile *apic_registers;
|
struct apic_registers_t volatile *apic_registers;
|
||||||
|
|
||||||
int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable)
|
int start_paging(uint32_t *directory, uint32_t *table, uint32_t *identityTable)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 1024; i++)
|
for (int i = 0; i < 1024; i++)
|
||||||
{
|
{
|
||||||
@@ -42,8 +42,9 @@ int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable)
|
|||||||
|
|
||||||
int initialize(void *multiboot_info)
|
int initialize(void *multiboot_info)
|
||||||
{
|
{
|
||||||
|
initialize_gdt();
|
||||||
|
initialize_idt();
|
||||||
printf("***%s***\n", PACKAGE_STRING);
|
printf("***%s***\n", PACKAGE_STRING);
|
||||||
static struct interrupt_descriptor_t idt[256];
|
|
||||||
static struct page_stack_t page_stack;
|
static struct page_stack_t page_stack;
|
||||||
static struct kernel_t kernel;
|
static struct kernel_t kernel;
|
||||||
struct memory_region_t map_array[16];
|
struct memory_region_t map_array[16];
|
||||||
@@ -76,33 +77,18 @@ int initialize(void *multiboot_info)
|
|||||||
{
|
{
|
||||||
load_module(&kernel, &boot_info.modules[i]);
|
load_module(&kernel, &boot_info.modules[i]);
|
||||||
}
|
}
|
||||||
memset(idt, 0, sizeof(struct interrupt_descriptor_t) * 256);
|
|
||||||
create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0);
|
|
||||||
create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0);
|
|
||||||
create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0);
|
|
||||||
create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0);
|
|
||||||
create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0);
|
|
||||||
create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0);
|
|
||||||
create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0);
|
|
||||||
lidt(idt);
|
|
||||||
asm volatile(
|
|
||||||
"mov $0xFF, %%al;"
|
|
||||||
"outb %%al, $0xA1;"
|
|
||||||
"outb %%al, $0x21;"
|
|
||||||
::: "al"
|
|
||||||
);
|
|
||||||
apic_enable(page_stack);
|
apic_enable(page_stack);
|
||||||
printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv));
|
|
||||||
printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer));
|
|
||||||
|
|
||||||
apic_registers->divide_config.value = APIC_DIVIDE_128;
|
apic_registers->divide_config.value = APIC_DIVIDE_128;
|
||||||
apic_registers->lvt_timer.vector = ISR_APIC_TIMER;
|
apic_registers->lvt_timer.vector = ISR_APIC_TIMER;
|
||||||
apic_registers->lvt_timer.timer_mode = APIC_TIMER_PERIODIC;
|
apic_registers->lvt_timer.timer_mode = APIC_TIMER_PERIODIC;
|
||||||
apic_registers->initial_count.value = 1024*1024*512;
|
apic_registers->initial_count.value = 1024*1024*1024;
|
||||||
apic_registers->lvt_timer.mask = 0;
|
apic_registers->lvt_timer.mask = 0;
|
||||||
printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv));
|
printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv));
|
||||||
printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer));
|
printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer));
|
||||||
asm("sti");
|
asm("sti");
|
||||||
while(1) asm("hlt");
|
while(1)
|
||||||
|
{
|
||||||
|
asm("hlt");
|
||||||
|
}
|
||||||
// TODO: enter first process
|
// TODO: enter first process
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user