Heap Gives Page Fault

417 views Asked by At

I am now getting a page fault which means i am accessing an invalid address. This is most likely to the higher half kernel design i chose to follow. But i could not see where it leads to a page fault. Here is my kernel.c++

#include "types.h"
#include "gdt.h"
#include "stdio.h"
#include "serial.h"
#include "mem.h"
#include "idt.h"
#include "timer.h"
#include "isr.h"
#include "kbd.h"
#include "mouse.h"
#include "irq.h"
#include "string.h"
#include "terminal.h"
#include "multiboot.h"
#include "pmm.h"
#include "heap.h"




//Call all class constructor
//for global objects before
//calling the kernel
typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void callConstructors()
{
    for(constructor* i = &start_ctors; i != &end_ctors; i++)
       (*i)();
}



extern "C" void kernelMain(uint32_t kernel_virtual_end,
        uint32_t  kernel_physical_end,
        uint32_t placeholder,
        uint32_t kernel_physical_start, uint32_t  kernel_virtual_start,
        multiboot_info_t *multiboot_structure,uint32_t magicnumber
        )


{


       cls();
       printf("******KERNEL INFO********\n");
       printf("KERNEL START VIRTUAL 0x%x\n" , kernel_virtual_start);
       printf("KERNEL START PHYSICAL 0x%x\n" , kernel_physical_start);
       printf("KERNEL END VIRTUAL 0x%x\n" , kernel_virtual_end);
       printf("KERNEL END PHYSICAL 0x%x\n" , kernel_physical_end);
       printf("MAGIC 0x%x\n" , magicnumber);
       printf("*************************");
//     printf("********RAM INFO*********\n");
//
//
//     printf("Memory Upper : %d \n", multiboot_structure->mem_upper);
//     printf("Memory Lower : %d \n", multiboot_structure->mem_lower);
//
//     printf("*************************\n");



       gdt gt;
       IDT idt;
       ISR isr;
       IRQ irq;
       SerialPort sp;
       isr.install_isrs();
       irq.install_irqs();
        Timer timer;
        timer.install_timer();
        KBD kbd;

        kbd.install_kbd_driver();


        MOUSE mouse;
        mouse.install_mouse_driver();
        __asm__ __volatile__ ("sti");


        PhyiscalMemoryManager pmm(multiboot_structure);

        KHEAP       kheap;
        char        *ptr;

        Heap heap((&kheap));
        heap.k_addBlock(&kheap, (0x100000+0xC0000000), (0x100000+0xC0000000));
        //ptr = (char*)heap.k_malloc(&kheap, 256);
        //heap.k_free(&kheap, ptr);

   while(1);
   err:
       while(1);
}

Ok you can see i commented out the last lines.. the k_malloc() there is what is causing all the chaos . for some reason it malloc's() bellow 0xC0100000 , which is the minumum size we can go to for the kernel, because we are using virtual addresses and, the 1MB is Grub Related Stuff. Saying that here is my heap.c++ :

#include "heap.h"


int Heap::k_addBlock(KHEAPLCAB *heap, uintptr_t addr, uint32_t size)
{
        KHEAPBLOCKLCAB          *hb;
        KHEAPHDRLCAB            *hdr;

        hb = (KHEAPBLOCKLCAB*)addr;
        hb->size = size;
        hb->used = 0;
        hb->next = heap->fblock;
        heap->fblock = hb;

        hdr = (KHEAPHDRLCAB*)&hb[1];
        hdr->flagsize = hb->size - (sizeof(KHEAPBLOCKLCAB) + 32);

        ++heap->bcnt;

        hb->lastdsize = 0;
        hb->lastdhdr = 0;

        return 1;
}

/*
    Look behind and forward to see if we can merge back into some chunks.
*/
void Heap::k_free(KHEAPLCAB *heap, void *ptr)
{
    KHEAPHDRLCAB                *hdr, *phdr, *nhdr;
    KHEAPBLOCKLCAB              *hb;
    uint32_t                        sz;
    uint8_t                     fg;


    hdr = (KHEAPHDRLCAB*)ptr;
    hdr[-1].flagsize &= ~0x80000000;


    phdr = 0;
    /* find the block we are located in */
    for (hb = heap->fblock; hb; hb = hb->next)
    {
        if (((uintptr_t)ptr > (uintptr_t)hb) && ((uintptr_t)ptr < (uintptr_t)hb + hb->size))
        {

            hdr = (KHEAPHDRLCAB*)((uintptr_t)ptr - sizeof(KHEAPHDRLCAB));


            hdr->flagsize &= ~0x80000000;

            hb->used -= hdr->flagsize;


            if (hdr->prevsize)
            {
                phdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr - (sizeof(KHEAPHDRLCAB) + hdr->prevsize));
            }
            else
            {
                phdr = 0;
            }

            /* get next header */
            nhdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + hdr->flagsize);
            if ((uintptr_t)nhdr >= ((uintptr_t)hb + hb->size))
            {
                nhdr = 0;
            }

            if (nhdr)
            {
                if (!(nhdr->flagsize & 0x80000000))
                {
                    /* combine with it */
                    hdr->flagsize += sizeof(KHEAPHDRLCAB) + nhdr->flagsize;
                    hb->used -= sizeof(KHEAPHDRLCAB);
                    /* set next header prevsize */
                    nhdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + hdr->flagsize);
                    nhdr->prevsize = hdr->flagsize;
                }
            }


            if (phdr)
            {
                if (!(phdr->flagsize & 0x80000000))
                {
                    phdr->flagsize += sizeof(KHEAPHDRLCAB) + hdr->flagsize;
                    hb->used -= sizeof(KHEAPHDRLCAB);
                    hdr = phdr;
                    nhdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + hdr->flagsize);
                    if ((uintptr_t)nhdr < (uintptr_t)hb + sizeof(KHEAPBLOCKLCAB) + hb->size)
                    {
                        nhdr->prevsize = hdr->flagsize;
                    }
                }
            }

            /* optimization */
            if (hdr->flagsize > hb->lastdsize)
            {
                hb->lastdsize = hdr->flagsize;
                hb->lastdhdr = hdr;
            }

            return;
        }
    }

    printf("uhoh ptr:%p\n", ptr);
    for (hb = heap->fblock; hb; hb = hb->next) {
        printf("lcab free looking at block:%p next:%p ptr:%p end:%p\n", hb, hb->next, ptr, (uintptr_t)hb + hb->size);
        if (((uintptr_t)ptr > (uintptr_t)hb)) {
            printf("above\n");
            if (((uintptr_t)ptr < ((uintptr_t)hb + hb->size))) {
                printf("found\n");
            }
        }
    }
    for (;;);
    /* uhoh.. this should not happen.. */
    return;
}

/*
    This will allocate a chunk of memory by the specified size, and if
    no memory chunk can be found it will return zero.
*/
void* Heap::k_malloc(KHEAPLCAB *heap, uint32_t size)
{
    KHEAPBLOCKLCAB      *hb;
    KHEAPHDRLCAB        *hdr, *_hdr, *phdr;
    uint32_t            sz;
    uint8_t             fg;
    uint32_t            checks;
    uint32_t            bc;

    checks = 0;
    bc =0;


    for (hb = heap->fblock; hb; hb = hb->next) {
        if ((hb->size - hb->used) >= (size + sizeof(KHEAPHDRLCAB))) {
            ++bc;

            hdr = (KHEAPHDRLCAB*)&hb[1];


            phdr = 0;
            while ((uintptr_t)hdr < ((uintptr_t)hb + hb->size)) {
                ++checks;

                fg = hdr->flagsize >> 31;
                sz = hdr->flagsize & 0x7fffffff;

                if (!fg)
                {

                    if (sz >= size)
                    {

                        if (sz > (size + sizeof(KHEAPHDRLCAB) + 16))
                        {

                            _hdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + size);
                            _hdr->flagsize = sz - (size + sizeof(KHEAPHDRLCAB));
                            _hdr->prevsize = size;
                            hdr->flagsize = 0x80000000 | size;
                            hb->used += sizeof(KHEAPHDRLCAB);

                        }
                        else
                        {
                            hdr->flagsize |= 0x80000000;
                        }
                        hb->used += size;


                        return &hdr[1];
                    }
                }
                phdr = hdr;
                hdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + sz);
            }

        }
    }

    return 0;
}


Heap::Heap(KHEAPLCAB *heap)
{
    heap->fblock = 0;
    heap->bcnt = 0;
}

Heap::~Heap()
{

}

The problem is with malloc() i think , because when i coment that out, it works all fine. I am accessing some invalid address in that function :

void* Heap::k_malloc(KHEAPLCAB *heap, uint32_t size)
{
    KHEAPBLOCKLCAB      *hb;
    KHEAPHDRLCAB        *hdr, *_hdr, *phdr;
    uint32_t            sz;
    uint8_t             fg;
    uint32_t            checks;
    uint32_t            bc;

    checks = 0;
    bc =0;


    for (hb = heap->fblock; hb; hb = hb->next) {
        if ((hb->size - hb->used) >= (size + sizeof(KHEAPHDRLCAB))) {
            ++bc;

            hdr = (KHEAPHDRLCAB*)&hb[1];


            phdr = 0;
            while ((uintptr_t)hdr < ((uintptr_t)hb + hb->size)) {
                ++checks;

                fg = hdr->flagsize >> 31;
                sz = hdr->flagsize & 0x7fffffff;

                if (!fg)
                {

                    if (sz >= size)
                    {

                        if (sz > (size + sizeof(KHEAPHDRLCAB) + 16))
                        {

                            _hdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + size);
                            _hdr->flagsize = sz - (size + sizeof(KHEAPHDRLCAB));
                            _hdr->prevsize = size;
                            hdr->flagsize = 0x80000000 | size;
                            hb->used += sizeof(KHEAPHDRLCAB);

                        }
                        else
                        {
                            hdr->flagsize |= 0x80000000;
                        }
                        hb->used += size;


                        return &hdr[1];
                    }
                }
                phdr = hdr;
                hdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + sz);
            }

        }
    }

    return 0;
}

. Help Would Be Appreciated. Here is My Full Source Code in Github : https://github.com/amanuel2/OS_MIRROR

0

There are 0 answers