Skip to content

Commit

Permalink
mmu: do tlb flush while changing permission only if permissions are r…
Browse files Browse the repository at this point in the history
…educed

If permissions are elevated another cpu will fault and will see new
permission after page walk.

Signed-off-by: Gleb Natapov <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
  • Loading branch information
gleb-cloudius authored and avikivity committed Dec 26, 2013
1 parent 73a97f1 commit eefcb08
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions core/mmu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,12 @@ void allocate_intermediate_level(hw_ptep ptep)
ptep.write(make_normal_pte(pt_page));
}

void change_perm(hw_ptep ptep, unsigned int perm)
bool change_perm(hw_ptep ptep, unsigned int perm)
{
pt_element pte = ptep.read();
unsigned int old = (pte.present() ? perm_read : 0) |
(pte.writable() ? perm_write : 0) |
(!pte.nx() ? perm_exec : 0);
// Note: in x86, if the present bit (0x1) is off, not only read is
// disallowed, but also write and exec. So in mprotect, if any
// permission is requested, we must also grant read permission.
Expand All @@ -146,6 +149,8 @@ void change_perm(hw_ptep ptep, unsigned int perm)
pte.set_writable(perm & perm_write);
pte.set_nx(!(perm & perm_exec));
ptep.write(pte);

return old & ~perm;
}

void split_large_page(hw_ptep ptep, unsigned level)
Expand Down Expand Up @@ -507,16 +512,17 @@ class unpopulate : public vma_operation<allocate_intermediate_opt::no> {
class protection : public vma_operation<allocate_intermediate_opt::no> {
private:
unsigned int perm;
bool do_flush;
public:
protection(unsigned int perm) : perm(perm) { }
protection(unsigned int perm) : perm(perm), do_flush(false) { }
void small_page(hw_ptep ptep, uintptr_t offset) {
change_perm(ptep, perm);
do_flush |= change_perm(ptep, perm);
}
bool huge_page(hw_ptep ptep, uintptr_t offset) {
change_perm(ptep, perm);
do_flush |= change_perm(ptep, perm);
return true;
}
bool tlb_flush_needed(void) {return true;}
bool tlb_flush_needed(void) {return do_flush;}
};

class virt_to_phys_map :
Expand Down

0 comments on commit eefcb08

Please sign in to comment.