Marcelo Tosatti wrote:
> Forgot to copy you... Ideally all pte updates should be done via the
> paravirt interface.
>   

Hm, are you sure?

> +static inline void pte_clear_bit(unsigned int bit, pte_t *ptep)
> +{
> +     pte_t pte = *ptep;
> +     clear_bit(bit, (unsigned long *)&pte.pte);
> +     set_pte(ptep, pte);
> +}
>   

This is not a safe transformation.  This will lose hardware A/D bit 
changes if the pte is part of an active pagetable.  Aside from that, 
clear_bit is atomic and so is the wrong thing to use on a local 
variable; a plain bitmask would do the job.

clear_bit on a PTE is fine, since everyone has to support some level of 
trap'n'emulate on pte-level entries (ptep_get_and_clear is very hard to 
implement otherwise).  Shadow pagetable implementations will do this 
naturally, and Xen must do it to allow atomic updates on ptes (also 
because it makes late-pinning/early-unpinning a performance win).

> +
>  static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
>                             pte_t *ptep, pte_t pte)
>  {
> Index: linux-2.6-x86-kvm/include/asm-x86/pgtable.h
> ===================================================================
> --- linux-2.6-x86-kvm.orig/include/asm-x86/pgtable.h
> +++ linux-2.6-x86-kvm/include/asm-x86/pgtable.h
> @@ -227,6 +227,8 @@ void native_pagetable_setup_done(pgd_t *
>  #define pte_update(mm, addr, ptep)              do { } while (0)
>  #define pte_update_defer(mm, addr, ptep)        do { } while (0)
>  
> +#define pte_clear_bit(bit, ptep)     clear_bit(bit, (unsigned long 
> *)&ptep->pte)
> +
>  static inline void paravirt_pagetable_setup_start(pgd_t *base)
>  {
>       native_pagetable_setup_start(base);
> @@ -302,7 +304,7 @@ static inline void native_set_pte_at(str
>  ({                                                                   \
>       int __changed = !pte_same(*(ptep), entry);                      \
>       if (__changed && dirty) {                                       \
> -             *ptep = entry;                                          \
> +             set_pte(ptep, entry);                                   \
>   

This change is OK, but doesn't really do anything.  All hypervisors 
allow direct access to ptes.

>               pte_update_defer((vma)->vm_mm, (address), (ptep));      \
>               flush_tlb_page(vma, address);                           \
>       }                                                               \
> @@ -357,7 +359,7 @@ static inline pte_t ptep_get_and_clear_f
>  #define __HAVE_ARCH_PTEP_SET_WRPROTECT
>  static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long 
> addr, pte_t *ptep)
>  {
> -     clear_bit(_PAGE_BIT_RW, (unsigned long *)&ptep->pte);
> +     pte_clear_bit(_PAGE_BIT_RW, ptep);
>   

This is only valid if ptep_set_wrprotect is never used on active ptes, 
which I don't think is the case.

    J

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to