<div dir="ltr">Hello,<div><br></div><div>This week I've been looking over the pmap code and compare the generic x86 PG_* bits with the EPT ones and try to find a common API between those. Also Neel Natu pointed out his work on FreeBSD about EPT in pmap which helped me out find more easily the common API.</div>
<div><br></div><div>I have rewritten the pmap code adding support for custom PG_* bits by adding in the "struct pmap {" a field for them (pmap->pmap_bits). A particular pool of these bits are the cache ones. I've added the pte_pat_index vector in the pmap also with the name "pmap->pmap_cache_bits". This vector it's indexed with the type of caching, an entry containing the bits to be set in the PTE (page table entry) in order to obtain that caching type. I've also added a field "pmap->pmap_cache_mask" which identify all the cache bits in a PTE. I saw that in Dfly we don't use the PDE cache bits in order to map bigger pages (>4k). This removed the need for having multiple masks, depending on the type of the page sizes we map.</div>
<div><br></div><div>In FreeBSD they are using PDE for bigger pages, so they having multiple cases (the PAT corresponding to a PDE is different than the PAT corresponding to a PTE).</div><div><br></div><div>I've removed all the PG_* bits and replace them with the pmap private members. Seems that the system still works.</div>
<div><br></div><div>I've also build the EPT bits like this:</div><div>- PG_V - valid (EPT_READ and EPT_EXECUTE bits are set) - on the normal map we didn't have these, we had only the VALID bit</div><div>- PG_RW - read/write (EPT_READ and EPT_EXECUTE and EPT_WRITE)</div>
<div>- PG_U - don't have a correspondent (0)</div><div>- PG_A - EPT_A (bit8)</div><div>- PG_M - EPT_M (bit9)</div><div>- PG_G - don't have a correspondent (0)</div><div>- PG_AVAIL1 - moved from bit9 to bit10</div>
<div>- PG_AVAIL2 - moved from bit10 to bit11</div><div>- PG_AVAIL3 - moved from bit11 to bit52 (the first free)</div><div>- bit3-bit6 controls the cache type. I've made an array like pte_pat_index and each cache type has the right bits in place<br>
</div><div><br></div><div>Now we have a vkernel with a vmspace (including the pmap) in the regular format. I've build a function that converts this table to EPT format (only the USERSPACE side), but I'm loosing some cache info's (the EPT PDE has to have the cache bits to 0) and I can't revert it back. One idea is to vmspace_fork which creates a new vmspace with the same vm_maps and an empty pmap. Replace the private members with the EPT ones. The pmap will be populated at each pagefault with the new bits. It would be great if we could maintain the two vmspaces synchronized (one for EPT and one for normal use). This way I shouldn't rewrite the copyin/copyout procedures. But I'm still thinking which would be the best approach.</div>
<div><br></div><div>Another things I should approach are:</div><div>- invalidating instruction [invept] (I should invalidate the EPT with a special call when it's appropiate)</div><div>- emulating the A/D bits. Unfortunately my testing hardware does not support the A/D for EPT. I've looked over FreeBSD implementation and I will get the mechanisms from there I guess.</div>
<div><br></div><div>Nothing tested yet with EPT. Hope tomorrow to do some tests to see what errors EPT would throw me :).</div><div><br></div><div>Thanks,</div><div>Mihai</div></div>