Mixed PTK/GTK CCMP/TKIP support.
[powerpc.git] / include / asm-ppc64 / page.h
index a5893a3..82ce187 100644 (file)
  */
 
 #include <linux/config.h>
+#include <asm/ppc_asm.h> /* for ASM_CONST */
 
-#ifdef __ASSEMBLY__
-  #define ASM_CONST(x) x
+/*
+ * We support either 4k or 64k software page size. When using 64k pages
+ * however, wether we are really supporting 64k pages in HW or not is
+ * irrelevant to those definitions. We always define HW_PAGE_SHIFT to 12
+ * as use of 64k pages remains a linux kernel specific, every notion of
+ * page number shared with the firmware, TCEs, iommu, etc... still assumes
+ * a page size of 4096.
+ */
+#ifdef CONFIG_PPC_64K_PAGES
+#define PAGE_SHIFT             16
 #else
-  #define __ASM_CONST(x) x##UL
-  #define ASM_CONST(x) __ASM_CONST(x)
+#define PAGE_SHIFT             12
 #endif
 
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT     12
-#define PAGE_SIZE      (ASM_CONST(1) << PAGE_SHIFT)
-#define PAGE_MASK      (~(PAGE_SIZE-1))
+#define PAGE_SIZE              (ASM_CONST(1) << PAGE_SHIFT)
+#define PAGE_MASK              (~(PAGE_SIZE-1))
 
-#define SID_SHIFT       28
-#define SID_MASK        0xfffffffffUL
-#define ESID_MASK      0xfffffffff0000000UL
-#define GET_ESID(x)     (((x) >> SID_SHIFT) & SID_MASK)
+/* HW_PAGE_SHIFT is always 4k pages */
+#define HW_PAGE_SHIFT          12
+#define HW_PAGE_SIZE           (ASM_CONST(1) << HW_PAGE_SHIFT)
+#define HW_PAGE_MASK           (~(HW_PAGE_SIZE-1))
 
-#define HPAGE_SHIFT    24
-#define HPAGE_SIZE     ((1UL) << HPAGE_SHIFT)
-#define HPAGE_MASK     (~(HPAGE_SIZE - 1))
+/* PAGE_FACTOR is the number of bits factor between PAGE_SHIFT and
+ * HW_PAGE_SHIFT, that is 4k pages
+ */
+#define PAGE_FACTOR            (PAGE_SHIFT - HW_PAGE_SHIFT)
 
-#ifdef CONFIG_HUGETLB_PAGE
+/* Segment size */
+#define SID_SHIFT              28
+#define SID_MASK               0xfffffffffUL
+#define ESID_MASK              0xfffffffff0000000UL
+#define GET_ESID(x)            (((x) >> SID_SHIFT) & SID_MASK)
 
+/* Large pages size */
+
+#ifndef __ASSEMBLY__
+extern unsigned int HPAGE_SHIFT;
+#define HPAGE_SIZE             ((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK             (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_HUGETLB_PAGE
 
-/* For 64-bit processes the hugepage range is 1T-1.5T */
-#define TASK_HPAGE_BASE ASM_CONST(0x0000010000000000)
-#define TASK_HPAGE_END         ASM_CONST(0x0000018000000000)
 
-#define LOW_ESID_MASK(addr, len)       (((1U << (GET_ESID(addr+len-1)+1)) \
-                                       - (1U << GET_ESID(addr))) & 0xffff)
+#define HTLB_AREA_SHIFT                40
+#define HTLB_AREA_SIZE         (1UL << HTLB_AREA_SHIFT)
+#define GET_HTLB_AREA(x)       ((x) >> HTLB_AREA_SHIFT)
+
+#define LOW_ESID_MASK(addr, len)    (((1U << (GET_ESID(addr+len-1)+1)) \
+                                     - (1U << GET_ESID(addr))) & 0xffff)
+#define HTLB_AREA_MASK(addr, len)   (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \
+                                     - (1U << GET_HTLB_AREA(addr))) & 0xffff)
 
 #define ARCH_HAS_HUGEPAGE_ONLY_RANGE
 #define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
 
 #define touches_hugepage_low_range(mm, addr, len) \
-       (LOW_ESID_MASK((addr), (len)) & mm->context.htlb_segs)
-#define touches_hugepage_high_range(addr, len) \
-       (((addr) > (TASK_HPAGE_BASE-(len))) && ((addr) < TASK_HPAGE_END))
+       (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas)
+#define touches_hugepage_high_range(mm, addr, len) \
+       (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas)
 
 #define __within_hugepage_low_range(addr, len, segmask) \
        ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask))
 #define within_hugepage_low_range(addr, len) \
        __within_hugepage_low_range((addr), (len), \
-                                   current->mm->context.htlb_segs)
-#define within_hugepage_high_range(addr, len) (((addr) >= TASK_HPAGE_BASE) \
-         && ((addr)+(len) <= TASK_HPAGE_END) && ((addr)+(len) >= (addr)))
+                                   current->mm->context.low_htlb_areas)
+#define __within_hugepage_high_range(addr, len, zonemask) \
+       ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask))
+#define within_hugepage_high_range(addr, len) \
+       __within_hugepage_high_range((addr), (len), \
+                                   current->mm->context.high_htlb_areas)
 
 #define is_hugepage_only_range(mm, addr, len) \
-       (touches_hugepage_high_range((addr), (len)) || \
+       (touches_hugepage_high_range((mm), (addr), (len)) || \
          touches_hugepage_low_range((mm), (addr), (len)))
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
 #define in_hugepage_area(context, addr) \
        (cpu_has_feature(CPU_FTR_16M_PAGE) && \
-        ( (((addr) >= TASK_HPAGE_BASE) && ((addr) < TASK_HPAGE_END)) || \
+        ( ((1 << GET_HTLB_AREA(addr)) & (context).high_htlb_areas) || \
           ( ((addr) < 0x100000000L) && \
-            ((1 << GET_ESID(addr)) & (context).htlb_segs) ) ) )
+            ((1 << GET_ESID(addr)) & (context).low_htlb_areas) ) ) )
 
 #else /* !CONFIG_HUGETLB_PAGE */
 
@@ -114,7 +141,25 @@ static __inline__ void clear_page(void *addr)
        : "ctr", "memory");
 }
 
-extern void copy_page(void *to, void *from);
+extern void copy_4K_page(void *to, void *from);
+
+#ifdef CONFIG_PPC_64K_PAGES
+static inline void copy_page(void *to, void *from)
+{
+       unsigned int i;
+       for (i=0; i < (1 << (PAGE_SHIFT - 12)); i++) {
+               copy_4K_page(to, from);
+               to += 4096;
+               from += 4096;
+       }
+}
+#else /* CONFIG_PPC_64K_PAGES */
+static inline void copy_page(void *to, void *from)
+{
+       copy_4K_page(to, from);
+}
+#endif /* CONFIG_PPC_64K_PAGES */
+
 struct page;
 extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
 extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *p);
@@ -124,56 +169,80 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct pag
  * These are used to make use of C type-checking.  
  * Entries in the pte table are 64b, while entries in the pgd & pmd are 32b.
  */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned int  pmd; } pmd_t;
-typedef struct { unsigned int  pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
 
+/* PTE level */
+typedef struct { unsigned long pte; } pte_t;
 #define pte_val(x)     ((x).pte)
+#define __pte(x)       ((pte_t) { (x) })
+
+/* 64k pages additionally define a bigger "real PTE" type that gathers
+ * the "second half" part of the PTE for pseudo 64k pages
+ */
+#ifdef CONFIG_PPC_64K_PAGES
+typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
+#else
+typedef struct { pte_t pte; } real_pte_t;
+#endif
+
+/* PMD level */
+typedef struct { unsigned long pmd; } pmd_t;
 #define pmd_val(x)     ((x).pmd)
+#define __pmd(x)       ((pmd_t) { (x) })
+
+/* PUD level exusts only on 4k pages */
+#ifndef CONFIG_PPC_64K_PAGES
+typedef struct { unsigned long pud; } pud_t;
+#define pud_val(x)     ((x).pud)
+#define __pud(x)       ((pud_t) { (x) })
+#endif
+
+/* PGD level */
+typedef struct { unsigned long pgd; } pgd_t;
 #define pgd_val(x)     ((x).pgd)
-#define pgprot_val(x)  ((x).pgprot)
+#define __pgd(x)       ((pgd_t) { (x) })
 
-#define __pte(x)       ((pte_t) { (x) } )
-#define __pmd(x)       ((pmd_t) { (x) } )
-#define __pgd(x)       ((pgd_t) { (x) } )
-#define __pgprot(x)    ((pgprot_t) { (x) } )
+/* Page protection bits */
+typedef struct { unsigned long pgprot; } pgprot_t;
+#define pgprot_val(x)  ((x).pgprot)
+#define __pgprot(x)    ((pgprot_t) { (x) })
 
 #else
+
 /*
  * .. while these make it easier on the compiler
  */
-typedef unsigned long pte_t;
-typedef unsigned int  pmd_t;
-typedef unsigned int  pgd_t;
-typedef unsigned long pgprot_t;
 
+typedef unsigned long pte_t;
 #define pte_val(x)     (x)
+#define __pte(x)       (x)
+
+#ifdef CONFIG_PPC_64K_PAGES
+typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
+#else
+typedef unsigned long real_pte_t;
+#endif
+
+
+typedef unsigned long pmd_t;
 #define pmd_val(x)     (x)
+#define __pmd(x)       (x)
+
+#ifndef CONFIG_PPC_64K_PAGES
+typedef unsigned long pud_t;
+#define pud_val(x)     (x)
+#define __pud(x)       (x)
+#endif
+
+typedef unsigned long pgd_t;
 #define pgd_val(x)     (x)
 #define pgprot_val(x)  (x)
 
-#define __pte(x)       (x)
-#define __pmd(x)       (x)
+typedef unsigned long pgprot_t;
 #define __pgd(x)       (x)
 #define __pgprot(x)    (x)
 
 #endif
 
-/* Pure 2^n version of get_order */
-static inline int get_order(unsigned long size)
-{
-       int order;
-
-       size = (size-1) >> (PAGE_SHIFT-1);
-       order = -1;
-       do {
-               size >>= 1;
-               order++;
-       } while (size);
-       return order;
-}
-
 #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
 
 extern int page_is_ram(unsigned long pfn);
@@ -208,9 +277,6 @@ extern u64 ppc64_pft_size;          /* Log 2 of page table size */
 #define USER_REGION_ID     (0UL)
 #define REGION_ID(ea)     (((unsigned long)(ea)) >> REGION_SHIFT)
 
-#define __bpn_to_ba(x) ((((unsigned long)(x)) << PAGE_SHIFT) + KERNELBASE)
-#define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT)
-
 #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE))
 
 #ifdef CONFIG_DISCONTIGMEM
@@ -261,4 +327,7 @@ extern u64 ppc64_pft_size;          /* Log 2 of page table size */
         VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
 
 #endif /* __KERNEL__ */
+
+#include <asm-generic/page.h>
+
 #endif /* _PPC64_PAGE_H */