i'm getting a general protection fault and i don't know why, i send a interrupt $0 and i get the message : Divide error 0 so it's good but then i got a loop of general protection fault and then it segfault.
here my code : init_tables.c
#include <k/types.h>
#include "io.h"
#include "init_tables.h"
extern void gdt_flush(u32 gdt_ptr);
extern void idt_flush(u32 idt_p);
/* 1. SERIAL PORT */
void init_uart(void) //Initialize uart 16550 for 38400 bps
{
u8 ier = inb(SERIAL_PORT + 1);
u8 fcr = inb(SERIAL_PORT + 2);
u8 lcr = inb(SERIAL_PORT + 3);
u16 rate = 38400;
outb(SERIAL_PORT + 3, lcr | 1 << 7);
outb(SERIAL_PORT + 0, (115200 / rate) & 255); // = 0x3
outb(SERIAL_PORT + 1, (115200 / rate) >> 8); // = 0x0
outb(SERIAL_PORT + 3, lcr & ~(1 << 7));
outb(SERIAL_PORT + 2, fcr | 1 << 1);
outb(SERIAL_PORT + 2, fcr | 1 << 2);
outb(SERIAL_PORT + 2, fcr | 1 << 6);
outb(SERIAL_PORT + 2, fcr | 1 << 7);
outb(SERIAL_PORT + 1, ier | 1 << 1);
}
/* 2. MEMORY MANAGER */
static struct gdt_entry gdt[5];
static struct gdt_r gdt_r;
static struct idt_entry idt_e[256];
static struct idt_r idt_r;
static void set_gdt_entry(unsigned index, u32 base, u32 limit, u16 access, u16 flags)/* Function to initialize an index of the gtd_entry structure */
{
if (index >= SIZE_ARRAY(gdt))
printf("ARRAY SIZE INCORRECT\n");
gdt[index].base_15_00 = (base & 0xFFFF); // set segment limit of 00-15
gdt[index].base_23_16 = (base >> 16) & 0xFF; //set up base 16-23 bit
gdt[index].base_31_24 = (base >> 24) & 0xFF; //set up base 24-31 bit*/
gdt[index].seg_lim_15_00 = (limit & 0xFFFF); //set up base 00-15 bit
gdt[index].granularity = (limit >> 16) & 0x0F; //set segment of 16-19
gdt[index].granularity |= flags & 0xF0; // granularity, operand size, zero and avl -> flags
gdt[index].access_byte = access; //set up type, s, dpl, p
}
static void init_gdt(void)
{
gdt_r.limit = sizeof(gdt) - 1;
gdt_r.base = (u32)&gdt;
set_gdt_entry(0, 0, 0, 0, 0); /* Null segment */
set_gdt_entry(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); /* Code segment */
set_gdt_entry(2, 0, 0xFFFFFFFF, 0x92, 0xCF); /* Data segment */
//set_gdt_entry(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); /* User mode code segment */
//set_gdt_entry(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); /* User mode data segment */
gdt_flush((u32)&gdt_r);
}
void init_kernel(void)
{
init_uart();
init_gdt();
init_idt();
}
static int idt_set_gate(u32 n, u32 base, u16 sel, u8 flags)
{
if (n >= SIZE_ARRAY(idt_e))
return -1;
idt_e[n].base_15_00 = base & 0xFFFF;
idt_e[n].base_16_31 = (base >> 16) & 0xFFFF;
idt_e[n].segment_sel= sel;
idt_e[n].zero = 0;
/* We must uncomment the OR below when we get to using user-mode. It
sets the interrupt gate's privilege level to 3. */
idt_e[n].flags = flags /* | 0x60 */;
return 0;
}
void init_idt()
{
idt_r.limit = sizeof(idt_e) - 1;
idt_r.base = (u32)&idt_e;
(void)memset(&idt_e, 0, sizeof(idt_e));
/*outb(0x20, 0x11); // remap irq table
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);*/
idt_set_gate( 0, (u32)isr0, 0x08, 0x8E);
idt_set_gate( 1, (u32)isr1, 0x08, 0x8E);
idt_set_gate( 2, (u32)isr2, 0x08, 0x8E);
idt_set_gate( 3, (u32)isr3, 0x08, 0x8E);
idt_set_gate( 4, (u32)isr4, 0x08, 0x8E);
idt_set_gate( 5, (u32)isr5, 0x08, 0x8E);
idt_set_gate( 6, (u32)isr6, 0x08, 0x8E);
idt_set_gate( 7, (u32)isr7, 0x08, 0x8E);
idt_set_gate( 8, (u32)isr8, 0x08, 0x8E);
idt_set_gate( 9, (u32)isr9, 0x08, 0x8E);
idt_set_gate(10, (u32)isr10, 0x08, 0x8E);
idt_set_gate(11, (u32)isr11, 0x08, 0x8E);
idt_set_gate(12, (u32)isr12, 0x08, 0x8E);
idt_set_gate(13, (u32)isr13, 0x08, 0x8E);
idt_set_gate(14, (u32)isr14, 0x08, 0x8E);
idt_set_gate(15, (u32)isr15, 0x08, 0x8E);
idt_set_gate(16, (u32)isr16, 0x08, 0x8E);
idt_set_gate(17, (u32)isr17, 0x08, 0x8E);
idt_set_gate(18, (u32)isr18, 0x08, 0x8E);
idt_set_gate(19, (u32)isr19, 0x08, 0x8E);
idt_set_gate(20, (u32)isr20, 0x08, 0x8E);
idt_set_gate(21, (u32)isr21, 0x08, 0x8E);
idt_set_gate(22, (u32)isr22, 0x08, 0x8E);
idt_set_gate(23, (u32)isr23, 0x08, 0x8E);
idt_set_gate(24, (u32)isr24, 0x08, 0x8E);
idt_set_gate(25, (u32)isr25, 0x08, 0x8E);
idt_set_gate(26, (u32)isr26, 0x08, 0x8E);
idt_set_gate(27, (u32)isr27, 0x08, 0x8E);
idt_set_gate(28, (u32)isr28, 0x08, 0x8E);
idt_set_gate(29, (u32)isr29, 0x08, 0x8E);
idt_set_gate(30, (u32)isr30, 0x08, 0x8E);
idt_set_gate(31, (u32)isr31, 0x08, 0x8E);
/*idt_set_gate(32, (u32)irq0, 0x08, 0x8E);
idt_set_gate(33, (u32)irq1, 0x08, 0x8E);
idt_set_gate(34, (u32)irq2, 0x08, 0x8E);
idt_set_gate(35, (u32)irq3, 0x08, 0x8E);
idt_set_gate(36, (u32)irq4, 0x08, 0x8E);
idt_set_gate(37, (u32)irq5, 0x08, 0x8E);
idt_set_gate(38, (u32)irq6, 0x08, 0x8E);
idt_set_gate(39, (u32)irq7, 0x08, 0x8E);
idt_set_gate(40, (u32)irq8, 0x08, 0x8E);
idt_set_gate(41, (u32)irq9, 0x08, 0x8E);
idt_set_gate(42, (u32)irq10, 0x08, 0x8E);
idt_set_gate(43, (u32)irq11, 0x08, 0x8E);
idt_set_gate(44, (u32)irq12, 0x08, 0x8E);
idt_set_gate(45, (u32)irq13, 0x08, 0x8E);
idt_set_gate(46, (u32)irq14, 0x08, 0x8E);
idt_set_gate(47, (u32)irq15, 0x08, 0x8E);*/
idt_flush((u32)&idt_r);
}
Then i got my asm file : init_tab.asm
[GLOBAL gdt_flush] ; allow in C to call these functions
gdt_flush:
mov eax, [esp+4] ; Get the pointer to the GDT, passed as a parameter.
lgdt [eax] ; Load the new GDT pointer
mov eax, cr0 ; Activate protected mode
or eax, 1
mov cr0, eax
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax ; Load all data segment selectors
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:.flush ; 0x08 is the offset to our code segment: Far jump!
.flush:
ret
[GLOBAL idt_flush]
idt_flush:
mov eax, [esp+4] ; Get the pointer to the IDT, passed as a parameter.
lidt [eax] ; Load the IDT pointer.
ret
and then i got my interrupt common stub : interrupt_conf.asm :
%macro ISR_NO_ERROR 1 ; define a macro, taking one parameter
[GLOBAL isr%1] ; %1 accesses the first parameter.
isr%1:
;cli
push byte 0
push byte %1
jmp isr_common_stub
%endmacro
%macro ISR_ERROR 1
[GLOBAL isr%1]
isr%1:
;cli
push byte %1
jmp isr_common_stub
%endmacro
ISR_NO_ERROR 0
ISR_NO_ERROR 1
ISR_NO_ERROR 2
ISR_NO_ERROR 3
ISR_NO_ERROR 4
ISR_NO_ERROR 5
ISR_NO_ERROR 6
ISR_NO_ERROR 7
ISR_ERROR 8
ISR_NO_ERROR 9
ISR_ERROR 10
ISR_ERROR 11
ISR_ERROR 12
ISR_ERROR 13
ISR_ERROR 14
ISR_NO_ERROR 15
ISR_NO_ERROR 16
ISR_NO_ERROR 17
ISR_NO_ERROR 18
ISR_NO_ERROR 19
ISR_NO_ERROR 20
ISR_NO_ERROR 21
ISR_NO_ERROR 22
ISR_NO_ERROR 23
ISR_NO_ERROR 24
ISR_NO_ERROR 25
ISR_NO_ERROR 26
ISR_NO_ERROR 27
ISR_NO_ERROR 28
ISR_NO_ERROR 29
ISR_NO_ERROR 30
ISR_NO_ERROR 31
; In isr.c
[EXTERN isr_handler]
; This is our common ISR stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
isr_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov eax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
mov eax, 0x10 ; load the kernel data segment descriptor
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
call isr_handler
pop eax ; reload the original data segment descriptor
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
;sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
; This macro creates a stub for an IRQ - the first parameter is
; the IRQ number, the second is the ISR number it is remapped to.
%macro IRQ 2
[GLOBAL irq%1]
irq%1:
cli
push byte 0
push byte %2
jmp irq_common_stub
%endmacro
;IRQ 0, 32
;IRQ 1, 33
;IRQ 2, 34
;IRQ 3, 35
;IRQ 4, 36
;IRQ 5, 37
;IRQ 6, 38
;IRQ 7, 39
;IRQ 8, 40
;IRQ 9, 41
;IRQ 10, 42
;IRQ 11, 43
;IRQ 12, 44
;IRQ 13, 45
;IRQ 14, 46
;IRQ 15, 47
; In isr.c
[EXTERN irq_handler]
; This is our common IRQ stub. It saves the processor state, sets
; up for kernel mode segments, calls the C-level fault handler,
; and finally restores the stack frame.
irq_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
mov ax, 0x10 ; load the kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call irq_handler
pop ebx ; reload the original data segment descriptor
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
my main look like this :
void k_main(unsigned long magic, multiboot_info_t *info)
{
init_kernel();
printf("perfect toto\n");
asm volatile("int $0");
}
After that i got this on my terminal :
and here my file where k_main is launch :
#include "multiboot.h"
#define HEADER_FLAGS (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO)
#define STACK_SIZE 8192
.section .multiboot
.type multiboot_header, @object
multiboot_header:
.align MULTIBOOT_HEADER_ALIGN
.long MULTIBOOT_HEADER_MAGIC
.long HEADER_FLAGS
.long -(MULTIBOOT_HEADER_MAGIC + HEADER_FLAGS)
.size multiboot_header, . - multiboot_header
.section .text
.global k_entry
.type k_entry, @function
k_entry:
lea end_stack, %esp
push %ebx /* multiboot info */
push %eax /* magic */
call k_main /* kernel entry point */
.Lend:
jmp .Lend
.size k_entry, . - k_entry
.section .bss
stack:
.space STACK_SIZE
.align 16
end_stack:
.global end_stack
here is my handlers function:
static const char *exceptions[32] = {
[0] = "Divide Error",
[1] = "Debug Exception",
[2] = "NMI Interrupt",
[3] = "Breakpoint",
[4] = "Overflow",
[5] = "Bound Range Exceeded",
[6] = "Invalid Opcode",
[7] = "Device Not Available",
[8] = "Double Fault",
[9] = "Coprocessor Segment Overrum",
[10] = "Invalid TSS",
[11] = "Segment Not Present",
[12] = "Stack Segment Fault",
[13] = "General Protection Fault",
[14] = "Page Fault",
[15] = "Unknown interrupt exception",
[16] = "x87 FPU Fault",
[17] = "Alignment Check",
[18] = "Machine Check",
[19] = "SIMD Floating Point Exception",
[20] = "Virtualization Exception",
};
isrhdl_t interrupt_handlers[256];
/* This gets called from our ASM interrupt handler stub. */
void
isr_handler(struct cpu_regs regs)
{
if (interrupt_handlers[regs.int_no] != NULL) {
isrhdl_t handler = interrupt_handlers[regs.int_no];
handler(regs);
} else {
printf("unhandled interrupt: %s\n", exceptions[regs.int_no]);
}
}
/* This gets called from our ASM interrupt handler stub. */
void
irq_handler(struct cpu_regs regs) {
/* Send an EOI (end of interrupt) signal to the PICs. If this interrupt
involved the slave. */
if (regs.int_no >= 40) {
/* Send reset signal to slave.*/
outb(0xA0, 0x20);
}
/* Send reset signal to master. */
outb(0x20, 0x20);
if (interrupt_handlers[regs.int_no] != 0) {
isrhdl_t handler = interrupt_handlers[regs.int_no];
handler(regs);
}
}
void
register_interrupt_handler(u32 n, isrhdl_t handler)
{
if (n >= SIZE_ARRAY(interrupt_handlers))
printf("Bad interrupt handler index.");
interrupt_handlers[n] = handler;
}
i've been stuck 1 week on that i'm terribly tired of that ... Can somebody help me please thank you very much for help !
EDIT SOLUTION : Cannot modify data segment register. When tried General Protection Error is thrown
User contributions licensed under CC BY-SA 3.0