aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-xtensa/page.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-xtensa/page.h')
-rw-r--r--include/asm-xtensa/page.h106
1 files changed, 74 insertions, 32 deletions
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index 1213cde75438..55ce2c9749a3 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -1,11 +1,11 @@
1/* 1/*
2 * linux/include/asm-xtensa/page.h 2 * include/asm-xtensa/page.h
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version2 as 5 * it under the terms of the GNU General Public License version2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 * 7 *
8 * Copyright (C) 2001 - 2005 Tensilica Inc. 8 * Copyright (C) 2001 - 2007 Tensilica Inc.
9 */ 9 */
10 10
11#ifndef _XTENSA_PAGE_H 11#ifndef _XTENSA_PAGE_H
@@ -14,6 +14,12 @@
14#ifdef __KERNEL__ 14#ifdef __KERNEL__
15 15
16#include <asm/processor.h> 16#include <asm/processor.h>
17#include <asm/types.h>
18#include <asm/cache.h>
19
20/*
21 * Fixed TLB translations in the processor.
22 */
17 23
18#define XCHAL_KSEG_CACHED_VADDR 0xd0000000 24#define XCHAL_KSEG_CACHED_VADDR 0xd0000000
19#define XCHAL_KSEG_BYPASS_VADDR 0xd8000000 25#define XCHAL_KSEG_BYPASS_VADDR 0xd8000000
@@ -26,13 +32,60 @@
26 */ 32 */
27 33
28#define PAGE_SHIFT 12 34#define PAGE_SHIFT 12
29#define PAGE_SIZE (1 << PAGE_SHIFT) 35#define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT)
30#define PAGE_MASK (~(PAGE_SIZE-1)) 36#define PAGE_MASK (~(PAGE_SIZE-1))
31#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK) 37#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
32 38
33#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR 39#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
34#define MAX_MEM_PFN XCHAL_KSEG_SIZE 40#define MAX_MEM_PFN XCHAL_KSEG_SIZE
35#define PGTABLE_START 0x80000000 41#define PGTABLE_START 0x80000000
42
43/*
44 * Cache aliasing:
45 *
46 * If the cache size for one way is greater than the page size, we have to
47 * deal with cache aliasing. The cache index is wider than the page size:
48 *
49 * | |cache| cache index
50 * | pfn |off| virtual address
51 * |xxxx:X|zzz|
52 * | : | |
53 * | \ / | |
54 * |trans.| |
55 * | / \ | |
56 * |yyyy:Y|zzz| physical address
57 *
58 * When the page number is translated to the physical page address, the lowest
59 * bit(s) (X) that are part of the cache index are also translated (Y).
60 * If this translation changes bit(s) (X), the cache index is also afected,
61 * thus resulting in a different cache line than before.
62 * The kernel does not provide a mechanism to ensure that the page color
63 * (represented by this bit) remains the same when allocated or when pages
64 * are remapped. When user pages are mapped into kernel space, the color of
65 * the page might also change.
66 *
67 * We use the address space VMALLOC_END ... VMALLOC_END + DCACHE_WAY_SIZE * 2
68 * to temporarily map a patch so we can match the color.
69 */
70
71#if DCACHE_WAY_SIZE > PAGE_SIZE
72# define DCACHE_ALIAS_ORDER (DCACHE_WAY_SHIFT - PAGE_SHIFT)
73# define DCACHE_ALIAS_MASK (PAGE_MASK & (DCACHE_WAY_SIZE - 1))
74# define DCACHE_ALIAS(a) (((a) & DCACHE_ALIAS_MASK) >> PAGE_SHIFT)
75# define DCACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0)
76#else
77# define DCACHE_ALIAS_ORDER 0
78#endif
79
80#if ICACHE_WAY_SIZE > PAGE_SIZE
81# define ICACHE_ALIAS_ORDER (ICACHE_WAY_SHIFT - PAGE_SHIFT)
82# define ICACHE_ALIAS_MASK (PAGE_MASK & (ICACHE_WAY_SIZE - 1))
83# define ICACHE_ALIAS(a) (((a) & ICACHE_ALIAS_MASK) >> PAGE_SHIFT)
84# define ICACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & ICACHE_ALIAS_MASK) == 0)
85#else
86# define ICACHE_ALIAS_ORDER 0
87#endif
88
36 89
37#ifdef __ASSEMBLY__ 90#ifdef __ASSEMBLY__
38 91
@@ -58,34 +111,23 @@ typedef struct { unsigned long pgprot; } pgprot_t;
58 111
59/* 112/*
60 * Pure 2^n version of get_order 113 * Pure 2^n version of get_order
114 * Use 'nsau' instructions if supported by the processor or the generic version.
61 */ 115 */
62 116
63static inline int get_order(unsigned long size) 117#if XCHAL_HAVE_NSA
118
119static inline __attribute_const__ int get_order(unsigned long size)
64{ 120{
65 int order; 121 int lz;
66#ifndef XCHAL_HAVE_NSU 122 asm ("nsau %0, %1" : "=r" (lz) : "r" ((size - 1) >> PAGE_SHIFT));
67 unsigned long x1, x2, x4, x8, x16; 123 return 32 - lz;
68
69 size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
70 x1 = size & 0xAAAAAAAA;
71 x2 = size & 0xCCCCCCCC;
72 x4 = size & 0xF0F0F0F0;
73 x8 = size & 0xFF00FF00;
74 x16 = size & 0xFFFF0000;
75 order = x2 ? 2 : 0;
76 order += (x16 != 0) * 16;
77 order += (x8 != 0) * 8;
78 order += (x4 != 0) * 4;
79 order += (x1 != 0);
80
81 return order;
82#else
83 size = (size - 1) >> PAGE_SHIFT;
84 asm ("nsau %0, %1" : "=r" (order) : "r" (size));
85 return 32 - order;
86#endif
87} 124}
88 125
126#else
127
128# include <asm-generic/page.h>
129
130#endif
89 131
90struct page; 132struct page;
91extern void clear_page(void *page); 133extern void clear_page(void *page);
@@ -96,11 +138,11 @@ extern void copy_page(void *to, void *from);
96 * some extra work 138 * some extra work
97 */ 139 */
98 140
99#if (DCACHE_WAY_SIZE > PAGE_SIZE) 141#if DCACHE_WAY_SIZE > PAGE_SIZE
100void clear_user_page(void *addr, unsigned long vaddr, struct page* page); 142extern void clear_user_page(void*, unsigned long, struct page*);
101void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page); 143extern void copy_user_page(void*, void*, unsigned long, struct page*);
102#else 144#else
103# define clear_user_page(page,vaddr,pg) clear_page(page) 145# define clear_user_page(page, vaddr, pg) clear_page(page)
104# define copy_user_page(to, from, vaddr, pg) copy_page(to, from) 146# define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
105#endif 147#endif
106 148