]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - include/asm-mips/pgtable.h
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6-omap-h63xx.git] / include / asm-mips / pgtable.h
index 34facd9965034d354eb72ea91bc71586759083f6..be75cca20e8d8de7aab02dc4d5d07336020cf9a7 100644 (file)
@@ -19,6 +19,9 @@
 #include <asm/io.h>
 #include <asm/pgtable-bits.h>
 
+struct mm_struct;
+struct vm_area_struct;
+
 #define PAGE_NONE      __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
 #define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
                        PAGE_CACHABLE_DEFAULT)
@@ -67,7 +70,15 @@ extern unsigned long zero_page_mask;
 #define ZERO_PAGE(vaddr) \
        (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
 
-#define __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+#define __HAVE_ARCH_MOVE_PTE
+#define move_pte(pte, prot, old_addr, new_addr)                                \
+({                                                                     \
+       pte_t newpte = (pte);                                           \
+       if (pte_present(pte) && pfn_valid(pte_pfn(pte)) &&              \
+                       pte_page(pte) == ZERO_PAGE(old_addr))           \
+               newpte = mk_pte(ZERO_PAGE(new_addr), (prot));           \
+       newpte;                                                         \
+})
 
 extern void paging_init(void);
 
@@ -79,10 +90,11 @@ extern void paging_init(void);
 #define pmd_page(pmd)          (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
 #define pmd_page_kernel(pmd)   pmd_val(pmd)
 
-#define pte_none(pte)          (!(pte_val(pte) & ~_PAGE_GLOBAL))
-#define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
-
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
+
+#define pte_none(pte)          (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
+#define pte_present(pte)       ((pte).pte_low & _PAGE_PRESENT)
+
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
        ptep->pte_high = pte.pte_high;
@@ -90,27 +102,35 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
        ptep->pte_low = pte.pte_low;
        //printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
 
-       if (pte_val(pte) & _PAGE_GLOBAL) {
+       if (pte.pte_low & _PAGE_GLOBAL) {
                pte_t *buddy = ptep_buddy(ptep);
                /*
                 * Make sure the buddy is global too (if it's !none,
                 * it better already be global)
                 */
-               if (pte_none(*buddy))
-                       buddy->pte_low |= _PAGE_GLOBAL;
+               if (pte_none(*buddy)) {
+                       buddy->pte_low  |= _PAGE_GLOBAL;
+                       buddy->pte_high |= _PAGE_GLOBAL;
+               }
        }
 }
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
+       pte_t null = __pte(0);
+
        /* Preserve global status for the pair */
-       if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
-               set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL));
-       else
-               set_pte_at(mm, addr, ptep, __pte(0));
+       if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL)
+               null.pte_low = null.pte_high = _PAGE_GLOBAL;
+
+       set_pte_at(mm, addr, ptep, null);
 }
 #else
+
+#define pte_none(pte)          (!(pte_val(pte) & ~_PAGE_GLOBAL))
+#define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
+
 /*
  * Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
@@ -171,75 +191,76 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
  */
 static inline int pte_user(pte_t pte)  { BUG(); return 0; }
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
-static inline int pte_read(pte_t pte)  { return (pte).pte_low & _PAGE_READ; }
-static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_WRITE; }
-static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_MODIFIED; }
-static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; }
-static inline int pte_file(pte_t pte)  { return (pte).pte_low & _PAGE_FILE; }
+static inline int pte_read(pte_t pte)  { return pte.pte_low & _PAGE_READ; }
+static inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)  { return pte.pte_low & _PAGE_FILE; }
+
 static inline pte_t pte_wrprotect(pte_t pte)
 {
-       (pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
-       (pte).pte_high &= ~_PAGE_SILENT_WRITE;
+       pte.pte_low  &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+       pte.pte_high &= ~_PAGE_SILENT_WRITE;
        return pte;
 }
 
 static inline pte_t pte_rdprotect(pte_t pte)
 {
-       (pte).pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-       (pte).pte_high &= ~_PAGE_SILENT_READ;
+       pte.pte_low  &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+       pte.pte_high &= ~_PAGE_SILENT_READ;
        return pte;
 }
 
 static inline pte_t pte_mkclean(pte_t pte)
 {
-       (pte).pte_low &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
-       (pte).pte_high &= ~_PAGE_SILENT_WRITE;
+       pte.pte_low  &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
+       pte.pte_high &= ~_PAGE_SILENT_WRITE;
        return pte;
 }
 
 static inline pte_t pte_mkold(pte_t pte)
 {
-       (pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
-       (pte).pte_high &= ~_PAGE_SILENT_READ;
+       pte.pte_low  &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ);
+       pte.pte_high &= ~_PAGE_SILENT_READ;
        return pte;
 }
 
 static inline pte_t pte_mkwrite(pte_t pte)
 {
-       (pte).pte_low |= _PAGE_WRITE;
-       if ((pte).pte_low & _PAGE_MODIFIED) {
-               (pte).pte_low |= _PAGE_SILENT_WRITE;
-               (pte).pte_high |= _PAGE_SILENT_WRITE;
+       pte.pte_low |= _PAGE_WRITE;
+       if (pte.pte_low & _PAGE_MODIFIED) {
+               pte.pte_low  |= _PAGE_SILENT_WRITE;
+               pte.pte_high |= _PAGE_SILENT_WRITE;
        }
        return pte;
 }
 
 static inline pte_t pte_mkread(pte_t pte)
 {
-       (pte).pte_low |= _PAGE_READ;
-       if ((pte).pte_low & _PAGE_ACCESSED) {
-               (pte).pte_low |= _PAGE_SILENT_READ;
-               (pte).pte_high |= _PAGE_SILENT_READ;
+       pte.pte_low |= _PAGE_READ;
+       if (pte.pte_low & _PAGE_ACCESSED) {
+               pte.pte_low  |= _PAGE_SILENT_READ;
+               pte.pte_high |= _PAGE_SILENT_READ;
        }
        return pte;
 }
 
 static inline pte_t pte_mkdirty(pte_t pte)
 {
-       (pte).pte_low |= _PAGE_MODIFIED;
-       if ((pte).pte_low & _PAGE_WRITE) {
-               (pte).pte_low |= _PAGE_SILENT_WRITE;
-               (pte).pte_high |= _PAGE_SILENT_WRITE;
+       pte.pte_low |= _PAGE_MODIFIED;
+       if (pte.pte_low & _PAGE_WRITE) {
+               pte.pte_low  |= _PAGE_SILENT_WRITE;
+               pte.pte_high |= _PAGE_SILENT_WRITE;
        }
        return pte;
 }
 
 static inline pte_t pte_mkyoung(pte_t pte)
 {
-       (pte).pte_low |= _PAGE_ACCESSED;
-       if ((pte).pte_low & _PAGE_READ)
-               (pte).pte_low |= _PAGE_SILENT_READ;
-               (pte).pte_high |= _PAGE_SILENT_READ;
+       pte.pte_low |= _PAGE_ACCESSED;
+       if (pte.pte_low & _PAGE_READ)
+               pte.pte_low  |= _PAGE_SILENT_READ;
+               pte.pte_high |= _PAGE_SILENT_READ;
        return pte;
 }
 #else
@@ -332,8 +353,9 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       pte.pte_low &= _PAGE_CHG_MASK;
-       pte.pte_low |= pgprot_val(newprot);
+       pte.pte_low  &= _PAGE_CHG_MASK;
+       pte.pte_high &= ~0x3f;
+       pte.pte_low  |= pgprot_val(newprot);
        pte.pte_high |= pgprot_val(newprot) & 0x3f;
        return pte;
 }
@@ -357,9 +379,7 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
        __update_cache(vma, address, pte);
 }
 
-#ifndef CONFIG_NEED_MULTIPLE_NODES
 #define kern_addr_valid(addr)  (1)
-#endif
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
 extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot);