Error compile GDT and Interrupt

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
MichaelPetch
Member
Member
Posts: 797
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Error compile GDT and Interrupt

Post by MichaelPetch »

This doesn't look right either:

Code: Select all

gdt_entries[num].granularity |= granularity & 0x0F;
Maybe you meant:

Code: Select all

gdt_entries[num].granularity |= granularity & 0xF0;
Ananta96
Posts: 24
Joined: Mon Jul 01, 2019 10:46 am

Re: Error compile GDT and Interrupt

Post by Ananta96 »

I've changed my code but still get trouble

Code: Select all

#include <stdint.h>

struct gdt_entry {
    uint16_t limit_low;
    uint16_t base_low;
    uint8_t base_middle;
    uint8_t access;
    uint8_t granularity;
    uint8_t base_high;
};

struct gdt_ptr {
    uint16_t limit;
    uint32_t base;
};

void init_gdt();

extern void gdt_flush(uint32_t);
static void gdt_set_gate(int32_t,uint32_t,uint32_t,uint8_t,uint8_t);

struct gdt_entry gdt_entries[5];
struct gdt_ptr gdt_ptr;

void init_gdt() {
    gdt_ptr.limit = (sizeof(struct gdt_entry) * 5) - 1;
    gdt_ptr.base = (uint32_t)&gdt_entries;
    gdt_set_gate(0,0,0,0,0);
    gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
    gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
    gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
    gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
    gdt_flush((uint32_t)&gdt_ptr);
}

static void gdt_set_gate(int32_t num,uint32_t base,uint32_t limit,
uint8_t access,uint8_t granularity) {
    gdt_entries[num].base_low = (base & 0xFFFF);
    gdt_entries[num].base_middle = (base >> 16) & 0xFF;
    gdt_entries[num].base_high = (base >> 24) & 0xFF;

    gdt_entries[num].limit_low = (limit & 0xFFFF); 
    gdt_entries[num].granularity = (limit >> 16) & 0x0F;

    gdt_entries[num].granularity |= granularity & 0xF0;
    gdt_entries[num].access = access;
}
i hope you can look my source code: https://github.com/Ananta98/OSdev. I hope you know this trouble.
MichaelPetch
Member
Member
Posts: 797
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Error compile GDT and Interrupt

Post by MichaelPetch »

Now that you have a project it is much easier to help. Your final issue is this:

Code: Select all

struct gdt_ptr {
    uint16_t limit;
    uint32_t base;
};
Because GCC is by default using natural alignment for placing data in structures. It has added padding between limit and base to align base (a 32-bit value) on a 32-bit (4 byte) boundary. To change that behavior you will need to tell GCC to pack the structure:

Code: Select all

struct gdt_ptr {
    uint16_t limit;
    uint32_t base;
} __attribute__((packed));
Last edited by MichaelPetch on Sun Jul 28, 2019 8:00 am, edited 1 time in total.
Ananta96
Posts: 24
Joined: Mon Jul 01, 2019 10:46 am

Re: Error compile GDT and Interrupt

Post by Ananta96 »

Thank you Petch it works
Ananta96
Posts: 24
Joined: Mon Jul 01, 2019 10:46 am

Re: Error compile GDT and Interrupt

Post by Ananta96 »

I want to ask there is interrupt no 65536. If there is no interrupt 65536 what's wrong with mycode ???

idt.c

Code: Select all

#include <stdint.h>
#include "../../include/string.h"
struct idt_entry {
    uint16_t base_low;
    uint16_t selector;
    uint8_t always_zero;
    uint8_t flags;
    uint16_t base_high;
}__attribute__((packed));

struct idt_ptr {
    uint16_t limit;
    uint32_t base;
}__attribute__((packed));

struct idt_ptr idt_ptr;
struct idt_entry idt_entries[256];
extern void idt_flush(uint32_t);
static void idt_set_gate(uint8_t,uint32_t,uint16_t,uint8_t);
void init_idt();

extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();


void init_idt() {
    idt_ptr.limit = sizeof(struct idt_entry) * 256 - 1;
    idt_ptr.base = (uint32_t)&idt_entries;
    memset(&idt_entries,0,sizeof(struct idt_entry) * 256);
    idt_set_gate(1,(uint32_t)isr0,0x08,0x8E);
    idt_set_gate(2,(uint32_t)isr2,0x08,0x8E);
    idt_set_gate(3,(uint32_t)isr3,0x08,0x8E);
    idt_set_gate(4,(uint32_t)isr4,0x08,0x8E);
    idt_set_gate(5,(uint32_t)isr5,0x08,0x8E);
    idt_set_gate(6,(uint32_t)isr6,0x08,0x8E);
    idt_set_gate(7,(uint32_t)isr7,0x08,0x8E);
    idt_set_gate(8,(uint32_t)isr8,0x08,0x8E);
    idt_set_gate(9,(uint32_t)isr9,0x08,0x8E);
    idt_set_gate(10,(uint32_t)isr10,0x08,0x8E);
    idt_set_gate(11,(uint32_t)isr11,0x08,0x8E);
    idt_set_gate(12,(uint32_t)isr12,0x08,0x8E);
    idt_set_gate(13,(uint32_t)isr13,0x08,0x8E);
    idt_set_gate(14,(uint32_t)isr14,0x08,0x8E);
    idt_set_gate(15,(uint32_t)isr15,0x08,0x8E);
    idt_set_gate(16,(uint32_t)isr16,0x08,0x8E);
    idt_set_gate(17,(uint32_t)isr17,0x08,0x8E);
    idt_set_gate(18,(uint32_t)isr18,0x08,0x8E);
    idt_set_gate(19,(uint32_t)isr19,0x08,0x8E);
    idt_set_gate(20,(uint32_t)isr20,0x08,0x8E);
    idt_set_gate(21,(uint32_t)isr21,0x08,0x8E);
    idt_set_gate(22,(uint32_t)isr22,0x08,0x8E);
    idt_set_gate(23,(uint32_t)isr23,0x08,0x8E);
    idt_set_gate(24,(uint32_t)isr24,0x08,0x8E);
    idt_set_gate(25,(uint32_t)isr25,0x08,0x8E);
    idt_set_gate(26,(uint32_t)isr26,0x08,0x8E);
    idt_set_gate(27,(uint32_t)isr27,0x08,0x8E);
    idt_set_gate(28,(uint32_t)isr28,0x08,0x8E);
    idt_set_gate(29,(uint32_t)isr29,0x08,0x8E);
    idt_set_gate(30,(uint32_t)isr30,0x08,0x8E);
    idt_set_gate(31,(uint32_t)isr31,0x08,0x8E);
    idt_flush((uint32_t)&idt_ptr);
}

 static void idt_set_gate(uint8_t num,uint32_t base,uint16_t selector,uint8_t flags) {
    idt_entries[num].base_low = base & 0xFFFF;
    idt_entries[num].base_high = (base >> 16) & 0xFFFF;
    idt_entries[num].selector = selector;
    idt_entries[num].always_zero = 0;
    idt_entries[num].flags = flags | 0x60;
}
idt.s

Code: Select all

.section .text
.align 4

.global idt_flush
.type idt_flush, @function

idt_flush:
    mov 4(%esp),%eax
    lidt (%eax)
    ret
interrupt.s

Code: Select all

.section .text
.align 4

.macro ISR_NOERR index
    .global isr\index
    isr\index:
        cli
        push $0
        push $\index
        jmp isr_common
.endm

.macro ISR_ERR index
    .global isr\index
    isr\index:
        cli
        push $\index
        jmp isr_common
.endm

ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR   8
ISR_NOERR 9
ISR_ERR   10
ISR_ERR   11
ISR_ERR   12
ISR_ERR   13
ISR_ERR   14
ISR_NOERR 15
ISR_NOERR 16
ISR_NOERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_NOERR 30
ISR_NOERR 31
ISR_NOERR 127

.extern isr_handler
.type isr_handler, @function


isr_common:
    pusha

    /* Save segment registers */
    push %ds
    push %es
    push %fs
    push %gs
    mov $0x10, %ax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs
    cld


    push %esp
    call isr_handler
    add $4, %esp


    pop %gs
    pop %fs
    pop %es
    pop %ds


    popa

    add $8, %esp
    iret
MichaelPetch
Member
Member
Posts: 797
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Error compile GDT and Interrupt

Post by MichaelPetch »

I'm not sure what you are asking. The maximum number of interrupts supported in 32-bit protected mode is 8192. Each entry is 8 bytes so 65536/8=8192. You don't have to fill them all up. If your code is failing in some way you should update your github project. The one thing I do see is this:

Code: Select all

    idt_set_gate(1,(uint32_t)isr0,0x08,0x8E);
    idt_set_gate(2,(uint32_t)isr2,0x08,0x8E);
    idt_set_gate(3,(uint32_t)isr3,0x08,0x8E);
    idt_set_gate(4,(uint32_t)isr4,0x08,0x8E);
    ...
    idt_set_gate(31,(uint32_t)isr31,0x08,0x8E);
Interrupt numbers start with 0 but you started with 1 (first parameter). Then for some reason you started with isr0 and skipped isr1. I'd expect it to look something like:

Code: Select all

    idt_set_gate(0,(uint32_t)isr0,0x08,0x8E);
    idt_set_gate(1,(uint32_t)isr1,0x08,0x8E);
    idt_set_gate(2,(uint32_t)isr2,0x08,0x8E);
    idt_set_gate(3,(uint32_t)isr3,0x08,0x8E);
    ...
    idt_set_gate(31,(uint32_t)isr31,0x08,0x8E);
Ananta96
Posts: 24
Joined: Mon Jul 01, 2019 10:46 am

Re: Error compile GDT and Interrupt

Post by Ananta96 »

I've got trouble especially pit.c (PIT doesn't work),paging.c and kheap.c what's wrong in my source code. If you can, you can also check all source code for idt and gdt. I hope you can help me. website github https://github.com/Ananta98/OSdev
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: Error compile GDT and Interrupt

Post by LtG »

MichaelPetch wrote:The maximum number of interrupts supported in 32-bit protected mode is 8192. Each entry is 8 bytes so 65536/8=8192.
I thought there's only 256 interrupts?
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: Error compile GDT and Interrupt

Post by LtG »

Ananta96 wrote:I want to ask there is interrupt no 65536. If there is no interrupt 65536 what's wrong with mycode ???
What does interrupt #65536 have to do with anything? And of course, if there's 65536 of something, since 0 is the first one, then the last is 65535, note the last digit. But beyond that, I don't really understand what you are talking about.

Also, it would be useful to explain what your problem is, instead of a "what's wrong"...
Ananta96 wrote:I've got trouble especially pit.c (PIT doesn't work),paging.c and kheap.c what's wrong in my source code. If you can, you can also check all source code for idt and gdt. I hope you can help me. website github https://github.com/Ananta98/OSdev
What does "doesn't work" mean exactly? You should provide more specific details, explain what the problem is.

And try to do troubleshooting/debugging and tell what you found. If you haven't done debugging:
https://wiki.osdev.org/Kernel_Debugging
https://wiki.osdev.org/GDB
Ananta96
Posts: 24
Joined: Mon Jul 01, 2019 10:46 am

Re: Error compile GDT and Interrupt

Post by Ananta96 »

Now i want to debug assembly how because the code combination c and assembly? I've got trouble, when breakpoint set pc 0x0? how to solve it ?
Attachments
Capture.PNG
User avatar
iansjack
Member
Member
Posts: 4705
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Error compile GDT and Interrupt

Post by iansjack »

You can't debug an individual object file like that. You have to load the linked executable and then the breakpoints will be set at the correct relocated addresses.
Ananta96
Posts: 24
Joined: Mon Jul 01, 2019 10:46 am

Re: Error compile GDT and Interrupt

Post by Ananta96 »

i want to know nasm command for debugging ?
And what's wrong my code in my gdt nasm version, I've got trouble guru meditation again

gdt.asm

Code: Select all

section .text
align 4
global gdt_flush
gdt_flush:
    mov eax, [esp + 4]
    lgdt [eax]
    mov ax,0x10
    mov ds,ax
    mov es,ax
    mov fs,ax
    mov ss,ax
    mov gs,ax
    jmp 0x08:.flush
.flush:
    ret
gdtuser.h

Code: Select all

#include <stdint.h>
struct gdt_entry {
    uint16_t base_low;
    uint16_t limit_low;
    uint8_t base_middle;
    uint8_t access;
    uint8_t granularity;
    uint8_t base_high;
} __attribute__((packed));

struct gdt_ptr {
    uint16_t limit;
    uint32_t base;
} __attribute__((packed));

void install_gdt();

extern void gdt_flush(uint32_t);
static void gdt_set_gate(int32_t,uint32_t,uint32_t,uint8_t,uint8_t);

struct gdt_entry gdt_entries[5];
struct gdt_ptr gdt_ptr;
gdt_user.c

Code: Select all

#include "gdt_user.h"

void install_gdt() {
    gdt_ptr.limit = (sizeof(struct gdt_entry) * 5) - 1;
    gdt_ptr.base = (uint32_t)&gdt_entries;
    gdt_set_gate(0, 0, 0, 0, 0);  
    gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
    gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
    gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
    gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
    gdt_flush((uint32_t)&gdt_ptr);
}

static void gdt_set_gate(int32_t num,uint32_t base,
uint32_t limit,uint8_t access,uint8_t granularity) {
    gdt_entries[num].base_low = (base & 0xFFFF);
    gdt_entries[num].base_middle = (base >> 16) & 0xFF;
    gdt_entries[num].base_high = (base >> 24) & 0xFF;

    gdt_entries[num].limit_low = (limit & 0xFFFF); 
    gdt_entries[num].granularity = (limit >> 16) & 0x0F;

    gdt_entries[num].granularity |= granularity & 0xF0;
    gdt_entries[num].access = access;
}
User avatar
iansjack
Member
Member
Posts: 4705
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Error compile GDT and Interrupt

Post by iansjack »

It's clear from your previous post that you know that the command to debug an executable is "gdb".
Ananta96
Posts: 24
Joined: Mon Jul 01, 2019 10:46 am

Re: Error compile GDT and Interrupt

Post by Ananta96 »

Sorry for inconvinient. I want to ask what's the problem of my code for paging. I've started from zero again because osdev in my github still alot got trouble. I've decided to learn osdev only in one directory in my laptop.

kheap.h

Code: Select all

#include <stdint.h>
#include <stddef.h>

size_t kmalloc_int(size_t size,int align, size_t *phys);
size_t kmalloc_a(size_t size);
size_t kmalloc_p(size_t size,size_t *phys);
size_t kmalloc_ap(size_t size,size_t *phys);
size_t kmalloc(size_t size);
kheap.c

Code: Select all

#include "kheap.h"
extern uint32_t end;
uint32_t placement_address = (uint32_t)&end;

size_t kmalloc_int(size_t size,int align, size_t *phys) {
    if (align == 1 && (placement_address & 0xFFFFF000)) {
        placement_address &= 0xFFFFF000;
        placement_address += 0x1000;
    }
    if (phys)
        *phys = placement_address;
    size_t tmp = placement_address;
    placement_address += size;
    return tmp;
}

size_t kmalloc_a(size_t size) {
    return kmalloc_int(size,1,0);
}

size_t kmalloc_p(size_t size,size_t *phys) {
    return kmalloc_int(size,0,phys);
}

size_t kmalloc_ap(size_t size,size_t *phys) {
    return kmalloc_int(size,1,phys);
}

size_t kmalloc(size_t size) {
    return kmalloc_int(size,0,0);
}


paging.h

Code: Select all

#include <stdint.h>
#include "register.h"

struct page {
    uint32_t present : 1;
    uint32_t rw : 1;
    uint32_t user : 1;
    uint32_t accessed : 1;
    uint32_t dirty : 1;
    uint32_t unused : 7;
    uint32_t frame : 20;
};

struct page_table {
    struct page pages[1024];
};

struct page_directory {
    struct page_table *tables[1024];
    uint32_t tablesPhysical[1024];
    uint32_t physicalAddr;
};

void initialise_paging();
void switch_page_directory(struct page_directory *new);
struct page *get_page(uint32_t address,int make,struct page_directory *dir);
void page_fault(struct regs *regs);
paging.c

Code: Select all

#include "paging.h"
#include "stdio.h"
#include "kheap.h"
#include "irq_user.h"

uint32_t *frames;
uint32_t nframes;

struct page_directory *kernel_directory = 0;
struct page_directory *current_directory = 0;

extern uint32_t placement_address;

#define INDEX_FROM_BIT(a) (a/(8*4))
#define OFFSET_FROM_BIT(a) (a%(8*4))

static void set_frame(uint32_t frame_addr) {
    uint32_t frame = frame_addr / 0x1000;
    uint32_t idx = INDEX_FROM_BIT(frame);
    uint32_t off = OFFSET_FROM_BIT(frame);
    frames[idx] |= (0x1 << off);
}

static void clear_frame(uint32_t frame_addr) {
    uint32_t frame = frame_addr / 0x1000;
    uint32_t idx = INDEX_FROM_BIT(frame);
    uint32_t off = OFFSET_FROM_BIT(frame);
    frames[idx] &= ~(0x1 << off);
}

static uint32_t test_frame(uint32_t frame_addr) {
    uint32_t frame = frame_addr / 0x1000;
    uint32_t idx = INDEX_FROM_BIT(frame);
    uint32_t off = OFFSET_FROM_BIT(frame);
    return (frames[idx] & (0x1 << off));
}

static uint32_t fist_frame() {
    int i , j;
    for (i = 0; i < INDEX_FROM_BIT(nframes); i++) {
        if (frames[i] != 0xFFFFFFFF) {
            for (j = 0; j < 32; j++) {
                uint32_t test = 0x1 << j;
                if (!(frames[i] & test))
                    return i*4*8+j;
            }
        }
    }
}

void alloc_frame(struct page *page,int is_kernel,int is_writeable) {
    if (page->frame != 0)
        return;
    else {
        uint32_t idx = fist_frame();
        if (idx == (uint32_t)-1) {
           kprintf("No free frames\n");
           return;
        }
        set_frame(idx * 0x1000);
        page->present = 1;
        page->rw = (is_writeable) ? 1 : 0;
        page->user = (is_kernel) ? 0 : 1;
        page->frame = idx;
    }
}

void free_frame(struct page *page) {
    uint32_t frame;
    if (!(frame=page->frame))
        return;
    else {
        clear_frame(frame);
        page->frame = 0x0;
    }
}

void switch_page_directory(struct page_directory *dir) {
    current_directory = dir;
    asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
    uint32_t cr0;
    asm volatile("mov %%cr0, %0" : "=r"(cr0));
    cr0 |= 0x80000000;
    asm volatile("mov %0, %%cr0" :: "r"(cr0));
}

struct page *get_page(uint32_t address,int make,struct page_directory *dir) {
    address /= 0x1000;
    uint32_t table_idx = address / 1024;
    if (dir->tables[table_idx])
        return &dir->tables[table_idx]->pages[address % 1024];
    else if (make) {
        uint32_t tmp;
        dir->tables[table_idx] = (struct page_table*)kmalloc_ap(sizeof(struct page_table),&tmp);
        dir->tablesPhysical[table_idx] = tmp | 0x7;
        return &dir->tables[table_idx]->pages[address%1024];
    } else {
        return 0;
    }
}

void page_fault(struct regs *regs) {
    uint32_t faulting_address;
    asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
    int present = !(regs->err_code & 0x01);
    int rw = regs->err_code & 0x02;
    int us = regs->err_code & 0x04;
    int reserved = regs->err_code & 0x08;
    int id = regs->err_code & 0x10;
    kprintf("Page fault\n");
    if (rw) kprintf("Present\n");
    if (us) kprintf("User mode\n");
    if (reserved) kprintf("Reserved\n");
    kprintf("Address : %x\n",faulting_address);
}

void initialise_paging() {
    uint32_t mem_end_page = 0x1000000;
    nframes = mem_end_page / 0x1000;
    frames = (uint32_t*) kmalloc_a(INDEX_FROM_BIT(nframes));
    memset(frames,0,INDEX_FROM_BIT(nframes));
    kernel_directory = (struct page_directory*)kmalloc_a(sizeof(struct page_directory));
    memset(kernel_directory,0,sizeof(struct page_directory));
    current_directory = kernel_directory;
    int i = 0;
    while (i < placement_address) {
        alloc_frame(get_page(i,1,kernel_directory),0,0);
        i += 0x1000;
    }
    irq_install_handler(14,page_fault);
    switch_page_directory(kernel_directory);
}
User avatar
iansjack
Member
Member
Posts: 4705
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Error compile GDT and Interrupt

Post by iansjack »

"still alot got trouble" is not really a very clear description of your problem.

What are you expecting to happen?
What is actually happening?
What steps have you taken to solving the problem?
Have you run the code under a debugger, inspecting registers and memory structures to see if they fit with what you expect?

Juat posting a lot of code and saying "it doesn't work" is unlikely to elicit useful responses.
Post Reply