Stubborn Paging Bug.

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.
Post Reply
User avatar
astrocrep
Member
Member
Posts: 127
Joined: Sat Apr 21, 2007 7:21 pm

Stubborn Paging Bug.

Post by astrocrep »

Ok,

Note: my actual issue is below the code...

I have a simple physical page allocator... it has two main functions

Code: Select all

mm_alloc();  = This returns the PAGE of the first free page over 16mb, if there are any availible;

mm_allocl(); = This returns the PAGE of the first free page...
Now in my Virtual Mem Man, I have 3 main functions, init, a mapper, and then a function to give me a buffer for a new pt
Here is the code for my init function...

Code: Select all

unsigned long *kernel_pd;	//This is the kernel Page Directory

int vmm_install()
{
	int i;
	char *test;
	unsigned long *pt;
	
	kernel_pd = (unsigned long *) (mm_allocl() * 4096);
	
	for (i = 0; i < 1024; i++)
	{
		kernel_pd[i] = 0 | 2;
	}
	
	//Now, we will init the whole pd w/ 1 pt (1:1 for 0-4mb) and the rest blank
	kernel_pd[0] = (mm_allocl() * 4096);
	vmm_create_pt1to1(kernel_pd[0], 3, 0);
	kernel_pd[0] = kernel_pd[0] | 3;
	
	pt = (unsigned long *) (mm_allocl() * 4096);
	
	for (i = 0; i < 1024; i++)
	{
		pt[i] = 0 | 2;
	}
	
	kernel_pd[128] = pt;
	kernel_pd[128] = kernel_pd[128] | 3;
	
	//Map in 2 pages (8k) at 1gb for use later w/ the kernel malloc...
	vmm_map(262144,mm_alloc());
	vmm_map(262145,mm_alloc());
	
	vmm_set_pd(kernel_pd);
	vmm_enable_paging();
}
Here is the code for my mapping function. Basically, you give it a virtual page, and a physical page, and it will map the rest.

Code: Select all

int vmm_map(unsigned long virt_page, unsigned long phys_page)
{
	int pd_index;
	int pt_index;
	unsigned long *pt;
	
	pd_index = virt_page / 1024;
	kprintf("pd_index = %d\n", pd_index);
	
	pt = (unsigned long *)kernel_pd[pd_index];
	
	if (pt == (unsigned long *)2)
		pt = (unsigned long *) vmm_new_pt(); //(mm_allocl() * 4096); create a new page table.
	else
		pt = (unsigned long *) (kernel_pd[pd_index] & 0xFFFFF000);

	pt_index = ((virt_page * 4096) - (pd_index * 0x400000)) / 4096;
	kprintf("pt address = %d\n", pt);
	kprintf("pt_index = %d\n", pt_index);
	kprintf("phys page = %d\n", phys_page * 4096);
	pt[pt_index] = (phys_page * 4096) | 3;
	
	kernel_pd[pd_index] = pt;
	kernel_pd[pd_index] = kernel_pd[pd_index] | 3;
}
Lastly, this guy gets me a new pt.

Code: Select all

unsigned long vmm_new_pt()
{
	int i;
	unsigned long *pt;
	
	pt = (unsigned long *) (kernel_pd[128] & 0xFFFFF000);	//Pointer for 512mb PT.
	
	for (i = 0; i < 1024; i++)
	{
		if (pt[i] == (unsigned long *)2)
		{
			pt[i] = (unsigned long *) (mm_alloc() * 4096);
			pt[i] = pt[i] | 3;
			kernel_pd[128] = pt;
			kernel_pd[128] = kernel_pd[128] | 3;
			kprintf("\nReturning: %d\n", 0x20000000 + (i * 4096));
			return (0x20000000 + (i * 4096));
		}
		
	}
}
The problem is in the mapper, or in the "new pt" function, I assume. The actual visual error is in my main:

Code: Select all

 s1 = (char*)malloc(100);
 strcpy(s1,"this is a test001\n\0");
 kprintf("%d || %s",s1,s1);
As far as I can tell the issue is coming from here: (in the mapper)

Code: Select all

pt = (unsigned long *) vmm_new_pt(); //(mm_allocl() * 4096);
When I do that, s1 has the proper address... but it prints out total garbage... if I get the new mm_allocl() * 4096 it works flawlessly, and s1 gives its message.

The issue is the first 4mb is mapped 1:1 and in this case mm_allocl * 4096 returns a value in the first 4mb, so its actually there. What I was trying to do in the vmm_new_pt function is set aside 512m - 516m (virtual) for the page tables. When a request for a new pt would come in, it would alloc a physical buffer and map it somewhere between 512 and 516, then return this 51x address. This way the PT could be placed there in virtual ram.

Big Thanks in Advance.

-Rich
User avatar
astrocrep
Member
Member
Posts: 127
Joined: Sat Apr 21, 2007 7:21 pm

Post by astrocrep »

Could this be because I need to invalidate the PT for the new pte I am creating?

-Rich
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

One: if you have tried it, you'd know the answer.

Two: do you have a .rodata in your linker script?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
astrocrep
Member
Member
Posts: 127
Joined: Sat Apr 21, 2007 7:21 pm

Post by astrocrep »

1.) I thought of it while I am at work... I won't be able to try it till later.

2.) This is my linker.ld

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(4096);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(4096);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(4096);
  }
  end = .;
}
Thanks,
Rich
User avatar
astrocrep
Member
Member
Posts: 127
Joined: Sat Apr 21, 2007 7:21 pm

Post by astrocrep »

Fixed...

-Rich
Post Reply