diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-02-09 12:24:37 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-02-09 12:24:41 -0500 |
commit | 6252d702c5311ce916caf75ed82e5c8245171c92 (patch) | |
tree | 3490f27b5f888ff2c1ec915d4e7201000f37a771 /include/asm-s390/pgtable.h | |
parent | 5a216a20837c5f5fa1ca4b8ae8991ffd96b08e6f (diff) |
[S390] dynamic page tables.
Add support for different number of page table levels dependent
on the highest address used for a process. This will cause a 31 bit
process to use a two level page table instead of the four level page
table that is the default after the pud has been introduced. Likewise
a normal 64 bit process will use three levels instead of four. Only
if a process runs out of the 4 tera bytes which can be addressed with
a three level page table the fourth level is dynamically added. Then
the process can use up to 8 peta byte.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'include/asm-s390/pgtable.h')
-rw-r--r-- | include/asm-s390/pgtable.h | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 8f473a718111..65154dc9a9e5 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h | |||
@@ -421,36 +421,54 @@ static inline int pud_bad(pud_t pud) { return 0; } | |||
421 | 421 | ||
422 | static inline int pgd_present(pgd_t pgd) | 422 | static inline int pgd_present(pgd_t pgd) |
423 | { | 423 | { |
424 | if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R2) | ||
425 | return 1; | ||
424 | return (pgd_val(pgd) & _REGION_ENTRY_ORIGIN) != 0UL; | 426 | return (pgd_val(pgd) & _REGION_ENTRY_ORIGIN) != 0UL; |
425 | } | 427 | } |
426 | 428 | ||
427 | static inline int pgd_none(pgd_t pgd) | 429 | static inline int pgd_none(pgd_t pgd) |
428 | { | 430 | { |
431 | if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R2) | ||
432 | return 0; | ||
429 | return (pgd_val(pgd) & _REGION_ENTRY_INV) != 0UL; | 433 | return (pgd_val(pgd) & _REGION_ENTRY_INV) != 0UL; |
430 | } | 434 | } |
431 | 435 | ||
432 | static inline int pgd_bad(pgd_t pgd) | 436 | static inline int pgd_bad(pgd_t pgd) |
433 | { | 437 | { |
438 | /* | ||
439 | * With dynamic page table levels the pgd can be a region table | ||
440 | * entry or a segment table entry. Check for the bit that are | ||
441 | * invalid for either table entry. | ||
442 | */ | ||
434 | unsigned long mask = | 443 | unsigned long mask = |
435 | ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV & | 444 | ~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INV & |
436 | ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH; | 445 | ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH; |
437 | return (pgd_val(pgd) & mask) != 0; | 446 | return (pgd_val(pgd) & mask) != 0; |
438 | } | 447 | } |
439 | 448 | ||
440 | static inline int pud_present(pud_t pud) | 449 | static inline int pud_present(pud_t pud) |
441 | { | 450 | { |
451 | if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3) | ||
452 | return 1; | ||
442 | return (pud_val(pud) & _REGION_ENTRY_ORIGIN) != 0UL; | 453 | return (pud_val(pud) & _REGION_ENTRY_ORIGIN) != 0UL; |
443 | } | 454 | } |
444 | 455 | ||
445 | static inline int pud_none(pud_t pud) | 456 | static inline int pud_none(pud_t pud) |
446 | { | 457 | { |
458 | if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3) | ||
459 | return 0; | ||
447 | return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL; | 460 | return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL; |
448 | } | 461 | } |
449 | 462 | ||
450 | static inline int pud_bad(pud_t pud) | 463 | static inline int pud_bad(pud_t pud) |
451 | { | 464 | { |
465 | /* | ||
466 | * With dynamic page table levels the pud can be a region table | ||
467 | * entry or a segment table entry. Check for the bit that are | ||
468 | * invalid for either table entry. | ||
469 | */ | ||
452 | unsigned long mask = | 470 | unsigned long mask = |
453 | ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV & | 471 | ~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INV & |
454 | ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH; | 472 | ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH; |
455 | return (pud_val(pud) & mask) != 0; | 473 | return (pud_val(pud) & mask) != 0; |
456 | } | 474 | } |
@@ -535,7 +553,8 @@ static inline int pte_young(pte_t pte) | |||
535 | 553 | ||
536 | static inline void pgd_clear_kernel(pgd_t * pgd) | 554 | static inline void pgd_clear_kernel(pgd_t * pgd) |
537 | { | 555 | { |
538 | pgd_val(*pgd) = _REGION2_ENTRY_EMPTY; | 556 | if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2) |
557 | pgd_val(*pgd) = _REGION2_ENTRY_EMPTY; | ||
539 | } | 558 | } |
540 | 559 | ||
541 | static inline void pgd_clear(pgd_t * pgd) | 560 | static inline void pgd_clear(pgd_t * pgd) |
@@ -549,10 +568,11 @@ static inline void pgd_clear(pgd_t * pgd) | |||
549 | 568 | ||
550 | static inline void pud_clear_kernel(pud_t *pud) | 569 | static inline void pud_clear_kernel(pud_t *pud) |
551 | { | 570 | { |
552 | pud_val(*pud) = _REGION3_ENTRY_EMPTY; | 571 | if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) |
572 | pud_val(*pud) = _REGION3_ENTRY_EMPTY; | ||
553 | } | 573 | } |
554 | 574 | ||
555 | static inline void pud_clear(pud_t * pud) | 575 | static inline void pud_clear(pud_t *pud) |
556 | { | 576 | { |
557 | pud_t *shadow = get_shadow_table(pud); | 577 | pud_t *shadow = get_shadow_table(pud); |
558 | 578 | ||
@@ -841,13 +861,17 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot) | |||
841 | 861 | ||
842 | static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) | 862 | static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) |
843 | { | 863 | { |
844 | pud_t *pud = (pud_t *) pgd_deref(*pgd); | 864 | pud_t *pud = (pud_t *) pgd; |
865 | if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2) | ||
866 | pud = (pud_t *) pgd_deref(*pgd); | ||
845 | return pud + pud_index(address); | 867 | return pud + pud_index(address); |
846 | } | 868 | } |
847 | 869 | ||
848 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) | 870 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) |
849 | { | 871 | { |
850 | pmd_t *pmd = (pmd_t *) pud_deref(*pud); | 872 | pmd_t *pmd = (pmd_t *) pud; |
873 | if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) | ||
874 | pmd = (pmd_t *) pud_deref(*pud); | ||
851 | return pmd + pmd_index(address); | 875 | return pmd + pmd_index(address); |
852 | } | 876 | } |
853 | 877 | ||