diff options
-rw-r--r-- | arch/ia64/Kconfig | 13 | ||||
-rw-r--r-- | arch/ia64/configs/sn2_defconfig | 2 | ||||
-rw-r--r-- | arch/ia64/defconfig | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/ivt.S | 63 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/setup.c | 157 | ||||
-rw-r--r-- | include/asm-ia64/page.h | 8 | ||||
-rw-r--r-- | include/asm-ia64/pgalloc.h | 19 | ||||
-rw-r--r-- | include/asm-ia64/pgtable.h | 76 |
8 files changed, 303 insertions, 37 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index d4de8a4814be..8796e12c56f3 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -164,6 +164,19 @@ config IA64_PAGE_SIZE_64KB | |||
164 | 164 | ||
165 | endchoice | 165 | endchoice |
166 | 166 | ||
167 | choice | ||
168 | prompt "Page Table Levels" | ||
169 | default PGTABLE_3 | ||
170 | |||
171 | config PGTABLE_3 | ||
172 | bool "3 Levels" | ||
173 | |||
174 | config PGTABLE_4 | ||
175 | depends on !IA64_PAGE_SIZE_64KB | ||
176 | bool "4 Levels" | ||
177 | |||
178 | endchoice | ||
179 | |||
167 | source kernel/Kconfig.hz | 180 | source kernel/Kconfig.hz |
168 | 181 | ||
169 | config IA64_BRL_EMU | 182 | config IA64_BRL_EMU |
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index 08112ab38468..87cfd31a4a39 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig | |||
@@ -80,6 +80,8 @@ CONFIG_MCKINLEY=y | |||
80 | # CONFIG_IA64_PAGE_SIZE_8KB is not set | 80 | # CONFIG_IA64_PAGE_SIZE_8KB is not set |
81 | CONFIG_IA64_PAGE_SIZE_16KB=y | 81 | CONFIG_IA64_PAGE_SIZE_16KB=y |
82 | # CONFIG_IA64_PAGE_SIZE_64KB is not set | 82 | # CONFIG_IA64_PAGE_SIZE_64KB is not set |
83 | # CONFIG_PGTABLE_3 is not set | ||
84 | CONFIG_PGTABLE_4=y | ||
83 | # CONFIG_HZ_100 is not set | 85 | # CONFIG_HZ_100 is not set |
84 | CONFIG_HZ_250=y | 86 | CONFIG_HZ_250=y |
85 | # CONFIG_HZ_1000 is not set | 87 | # CONFIG_HZ_1000 is not set |
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig index 6e3f147e03e5..275a26c6e5aa 100644 --- a/arch/ia64/defconfig +++ b/arch/ia64/defconfig | |||
@@ -82,6 +82,8 @@ CONFIG_MCKINLEY=y | |||
82 | # CONFIG_IA64_PAGE_SIZE_8KB is not set | 82 | # CONFIG_IA64_PAGE_SIZE_8KB is not set |
83 | CONFIG_IA64_PAGE_SIZE_16KB=y | 83 | CONFIG_IA64_PAGE_SIZE_16KB=y |
84 | # CONFIG_IA64_PAGE_SIZE_64KB is not set | 84 | # CONFIG_IA64_PAGE_SIZE_64KB is not set |
85 | CONFIG_PGTABLE_3=y | ||
86 | # CONFIG_PGTABLE_4 is not set | ||
85 | # CONFIG_HZ_100 is not set | 87 | # CONFIG_HZ_100 is not set |
86 | CONFIG_HZ_250=y | 88 | CONFIG_HZ_250=y |
87 | # CONFIG_HZ_1000 is not set | 89 | # CONFIG_HZ_1000 is not set |
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index c13ca0d49c4a..e06f21f60dc5 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S | |||
@@ -114,7 +114,7 @@ ENTRY(vhpt_miss) | |||
114 | shl r21=r16,3 // shift bit 60 into sign bit | 114 | shl r21=r16,3 // shift bit 60 into sign bit |
115 | shr.u r17=r16,61 // get the region number into r17 | 115 | shr.u r17=r16,61 // get the region number into r17 |
116 | ;; | 116 | ;; |
117 | shr r22=r21,3 | 117 | shr.u r22=r21,3 |
118 | #ifdef CONFIG_HUGETLB_PAGE | 118 | #ifdef CONFIG_HUGETLB_PAGE |
119 | extr.u r26=r25,2,6 | 119 | extr.u r26=r25,2,6 |
120 | ;; | 120 | ;; |
@@ -140,20 +140,34 @@ ENTRY(vhpt_miss) | |||
140 | (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 | 140 | (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 |
141 | (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) | 141 | (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) |
142 | cmp.eq p7,p6=0,r21 // unused address bits all zeroes? | 142 | cmp.eq p7,p6=0,r21 // unused address bits all zeroes? |
143 | shr.u r18=r22,PMD_SHIFT // shift L2 index into position | 143 | #ifdef CONFIG_PGTABLE_4 |
144 | shr.u r28=r22,PUD_SHIFT // shift L2 index into position | ||
145 | #else | ||
146 | shr.u r18=r22,PMD_SHIFT // shift L3 index into position | ||
147 | #endif | ||
144 | ;; | 148 | ;; |
145 | ld8 r17=[r17] // fetch the L1 entry (may be 0) | 149 | ld8 r17=[r17] // fetch the L1 entry (may be 0) |
146 | ;; | 150 | ;; |
147 | (p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? | 151 | (p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? |
148 | dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry | 152 | #ifdef CONFIG_PGTABLE_4 |
153 | dep r28=r28,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry | ||
154 | ;; | ||
155 | shr.u r18=r22,PMD_SHIFT // shift L3 index into position | ||
156 | (p7) ld8 r29=[r28] // fetch the L2 entry (may be 0) | ||
149 | ;; | 157 | ;; |
150 | (p7) ld8 r20=[r17] // fetch the L2 entry (may be 0) | 158 | (p7) cmp.eq.or.andcm p6,p7=r29,r0 // was L2 entry NULL? |
151 | shr.u r19=r22,PAGE_SHIFT // shift L3 index into position | 159 | dep r17=r18,r29,3,(PAGE_SHIFT-3) // compute address of L3 page table entry |
160 | #else | ||
161 | dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry | ||
162 | #endif | ||
152 | ;; | 163 | ;; |
153 | (p7) cmp.eq.or.andcm p6,p7=r20,r0 // was L2 entry NULL? | 164 | (p7) ld8 r20=[r17] // fetch the L3 entry (may be 0) |
154 | dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L3 page table entry | 165 | shr.u r19=r22,PAGE_SHIFT // shift L4 index into position |
155 | ;; | 166 | ;; |
156 | (p7) ld8 r18=[r21] // read the L3 PTE | 167 | (p7) cmp.eq.or.andcm p6,p7=r20,r0 // was L3 entry NULL? |
168 | dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L4 page table entry | ||
169 | ;; | ||
170 | (p7) ld8 r18=[r21] // read the L4 PTE | ||
157 | mov r19=cr.isr // cr.isr bit 0 tells us if this is an insn miss | 171 | mov r19=cr.isr // cr.isr bit 0 tells us if this is an insn miss |
158 | ;; | 172 | ;; |
159 | (p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared? | 173 | (p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared? |
@@ -192,14 +206,21 @@ ENTRY(vhpt_miss) | |||
192 | * between reading the pagetable and the "itc". If so, flush the entry we | 206 | * between reading the pagetable and the "itc". If so, flush the entry we |
193 | * inserted and retry. | 207 | * inserted and retry. |
194 | */ | 208 | */ |
195 | ld8 r25=[r21] // read L3 PTE again | 209 | ld8 r25=[r21] // read L4 entry again |
196 | ld8 r26=[r17] // read L2 entry again | 210 | ld8 r26=[r17] // read L3 PTE again |
211 | #ifdef CONFIG_PGTABLE_4 | ||
212 | ld8 r18=[r28] // read L2 entry again | ||
213 | #endif | ||
214 | cmp.ne p6,p7=r0,r0 | ||
197 | ;; | 215 | ;; |
198 | cmp.ne p6,p7=r26,r20 // did L2 entry change | 216 | cmp.ne.or.andcm p6,p7=r26,r20 // did L3 entry change |
217 | #ifdef CONFIG_PGTABLE_4 | ||
218 | cmp.ne.or.andcm p6,p7=r29,r18 // did L4 PTE change | ||
219 | #endif | ||
199 | mov r27=PAGE_SHIFT<<2 | 220 | mov r27=PAGE_SHIFT<<2 |
200 | ;; | 221 | ;; |
201 | (p6) ptc.l r22,r27 // purge PTE page translation | 222 | (p6) ptc.l r22,r27 // purge PTE page translation |
202 | (p7) cmp.ne.or.andcm p6,p7=r25,r18 // did L3 PTE change | 223 | (p7) cmp.ne.or.andcm p6,p7=r25,r18 // did L4 PTE change |
203 | ;; | 224 | ;; |
204 | (p6) ptc.l r16,r27 // purge translation | 225 | (p6) ptc.l r16,r27 // purge translation |
205 | #endif | 226 | #endif |
@@ -432,18 +453,30 @@ ENTRY(nested_dtlb_miss) | |||
432 | (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 | 453 | (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 |
433 | (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) | 454 | (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) |
434 | cmp.eq p7,p6=0,r21 // unused address bits all zeroes? | 455 | cmp.eq p7,p6=0,r21 // unused address bits all zeroes? |
435 | shr.u r18=r22,PMD_SHIFT // shift L2 index into position | 456 | #ifdef CONFIG_PGTABLE_4 |
457 | shr.u r18=r22,PUD_SHIFT // shift L2 index into position | ||
458 | #else | ||
459 | shr.u r18=r22,PMD_SHIFT // shift L3 index into position | ||
460 | #endif | ||
436 | ;; | 461 | ;; |
437 | ld8 r17=[r17] // fetch the L1 entry (may be 0) | 462 | ld8 r17=[r17] // fetch the L1 entry (may be 0) |
438 | ;; | 463 | ;; |
439 | (p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? | 464 | (p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? |
440 | dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry | 465 | dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry |
441 | ;; | 466 | ;; |
467 | #ifdef CONFIG_PGTABLE_4 | ||
442 | (p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) | 468 | (p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) |
443 | shr.u r19=r22,PAGE_SHIFT // shift L3 index into position | 469 | shr.u r18=r22,PMD_SHIFT // shift L3 index into position |
444 | ;; | 470 | ;; |
445 | (p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? | 471 | (p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? |
446 | dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry | 472 | dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry |
473 | ;; | ||
474 | #endif | ||
475 | (p7) ld8 r17=[r17] // fetch the L3 entry (may be 0) | ||
476 | shr.u r19=r22,PAGE_SHIFT // shift L4 index into position | ||
477 | ;; | ||
478 | (p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L3 entry NULL? | ||
479 | dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L4 page table entry | ||
447 | (p6) br.cond.spnt page_fault | 480 | (p6) br.cond.spnt page_fault |
448 | mov b0=r30 | 481 | mov b0=r30 |
449 | br.sptk.many b0 // return to continuation point | 482 | br.sptk.many b0 // return to continuation point |
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 0fb579ef18c2..e510dce9971f 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/root_dev.h> | 30 | #include <linux/root_dev.h> |
31 | #include <linux/nodemask.h> | 31 | #include <linux/nodemask.h> |
32 | #include <linux/pm.h> | 32 | #include <linux/pm.h> |
33 | #include <linux/efi.h> | ||
33 | 34 | ||
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
35 | #include <asm/sal.h> | 36 | #include <asm/sal.h> |
@@ -242,6 +243,135 @@ static void __init sn_check_for_wars(void) | |||
242 | } | 243 | } |
243 | } | 244 | } |
244 | 245 | ||
246 | /* | ||
247 | * Scan the EFI PCDP table (if it exists) for an acceptable VGA console | ||
248 | * output device. If one exists, pick it and set sn_legacy_{io,mem} to | ||
249 | * reflect the bus offsets needed to address it. | ||
250 | * | ||
251 | * Since pcdp support in SN is not supported in the 2.4 kernel (or at least | ||
252 | * the one lbs is based on) just declare the needed structs here. | ||
253 | * | ||
254 | * Reference spec http://www.dig64.org/specifications/DIG64_PCDPv20.pdf | ||
255 | * | ||
256 | * Returns 0 if no acceptable vga is found, !0 otherwise. | ||
257 | * | ||
258 | * Note: This stuff is duped here because Altix requires the PCDP to | ||
259 | * locate a usable VGA device due to lack of proper ACPI support. Structures | ||
260 | * could be used from drivers/firmware/pcdp.h, but it was decided that moving | ||
261 | * this file to a more public location just for Altix use was undesireable. | ||
262 | */ | ||
263 | |||
264 | struct hcdp_uart_desc { | ||
265 | u8 pad[45]; | ||
266 | }; | ||
267 | |||
268 | struct pcdp { | ||
269 | u8 signature[4]; /* should be 'HCDP' */ | ||
270 | u32 length; | ||
271 | u8 rev; /* should be >=3 for pcdp, <3 for hcdp */ | ||
272 | u8 sum; | ||
273 | u8 oem_id[6]; | ||
274 | u64 oem_tableid; | ||
275 | u32 oem_rev; | ||
276 | u32 creator_id; | ||
277 | u32 creator_rev; | ||
278 | u32 num_type0; | ||
279 | struct hcdp_uart_desc uart[0]; /* num_type0 of these */ | ||
280 | /* pcdp descriptors follow */ | ||
281 | } __attribute__((packed)); | ||
282 | |||
283 | struct pcdp_device_desc { | ||
284 | u8 type; | ||
285 | u8 primary; | ||
286 | u16 length; | ||
287 | u16 index; | ||
288 | /* interconnect specific structure follows */ | ||
289 | /* device specific structure follows that */ | ||
290 | } __attribute__((packed)); | ||
291 | |||
292 | struct pcdp_interface_pci { | ||
293 | u8 type; /* 1 == pci */ | ||
294 | u8 reserved; | ||
295 | u16 length; | ||
296 | u8 segment; | ||
297 | u8 bus; | ||
298 | u8 dev; | ||
299 | u8 fun; | ||
300 | u16 devid; | ||
301 | u16 vendid; | ||
302 | u32 acpi_interrupt; | ||
303 | u64 mmio_tra; | ||
304 | u64 ioport_tra; | ||
305 | u8 flags; | ||
306 | u8 translation; | ||
307 | } __attribute__((packed)); | ||
308 | |||
309 | struct pcdp_vga_device { | ||
310 | u8 num_eas_desc; | ||
311 | /* ACPI Extended Address Space Desc follows */ | ||
312 | } __attribute__((packed)); | ||
313 | |||
314 | /* from pcdp_device_desc.primary */ | ||
315 | #define PCDP_PRIMARY_CONSOLE 0x01 | ||
316 | |||
317 | /* from pcdp_device_desc.type */ | ||
318 | #define PCDP_CONSOLE_INOUT 0x0 | ||
319 | #define PCDP_CONSOLE_DEBUG 0x1 | ||
320 | #define PCDP_CONSOLE_OUT 0x2 | ||
321 | #define PCDP_CONSOLE_IN 0x3 | ||
322 | #define PCDP_CONSOLE_TYPE_VGA 0x8 | ||
323 | |||
324 | #define PCDP_CONSOLE_VGA (PCDP_CONSOLE_TYPE_VGA | PCDP_CONSOLE_OUT) | ||
325 | |||
326 | /* from pcdp_interface_pci.type */ | ||
327 | #define PCDP_IF_PCI 1 | ||
328 | |||
329 | /* from pcdp_interface_pci.translation */ | ||
330 | #define PCDP_PCI_TRANS_IOPORT 0x02 | ||
331 | #define PCDP_PCI_TRANS_MMIO 0x01 | ||
332 | |||
333 | static void | ||
334 | sn_scan_pcdp(void) | ||
335 | { | ||
336 | u8 *bp; | ||
337 | struct pcdp *pcdp; | ||
338 | struct pcdp_device_desc device; | ||
339 | struct pcdp_interface_pci if_pci; | ||
340 | extern struct efi efi; | ||
341 | |||
342 | pcdp = efi.hcdp; | ||
343 | if (! pcdp) | ||
344 | return; /* no hcdp/pcdp table */ | ||
345 | |||
346 | if (pcdp->rev < 3) | ||
347 | return; /* only support PCDP (rev >= 3) */ | ||
348 | |||
349 | for (bp = (u8 *)&pcdp->uart[pcdp->num_type0]; | ||
350 | bp < (u8 *)pcdp + pcdp->length; | ||
351 | bp += device.length) { | ||
352 | memcpy(&device, bp, sizeof(device)); | ||
353 | if (! (device.primary & PCDP_PRIMARY_CONSOLE)) | ||
354 | continue; /* not primary console */ | ||
355 | |||
356 | if (device.type != PCDP_CONSOLE_VGA) | ||
357 | continue; /* not VGA descriptor */ | ||
358 | |||
359 | memcpy(&if_pci, bp+sizeof(device), sizeof(if_pci)); | ||
360 | if (if_pci.type != PCDP_IF_PCI) | ||
361 | continue; /* not PCI interconnect */ | ||
362 | |||
363 | if (if_pci.translation & PCDP_PCI_TRANS_IOPORT) | ||
364 | vga_console_iobase = | ||
365 | if_pci.ioport_tra | __IA64_UNCACHED_OFFSET; | ||
366 | |||
367 | if (if_pci.translation & PCDP_PCI_TRANS_MMIO) | ||
368 | vga_console_membase = | ||
369 | if_pci.mmio_tra | __IA64_UNCACHED_OFFSET; | ||
370 | |||
371 | break; /* once we find the primary, we're done */ | ||
372 | } | ||
373 | } | ||
374 | |||
245 | /** | 375 | /** |
246 | * sn_setup - SN platform setup routine | 376 | * sn_setup - SN platform setup routine |
247 | * @cmdline_p: kernel command line | 377 | * @cmdline_p: kernel command line |
@@ -263,16 +393,35 @@ void __init sn_setup(char **cmdline_p) | |||
263 | 393 | ||
264 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) | 394 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) |
265 | /* | 395 | /* |
266 | * If there was a primary vga adapter identified through the | 396 | * Handle SN vga console. |
267 | * EFI PCDP table, make it the preferred console. Otherwise | 397 | * |
268 | * zero out conswitchp. | 398 | * SN systems do not have enough ACPI table information |
399 | * being passed from prom to identify VGA adapters and the legacy | ||
400 | * addresses to access them. Until that is done, SN systems rely | ||
401 | * on the PCDP table to identify the primary VGA console if one | ||
402 | * exists. | ||
403 | * | ||
404 | * However, kernel PCDP support is optional, and even if it is built | ||
405 | * into the kernel, it will not be used if the boot cmdline contains | ||
406 | * console= directives. | ||
407 | * | ||
408 | * So, to work around this mess, we duplicate some of the PCDP code | ||
409 | * here so that the primary VGA console (as defined by PCDP) will | ||
410 | * work on SN systems even if a different console (e.g. serial) is | ||
411 | * selected on the boot line (or CONFIG_EFI_PCDP is off). | ||
269 | */ | 412 | */ |
270 | 413 | ||
414 | if (! vga_console_membase) | ||
415 | sn_scan_pcdp(); | ||
416 | |||
271 | if (vga_console_membase) { | 417 | if (vga_console_membase) { |
272 | /* usable vga ... make tty0 the preferred default console */ | 418 | /* usable vga ... make tty0 the preferred default console */ |
273 | add_preferred_console("tty", 0, NULL); | 419 | if (!strstr(*cmdline_p, "console=")) |
420 | add_preferred_console("tty", 0, NULL); | ||
274 | } else { | 421 | } else { |
275 | printk(KERN_DEBUG "SGI: Disabling VGA console\n"); | 422 | printk(KERN_DEBUG "SGI: Disabling VGA console\n"); |
423 | if (!strstr(*cmdline_p, "console=")) | ||
424 | add_preferred_console("ttySG", 0, NULL); | ||
276 | #ifdef CONFIG_DUMMY_CONSOLE | 425 | #ifdef CONFIG_DUMMY_CONSOLE |
277 | conswitchp = &dummy_con; | 426 | conswitchp = &dummy_con; |
278 | #else | 427 | #else |
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 9d41548b7fef..9dd9da105278 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h | |||
@@ -47,8 +47,6 @@ | |||
47 | #define PERCPU_PAGE_SHIFT 16 /* log2() of max. size of per-CPU area */ | 47 | #define PERCPU_PAGE_SHIFT 16 /* log2() of max. size of per-CPU area */ |
48 | #define PERCPU_PAGE_SIZE (__IA64_UL_CONST(1) << PERCPU_PAGE_SHIFT) | 48 | #define PERCPU_PAGE_SIZE (__IA64_UL_CONST(1) << PERCPU_PAGE_SHIFT) |
49 | 49 | ||
50 | #define RGN_MAP_LIMIT ((1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE) /* per region addr limit */ | ||
51 | |||
52 | 50 | ||
53 | #ifdef CONFIG_HUGETLB_PAGE | 51 | #ifdef CONFIG_HUGETLB_PAGE |
54 | # define HPAGE_REGION_BASE RGN_BASE(RGN_HPAGE) | 52 | # define HPAGE_REGION_BASE RGN_BASE(RGN_HPAGE) |
@@ -175,11 +173,17 @@ get_order (unsigned long size) | |||
175 | */ | 173 | */ |
176 | typedef struct { unsigned long pte; } pte_t; | 174 | typedef struct { unsigned long pte; } pte_t; |
177 | typedef struct { unsigned long pmd; } pmd_t; | 175 | typedef struct { unsigned long pmd; } pmd_t; |
176 | #ifdef CONFIG_PGTABLE_4 | ||
177 | typedef struct { unsigned long pud; } pud_t; | ||
178 | #endif | ||
178 | typedef struct { unsigned long pgd; } pgd_t; | 179 | typedef struct { unsigned long pgd; } pgd_t; |
179 | typedef struct { unsigned long pgprot; } pgprot_t; | 180 | typedef struct { unsigned long pgprot; } pgprot_t; |
180 | 181 | ||
181 | # define pte_val(x) ((x).pte) | 182 | # define pte_val(x) ((x).pte) |
182 | # define pmd_val(x) ((x).pmd) | 183 | # define pmd_val(x) ((x).pmd) |
184 | #ifdef CONFIG_PGTABLE_4 | ||
185 | # define pud_val(x) ((x).pud) | ||
186 | #endif | ||
183 | # define pgd_val(x) ((x).pgd) | 187 | # define pgd_val(x) ((x).pgd) |
184 | # define pgprot_val(x) ((x).pgprot) | 188 | # define pgprot_val(x) ((x).pgprot) |
185 | 189 | ||
diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h index a5f214554afd..f2f233846476 100644 --- a/include/asm-ia64/pgalloc.h +++ b/include/asm-ia64/pgalloc.h | |||
@@ -86,6 +86,25 @@ static inline void pgd_free(pgd_t * pgd) | |||
86 | pgtable_quicklist_free(pgd); | 86 | pgtable_quicklist_free(pgd); |
87 | } | 87 | } |
88 | 88 | ||
89 | #ifdef CONFIG_PGTABLE_4 | ||
90 | static inline void | ||
91 | pgd_populate(struct mm_struct *mm, pgd_t * pgd_entry, pud_t * pud) | ||
92 | { | ||
93 | pgd_val(*pgd_entry) = __pa(pud); | ||
94 | } | ||
95 | |||
96 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
97 | { | ||
98 | return pgtable_quicklist_alloc(); | ||
99 | } | ||
100 | |||
101 | static inline void pud_free(pud_t * pud) | ||
102 | { | ||
103 | pgtable_quicklist_free(pud); | ||
104 | } | ||
105 | #define __pud_free_tlb(tlb, pud) pud_free(pud) | ||
106 | #endif /* CONFIG_PGTABLE_4 */ | ||
107 | |||
89 | static inline void | 108 | static inline void |
90 | pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd) | 109 | pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd) |
91 | { | 110 | { |
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index c34ba80c1c31..e2560c58384b 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h | |||
@@ -84,32 +84,55 @@ | |||
84 | #define __DIRTY_BITS _PAGE_ED | __DIRTY_BITS_NO_ED | 84 | #define __DIRTY_BITS _PAGE_ED | __DIRTY_BITS_NO_ED |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * Definitions for first level: | 87 | * How many pointers will a page table level hold expressed in shift |
88 | * | ||
89 | * PGDIR_SHIFT determines what a first-level page table entry can map. | ||
90 | */ | 88 | */ |
91 | #define PGDIR_SHIFT (PAGE_SHIFT + 2*(PAGE_SHIFT-3)) | 89 | #define PTRS_PER_PTD_SHIFT (PAGE_SHIFT-3) |
92 | #define PGDIR_SIZE (__IA64_UL(1) << PGDIR_SHIFT) | ||
93 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
94 | #define PTRS_PER_PGD (1UL << (PAGE_SHIFT-3)) | ||
95 | #define USER_PTRS_PER_PGD (5*PTRS_PER_PGD/8) /* regions 0-4 are user regions */ | ||
96 | #define FIRST_USER_ADDRESS 0 | ||
97 | 90 | ||
98 | /* | 91 | /* |
99 | * Definitions for second level: | 92 | * Definitions for fourth level: |
93 | */ | ||
94 | #define PTRS_PER_PTE (__IA64_UL(1) << (PTRS_PER_PTD_SHIFT)) | ||
95 | |||
96 | /* | ||
97 | * Definitions for third level: | ||
100 | * | 98 | * |
101 | * PMD_SHIFT determines the size of the area a second-level page table | 99 | * PMD_SHIFT determines the size of the area a third-level page table |
102 | * can map. | 100 | * can map. |
103 | */ | 101 | */ |
104 | #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3)) | 102 | #define PMD_SHIFT (PAGE_SHIFT + (PTRS_PER_PTD_SHIFT)) |
105 | #define PMD_SIZE (1UL << PMD_SHIFT) | 103 | #define PMD_SIZE (1UL << PMD_SHIFT) |
106 | #define PMD_MASK (~(PMD_SIZE-1)) | 104 | #define PMD_MASK (~(PMD_SIZE-1)) |
107 | #define PTRS_PER_PMD (1UL << (PAGE_SHIFT-3)) | 105 | #define PTRS_PER_PMD (1UL << (PTRS_PER_PTD_SHIFT)) |
108 | 106 | ||
107 | #ifdef CONFIG_PGTABLE_4 | ||
109 | /* | 108 | /* |
110 | * Definitions for third level: | 109 | * Definitions for second level: |
110 | * | ||
111 | * PUD_SHIFT determines the size of the area a second-level page table | ||
112 | * can map. | ||
111 | */ | 113 | */ |
112 | #define PTRS_PER_PTE (__IA64_UL(1) << (PAGE_SHIFT-3)) | 114 | #define PUD_SHIFT (PMD_SHIFT + (PTRS_PER_PTD_SHIFT)) |
115 | #define PUD_SIZE (1UL << PUD_SHIFT) | ||
116 | #define PUD_MASK (~(PUD_SIZE-1)) | ||
117 | #define PTRS_PER_PUD (1UL << (PTRS_PER_PTD_SHIFT)) | ||
118 | #endif | ||
119 | |||
120 | /* | ||
121 | * Definitions for first level: | ||
122 | * | ||
123 | * PGDIR_SHIFT determines what a first-level page table entry can map. | ||
124 | */ | ||
125 | #ifdef CONFIG_PGTABLE_4 | ||
126 | #define PGDIR_SHIFT (PUD_SHIFT + (PTRS_PER_PTD_SHIFT)) | ||
127 | #else | ||
128 | #define PGDIR_SHIFT (PMD_SHIFT + (PTRS_PER_PTD_SHIFT)) | ||
129 | #endif | ||
130 | #define PGDIR_SIZE (__IA64_UL(1) << PGDIR_SHIFT) | ||
131 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
132 | #define PTRS_PER_PGD_SHIFT PTRS_PER_PTD_SHIFT | ||
133 | #define PTRS_PER_PGD (1UL << PTRS_PER_PGD_SHIFT) | ||
134 | #define USER_PTRS_PER_PGD (5*PTRS_PER_PGD/8) /* regions 0-4 are user regions */ | ||
135 | #define FIRST_USER_ADDRESS 0 | ||
113 | 136 | ||
114 | /* | 137 | /* |
115 | * All the normal masks have the "page accessed" bits on, as any time | 138 | * All the normal masks have the "page accessed" bits on, as any time |
@@ -161,6 +184,9 @@ | |||
161 | #define __S111 __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RWX) | 184 | #define __S111 __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RWX) |
162 | 185 | ||
163 | #define pgd_ERROR(e) printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e)) | 186 | #define pgd_ERROR(e) printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e)) |
187 | #ifdef CONFIG_PGTABLE_4 | ||
188 | #define pud_ERROR(e) printk("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_val(e)) | ||
189 | #endif | ||
164 | #define pmd_ERROR(e) printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e)) | 190 | #define pmd_ERROR(e) printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e)) |
165 | #define pte_ERROR(e) printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) | 191 | #define pte_ERROR(e) printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) |
166 | 192 | ||
@@ -218,6 +244,9 @@ ia64_phys_addr_valid (unsigned long addr) | |||
218 | #define kc_vaddr_to_offset(v) ((v) - RGN_BASE(RGN_GATE)) | 244 | #define kc_vaddr_to_offset(v) ((v) - RGN_BASE(RGN_GATE)) |
219 | #define kc_offset_to_vaddr(o) ((o) + RGN_BASE(RGN_GATE)) | 245 | #define kc_offset_to_vaddr(o) ((o) + RGN_BASE(RGN_GATE)) |
220 | 246 | ||
247 | #define RGN_MAP_SHIFT (PGDIR_SHIFT + PTRS_PER_PGD_SHIFT - 3) | ||
248 | #define RGN_MAP_LIMIT ((1UL << RGN_MAP_SHIFT) - PAGE_SIZE) /* per region addr limit */ | ||
249 | |||
221 | /* | 250 | /* |
222 | * Conversion functions: convert page frame number (pfn) and a protection value to a page | 251 | * Conversion functions: convert page frame number (pfn) and a protection value to a page |
223 | * table entry (pte). | 252 | * table entry (pte). |
@@ -254,9 +283,16 @@ ia64_phys_addr_valid (unsigned long addr) | |||
254 | #define pud_bad(pud) (!ia64_phys_addr_valid(pud_val(pud))) | 283 | #define pud_bad(pud) (!ia64_phys_addr_valid(pud_val(pud))) |
255 | #define pud_present(pud) (pud_val(pud) != 0UL) | 284 | #define pud_present(pud) (pud_val(pud) != 0UL) |
256 | #define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) | 285 | #define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) |
257 | |||
258 | #define pud_page(pud) ((unsigned long) __va(pud_val(pud) & _PFN_MASK)) | 286 | #define pud_page(pud) ((unsigned long) __va(pud_val(pud) & _PFN_MASK)) |
259 | 287 | ||
288 | #ifdef CONFIG_PGTABLE_4 | ||
289 | #define pgd_none(pgd) (!pgd_val(pgd)) | ||
290 | #define pgd_bad(pgd) (!ia64_phys_addr_valid(pgd_val(pgd))) | ||
291 | #define pgd_present(pgd) (pgd_val(pgd) != 0UL) | ||
292 | #define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0UL) | ||
293 | #define pgd_page(pgd) ((unsigned long) __va(pgd_val(pgd) & _PFN_MASK)) | ||
294 | #endif | ||
295 | |||
260 | /* | 296 | /* |
261 | * The following have defined behavior only work if pte_present() is true. | 297 | * The following have defined behavior only work if pte_present() is true. |
262 | */ | 298 | */ |
@@ -324,7 +360,13 @@ pgd_offset (struct mm_struct *mm, unsigned long address) | |||
324 | here. */ | 360 | here. */ |
325 | #define pgd_offset_gate(mm, addr) pgd_offset_k(addr) | 361 | #define pgd_offset_gate(mm, addr) pgd_offset_k(addr) |
326 | 362 | ||
363 | #ifdef CONFIG_PGTABLE_4 | ||
327 | /* Find an entry in the second-level page table.. */ | 364 | /* Find an entry in the second-level page table.. */ |
365 | #define pud_offset(dir,addr) \ | ||
366 | ((pud_t *) pgd_page(*(dir)) + (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))) | ||
367 | #endif | ||
368 | |||
369 | /* Find an entry in the third-level page table.. */ | ||
328 | #define pmd_offset(dir,addr) \ | 370 | #define pmd_offset(dir,addr) \ |
329 | ((pmd_t *) pud_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))) | 371 | ((pmd_t *) pud_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))) |
330 | 372 | ||
@@ -557,7 +599,9 @@ do { \ | |||
557 | #define __HAVE_ARCH_PGD_OFFSET_GATE | 599 | #define __HAVE_ARCH_PGD_OFFSET_GATE |
558 | #define __HAVE_ARCH_LAZY_MMU_PROT_UPDATE | 600 | #define __HAVE_ARCH_LAZY_MMU_PROT_UPDATE |
559 | 601 | ||
602 | #ifndef CONFIG_PGTABLE_4 | ||
560 | #include <asm-generic/pgtable-nopud.h> | 603 | #include <asm-generic/pgtable-nopud.h> |
604 | #endif | ||
561 | #include <asm-generic/pgtable.h> | 605 | #include <asm-generic/pgtable.h> |
562 | 606 | ||
563 | #endif /* _ASM_IA64_PGTABLE_H */ | 607 | #endif /* _ASM_IA64_PGTABLE_H */ |