basic 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.
GLneo

basic paging

Post 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
AR

Re:basic paging

Post 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?
GLneo

Re:basic paging

Post 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
}
proxy

Re:basic paging

Post 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
Mark

Re:basic paging

Post 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.
GLneo

Re:basic paging

Post by GLneo »

i think it is set up so it is vurtual = phys for now so that shouldn't hurt, should it???
AR

Re:basic paging

Post 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.
GLneo

Re:basic paging

Post 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 :)
AR

Re:basic paging

Post 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.
GLneo

Re:basic paging

Post 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???
AR

Re:basic paging

Post 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);
GLneo

Re:basic paging

Post 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??
AR

Re:basic paging

Post 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.
GLneo

Re:basic paging

Post 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
AR

Re:basic paging

Post 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)
Post Reply