Page 1 of 1

Strange problems with paging in higherhalf kernel

Posted: Wed Oct 05, 2005 12:23 pm
by Freanan
I still have several problem-symptoms (with, as i hope, the same reason), since i changed over to a higherhalf kernel. Since the problems get more and i am trying to debug it from time to time, i decided to move it out of the isr-related thread were it started...
It seems to be a mapping-issue, after all.

First strange thing is, that the following line lets my code crash with
"running in bogus memory".
This also happens, when i change "read_pagedir_seg()" to "page_dir" (which is
a variable that holds the same value, ie the page dir's adress).
So i actually don't change anything, but when i leave this line in, it breaks.
The code is taken from a function, where i set up my own paging data.
Mapping should be the same as after the execution of the higherhalf barebones,
just that i use a page table filled with 4kb pages instead of a single 4mb page.
Anyway, it works and maps, as it seems (i tried putnum(physical(page_dir)),
which produced a plausible output), correctly when i leave the following
line out and crashes with the line included.

Code: Select all

set_pagedir_seg(read_pagedir_seg()-0xc0000000);   //--> "running in bogus memory"
Next problem...
Adding integer constants, maybe in form of printed debugging messages, causes
the output to "break" (at a certain point, an infinite number of blanks is
printed).
I thought that maybe my kernel is too large to fit into the 4mb that i
mapped so that the strings are not were they are supposed to be and are not
printed thus, but actually my kernel ends at 0xc010a9c0, which is not larger then
0xc0000000+4mb, or am i wrong there?

Really strange is the fact that my change of an entry in the page_dir did not work as it
should. Finally i tried to use the value that needs to be written to that
entry as a literal constant, as seen below.
Still when i print it there is not the value i wrote to it, but 0xffffffff.
Actually this seems to me like another sign for a kernel that is too large for
the mapping - but as i said, my kernel image seems not to be that large.
Also there should be a pagefault then, right..?

Code: Select all

page_dir[entry]=0x2d003;          //tried to use the actual value as a constant
putnum(page_dir[entry],16);         //output: 0xffffffff (!)
I think all this points to a mapping problem, but i tested all kinds of stuff,
like printing out the physical and virtual adresses of things, having used
adresses and so on loged by my kernel and all outputs made sense.
Thus i am really stuck and would be thankfull for some suggestions and
ideas...
Thanks in advance!

Re:Strange problems with paging in higherhalf kernel

Posted: Wed Oct 05, 2005 1:46 pm
by bluecode
hi,

you should really give us more code. Perhaps the function that maps the memory and some info about your memory layout (I can't figure out what read_pagedir_seg()-0xc0000000 should mean?)
You could also attach a file ;)

Re:Strange problems with paging in higherhalf kernel

Posted: Wed Oct 05, 2005 2:34 pm
by Freanan
OK ;) !

My virtual memory is laid out thus that the first 4mb of physical memory are mapped to start at offset 0xc0000000, ie the higher half of virtual memory.
Thus when i want to calculate a physical adress the silly way (instead of looking it up in page dir and page tables, as the mmu does it), which seems inevitable on some occassions, i substract 0xc0000000.
The first time this mapping is done in the assembler-setup routine - exactly like in the "higher half barebones" in the faq. Inside my kernel i overwrite it, so that the mapping stays the same actually, but instead of a single 4mb page i am using a page table full of 4kb pages from there on.
I decided to do this because i want to be sure that i know were my page directory is, and on a less rational level, because it seemed to be required (it fixed some other bug some time ago)...

Well, here is my setup_paging function, which should actually be called reset_paging()...

Code: Select all

//Reset paging for the first 4MB of higher half of physical memory
void setup_paging()
{
   int i;
   adress_t adress;
   adress=0;

   //Read pagedir adress from cr3,add 0xc0000000 to get the virtual adress
   adress_t* pagedir=(adress_t*)((adress_t)read_pagedir_seg()+0xC0000000);
   
   //Fill up the pagetable to point to the physical adresses 0-0x00100000
   for(i=0; i<1024; i++)
   {
      set_pagetableentry(i, adress, page_table, 3);
      adress+=4096;
   };

   //Add empty entries to the pagedir...
   for(i=0; i<0xC0000000>>22; i++)
      set_pagedirentry(i, pagedir, 0, 2);
   
   //Add the created page table at the right place
   set_pagedirentry(0xC0000000>>22, pagedir, page_table-0xC0000000, 3);

   //Fill in more empty entries
   for(i=(0xC0000000>>22)+1; i<1024; i++)
      set_pagedirentry(i, pagedir, 0, 2);

   update_tlb(0xC0000000>>22);
       //cut out that line, as it causes the described error:
       //set_pagedir_seg(page_dir-0xc0000000);
};
The subfunctions that are called should be all correct, because they used to work back when i was running in identity-mapped memory.

Actually the mapping shows no sign of errors, except the described bugs.
I can output the physical adresses of data (physical adress is calculated the proper way, not by simply substracting 0xc0000000) and the output makes perfect sense, for example
putnum(page_dir,16);
putnum(physical(page_dir),16);
output: c0103000; 103000 - that's exactly what it should...

The error were i try to write to a pagedir entry and the value is still 0xffffffff happens below that function, when i do more mapping, in order to map the multiboot info from grub to existing memory.
The error with the string constants happens no matter if i do the additional re-mapping or not.

Re:Strange problems with paging in higherhalf kernel

Posted: Thu Oct 06, 2005 10:25 am
by Freanan
Okay, i tried out more things and came to the conclusion that having a too large kernel can't be the cause for the problem with writing to "mbi_page_table".
I output the virtual and physical adress of the table entry i want to write and both are "correct" ie the entry-adress is in the boundaries of my mapped memory and it's physical adress is as expected virtual-0xc0000000.

Code: Select all

   putnum((adress_t)(mbi_page_table+entry), 16);                 //virtual write addr
   putnum(physical((adress_t)(mbi_page_table+entry)), 16);  //phys. write addr
   mbi_page_table[entry]=0x2d003;                    //writing, const. for testing
   putnum(mbi_page_table[entry],16);                 //printing to check
resulting output:

Code: Select all

C01050B4     //plausible
     1050B4     //fits in
FFFFFFFF      //should be 2d003. arg!
Everything seems to be maped the right way, still writing to the var does not work... That's the most seemingly irrational thing i experienced in coding ever...
And actually, it is the main problem at the moment.