vfb: use sys instead of cfb drawing functions
[safe/jmp/linux-2.6] / include / asm-sparc64 / pgtable.h
index 3c02d5d..9e80ad4 100644 (file)
 
 #include <asm-generic/pgtable-nopud.h>
 
-#include <linux/config.h>
 #include <linux/compiler.h>
+#include <linux/const.h>
 #include <asm/types.h>
 #include <asm/spitfire.h>
 #include <asm/asi.h>
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/processor.h>
-#include <asm/const.h>
 
 /* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB).
  * The page copy blockops can use 0x2000000 to 0x4000000.
 #define _PAGE_RES1_4U    _AC(0x0002000000000000,UL) /* Reserved             */
 #define _PAGE_SZ32MB_4U          _AC(0x0001000000000000,UL) /* (Panther) 32MB page  */
 #define _PAGE_SZ256MB_4U  _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
+#define _PAGE_SZALL_4U   _AC(0x6001000000000000,UL) /* All pgsz bits        */
 #define _PAGE_SN_4U      _AC(0x0000800000000000,UL) /* (Cheetah) Snoop      */
 #define _PAGE_RES2_4U    _AC(0x0000780000000000,UL) /* Reserved             */
 #define _PAGE_PADDR_4U   _AC(0x000007FFFFFFE000,UL) /* (Cheetah) pa[42:13]  */
 #define _PAGE_SZ512K_4V          _AC(0x0000000000000002,UL) /* 512K Page            */
 #define _PAGE_SZ64K_4V   _AC(0x0000000000000001,UL) /* 64K Page             */
 #define _PAGE_SZ8K_4V    _AC(0x0000000000000000,UL) /* 8K Page              */
+#define _PAGE_SZALL_4V   _AC(0x0000000000000007,UL) /* All pgsz bits        */
 
 #if PAGE_SHIFT == 13
 #define _PAGE_SZBITS_4U        _PAGE_SZ8K_4U
@@ -206,6 +207,7 @@ extern unsigned long pte_sz_bits(unsigned long size);
 extern pgprot_t PAGE_KERNEL;
 extern pgprot_t PAGE_KERNEL_LOCKED;
 extern pgprot_t PAGE_COPY;
+extern pgprot_t PAGE_SHARED;
 
 /* XXX This uglyness is for the atyfb driver's sparc mmap() support. XXX */
 extern unsigned long _PAGE_IE;
@@ -216,9 +218,6 @@ extern unsigned long pg_iobits;
 extern unsigned long _PAGE_ALL_SZ_BITS;
 extern unsigned long _PAGE_SZBITS;
 
-extern unsigned long phys_base;
-extern unsigned long pfn_base;
-
 extern struct page *mem_map_zero;
 #define ZERO_PAGE(vaddr)       (mem_map_zero)
 
@@ -227,11 +226,402 @@ extern struct page *mem_map_zero;
  * the first physical page in the machine is at some huge physical address,
  * such as 4GB.   This is common on a partitioned E10000, for example.
  */
-extern pte_t pfn_pte(unsigned long, pgprot_t);
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+       unsigned long paddr = pfn << PAGE_SHIFT;
+       unsigned long sz_bits;
+
+       sz_bits = 0UL;
+       if (_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL) {
+               __asm__ __volatile__(
+               "\n661: sethi           %%uhi(%1), %0\n"
+               "       sllx            %0, 32, %0\n"
+               "       .section        .sun4v_2insn_patch, \"ax\"\n"
+               "       .word           661b\n"
+               "       mov             %2, %0\n"
+               "       nop\n"
+               "       .previous\n"
+               : "=r" (sz_bits)
+               : "i" (_PAGE_SZBITS_4U), "i" (_PAGE_SZBITS_4V));
+       }
+       return __pte(paddr | sz_bits | pgprot_val(prot));
+}
 #define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
-extern unsigned long pte_pfn(pte_t);
+
+/* This one can be done with two shifts.  */
+static inline unsigned long pte_pfn(pte_t pte)
+{
+       unsigned long ret;
+
+       __asm__ __volatile__(
+       "\n661: sllx            %1, %2, %0\n"
+       "       srlx            %0, %3, %0\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sllx            %1, %4, %0\n"
+       "       srlx            %0, %5, %0\n"
+       "       .previous\n"
+       : "=r" (ret)
+       : "r" (pte_val(pte)),
+         "i" (21), "i" (21 + PAGE_SHIFT),
+         "i" (8), "i" (8 + PAGE_SHIFT));
+
+       return ret;
+}
 #define pte_page(x) pfn_to_page(pte_pfn(x))
-extern pte_t pte_modify(pte_t, pgprot_t);
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
+{
+       unsigned long mask, tmp;
+
+       /* SUN4U: 0x600307ffffffecb8 (negated == 0x9ffcf80000001347)
+        * SUN4V: 0x30ffffffffffee17 (negated == 0xcf000000000011e8)
+        *
+        * Even if we use negation tricks the result is still a 6
+        * instruction sequence, so don't try to play fancy and just
+        * do the most straightforward implementation.
+        *
+        * Note: We encode this into 3 sun4v 2-insn patch sequences.
+        */
+
+       __asm__ __volatile__(
+       "\n661: sethi           %%uhi(%2), %1\n"
+       "       sethi           %%hi(%2), %0\n"
+       "\n662: or              %1, %%ulo(%2), %1\n"
+       "       or              %0, %%lo(%2), %0\n"
+       "\n663: sllx            %1, 32, %1\n"
+       "       or              %0, %1, %0\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%3), %1\n"
+       "       sethi           %%hi(%3), %0\n"
+       "       .word           662b\n"
+       "       or              %1, %%ulo(%3), %1\n"
+       "       or              %0, %%lo(%3), %0\n"
+       "       .word           663b\n"
+       "       sllx            %1, 32, %1\n"
+       "       or              %0, %1, %0\n"
+       "       .previous\n"
+       : "=r" (mask), "=r" (tmp)
+       : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
+              _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
+              _PAGE_SZBITS_4U),
+         "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
+              _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
+              _PAGE_SZBITS_4V));
+
+       return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
+}
+
+static inline pte_t pgoff_to_pte(unsigned long off)
+{
+       off <<= PAGE_SHIFT;
+
+       __asm__ __volatile__(
+       "\n661: or              %0, %2, %0\n"
+       "       .section        .sun4v_1insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       or              %0, %3, %0\n"
+       "       .previous\n"
+       : "=r" (off)
+       : "0" (off), "i" (_PAGE_FILE_4U), "i" (_PAGE_FILE_4V));
+
+       return __pte(off);
+}
+
+static inline pgprot_t pgprot_noncached(pgprot_t prot)
+{
+       unsigned long val = pgprot_val(prot);
+
+       __asm__ __volatile__(
+       "\n661: andn            %0, %2, %0\n"
+       "       or              %0, %3, %0\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       andn            %0, %4, %0\n"
+       "       or              %0, %5, %0\n"
+       "       .previous\n"
+       : "=r" (val)
+       : "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
+                    "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V));
+
+       return __pgprot(val);
+}
+/* Various pieces of code check for platform support by ifdef testing
+ * on "pgprot_noncached".  That's broken and should be fixed, but for
+ * now...
+ */
+#define pgprot_noncached pgprot_noncached
+
+#ifdef CONFIG_HUGETLB_PAGE
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+       unsigned long mask;
+
+       __asm__ __volatile__(
+       "\n661: sethi           %%uhi(%1), %0\n"
+       "       sllx            %0, 32, %0\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       mov             %2, %0\n"
+       "       nop\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
+
+       return __pte(pte_val(pte) | mask);
+}
+#endif
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+       unsigned long val = pte_val(pte), tmp;
+
+       __asm__ __volatile__(
+       "\n661: or              %0, %3, %0\n"
+       "       nop\n"
+       "\n662: nop\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%4), %1\n"
+       "       sllx            %1, 32, %1\n"
+       "       .word           662b\n"
+       "       or              %1, %%lo(%4), %1\n"
+       "       or              %0, %1, %0\n"
+       "       .previous\n"
+       : "=r" (val), "=r" (tmp)
+       : "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
+         "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
+
+       return __pte(val);
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+       unsigned long val = pte_val(pte), tmp;
+
+       __asm__ __volatile__(
+       "\n661: andn            %0, %3, %0\n"
+       "       nop\n"
+       "\n662: nop\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%4), %1\n"
+       "       sllx            %1, 32, %1\n"
+       "       .word           662b\n"
+       "       or              %1, %%lo(%4), %1\n"
+       "       andn            %0, %1, %0\n"
+       "       .previous\n"
+       : "=r" (val), "=r" (tmp)
+       : "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
+         "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
+
+       return __pte(val);
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+       unsigned long val = pte_val(pte), mask;
+
+       __asm__ __volatile__(
+       "\n661: mov             %1, %0\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%2), %0\n"
+       "       sllx            %0, 32, %0\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
+
+       return __pte(val | mask);
+}
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+       unsigned long val = pte_val(pte), tmp;
+
+       __asm__ __volatile__(
+       "\n661: andn            %0, %3, %0\n"
+       "       nop\n"
+       "\n662: nop\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%4), %1\n"
+       "       sllx            %1, 32, %1\n"
+       "       .word           662b\n"
+       "       or              %1, %%lo(%4), %1\n"
+       "       andn            %0, %1, %0\n"
+       "       .previous\n"
+       : "=r" (val), "=r" (tmp)
+       : "0" (val), "i" (_PAGE_WRITE_4U | _PAGE_W_4U),
+         "i" (_PAGE_WRITE_4V | _PAGE_W_4V));
+
+       return __pte(val);
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+       unsigned long mask;
+
+       __asm__ __volatile__(
+       "\n661: mov             %1, %0\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%2), %0\n"
+       "       sllx            %0, 32, %0\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+       mask |= _PAGE_R;
+
+       return __pte(pte_val(pte) & ~mask);
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+       unsigned long mask;
+
+       __asm__ __volatile__(
+       "\n661: mov             %1, %0\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%2), %0\n"
+       "       sllx            %0, 32, %0\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+       mask |= _PAGE_R;
+
+       return __pte(pte_val(pte) | mask);
+}
+
+static inline unsigned long pte_young(pte_t pte)
+{
+       unsigned long mask;
+
+       __asm__ __volatile__(
+       "\n661: mov             %1, %0\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%2), %0\n"
+       "       sllx            %0, 32, %0\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+       return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_dirty(pte_t pte)
+{
+       unsigned long mask;
+
+       __asm__ __volatile__(
+       "\n661: mov             %1, %0\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%2), %0\n"
+       "       sllx            %0, 32, %0\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_MODIFIED_4U), "i" (_PAGE_MODIFIED_4V));
+
+       return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_write(pte_t pte)
+{
+       unsigned long mask;
+
+       __asm__ __volatile__(
+       "\n661: mov             %1, %0\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%2), %0\n"
+       "       sllx            %0, 32, %0\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
+
+       return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_exec(pte_t pte)
+{
+       unsigned long mask;
+
+       __asm__ __volatile__(
+       "\n661: sethi           %%hi(%1), %0\n"
+       "       .section        .sun4v_1insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       mov             %2, %0\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_EXEC_4U), "i" (_PAGE_EXEC_4V));
+
+       return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_read(pte_t pte)
+{
+       unsigned long mask;
+
+       __asm__ __volatile__(
+       "\n661: mov             %1, %0\n"
+       "       nop\n"
+       "       .section        .sun4v_2insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       sethi           %%uhi(%2), %0\n"
+       "       sllx            %0, 32, %0\n"
+       "       .previous\n"
+       : "=r" (mask)
+       : "i" (_PAGE_READ_4U), "i" (_PAGE_READ_4V));
+
+       return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_file(pte_t pte)
+{
+       unsigned long val = pte_val(pte);
+
+       __asm__ __volatile__(
+       "\n661: and             %0, %2, %0\n"
+       "       .section        .sun4v_1insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       and             %0, %3, %0\n"
+       "       .previous\n"
+       : "=r" (val)
+       : "0" (val), "i" (_PAGE_FILE_4U), "i" (_PAGE_FILE_4V));
+
+       return val;
+}
+
+static inline unsigned long pte_present(pte_t pte)
+{
+       unsigned long val = pte_val(pte);
+
+       __asm__ __volatile__(
+       "\n661: and             %0, %2, %0\n"
+       "       .section        .sun4v_1insn_patch, \"ax\"\n"
+       "       .word           661b\n"
+       "       and             %0, %3, %0\n"
+       "       .previous\n"
+       : "=r" (val)
+       : "0" (val), "i" (_PAGE_PRESENT_4U), "i" (_PAGE_PRESENT_4V));
+
+       return val;
+}
 
 #define pmd_set(pmdp, ptep)    \
        (pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
@@ -240,8 +630,9 @@ extern pte_t pte_modify(pte_t, pgprot_t);
 #define __pmd_page(pmd)                \
        ((unsigned long) __va((((unsigned long)pmd_val(pmd))<<11UL)))
 #define pmd_page(pmd)                  virt_to_page((void *)__pmd_page(pmd))
-#define pud_page(pud)          \
+#define pud_page_vaddr(pud)            \
        ((unsigned long) __va((((unsigned long)pud_val(pud))<<11UL)))
+#define pud_page(pud)                  virt_to_page((void *)pud_page_vaddr(pud))
 #define pmd_none(pmd)                  (!pmd_val(pmd))
 #define pmd_bad(pmd)                   (0)
 #define pmd_present(pmd)               (pmd_val(pmd) != 0U)
@@ -254,27 +645,6 @@ extern pte_t pte_modify(pte_t, pgprot_t);
 /* Same in both SUN4V and SUN4U.  */
 #define pte_none(pte)                  (!pte_val(pte))
 
-extern unsigned long pte_present(pte_t);
-
-/* The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-extern unsigned long pte_read(pte_t);
-extern unsigned long pte_exec(pte_t);
-extern unsigned long pte_write(pte_t);
-extern unsigned long pte_dirty(pte_t);
-extern unsigned long pte_young(pte_t);
-extern pte_t pte_wrprotect(pte_t);
-extern pte_t pte_rdprotect(pte_t);
-extern pte_t pte_mkclean(pte_t);
-extern pte_t pte_mkold(pte_t);
-
-/* Be very careful when you change these three, they are delicate. */
-extern pte_t pte_mkyoung(pte_t);
-extern pte_t pte_mkwrite(pte_t);
-extern pte_t pte_mkdirty(pte_t);
-extern pte_t pte_mkhuge(pte_t);
-
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address)     (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
 #define pgd_offset(mm, address)        ((mm)->pgd + pgd_index(address))
@@ -284,7 +654,7 @@ extern pte_t pte_mkhuge(pte_t);
 
 /* Find an entry in the second-level page table.. */
 #define pmd_offset(pudp, address)      \
-       ((pmd_t *) pud_page(*(pudp)) + \
+       ((pmd_t *) pud_page_vaddr(*(pudp)) + \
         (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)))
 
 /* Find an entry in the third-level page table.. */
@@ -319,6 +689,23 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p
 #define pte_clear(mm,addr,ptep)                \
        set_pte_at((mm), (addr), (ptep), __pte(0UL))
 
+#ifdef DCACHE_ALIASING_POSSIBLE
+#define __HAVE_ARCH_MOVE_PTE
+#define move_pte(pte, prot, old_addr, new_addr)                                \
+({                                                                     \
+       pte_t newpte = (pte);                                           \
+       if (tlb_type != hypervisor && pte_present(pte)) {               \
+               unsigned long this_pfn = pte_pfn(pte);                  \
+                                                                       \
+               if (pfn_valid(this_pfn) &&                              \
+                   (((old_addr) ^ (new_addr)) & (1 << 13)))            \
+                       flush_dcache_page_all(current->mm,              \
+                                             pfn_to_page(this_pfn));   \
+       }                                                               \
+       newpte;                                                         \
+})
+#endif
+
 extern pgd_t swapper_pg_dir[2048];
 extern pmd_t swapper_low_pmd_dir[2048];
 
@@ -350,33 +737,18 @@ extern unsigned long pte_file(pte_t);
 extern pte_t pgoff_to_pte(unsigned long);
 #define PTE_FILE_MAX_BITS      (64UL - PAGE_SHIFT - 1UL)
 
-extern unsigned long prom_virt_to_phys(unsigned long, int *);
-
-extern unsigned long sun4u_get_pte(unsigned long);
-
-static inline unsigned long __get_phys(unsigned long addr)
-{
-       return sun4u_get_pte(addr);
-}
-
-static inline int __get_iospace(unsigned long addr)
-{
-       return ((sun4u_get_pte(addr) & 0xf0000000) >> 28);
-}
-
 extern unsigned long *sparc64_valid_addr_bitmap;
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
 #define kern_addr_valid(addr)  \
        (test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
 
+extern int page_in_phys_avail(unsigned long paddr);
+
 extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
                               unsigned long pfn,
                               unsigned long size, pgprot_t prot);
 
-/* Clear virtual and physical cachability, set side-effect bit.  */
-extern pgprot_t pgprot_noncached(pgprot_t);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -387,8 +759,11 @@ extern pgprot_t pgprot_noncached(pgprot_t);
 
 #include <asm-generic/pgtable.h>
 
-/* We provide our own get_unmapped_area to cope with VA holes for userland */
+/* We provide our own get_unmapped_area to cope with VA holes and
+ * SHM area cache aliasing for userland.
+ */
 #define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
 
 /* We provide a special get_unmapped_area for framebuffer mmaps to try and use
  * the largest alignment possible such that larget PTEs can be used.
@@ -402,6 +777,8 @@ extern void pgtable_cache_init(void);
 extern void sun4v_register_fault_status(void);
 extern void sun4v_ktsb_register(void);
 
+extern unsigned long cmdline_memory_size;
+
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(_SPARC64_PGTABLE_H) */