ACPI: asus_acpi: fix proc files parsing
[powerpc.git] / include / asm-i386 / pgtable.h
index 541b3e2..7d398f4 100644 (file)
@@ -246,6 +246,23 @@ static inline pte_t pte_mkhuge(pte_t pte)  { (pte).pte_low |= _PAGE_PSE; return p
 # include <asm/pgtable-2level.h>
 #endif
 
+/*
+ * Rules for using pte_update - it must be called after any PTE update which
+ * has not been done using the set_pte / clear_pte interfaces.  It is used by
+ * shadow mode hypervisors to resynchronize the shadow page tables.  Kernel PTE
+ * updates should either be sets, clears, or set_pte_atomic for P->P
+ * transitions, which means this hook should only be called for user PTEs.
+ * This hook implies a P->P protection or access change has taken place, which
+ * requires a subsequent TLB flush.  The notification can optionally be delayed
+ * until the TLB flush event by using the pte_update_defer form of the
+ * interface, but care must be taken to assure that the flush happens while
+ * still holding the same page table lock so that the shadow and primary pages
+ * do not become out of sync on SMP.
+ */
+#define pte_update(mm, addr, ptep)             do { } while (0)
+#define pte_update_defer(mm, addr, ptep)       do { } while (0)
+
+
 /*
  * We only update the dirty/accessed state if we set
  * the dirty bit by hand in the kernel, since the hardware
@@ -258,25 +275,54 @@ static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= _PAGE_PSE; return p
 do {                                                                   \
        if (dirty) {                                                    \
                (ptep)->pte_low = (entry).pte_low;                      \
+               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
                flush_tlb_page(vma, address);                           \
        }                                                               \
 } while (0)
 
+/*
+ * We don't actually have these, but we want to advertise them so that
+ * we can encompass the flush here.
+ */
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-       if (!pte_dirty(*ptep))
-               return 0;
-       return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
-}
-
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
-       if (!pte_young(*ptep))
-               return 0;
-       return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
-}
+
+/*
+ * Rules for using ptep_establish: the pte MUST be a user pte, and
+ * must be a present->present transition.
+ */
+#define __HAVE_ARCH_PTEP_ESTABLISH
+#define ptep_establish(vma, address, ptep, pteval)                     \
+do {                                                                   \
+       set_pte_present((vma)->vm_mm, address, ptep, pteval);           \
+       flush_tlb_page(vma, address);                                   \
+} while (0)
+
+#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
+#define ptep_clear_flush_dirty(vma, address, ptep)                     \
+({                                                                     \
+       int __dirty;                                                    \
+       __dirty = pte_dirty(*(ptep));                                   \
+       if (__dirty) {                                                  \
+               clear_bit(_PAGE_BIT_DIRTY, &(ptep)->pte_low);           \
+               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
+               flush_tlb_page(vma, address);                           \
+       }                                                               \
+       __dirty;                                                        \
+})
+
+#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+#define ptep_clear_flush_young(vma, address, ptep)                     \
+({                                                                     \
+       int __young;                                                    \
+       __young = pte_young(*(ptep));                                   \
+       if (__young) {                                                  \
+               clear_bit(_PAGE_BIT_ACCESSED, &(ptep)->pte_low);        \
+               pte_update_defer((vma)->vm_mm, (addr), (ptep));         \
+               flush_tlb_page(vma, address);                           \
+       }                                                               \
+       __young;                                                        \
+})
 
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
 static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
@@ -295,6 +341,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
+       pte_update(mm, addr, ptep);
 }
 
 /*
@@ -426,6 +473,13 @@ extern pte_t *lookup_address(unsigned long address);
 #define pte_unmap_nested(pte) do { } while (0)
 #endif
 
+/* Clear a kernel PTE and flush it from the TLB */
+#define kpte_clear_flush(ptep, vaddr)                                  \
+do {                                                                   \
+       pte_clear(&init_mm, vaddr, ptep);                               \
+       __flush_tlb_one(vaddr);                                         \
+} while (0)
+
 /*
  * The i386 doesn't have any external MMU info: the kernel page
  * tables contain all the necessary information.