Page 1 of 1

Help with Quick_And_Dirty_Virtual_Address_Space_Scheme

Posted: Mon Apr 30, 2007 8:39 am
by sparky
Good afternoon, wondering if anyone can help with a question i have about the article http://www.osdev.org/wiki/Quick_And_Dir ... ace_Scheme

Its a really good and informative article, but im a bit stuck/confused with the function:

Code: Select all

void pmm_init(unsigned int page, unsigned int count){
	if(g_pmm_map == 0){
		if(count >= g_pmm_reqpages){
			g_pmm_map = (unsigned char*)page;
			page += (count<<12);
			count -= g_pmm_reqpages;
			pmm_strip((unsigned int)g_pmm_map, g_pmm_reqpages);
		}else{
			return;
		}
	}
	for(x = 0; x < count; ++x){
		g_pmm_map[(page>>12)+x] = 0;
	}
	return;
}
I understand the for loop at the end, but i cant seem to work out what are "sensible" arguments to the function, any i use or think appropriate result in either the pmm_map not getting "populated" or somethin else that i dont think it should be doing.

Thanks in advance.

Posted: Mon Apr 30, 2007 1:48 pm
by Kevin McGuire
I had to go look that back up and figure out what in the world I was doing.

Take a look at this one:
/// EDITED ///
See the next post below. I changed something else.
////////////////

I think it was my screw up.

page += (count<<12);
Should Be:
page += (g_pmm_reqpages<<12);


I appreciate you bringing that to my attention. I think I wrote all the code in that tutorial with out actually testing it. I mean I based it completely off what is in my own kernel, but some parts were cleaned up and made easier to use and thus get some of those little funny bugs because I forgot about actually testing it.

Sorry. :cry:

Posted: Mon Apr 30, 2007 2:03 pm
by Kevin McGuire
A correct argument example would be one of the such:

pmm_init(0x2090A200, 0xC00);

This would say: Tell the physical memory manager to denote the memory address 0x2090A200 and then 0xC00 pages afterward as free.

0x2090A200 = 20MB
0xC00000 = 12MB (0xC00 = How many pages in twelve megabytes.)

20MB + 12MB = 32MB

So in the case above you would have told the physical memory manager that the memory range between 20MB and 32MB is free to use.

I actually have to fix the function again as I foresee another bug. I now have a extra loop to set all bytes to the initial value of five which should help in cases where you might use pmm_setmaxmem for lets say thirty-two megabytes of RAM, but in the process of doing so the memory used by the bitmap (g_pmm_map) may become filled with zeros from the default state of RAM in the machine when turned on or something similar. So I use a value of five instead to repersent existing memory in the machine, but not in a freed or allocated state.

Code: Select all

void pmm_init(unsigned int page, unsigned int count){
	unsigned int x;
	if(g_pmm_map == 0){
		if(count >= g_pmm_reqpages){
			g_pmm_map = (unsigned char*)page;
			page += (g_pmm_reqpages<<12);
			count -= g_pmm_reqpages;
			pmm_strip((unsigned int)g_pmm_map, g_pmm_reqpages);
			for(x = 0; x < ((g_pmm_reqpages-1)<<12); ++x){
				g_pmm_map[x] = 5;
			}
		}else{
                        __PRINT___ERROR__MESSAGE__;
			return;
		}
	}
	for(x = 0; x < count; ++x){
		g_pmm_map[(page>>12)+x] = 0;
	}
	return;
}
I am so sorry for my tutorial causing you the least bit of trouble. My sincere apologies are due. I do really appreciate you taking the time to ask about it since it jump starts my brain into gear so I can fix these things.

Posted: Mon Apr 30, 2007 2:09 pm
by sparky
Dude, dont apologise, I really appreciate that people like yourself have taken the time to try and teach and tutor people like myself. Its hard to find good, comprehensive documentation aimed at the "novice" level. And I think that by spending the time going through it and any "mistakes" have possibly helped me understand it better, I've been tracing the code through on paper and the like, and have really got my head around alot of key issues.

So thanks again for a really good tutorial. :)

Posted: Mon Apr 30, 2007 2:20 pm
by Kevin McGuire
If I died today I would die a happy person. I do not care how much digging I have to do tomorrow at work with the shovel I am going to have fun doing it!

Posted: Mon Apr 30, 2007 4:45 pm
by sparky
Kevin McGuire wrote: 0x2090A200 = 20MB
U sure?

0x1400000 = 20Mb by my maths, but ive had a long and stressful day :)

Posted: Mon Apr 30, 2007 5:31 pm
by Kevin McGuire
Yeah. I just did it again and got 0x1400000. You are right.

I think, I accidentally left my calculator in hexadecimal mode when doing 1024*1024*20.

I also screwed up again in the math up in the function I posted. I finished converting the tutorial to dokuwiki on my own site. I think I fixed the problem this time. :x

I know what I am thinking. I just always find it hard to get it right on paper.
http://kmcguire.jouleos.galekus.com/dok ... ace_scheme

Posted: Mon Apr 30, 2007 7:18 pm
by sparky
Sweet, thanks for confirming that. I've noticed something else tho...

Code: Select all

if(count >= g_pmm_reqpages)
How or why would someone request more pages than g_pmm_reqpages? Isnt g_pmm_reqpages set to the amount of pages spanning our total amount of memory?

In your example, count would be 0xC00 pages (no. of pages spanning 12MB) but g_pmm_reqpages would be 0x1400 (no. of pages spanning 20MB) so the test would be false, and we'd just return from the function? :(

Posted: Mon Apr 30, 2007 8:08 pm
by Kevin McGuire
I had to change another function which I forgot the /4096 on the end. This might be where you are getting confused since the old copy has a bug in it here too which I found earlier. :cry:

Code: Select all

void pmm_setmaxmem(unsigned int max){
	g_pmm_reqpages = ((max>>12)+1)/4096;
}
(1024*1024*32) = 0x2000000 >> 12 = 0x2000 / 4096 = 0x2

So for a system with thirty-two megabytes of memory we need two pages for the byte map.

pmm_setmaxmem(32MB);
pmm_init(20MB, 12MB);

I normally like to use the GRUB memory map. What I do is do this same calculation then walk through the GRUB memory map looking for a range of pages that are free and >= ((max>>12)+1)/4096. Then I hand this to pmm_init first to ensure that it had enough to create the byte map. After that I just chunk the rest right into to it with out thinking about it.

Let me know if you see anything else really strange. It is most likely a bug of mine. I really do appreciate you taking the time to tell me about these things. :)

Posted: Mon Apr 30, 2007 8:37 pm
by sparky
Ah, its all becoming clear now, I remember in the initial tutorial, u mentioned requiring shifting twice to firstly get the total number of pages to span the memory, and then shift again to get the number of pages needed for the bytemap. I then got confused when the code didnt contain two shifts, and just ignored it, thinking I'd misread it...

Ah well, im now alot more confident with bits, bytes, converting between diff bases and physical memory management.

Really appreciate the speed and "fullness" of your replies, it's really helped. 4am my time, so time for sleep.

PS. I'll let you know if i find any more quirks in the code :)

Posted: Tue May 01, 2007 4:22 am
by sparky

Code: Select all

unsigned int pmm_alloc(void){
	unsigned int x;
	for(x = 0; x < g_pmm_reqpages; ++x){
		if(g_pmm_map[[x]] == 0){
			g_pmm_map[[x]] = 1;
			return (x<<12);
		}
	}
}
Shouldnt the condition in the for loop be, x < g_pmm_reqpages*4096 or possibly x < g_pmm_reqpages<<12

Hmm, I'm confused as to whether we want g_pmm_reqpages to contain the size of the pagemap or the number of pages in that map? :?

The number of pages sounds more ideal to me, but then code in the init function will need to be modified.

Posted: Tue May 01, 2007 4:48 pm
by Kevin McGuire
Yeah. I think you are right. It should transverse the map byte by byte.

Code: Select all

unsigned int pmm_alloc(void){
   unsigned int x;
   for(x = 0; x < (g_pmm_reqpages<<12); ++x){
      if(g_pmm_map[[x]] == 0){
         g_pmm_map[[x]] = 1;
         return (x<<12);
      }
   }
} 
Yeah, g_pmm_reqpages holds the number of pages the bitmap takes. Let me go fix that one too. :cry:

I really do appreciate you're time helping me find these bugs. I will credit you're name to the tutorial for helping make it a "good" tutorial.
http://kmcguire.jouleos.galekus.com/dok ... eme#thanks

[push the edit page button]
Just go edit that if you like, and change the name to include a internet mail address or anything you like. As far as I am concerned with out the feed back it would not be worth anything. (You're profile just showed a user name.)

Posted: Wed May 02, 2007 8:11 am
by sparky
Edited the #thanks but not sure I deserve it, I'm just pointing things out because I dont understand them, someone with an understanding probably wouldn't notice :)

Once I've finished my memory manager, I'll check over the tutorial again to check that everything works as it is expected, since my memory manager is quite closely based upon the tutorial. :P