]> err.no Git - linux-2.6/blobdiff - include/asm-xtensa/page.h
Merge branch 'for-2.6.27' of git://linux-nfs.org/~bfields/linux
[linux-2.6] / include / asm-xtensa / page.h
index 2d6ac21136cfba98765735f5ec642229dc4d85bc..11f7dc2dbec769f4ed5dd4233a6bc787d983556e 100644 (file)
 #ifndef _XTENSA_PAGE_H
 #define _XTENSA_PAGE_H
 
-#ifdef __KERNEL__
-
 #include <asm/processor.h>
 #include <asm/types.h>
+#include <asm/cache.h>
 
 /*
  * Fixed TLB translations in the processor.
 
 /*
  * PAGE_SHIFT determines the page size
- * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
  */
 
 #define PAGE_SHIFT             12
 #define PAGE_SIZE              (__XTENSA_UL_CONST(1) << PAGE_SHIFT)
 #define PAGE_MASK              (~(PAGE_SIZE-1))
-#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
 
 #define PAGE_OFFSET            XCHAL_KSEG_CACHED_VADDR
 #define MAX_MEM_PFN            XCHAL_KSEG_SIZE
 #define PGTABLE_START          0x80000000
 
+/*
+ * Cache aliasing:
+ *
+ * If the cache size for one way is greater than the page size, we have to
+ * deal with cache aliasing. The cache index is wider than the page size:
+ *
+ * |    |cache| cache index
+ * | pfn  |off|        virtual address
+ * |xxxx:X|zzz|
+ * |    : |   |
+ * | \  / |   |
+ * |trans.|   |
+ * | /  \ |   |
+ * |yyyy:Y|zzz|        physical address
+ *
+ * When the page number is translated to the physical page address, the lowest
+ * bit(s) (X) that are part of the cache index are also translated (Y).
+ * If this translation changes bit(s) (X), the cache index is also afected,
+ * thus resulting in a different cache line than before.
+ * The kernel does not provide a mechanism to ensure that the page color
+ * (represented by this bit) remains the same when allocated or when pages
+ * are remapped. When user pages are mapped into kernel space, the color of
+ * the page might also change.
+ *
+ * We use the address space VMALLOC_END ... VMALLOC_END + DCACHE_WAY_SIZE * 2
+ * to temporarily map a patch so we can match the color.
+ */
+
+#if DCACHE_WAY_SIZE > PAGE_SIZE
+# define DCACHE_ALIAS_ORDER    (DCACHE_WAY_SHIFT - PAGE_SHIFT)
+# define DCACHE_ALIAS_MASK     (PAGE_MASK & (DCACHE_WAY_SIZE - 1))
+# define DCACHE_ALIAS(a)       (((a) & DCACHE_ALIAS_MASK) >> PAGE_SHIFT)
+# define DCACHE_ALIAS_EQ(a,b)  ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0)
+#else
+# define DCACHE_ALIAS_ORDER    0
+#endif
+
+#if ICACHE_WAY_SIZE > PAGE_SIZE
+# define ICACHE_ALIAS_ORDER    (ICACHE_WAY_SHIFT - PAGE_SHIFT)
+# define ICACHE_ALIAS_MASK     (PAGE_MASK & (ICACHE_WAY_SIZE - 1))
+# define ICACHE_ALIAS(a)       (((a) & ICACHE_ALIAS_MASK) >> PAGE_SHIFT)
+# define ICACHE_ALIAS_EQ(a,b)  ((((a) ^ (b)) & ICACHE_ALIAS_MASK) == 0)
+#else
+# define ICACHE_ALIAS_ORDER    0
+#endif
+
+
 #ifdef __ASSEMBLY__
 
 #define __pgprot(x)    (x)
@@ -52,6 +96,7 @@
 typedef struct { unsigned long pte; } pte_t;           /* page table entry */
 typedef struct { unsigned long pgd; } pgd_t;           /* PGD table entry */
 typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
 
 #define pte_val(x)     ((x).pte)
 #define pgd_val(x)     ((x).pgd)
@@ -90,11 +135,11 @@ extern void copy_page(void *to, void *from);
  * some extra work
  */
 
-#if (DCACHE_WAY_SIZE > PAGE_SIZE)
-void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
-void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
+#if DCACHE_WAY_SIZE > PAGE_SIZE
+extern void clear_user_page(void*, unsigned long, struct page*);
+extern void copy_user_page(void*, void*, unsigned long, struct page*);
 #else
-# define clear_user_page(page,vaddr,pg)                clear_page(page)
+# define clear_user_page(page, vaddr, pg)      clear_page(page)
 # define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
 #endif
 
@@ -126,5 +171,4 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #include <asm-generic/memory_model.h>
-#endif /* __KERNEL__ */
 #endif /* _XTENSA_PAGE_H */