Page 1 of 3

basic paging

Posted: Thu Jul 07, 2005 1:53 pm
by GLneo
hi all, ok, i've read the basic paging tutorial at osdever.net and when i start it just locks up here is my code:

Code: Select all

int read_cr0()
{
    int cr0;
    asm("movl %%cr0, %0":"=r"(cr0));
    return cr0;
}

void write_cr0(int cr0)
{
    asm("movl %0, %%cr0"::"r"(cr0));
}

int read_cr3()
{
    int cr3;
    asm("movl %%cr3, %0":"=r"(cr3));
    return cr3;
}

void write_cr3(int cr3)
{
    asm("movl %0, %%cr3"::"r"(cr3));
}

void set_paging()
{
    int x;
    unsigned long physaddr = 0;
    for(x = 0; x < 1024; x++)  // set a test table with liner addressing
    {
        page_table[x] = physaddr | read_write | present;
        physaddr += 4096;
    }    
    page_directory[0] = (int)page_table | read_write; // set test table to first in directory
    for(x = 0; x < 1024; x++) // fill directory with nonpresent pages
    {
        page_table[x] = 0 | read_write;
    }
    write_cr3((int)page_directory); // write pointer to cr3
    write_cr0(read_cr0() | 0x80000000); // set paging bit
}
any ideas (or a better way), thx :)

p.s. bochs says cr0 = 0x60000010, so that cant be good :o

Re:basic paging

Posted: Thu Jul 07, 2005 2:35 pm
by AR
The obivous problem is that you set page_directory[0 ] then start a loop filling the page table with 2s.

Can I ask what the usefulness of making a non-present page writable is?

Re:basic paging

Posted: Thu Jul 07, 2005 3:15 pm
by GLneo
1.) wow that was obivous :)
2.) no reason
3.) still crashes and cr0 is still crasy (but that might be becouse the crash resets the computer so it is not set???)

p.s. bochs says:

Code: Select all

00008311571e[CPU  ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting
here is my new code:

Code: Select all

void set_paging()
{
    int x;
    unsigned long physaddr = 0;
    for(x = 0; x < 1024; x++)  // set a test table with liner addressing
    {
        page_table[x] = physaddr | read_write | present;
        physaddr += 4096;
    }    
    page_directory[0] = (int)page_table | read_write; // set test table to first in directory
    for(x = 1; x < 1024; x++) // fill directory with nonpresent pages
    {
        page_directory[x] = 0 | read_write;
    }
    write_cr3((int)page_directory); // write pointer to cr3
    write_cr0(read_cr0() | 0x80000000); // set paging bit
}

Re:basic paging

Posted: Thu Jul 07, 2005 3:21 pm
by proxy
i've noticed bochs graphical debugger giving wrong results, so it may be correct or it might not be. double check that.

proxy

Re:basic paging

Posted: Thu Jul 07, 2005 3:34 pm
by Mark
Remember once you enable paging the code you are running must be mapped to the same address it was linked at. And dont for get the data segments and stack.

The way I set it all up was from my boot assembler map the kernel C code (linked for 0xc0000000 and placed at 0x00010000) and data and stack segs. I then enable paging and jump into C world.

Re:basic paging

Posted: Thu Jul 07, 2005 4:01 pm
by GLneo
i think it is set up so it is vurtual = phys for now so that shouldn't hurt, should it???

Re:basic paging

Posted: Thu Jul 07, 2005 6:03 pm
by AR
No it should be fine. The other problem is that you aren't setting present on the page table entry in the page directory.

Re:basic paging

Posted: Thu Jul 07, 2005 8:32 pm
by GLneo
thx ;D that fixed it, but now my progs dont work, but that is becuse there pages aren't "present", so heres what i'm trying, all my progs think there are at 0x01000000(and before paging there were), so what ill do is "malloc" a bit of mem to fit the prog, but how do i get:
vurtual(0x01000000) = phys(malloc(size)) ???

p.s. AR your good at spoting errors :)

Re:basic paging

Posted: Thu Jul 07, 2005 8:56 pm
by AR
You can't, all virtual memory operations operate on 4KB pages. What you need to do is put them in a unused physical page and map it at that address.

You should probably write a physical memory manager now as it'll save trouble later.

Re:basic paging

Posted: Thu Jul 07, 2005 9:03 pm
by GLneo
i dont understand , i do have a phys memory maneger???

mabey i am confused, i load my progs to mem, but how do i get them to think they are at a diferent position???

Re:basic paging

Posted: Thu Jul 07, 2005 9:07 pm
by AR
Something that keeps track of which physical 4KB pages are used and which ones aren't so that you can simply say:

Code: Select all

physpageptr_t pp = FindUnusedPage();
if(!pp)
    PANIC("No RAM left (TODO: Use paging file)");
MapPage(pp, 0x01000000);

Re:basic paging

Posted: Thu Jul 07, 2005 9:11 pm
by GLneo
so a mem manegment that can give out mem 4k page at a time???

so what does mappage do, and where exeactly does my prog go??

Re:basic paging

Posted: Thu Jul 07, 2005 9:21 pm
by AR
Usually the memory management system is layered: Physical Memory Manager > Virtual Memory Manager > Heap/Something.

MapPage is part of the Virtual Memory Manager, it maps the given physical page at the given virtual address (creates the page table if the page directory entry is missing, creates the page table entry).

If you just want to hack it for the time being you can alter your set function to create a second page table at the appropriate offset in the page directory.

Re:basic paging

Posted: Thu Jul 07, 2005 9:35 pm
by GLneo
well no need to hack it i have nothing else to work on, my old mm i think you showed me (linked-list), but i've mad an experamental page table based mm but it doesn't work hear is the code:

Code: Select all

typedef struct 
{
    unsigned char byte[4096];
}__attribute__ ((packed)) BITMAP;

static BITMAP *bitmap = (BITMAP *)0x200;

unsigned char set(unsigned int page, char set)
{
    page -= 1;
    if(set == -1)
        return (bitmap + ((page / (4096 * 8))*4096))->byte[(page % (4096 * 8)) / 8] & (1 << ((page % (4096 * 8)) % 8));
    else if(set)
        (bitmap + (page / (4096 * 8)) * 4096)->byte[(page % (4096 * 8)) / 8] |= set << ((page%(4096*8))%8);
    else if(!set)
        (bitmap + (page / (4096 * 8)) * 4096)->byte[(page % (4096 * 8)) / 8] &= (set << ((page%(4096*8))%8)) ^ 0xFF;
    return 0;
}

void *malloc(size_t sz)
{
    int pages, x, inerx, consecutive_pages_found = 0;
    pages = sz / 4096;
    if(sz % 4096)
        pages++;
    for(x = 0; x < page_count; x++)
    {
        if(!set(x, -1))
        {
            if(pages == 1)
            {
                set(x, 1);
                return (void *)0x100000 + (4096 * (x - 1));
            }
            for(inerx = x + 1; inerx <= page_count; inerx++)
            {
                if(!set(inerx, -1))
                {
                    consecutive_pages_found++;
                    if(consecutive_pages_found >= pages)
                    {
                        for(inerx = x; inerx < x + pages; inerx++)
                            set(inerx, 1);
                        return (void *)0x100000 + (4096 * (x - 1));
                    }
                }
                else
                {
                    consecutive_pages_found = 0;
                    x = inerx;
                    break;
                }
            }
        }
    }        
}
p.s. "set" sets a "page" to what is in "set" unless set == -1 then it returns what is in that page

Re:basic paging

Posted: Thu Jul 07, 2005 9:56 pm
by AR
That's sort of around a physical manager, you've just built it into malloc rather than having it as layer underneath malloc.

Code: Select all

byte_t *bitmap;
uint32_t NumPages;

void Initalise(byte_t *Bitmap, uint32_t PageCnt)
{
     bitmap = Bitmap;
     NumPages = PageCnt;
}

physpageptr_t FindFreePage()
{
      for(uint32_t i = 0 ; i < NumPages ; ++i)
            if((bitmap[i/8] & (1 << (i % 8))) == 0)
            {
                 bitmap[i / 8] |= 1 << (i % 8);
                 return (physpageptr_t) i * 4096;
            }

      return NULL;
}

void FreePage(physpageptr_t page)
{
      page /= 4096;
      /* Warning XOR will turn the bit ON if it is already off */
      bitmap[page / 8] ^= 1 << (i % 8);
}
(I've got a bit of a headache at the moment so I might have stuffed up the logic a bit, but you get the idea)