Help with tutorial? [Paging]

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.
User avatar
GeniusCobyWalker
Member
Member
Posts: 65
Joined: Mon Jan 12, 2009 4:17 pm

Re: Help with tutorial?

Post by GeniusCobyWalker »

well, :roll: I have been trying to get this to work for like Forever.
I have tried numerious things. So i decided just to completely use
his just to see if I can get it to work. So after Small mods to fit my kernel
here is the code: (includes are the same (except paging(init(Hi)) )

Code: Select all

//Paging.c Memory Paging

#include <ia32/paging.h>
#include <kheap.h>
#include <monitor.h>

// The kernel's page directory
page_directory_t *kernel_directory=0;

// The current page directory;
page_directory_t *current_directory=0;

// A bitset of frames - used or free.
u32int *frames;
u32int nframes;

// Defined in kheap.c
extern u32int placement_address;

// Macros used in the bitset algorithms.
#define INDEX_FROM_BIT(a) (a/(8*4))
#define OFFSET_FROM_BIT(a) (a%(8*4))

// Static function to set a bit in the frames bitset
static void set_frame(u32int frame_addr)
{
    u32int frame = frame_addr/0x1000;
    u32int idx = INDEX_FROM_BIT(frame);
    u32int off = OFFSET_FROM_BIT(frame);
    frames[idx] |= (0x1 << off);
}

// Static function to clear a bit in the frames bitset
static void clear_frame(u32int frame_addr)
{
    u32int frame = frame_addr/0x1000;
    u32int idx = INDEX_FROM_BIT(frame);
    u32int off = OFFSET_FROM_BIT(frame);
    frames[idx] &= ~(0x1 << off);
}

// Static function to test if a bit is set.
static u32int test_frame(u32int frame_addr)
{
    u32int frame = frame_addr/0x1000;
    u32int idx = INDEX_FROM_BIT(frame);
    u32int off = OFFSET_FROM_BIT(frame);
    return (frames[idx] & (0x1 << off));
}

// Static function to find the first free frame.
static u32int first_frame()
{
    u32int i, j;
    for (i = 0; i < INDEX_FROM_BIT(nframes); i++)
    {
        if (frames[i] != 0xFFFFFFFF) // nothing free, exit early.
        {
            // at least one bit is free here.
            for (j = 0; j < 32; j++)
            {
                u32int toTest = 0x1 << j;
                if ( !(frames[i]&toTest) )
                {
                    return i*4*8+j;
                }
            }
        }
	
    }
return 0;
}

// Function to allocate a frame.
void alloc_frame(page_t *page, int is_kernel, int is_writeable)
{
    if (page->frame != 0)
    {
        return;
    }
    else
    {
        u32int idx = first_frame();
        if (idx == (u32int)-1)
        {
            // PANIC! no free frames!!
        }
        set_frame(idx*0x1000);
        page->present = 1;
        page->rw = (is_writeable)?1:0;
        page->user = (is_kernel)?0:1;
        page->frame = idx;
    }
}

// Function to deallocate a frame.
void free_frame(page_t *page)
{
    u32int frame;
    if (!(frame=page->frame))
    {
        return;
    }
    else
    {
        clear_frame(frame);
        page->frame = 0x0;
    }
}

void init_paging(unsigned int Hi)
{
    // Hi is a variable telling how Bootloader said big memory is//
    u32int mem_end_page = Hi;
    
    nframes = mem_end_page / 0x1000;
    frames = (u32int*)kmalloc(INDEX_FROM_BIT(nframes));
    memset(frames, 0, INDEX_FROM_BIT(nframes));
    
    // Let's make a page directory.
    kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
    current_directory = kernel_directory;

    // We need to identity map (phys addr = virt addr) from
    // 0x0 to the end of used memory, so we can access this
    // transparently, as if paging wasn't enabled.
    // NOTE that we use a while loop here deliberately.
    // inside the loop body we actually change placement_address
    // by calling kmalloc(). A while loop causes this to be
    // computed on-the-fly rather than once at the start.
    int i = 0;
    while (i < placement_address)
    {
        // Kernel code is readable but not writeable from userspace.
        alloc_frame( get_page(i, 1, kernel_directory), 0, 0);
        i += 0x1000;
    }
    // Before we enable paging, we must register our page fault handler.
    register_interrupt_handler(14, &page_fault);

    // Now, enable paging!
    switch_page_directory(kernel_directory);
}

void switch_page_directory(page_directory_t *dir)
{
    current_directory = dir;
    asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
    u32int cr0;
    asm volatile("mov %%cr0, %0": "=r"(cr0));
    cr0 |= 0x80000000; // Enable paging!
    asm volatile("mov %0, %%cr0":: "r"(cr0));
}

page_t *get_page(u32int address, int make, page_directory_t *dir)
{
    // Turn the address into an index.
    address /= 0x1000;
    // Find the page table containing this address.
    u32int table_idx = address / 1024;
    if (dir->tables[table_idx]) // If this table is already assigned
    {
        return &dir->tables[table_idx]->pages[address%1024];
    }
    else if(make)
    {
        u32int tmp;
        dir->tables[table_idx] = (page_table_t*)kmalloc_ap(sizeof(page_table_t), &tmp);
        dir->tablesPhysical[table_idx] = tmp | 0x7; // PRESENT, RW, US.
        return &dir->tables[table_idx]->pages[address%1024];
    }
    else
    {
        return 0;
    }
}


void page_fault(registers_t regs)
{
    // A page fault has occurred.
    // The faulting address is stored in the CR2 register.
    u32int faulting_address;
    asm volatile("mov %%cr2, %0" : "=r" (faulting_address));
    
    // The error code gives us details of what happened.
    int present   = !(regs.err_code & 0x1); // Page not present
    int rw = regs.err_code & 0x2;           // Write operation?
    int us = regs.err_code & 0x4;           // Processor was in user-mode?
    int reserved = regs.err_code & 0x8;     // Overwritten CPU-reserved bits of page entry?
    int id = regs.err_code & 0x10;          // Caused by an instruction fetch?

    // Output an error message.
    m_text("Page fault! ( ");
    if (present) {m_text("present ");}
    if (rw) {m_text("read-only ");}
    if (us) {m_text("user-mode ");}
    if (id) {m_text("Instruction Error");}
    if (reserved) {m_text("reserved ");}
    m_text(") at 0x");
    m_text_hex(faulting_address);
    m_text("\n");
    while (1) {}
}
Full Knowledge in:
GML, Ti-Basic, Zilog Z80 Assembly, SX28 Assembly and Blender
Experience in:
C++,OpenGl,NDS C++,Dark Basic,Dark Basic Pro,Dark Gdk and PSP Coding
Using:
Ubuntu ,GEdit ,NASM ,GCC ,LD ,Bochs
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Help with tutorial? [Paging]

Post by neon »

well, :roll: I have been trying to get this to work for like Forever.
You have not been working on it long enough to warrant saying that. What have you tried already? Have you verified that your kmalloc_ap and other kmalloc routine work by themselves without error?

I have noticed that you have #include <kheap.h>. Be very cautious if you are using the routines in it. If you are, take it out and focus on just the physical frame allocator first. After you have verified all of the routines work as expected, then focus on the paging code and paging code alone. (The specific paging tutorial that you are referring to does not have it.)

Sorry, but I cannot test the code - it is too much centric to your OS. Perhaps JamesM has comments on it.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
gravaera
Member
Member
Posts: 737
Joined: Tue Jun 02, 2009 4:35 pm
Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.

Re: Help with tutorial? [Paging]

Post by gravaera »

Hi: @OP: try to slow down. Take the time to read. A lot. Reading isn't googling and skimming. Try grappling with multiple articles. BTW, it seems that JamesM is fixing to release anew set of Tutorials. You could look forward to that.

Take the time to slow down and draw out diagrammatic representations of what you think Memory Management is. I find it useful to use a physical diary as my 'Development Diary', and for more than one topic of difficulty, I found myself writing out essays in the 1st person and rationalizing the issue.

One thing I found that was really confusing, for example, was understaning the distinction between Paging and Segmentation, and where the faciities they provide differentiated, and where they phased together to provide said functionality.

Try writing out the fundamentals, and reading through the material again. Challenge yourself to find out the whys. And keep a calculator handy while plotting how you're going to do your MM.

Another thing to keep in mind is that you don't use a tutorial, but you read it and pick up the relevent bits and factor them out for reuse. Then you draft out your own custom solution. So hopefully, the answer to the last line of your last post on the first page of this topic,

"Has anyone else used that Tutorial and had success?"

...is no. Get the concept, grasp the rules of its application, and use it as you see fit.

All the best.
-gravaera
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.
earlz
Member
Member
Posts: 1546
Joined: Thu Jul 07, 2005 11:00 pm
Contact:

Re: Help with tutorial? [Paging]

Post by earlz »

gravaera wrote:
Take the time to slow down and draw out diagrammatic representations of what you think Memory Management is. I find it useful to use a physical diary as my 'Development Diary', and for more than one topic of difficulty, I found myself writing out essays in the 1st person and rationalizing the issue.
I find that tiddlywiki is great for that purpose(unless of course you need to draw things out as sometimes needed)
Post Reply