problem changing page table in bochs

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.
vjain20
Member
Member
Posts: 73
Joined: Wed Apr 04, 2012 9:12 pm

problem changing page table in bochs

Post by vjain20 »

Hi,

I am trying to copy the contents of two arrays to two different pages allocated by physical memory manager.
I have a function - vmmgr_temp_map_page() which maps any physical address to a fixed virtual address - 0xC0000000
so that I can write to that page using the fixed virtual address.
Now the problem is that at one point, when vmmgr_temp_map_page() is called, the page table entry is not getting modified.

Here is the code :

Code: Select all

char[] code_array = { ... }
char[] data_array = { ... }

void* code_frame = pmmgr_alloc_block();                       //Allocate a page 
void* code_virt = vmmgr_temp_map_page(code_frame);   //Map page to 0xC000 0000 << WORKS
char* dest = (char*)code_virt;

int j, k = 0;
//Copy contents of code_array to page
for(j = 0; j < 0x23 ; j ++)
{
  dest[j] =  code_array[j];
}

void* data_frame = pmmgr_alloc_block();                        //Allocate a page 
void* data_virt = vmmgr_temp_map_page(data_frame);     //Map page to 0xC000 0000    << DOESNT WORK
dest  = (char*)data_virt;

//Copy contents of data_array to page
for(k =0 ; k < 0x31; k++)
  {
    dest[k] = data_array[k];
  }
[/size]


Here the first call to vmmgr_temp_map_page() works but the second one doesn't.
The physical address of code_frame is 0x8000 and that of data frame is 0x116000.
I am using the command 'info tab' on bochs debugger to check the mappings. After the firs call to vmmgr_temp_map_page()
info tab shows the entry

Code: Select all

0xc0000000-0xc0000fff -> 0x0000000000008000-0x0000000000008fff
[/size]

but after second call also it shows the same entry.
Now the strange thing here is that when I check the page table entry using the physical address of the page table
it shows that the entry is changed after the second call but 'info tab' still shows the old entry.

Code: Select all

<bochs:5> xp /4bx 0x2000
[bochs]:
0x00002000 <bogus+       0>:	0x67	0x60	0x11	0x00
[/size]

This is PTE of the page table at physical address 0x2000 which maps addresses starting from 0xC0000000. It clearly shows that
the physical address mapped to 0xC0000000 is 0x116000
But the output from info tab differs :

Code: Select all

<bochs:6> info tab
cr3: 0x0a8fb5c800003000
0x00000000-0x003fffff -> 0x0000000000000000-0x00000000003fffff
0xc0000000-0xc0000fff -> 0x0000000000008000-0x0000000000008fff     <<<<<<<<<<<<<<<<
0xc0001000-0xc03fffff -> 0x0000000000101000-0x00000000004fffff
0xd0000000-0xd00fffff -> 0x0000000000009000-0x0000000000108fff
0xffc00000-0xffc00fff -> 0x0000000000001000-0x0000000000001fff
0xfff00000-0xfff00fff -> 0x0000000000002000-0x0000000000002fff
0xfff40000-0xfff40fff -> 0x0000000000006000-0x0000000000006fff
0xfffff000-0xffffffff -> 0x0000000000003000-0x0000000000003fff
[/size]

When I continue, the code fails as the frame at 0x8000 is modified again in place of the frame at 0x116000.
What is more confusing is that once in a while info tab shows correct mappings and the code runs correctly but mostly it is
failing. I have been debugging this for a few hours now and don't know what else to do.


-Thanks
Vaibhav Jain
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:

Re: problem changing page table in bochs

Post by Combuster »

Look up "TLB" in the intel manuals
"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 ]
vjain20
Member
Member
Posts: 73
Joined: Wed Apr 04, 2012 9:12 pm

Re: problem changing page table in bochs

Post by vjain20 »

Look up "TLB" in the intel manuals
I guess you are referring to invalidating a TLB entry.
The function vmmgr_temp_map_page calls another function to invalidate a TLB entry

Code: Select all

void vmmgr_flush_tlb_entry(void* addr)
{
    asm volatile("cli");
    asm volatile("invlpg %0":: "m"((uint32)addr));
    asm volatile("sti");
}
-Thanks
vjain20
Member
Member
Posts: 73
Joined: Wed Apr 04, 2012 9:12 pm

Re: problem changing page table in bochs

Post by vjain20 »

I found that a full tlb flush is working while invalidating a single entry using the invlpg instruction is not.
But this seems to be an overhead.





-Thanks
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: problem changing page table in bochs

Post by iansjack »

Have a look at: http://wiki.osdev.org/Inline_Assembly/Examples . The correct use of the "invlpg" instruction can be a little tricky.
vjain20
Member
Member
Posts: 73
Joined: Wed Apr 04, 2012 9:12 pm

Re: problem changing page table in bochs

Post by vjain20 »

Have a look at: http://wiki.osdev.org/Inline_Assembly/Examples . The correct use of the "invlpg" instruction can be a little tricky.
Thanks for the link but I couldn't quite understand what is given in the article.
The 'm' pointer points to a logical address, not a physical or virtual one: an offset for your ds segment. Note '*m' is used, not just 'm': if you use 'm' here, you invalidate the address of the 'm' variable (not what you want!).

static inline
void pgFlushOneTlb( void * m )
{
asm volatile( "invlpg %0"
: // no output
: "m"(*m) //
: "memory" // clobber memory to avoid optimizer re-ordering access before invlpg, which may cause nasty bug.
);
}
Could you please tell what should I pass to this method if I want to invalidate a virtual address X ?
I added the clobber memory to my function which provides a virtual address as an operand to invlpg but it did not work.

Code: Select all

void vmmgr_flush_tlb_entry(void* addr)
{
    asm volatile("cli");
    asm volatile("invlpg %0":: "m"((uint32)addr) : "clobber");
    asm volatile("sti");
}

I looked up the intel manual which only says :
Invalidates (flushes) the translation lookaside buffer (TLB) entry specified with the source
operand. The source operand is a memory address. The processor determines the page that
contains that address and flushes the TLB entry for that page
.
- Thanks
Vaibhav jain
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: problem changing page table in bochs

Post by iansjack »

It's a question of which address you want to invalidate. m is a variable that holds a pointer to an address. *m is the pointer to that address (which is what variable m contains).

So which address do you want to invalidate, the address of the variable containing the pointer (m) or the pointer that the variable contains (*m)?
vjain20
Member
Member
Posts: 73
Joined: Wed Apr 04, 2012 9:12 pm

Re: problem changing page table in bochs

Post by vjain20 »

Thanks! I still don't understand it but it started working.
Here is my function to invalidate TLB entry

Code: Select all

void vmmgr_flush_tlb_entry(void* addr)
{
    asm volatile("cli");
    asm volatile("invlpg %0":: "m"(*((uint32*)addr)): "memory");
    asm volatile("sti");
}
[/size]

And to invalidate any virtual address say 0xC0000000 I am directly calling vmmgr_flush_tlb_entry(0xC0000000).
So it seems that the instruction invlpg is taking the value at address which is to be invalidated as input. :?
- Thanks
Vaibhav jain
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: problem changing page table in bochs

Post by iansjack »

You should think about it more and try to understand exactly what is happening. It might help if you were to look at the assembler code generated when you compile that function, or even single-step through the assembler code to see what exactly is happening.

This is fairly basic pointer stuff and you need to understand it to successfully interface between C code and assembler code.
User avatar
Griwes
Member
Member
Posts: 374
Joined: Sat Jul 30, 2011 10:07 am
Libera.chat IRC: Griwes
Location: Wrocław/Racibórz, Poland
Contact:

Re: problem changing page table in bochs

Post by Griwes »

Tip: what does the following do?

Code: Select all

*((uint32*)addr)
Reaver Project :: Repository :: Ohloh project page
<klange> This is a horror story about what happens when you need a hammer and all you have is the skulls of the damned.
<drake1> as long as the lock is read and modified by atomic operations
User avatar
Griwes
Member
Member
Posts: 374
Joined: Sat Jul 30, 2011 10:07 am
Libera.chat IRC: Griwes
Location: Wrocław/Racibórz, Poland
Contact:

Re: problem changing page table in bochs

Post by Griwes »

berkus wrote:
Griwes wrote:Tip: what does the following do?

Code: Select all

*((uint32*)addr)
It uses a non-standard typedef for 32-bits unsigned integer, perhaps.
I mean the syntax, not the uint32 part:
vjain20 wrote:So it seems that the instruction invlpg is taking the value at address which is to be invalidated as input.
Reaver Project :: Repository :: Ohloh project page
<klange> This is a horror story about what happens when you need a hammer and all you have is the skulls of the damned.
<drake1> as long as the lock is read and modified by atomic operations
User avatar
Griwes
Member
Member
Posts: 374
Joined: Sat Jul 30, 2011 10:07 am
Libera.chat IRC: Griwes
Location: Wrocław/Racibórz, Poland
Contact:

Re: problem changing page table in bochs

Post by Griwes »

berkus, once again: he is taking the address, dereferencing it as pointer to 32bit value, and feeding the value to the invlpg and doesn't know why invlpg is executed with the value at address, not the address...
Reaver Project :: Repository :: Ohloh project page
<klange> This is a horror story about what happens when you need a hammer and all you have is the skulls of the damned.
<drake1> as long as the lock is read and modified by atomic operations
User avatar
Griwes
Member
Member
Posts: 374
Joined: Sat Jul 30, 2011 10:07 am
Libera.chat IRC: Griwes
Location: Wrocław/Racibórz, Poland
Contact:

Re: problem changing page table in bochs

Post by Griwes »

Nah, seems that I've used all my trollcasting mana recently :F
Reaver Project :: Repository :: Ohloh project page
<klange> This is a horror story about what happens when you need a hammer and all you have is the skulls of the damned.
<drake1> as long as the lock is read and modified by atomic operations
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: problem changing page table in bochs

Post by iansjack »

I think this is all getting a little complicated and is obfuscating the OP's problem. It's a simple matter of understanding the difference between the address of a variable and the contents of that variable. Especially in the case when the contents of the variable are a pointer to a memory address.

Forget all the crap about casts; that's not the OP's conceptual problem.

I still think the best way that he will understand is to single-step through the generated assemble and watch what happens to registers and memory contents; you can't beat seeing the CPU in action.
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: problem changing page table in bochs

Post by iansjack »

berkus wrote:Explicit cast however shows the intention more noticeably.
It certainly does, and just checking my own code I see that I do use explicit casts in this situation (although you'll have to forgive the fact that I use good old-fashioned C-style casts), once you understand why you are doing it. And it's very useful as a reminder when you are looking at the code after you wrote it.

But I think the OP is having difficulty grasping that why. Watch it in action in a debugger and he'd soon realise why and what was wrong with his original code.
Post Reply