#ifndef __ASSEMBLY__
 #include <linux/mmdebug.h>
+#include <linux/bug.h>
 #endif
 
 /*
 
 #define _PAGE_SOFT_DIRTY       _RPAGE_SW3 /* software: software dirty tracking */
 #define _PAGE_SPECIAL          _RPAGE_SW2 /* software: special page */
+#define _PAGE_DEVMAP           _RPAGE_SW1 /* software: ZONE_DEVICE page */
+#define __HAVE_ARCH_PTE_DEVMAP
+
 /*
  * Drivers request for cache inhibited pte mapping using _PAGE_NO_CACHE
  * Instead of fixing all of them, add an alternate define which
        return pte;
 }
 
+static inline pte_t pte_mkdevmap(pte_t pte)
+{
+       return __pte(pte_val(pte) | _PAGE_SPECIAL|_PAGE_DEVMAP);
+}
+
+static inline int pte_devmap(pte_t pte)
+{
+       return !!(pte_raw(pte) & cpu_to_be64(_PAGE_DEVMAP));
+}
+
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
        /* FIXME!! check whether this need to be a conditional */
        return true;
 }
 
+
+static inline pmd_t pmd_mkdevmap(pmd_t pmd)
+{
+       return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_DEVMAP));
+}
+
+static inline int pmd_devmap(pmd_t pmd)
+{
+       return pte_devmap(pmd_pte(pmd));
+}
+
+static inline int pud_devmap(pud_t pud)
+{
+       return 0;
+}
+
+static inline int pgd_devmap(pgd_t pgd)
+{
+       return 0;
+}
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
+static inline const int pud_pfn(pud_t pud)
+{
+       /*
+        * Currently all calls to pud_pfn() are gated around a pud_devmap()
+        * check so this should never be used. If it grows another user we
+        * want to know about it.
+        */
+       BUILD_BUG();
+       return 0;
+}
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */
 
 
 static inline int radix__pmd_trans_huge(pmd_t pmd)
 {
-       return !!(pmd_val(pmd) & _PAGE_PTE);
+       return (pmd_val(pmd) & (_PAGE_PTE | _PAGE_DEVMAP)) == _PAGE_PTE;
 }
 
 static inline pmd_t radix__pmd_mkhuge(pmd_t pmd)
 
                        if (pmd_none(pmd))
                                return NULL;
 
-                       if (pmd_trans_huge(pmd)) {
+                       if (pmd_trans_huge(pmd) || pmd_devmap(pmd)) {
                                if (is_thp)
                                        *is_thp = true;
                                ret_pte = (pte_t *) pmdp;
 
 {
        int changed;
 #ifdef CONFIG_DEBUG_VM
-       WARN_ON(!pmd_trans_huge(*pmdp));
+       WARN_ON(!pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp));
        assert_spin_locked(&vma->vm_mm->page_table_lock);
 #endif
        changed = !pmd_same(*(pmdp), entry);
 #ifdef CONFIG_DEBUG_VM
        WARN_ON(pte_present(pmd_pte(*pmdp)) && !pte_protnone(pmd_pte(*pmdp)));
        assert_spin_locked(&mm->page_table_lock);
-       WARN_ON(!pmd_trans_huge(pmd));
+       WARN_ON(!(pmd_trans_huge(pmd) || pmd_devmap(pmd)));
 #endif
        trace_hugepage_set_pmd(addr, pmd_val(pmd));
        return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd));
 
        unsigned long old;
 
 #ifdef CONFIG_DEBUG_VM
-       WARN_ON(!pmd_trans_huge(*pmdp));
+       WARN_ON(!hash__pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp));
        assert_spin_locked(&mm->page_table_lock);
 #endif
 
 
        VM_BUG_ON(address & ~HPAGE_PMD_MASK);
        VM_BUG_ON(pmd_trans_huge(*pmdp));
+       VM_BUG_ON(pmd_devmap(*pmdp));
 
        pmd = *pmdp;
        pmd_clear(pmdp);
 {
        VM_BUG_ON(address & ~HPAGE_PMD_MASK);
        VM_BUG_ON(REGION_ID(address) != USER_REGION_ID);
+       VM_BUG_ON(pmd_devmap(*pmdp));
 
        /*
         * We can't mark the pmd none here, because that will cause a race
 
        unsigned long old;
 
 #ifdef CONFIG_DEBUG_VM
-       WARN_ON(!radix__pmd_trans_huge(*pmdp));
+       WARN_ON(!radix__pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp));
        assert_spin_locked(&mm->page_table_lock);
 #endif
 
 
        VM_BUG_ON(address & ~HPAGE_PMD_MASK);
        VM_BUG_ON(radix__pmd_trans_huge(*pmdp));
+       VM_BUG_ON(pmd_devmap(*pmdp));
        /*
         * khugepaged calls this for normal pmd
         */
 
  */
 struct page *pmd_page(pmd_t pmd)
 {
-       if (pmd_trans_huge(pmd) || pmd_huge(pmd))
+       if (pmd_trans_huge(pmd) || pmd_huge(pmd) || pmd_devmap(pmd))
                return pte_page(pmd_pte(pmd));
        return virt_to_page(pmd_page_vaddr(pmd));
 }