OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Sep 16, 2019 10:15 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: GRUB memory map page faults
PostPosted: Thu Aug 01, 2019 7:34 am 
Offline

Joined: Wed Oct 17, 2018 9:56 am
Posts: 19
Hello,

I'm going to get my memory map via GRUB.
Here in the linker file I put some symbols to get the start and the end of the kernel (I'm using an higher half kernel):
Code:
...
/* lower half stuff */
    . += KERNEL_VIRTUAL_BASE;
    . = ALIGN (4096);
    start = .;
...
    . = ALIGN(4096);
    end = .;
}

Then in the initialization of the memory manager I get the RAM size checking the flags and summing it up:
Code:
/**
* Get and anylize the GRUB memory map to count the RAM size.
*/
unsigned int findRAMSize(multiboot_info_t* mbt) {
    uint32_t size = 0;

    /**
     * If the bit 0 is set, it is possible to safely refer to mbd->mem_lower for conventional memory and mbd->mem_upper for high memory.
     * Both are given in kibibytes, i.e. blocks of 1024 bytes each.
     */
    if(mbt->flags & 0x1)
        size = mbt->mem_lower + mbt->mem_upper;
    /**
     * Otherwise bit 6 in the flags uint16_t is set, then the mmap_* fields are valid,
     * and indicate the address and length of a buffer containing a memory map of the machine provided by the BIOS
     */
    else if (mbt->flags & 0x20) {
        memory_map_t *mmap = mbt->mmap_addr;

        while ((unsigned int)mmap < (mbt->mmap_addr + mbt->mmap_length)) {
            size += mbt->mmap_length;
            mmap = (memory_map_t *)(mmap + mmap->size + sizeof(mmap->size));
        }
    }
    return size;
}


So in some kind it works.
Now I have to find the actual blocks. I set (I'm not sure if this is correct)
Code:
stack = end
and then decrement both end and start:
Code:
end -= 0xC0000000;
start -= 0xC0000000;

It is ok until here.
I use the code example in the Wiki https://wiki.osdev.org/Detecting_Memory_(x86)#Getting_a_GRUB_Memory_Map but when it has to go to the next free block, it crashes with a page fault.
Code:
    // Find out what addresses are free
    memory_map_t *mmap = mbt->mmap_addr;

    // TODO: Find kernel + stack start and end addresses

    while ((uint32_t)mmap < (mbt->mmap_addr + mbt->mmap_length)) {
        printf("mmap = 0x%x\n", mmap);

        mmap = (memory_map_t *)((uint32_t)mmap + mmap->size + sizeof(mmap->size));
    }


Do you have some advice?
Thank you to who will help in advance.


Top
 Profile  
 
 Post subject: Re: GRUB memory map page faults
PostPosted: Thu Aug 01, 2019 8:22 pm 
Offline
Member
Member

Joined: Fri Jun 28, 2013 1:48 am
Posts: 42
In your linker script you defined two symbols:

Code:
start = .;
...
end = .;


And in your C code you should add the external symbol as:

Code:
extern char start;
extern char end;


Note they are char typed, if you want to get the address of those two symbols:

Code:
size_t start_addr = &start;
size_t end_addr = &end;


You have to first get their address, or you are just changing the char value stored at those two memory location.

_________________
Reinventing the Wheel, code: https://github.com/songziming/wheel


Top
 Profile  
 
 Post subject: Re: GRUB memory map page faults
PostPosted: Fri Aug 02, 2019 3:02 am 
Offline

Joined: Wed Oct 17, 2018 9:56 am
Posts: 19
Thank you for the suggestion! I fixed my error!

Now it only remains one problem, though.
I'm still getting a Page Fault while working with the memory map.

I get the address of it from GRUB:
Code:
memory_map_t *mmap = mbt->mmap_addr;


Then following some Wiki advice I go with a while loop:
Code:
    while ((uint32_t)mmap < (mbt->mmap_addr + mbt->mmap_length)) {
        // Gonna push every free block if it isn't in the kernel + stack space
        printf("mmap = 0x%x\n", mmap);
        printf("mmap->size = 0x%x\n", mmap->size);
        printf("mmap->type = 0x%x\n\n", mmap->type);

        printf("mmap->base_addr_low = 0x%x\n", mmap->base_addr_low);
        printf("mmap->length_low = 0x%x\n", mmap->length_low);
        printf("mmap->base_addr_high = 0x%x\n", mmap->base_addr_high);
        printf("mmap->length_high = 0x%x\n", mmap->length_high);

        mmap = (memory_map_t *)((uint32_t)mmap + mmap->size + sizeof(mmap->size));
    }

It just prints the first mmap, though.
The page fault comes even if I only reference the members. There's no need to "jump" (at the end of the while) to #PF...

Can you help me?


Top
 Profile  
 
 Post subject: Re: GRUB memory map page faults
PostPosted: Fri Aug 02, 2019 3:37 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 1636
Xcp wrote:
It just prints the first mmap, though.
The page fault comes even if I only reference the members.

What address does it print for the first mmap? Have you identity-mapped that address?


Top
 Profile  
 
 Post subject: Re: GRUB memory map page faults
PostPosted: Fri Aug 09, 2019 7:37 am 
Offline

Joined: Wed Oct 17, 2018 9:56 am
Posts: 19
Oh f**k, sorry!
I enabled 4MB paging in the boot loader to load the kernel, but I want 4KB pages for the OS. Can I disable paging now and re-enable it with the init of the virtual memory manager?


Top
 Profile  
 
 Post subject: Re: GRUB memory map page faults
PostPosted: Fri Aug 09, 2019 7:49 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 1636
You can switch between 4kB and 4MB pages without disabling paging.

If you want to disable and then re-enable paging, you need to make sure everything you want to access while paging is disabled is identity-mapped, including the code that's running and the stack.


Top
 Profile  
 
 Post subject: Re: GRUB memory map page faults
PostPosted: Sat Aug 10, 2019 11:46 am 
Offline

Joined: Wed Oct 17, 2018 9:56 am
Posts: 19
Ok, so I'm gonna make a new Page Directory and Page Table where I map the first MB of the RAM (I'm pretty sure the IP register is executing at 3GB as the kernel is up there, though, right? So I'll need to map something like 0x0000000 - 0xC0000000 until 0x00010000 - 0xC0010000). Then I will switch from 4MB pages to 4KB ones setting the new Page Directory.

The mmap is at 0x100A8 address though, so can you please help me in mapping these addresses?
Theoretically just mapping 0 (physical) to 3GB (virtual) should work?


Top
 Profile  
 
 Post subject: Re: GRUB memory map page faults
PostPosted: Mon Aug 12, 2019 2:36 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 1636
You'd know better than I do what address your kernel is executing at.

You can map the physical location of the memory map to any virtual location, as long as you also translate any pointers you're using the same way. If you map physical address 0 to virtual address 3GB, then you'd need to add 0xC0000000 to the pointer. Note that you may need to redefine the multiboot structures to contain integers rather than pointers: there is no way to translate a pointer without invoking undefined behavior in C (not even by casting to an integer and back to a pointer), but it's completely fine if the integer you cast to a pointer was not originally derived from a pointer.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: MichaelPetch and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group