aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r--include/asm-powerpc/io.h462
-rw-r--r--include/asm-powerpc/mmu.h399
-rw-r--r--include/asm-powerpc/mmu_context.h89
-rw-r--r--include/asm-powerpc/mmzone.h50
-rw-r--r--include/asm-powerpc/pci-bridge.h153
-rw-r--r--include/asm-powerpc/pgalloc.h156
-rw-r--r--include/asm-powerpc/pgtable-4k.h91
-rw-r--r--include/asm-powerpc/pgtable-64k.h90
-rw-r--r--include/asm-powerpc/pgtable.h524
9 files changed, 2014 insertions, 0 deletions
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
new file mode 100644
index 000000000000..48938d84d055
--- /dev/null
+++ b/include/asm-powerpc/io.h
@@ -0,0 +1,462 @@
1#ifndef _ASM_POWERPC_IO_H
2#define _ASM_POWERPC_IO_H
3
4/*
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10
11#ifndef CONFIG_PPC64
12#include <asm-ppc/io.h>
13#else
14
15#include <linux/compiler.h>
16#include <asm/page.h>
17#include <asm/byteorder.h>
18#ifdef CONFIG_PPC_ISERIES
19#include <asm/iseries/iseries_io.h>
20#endif
21#include <asm/synch.h>
22#include <asm/delay.h>
23
24#include <asm-generic/iomap.h>
25
26#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 __iomem *)(p), (a), (c))
27#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 __iomem *)(p), (a), (c))
28#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 __iomem *)(p), (a), (c))
29#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 __iomem *)(p), (a), (c))
30
31
32#define SIO_CONFIG_RA 0x398
33#define SIO_CONFIG_RD 0x399
34
35#define SLOW_DOWN_IO
36
37extern unsigned long isa_io_base;
38extern unsigned long pci_io_base;
39extern unsigned long io_page_mask;
40
41#define MAX_ISA_PORT 0x10000
42
43#define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) \
44 & io_page_mask)
45
46#ifdef CONFIG_PPC_ISERIES
47/* __raw_* accessors aren't supported on iSeries */
48#define __raw_readb(addr) { BUG(); 0; }
49#define __raw_readw(addr) { BUG(); 0; }
50#define __raw_readl(addr) { BUG(); 0; }
51#define __raw_readq(addr) { BUG(); 0; }
52#define __raw_writeb(v, addr) { BUG(); 0; }
53#define __raw_writew(v, addr) { BUG(); 0; }
54#define __raw_writel(v, addr) { BUG(); 0; }
55#define __raw_writeq(v, addr) { BUG(); 0; }
56#define readb(addr) iSeries_Read_Byte(addr)
57#define readw(addr) iSeries_Read_Word(addr)
58#define readl(addr) iSeries_Read_Long(addr)
59#define writeb(data, addr) iSeries_Write_Byte((data),(addr))
60#define writew(data, addr) iSeries_Write_Word((data),(addr))
61#define writel(data, addr) iSeries_Write_Long((data),(addr))
62#define memset_io(a,b,c) iSeries_memset_io((a),(b),(c))
63#define memcpy_fromio(a,b,c) iSeries_memcpy_fromio((a), (b), (c))
64#define memcpy_toio(a,b,c) iSeries_memcpy_toio((a), (b), (c))
65
66#define inb(addr) readb(((void __iomem *)(long)(addr)))
67#define inw(addr) readw(((void __iomem *)(long)(addr)))
68#define inl(addr) readl(((void __iomem *)(long)(addr)))
69#define outb(data,addr) writeb(data,((void __iomem *)(long)(addr)))
70#define outw(data,addr) writew(data,((void __iomem *)(long)(addr)))
71#define outl(data,addr) writel(data,((void __iomem *)(long)(addr)))
72/*
73 * The *_ns versions below don't do byte-swapping.
74 * Neither do the standard versions now, these are just here
75 * for older code.
76 */
77#define insw_ns(port, buf, ns) _insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
78#define insl_ns(port, buf, nl) _insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
79#else
80
81static inline unsigned char __raw_readb(const volatile void __iomem *addr)
82{
83 return *(volatile unsigned char __force *)addr;
84}
85static inline unsigned short __raw_readw(const volatile void __iomem *addr)
86{
87 return *(volatile unsigned short __force *)addr;
88}
89static inline unsigned int __raw_readl(const volatile void __iomem *addr)
90{
91 return *(volatile unsigned int __force *)addr;
92}
93static inline unsigned long __raw_readq(const volatile void __iomem *addr)
94{
95 return *(volatile unsigned long __force *)addr;
96}
97static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
98{
99 *(volatile unsigned char __force *)addr = v;
100}
101static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
102{
103 *(volatile unsigned short __force *)addr = v;
104}
105static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
106{
107 *(volatile unsigned int __force *)addr = v;
108}
109static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
110{
111 *(volatile unsigned long __force *)addr = v;
112}
113#define readb(addr) eeh_readb(addr)
114#define readw(addr) eeh_readw(addr)
115#define readl(addr) eeh_readl(addr)
116#define readq(addr) eeh_readq(addr)
117#define writeb(data, addr) eeh_writeb((data), (addr))
118#define writew(data, addr) eeh_writew((data), (addr))
119#define writel(data, addr) eeh_writel((data), (addr))
120#define writeq(data, addr) eeh_writeq((data), (addr))
121#define memset_io(a,b,c) eeh_memset_io((a),(b),(c))
122#define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(b),(c))
123#define memcpy_toio(a,b,c) eeh_memcpy_toio((a),(b),(c))
124#define inb(port) eeh_inb((unsigned long)port)
125#define outb(val, port) eeh_outb(val, (unsigned long)port)
126#define inw(port) eeh_inw((unsigned long)port)
127#define outw(val, port) eeh_outw(val, (unsigned long)port)
128#define inl(port) eeh_inl((unsigned long)port)
129#define outl(val, port) eeh_outl(val, (unsigned long)port)
130
131/*
132 * The insw/outsw/insl/outsl macros don't do byte-swapping.
133 * They are only used in practice for transferring buffers which
134 * are arrays of bytes, and byte-swapping is not appropriate in
135 * that case. - paulus */
136#define insb(port, buf, ns) eeh_insb((port), (buf), (ns))
137#define insw(port, buf, ns) eeh_insw_ns((port), (buf), (ns))
138#define insl(port, buf, nl) eeh_insl_ns((port), (buf), (nl))
139#define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns))
140#define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl))
141
142#define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
143#define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
144#define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
145
146#endif
147
148#define readb_relaxed(addr) readb(addr)
149#define readw_relaxed(addr) readw(addr)
150#define readl_relaxed(addr) readl(addr)
151#define readq_relaxed(addr) readq(addr)
152
153extern void _insb(volatile u8 __iomem *port, void *buf, int ns);
154extern void _outsb(volatile u8 __iomem *port, const void *buf, int ns);
155extern void _insw(volatile u16 __iomem *port, void *buf, int ns);
156extern void _outsw(volatile u16 __iomem *port, const void *buf, int ns);
157extern void _insl(volatile u32 __iomem *port, void *buf, int nl);
158extern void _outsl(volatile u32 __iomem *port, const void *buf, int nl);
159extern void _insw_ns(volatile u16 __iomem *port, void *buf, int ns);
160extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, int ns);
161extern void _insl_ns(volatile u32 __iomem *port, void *buf, int nl);
162extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, int nl);
163
164#define mmiowb()
165
166/*
167 * output pause versions need a delay at least for the
168 * w83c105 ide controller in a p610.
169 */
170#define inb_p(port) inb(port)
171#define outb_p(val, port) (udelay(1), outb((val), (port)))
172#define inw_p(port) inw(port)
173#define outw_p(val, port) (udelay(1), outw((val), (port)))
174#define inl_p(port) inl(port)
175#define outl_p(val, port) (udelay(1), outl((val), (port)))
176
177/*
178 * The *_ns versions below don't do byte-swapping.
179 * Neither do the standard versions now, these are just here
180 * for older code.
181 */
182#define outsw_ns(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
183#define outsl_ns(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
184
185
186#define IO_SPACE_LIMIT ~(0UL)
187
188
189#ifdef __KERNEL__
190extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr,
191 unsigned long size, unsigned long flags);
192extern void __iomem *__ioremap(unsigned long address, unsigned long size,
193 unsigned long flags);
194
195/**
196 * ioremap - map bus memory into CPU space
197 * @address: bus address of the memory
198 * @size: size of the resource to map
199 *
200 * ioremap performs a platform specific sequence of operations to
201 * make bus memory CPU accessible via the readb/readw/readl/writeb/
202 * writew/writel functions and the other mmio helpers. The returned
203 * address is not guaranteed to be usable directly as a virtual
204 * address.
205 */
206extern void __iomem *ioremap(unsigned long address, unsigned long size);
207
208#define ioremap_nocache(addr, size) ioremap((addr), (size))
209extern int iounmap_explicit(volatile void __iomem *addr, unsigned long size);
210extern void iounmap(volatile void __iomem *addr);
211extern void __iomem * reserve_phb_iospace(unsigned long size);
212
213/**
214 * virt_to_phys - map virtual addresses to physical
215 * @address: address to remap
216 *
217 * The returned physical address is the physical (CPU) mapping for
218 * the memory address given. It is only valid to use this function on
219 * addresses directly mapped or allocated via kmalloc.
220 *
221 * This function does not give bus mappings for DMA transfers. In
222 * almost all conceivable cases a device driver should not be using
223 * this function
224 */
225static inline unsigned long virt_to_phys(volatile void * address)
226{
227 return __pa((unsigned long)address);
228}
229
230/**
231 * phys_to_virt - map physical address to virtual
232 * @address: address to remap
233 *
234 * The returned virtual address is a current CPU mapping for
235 * the memory address given. It is only valid to use this function on
236 * addresses that have a kernel mapping
237 *
238 * This function does not handle bus mappings for DMA transfers. In
239 * almost all conceivable cases a device driver should not be using
240 * this function
241 */
242static inline void * phys_to_virt(unsigned long address)
243{
244 return (void *)__va(address);
245}
246
247/*
248 * Change "struct page" to physical address.
249 */
250#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
251
252/* We do NOT want virtual merging, it would put too much pressure on
253 * our iommu allocator. Instead, we want drivers to be smart enough
254 * to coalesce sglists that happen to have been mapped in a contiguous
255 * way by the iommu
256 */
257#define BIO_VMERGE_BOUNDARY 0
258
259#endif /* __KERNEL__ */
260
261static inline void iosync(void)
262{
263 __asm__ __volatile__ ("sync" : : : "memory");
264}
265
266/* Enforce in-order execution of data I/O.
267 * No distinction between read/write on PPC; use eieio for all three.
268 */
269#define iobarrier_rw() eieio()
270#define iobarrier_r() eieio()
271#define iobarrier_w() eieio()
272
273/*
274 * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
275 * These routines do not perform EEH-related I/O address translation,
276 * and should not be used directly by device drivers. Use inb/readb
277 * instead.
278 */
279static inline int in_8(const volatile unsigned char __iomem *addr)
280{
281 int ret;
282
283 __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
284 : "=r" (ret) : "m" (*addr));
285 return ret;
286}
287
288static inline void out_8(volatile unsigned char __iomem *addr, int val)
289{
290 __asm__ __volatile__("stb%U0%X0 %1,%0; sync"
291 : "=m" (*addr) : "r" (val));
292}
293
294static inline int in_le16(const volatile unsigned short __iomem *addr)
295{
296 int ret;
297
298 __asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync"
299 : "=r" (ret) : "r" (addr), "m" (*addr));
300 return ret;
301}
302
303static inline int in_be16(const volatile unsigned short __iomem *addr)
304{
305 int ret;
306
307 __asm__ __volatile__("lhz%U1%X1 %0,%1; twi 0,%0,0; isync"
308 : "=r" (ret) : "m" (*addr));
309 return ret;
310}
311
312static inline void out_le16(volatile unsigned short __iomem *addr, int val)
313{
314 __asm__ __volatile__("sthbrx %1,0,%2; sync"
315 : "=m" (*addr) : "r" (val), "r" (addr));
316}
317
318static inline void out_be16(volatile unsigned short __iomem *addr, int val)
319{
320 __asm__ __volatile__("sth%U0%X0 %1,%0; sync"
321 : "=m" (*addr) : "r" (val));
322}
323
324static inline unsigned in_le32(const volatile unsigned __iomem *addr)
325{
326 unsigned ret;
327
328 __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
329 : "=r" (ret) : "r" (addr), "m" (*addr));
330 return ret;
331}
332
333static inline unsigned in_be32(const volatile unsigned __iomem *addr)
334{
335 unsigned ret;
336
337 __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
338 : "=r" (ret) : "m" (*addr));
339 return ret;
340}
341
342static inline void out_le32(volatile unsigned __iomem *addr, int val)
343{
344 __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
345 : "r" (val), "r" (addr));
346}
347
348static inline void out_be32(volatile unsigned __iomem *addr, int val)
349{
350 __asm__ __volatile__("stw%U0%X0 %1,%0; sync"
351 : "=m" (*addr) : "r" (val));
352}
353
354static inline unsigned long in_le64(const volatile unsigned long __iomem *addr)
355{
356 unsigned long tmp, ret;
357
358 __asm__ __volatile__(
359 "ld %1,0(%2)\n"
360 "twi 0,%1,0\n"
361 "isync\n"
362 "rldimi %0,%1,5*8,1*8\n"
363 "rldimi %0,%1,3*8,2*8\n"
364 "rldimi %0,%1,1*8,3*8\n"
365 "rldimi %0,%1,7*8,4*8\n"
366 "rldicl %1,%1,32,0\n"
367 "rlwimi %0,%1,8,8,31\n"
368 "rlwimi %0,%1,24,16,23\n"
369 : "=r" (ret) , "=r" (tmp) : "b" (addr) , "m" (*addr));
370 return ret;
371}
372
373static inline unsigned long in_be64(const volatile unsigned long __iomem *addr)
374{
375 unsigned long ret;
376
377 __asm__ __volatile__("ld%U1%X1 %0,%1; twi 0,%0,0; isync"
378 : "=r" (ret) : "m" (*addr));
379 return ret;
380}
381
382static inline void out_le64(volatile unsigned long __iomem *addr, unsigned long val)
383{
384 unsigned long tmp;
385
386 __asm__ __volatile__(
387 "rldimi %0,%1,5*8,1*8\n"
388 "rldimi %0,%1,3*8,2*8\n"
389 "rldimi %0,%1,1*8,3*8\n"
390 "rldimi %0,%1,7*8,4*8\n"
391 "rldicl %1,%1,32,0\n"
392 "rlwimi %0,%1,8,8,31\n"
393 "rlwimi %0,%1,24,16,23\n"
394 "std %0,0(%3)\n"
395 "sync"
396 : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr));
397}
398
399static inline void out_be64(volatile unsigned long __iomem *addr, unsigned long val)
400{
401 __asm__ __volatile__("std%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val));
402}
403
404#ifndef CONFIG_PPC_ISERIES
405#include <asm/eeh.h>
406#endif
407
408#ifdef __KERNEL__
409
410/**
411 * check_signature - find BIOS signatures
412 * @io_addr: mmio address to check
413 * @signature: signature block
414 * @length: length of signature
415 *
416 * Perform a signature comparison with the mmio address io_addr. This
417 * address should have been obtained by ioremap.
418 * Returns 1 on a match.
419 */
420static inline int check_signature(const volatile void __iomem * io_addr,
421 const unsigned char *signature, int length)
422{
423 int retval = 0;
424#ifndef CONFIG_PPC_ISERIES
425 do {
426 if (readb(io_addr) != *signature)
427 goto out;
428 io_addr++;
429 signature++;
430 length--;
431 } while (length);
432 retval = 1;
433out:
434#endif
435 return retval;
436}
437
438/* Nothing to do */
439
440#define dma_cache_inv(_start,_size) do { } while (0)
441#define dma_cache_wback(_start,_size) do { } while (0)
442#define dma_cache_wback_inv(_start,_size) do { } while (0)
443
444/* Check of existence of legacy devices */
445extern int check_legacy_ioport(unsigned long base_port);
446
447
448/*
449 * Convert a physical pointer to a virtual kernel pointer for /dev/mem
450 * access
451 */
452#define xlate_dev_mem_ptr(p) __va(p)
453
454/*
455 * Convert a virtual cached pointer to an uncached pointer
456 */
457#define xlate_dev_kmem_ptr(p) p
458
459#endif /* __KERNEL__ */
460
461#endif /* CONFIG_PPC64 */
462#endif /* _ASM_POWERPC_IO_H */
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h
new file mode 100644
index 000000000000..c1b4bbabbe97
--- /dev/null
+++ b/include/asm-powerpc/mmu.h
@@ -0,0 +1,399 @@
1#ifndef _ASM_POWERPC_MMU_H_
2#define _ASM_POWERPC_MMU_H_
3
4#ifndef CONFIG_PPC64
5#include <asm-ppc/mmu.h>
6#else
7
8/*
9 * PowerPC memory management structures
10 *
11 * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com>
12 * PPC64 rework.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
18 */
19
20#include <asm/asm-compat.h>
21#include <asm/page.h>
22
23/*
24 * Segment table
25 */
26
27#define STE_ESID_V 0x80
28#define STE_ESID_KS 0x20
29#define STE_ESID_KP 0x10
30#define STE_ESID_N 0x08
31
32#define STE_VSID_SHIFT 12
33
34/* Location of cpu0's segment table */
35#define STAB0_PAGE 0x6
36#define STAB0_PHYS_ADDR (STAB0_PAGE<<12)
37
38#ifndef __ASSEMBLY__
39extern char initial_stab[];
40#endif /* ! __ASSEMBLY */
41
42/*
43 * SLB
44 */
45
46#define SLB_NUM_BOLTED 3
47#define SLB_CACHE_ENTRIES 8
48
49/* Bits in the SLB ESID word */
50#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */
51
52/* Bits in the SLB VSID word */
53#define SLB_VSID_SHIFT 12
54#define SLB_VSID_B ASM_CONST(0xc000000000000000)
55#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000)
56#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000)
57#define SLB_VSID_KS ASM_CONST(0x0000000000000800)
58#define SLB_VSID_KP ASM_CONST(0x0000000000000400)
59#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */
60#define SLB_VSID_L ASM_CONST(0x0000000000000100)
61#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */
62#define SLB_VSID_LP ASM_CONST(0x0000000000000030)
63#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000)
64#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010)
65#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020)
66#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030)
67#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP)
68
69#define SLB_VSID_KERNEL (SLB_VSID_KP)
70#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C)
71
72#define SLBIE_C (0x08000000)
73
74/*
75 * Hash table
76 */
77
78#define HPTES_PER_GROUP 8
79
80#define HPTE_V_AVPN_SHIFT 7
81#define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80)
82#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
83#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN))
84#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010)
85#define HPTE_V_LOCK ASM_CONST(0x0000000000000008)
86#define HPTE_V_LARGE ASM_CONST(0x0000000000000004)
87#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002)
88#define HPTE_V_VALID ASM_CONST(0x0000000000000001)
89
90#define HPTE_R_PP0 ASM_CONST(0x8000000000000000)
91#define HPTE_R_TS ASM_CONST(0x4000000000000000)
92#define HPTE_R_RPN_SHIFT 12
93#define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000)
94#define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff)
95#define HPTE_R_PP ASM_CONST(0x0000000000000003)
96#define HPTE_R_N ASM_CONST(0x0000000000000004)
97
98/* Values for PP (assumes Ks=0, Kp=1) */
99/* pp0 will always be 0 for linux */
100#define PP_RWXX 0 /* Supervisor read/write, User none */
101#define PP_RWRX 1 /* Supervisor read/write, User read */
102#define PP_RWRW 2 /* Supervisor read/write, User read/write */
103#define PP_RXRX 3 /* Supervisor read, User read */
104
105#ifndef __ASSEMBLY__
106
107typedef struct {
108 unsigned long v;
109 unsigned long r;
110} hpte_t;
111
112extern hpte_t *htab_address;
113extern unsigned long htab_hash_mask;
114
115/*
116 * Page size definition
117 *
118 * shift : is the "PAGE_SHIFT" value for that page size
119 * sllp : is a bit mask with the value of SLB L || LP to be or'ed
120 * directly to a slbmte "vsid" value
121 * penc : is the HPTE encoding mask for the "LP" field:
122 *
123 */
124struct mmu_psize_def
125{
126 unsigned int shift; /* number of bits */
127 unsigned int penc; /* HPTE encoding */
128 unsigned int tlbiel; /* tlbiel supported for that page size */
129 unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */
130 unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */
131};
132
133#endif /* __ASSEMBLY__ */
134
135/*
136 * The kernel use the constants below to index in the page sizes array.
137 * The use of fixed constants for this purpose is better for performances
138 * of the low level hash refill handlers.
139 *
140 * A non supported page size has a "shift" field set to 0
141 *
142 * Any new page size being implemented can get a new entry in here. Whether
143 * the kernel will use it or not is a different matter though. The actual page
144 * size used by hugetlbfs is not defined here and may be made variable
145 */
146
147#define MMU_PAGE_4K 0 /* 4K */
148#define MMU_PAGE_64K 1 /* 64K */
149#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */
150#define MMU_PAGE_1M 3 /* 1M */
151#define MMU_PAGE_16M 4 /* 16M */
152#define MMU_PAGE_16G 5 /* 16G */
153#define MMU_PAGE_COUNT 6
154
155#ifndef __ASSEMBLY__
156
157/*
158 * The current system page sizes
159 */
160extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
161extern int mmu_linear_psize;
162extern int mmu_virtual_psize;
163
164#ifdef CONFIG_HUGETLB_PAGE
165/*
166 * The page size index of the huge pages for use by hugetlbfs
167 */
168extern int mmu_huge_psize;
169
170#endif /* CONFIG_HUGETLB_PAGE */
171
172/*
173 * This function sets the AVPN and L fields of the HPTE appropriately
174 * for the page size
175 */
176static inline unsigned long hpte_encode_v(unsigned long va, int psize)
177{
178 unsigned long v =
179 v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
180 v <<= HPTE_V_AVPN_SHIFT;
181 if (psize != MMU_PAGE_4K)
182 v |= HPTE_V_LARGE;
183 return v;
184}
185
186/*
187 * This function sets the ARPN, and LP fields of the HPTE appropriately
188 * for the page size. We assume the pa is already "clean" that is properly
189 * aligned for the requested page size
190 */
191static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
192{
193 unsigned long r;
194
195 /* A 4K page needs no special encoding */
196 if (psize == MMU_PAGE_4K)
197 return pa & HPTE_R_RPN;
198 else {
199 unsigned int penc = mmu_psize_defs[psize].penc;
200 unsigned int shift = mmu_psize_defs[psize].shift;
201 return (pa & ~((1ul << shift) - 1)) | (penc << 12);
202 }
203 return r;
204}
205
206/*
207 * This hashes a virtual address for a 256Mb segment only for now
208 */
209
210static inline unsigned long hpt_hash(unsigned long va, unsigned int shift)
211{
212 return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift);
213}
214
215extern int __hash_page_4K(unsigned long ea, unsigned long access,
216 unsigned long vsid, pte_t *ptep, unsigned long trap,
217 unsigned int local);
218extern int __hash_page_64K(unsigned long ea, unsigned long access,
219 unsigned long vsid, pte_t *ptep, unsigned long trap,
220 unsigned int local);
221struct mm_struct;
222extern int hash_huge_page(struct mm_struct *mm, unsigned long access,
223 unsigned long ea, unsigned long vsid, int local);
224
225extern void htab_finish_init(void);
226extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
227 unsigned long pstart, unsigned long mode,
228 int psize);
229
230extern void htab_initialize(void);
231extern void htab_initialize_secondary(void);
232extern void hpte_init_native(void);
233extern void hpte_init_lpar(void);
234extern void hpte_init_iSeries(void);
235extern void mm_init_ppc64(void);
236
237extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
238 unsigned long va, unsigned long prpn,
239 unsigned long rflags,
240 unsigned long vflags, int psize);
241
242extern long native_hpte_insert(unsigned long hpte_group,
243 unsigned long va, unsigned long prpn,
244 unsigned long rflags,
245 unsigned long vflags, int psize);
246
247extern long iSeries_hpte_insert(unsigned long hpte_group,
248 unsigned long va, unsigned long prpn,
249 unsigned long rflags,
250 unsigned long vflags, int psize);
251
252extern void stabs_alloc(void);
253extern void slb_initialize(void);
254extern void stab_initialize(unsigned long stab);
255
256#endif /* __ASSEMBLY__ */
257
258/*
259 * VSID allocation
260 *
261 * We first generate a 36-bit "proto-VSID". For kernel addresses this
262 * is equal to the ESID, for user addresses it is:
263 * (context << 15) | (esid & 0x7fff)
264 *
265 * The two forms are distinguishable because the top bit is 0 for user
266 * addresses, whereas the top two bits are 1 for kernel addresses.
267 * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
268 * now.
269 *
270 * The proto-VSIDs are then scrambled into real VSIDs with the
271 * multiplicative hash:
272 *
273 * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
274 * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
275 * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
276 *
277 * This scramble is only well defined for proto-VSIDs below
278 * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
279 * reserved. VSID_MULTIPLIER is prime, so in particular it is
280 * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
281 * Because the modulus is 2^n-1 we can compute it efficiently without
282 * a divide or extra multiply (see below).
283 *
284 * This scheme has several advantages over older methods:
285 *
286 * - We have VSIDs allocated for every kernel address
287 * (i.e. everything above 0xC000000000000000), except the very top
288 * segment, which simplifies several things.
289 *
290 * - We allow for 15 significant bits of ESID and 20 bits of
291 * context for user addresses. i.e. 8T (43 bits) of address space for
292 * up to 1M contexts (although the page table structure and context
293 * allocation will need changes to take advantage of this).
294 *
295 * - The scramble function gives robust scattering in the hash
296 * table (at least based on some initial results). The previous
297 * method was more susceptible to pathological cases giving excessive
298 * hash collisions.
299 */
300/*
301 * WARNING - If you change these you must make sure the asm
302 * implementations in slb_allocate (slb_low.S), do_stab_bolted
303 * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
304 *
305 * You'll also need to change the precomputed VSID values in head.S
306 * which are used by the iSeries firmware.
307 */
308
309#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */
310#define VSID_BITS 36
311#define VSID_MODULUS ((1UL<<VSID_BITS)-1)
312
313#define CONTEXT_BITS 19
314#define USER_ESID_BITS 16
315
316#define USER_VSID_RANGE (1UL << (USER_ESID_BITS + SID_SHIFT))
317
318/*
319 * This macro generates asm code to compute the VSID scramble
320 * function. Used in slb_allocate() and do_stab_bolted. The function
321 * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
322 *
323 * rt = register continaing the proto-VSID and into which the
324 * VSID will be stored
325 * rx = scratch register (clobbered)
326 *
327 * - rt and rx must be different registers
328 * - The answer will end up in the low 36 bits of rt. The higher
329 * bits may contain other garbage, so you may need to mask the
330 * result.
331 */
332#define ASM_VSID_SCRAMBLE(rt, rx) \
333 lis rx,VSID_MULTIPLIER@h; \
334 ori rx,rx,VSID_MULTIPLIER@l; \
335 mulld rt,rt,rx; /* rt = rt * MULTIPLIER */ \
336 \
337 srdi rx,rt,VSID_BITS; \
338 clrldi rt,rt,(64-VSID_BITS); \
339 add rt,rt,rx; /* add high and low bits */ \
340 /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and \
341 * 2^36-1+2^28-1. That in particular means that if r3 >= \
342 * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \
343 * the bit clear, r3 already has the answer we want, if it \
344 * doesn't, the answer is the low 36 bits of r3+1. So in all \
345 * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
346 addi rx,rt,1; \
347 srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \
348 add rt,rt,rx
349
350
351#ifndef __ASSEMBLY__
352
353typedef unsigned long mm_context_id_t;
354
355typedef struct {
356 mm_context_id_t id;
357#ifdef CONFIG_HUGETLB_PAGE
358 u16 low_htlb_areas, high_htlb_areas;
359#endif
360} mm_context_t;
361
362
363static inline unsigned long vsid_scramble(unsigned long protovsid)
364{
365#if 0
366 /* The code below is equivalent to this function for arguments
367 * < 2^VSID_BITS, which is all this should ever be called
368 * with. However gcc is not clever enough to compute the
369 * modulus (2^n-1) without a second multiply. */
370 return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
371#else /* 1 */
372 unsigned long x;
373
374 x = protovsid * VSID_MULTIPLIER;
375 x = (x >> VSID_BITS) + (x & VSID_MODULUS);
376 return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
377#endif /* 1 */
378}
379
380/* This is only valid for addresses >= KERNELBASE */
381static inline unsigned long get_kernel_vsid(unsigned long ea)
382{
383 return vsid_scramble(ea >> SID_SHIFT);
384}
385
386/* This is only valid for user addresses (which are below 2^41) */
387static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
388{
389 return vsid_scramble((context << USER_ESID_BITS)
390 | (ea >> SID_SHIFT));
391}
392
393#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS)
394#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea))
395
396#endif /* __ASSEMBLY */
397
398#endif /* CONFIG_PPC64 */
399#endif /* _ASM_POWERPC_MMU_H_ */
diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h
new file mode 100644
index 000000000000..ea6798c7d5fc
--- /dev/null
+++ b/include/asm-powerpc/mmu_context.h
@@ -0,0 +1,89 @@
1#ifndef __ASM_POWERPC_MMU_CONTEXT_H
2#define __ASM_POWERPC_MMU_CONTEXT_H
3
4#ifndef CONFIG_PPC64
5#include <asm-ppc/mmu_context.h>
6#else
7
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <asm/mmu.h>
11#include <asm/cputable.h>
12
13/*
14 * Copyright (C) 2001 PPC 64 Team, IBM Corp
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
20 */
21
22/*
23 * Getting into a kernel thread, there is no valid user segment, mark
24 * paca->pgdir NULL so that SLB miss on user addresses will fault
25 */
26static inline void enter_lazy_tlb(struct mm_struct *mm,
27 struct task_struct *tsk)
28{
29#ifdef CONFIG_PPC_64K_PAGES
30 get_paca()->pgdir = NULL;
31#endif /* CONFIG_PPC_64K_PAGES */
32}
33
34#define NO_CONTEXT 0
35#define MAX_CONTEXT (0x100000-1)
36
37extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
38extern void destroy_context(struct mm_struct *mm);
39
40extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm);
41extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
42
43/*
44 * switch_mm is the entry point called from the architecture independent
45 * code in kernel/sched.c
46 */
47static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
48 struct task_struct *tsk)
49{
50 if (!cpu_isset(smp_processor_id(), next->cpu_vm_mask))
51 cpu_set(smp_processor_id(), next->cpu_vm_mask);
52
53 /* No need to flush userspace segments if the mm doesnt change */
54#ifdef CONFIG_PPC_64K_PAGES
55 if (prev == next && get_paca()->pgdir == next->pgd)
56 return;
57#else
58 if (prev == next)
59 return;
60#endif /* CONFIG_PPC_64K_PAGES */
61
62#ifdef CONFIG_ALTIVEC
63 if (cpu_has_feature(CPU_FTR_ALTIVEC))
64 asm volatile ("dssall");
65#endif /* CONFIG_ALTIVEC */
66
67 if (cpu_has_feature(CPU_FTR_SLB))
68 switch_slb(tsk, next);
69 else
70 switch_stab(tsk, next);
71}
72
73#define deactivate_mm(tsk,mm) do { } while (0)
74
75/*
76 * After we have set current->mm to a new value, this activates
77 * the context for the new mm so we see the new mappings.
78 */
79static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
80{
81 unsigned long flags;
82
83 local_irq_save(flags);
84 switch_mm(prev, next, current);
85 local_irq_restore(flags);
86}
87
88#endif /* CONFIG_PPC64 */
89#endif /* __ASM_POWERPC_MMU_CONTEXT_H */
diff --git a/include/asm-powerpc/mmzone.h b/include/asm-powerpc/mmzone.h
new file mode 100644
index 000000000000..54958d6cae04
--- /dev/null
+++ b/include/asm-powerpc/mmzone.h
@@ -0,0 +1,50 @@
1/*
2 * Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99
3 *
4 * PowerPC64 port:
5 * Copyright (C) 2002 Anton Blanchard, IBM Corp.
6 */
7#ifndef _ASM_MMZONE_H_
8#define _ASM_MMZONE_H_
9
10#include <linux/config.h>
11
12/*
13 * generic non-linear memory support:
14 *
15 * 1) we will not split memory into more chunks than will fit into the
16 * flags field of the struct page
17 */
18
19#ifdef CONFIG_NEED_MULTIPLE_NODES
20
21extern struct pglist_data *node_data[];
22/*
23 * Return a pointer to the node data for node n.
24 */
25#define NODE_DATA(nid) (node_data[nid])
26
27/*
28 * Following are specific to this numa platform.
29 */
30
31extern int numa_cpu_lookup_table[];
32extern cpumask_t numa_cpumask_lookup_table[];
33#ifdef CONFIG_MEMORY_HOTPLUG
34extern unsigned long max_pfn;
35#endif
36
37/*
38 * Following are macros that each numa implmentation must define.
39 */
40
41#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
42#define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn)
43
44#endif /* CONFIG_NEED_MULTIPLE_NODES */
45
46#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
47extern int __init early_pfn_to_nid(unsigned long pfn);
48#endif
49
50#endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
new file mode 100644
index 000000000000..223ec7bd81da
--- /dev/null
+++ b/include/asm-powerpc/pci-bridge.h
@@ -0,0 +1,153 @@
1#ifndef _ASM_POWERPC_PCI_BRIDGE_H
2#define _ASM_POWERPC_PCI_BRIDGE_H
3
4#ifndef CONFIG_PPC64
5#include <asm-ppc/pci-bridge.h>
6#else
7
8#include <linux/pci.h>
9#include <linux/list.h>
10
11/*
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18/*
19 * Structure of a PCI controller (host bridge)
20 */
21struct pci_controller {
22 struct pci_bus *bus;
23 char is_dynamic;
24 void *arch_data;
25 struct list_head list_node;
26
27 int first_busno;
28 int last_busno;
29
30 void __iomem *io_base_virt;
31 unsigned long io_base_phys;
32
33 /* Some machines have a non 1:1 mapping of
34 * the PCI memory space in the CPU bus space
35 */
36 unsigned long pci_mem_offset;
37 unsigned long pci_io_size;
38
39 struct pci_ops *ops;
40 volatile unsigned int __iomem *cfg_addr;
41 volatile void __iomem *cfg_data;
42
43 /* Currently, we limit ourselves to 1 IO range and 3 mem
44 * ranges since the common pci_bus structure can't handle more
45 */
46 struct resource io_resource;
47 struct resource mem_resources[3];
48 int global_number;
49 int local_number;
50 unsigned long buid;
51 unsigned long dma_window_base_cur;
52 unsigned long dma_window_size;
53};
54
55/*
56 * PCI stuff, for nodes representing PCI devices, pointed to
57 * by device_node->data.
58 */
59struct pci_controller;
60struct iommu_table;
61
62struct pci_dn {
63 int busno; /* for pci devices */
64 int bussubno; /* for pci devices */
65 int devfn; /* for pci devices */
66
67#ifdef CONFIG_PPC_PSERIES
68 int eeh_mode; /* See eeh.h for possible EEH_MODEs */
69 int eeh_config_addr;
70 int eeh_check_count; /* # times driver ignored error */
71 int eeh_freeze_count; /* # times this device froze up. */
72 int eeh_is_bridge; /* device is pci-to-pci bridge */
73#endif
74 int pci_ext_config_space; /* for pci devices */
75 struct pci_controller *phb; /* for pci devices */
76 struct iommu_table *iommu_table; /* for phb's or bridges */
77 struct pci_dev *pcidev; /* back-pointer to the pci device */
78 struct device_node *node; /* back-pointer to the device_node */
79#ifdef CONFIG_PPC_ISERIES
80 struct list_head Device_List;
81 int Irq; /* Assigned IRQ */
82 int Flags; /* Possible flags(disable/bist)*/
83 u8 LogicalSlot; /* Hv Slot Index for Tces */
84#endif
85 u32 config_space[16]; /* saved PCI config space */
86};
87
88/* Get the pointer to a device_node's pci_dn */
89#define PCI_DN(dn) ((struct pci_dn *) (dn)->data)
90
91struct device_node *fetch_dev_dn(struct pci_dev *dev);
92
93/* Get a device_node from a pci_dev. This code must be fast except
94 * in the case where the sysdata is incorrect and needs to be fixed
95 * up (this will only happen once).
96 * In this case the sysdata will have been inherited from a PCI host
97 * bridge or a PCI-PCI bridge further up the tree, so it will point
98 * to a valid struct pci_dn, just not the one we want.
99 */
100static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
101{
102 struct device_node *dn = dev->sysdata;
103 struct pci_dn *pdn = dn->data;
104
105 if (pdn && pdn->devfn == dev->devfn && pdn->busno == dev->bus->number)
106 return dn; /* fast path. sysdata is good */
107 return fetch_dev_dn(dev);
108}
109
110static inline int pci_device_from_OF_node(struct device_node *np,
111 u8 *bus, u8 *devfn)
112{
113 if (!PCI_DN(np))
114 return -ENODEV;
115 *bus = PCI_DN(np)->busno;
116 *devfn = PCI_DN(np)->devfn;
117 return 0;
118}
119
120static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
121{
122 if (bus->self)
123 return pci_device_to_OF_node(bus->self);
124 else
125 return bus->sysdata; /* Must be root bus (PHB) */
126}
127
128extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
129 struct device_node *dev, int primary);
130
131extern int pcibios_remove_root_bus(struct pci_controller *phb);
132
133extern void phbs_remap_io(void);
134
135static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
136{
137 struct device_node *busdn = bus->sysdata;
138
139 BUG_ON(busdn == NULL);
140 return PCI_DN(busdn)->phb;
141}
142
143extern struct pci_controller *
144pcibios_alloc_controller(struct device_node *dev);
145extern void pcibios_free_controller(struct pci_controller *phb);
146
147/* Return values for ppc_md.pci_probe_mode function */
148#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */
149#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */
150#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */
151
152#endif /* CONFIG_PPC64 */
153#endif
diff --git a/include/asm-powerpc/pgalloc.h b/include/asm-powerpc/pgalloc.h
new file mode 100644
index 000000000000..bfc2113b3630
--- /dev/null
+++ b/include/asm-powerpc/pgalloc.h
@@ -0,0 +1,156 @@
1#ifndef _ASM_POWERPC_PGALLOC_H
2#define _ASM_POWERPC_PGALLOC_H
3
4#ifndef CONFIG_PPC64
5#include <asm-ppc/pgalloc.h>
6#else
7
8#include <linux/mm.h>
9#include <linux/slab.h>
10#include <linux/cpumask.h>
11#include <linux/percpu.h>
12
13extern kmem_cache_t *pgtable_cache[];
14
15#ifdef CONFIG_PPC_64K_PAGES
16#define PTE_CACHE_NUM 0
17#define PMD_CACHE_NUM 1
18#define PGD_CACHE_NUM 2
19#else
20#define PTE_CACHE_NUM 0
21#define PMD_CACHE_NUM 1
22#define PUD_CACHE_NUM 1
23#define PGD_CACHE_NUM 0
24#endif
25
26/*
27 * This program is free software; you can redistribute it and/or
28 * modify it under the terms of the GNU General Public License
29 * as published by the Free Software Foundation; either version
30 * 2 of the License, or (at your option) any later version.
31 */
32
33static inline pgd_t *pgd_alloc(struct mm_struct *mm)
34{
35 return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL);
36}
37
38static inline void pgd_free(pgd_t *pgd)
39{
40 kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd);
41}
42
43#ifndef CONFIG_PPC_64K_PAGES
44
45#define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD)
46
47static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
48{
49 return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM],
50 GFP_KERNEL|__GFP_REPEAT);
51}
52
53static inline void pud_free(pud_t *pud)
54{
55 kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud);
56}
57
58static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
59{
60 pud_set(pud, (unsigned long)pmd);
61}
62
63#define pmd_populate(mm, pmd, pte_page) \
64 pmd_populate_kernel(mm, pmd, page_address(pte_page))
65#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte))
66
67
68#else /* CONFIG_PPC_64K_PAGES */
69
70#define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd)
71
72static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
73 pte_t *pte)
74{
75 pmd_set(pmd, (unsigned long)pte);
76}
77
78#define pmd_populate(mm, pmd, pte_page) \
79 pmd_populate_kernel(mm, pmd, page_address(pte_page))
80
81#endif /* CONFIG_PPC_64K_PAGES */
82
83static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
84{
85 return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM],
86 GFP_KERNEL|__GFP_REPEAT);
87}
88
89static inline void pmd_free(pmd_t *pmd)
90{
91 kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd);
92}
93
94static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
95 unsigned long address)
96{
97 return kmem_cache_alloc(pgtable_cache[PTE_CACHE_NUM],
98 GFP_KERNEL|__GFP_REPEAT);
99}
100
101static inline struct page *pte_alloc_one(struct mm_struct *mm,
102 unsigned long address)
103{
104 return virt_to_page(pte_alloc_one_kernel(mm, address));
105}
106
107static inline void pte_free_kernel(pte_t *pte)
108{
109 kmem_cache_free(pgtable_cache[PTE_CACHE_NUM], pte);
110}
111
112static inline void pte_free(struct page *ptepage)
113{
114 pte_free_kernel(page_address(ptepage));
115}
116
117#define PGF_CACHENUM_MASK 0xf
118
119typedef struct pgtable_free {
120 unsigned long val;
121} pgtable_free_t;
122
123static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
124 unsigned long mask)
125{
126 BUG_ON(cachenum > PGF_CACHENUM_MASK);
127
128 return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum};
129}
130
131static inline void pgtable_free(pgtable_free_t pgf)
132{
133 void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
134 int cachenum = pgf.val & PGF_CACHENUM_MASK;
135
136 kmem_cache_free(pgtable_cache[cachenum], p);
137}
138
139extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
140
141#define __pte_free_tlb(tlb, ptepage) \
142 pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
143 PTE_CACHE_NUM, PTE_TABLE_SIZE-1))
144#define __pmd_free_tlb(tlb, pmd) \
145 pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
146 PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
147#ifndef CONFIG_PPC_64K_PAGES
148#define __pud_free_tlb(tlb, pmd) \
149 pgtable_free_tlb(tlb, pgtable_free_cache(pud, \
150 PUD_CACHE_NUM, PUD_TABLE_SIZE-1))
151#endif /* CONFIG_PPC_64K_PAGES */
152
153#define check_pgt_cache() do { } while (0)
154
155#endif /* CONFIG_PPC64 */
156#endif /* _ASM_POWERPC_PGALLOC_H */
diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h
new file mode 100644
index 000000000000..e9590c06ad92
--- /dev/null
+++ b/include/asm-powerpc/pgtable-4k.h
@@ -0,0 +1,91 @@
1/*
2 * Entries per page directory level. The PTE level must use a 64b record
3 * for each page table entry. The PMD and PGD level use a 32b record for
4 * each entry by assuming that each entry is page aligned.
5 */
6#define PTE_INDEX_SIZE 9
7#define PMD_INDEX_SIZE 7
8#define PUD_INDEX_SIZE 7
9#define PGD_INDEX_SIZE 9
10
11#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE)
12#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE)
13#define PUD_TABLE_SIZE (sizeof(pud_t) << PUD_INDEX_SIZE)
14#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE)
15
16#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE)
17#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE)
18#define PTRS_PER_PUD (1 << PMD_INDEX_SIZE)
19#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
20
21/* PMD_SHIFT determines what a second-level page table entry can map */
22#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE)
23#define PMD_SIZE (1UL << PMD_SHIFT)
24#define PMD_MASK (~(PMD_SIZE-1))
25
26/* With 4k base page size, hugepage PTEs go at the PMD level */
27#define MIN_HUGEPTE_SHIFT PMD_SHIFT
28
29/* PUD_SHIFT determines what a third-level page table entry can map */
30#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE)
31#define PUD_SIZE (1UL << PUD_SHIFT)
32#define PUD_MASK (~(PUD_SIZE-1))
33
34/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
35#define PGDIR_SHIFT (PUD_SHIFT + PUD_INDEX_SIZE)
36#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
37#define PGDIR_MASK (~(PGDIR_SIZE-1))
38
39/* PTE bits */
40#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */
41#define _PAGE_GROUP_IX 0x7000 /* software: HPTE index within group */
42#define _PAGE_F_SECOND _PAGE_SECONDARY
43#define _PAGE_F_GIX _PAGE_GROUP_IX
44
45/* PTE flags to conserve for HPTE identification */
46#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | \
47 _PAGE_SECONDARY | _PAGE_GROUP_IX)
48
49/* PAGE_MASK gives the right answer below, but only by accident */
50/* It should be preserving the high 48 bits and then specifically */
51/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
52#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
53 _PAGE_HPTEFLAGS)
54
55/* Bits to mask out from a PMD to get to the PTE page */
56#define PMD_MASKED_BITS 0
57/* Bits to mask out from a PUD to get to the PMD page */
58#define PUD_MASKED_BITS 0
59/* Bits to mask out from a PGD to get to the PUD page */
60#define PGD_MASKED_BITS 0
61
62/* shift to put page number into pte */
63#define PTE_RPN_SHIFT (17)
64
65#define __real_pte(e,p) ((real_pte_t)(e))
66#define __rpte_to_pte(r) (r)
67#define __rpte_to_hidx(r,index) (pte_val((r)) >> 12)
68
69#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \
70 do { \
71 index = 0; \
72 shift = mmu_psize_defs[psize].shift; \
73
74#define pte_iterate_hashed_end() } while(0)
75
76/*
77 * 4-level page tables related bits
78 */
79
80#define pgd_none(pgd) (!pgd_val(pgd))
81#define pgd_bad(pgd) (pgd_val(pgd) == 0)
82#define pgd_present(pgd) (pgd_val(pgd) != 0)
83#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0)
84#define pgd_page(pgd) (pgd_val(pgd) & ~PGD_MASKED_BITS)
85
86#define pud_offset(pgdp, addr) \
87 (((pud_t *) pgd_page(*(pgdp))) + \
88 (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)))
89
90#define pud_ERROR(e) \
91 printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pud_val(e))
diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h
new file mode 100644
index 000000000000..154f1840ece4
--- /dev/null
+++ b/include/asm-powerpc/pgtable-64k.h
@@ -0,0 +1,90 @@
1#include <asm-generic/pgtable-nopud.h>
2
3
4#define PTE_INDEX_SIZE 12
5#define PMD_INDEX_SIZE 12
6#define PUD_INDEX_SIZE 0
7#define PGD_INDEX_SIZE 4
8
9#define PTE_TABLE_SIZE (sizeof(real_pte_t) << PTE_INDEX_SIZE)
10#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE)
11#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE)
12
13#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE)
14#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE)
15#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
16
17/* With 4k base page size, hugepage PTEs go at the PMD level */
18#define MIN_HUGEPTE_SHIFT PAGE_SHIFT
19
20/* PMD_SHIFT determines what a second-level page table entry can map */
21#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE)
22#define PMD_SIZE (1UL << PMD_SHIFT)
23#define PMD_MASK (~(PMD_SIZE-1))
24
25/* PGDIR_SHIFT determines what a third-level page table entry can map */
26#define PGDIR_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE)
27#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
28#define PGDIR_MASK (~(PGDIR_SIZE-1))
29
30/* Additional PTE bits (don't change without checking asm in hash_low.S) */
31#define _PAGE_HPTE_SUB 0x0ffff000 /* combo only: sub pages HPTE bits */
32#define _PAGE_HPTE_SUB0 0x08000000 /* combo only: first sub page */
33#define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */
34#define _PAGE_F_SECOND 0x00008000 /* full page: hidx bits */
35#define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */
36
37/* PTE flags to conserve for HPTE identification */
38#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_HPTE_SUB |\
39 _PAGE_COMBO)
40
41/* Shift to put page number into pte.
42 *
43 * That gives us a max RPN of 32 bits, which means a max of 48 bits
44 * of addressable physical space.
45 * We could get 3 more bits here by setting PTE_RPN_SHIFT to 29 but
46 * 32 makes PTEs more readable for debugging for now :)
47 */
48#define PTE_RPN_SHIFT (32)
49#define PTE_RPN_MAX (1UL << (64 - PTE_RPN_SHIFT))
50#define PTE_RPN_MASK (~((1UL<<PTE_RPN_SHIFT)-1))
51
52/* _PAGE_CHG_MASK masks of bits that are to be preserved accross
53 * pgprot changes
54 */
55#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
56 _PAGE_ACCESSED)
57
58/* Bits to mask out from a PMD to get to the PTE page */
59#define PMD_MASKED_BITS 0x1ff
60/* Bits to mask out from a PGD/PUD to get to the PMD page */
61#define PUD_MASKED_BITS 0x1ff
62
63#ifndef __ASSEMBLY__
64
65/* Manipulate "rpte" values */
66#define __real_pte(e,p) ((real_pte_t) { \
67 (e), pte_val(*((p) + PTRS_PER_PTE)) })
68#define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \
69 (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf))
70#define __rpte_to_pte(r) ((r).pte)
71#define __rpte_sub_valid(rpte, index) \
72 (pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index)))
73
74
75/* Trick: we set __end to va + 64k, which happens works for
76 * a 16M page as well as we want only one iteration
77 */
78#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \
79 do { \
80 unsigned long __end = va + PAGE_SIZE; \
81 unsigned __split = (psize == MMU_PAGE_4K || \
82 psize == MMU_PAGE_64K_AP); \
83 shift = mmu_psize_defs[psize].shift; \
84 for (index = 0; va < __end; index++, va += (1 << shift)) { \
85 if (!__split || __rpte_sub_valid(rpte, index)) do { \
86
87#define pte_iterate_hashed_end() } while(0); } } while(0)
88
89
90#endif /* __ASSEMBLY__ */
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h
new file mode 100644
index 000000000000..0303f57366c1
--- /dev/null
+++ b/include/asm-powerpc/pgtable.h
@@ -0,0 +1,524 @@
1#ifndef _ASM_POWERPC_PGTABLE_H
2#define _ASM_POWERPC_PGTABLE_H
3
4#ifndef CONFIG_PPC64
5#include <asm-ppc/pgtable.h>
6#else
7
8/*
9 * This file contains the functions and defines necessary to modify and use
10 * the ppc64 hashed page table.
11 */
12
13#ifndef __ASSEMBLY__
14#include <linux/config.h>
15#include <linux/stddef.h>
16#include <asm/processor.h> /* For TASK_SIZE */
17#include <asm/mmu.h>
18#include <asm/page.h>
19#include <asm/tlbflush.h>
20struct mm_struct;
21#endif /* __ASSEMBLY__ */
22
23#ifdef CONFIG_PPC_64K_PAGES
24#include <asm/pgtable-64k.h>
25#else
26#include <asm/pgtable-4k.h>
27#endif
28
29#define FIRST_USER_ADDRESS 0
30
31/*
32 * Size of EA range mapped by our pagetables.
33 */
34#define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
35 PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
36#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE)
37
38#if TASK_SIZE_USER64 > PGTABLE_RANGE
39#error TASK_SIZE_USER64 exceeds pagetable range
40#endif
41
42#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
43#error TASK_SIZE_USER64 exceeds user VSID range
44#endif
45
46/*
47 * Define the address range of the vmalloc VM area.
48 */
49#define VMALLOC_START (0xD000000000000000ul)
50#define VMALLOC_SIZE (0x80000000000UL)
51#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
52
53/*
54 * Define the address range of the imalloc VM area.
55 */
56#define PHBS_IO_BASE VMALLOC_END
57#define IMALLOC_BASE (PHBS_IO_BASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */
58#define IMALLOC_END (VMALLOC_START + PGTABLE_RANGE)
59
60/*
61 * Common bits in a linux-style PTE. These match the bits in the
62 * (hardware-defined) PowerPC PTE as closely as possible. Additional
63 * bits may be defined in pgtable-*.h
64 */
65#define _PAGE_PRESENT 0x0001 /* software: pte contains a translation */
66#define _PAGE_USER 0x0002 /* matches one of the PP bits */
67#define _PAGE_FILE 0x0002 /* (!present only) software: pte holds file offset */
68#define _PAGE_EXEC 0x0004 /* No execute on POWER4 and newer (we invert) */
69#define _PAGE_GUARDED 0x0008
70#define _PAGE_COHERENT 0x0010 /* M: enforce memory coherence (SMP systems) */
71#define _PAGE_NO_CACHE 0x0020 /* I: cache inhibit */
72#define _PAGE_WRITETHRU 0x0040 /* W: cache write-through */
73#define _PAGE_DIRTY 0x0080 /* C: page changed */
74#define _PAGE_ACCESSED 0x0100 /* R: page referenced */
75#define _PAGE_RW 0x0200 /* software: user write access allowed */
76#define _PAGE_HASHPTE 0x0400 /* software: pte has an associated HPTE */
77#define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */
78
79#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
80
81#define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY)
82
83/* __pgprot defined in asm-powerpc/page.h */
84#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
85
86#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER)
87#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER | _PAGE_EXEC)
88#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
89#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
90#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
91#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
92#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_WRENABLE)
93#define PAGE_KERNEL_CI __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
94 _PAGE_WRENABLE | _PAGE_NO_CACHE | _PAGE_GUARDED)
95#define PAGE_KERNEL_EXEC __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_EXEC)
96
97#define PAGE_AGP __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE)
98#define HAVE_PAGE_AGP
99
100/* PTEIDX nibble */
101#define _PTEIDX_SECONDARY 0x8
102#define _PTEIDX_GROUP_IX 0x7
103
104
105/*
106 * POWER4 and newer have per page execute protection, older chips can only
107 * do this on a segment (256MB) basis.
108 *
109 * Also, write permissions imply read permissions.
110 * This is the closest we can get..
111 *
112 * Note due to the way vm flags are laid out, the bits are XWR
113 */
114#define __P000 PAGE_NONE
115#define __P001 PAGE_READONLY
116#define __P010 PAGE_COPY
117#define __P011 PAGE_COPY
118#define __P100 PAGE_READONLY_X
119#define __P101 PAGE_READONLY_X
120#define __P110 PAGE_COPY_X
121#define __P111 PAGE_COPY_X
122
123#define __S000 PAGE_NONE
124#define __S001 PAGE_READONLY
125#define __S010 PAGE_SHARED
126#define __S011 PAGE_SHARED
127#define __S100 PAGE_READONLY_X
128#define __S101 PAGE_READONLY_X
129#define __S110 PAGE_SHARED_X
130#define __S111 PAGE_SHARED_X
131
132#ifndef __ASSEMBLY__
133
134/*
135 * ZERO_PAGE is a global shared page that is always zero: used
136 * for zero-mapped memory areas etc..
137 */
138extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
139#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
140#endif /* __ASSEMBLY__ */
141
142#ifdef CONFIG_HUGETLB_PAGE
143
144#define HAVE_ARCH_UNMAPPED_AREA
145#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
146
147#endif
148
149#ifndef __ASSEMBLY__
150
151/*
152 * Conversion functions: convert a page and protection to a page entry,
153 * and a page entry and page directory to the page they refer to.
154 *
155 * mk_pte takes a (struct page *) as input
156 */
157#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
158
159static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
160{
161 pte_t pte;
162
163
164 pte_val(pte) = (pfn << PTE_RPN_SHIFT) | pgprot_val(pgprot);
165 return pte;
166}
167
168#define pte_modify(_pte, newprot) \
169 (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
170
171#define pte_none(pte) ((pte_val(pte) & ~_PAGE_HPTEFLAGS) == 0)
172#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
173
174/* pte_clear moved to later in this file */
175
176#define pte_pfn(x) ((unsigned long)((pte_val(x)>>PTE_RPN_SHIFT)))
177#define pte_page(x) pfn_to_page(pte_pfn(x))
178
179#define pmd_set(pmdp, pmdval) (pmd_val(*(pmdp)) = (pmdval))
180#define pmd_none(pmd) (!pmd_val(pmd))
181#define pmd_bad(pmd) (pmd_val(pmd) == 0)
182#define pmd_present(pmd) (pmd_val(pmd) != 0)
183#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0)
184#define pmd_page_kernel(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS)
185#define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd))
186
187#define pud_set(pudp, pudval) (pud_val(*(pudp)) = (pudval))
188#define pud_none(pud) (!pud_val(pud))
189#define pud_bad(pud) ((pud_val(pud)) == 0)
190#define pud_present(pud) (pud_val(pud) != 0)
191#define pud_clear(pudp) (pud_val(*(pudp)) = 0)
192#define pud_page(pud) (pud_val(pud) & ~PUD_MASKED_BITS)
193
194#define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
195
196/*
197 * Find an entry in a page-table-directory. We combine the address region
198 * (the high order N bits) and the pgd portion of the address.
199 */
200/* to avoid overflow in free_pgtables we don't use PTRS_PER_PGD here */
201#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & 0x1ff)
202
203#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
204
205#define pmd_offset(pudp,addr) \
206 (((pmd_t *) pud_page(*(pudp))) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
207
208#define pte_offset_kernel(dir,addr) \
209 (((pte_t *) pmd_page_kernel(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
210
211#define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr))
212#define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr))
213#define pte_unmap(pte) do { } while(0)
214#define pte_unmap_nested(pte) do { } while(0)
215
216/* to find an entry in a kernel page-table-directory */
217/* This now only contains the vmalloc pages */
218#define pgd_offset_k(address) pgd_offset(&init_mm, address)
219
220/*
221 * The following only work if pte_present() is true.
222 * Undefined behaviour if not..
223 */
224static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER;}
225static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
226static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC;}
227static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
228static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
229static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
230
231static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
232static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
233
234static inline pte_t pte_rdprotect(pte_t pte) {
235 pte_val(pte) &= ~_PAGE_USER; return pte; }
236static inline pte_t pte_exprotect(pte_t pte) {
237 pte_val(pte) &= ~_PAGE_EXEC; return pte; }
238static inline pte_t pte_wrprotect(pte_t pte) {
239 pte_val(pte) &= ~(_PAGE_RW); return pte; }
240static inline pte_t pte_mkclean(pte_t pte) {
241 pte_val(pte) &= ~(_PAGE_DIRTY); return pte; }
242static inline pte_t pte_mkold(pte_t pte) {
243 pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
244static inline pte_t pte_mkread(pte_t pte) {
245 pte_val(pte) |= _PAGE_USER; return pte; }
246static inline pte_t pte_mkexec(pte_t pte) {
247 pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
248static inline pte_t pte_mkwrite(pte_t pte) {
249 pte_val(pte) |= _PAGE_RW; return pte; }
250static inline pte_t pte_mkdirty(pte_t pte) {
251 pte_val(pte) |= _PAGE_DIRTY; return pte; }
252static inline pte_t pte_mkyoung(pte_t pte) {
253 pte_val(pte) |= _PAGE_ACCESSED; return pte; }
254static inline pte_t pte_mkhuge(pte_t pte) {
255 return pte; }
256
257/* Atomic PTE updates */
258static inline unsigned long pte_update(pte_t *p, unsigned long clr)
259{
260 unsigned long old, tmp;
261
262 __asm__ __volatile__(
263 "1: ldarx %0,0,%3 # pte_update\n\
264 andi. %1,%0,%6\n\
265 bne- 1b \n\
266 andc %1,%0,%4 \n\
267 stdcx. %1,0,%3 \n\
268 bne- 1b"
269 : "=&r" (old), "=&r" (tmp), "=m" (*p)
270 : "r" (p), "r" (clr), "m" (*p), "i" (_PAGE_BUSY)
271 : "cc" );
272 return old;
273}
274
275/* PTE updating functions, this function puts the PTE in the
276 * batch, doesn't actually triggers the hash flush immediately,
277 * you need to call flush_tlb_pending() to do that.
278 * Pass -1 for "normal" size (4K or 64K)
279 */
280extern void hpte_update(struct mm_struct *mm, unsigned long addr,
281 pte_t *ptep, unsigned long pte, int huge);
282
283static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
284 unsigned long addr, pte_t *ptep)
285{
286 unsigned long old;
287
288 if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
289 return 0;
290 old = pte_update(ptep, _PAGE_ACCESSED);
291 if (old & _PAGE_HASHPTE) {
292 hpte_update(mm, addr, ptep, old, 0);
293 flush_tlb_pending();
294 }
295 return (old & _PAGE_ACCESSED) != 0;
296}
297#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
298#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
299({ \
300 int __r; \
301 __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
302 __r; \
303})
304
305/*
306 * On RW/DIRTY bit transitions we can avoid flushing the hpte. For the
307 * moment we always flush but we need to fix hpte_update and test if the
308 * optimisation is worth it.
309 */
310static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm,
311 unsigned long addr, pte_t *ptep)
312{
313 unsigned long old;
314
315 if ((pte_val(*ptep) & _PAGE_DIRTY) == 0)
316 return 0;
317 old = pte_update(ptep, _PAGE_DIRTY);
318 if (old & _PAGE_HASHPTE)
319 hpte_update(mm, addr, ptep, old, 0);
320 return (old & _PAGE_DIRTY) != 0;
321}
322#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
323#define ptep_test_and_clear_dirty(__vma, __addr, __ptep) \
324({ \
325 int __r; \
326 __r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \
327 __r; \
328})
329
330#define __HAVE_ARCH_PTEP_SET_WRPROTECT
331static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
332 pte_t *ptep)
333{
334 unsigned long old;
335
336 if ((pte_val(*ptep) & _PAGE_RW) == 0)
337 return;
338 old = pte_update(ptep, _PAGE_RW);
339 if (old & _PAGE_HASHPTE)
340 hpte_update(mm, addr, ptep, old, 0);
341}
342
343/*
344 * We currently remove entries from the hashtable regardless of whether
345 * the entry was young or dirty. The generic routines only flush if the
346 * entry was young or dirty which is not good enough.
347 *
348 * We should be more intelligent about this but for the moment we override
349 * these functions and force a tlb flush unconditionally
350 */
351#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
352#define ptep_clear_flush_young(__vma, __address, __ptep) \
353({ \
354 int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \
355 __ptep); \
356 __young; \
357})
358
359#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
360#define ptep_clear_flush_dirty(__vma, __address, __ptep) \
361({ \
362 int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \
363 __ptep); \
364 flush_tlb_page(__vma, __address); \
365 __dirty; \
366})
367
368#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
369static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
370 unsigned long addr, pte_t *ptep)
371{
372 unsigned long old = pte_update(ptep, ~0UL);
373
374 if (old & _PAGE_HASHPTE)
375 hpte_update(mm, addr, ptep, old, 0);
376 return __pte(old);
377}
378
379static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
380 pte_t * ptep)
381{
382 unsigned long old = pte_update(ptep, ~0UL);
383
384 if (old & _PAGE_HASHPTE)
385 hpte_update(mm, addr, ptep, old, 0);
386}
387
388/*
389 * set_pte stores a linux PTE into the linux page table.
390 */
391static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
392 pte_t *ptep, pte_t pte)
393{
394 if (pte_present(*ptep)) {
395 pte_clear(mm, addr, ptep);
396 flush_tlb_pending();
397 }
398 pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
399
400#ifdef CONFIG_PPC_64K_PAGES
401 if (mmu_virtual_psize != MMU_PAGE_64K)
402 pte = __pte(pte_val(pte) | _PAGE_COMBO);
403#endif /* CONFIG_PPC_64K_PAGES */
404
405 *ptep = pte;
406}
407
408/* Set the dirty and/or accessed bits atomically in a linux PTE, this
409 * function doesn't need to flush the hash entry
410 */
411#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
412static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
413{
414 unsigned long bits = pte_val(entry) &
415 (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
416 unsigned long old, tmp;
417
418 __asm__ __volatile__(
419 "1: ldarx %0,0,%4\n\
420 andi. %1,%0,%6\n\
421 bne- 1b \n\
422 or %0,%3,%0\n\
423 stdcx. %0,0,%4\n\
424 bne- 1b"
425 :"=&r" (old), "=&r" (tmp), "=m" (*ptep)
426 :"r" (bits), "r" (ptep), "m" (*ptep), "i" (_PAGE_BUSY)
427 :"cc");
428}
429#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
430 do { \
431 __ptep_set_access_flags(__ptep, __entry, __dirty); \
432 flush_tlb_page_nohash(__vma, __address); \
433 } while(0)
434
435/*
436 * Macro to mark a page protection value as "uncacheable".
437 */
438#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
439
440struct file;
441extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
442 unsigned long size, pgprot_t vma_prot);
443#define __HAVE_PHYS_MEM_ACCESS_PROT
444
445#define __HAVE_ARCH_PTE_SAME
446#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
447
448#define pte_ERROR(e) \
449 printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
450#define pmd_ERROR(e) \
451 printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
452#define pgd_ERROR(e) \
453 printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
454
455extern pgd_t swapper_pg_dir[];
456
457extern void paging_init(void);
458
459#ifdef CONFIG_HUGETLB_PAGE
460#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \
461 free_pgd_range(tlb, addr, end, floor, ceiling)
462#endif
463
464/*
465 * This gets called at the end of handling a page fault, when
466 * the kernel has put a new PTE into the page table for the process.
467 * We use it to put a corresponding HPTE into the hash table
468 * ahead of time, instead of waiting for the inevitable extra
469 * hash-table miss exception.
470 */
471struct vm_area_struct;
472extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
473
474/* Encode and de-code a swap entry */
475#define __swp_type(entry) (((entry).val >> 1) & 0x3f)
476#define __swp_offset(entry) ((entry).val >> 8)
477#define __swp_entry(type, offset) ((swp_entry_t){((type)<< 1)|((offset)<<8)})
478#define __pte_to_swp_entry(pte) ((swp_entry_t){pte_val(pte) >> PTE_RPN_SHIFT})
479#define __swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_RPN_SHIFT })
480#define pte_to_pgoff(pte) (pte_val(pte) >> PTE_RPN_SHIFT)
481#define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE})
482#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT)
483
484/*
485 * kern_addr_valid is intended to indicate whether an address is a valid
486 * kernel address. Most 32-bit archs define it as always true (like this)
487 * but most 64-bit archs actually perform a test. What should we do here?
488 * The only use is in fs/ncpfs/dir.c
489 */
490#define kern_addr_valid(addr) (1)
491
492#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
493 remap_pfn_range(vma, vaddr, pfn, size, prot)
494
495void pgtable_cache_init(void);
496
497/*
498 * find_linux_pte returns the address of a linux pte for a given
499 * effective address and directory. If not found, it returns zero.
500 */static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
501{
502 pgd_t *pg;
503 pud_t *pu;
504 pmd_t *pm;
505 pte_t *pt = NULL;
506
507 pg = pgdir + pgd_index(ea);
508 if (!pgd_none(*pg)) {
509 pu = pud_offset(pg, ea);
510 if (!pud_none(*pu)) {
511 pm = pmd_offset(pu, ea);
512 if (pmd_present(*pm))
513 pt = pte_offset_kernel(pm, ea);
514 }
515 }
516 return pt;
517}
518
519#include <asm-generic/pgtable.h>
520
521#endif /* __ASSEMBLY__ */
522
523#endif /* CONFIG_PPC64 */
524#endif /* _ASM_POWERPC_PGTABLE_H */