For a lot of time my kernel has been affected by strange occasional errors. These errors occurred during the task alternation and the problem seemed to reside in the paging mechanism, in particular as it regards the invalidation of the entries in the TLB.
To invalidate a single entry I used this inline function:
Code: Select all
static __inline__ void invlpg(unsigned int addr)
{
__asm__ __volatile__ ("invlpg %0" : : "m" (addr));
}
After having checked endless times the code

, I've resolved the problem by replacing every "invlpg()" instructions with a macro which invalidates the whole TLB.
Code: Select all
#define ReloadCR3() \
__asm__ __volatile__ ("push %eax;mov %cr3,%eax;mov %eax,%cr3;pop %eax");
Since so everything worked, I have left this solution, knowing, however, that the single entry invalidation would be more efficient...
In these past days, exploring the linux sources, I've found the same macro to invalidate a single entry in the TLB, but there was something different...
Code: Select all
#define __flush_tlb_single(addr) \
__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
As it seems, the argument of the asm instruction "invlpg" doesn't have to be the address of memory reported to the entry that we want to invalidate, but it has to be its content! Pratically invlpg use the memory pointer of the argument, as when we use the instructions "lea", "floats", etc...
Since this has maked me crazy for some months, I have thought to communicate to all of you... and if I'm not wrong, it seems to me that others among you have used my same old definition to invalidate single entries in the TLB...
Let me know...