1 /* $Id: page.h,v 1.22 1995/11/25 02:32:16 davem Exp $
2 * page.h: Various defines and such for MMU operations on the Sparc for
3 * the Linux kernel.
4 *
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8 #ifndef _SPARC_PAGE_H
9 #define _SPARC_PAGE_H
10
11 #include <asm/asi.h> /* for get/set segmap/pte routines */
12 #include <asm/contregs.h> /* for switch_to_context */
13 #include <asm/head.h> /* for KERNBASE */
14
15 #define PAGE_SHIFT 12 /* This is the virtual page... */
16 #define PAGE_OFFSET KERNBASE
17 #define PAGE_SIZE (1 << PAGE_SHIFT)
18
19 /* to mask away the intra-page address bits */
20 #define PAGE_MASK (~(PAGE_SIZE-1))
21
22 #ifdef __KERNEL__
23 #ifndef __ASSEMBLY__
24
25 #include <asm/processor.h>
26
27 /* The following structure is used to hold the physical
28 * memory configuration of the machine. This is filled in
29 * probe_memory() and is later used by mem_init() to set up
30 * mem_map[]. We statically allocate SPARC_PHYS_BANKS of
31 * these structs, this is arbitrary. The entry after the
32 * last valid one has num_bytes==0.
33 */
34
35 struct sparc_phys_banks {
36 unsigned long base_addr;
37 unsigned long num_bytes;
38 };
39
40 #define SPARC_PHYS_BANKS 32
41
42 extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
43
44 #define STRICT_MM_TYPECHECKS
45
46 #ifdef STRICT_MM_TYPECHECKS
47 /*
48 * These are used to make use of C type-checking..
49 */
50 typedef struct { unsigned long pte; } pte_t;
51 typedef struct { unsigned long pmd; } pmd_t;
52 typedef struct { unsigned long pgd; } pgd_t;
53 typedef struct { unsigned long pgprot; } pgprot_t;
54
55 #define pte_val(x) ((x).pte)
56 #define pmd_val(x) ((x).pmd)
57 #define pgd_val(x) ((x).pgd)
58 #define pgprot_val(x) ((x).pgprot)
59
60 #define __pte(x) ((pte_t) { (x) } )
61 #define __pmd(x) ((pmd_t) { (x) } )
62 #define __pgd(x) ((pgd_t) { (x) } )
63 #define __pgprot(x) ((pgprot_t) { (x) } )
64
65 #else
66 /*
67 * .. while these make it easier on the compiler
68 */
69 typedef unsigned long pte_t;
70 typedef unsigned long pmd_t;
71 typedef unsigned long pgd_t;
72 typedef unsigned long pgprot_t;
73
74 #define pte_val(x) (x)
75 #define pmd_val(x) (x)
76 #define pgd_val(x) (x)
77 #define pgprot_val(x) (x)
78
79 #define __pte(x) (x)
80 #define __pmd(x) (x)
81 #define __pgd(x) (x)
82 #define __pgprot(x) (x)
83
84 #endif
85
86 /* The current va context is global and known, so all that is needed to
87 * do an invalidate is flush the VAC on a sun4c or call the ASI flushing
88 * routines on a SRMMU.
89 */
90
91 extern void (*invalidate)(void);
92
93 /* Certain architectures need to do special things when pte's
94 * within a page table are directly modified. Thus, the following
95 * hook is made available.
96 */
97 extern void (*set_pte)(pte_t *pteptr, pte_t pteval);
98
99 /* to align the pointer to the (next) page boundary */
100 #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
101
102 /* We now put the free page pool mapped contiguously in high memory above
103 * the kernel.
104 */
105 #define MAP_NR(addr) ((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT)
106
107 #endif /* !(__ASSEMBLY__) */
108
109 /* The rest is kind of funky because on the sparc, the offsets into the mmu
110 * entries are encoded in magic alternate address space tables. I will
111 * probably find some nifty inline assembly routines to do the equivalent.
112 * Much thought must go into this code. (davem@caip.rutgers.edu)
113 */
114
115 /* Bitfields within a Sparc sun4c PTE (page table entry). */
116
117 #define PTE_V 0x80000000 /* valid bit */
118 #define PTE_ACC 0x60000000 /* access bits */
119 #define PTE_W 0x40000000 /* writable bit */
120 #define PTE_P 0x20000000 /* privileged page */
121 #define PTE_NC 0x10000000 /* page is non-cacheable */
122 #define PTE_TYP 0x0c000000 /* page type field */
123 #define PTE_RMEM 0x00000000 /* type == on board real memory */
124 #define PTE_IO 0x04000000 /* type == i/o area */
125 #define PTE_VME16 0x08000000 /* type == 16-bit VME area */
126 #define PTE_VME32 0x0c000000 /* type == 32-bit VME area */
127 #define PTE_R 0x02000000 /* page has been referenced */
128 #define PTE_M 0x01000000 /* page has been modified */
129 #define PTE_RESV 0x00f80000 /* reserved bits */
130 #define PTE_PHYPG 0x0007ffff /* phys pg number, sun4c only uses 16bits */
131
132 /* SRMMU defines */
133 /* The fields in an srmmu virtual address when it gets translated.
134 *
135 * -------------------------------------------------------------
136 * | INDEX 1 | INDEX 2 | INDEX 3 | PAGE OFFSET |
137 * -------------------------------------------------------------
138 * 31 24 23 18 17 12 11 0
139 */
140 #define SRMMU_IDX1_SHIFT 24
141 #define SRMMU_IDX1_MASK 0xff000000
142 #define SRMMU_IDX2_SHIFT 18
143 #define SRMMU_IDX2_MASK 0x00fc0000
144 #define SRMMU_IDX3_SHIFT 12
145 #define SRMMU_IDX3_MASK 0x0003f000
146
147 #define SRMMU_PGOFFSET_MASK 0x00000fff
148 /* The page table sizes for the various levels in bytes. */
149 #define SRMMU_LV1_PTSIZE 1024
150 #define SRMMU_LV2_PTSIZE 256
151 #define SRMMU_LV3_PTSIZE 256
152
153 /* Definition of the values in the ET field of PTD's and PTE's */
154 #define SRMMU_ET_INVALID 0x0
155 #define SRMMU_ET_PTD 0x1
156 #define SRMMU_ET_PTE 0x2
157 #define SRMMU_ET_RESV 0x3
158 #define SRMMU_ET_PTDBAD 0x3 /* Upward compatability my butt. */
159
160 /* Page table directory bits.
161 *
162 * ----------------
163 * | PTP | ET |
164 * ----------------
165 * 31 2 1 0
166 *
167 * PTP: The physical page table pointer. This value appears on
168 * bits 35->6 on the physical address bus during translation.
169 *
170 * ET: Entry type field. Must be 1 for a PTD.
171 */
172
173 #define SRMMU_PTD_PTP_SHIFT 0x2
174 #define SRMMU_PTD_PTP_MASK 0xfffffffc
175 #define SRMMU_PTD_PTP_PADDR_SHIFT 0x4
176 #define SRMMU_PTD_ET_SHIFT 0x0
177 #define SRMMU_PTD_ET_MASK 0x00000003
178
179 /* Page table entry bits.
180 *
181 * -------------------------------------------------
182 * | Physical Page Number | C | M | R | ACC | ET |
183 * -------------------------------------------------
184 * 31 8 7 6 5 4 2 1 0
185 *
186 * PPN: Physical page number, high order 24 bits of the 36-bit
187 * physical address, thus is you mask off all the non
188 * PPN bits you have the physical address of your page.
189 * No shifting necessary.
190 *
191 * C: Whether the page is cacheable in the mmu TLB or not. If
192 * not set the CPU cannot cache values to these addresses. For
193 * IO space translations this bit should be clear.
194 *
195 * M: Modified. This tells whether the page has been written to
196 * since the bit was last cleared. NOTE: this does not include
197 * accesses via the ASI physical page pass through since that does
198 * not use the MMU.
199 *
200 * R: References. This tells whether the page has been referenced
201 * in any way shape or form since the last clearing of the bit.
202 * NOTE: this does not include accesses via the ASI physical page
203 * pass through since that does not use the MMU.
204 *
205 * ACC: Access permissions for this page. This is further explained below
206 * with appropriate macros.
207 */
208
209 #define SRMMU_PTE_PPN_SHIFT 0x8
210 #define SRMMU_PTE_PPN_MASK 0xffffff00
211 #define SRMMU_PTE_PPN_PADDR_SHIFT 0x4
212 #define SRMMU_PTE_C_SHIFT 0x7
213 #define SRMMU_PTE_C_MASK 0x00000080
214 #define SRMMU_PTE_M_SHIFT 0x6
215 #define SRMMU_PTE_M_MASK 0x00000040
216 #define SRMMU_PTE_R_SHIFT 0x5
217 #define SRMMU_PTE_R_MASK 0x00000020
218 #define SRMMU_PTE_ACC_SHIFT 0x2
219 #define SRMMU_PTE_ACC_MASK 0x0000001c
220 #define SRMMU_PTE_ET_SHIFT 0x0
221 #define SRMMU_PTE_ET_MASK 0x00000003
222
223 /* SRMMU pte access bits.
224 *
225 * BIT USER ACCESS SUPERVISOR ACCESS
226 * --- -------------- -----------------
227 * 0x0 read only read only
228 * 0x1 read&write read&write
229 * 0x2 read&execute read&execute
230 * 0x3 read&write&execute read&write&execute
231 * 0x4 execute only execute only
232 * 0x5 read only read&write
233 * 0x6 ACCESS DENIED read&execute
234 * 0x7 ACCESS DENIED read&write&execute
235 *
236 * All these values are shifted left two bits.
237 */
238
239 #define SRMMU_ACC_US_RDONLY 0x00
240 #define SRMMU_ACC_US_RDWR 0x04
241 #define SRMMU_ACC_US_RDEXEC 0x08
242 #define SRMMU_ACC_US_RDWREXEC 0x0c
243 #define SRMMU_ACC_US_EXECONLY 0x10
244 #define SRMMU_ACC_U_RDONLY 0x14
245 #define SRMMU_ACC_S_RDWR 0x14
246 #define SRMMU_ACC_U_ACCDENIED 0x18
247 #define SRMMU_ACC_S_RDEXEC 0x18
248 #define SRMMU_ACC_U_ACCDENIED2 0x1c
249 #define SRMMU_ACC_S_RDWREXEC 0x1c
250
251 #ifndef __ASSEMBLY__
252
253 /* SUN4C pte, segmap, and context manipulation */
254 extern __inline__ unsigned long get_segmap(unsigned long addr)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
255 {
256 register unsigned long entry;
257
258 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
259 "=r" (entry) :
260 "r" (addr), "i" (ASI_SEGMAP));
261
262 return entry;
263 }
264
265 extern __inline__ void put_segmap(unsigned long addr, unsigned long entry)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
266 {
267
268 __asm__ __volatile__("\n\tstba %1, [%0] %2\n\t" : :
269 "r" (addr), "r" (entry),
270 "i" (ASI_SEGMAP));
271
272 return;
273 }
274
275 extern __inline__ unsigned long get_pte(unsigned long addr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
276 {
277 register unsigned long entry;
278
279 __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" :
280 "=r" (entry) :
281 "r" (addr), "i" (ASI_PTE));
282 return entry;
283 }
284
285 extern __inline__ void put_pte(unsigned long addr, unsigned long entry)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
286 {
287 __asm__ __volatile__("\n\tsta %1, [%0] %2\n\t" : :
288 "r" (addr),
289 "r" (entry), "i" (ASI_PTE));
290
291 return;
292 }
293
294 extern void (*switch_to_context)(void *tsk);
295
296 extern __inline__ int get_context(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
297 {
298 register int ctx;
299
300 __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
301 "=r" (ctx) :
302 "r" (AC_CONTEXT), "i" (ASI_CONTROL));
303
304 return ctx;
305 }
306
307 extern __inline__ int set_context(int ctx)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
308 {
309 __asm__ __volatile__("\n\tstba %0, [%1] %2\n\t" : :
310 "r" (ctx), "r" (AC_CONTEXT), "i" (ASI_CONTROL));
311
312 return ctx;
313 }
314
315 #endif /* __ASSEMBLY__ */
316
317 #endif /* __KERNEL__ */
318
319 #endif /* _SPARC_PAGE_H */