[S390] merge page_test_dirty and page_clear_dirty
[pandora-kernel.git] / arch / s390 / include / asm / pgtable.h
index 02ace34..4ca4dd2 100644 (file)
@@ -256,8 +256,6 @@ extern unsigned long VMALLOC_START;
 #define _PAGE_TYPE_FILE                0x601   /* bit 0x002 is used for offset !! */
 #define _PAGE_TYPE_RO          0x200
 #define _PAGE_TYPE_RW          0x000
-#define _PAGE_TYPE_EX_RO       0x202
-#define _PAGE_TYPE_EX_RW       0x002
 
 /*
  * Only four types for huge pages, using the invalid bit and protection bit
@@ -287,8 +285,6 @@ extern unsigned long VMALLOC_START;
  * _PAGE_TYPE_FILE     11?1   ->   11?1
  * _PAGE_TYPE_RO       0100   ->   1100
  * _PAGE_TYPE_RW       0000   ->   1000
- * _PAGE_TYPE_EX_RO    0110   ->   1110
- * _PAGE_TYPE_EX_RW    0010   ->   1010
  *
  * pte_none is true for bits combinations 1000, 1010, 1100, 1110
  * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001
@@ -377,65 +373,39 @@ extern unsigned long VMALLOC_START;
 #define _ASCE_USER_BITS                (_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \
                                 _ASCE_ALT_EVENT)
 
-/* Bits int the storage key */
-#define _PAGE_CHANGED    0x02          /* HW changed bit                   */
-#define _PAGE_REFERENCED 0x04          /* HW referenced bit                */
-
 /*
  * Page protection definitions.
  */
 #define PAGE_NONE      __pgprot(_PAGE_TYPE_NONE)
 #define PAGE_RO                __pgprot(_PAGE_TYPE_RO)
 #define PAGE_RW                __pgprot(_PAGE_TYPE_RW)
-#define PAGE_EX_RO     __pgprot(_PAGE_TYPE_EX_RO)
-#define PAGE_EX_RW     __pgprot(_PAGE_TYPE_EX_RW)
 
 #define PAGE_KERNEL    PAGE_RW
 #define PAGE_COPY      PAGE_RO
 
 /*
- * Dependent on the EXEC_PROTECT option s390 can do execute protection.
- * Write permission always implies read permission. In theory with a
- * primary/secondary page table execute only can be implemented but
- * it would cost an additional bit in the pte to distinguish all the
- * different pte types. To avoid that execute permission currently
- * implies read permission as well.
+ * On s390 the page table entry has an invalid bit and a read-only bit.
+ * Read permission implies execute permission and write permission
+ * implies read permission.
  */
          /*xwr*/
 #define __P000 PAGE_NONE
 #define __P001 PAGE_RO
 #define __P010 PAGE_RO
 #define __P011 PAGE_RO
-#define __P100 PAGE_EX_RO
-#define __P101 PAGE_EX_RO
-#define __P110 PAGE_EX_RO
-#define __P111 PAGE_EX_RO
+#define __P100 PAGE_RO
+#define __P101 PAGE_RO
+#define __P110 PAGE_RO
+#define __P111 PAGE_RO
 
 #define __S000 PAGE_NONE
 #define __S001 PAGE_RO
 #define __S010 PAGE_RW
 #define __S011 PAGE_RW
-#define __S100 PAGE_EX_RO
-#define __S101 PAGE_EX_RO
-#define __S110 PAGE_EX_RW
-#define __S111 PAGE_EX_RW
-
-#ifndef __s390x__
-# define PxD_SHADOW_SHIFT      1
-#else /* __s390x__ */
-# define PxD_SHADOW_SHIFT      2
-#endif /* __s390x__ */
-
-static inline void *get_shadow_table(void *table)
-{
-       unsigned long addr, offset;
-       struct page *page;
-
-       addr = (unsigned long) table;
-       offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1);
-       page = virt_to_page((void *)(addr ^ offset));
-       return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
-}
+#define __S100 PAGE_RO
+#define __S101 PAGE_RO
+#define __S110 PAGE_RW
+#define __S111 PAGE_RW
 
 /*
  * Certain architectures need to do special things when PTEs
@@ -446,14 +416,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
                              pte_t *ptep, pte_t entry)
 {
        *ptep = entry;
-       if (mm->context.noexec) {
-               if (!(pte_val(entry) & _PAGE_INVALID) &&
-                   (pte_val(entry) & _PAGE_SWX))
-                       pte_val(entry) |= _PAGE_RO;
-               else
-                       pte_val(entry) = _PAGE_TYPE_EMPTY;
-               ptep[PTRS_PER_PTE] = entry;
-       }
 }
 
 /*
@@ -589,8 +551,6 @@ static inline void rcp_unlock(pte_t *ptep)
 #endif
 }
 
-/* forward declaration for SetPageUptodate in page-flags.h*/
-static inline void page_clear_dirty(struct page *page, int mapped);
 #include <linux/page-flags.h>
 
 static inline void ptep_rcp_copy(pte_t *ptep)
@@ -600,7 +560,7 @@ static inline void ptep_rcp_copy(pte_t *ptep)
        unsigned int skey;
        unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
 
-       skey = page_get_storage_key(page_to_phys(page));
+       skey = page_get_storage_key(pte_val(*ptep) >> PAGE_SHIFT);
        if (skey & _PAGE_CHANGED) {
                set_bit_simple(RCP_GC_BIT, pgste);
                set_bit_simple(KVM_UD_BIT, pgste);
@@ -662,11 +622,7 @@ static inline void pgd_clear_kernel(pgd_t * pgd)
 
 static inline void pgd_clear(pgd_t * pgd)
 {
-       pgd_t *shadow = get_shadow_table(pgd);
-
        pgd_clear_kernel(pgd);
-       if (shadow)
-               pgd_clear_kernel(shadow);
 }
 
 static inline void pud_clear_kernel(pud_t *pud)
@@ -677,13 +633,8 @@ static inline void pud_clear_kernel(pud_t *pud)
 
 static inline void pud_clear(pud_t *pud)
 {
-       pud_t *shadow = get_shadow_table(pud);
-
        pud_clear_kernel(pud);
-       if (shadow)
-               pud_clear_kernel(shadow);
 }
-
 #endif /* __s390x__ */
 
 static inline void pmd_clear_kernel(pmd_t * pmdp)
@@ -693,18 +644,12 @@ static inline void pmd_clear_kernel(pmd_t * pmdp)
 
 static inline void pmd_clear(pmd_t *pmd)
 {
-       pmd_t *shadow = get_shadow_table(pmd);
-
        pmd_clear_kernel(pmd);
-       if (shadow)
-               pmd_clear_kernel(shadow);
 }
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
-       if (mm->context.noexec)
-               pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY;
 }
 
 /*
@@ -809,6 +754,7 @@ static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
 {
        int dirty;
        unsigned long *pgste;
+       unsigned long pfn;
        struct page *page;
        unsigned int skey;
 
@@ -816,8 +762,9 @@ static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
                return -EINVAL;
        rcp_lock(ptep);
        pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
-       page = virt_to_page(pte_val(*ptep));
-       skey = page_get_storage_key(page_to_phys(page));
+       pfn = pte_val(*ptep) >> PAGE_SHIFT;
+       page = pfn_to_page(pfn);
+       skey = page_get_storage_key(pfn);
        if (skey & _PAGE_CHANGED) {
                set_bit_simple(RCP_GC_BIT, pgste);
                set_bit_simple(KVM_UD_BIT, pgste);
@@ -828,7 +775,7 @@ static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
        }
        dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste);
        if (skey & _PAGE_CHANGED)
-               page_clear_dirty(page, 1);
+               page_set_storage_key(pfn, skey & ~_PAGE_CHANGED, 1);
        rcp_unlock(ptep);
        return dirty;
 }
@@ -839,16 +786,16 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
                                            unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_PGSTE
-       unsigned long physpage;
+       unsigned long pfn;
        int young;
        unsigned long *pgste;
 
        if (!vma->vm_mm->context.has_pgste)
                return 0;
-       physpage = pte_val(*ptep) & PAGE_MASK;
+       pfn = pte_val(*ptep) >> PAGE_SHIFT;
        pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
 
-       young = ((page_get_storage_key(physpage) & _PAGE_REFERENCED) != 0);
+       young = ((page_get_storage_key(pfn) & _PAGE_REFERENCED) != 0);
        rcp_lock(ptep);
        if (young)
                set_bit_simple(RCP_GR_BIT, pgste);
@@ -903,10 +850,6 @@ static inline void ptep_invalidate(struct mm_struct *mm,
        }
        __ptep_ipte(address, ptep);
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
-       if (mm->context.noexec) {
-               __ptep_ipte(address, ptep + PTRS_PER_PTE);
-               pte_val(*(ptep + PTRS_PER_PTE)) = _PAGE_TYPE_EMPTY;
-       }
 }
 
 /*
@@ -989,42 +932,6 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
        __changed;                                                      \
 })
 
-/*
- * Test and clear dirty bit in storage key.
- * We can't clear the changed bit atomically. This is a potential
- * race against modification of the referenced bit. This function
- * should therefore only be called if it is not mapped in any
- * address space.
- */
-#define __HAVE_ARCH_PAGE_TEST_DIRTY
-static inline int page_test_dirty(struct page *page)
-{
-       return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0;
-}
-
-#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
-static inline void page_clear_dirty(struct page *page, int mapped)
-{
-       page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY, mapped);
-}
-
-/*
- * Test and clear referenced bit in storage key.
- */
-#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
-static inline int page_test_and_clear_young(struct page *page)
-{
-       unsigned long physpage = page_to_phys(page);
-       int ccode;
-
-       asm volatile(
-               "       rrbe    0,%1\n"
-               "       ipm     %0\n"
-               "       srl     %0,28\n"
-               : "=d" (ccode) : "a" (physpage) : "cc" );
-       return ccode & 2;
-}
-
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.