OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 3:58 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Bad Code After Enabling Paging
PostPosted: Tue Nov 05, 2019 5:12 am 
Offline

Joined: Tue Nov 05, 2019 2:09 am
Posts: 4
Hey,
I'm following James Molloy's OS Development tutorial.
I'm in Paging chapter, and I'm having trouble getting it to work.
I use QEMU to run the ISO and GDB to debug the code.
Everything works until I reach the enablePaging function (xor cr0 with 0x80000000), and afterwards the code that starts executing is garbage.

(In GDB)
Code before enabling paging:
Code:
   0x101438 <_enable_paging+1>:   mov    ebp,esp
   0x10143a <_enable_paging+3>:   mov    eax,cr0
   0x10143d <_enable_paging+6>:   or     eax,0x80000000
=> 0x101442 <_enable_paging+11>:   mov    cr0,eax
   0x101445 <_enable_paging+14>:   mov    esp,ebp
   0x101447 <_enable_paging+16>:   pop    ebp
   0x101448 <_enable_paging+17>:   ret   
   0x101449 <gdt_dump>:   mov    eax,DWORD PTR [esp+0x4]

Registers:
eax            0x80000011          0x80000011
ecx            0xb8000             0xb8000
edx            0x10077c            0x10077c
ebx            0x10000             0x10000
esp            0x107c38            0x107c38
ebp            0x107c38            0x107c38
esi            0x0                 0x0
edi            0x0                 0x0
eip            0x101442            0x101442 <_enable_paging+11>
eflags         0x286               [ PF SF IF ]
cs             0x8                 0x8
ss             0x10                0x10
ds             0x10                0x10
es             0x10                0x10
fs             0x10                0x10
gs             0x10                0x10


After (one single step):
Code:
   0x10143f <_enable_paging+8>:   add    BYTE PTR [eax],al
   0x101441 <_enable_paging+10>:   add    BYTE PTR [eax],al
   0x101443 <_enable_paging+12>:   add    BYTE PTR [eax],al
=> 0x101445 <_enable_paging+14>:   add    BYTE PTR [eax],al
   0x101447 <_enable_paging+16>:   add    BYTE PTR [eax],al
   0x101449 <gdt_dump>:   add    BYTE PTR [eax],al
   0x10144b <gdt_dump+2>:   add    BYTE PTR [eax],al
   0x10144d <gdt_dump+4>:   add    BYTE PTR [eax],al

Registers:
eax            0x80000011          0x80000011
ecx            0xb8000             0xb8000
edx            0x10077c            0x10077c
ebx            0x10000             0x10000
esp            0x107c38            0x107c38
ebp            0x107c38            0x107c38
esi            0x0                 0x0
edi            0x0                 0x0
eip            0x101445            0x101445 <_enable_paging+14>
eflags         0x286               [ PF SF IF ]
cs             0x8                 0x8
ss             0x10                0x10
ds             0x10                0x10
es             0x10                0x10
fs             0x10                0x10
gs             0x10                0x10


Here is my code (some of my coding conventions may seem weird):
Code:
void kernel::paging::start()
{
    // allocate array of frame indexes
    nframes = (K_PHYSICAL_MEM_SIZE / K_PAGE_SIZE);
    frames = (uint32_t*)heap::allocate(INDEX_FROM_BIT(nframes), false);
    memset(frames, 0, INDEX_FROM_BIT(nframes));

    // TODO: When I implement new, change this to calling the constrcutor of page_directory_t
    kernel_directory = (page_directory_t*)heap::allocate(sizeof(page_directory_t));
    memset(kernel_directory, 0, sizeof(page_directory_t));

    // we are currently using this directory
    current_directory = kernel_directory;

    // identity map the kernel
    uint32_t i = 0;
    while(i < __kernel_heap)
    {
        frame::alloc(get_page(
                i,
                kernel_directory,
                true
                ), // we want to create all pages in directory
            false, // this directory is the kernel's
            false // kernel directory is1 not writeable from user space
        );
        i += PAGE_SIZE;
        printf("loop %d\n", i);
    }

    interrupts::set_handler((uint32_t)InterruptList::PageFault, __page_fault_handler);

    // this will enable paging
    set_directory(kernel_directory);
    paging::enable(); // just calls _enable_paging
}

void kernel::paging::set_directory(page_directory_t* dir)
{
    current_directory = dir;
    _load_page_directory((uint32_t*)&dir->tables_physical);
}

page_t* kernel::paging::get_page(uint32_t address, page_directory_t* dir, bool create)
{
    address /= PAGE_SIZE;

    uint32_t table_idx = address / 1024;

    // if we find an existing table, return it
    if (dir->tables[table_idx] != nullptr)
    {
        return &dir->tables[table_idx]->pages[address%1024];
    }

    // if no, create one and return it
    if (create)
    {
        uint32_t table_ptr = 0;
        dir->tables[table_idx] = (page_table_t*)heap::allocate_p(
            sizeof(page_directory_t),
            &table_ptr // save the physical address
        );
        memset(dir->tables[table_idx], 0, PAGE_SIZE);
        dir->tables_physical[table_idx] = table_ptr | 0x7; // PRESENT, RW, US
        return &dir->tables[table_idx]->pages[address%1024];
    }

    return (page_t*)PAGE_NOT_FOUND;
}


I've been searching for an explenation for this kind of mistake, but haven't found any.
Could someone please help me with my error or point me as to how I might fix this?
Thanks in advance!


Top
 Profile  
 
 Post subject: Re: Bad Code After Enabling Paging
PostPosted: Tue Nov 05, 2019 5:17 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
It looks like you haven't identity mapped the page(s) that your code is running in (or haven't done it correctly). So as soon as you enable paging you are pointing to a different physical address.

You need to either (a) identity map the pages that the kernel occupies or (b) before paging copy the code to the pages that you have mapped its address range to.


Top
 Profile  
 
 Post subject: Re: Bad Code After Enabling Paging
PostPosted: Tue Nov 05, 2019 11:18 am 
Offline

Joined: Tue Nov 05, 2019 2:09 am
Posts: 4
iansjack wrote:
It looks like you haven't identity mapped the page(s) that your code is running in (or haven't done it correctly). So as soon as you enable paging you are pointing to a different physical address.

You need to either (a) identity map the pages that the kernel occupies or (b) before paging copy the code to the pages that you have mapped its address range to.


Hey,
I define my __kernel_heap like this:

Code:
uint32_t __kernel_heap = (uint32_t)&end; // this will be the beginning of the kernel's heap


where "end" is defined by the linker like this:

Code:
ENTRY(_start)
SECTIONS
{

    .text 0x100000 :
    {
        code = .; _code = .; __code = .;
        *(.multiboot)
      *(.text)
        . = ALIGN(4096);
    }

    .data :
    {
        data = .; _data = .; __data = .;
        *(.data)
        *(.rodata)
        . = ALIGN(4096);
    }

    .bss :
    {
        bss = .; _bss = .; __bss = .;
        *(.bss)
        . = ALIGN(4096);
    }

    end = .; _end = .; __end = .;
}


Since I identity map all the way from 0 to __kernel_heap, shouldn't all of the program's code be identity mapped as well already?


Top
 Profile  
 
 Post subject: Re: Bad Code After Enabling Paging
PostPosted: Tue Nov 05, 2019 12:03 pm 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
You certainly map that address range, but I'm not convinced that you identity map it. I don't see enough of your code to be sure. The other possibility is that you clear a physical page when you allocate.

Your best bet is to set a breakpoint just before you enable paging, then check the page table.


Top
 Profile  
 
 Post subject: Re: Bad Code After Enabling Paging
PostPosted: Sat Nov 09, 2019 6:27 am 
Offline

Joined: Tue Nov 05, 2019 2:09 am
Posts: 4
I fixed the problem!

For future generations:
I'm not exactly sure where I had it wrong, but I suspect it was with the frame allocations.
I the paging with my own design and understanding of Paging (still heavily relying on the tutorial) and it worked!
I used a normal boolean array instead of a BITSET. Now that I know it works, I'll be changing the implementation to use a bitset instead.


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: SanderR and 66 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