aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-s390/pgtable.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-22 22:23:34 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-22 22:23:34 -0400
commit56d61a0e26c5a61c66d1ac259a59960295939da9 (patch)
treea23a30a966fe4220060682179294087cba1f9c57 /include/asm-s390/pgtable.h
parent5f48b338cd28f4095697a174d7e3e72084aca893 (diff)
parent190a1d722a59725706daf832bc8a511ed62f249d (diff)
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6: [S390] 4level-fixup cleanup [S390] Cleanup page table definitions. [S390] Introduce follow_table in uaccess_pt.c [S390] Remove unused user_seg from thread structure. [S390] tlb flush fix. [S390] kernel: Fix dump on panic for DASDs under LPAR. [S390] struct class_device -> struct device conversion. [S390] cio: Fix incomplete commit for uevent suppression. [S390] cio: Use to_channelpath() for device to channel path conversion. [S390] Add per-cpu idle time / idle count sysfs attributes. [S390] Update default configuration.
Diffstat (limited to 'include/asm-s390/pgtable.h')
-rw-r--r--include/asm-s390/pgtable.h429
1 files changed, 223 insertions, 206 deletions
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 39bb5192dc31..f2cc25b74adf 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -13,8 +13,6 @@
13#ifndef _ASM_S390_PGTABLE_H 13#ifndef _ASM_S390_PGTABLE_H
14#define _ASM_S390_PGTABLE_H 14#define _ASM_S390_PGTABLE_H
15 15
16#include <asm-generic/4level-fixup.h>
17
18/* 16/*
19 * The Linux memory management assumes a three-level page table setup. For 17 * The Linux memory management assumes a three-level page table setup. For
20 * s390 31 bit we "fold" the mid level into the top-level page table, so 18 * s390 31 bit we "fold" the mid level into the top-level page table, so
@@ -35,9 +33,6 @@
35#include <asm/bug.h> 33#include <asm/bug.h>
36#include <asm/processor.h> 34#include <asm/processor.h>
37 35
38struct vm_area_struct; /* forward declaration (include/linux/mm.h) */
39struct mm_struct;
40
41extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); 36extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
42extern void paging_init(void); 37extern void paging_init(void);
43extern void vmem_map_init(void); 38extern void vmem_map_init(void);
@@ -63,14 +58,18 @@ extern char empty_zero_page[PAGE_SIZE];
63 */ 58 */
64#ifndef __s390x__ 59#ifndef __s390x__
65# define PMD_SHIFT 22 60# define PMD_SHIFT 22
61# define PUD_SHIFT 22
66# define PGDIR_SHIFT 22 62# define PGDIR_SHIFT 22
67#else /* __s390x__ */ 63#else /* __s390x__ */
68# define PMD_SHIFT 21 64# define PMD_SHIFT 21
65# define PUD_SHIFT 31
69# define PGDIR_SHIFT 31 66# define PGDIR_SHIFT 31
70#endif /* __s390x__ */ 67#endif /* __s390x__ */
71 68
72#define PMD_SIZE (1UL << PMD_SHIFT) 69#define PMD_SIZE (1UL << PMD_SHIFT)
73#define PMD_MASK (~(PMD_SIZE-1)) 70#define PMD_MASK (~(PMD_SIZE-1))
71#define PUD_SIZE (1UL << PUD_SHIFT)
72#define PUD_MASK (~(PUD_SIZE-1))
74#define PGDIR_SIZE (1UL << PGDIR_SHIFT) 73#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
75#define PGDIR_MASK (~(PGDIR_SIZE-1)) 74#define PGDIR_MASK (~(PGDIR_SIZE-1))
76 75
@@ -83,10 +82,12 @@ extern char empty_zero_page[PAGE_SIZE];
83#ifndef __s390x__ 82#ifndef __s390x__
84# define PTRS_PER_PTE 1024 83# define PTRS_PER_PTE 1024
85# define PTRS_PER_PMD 1 84# define PTRS_PER_PMD 1
85# define PTRS_PER_PUD 1
86# define PTRS_PER_PGD 512 86# define PTRS_PER_PGD 512
87#else /* __s390x__ */ 87#else /* __s390x__ */
88# define PTRS_PER_PTE 512 88# define PTRS_PER_PTE 512
89# define PTRS_PER_PMD 1024 89# define PTRS_PER_PMD 1024
90# define PTRS_PER_PUD 1
90# define PTRS_PER_PGD 2048 91# define PTRS_PER_PGD 2048
91#endif /* __s390x__ */ 92#endif /* __s390x__ */
92 93
@@ -96,6 +97,8 @@ extern char empty_zero_page[PAGE_SIZE];
96 printk("%s:%d: bad pte %p.\n", __FILE__, __LINE__, (void *) pte_val(e)) 97 printk("%s:%d: bad pte %p.\n", __FILE__, __LINE__, (void *) pte_val(e))
97#define pmd_ERROR(e) \ 98#define pmd_ERROR(e) \
98 printk("%s:%d: bad pmd %p.\n", __FILE__, __LINE__, (void *) pmd_val(e)) 99 printk("%s:%d: bad pmd %p.\n", __FILE__, __LINE__, (void *) pmd_val(e))
100#define pud_ERROR(e) \
101 printk("%s:%d: bad pud %p.\n", __FILE__, __LINE__, (void *) pud_val(e))
99#define pgd_ERROR(e) \ 102#define pgd_ERROR(e) \
100 printk("%s:%d: bad pgd %p.\n", __FILE__, __LINE__, (void *) pgd_val(e)) 103 printk("%s:%d: bad pgd %p.\n", __FILE__, __LINE__, (void *) pgd_val(e))
101 104
@@ -195,7 +198,7 @@ extern unsigned long vmalloc_end;
195 * I Segment-Invalid Bit: Segment is not available for address-translation 198 * I Segment-Invalid Bit: Segment is not available for address-translation
196 * TT Type 01 199 * TT Type 01
197 * TF 200 * TF
198 * TL Table lenght 201 * TL Table length
199 * 202 *
200 * The 64 bit regiontable origin of S390 has following format: 203 * The 64 bit regiontable origin of S390 has following format:
201 * | region table origon | DTTL 204 * | region table origon | DTTL
@@ -221,6 +224,8 @@ extern unsigned long vmalloc_end;
221/* Hardware bits in the page table entry */ 224/* Hardware bits in the page table entry */
222#define _PAGE_RO 0x200 /* HW read-only bit */ 225#define _PAGE_RO 0x200 /* HW read-only bit */
223#define _PAGE_INVALID 0x400 /* HW invalid bit */ 226#define _PAGE_INVALID 0x400 /* HW invalid bit */
227
228/* Software bits in the page table entry */
224#define _PAGE_SWT 0x001 /* SW pte type bit t */ 229#define _PAGE_SWT 0x001 /* SW pte type bit t */
225#define _PAGE_SWX 0x002 /* SW pte type bit x */ 230#define _PAGE_SWX 0x002 /* SW pte type bit x */
226 231
@@ -264,60 +269,75 @@ extern unsigned long vmalloc_end;
264 269
265#ifndef __s390x__ 270#ifndef __s390x__
266 271
267/* Bits in the segment table entry */ 272/* Bits in the segment table address-space-control-element */
268#define _PAGE_TABLE_LEN 0xf /* only full page-tables */ 273#define _ASCE_SPACE_SWITCH 0x80000000UL /* space switch event */
269#define _PAGE_TABLE_COM 0x10 /* common page-table */ 274#define _ASCE_ORIGIN_MASK 0x7ffff000UL /* segment table origin */
270#define _PAGE_TABLE_INV 0x20 /* invalid page-table */ 275#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */
271#define _SEG_PRESENT 0x001 /* Software (overlap with PTL) */ 276#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */
272 277#define _ASCE_TABLE_LENGTH 0x7f /* 128 x 64 entries = 8k */
273/* Bits int the storage key */
274#define _PAGE_CHANGED 0x02 /* HW changed bit */
275#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
276
277#define _USER_SEG_TABLE_LEN 0x7f /* user-segment-table up to 2 GB */
278#define _KERNEL_SEG_TABLE_LEN 0x7f /* kernel-segment-table up to 2 GB */
279
280/*
281 * User and Kernel pagetables are identical
282 */
283#define _PAGE_TABLE _PAGE_TABLE_LEN
284#define _KERNPG_TABLE _PAGE_TABLE_LEN
285
286/*
287 * The Kernel segment-tables includes the User segment-table
288 */
289 278
290#define _SEGMENT_TABLE (_USER_SEG_TABLE_LEN|0x80000000|0x100) 279/* Bits in the segment table entry */
291#define _KERNSEG_TABLE _KERNEL_SEG_TABLE_LEN 280#define _SEGMENT_ENTRY_ORIGIN 0x7fffffc0UL /* page table origin */
281#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
282#define _SEGMENT_ENTRY_COMMON 0x10 /* common segment bit */
283#define _SEGMENT_ENTRY_PTL 0x0f /* page table length */
292 284
293#define USER_STD_MASK 0x00000080UL 285#define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PTL)
286#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
294 287
295#else /* __s390x__ */ 288#else /* __s390x__ */
296 289
290/* Bits in the segment/region table address-space-control-element */
291#define _ASCE_ORIGIN ~0xfffUL/* segment table origin */
292#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */
293#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */
294#define _ASCE_SPACE_SWITCH 0x40 /* space switch event */
295#define _ASCE_REAL_SPACE 0x20 /* real space control */
296#define _ASCE_TYPE_MASK 0x0c /* asce table type mask */
297#define _ASCE_TYPE_REGION1 0x0c /* region first table type */
298#define _ASCE_TYPE_REGION2 0x08 /* region second table type */
299#define _ASCE_TYPE_REGION3 0x04 /* region third table type */
300#define _ASCE_TYPE_SEGMENT 0x00 /* segment table type */
301#define _ASCE_TABLE_LENGTH 0x03 /* region table length */
302
303/* Bits in the region table entry */
304#define _REGION_ENTRY_ORIGIN ~0xfffUL/* region/segment table origin */
305#define _REGION_ENTRY_INV 0x20 /* invalid region table entry */
306#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */
307#define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */
308#define _REGION_ENTRY_TYPE_R2 0x08 /* region second table type */
309#define _REGION_ENTRY_TYPE_R3 0x04 /* region third table type */
310#define _REGION_ENTRY_LENGTH 0x03 /* region third length */
311
312#define _REGION1_ENTRY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_LENGTH)
313#define _REGION1_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INV)
314#define _REGION2_ENTRY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH)
315#define _REGION2_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INV)
316#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
317#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV)
318
297/* Bits in the segment table entry */ 319/* Bits in the segment table entry */
298#define _PMD_ENTRY_INV 0x20 /* invalid segment table entry */ 320#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* segment table origin */
299#define _PMD_ENTRY 0x00 321#define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */
322#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
323
324#define _SEGMENT_ENTRY (0)
325#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
300 326
301/* Bits in the region third table entry */ 327#endif /* __s390x__ */
302#define _PGD_ENTRY_INV 0x20 /* invalid region table entry */
303#define _PGD_ENTRY 0x07
304 328
305/* 329/*
306 * User and kernel page directory 330 * A user page table pointer has the space-switch-event bit, the
331 * private-space-control bit and the storage-alteration-event-control
332 * bit set. A kernel page table pointer doesn't need them.
307 */ 333 */
308#define _REGION_THIRD 0x4 334#define _ASCE_USER_BITS (_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \
309#define _REGION_THIRD_LEN 0x3 335 _ASCE_ALT_EVENT)
310#define _REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN|0x40|0x100)
311#define _KERN_REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN)
312
313#define USER_STD_MASK 0x0000000000000080UL
314 336
315/* Bits in the storage key */ 337/* Bits int the storage key */
316#define _PAGE_CHANGED 0x02 /* HW changed bit */ 338#define _PAGE_CHANGED 0x02 /* HW changed bit */
317#define _PAGE_REFERENCED 0x04 /* HW referenced bit */ 339#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
318 340
319#endif /* __s390x__ */
320
321/* 341/*
322 * Page protection definitions. 342 * Page protection definitions.
323 */ 343 */
@@ -358,65 +378,38 @@ extern unsigned long vmalloc_end;
358#define __S111 PAGE_EX_RW 378#define __S111 PAGE_EX_RW
359 379
360#ifndef __s390x__ 380#ifndef __s390x__
361# define PMD_SHADOW_SHIFT 1 381# define PxD_SHADOW_SHIFT 1
362# define PGD_SHADOW_SHIFT 1
363#else /* __s390x__ */ 382#else /* __s390x__ */
364# define PMD_SHADOW_SHIFT 2 383# define PxD_SHADOW_SHIFT 2
365# define PGD_SHADOW_SHIFT 2
366#endif /* __s390x__ */ 384#endif /* __s390x__ */
367 385
368static inline struct page *get_shadow_page(struct page *page) 386static inline struct page *get_shadow_page(struct page *page)
369{ 387{
370 if (s390_noexec && !list_empty(&page->lru)) 388 if (s390_noexec && page->index)
371 return virt_to_page(page->lru.next); 389 return virt_to_page((void *)(addr_t) page->index);
372 return NULL;
373}
374
375static inline pte_t *get_shadow_pte(pte_t *ptep)
376{
377 unsigned long pteptr = (unsigned long) (ptep);
378
379 if (s390_noexec) {
380 unsigned long offset = pteptr & (PAGE_SIZE - 1);
381 void *addr = (void *) (pteptr ^ offset);
382 struct page *page = virt_to_page(addr);
383 if (!list_empty(&page->lru))
384 return (pte_t *) ((unsigned long) page->lru.next |
385 offset);
386 }
387 return NULL; 390 return NULL;
388} 391}
389 392
390static inline pmd_t *get_shadow_pmd(pmd_t *pmdp) 393static inline void *get_shadow_pte(void *table)
391{ 394{
392 unsigned long pmdptr = (unsigned long) (pmdp); 395 unsigned long addr, offset;
396 struct page *page;
393 397
394 if (s390_noexec) { 398 addr = (unsigned long) table;
395 unsigned long offset = pmdptr & 399 offset = addr & (PAGE_SIZE - 1);
396 ((PAGE_SIZE << PMD_SHADOW_SHIFT) - 1); 400 page = virt_to_page((void *)(addr ^ offset));
397 void *addr = (void *) (pmdptr ^ offset); 401 return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
398 struct page *page = virt_to_page(addr);
399 if (!list_empty(&page->lru))
400 return (pmd_t *) ((unsigned long) page->lru.next |
401 offset);
402 }
403 return NULL;
404} 402}
405 403
406static inline pgd_t *get_shadow_pgd(pgd_t *pgdp) 404static inline void *get_shadow_table(void *table)
407{ 405{
408 unsigned long pgdptr = (unsigned long) (pgdp); 406 unsigned long addr, offset;
407 struct page *page;
409 408
410 if (s390_noexec) { 409 addr = (unsigned long) table;
411 unsigned long offset = pgdptr & 410 offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1);
412 ((PAGE_SIZE << PGD_SHADOW_SHIFT) - 1); 411 page = virt_to_page((void *)(addr ^ offset));
413 void *addr = (void *) (pgdptr ^ offset); 412 return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
414 struct page *page = virt_to_page(addr);
415 if (!list_empty(&page->lru))
416 return (pgd_t *) ((unsigned long) page->lru.next |
417 offset);
418 }
419 return NULL;
420} 413}
421 414
422/* 415/*
@@ -424,7 +417,8 @@ static inline pgd_t *get_shadow_pgd(pgd_t *pgdp)
424 * within a page table are directly modified. Thus, the following 417 * within a page table are directly modified. Thus, the following
425 * hook is made available. 418 * hook is made available.
426 */ 419 */
427static inline void set_pte(pte_t *pteptr, pte_t pteval) 420static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
421 pte_t *pteptr, pte_t pteval)
428{ 422{
429 pte_t *shadow_pte = get_shadow_pte(pteptr); 423 pte_t *shadow_pte = get_shadow_pte(pteptr);
430 424
@@ -437,7 +431,6 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
437 pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY; 431 pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
438 } 432 }
439} 433}
440#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
441 434
442/* 435/*
443 * pgd/pmd/pte query functions 436 * pgd/pmd/pte query functions
@@ -448,47 +441,50 @@ static inline int pgd_present(pgd_t pgd) { return 1; }
448static inline int pgd_none(pgd_t pgd) { return 0; } 441static inline int pgd_none(pgd_t pgd) { return 0; }
449static inline int pgd_bad(pgd_t pgd) { return 0; } 442static inline int pgd_bad(pgd_t pgd) { return 0; }
450 443
451static inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; } 444static inline int pud_present(pud_t pud) { return 1; }
452static inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; } 445static inline int pud_none(pud_t pud) { return 0; }
453static inline int pmd_bad(pmd_t pmd) 446static inline int pud_bad(pud_t pud) { return 0; }
454{
455 return (pmd_val(pmd) & (~PAGE_MASK & ~_PAGE_TABLE_INV)) != _PAGE_TABLE;
456}
457 447
458#else /* __s390x__ */ 448#else /* __s390x__ */
459 449
460static inline int pgd_present(pgd_t pgd) 450static inline int pgd_present(pgd_t pgd) { return 1; }
451static inline int pgd_none(pgd_t pgd) { return 0; }
452static inline int pgd_bad(pgd_t pgd) { return 0; }
453
454static inline int pud_present(pud_t pud)
461{ 455{
462 return (pgd_val(pgd) & ~PAGE_MASK) == _PGD_ENTRY; 456 return pud_val(pud) & _REGION_ENTRY_ORIGIN;
463} 457}
464 458
465static inline int pgd_none(pgd_t pgd) 459static inline int pud_none(pud_t pud)
466{ 460{
467 return pgd_val(pgd) & _PGD_ENTRY_INV; 461 return pud_val(pud) & _REGION_ENTRY_INV;
468} 462}
469 463
470static inline int pgd_bad(pgd_t pgd) 464static inline int pud_bad(pud_t pud)
471{ 465{
472 return (pgd_val(pgd) & (~PAGE_MASK & ~_PGD_ENTRY_INV)) != _PGD_ENTRY; 466 unsigned long mask = ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV;
467 return (pud_val(pud) & mask) != _REGION3_ENTRY;
473} 468}
474 469
470#endif /* __s390x__ */
471
475static inline int pmd_present(pmd_t pmd) 472static inline int pmd_present(pmd_t pmd)
476{ 473{
477 return (pmd_val(pmd) & ~PAGE_MASK) == _PMD_ENTRY; 474 return pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN;
478} 475}
479 476
480static inline int pmd_none(pmd_t pmd) 477static inline int pmd_none(pmd_t pmd)
481{ 478{
482 return pmd_val(pmd) & _PMD_ENTRY_INV; 479 return pmd_val(pmd) & _SEGMENT_ENTRY_INV;
483} 480}
484 481
485static inline int pmd_bad(pmd_t pmd) 482static inline int pmd_bad(pmd_t pmd)
486{ 483{
487 return (pmd_val(pmd) & (~PAGE_MASK & ~_PMD_ENTRY_INV)) != _PMD_ENTRY; 484 unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INV;
485 return (pmd_val(pmd) & mask) != _SEGMENT_ENTRY;
488} 486}
489 487
490#endif /* __s390x__ */
491
492static inline int pte_none(pte_t pte) 488static inline int pte_none(pte_t pte)
493{ 489{
494 return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT); 490 return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT);
@@ -508,7 +504,8 @@ static inline int pte_file(pte_t pte)
508 return (pte_val(pte) & mask) == _PAGE_TYPE_FILE; 504 return (pte_val(pte) & mask) == _PAGE_TYPE_FILE;
509} 505}
510 506
511#define pte_same(a,b) (pte_val(a) == pte_val(b)) 507#define __HAVE_ARCH_PTE_SAME
508#define pte_same(a,b) (pte_val(a) == pte_val(b))
512 509
513/* 510/*
514 * query functions pte_write/pte_dirty/pte_young only work if 511 * query functions pte_write/pte_dirty/pte_young only work if
@@ -543,58 +540,52 @@ static inline int pte_young(pte_t pte)
543 540
544#ifndef __s390x__ 541#ifndef __s390x__
545 542
546static inline void pgd_clear(pgd_t * pgdp) { } 543#define pgd_clear(pgd) do { } while (0)
544#define pud_clear(pud) do { } while (0)
547 545
548static inline void pmd_clear_kernel(pmd_t * pmdp) 546static inline void pmd_clear_kernel(pmd_t * pmdp)
549{ 547{
550 pmd_val(pmdp[0]) = _PAGE_TABLE_INV; 548 pmd_val(pmdp[0]) = _SEGMENT_ENTRY_EMPTY;
551 pmd_val(pmdp[1]) = _PAGE_TABLE_INV; 549 pmd_val(pmdp[1]) = _SEGMENT_ENTRY_EMPTY;
552 pmd_val(pmdp[2]) = _PAGE_TABLE_INV; 550 pmd_val(pmdp[2]) = _SEGMENT_ENTRY_EMPTY;
553 pmd_val(pmdp[3]) = _PAGE_TABLE_INV; 551 pmd_val(pmdp[3]) = _SEGMENT_ENTRY_EMPTY;
554}
555
556static inline void pmd_clear(pmd_t * pmdp)
557{
558 pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
559
560 pmd_clear_kernel(pmdp);
561 if (shadow_pmd)
562 pmd_clear_kernel(shadow_pmd);
563} 552}
564 553
565#else /* __s390x__ */ 554#else /* __s390x__ */
566 555
567static inline void pgd_clear_kernel(pgd_t * pgdp) 556#define pgd_clear(pgd) do { } while (0)
557
558static inline void pud_clear_kernel(pud_t *pud)
568{ 559{
569 pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; 560 pud_val(*pud) = _REGION3_ENTRY_EMPTY;
570} 561}
571 562
572static inline void pgd_clear(pgd_t * pgdp) 563static inline void pud_clear(pud_t * pud)
573{ 564{
574 pgd_t *shadow_pgd = get_shadow_pgd(pgdp); 565 pud_t *shadow = get_shadow_table(pud);
575 566
576 pgd_clear_kernel(pgdp); 567 pud_clear_kernel(pud);
577 if (shadow_pgd) 568 if (shadow)
578 pgd_clear_kernel(shadow_pgd); 569 pud_clear_kernel(shadow);
579} 570}
580 571
581static inline void pmd_clear_kernel(pmd_t * pmdp) 572static inline void pmd_clear_kernel(pmd_t * pmdp)
582{ 573{
583 pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; 574 pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY;
584 pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; 575 pmd_val1(*pmdp) = _SEGMENT_ENTRY_EMPTY;
585} 576}
586 577
578#endif /* __s390x__ */
579
587static inline void pmd_clear(pmd_t * pmdp) 580static inline void pmd_clear(pmd_t * pmdp)
588{ 581{
589 pmd_t *shadow_pmd = get_shadow_pmd(pmdp); 582 pmd_t *shadow_pmd = get_shadow_table(pmdp);
590 583
591 pmd_clear_kernel(pmdp); 584 pmd_clear_kernel(pmdp);
592 if (shadow_pmd) 585 if (shadow_pmd)
593 pmd_clear_kernel(shadow_pmd); 586 pmd_clear_kernel(shadow_pmd);
594} 587}
595 588
596#endif /* __s390x__ */
597
598static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 589static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
599{ 590{
600 pte_t *shadow_pte = get_shadow_pte(ptep); 591 pte_t *shadow_pte = get_shadow_pte(ptep);
@@ -663,24 +654,19 @@ static inline pte_t pte_mkyoung(pte_t pte)
663 return pte; 654 return pte;
664} 655}
665 656
666static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) 657#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
658static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
659 unsigned long addr, pte_t *ptep)
667{ 660{
668 return 0; 661 return 0;
669} 662}
670 663
671static inline int 664#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
672ptep_clear_flush_young(struct vm_area_struct *vma, 665static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
673 unsigned long address, pte_t *ptep) 666 unsigned long address, pte_t *ptep)
674{ 667{
675 /* No need to flush TLB; bits are in storage key */ 668 /* No need to flush TLB; bits are in storage key */
676 return ptep_test_and_clear_young(vma, address, ptep); 669 return 0;
677}
678
679static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
680{
681 pte_t pte = *ptep;
682 pte_clear(mm, addr, ptep);
683 return pte;
684} 670}
685 671
686static inline void __ptep_ipte(unsigned long address, pte_t *ptep) 672static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
@@ -709,6 +695,32 @@ static inline void ptep_invalidate(unsigned long address, pte_t *ptep)
709 __ptep_ipte(address, ptep); 695 __ptep_ipte(address, ptep);
710} 696}
711 697
698/*
699 * This is hard to understand. ptep_get_and_clear and ptep_clear_flush
700 * both clear the TLB for the unmapped pte. The reason is that
701 * ptep_get_and_clear is used in common code (e.g. change_pte_range)
702 * to modify an active pte. The sequence is
703 * 1) ptep_get_and_clear
704 * 2) set_pte_at
705 * 3) flush_tlb_range
706 * On s390 the tlb needs to get flushed with the modification of the pte
707 * if the pte is active. The only way how this can be implemented is to
708 * have ptep_get_and_clear do the tlb flush. In exchange flush_tlb_range
709 * is a nop.
710 */
711#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
712#define ptep_get_and_clear(__mm, __address, __ptep) \
713({ \
714 pte_t __pte = *(__ptep); \
715 if (atomic_read(&(__mm)->mm_users) > 1 || \
716 (__mm) != current->active_mm) \
717 ptep_invalidate(__address, __ptep); \
718 else \
719 pte_clear((__mm), (__address), (__ptep)); \
720 __pte; \
721})
722
723#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
712static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, 724static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
713 unsigned long address, pte_t *ptep) 725 unsigned long address, pte_t *ptep)
714{ 726{
@@ -717,12 +729,40 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
717 return pte; 729 return pte;
718} 730}
719 731
720static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 732/*
733 * The batched pte unmap code uses ptep_get_and_clear_full to clear the
734 * ptes. Here an optimization is possible. tlb_gather_mmu flushes all
735 * tlbs of an mm if it can guarantee that the ptes of the mm_struct
736 * cannot be accessed while the batched unmap is running. In this case
737 * full==1 and a simple pte_clear is enough. See tlb.h.
738 */
739#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
740static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
741 unsigned long addr,
742 pte_t *ptep, int full)
721{ 743{
722 pte_t old_pte = *ptep; 744 pte_t pte = *ptep;
723 set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); 745
746 if (full)
747 pte_clear(mm, addr, ptep);
748 else
749 ptep_invalidate(addr, ptep);
750 return pte;
724} 751}
725 752
753#define __HAVE_ARCH_PTEP_SET_WRPROTECT
754#define ptep_set_wrprotect(__mm, __addr, __ptep) \
755({ \
756 pte_t __pte = *(__ptep); \
757 if (pte_write(__pte)) { \
758 if (atomic_read(&(__mm)->mm_users) > 1 || \
759 (__mm) != current->active_mm) \
760 ptep_invalidate(__addr, __ptep); \
761 set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte)); \
762 } \
763})
764
765#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
726#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ 766#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
727({ \ 767({ \
728 int __changed = !pte_same(*(__ptep), __entry); \ 768 int __changed = !pte_same(*(__ptep), __entry); \
@@ -740,11 +780,13 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
740 * should therefore only be called if it is not mapped in any 780 * should therefore only be called if it is not mapped in any
741 * address space. 781 * address space.
742 */ 782 */
783#define __HAVE_ARCH_PAGE_TEST_DIRTY
743static inline int page_test_dirty(struct page *page) 784static inline int page_test_dirty(struct page *page)
744{ 785{
745 return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0; 786 return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0;
746} 787}
747 788
789#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
748static inline void page_clear_dirty(struct page *page) 790static inline void page_clear_dirty(struct page *page)
749{ 791{
750 page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY); 792 page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY);
@@ -753,6 +795,7 @@ static inline void page_clear_dirty(struct page *page)
753/* 795/*
754 * Test and clear referenced bit in storage key. 796 * Test and clear referenced bit in storage key.
755 */ 797 */
798#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
756static inline int page_test_and_clear_young(struct page *page) 799static inline int page_test_and_clear_young(struct page *page)
757{ 800{
758 unsigned long physpage = page_to_phys(page); 801 unsigned long physpage = page_to_phys(page);
@@ -784,63 +827,48 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
784 return mk_pte_phys(physpage, pgprot); 827 return mk_pte_phys(physpage, pgprot);
785} 828}
786 829
787static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) 830#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
788{ 831#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
789 unsigned long physpage = __pa((pfn) << PAGE_SHIFT); 832#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
790 833#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
791 return mk_pte_phys(physpage, pgprot);
792}
793
794#ifdef __s390x__
795
796static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
797{
798 unsigned long physpage = __pa((pfn) << PAGE_SHIFT);
799
800 return __pmd(physpage + pgprot_val(pgprot));
801}
802
803#endif /* __s390x__ */
804
805#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
806#define pte_page(x) pfn_to_page(pte_pfn(x))
807 834
808#define pmd_page_vaddr(pmd) (pmd_val(pmd) & PAGE_MASK) 835#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
836#define pgd_offset_k(address) pgd_offset(&init_mm, address)
809 837
810#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT) 838#ifndef __s390x__
811 839
812#define pgd_page_vaddr(pgd) (pgd_val(pgd) & PAGE_MASK) 840#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
841#define pud_deref(pmd) ({ BUG(); 0UL; })
842#define pgd_deref(pmd) ({ BUG(); 0UL; })
813 843
814#define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT) 844#define pud_offset(pgd, address) ((pud_t *) pgd)
845#define pmd_offset(pud, address) ((pmd_t *) pud + pmd_index(address))
815 846
816/* to find an entry in a page-table-directory */ 847#else /* __s390x__ */
817#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
818#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
819 848
820/* to find an entry in a kernel page-table-directory */ 849#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
821#define pgd_offset_k(address) pgd_offset(&init_mm, address) 850#define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN)
851#define pgd_deref(pgd) ({ BUG(); 0UL; })
822 852
823#ifndef __s390x__ 853#define pud_offset(pgd, address) ((pud_t *) pgd)
824 854
825/* Find an entry in the second-level page table.. */ 855static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
826static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
827{ 856{
828 return (pmd_t *) dir; 857 pmd_t *pmd = (pmd_t *) pud_deref(*pud);
858 return pmd + pmd_index(address);
829} 859}
830 860
831#else /* __s390x__ */ 861#endif /* __s390x__ */
832 862
833/* Find an entry in the second-level page table.. */ 863#define pfn_pte(pfn,pgprot) mk_pte_phys(__pa((pfn) << PAGE_SHIFT),(pgprot))
834#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) 864#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
835#define pmd_offset(dir,addr) \ 865#define pte_page(x) pfn_to_page(pte_pfn(x))
836 ((pmd_t *) pgd_page_vaddr(*(dir)) + pmd_index(addr))
837 866
838#endif /* __s390x__ */ 867#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
839 868
840/* Find an entry in the third-level page table.. */ 869/* Find an entry in the lowest level page table.. */
841#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) 870#define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
842#define pte_offset_kernel(pmd, address) \ 871#define pte_offset_kernel(pmd, address) pte_offset(pmd,address)
843 ((pte_t *) pmd_page_vaddr(*(pmd)) + pte_index(address))
844#define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) 872#define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
845#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address) 873#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
846#define pte_unmap(pte) do { } while (0) 874#define pte_unmap(pte) do { } while (0)
@@ -930,17 +958,6 @@ extern int remove_shared_memory(unsigned long start, unsigned long size);
930#define __HAVE_ARCH_MEMMAP_INIT 958#define __HAVE_ARCH_MEMMAP_INIT
931extern void memmap_init(unsigned long, int, unsigned long, unsigned long); 959extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
932 960
933#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
934#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
935#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
936#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
937#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
938#define __HAVE_ARCH_PTEP_SET_WRPROTECT
939#define __HAVE_ARCH_PTE_SAME
940#define __HAVE_ARCH_PAGE_TEST_DIRTY
941#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
942#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
943#include <asm-generic/pgtable.h> 961#include <asm-generic/pgtable.h>
944 962
945#endif /* _S390_PAGE_H */ 963#endif /* _S390_PAGE_H */
946