1 #ifndef _PPC64_PAGE_H
2 #define _PPC64_PAGE_H
3 
4 /*
5  * Copyright (C) 2001 PPC64 Team, IBM Corp
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version
10  * 2 of the License, or (at your option) any later version.
11  */
12 
13 #include <linux/config.h>
14 
15 /* PAGE_SHIFT determines the page size */
16 #define PAGE_SHIFT	12
17 #ifndef __ASSEMBLY__
18 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
19 #else
20 # define PAGE_SIZE	(1 << PAGE_SHIFT)
21 #endif
22 #define PAGE_MASK	(~(PAGE_SIZE-1))
23 #define PAGE_OFFSET_MASK (PAGE_SIZE-1)
24 
25 #define SID_SHIFT       28
26 #define SID_MASK        0xfffffffff
27 #define GET_ESID(x)     (((x) >> SID_SHIFT) & SID_MASK)
28 
29 /* Define an illegal instr to trap on the bug.
30  * We don't use 0 because that marks the end of a function
31  * in the ELF ABI.  That's "Boo Boo" in case you wonder...
32  */
33 #define BUG_OPCODE .long 0x00b00b00  /* For asm */
34 #define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */
35 
36 #ifdef __KERNEL__
37 #ifndef __ASSEMBLY__
38 #include <asm/naca.h>
39 #include <asm/systemcfg.h>
40 
41 #define STRICT_MM_TYPECHECKS
42 
43 #define REGION_SIZE   4UL
44 #define OFFSET_SIZE   60UL
45 #define REGION_SHIFT  60UL
46 #define OFFSET_SHIFT  0UL
47 #define REGION_MASK   (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT)
48 #define REGION_STRIDE (1UL << REGION_SHIFT)
49 
50 #ifdef ___powerpc64__
51 typedef union ppc64_va {
52         struct {
53                 unsigned long off : OFFSET_SIZE;  /* intra-region offset */
54                 unsigned long reg : REGION_SIZE;  /* region number */
55         } f;
56         unsigned long l;
57         void *p;
58 } ppc64_va;
59 #endif /* ___powerpc64__ */
60 
clear_page(void * addr)61 static __inline__ void clear_page(void *addr)
62 {
63 	unsigned long lines, line_size;
64 
65 	line_size = systemcfg->dCacheL1LineSize;
66 	lines = naca->dCacheL1LinesPerPage;
67 
68 	__asm__ __volatile__(
69 "  	mtctr  	%1\n\
70 1:      dcbz  	0,%0\n\
71 	add	%0,%0,%3\n\
72 	bdnz+	1b"
73         : "=r" (addr)
74         : "r" (lines), "0" (addr), "r" (line_size)
75 	: "ctr", "memory");
76 }
77 
78 extern void copy_page(void *to, void *from);
79 struct page;
80 extern void clear_user_page(void *page, unsigned long vaddr);
81 extern void copy_user_page(void *to, void *from, unsigned long vaddr);
82 
83 #ifdef STRICT_MM_TYPECHECKS
84 /*
85  * These are used to make use of C type-checking.
86  * Entries in the pte table are 64b, while entries in the pgd & pmd are 32b.
87  */
88 typedef struct { unsigned long pte; } pte_t;
89 typedef struct { unsigned int  pmd; } pmd_t;
90 typedef struct { unsigned int  pgd; } pgd_t;
91 typedef struct { unsigned long pgprot; } pgprot_t;
92 
93 #define pte_val(x)	((x).pte)
94 #define pmd_val(x)	((x).pmd)
95 #define pgd_val(x)	((x).pgd)
96 #define pgprot_val(x)	((x).pgprot)
97 
98 #define __pte(x)	((pte_t) { (x) } )
99 #define __pmd(x)	((pmd_t) { (x) } )
100 #define __pgd(x)	((pgd_t) { (x) } )
101 #define __pgprot(x)	((pgprot_t) { (x) } )
102 
103 #else
104 /*
105  * .. while these make it easier on the compiler
106  */
107 typedef unsigned long pte_t;
108 typedef unsigned int  pmd_t;
109 typedef unsigned int  pgd_t;
110 typedef unsigned long pgprot_t;
111 
112 #define pte_val(x)	(x)
113 #define pmd_val(x)	(x)
114 #define pgd_val(x)	(x)
115 #define pgprot_val(x)	(x)
116 
117 #define __pte(x)	(x)
118 #define __pmd(x)	(x)
119 #define __pgd(x)	(x)
120 #define __pgprot(x)	(x)
121 
122 #endif
123 
124 #ifdef CONFIG_XMON
125 #include <asm/ptrace.h>
126 extern void xmon(struct pt_regs *excp);
127 #define BUG() do { \
128 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
129 	xmon(0); \
130 } while (0)
131 #else
132 #define BUG() do { \
133 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
134 	__asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
135 } while (0)
136 #endif
137 
138 #define PAGE_BUG(page) do { BUG(); } while (0)
139 
140 /* Pure 2^n version of get_order */
get_order(unsigned long size)141 static inline int get_order(unsigned long size)
142 {
143 	int order;
144 
145 	size = (size-1) >> (PAGE_SHIFT-1);
146 	order = -1;
147 	do {
148 		size >>= 1;
149 		order++;
150 	} while (size);
151 	return order;
152 }
153 
154 #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
155 
156 #endif /* __ASSEMBLY__ */
157 
158 /* align addr on a size boundry - adjust address up/down if needed */
159 #define _ALIGN_UP(addr,size)	(((addr)+((size)-1))&(~((size)-1)))
160 #define _ALIGN_DOWN(addr,size)	((addr)&(~((size)-1)))
161 
162 /* align addr on a size boundry - adjust address up if needed */
163 #define _ALIGN(addr,size)     _ALIGN_UP(addr,size)
164 
165 /* to align the pointer to the (next) double word boundary */
166 #define DOUBLEWORD_ALIGN(addr)	_ALIGN(addr,sizeof(unsigned long))
167 
168 /* to align the pointer to the (next) page boundary */
169 #define PAGE_ALIGN(addr)	_ALIGN(addr, PAGE_SIZE)
170 
171 #ifdef MODULE
172 #define __page_aligned __attribute__((__aligned__(PAGE_SIZE)))
173 #else
174 #define __page_aligned \
175 	__attribute__((__aligned__(PAGE_SIZE), \
176 		__section__(".data.page_aligned")))
177 #endif
178 
179 
180 /* This must match the -Ttext linker address            */
181 /* Note: tophys & tovirt make assumptions about how     */
182 /*       KERNELBASE is defined for performance reasons. */
183 /*       When KERNELBASE moves, those macros may have   */
184 /*             to change!                               */
185 #define PAGE_OFFSET     0xC000000000000000
186 #define KERNELBASE      PAGE_OFFSET
187 #define VMALLOCBASE     0xD000000000000000
188 #define IOREGIONBASE    0xE000000000000000
189 #define EEHREGIONBASE   0xA000000000000000
190 #define BOLTEDBASE      0xB000000000000000
191 
192 #define IO_REGION_ID       (IOREGIONBASE>>REGION_SHIFT)
193 #define EEH_REGION_ID      (EEHREGIONBASE>>REGION_SHIFT)
194 #define VMALLOC_REGION_ID  (VMALLOCBASE>>REGION_SHIFT)
195 #define KERNEL_REGION_ID   (KERNELBASE>>REGION_SHIFT)
196 #define BOLTED_REGION_ID   (BOLTEDBASE>>REGION_SHIFT)
197 #define USER_REGION_ID     (0UL)
198 #define REGION_ID(X)	   (((unsigned long)(X))>>REGION_SHIFT)
199 
200 /*
201  * Define valid/invalid EA bits (for all ranges)
202  */
203 #define VALID_EA_BITS   (0x000001ffffffffffUL)
204 #define INVALID_EA_BITS (~(REGION_MASK|VALID_EA_BITS))
205 
206 #define IS_VALID_REGION_ID(x) \
207         (((x) == USER_REGION_ID) || ((x) >= BOLTED_REGION_ID))
208 #define IS_VALID_EA(x) \
209         ((!((x) & INVALID_EA_BITS)) && IS_VALID_REGION_ID(REGION_ID(x)))
210 
211 #define __bpn_to_ba(x) ((((unsigned long)(x))<<PAGE_SHIFT) + KERNELBASE)
212 #define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT)
213 
214 #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE))
215 
216 /* Given that physical addresses do not map 1-1 to absolute addresses, we
217  * use these macros to better specify exactly what we want to do.
218  * The only restriction on their use is that the absolute address
219  * macros cannot be used until after the LMB structure has been
220  * initialized in prom.c.  -Peter
221  */
222 #define __v2p(x) ((void *) __pa(x))
223 #define __v2a(x) ((void *) phys_to_absolute(__pa(x)))
224 #define __p2a(x) ((void *) phys_to_absolute(x))
225 #define __p2v(x) ((void *) __va(x))
226 #define __a2p(x) ((void *) absolute_to_phys(x))
227 #define __a2v(x) ((void *) __va(absolute_to_phys(x)))
228 
229 #define virt_to_page(kaddr) (mem_map+(__pa((unsigned long)kaddr) >> PAGE_SHIFT))
230 
231 #define VALID_PAGE(page)    ((page - mem_map) < max_mapnr)
232 
233 #define MAP_NR(addr)        (__pa(addr) >> PAGE_SHIFT)
234 
235 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
236 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
237 
238 #endif /* __KERNEL__ */
239 #endif /* _PPC64_PAGE_H */
240