sed4906h wrote:
Using your code (which is similar to my previous code), the check for whether a page table exists always returns true and tries to make a new page table. What?
Hm. I concur with the question. Does my macro work correctly? I just wrote that code off the cuff. Have you tried multiple addresses in the same aligned 4MB range?
sed4906h wrote:
Another related question... How should I approach zeroing out the new page table before mapping it?
Ah, the problems I don't have. See, I'm working in 64-bit mode, where I have more than enough virtual space to map all memory linearly and then still have enough left over for logical mappings. I use that for my implementation of virt_from_phys(), which merely has to add a base address.
Well, the solution I would go with is to declare one page directory the "temporary" directory that is always filled. For example, directory 1022, why not. When you initialize paging, you clear a page of RAM and set page directory 1022 to that page. That way, you can map up to 1024 pages temporarily. For the purpose of allocating a zeroed page, you only need one, so I would make that one temporary address per CPU. That way, you don't need TLB shootdowns for this purpose, at least. Then a zeroed allocation would just be
Code:
#define PGD_TEMP 1022
#define TEMP_ADDR ((void*)(PGD_TEMP << 22 | this_cpu()->nr << 12))
uint32_t phys_zalloc(void) {
uint32_t pg = phys_alloc();
if (!pg)
return pg;
MAKE_PGD_ADDR(PGD_TEMP, this_cpu()->nr) = pg | 3;
asm("" ::: "memory"); /* make GCC not reorder the memset above the assignment */
memset(TEMP_ADDR, 0, PAGE_SIZE);
asm("" ::: "memory"); /* make GCC not reorder the assignment above the memset */
MAKE_PGD_ADDR(PGD_TEMP, this_cpu()->nr) = 0;
asm("invlpg %0" :: "r"(TEMP_ADDR) : "memory");
return pg;
}
Even if the other CPUs ever get a TLB for the current CPU's TEMP_ADDR, it is never accessed, so no page fault is possible. Or if it happens, it is spurious.
I had briefly considered just mapping the new page table to its final place and zeroing it out through the recursive mapping, but then you need to invalidate all 1024 TLBs in that 4MB region. And nobody wants that.