aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-s390/pgtable.h
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2008-02-09 12:24:37 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-02-09 12:24:41 -0500
commit6252d702c5311ce916caf75ed82e5c8245171c92 (patch)
tree3490f27b5f888ff2c1ec915d4e7201000f37a771 /include/asm-s390/pgtable.h
parent5a216a20837c5f5fa1ca4b8ae8991ffd96b08e6f (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.h38
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
422static inline int pgd_present(pgd_t pgd) 422static 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
427static inline int pgd_none(pgd_t pgd) 429static 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
432static inline int pgd_bad(pgd_t pgd) 436static 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
440static inline int pud_present(pud_t pud) 449static 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
445static inline int pud_none(pud_t pud) 456static 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
450static inline int pud_bad(pud_t pud) 463static 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
536static inline void pgd_clear_kernel(pgd_t * pgd) 554static 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
541static inline void pgd_clear(pgd_t * pgd) 560static inline void pgd_clear(pgd_t * pgd)
@@ -549,10 +568,11 @@ static inline void pgd_clear(pgd_t * pgd)
549 568
550static inline void pud_clear_kernel(pud_t *pud) 569static 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
555static inline void pud_clear(pud_t * pud) 575static 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
842static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) 862static 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
848static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) 870static 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