8infy wrote:Currently it always flushes the entire TLB by moving into the cr3 register, however, I know that INVLPG is a better option for flushing single pages.
Moving into CR3 does not flush global pages. You need INVLPG if you use global pages.
8infy wrote:My questions if I map a new table in the page directory do I have to flush the entire TLB or do I not have to flush anything at all since it wasn't in the cache in the first place?
Intel and AMD CPUs don't cache entries marked not-present. As long as you flushed the TLB entry after you first changed the entry from present to not-present, you do not have to flush it again after you change the entry from not-present to present.
8infy wrote:Also, can you use INVLPG to flush a page directory entry?
Yes. On all Intel CPUs, and on AMD CPUs with EFER[TCE]=0, INVLPG flushes all upper-level entries. On AMD CPUs with EFER[TCE]=1, INVLPG flushes only the upper-level entries associated with the TLB entry being flushed.
8infy wrote:Is my understanding correct that INVLPG takes a virtual address of the page that you want to flush?
Yes. (It's actually the virtual address of one byte within the page you want to flush.)
8infy wrote:And one last thing, should I disable interrupts when doing changes to the page directory/table?
Probably. What would happen if you didn't, and an interrupt happened while you were updating an entry but before you flushed the TLB?
8infy wrote:Here's my current implementation of map_page(), which as you can see does flush_all(), however I tried without it and it doesn't cause a page fault.
Of course you see no page fault - Intel and AMD CPUs don't cache not-present page table entries.
Instead, you might see a much worse bug: if the page is already marked present, you update the entry without flushing the TLB, so the CPU might silently access the wrong page!
(Also, please don't post screenshots of code.)