aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-sparc64/pgtable.h
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-12 00:57:54 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:12:25 -0500
commitc4bce90ea2069e5a87beac806de3090ab32128d5 (patch)
tree3983a206c8060ef65ba17945d1c9f69e68d88b3d /include/asm-sparc64/pgtable.h
parent490384e752a43aa281ed533e9de2da36df25c337 (diff)
[SPARC64]: Deal with PTE layout differences in SUN4V.
Yes, you heard it right, they changed the PTE layout for SUN4V. Ho hum... This is the simple and inefficient way to support this. It'll get optimized, don't worry. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/asm-sparc64/pgtable.h')
-rw-r--r--include/asm-sparc64/pgtable.h266
1 files changed, 72 insertions, 194 deletions
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index a480007f0a9d..bd8bce704a9f 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -90,134 +90,48 @@
90 90
91#endif /* !(__ASSEMBLY__) */ 91#endif /* !(__ASSEMBLY__) */
92 92
93/* Spitfire/Cheetah TTE bits. */ 93/* PTE bits which are the same in SUN4U and SUN4V format. */
94#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */ 94#define _PAGE_VALID 0x8000000000000000 /* Valid TTE */
95#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit up to date*/ 95#define _PAGE_R 0x8000000000000000 /* Keep ref bit up to date*/
96#define _PAGE_SZ4MB _AC(0x6000000000000000,UL) /* 4MB Page */ 96
97#define _PAGE_SZ512K _AC(0x4000000000000000,UL) /* 512K Page */ 97/* These are actually filled in at boot time by sun4{u,v}_pgprot_init() */
98#define _PAGE_SZ64K _AC(0x2000000000000000,UL) /* 64K Page */ 98#define __P000 __pgprot(0)
99#define _PAGE_SZ8K _AC(0x0000000000000000,UL) /* 8K Page */ 99#define __P001 __pgprot(0)
100#define _PAGE_NFO _AC(0x1000000000000000,UL) /* No Fault Only */ 100#define __P010 __pgprot(0)
101#define _PAGE_IE _AC(0x0800000000000000,UL) /* Invert Endianness */ 101#define __P011 __pgprot(0)
102#define _PAGE_SOFT2 _AC(0x07FC000000000000,UL) /* Software bits, set 2 */ 102#define __P100 __pgprot(0)
103#define _PAGE_RES1 _AC(0x0002000000000000,UL) /* Reserved */ 103#define __P101 __pgprot(0)
104#define _PAGE_SZ32MB _AC(0x0001000000000000,UL) /* (Panther) 32MB page */ 104#define __P110 __pgprot(0)
105#define _PAGE_SZ256MB _AC(0x2001000000000000,UL) /* (Panther) 256MB page */ 105#define __P111 __pgprot(0)
106#define _PAGE_SN _AC(0x0000800000000000,UL) /* (Cheetah) Snoop */ 106
107#define _PAGE_RES2 _AC(0x0000780000000000,UL) /* Reserved */ 107#define __S000 __pgprot(0)
108#define _PAGE_PADDR_SF _AC(0x000001FFFFFFE000,UL) /* (Spitfire) paddr[40:13]*/ 108#define __S001 __pgprot(0)
109#define _PAGE_PADDR _AC(0x000007FFFFFFE000,UL) /* (Cheetah) paddr[42:13] */ 109#define __S010 __pgprot(0)
110#define _PAGE_SOFT _AC(0x0000000000001F80,UL) /* Software bits */ 110#define __S011 __pgprot(0)
111#define _PAGE_L _AC(0x0000000000000040,UL) /* Locked TTE */ 111#define __S100 __pgprot(0)
112#define _PAGE_CP _AC(0x0000000000000020,UL) /* Cacheable in P-Cache */ 112#define __S101 __pgprot(0)
113#define _PAGE_CV _AC(0x0000000000000010,UL) /* Cacheable in V-Cache */ 113#define __S110 __pgprot(0)
114#define _PAGE_E _AC(0x0000000000000008,UL) /* side-Effect */ 114#define __S111 __pgprot(0)
115#define _PAGE_P _AC(0x0000000000000004,UL) /* Privileged Page */
116#define _PAGE_W _AC(0x0000000000000002,UL) /* Writable */
117#define _PAGE_G _AC(0x0000000000000001,UL) /* Global */
118
119#define _PAGE_ALL_SZ_BITS \
120 (_PAGE_SZ4MB | _PAGE_SZ512K | _PAGE_SZ64K | \
121 _PAGE_SZ8K | _PAGE_SZ32MB | _PAGE_SZ256MB)
122
123/* Here are the SpitFire software bits we use in the TTE's.
124 *
125 * WARNING: If you are going to try and start using some
126 * of the soft2 bits, you will need to make
127 * modifications to the swap entry implementation.
128 * For example, one thing that could happen is that
129 * swp_entry_to_pte() would BUG_ON() if you tried
130 * to use one of the soft2 bits for _PAGE_FILE.
131 *
132 * Like other architectures, I have aliased _PAGE_FILE with
133 * _PAGE_MODIFIED. This works because _PAGE_FILE is never
134 * interpreted that way unless _PAGE_PRESENT is clear.
135 */
136#define _PAGE_EXEC _AC(0x0000000000001000,UL) /* Executable SW bit */
137#define _PAGE_MODIFIED _AC(0x0000000000000800,UL) /* Modified (dirty) */
138#define _PAGE_FILE _AC(0x0000000000000800,UL) /* Pagecache page */
139#define _PAGE_ACCESSED _AC(0x0000000000000400,UL) /* Accessed (ref'd) */
140#define _PAGE_READ _AC(0x0000000000000200,UL) /* Readable SW Bit */
141#define _PAGE_WRITE _AC(0x0000000000000100,UL) /* Writable SW Bit */
142#define _PAGE_PRESENT _AC(0x0000000000000080,UL) /* Present */
143
144#if PAGE_SHIFT == 13
145#define _PAGE_SZBITS _PAGE_SZ8K
146#elif PAGE_SHIFT == 16
147#define _PAGE_SZBITS _PAGE_SZ64K
148#elif PAGE_SHIFT == 19
149#define _PAGE_SZBITS _PAGE_SZ512K
150#elif PAGE_SHIFT == 22
151#define _PAGE_SZBITS _PAGE_SZ4MB
152#else
153#error Wrong PAGE_SHIFT specified
154#endif
155
156#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
157#define _PAGE_SZHUGE _PAGE_SZ4MB
158#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K)
159#define _PAGE_SZHUGE _PAGE_SZ512K
160#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
161#define _PAGE_SZHUGE _PAGE_SZ64K
162#endif
163
164#define _PAGE_CACHE (_PAGE_CP | _PAGE_CV)
165
166#define __DIRTY_BITS (_PAGE_MODIFIED | _PAGE_WRITE | _PAGE_W)
167#define __ACCESS_BITS (_PAGE_ACCESSED | _PAGE_READ | _PAGE_R)
168#define __PRIV_BITS _PAGE_P
169
170#define PAGE_NONE __pgprot (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_CACHE)
171
172/* Don't set the TTE _PAGE_W bit here, else the dirty bit never gets set. */
173#define PAGE_SHARED __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
174 __ACCESS_BITS | _PAGE_WRITE | _PAGE_EXEC)
175
176#define PAGE_COPY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
177 __ACCESS_BITS | _PAGE_EXEC)
178
179#define PAGE_READONLY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
180 __ACCESS_BITS | _PAGE_EXEC)
181
182#define PAGE_KERNEL __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
183 __PRIV_BITS | \
184 __ACCESS_BITS | __DIRTY_BITS | _PAGE_EXEC)
185
186#define PAGE_SHARED_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
187 _PAGE_CACHE | \
188 __ACCESS_BITS | _PAGE_WRITE)
189
190#define PAGE_COPY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
191 _PAGE_CACHE | __ACCESS_BITS)
192
193#define PAGE_READONLY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \
194 _PAGE_CACHE | __ACCESS_BITS)
195
196#define _PFN_MASK _PAGE_PADDR
197
198#define pg_iobits (_PAGE_VALID | _PAGE_PRESENT | __DIRTY_BITS | \
199 __ACCESS_BITS | _PAGE_E)
200
201#define __P000 PAGE_NONE
202#define __P001 PAGE_READONLY_NOEXEC
203#define __P010 PAGE_COPY_NOEXEC
204#define __P011 PAGE_COPY_NOEXEC
205#define __P100 PAGE_READONLY
206#define __P101 PAGE_READONLY
207#define __P110 PAGE_COPY
208#define __P111 PAGE_COPY
209
210#define __S000 PAGE_NONE
211#define __S001 PAGE_READONLY_NOEXEC
212#define __S010 PAGE_SHARED_NOEXEC
213#define __S011 PAGE_SHARED_NOEXEC
214#define __S100 PAGE_READONLY
215#define __S101 PAGE_READONLY
216#define __S110 PAGE_SHARED
217#define __S111 PAGE_SHARED
218 115
219#ifndef __ASSEMBLY__ 116#ifndef __ASSEMBLY__
220 117
118extern pte_t mk_pte_io(unsigned long, pgprot_t, int, unsigned long);
119
120extern unsigned long pte_sz_bits(unsigned long size);
121
122extern pgprot_t PAGE_KERNEL;
123extern pgprot_t PAGE_KERNEL_LOCKED;
124extern pgprot_t PAGE_COPY;
125
126/* XXX This uglyness is for the atyfb driver's sparc mmap() support. XXX */
127extern unsigned long _PAGE_IE;
128extern unsigned long _PAGE_E;
129extern unsigned long _PAGE_CACHE;
130
131extern unsigned long pg_iobits;
132extern unsigned long _PAGE_ALL_SZ_BITS;
133extern unsigned long _PAGE_SZBITS;
134
221extern unsigned long phys_base; 135extern unsigned long phys_base;
222extern unsigned long pfn_base; 136extern unsigned long pfn_base;
223 137
@@ -229,27 +143,12 @@ extern struct page *mem_map_zero;
229 * the first physical page in the machine is at some huge physical address, 143 * the first physical page in the machine is at some huge physical address,
230 * such as 4GB. This is common on a partitioned E10000, for example. 144 * such as 4GB. This is common on a partitioned E10000, for example.
231 */ 145 */
232 146extern pte_t pfn_pte(unsigned long, pgprot_t);
233#define pfn_pte(pfn, prot) \
234 __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot) | _PAGE_SZBITS)
235#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) 147#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
148extern unsigned long pte_pfn(pte_t);
149#define pte_page(x) pfn_to_page(pte_pfn(x))
150extern pte_t pte_modify(pte_t, pgprot_t);
236 151
237#define pte_pfn(x) ((pte_val(x) & _PAGE_PADDR)>>PAGE_SHIFT)
238#define pte_page(x) pfn_to_page(pte_pfn(x))
239
240static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
241{
242 pte_t __pte;
243 const unsigned long preserve_mask = (_PFN_MASK |
244 _PAGE_MODIFIED | _PAGE_ACCESSED |
245 _PAGE_CACHE | _PAGE_E |
246 _PAGE_PRESENT | _PAGE_SZBITS);
247
248 pte_val(__pte) = (pte_val(orig_pte) & preserve_mask) |
249 (pgprot_val(new_prot) & ~preserve_mask);
250
251 return __pte;
252}
253#define pmd_set(pmdp, ptep) \ 152#define pmd_set(pmdp, ptep) \
254 (pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL)) 153 (pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
255#define pud_set(pudp, pmdp) \ 154#define pud_set(pudp, pmdp) \
@@ -259,8 +158,6 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
259#define pmd_page(pmd) virt_to_page((void *)__pmd_page(pmd)) 158#define pmd_page(pmd) virt_to_page((void *)__pmd_page(pmd))
260#define pud_page(pud) \ 159#define pud_page(pud) \
261 ((unsigned long) __va((((unsigned long)pud_val(pud))<<11UL))) 160 ((unsigned long) __va((((unsigned long)pud_val(pud))<<11UL)))
262#define pte_none(pte) (!pte_val(pte))
263#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
264#define pmd_none(pmd) (!pmd_val(pmd)) 161#define pmd_none(pmd) (!pmd_val(pmd))
265#define pmd_bad(pmd) (0) 162#define pmd_bad(pmd) (0)
266#define pmd_present(pmd) (pmd_val(pmd) != 0U) 163#define pmd_present(pmd) (pmd_val(pmd) != 0U)
@@ -270,30 +167,29 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
270#define pud_present(pud) (pud_val(pud) != 0U) 167#define pud_present(pud) (pud_val(pud) != 0U)
271#define pud_clear(pudp) (pud_val(*(pudp)) = 0U) 168#define pud_clear(pudp) (pud_val(*(pudp)) = 0U)
272 169
170/* Same in both SUN4V and SUN4U. */
171#define pte_none(pte) (!pte_val(pte))
172
173extern unsigned long pte_present(pte_t);
174
273/* The following only work if pte_present() is true. 175/* The following only work if pte_present() is true.
274 * Undefined behaviour if not.. 176 * Undefined behaviour if not..
275 */ 177 */
276#define pte_read(pte) (pte_val(pte) & _PAGE_READ) 178extern unsigned long pte_read(pte_t);
277#define pte_exec(pte) (pte_val(pte) & _PAGE_EXEC) 179extern unsigned long pte_exec(pte_t);
278#define pte_write(pte) (pte_val(pte) & _PAGE_WRITE) 180extern unsigned long pte_write(pte_t);
279#define pte_dirty(pte) (pte_val(pte) & _PAGE_MODIFIED) 181extern unsigned long pte_dirty(pte_t);
280#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED) 182extern unsigned long pte_young(pte_t);
281#define pte_wrprotect(pte) (__pte(pte_val(pte) & ~(_PAGE_WRITE|_PAGE_W))) 183extern pte_t pte_wrprotect(pte_t);
282#define pte_rdprotect(pte) \ 184extern pte_t pte_rdprotect(pte_t);
283 (__pte(((pte_val(pte)<<1UL)>>1UL) & ~_PAGE_READ)) 185extern pte_t pte_mkclean(pte_t);
284#define pte_mkclean(pte) \ 186extern pte_t pte_mkold(pte_t);
285 (__pte(pte_val(pte) & ~(_PAGE_MODIFIED|_PAGE_W)))
286#define pte_mkold(pte) \
287 (__pte(((pte_val(pte)<<1UL)>>1UL) & ~_PAGE_ACCESSED))
288
289/* Permanent address of a page. */
290#define __page_address(page) page_address(page)
291 187
292/* Be very careful when you change these three, they are delicate. */ 188/* Be very careful when you change these three, they are delicate. */
293#define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_ACCESSED | _PAGE_R)) 189extern pte_t pte_mkyoung(pte_t);
294#define pte_mkwrite(pte) (__pte(pte_val(pte) | _PAGE_WRITE)) 190extern pte_t pte_mkwrite(pte_t);
295#define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_MODIFIED | _PAGE_W)) 191extern pte_t pte_mkdirty(pte_t);
296#define pte_mkhuge(pte) (__pte(pte_val(pte) | _PAGE_SZHUGE)) 192extern pte_t pte_mkhuge(pte_t);
297 193
298/* to find an entry in a page-table-directory. */ 194/* to find an entry in a page-table-directory. */
299#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) 195#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
@@ -328,6 +224,9 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p
328 224
329 /* It is more efficient to let flush_tlb_kernel_range() 225 /* It is more efficient to let flush_tlb_kernel_range()
330 * handle init_mm tlb flushes. 226 * handle init_mm tlb flushes.
227 *
228 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
229 * and SUN4V pte layout, so this inline test is fine.
331 */ 230 */
332 if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID)) 231 if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID))
333 tlb_batch_add(mm, addr, ptep, orig); 232 tlb_batch_add(mm, addr, ptep, orig);
@@ -362,42 +261,23 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
362#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) 261#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
363 262
364/* File offset in PTE support. */ 263/* File offset in PTE support. */
365#define pte_file(pte) (pte_val(pte) & _PAGE_FILE) 264extern unsigned long pte_file(pte_t);
366#define pte_to_pgoff(pte) (pte_val(pte) >> PAGE_SHIFT) 265#define pte_to_pgoff(pte) (pte_val(pte) >> PAGE_SHIFT)
367#define pgoff_to_pte(off) (__pte(((off) << PAGE_SHIFT) | _PAGE_FILE)) 266extern pte_t pgoff_to_pte(unsigned long);
368#define PTE_FILE_MAX_BITS (64UL - PAGE_SHIFT - 1UL) 267#define PTE_FILE_MAX_BITS (64UL - PAGE_SHIFT - 1UL)
369 268
370extern unsigned long prom_virt_to_phys(unsigned long, int *); 269extern unsigned long prom_virt_to_phys(unsigned long, int *);
371 270
372static __inline__ unsigned long 271extern unsigned long sun4u_get_pte(unsigned long);
373sun4u_get_pte (unsigned long addr)
374{
375 pgd_t *pgdp;
376 pud_t *pudp;
377 pmd_t *pmdp;
378 pte_t *ptep;
379
380 if (addr >= PAGE_OFFSET)
381 return addr & _PAGE_PADDR;
382 if ((addr >= LOW_OBP_ADDRESS) && (addr < HI_OBP_ADDRESS))
383 return prom_virt_to_phys(addr, NULL);
384 pgdp = pgd_offset_k(addr);
385 pudp = pud_offset(pgdp, addr);
386 pmdp = pmd_offset(pudp, addr);
387 ptep = pte_offset_kernel(pmdp, addr);
388 return pte_val(*ptep) & _PAGE_PADDR;
389}
390 272
391static __inline__ unsigned long 273static inline unsigned long __get_phys(unsigned long addr)
392__get_phys (unsigned long addr)
393{ 274{
394 return sun4u_get_pte (addr); 275 return sun4u_get_pte(addr);
395} 276}
396 277
397static __inline__ int 278static inline int __get_iospace(unsigned long addr)
398__get_iospace (unsigned long addr)
399{ 279{
400 return ((sun4u_get_pte (addr) & 0xf0000000) >> 28); 280 return ((sun4u_get_pte(addr) & 0xf0000000) >> 28);
401} 281}
402 282
403extern unsigned long *sparc64_valid_addr_bitmap; 283extern unsigned long *sparc64_valid_addr_bitmap;
@@ -411,9 +291,7 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
411 unsigned long size, pgprot_t prot); 291 unsigned long size, pgprot_t prot);
412 292
413/* Clear virtual and physical cachability, set side-effect bit. */ 293/* Clear virtual and physical cachability, set side-effect bit. */
414#define pgprot_noncached(prot) \ 294extern pgprot_t pgprot_noncached(pgprot_t);
415 (__pgprot((pgprot_val(prot) & ~(_PAGE_CP | _PAGE_CV)) | \
416 _PAGE_E))
417 295
418/* 296/*
419 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in 297 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in