Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus
[pandora-kernel.git] / arch / s390 / include / asm / pgtable.h
index 3157441..02ace34 100644 (file)
@@ -38,6 +38,7 @@
 extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
 extern void paging_init(void);
 extern void vmem_map_init(void);
+extern void fault_init(void);
 
 /*
  * The S390 doesn't have any external MMU info: the kernel page
@@ -46,11 +47,27 @@ extern void vmem_map_init(void);
 #define update_mmu_cache(vma, address, ptep)     do { } while (0)
 
 /*
- * ZERO_PAGE is a global shared page that is always zero: used
+ * ZERO_PAGE is a global shared page that is always zero; used
  * for zero-mapped memory areas etc..
  */
-extern char empty_zero_page[PAGE_SIZE];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern unsigned long empty_zero_page;
+extern unsigned long zero_page_mask;
+
+#define ZERO_PAGE(vaddr) \
+       (virt_to_page((void *)(empty_zero_page + \
+        (((unsigned long)(vaddr)) &zero_page_mask))))
+
+#define is_zero_pfn is_zero_pfn
+static inline int is_zero_pfn(unsigned long pfn)
+{
+       extern unsigned long zero_pfn;
+       unsigned long offset_from_zero_pfn = pfn - zero_pfn;
+       return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
+}
+
+#define my_zero_pfn(addr)      page_to_pfn(ZERO_PAGE(addr))
+
 #endif /* !__ASSEMBLY__ */
 
 /*
@@ -300,6 +317,7 @@ extern unsigned long VMALLOC_START;
 
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_ORIGIN  0x7fffffc0UL    /* page table origin        */
+#define _SEGMENT_ENTRY_RO      0x200   /* page protection bit              */
 #define _SEGMENT_ENTRY_INV     0x20    /* invalid segment table entry      */
 #define _SEGMENT_ENTRY_COMMON  0x10    /* common segment bit               */
 #define _SEGMENT_ENTRY_PTL     0x0f    /* page table length                */
@@ -572,7 +590,7 @@ static inline void rcp_unlock(pte_t *ptep)
 }
 
 /* forward declaration for SetPageUptodate in page-flags.h*/
-static inline void page_clear_dirty(struct page *page);
+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)
@@ -754,6 +772,34 @@ static inline pte_t pte_mkspecial(pte_t pte)
        return pte;
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+       /*
+        * PROT_NONE needs to be remapped from the pte type to the ste type.
+        * The HW invalid bit is also different for pte and ste. The pte
+        * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE
+        * bit, so we don't have to clear it.
+        */
+       if (pte_val(pte) & _PAGE_INVALID) {
+               if (pte_val(pte) & _PAGE_SWT)
+                       pte_val(pte) |= _HPAGE_TYPE_NONE;
+               pte_val(pte) |= _SEGMENT_ENTRY_INV;
+       }
+       /*
+        * Clear SW pte bits SWT and SWX, there are no SW bits in a segment
+        * table entry.
+        */
+       pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX);
+       /*
+        * Also set the change-override bit because we don't need dirty bit
+        * tracking for hugetlbfs pages.
+        */
+       pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO);
+       return pte;
+}
+#endif
+
 #ifdef CONFIG_PGSTE
 /*
  * Get (and clear) the user dirty bit for a PTE.
@@ -782,7 +828,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);
+               page_clear_dirty(page, 1);
        rcp_unlock(ptep);
        return dirty;
 }
@@ -957,9 +1003,9 @@ static inline int page_test_dirty(struct page *page)
 }
 
 #define __HAVE_ARCH_PAGE_CLEAR_DIRTY
-static inline void page_clear_dirty(struct page *page)
+static inline void page_clear_dirty(struct page *page, int mapped)
 {
-       page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY);
+       page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY, mapped);
 }
 
 /*
@@ -1048,9 +1094,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
 #define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
 #define pte_offset_kernel(pmd, address) pte_offset(pmd,address)
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
-#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 
 /*
  * 31 bit swap entry format: