diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-02-09 12:24:36 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-02-09 12:24:40 -0500 |
commit | 5a216a20837c5f5fa1ca4b8ae8991ffd96b08e6f (patch) | |
tree | dde54e28497e920fa460cc95dadb6b38f1b2dbe0 /include | |
parent | 146e4b3c8b92071b18f0b2e6f47165bad4f9e825 (diff) |
[S390] Add four level page tables for CONFIG_64BIT=y.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-s390/elf.h | 9 | ||||
-rw-r--r-- | include/asm-s390/mmu_context.h | 2 | ||||
-rw-r--r-- | include/asm-s390/pgalloc.h | 29 | ||||
-rw-r--r-- | include/asm-s390/pgtable.h | 57 | ||||
-rw-r--r-- | include/asm-s390/processor.h | 24 | ||||
-rw-r--r-- | include/asm-s390/tlb.h | 33 |
6 files changed, 109 insertions, 45 deletions
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h index 8181ca5b98f4..b760cd4de385 100644 --- a/include/asm-s390/elf.h +++ b/include/asm-s390/elf.h | |||
@@ -138,14 +138,7 @@ typedef s390_regs elf_gregset_t; | |||
138 | use of this is to invoke "./ld.so someprog" to test out a new version of | 138 | use of this is to invoke "./ld.so someprog" to test out a new version of |
139 | the loader. We need to make sure that it is out of the way of the program | 139 | the loader. We need to make sure that it is out of the way of the program |
140 | that it will "exec", and that there is sufficient room for the brk. */ | 140 | that it will "exec", and that there is sufficient room for the brk. */ |
141 | 141 | #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) | |
142 | #ifndef __s390x__ | ||
143 | #define ELF_ET_DYN_BASE ((TASK_SIZE & 0x80000000) \ | ||
144 | ? TASK_SIZE / 3 * 2 \ | ||
145 | : 2 * TASK_SIZE / 3) | ||
146 | #else /* __s390x__ */ | ||
147 | #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) | ||
148 | #endif /* __s390x__ */ | ||
149 | 142 | ||
150 | /* Wow, the "main" arch needs arch dependent functions too.. :) */ | 143 | /* Wow, the "main" arch needs arch dependent functions too.. :) */ |
151 | 144 | ||
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h index 3eaac5efc632..b3ea3e199921 100644 --- a/include/asm-s390/mmu_context.h +++ b/include/asm-s390/mmu_context.h | |||
@@ -18,7 +18,7 @@ static inline int init_new_context(struct task_struct *tsk, | |||
18 | { | 18 | { |
19 | mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS; | 19 | mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS; |
20 | #ifdef CONFIG_64BIT | 20 | #ifdef CONFIG_64BIT |
21 | mm->context.asce_bits |= _ASCE_TYPE_REGION3; | 21 | mm->context.asce_bits |= _ASCE_TYPE_REGION2; |
22 | #endif | 22 | #endif |
23 | mm->context.noexec = s390_noexec; | 23 | mm->context.noexec = s390_noexec; |
24 | return 0; | 24 | return 0; |
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h index af4aee856df3..cc47dd65a499 100644 --- a/include/asm-s390/pgalloc.h +++ b/include/asm-s390/pgalloc.h | |||
@@ -73,11 +73,17 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm) | |||
73 | 73 | ||
74 | static inline unsigned long pgd_entry_type(struct mm_struct *mm) | 74 | static inline unsigned long pgd_entry_type(struct mm_struct *mm) |
75 | { | 75 | { |
76 | return _REGION3_ENTRY_EMPTY; | 76 | return _REGION2_ENTRY_EMPTY; |
77 | } | 77 | } |
78 | 78 | ||
79 | #define pud_alloc_one(mm,address) ({ BUG(); ((pud_t *)2); }) | 79 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) |
80 | #define pud_free(mm, x) do { } while (0) | 80 | { |
81 | unsigned long *table = crst_table_alloc(mm, mm->context.noexec); | ||
82 | if (table) | ||
83 | crst_table_init(table, _REGION3_ENTRY_EMPTY); | ||
84 | return (pud_t *) table; | ||
85 | } | ||
86 | #define pud_free(mm, pud) crst_table_free(mm, (unsigned long *) pud) | ||
81 | 87 | ||
82 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) | 88 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) |
83 | { | 89 | { |
@@ -88,8 +94,21 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) | |||
88 | } | 94 | } |
89 | #define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd) | 95 | #define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd) |
90 | 96 | ||
91 | #define pgd_populate(mm, pgd, pud) BUG() | 97 | static inline void pgd_populate_kernel(struct mm_struct *mm, |
92 | #define pgd_populate_kernel(mm, pgd, pud) BUG() | 98 | pgd_t *pgd, pud_t *pud) |
99 | { | ||
100 | pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud); | ||
101 | } | ||
102 | |||
103 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) | ||
104 | { | ||
105 | pgd_t *shadow_pgd = get_shadow_table(pgd); | ||
106 | pud_t *shadow_pud = get_shadow_table(pud); | ||
107 | |||
108 | if (shadow_pgd && shadow_pud) | ||
109 | pgd_populate_kernel(mm, shadow_pgd, shadow_pud); | ||
110 | pgd_populate_kernel(mm, pgd, pud); | ||
111 | } | ||
93 | 112 | ||
94 | static inline void pud_populate_kernel(struct mm_struct *mm, | 113 | static inline void pud_populate_kernel(struct mm_struct *mm, |
95 | pud_t *pud, pmd_t *pmd) | 114 | pud_t *pud, pmd_t *pmd) |
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 4fc937711482..8f473a718111 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h | |||
@@ -63,15 +63,15 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
63 | #else /* __s390x__ */ | 63 | #else /* __s390x__ */ |
64 | # define PMD_SHIFT 20 | 64 | # define PMD_SHIFT 20 |
65 | # define PUD_SHIFT 31 | 65 | # define PUD_SHIFT 31 |
66 | # define PGDIR_SHIFT 31 | 66 | # define PGDIR_SHIFT 42 |
67 | #endif /* __s390x__ */ | 67 | #endif /* __s390x__ */ |
68 | 68 | ||
69 | #define PMD_SIZE (1UL << PMD_SHIFT) | 69 | #define PMD_SIZE (1UL << PMD_SHIFT) |
70 | #define PMD_MASK (~(PMD_SIZE-1)) | 70 | #define PMD_MASK (~(PMD_SIZE-1)) |
71 | #define PUD_SIZE (1UL << PUD_SHIFT) | 71 | #define PUD_SIZE (1UL << PUD_SHIFT) |
72 | #define PUD_MASK (~(PUD_SIZE-1)) | 72 | #define PUD_MASK (~(PUD_SIZE-1)) |
73 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | 73 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) |
74 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | 74 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) |
75 | 75 | ||
76 | /* | 76 | /* |
77 | * entries per page directory level: the S390 is two-level, so | 77 | * entries per page directory level: the S390 is two-level, so |
@@ -82,10 +82,11 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
82 | #define PTRS_PER_PTE 256 | 82 | #define PTRS_PER_PTE 256 |
83 | #ifndef __s390x__ | 83 | #ifndef __s390x__ |
84 | #define PTRS_PER_PMD 1 | 84 | #define PTRS_PER_PMD 1 |
85 | #define PTRS_PER_PUD 1 | ||
85 | #else /* __s390x__ */ | 86 | #else /* __s390x__ */ |
86 | #define PTRS_PER_PMD 2048 | 87 | #define PTRS_PER_PMD 2048 |
88 | #define PTRS_PER_PUD 2048 | ||
87 | #endif /* __s390x__ */ | 89 | #endif /* __s390x__ */ |
88 | #define PTRS_PER_PUD 1 | ||
89 | #define PTRS_PER_PGD 2048 | 90 | #define PTRS_PER_PGD 2048 |
90 | 91 | ||
91 | #define FIRST_USER_ADDRESS 0 | 92 | #define FIRST_USER_ADDRESS 0 |
@@ -418,9 +419,23 @@ static inline int pud_bad(pud_t pud) { return 0; } | |||
418 | 419 | ||
419 | #else /* __s390x__ */ | 420 | #else /* __s390x__ */ |
420 | 421 | ||
421 | static inline int pgd_present(pgd_t pgd) { return 1; } | 422 | static inline int pgd_present(pgd_t pgd) |
422 | static inline int pgd_none(pgd_t pgd) { return 0; } | 423 | { |
423 | static inline int pgd_bad(pgd_t pgd) { return 0; } | 424 | return (pgd_val(pgd) & _REGION_ENTRY_ORIGIN) != 0UL; |
425 | } | ||
426 | |||
427 | static inline int pgd_none(pgd_t pgd) | ||
428 | { | ||
429 | return (pgd_val(pgd) & _REGION_ENTRY_INV) != 0UL; | ||
430 | } | ||
431 | |||
432 | static inline int pgd_bad(pgd_t pgd) | ||
433 | { | ||
434 | unsigned long mask = | ||
435 | ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV & | ||
436 | ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH; | ||
437 | return (pgd_val(pgd) & mask) != 0; | ||
438 | } | ||
424 | 439 | ||
425 | static inline int pud_present(pud_t pud) | 440 | static inline int pud_present(pud_t pud) |
426 | { | 441 | { |
@@ -434,8 +449,10 @@ static inline int pud_none(pud_t pud) | |||
434 | 449 | ||
435 | static inline int pud_bad(pud_t pud) | 450 | static inline int pud_bad(pud_t pud) |
436 | { | 451 | { |
437 | unsigned long mask = ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV; | 452 | unsigned long mask = |
438 | return (pud_val(pud) & mask) != _REGION3_ENTRY; | 453 | ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV & |
454 | ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH; | ||
455 | return (pud_val(pud) & mask) != 0; | ||
439 | } | 456 | } |
440 | 457 | ||
441 | #endif /* __s390x__ */ | 458 | #endif /* __s390x__ */ |
@@ -516,7 +533,19 @@ static inline int pte_young(pte_t pte) | |||
516 | 533 | ||
517 | #else /* __s390x__ */ | 534 | #else /* __s390x__ */ |
518 | 535 | ||
519 | #define pgd_clear(pgd) do { } while (0) | 536 | static inline void pgd_clear_kernel(pgd_t * pgd) |
537 | { | ||
538 | pgd_val(*pgd) = _REGION2_ENTRY_EMPTY; | ||
539 | } | ||
540 | |||
541 | static inline void pgd_clear(pgd_t * pgd) | ||
542 | { | ||
543 | pgd_t *shadow = get_shadow_table(pgd); | ||
544 | |||
545 | pgd_clear_kernel(pgd); | ||
546 | if (shadow) | ||
547 | pgd_clear_kernel(shadow); | ||
548 | } | ||
520 | 549 | ||
521 | static inline void pud_clear_kernel(pud_t *pud) | 550 | static inline void pud_clear_kernel(pud_t *pud) |
522 | { | 551 | { |
@@ -808,9 +837,13 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot) | |||
808 | 837 | ||
809 | #define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) | 838 | #define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) |
810 | #define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN) | 839 | #define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN) |
811 | #define pgd_deref(pgd) ({ BUG(); 0UL; }) | 840 | #define pgd_deref(pgd) (pgd_val(pgd) & _REGION_ENTRY_ORIGIN) |
812 | 841 | ||
813 | #define pud_offset(pgd, address) ((pud_t *) pgd) | 842 | static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) |
843 | { | ||
844 | pud_t *pud = (pud_t *) pgd_deref(*pgd); | ||
845 | return pud + pud_index(address); | ||
846 | } | ||
814 | 847 | ||
815 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) | 848 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) |
816 | { | 849 | { |
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index e8785634cbdb..5a21f457d583 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h | |||
@@ -64,24 +64,28 @@ extern int get_cpu_capability(unsigned int *); | |||
64 | */ | 64 | */ |
65 | #ifndef __s390x__ | 65 | #ifndef __s390x__ |
66 | 66 | ||
67 | # define TASK_SIZE (0x80000000UL) | 67 | #define TASK_SIZE (1UL << 31) |
68 | # define TASK_UNMAPPED_BASE (TASK_SIZE / 2) | 68 | #define TASK_UNMAPPED_BASE (1UL << 30) |
69 | # define DEFAULT_TASK_SIZE (0x80000000UL) | ||
70 | 69 | ||
71 | #else /* __s390x__ */ | 70 | #else /* __s390x__ */ |
72 | 71 | ||
73 | # define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk, TIF_31BIT) ? \ | 72 | #define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk,TIF_31BIT) ? \ |
74 | (0x80000000UL) : (0x40000000000UL)) | 73 | (1UL << 31) : (1UL << 53)) |
75 | # define TASK_SIZE TASK_SIZE_OF(current) | 74 | #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ |
76 | # define TASK_UNMAPPED_BASE (TASK_SIZE / 2) | 75 | (1UL << 30) : (1UL << 41)) |
77 | # define DEFAULT_TASK_SIZE (0x40000000000UL) | 76 | #define TASK_SIZE TASK_SIZE_OF(current) |
78 | 77 | ||
79 | #endif /* __s390x__ */ | 78 | #endif /* __s390x__ */ |
80 | 79 | ||
81 | #ifdef __KERNEL__ | 80 | #ifdef __KERNEL__ |
82 | 81 | ||
83 | #define STACK_TOP TASK_SIZE | 82 | #ifndef __s390x__ |
84 | #define STACK_TOP_MAX DEFAULT_TASK_SIZE | 83 | #define STACK_TOP (1UL << 31) |
84 | #else /* __s390x__ */ | ||
85 | #define STACK_TOP (1UL << (test_thread_flag(TIF_31BIT) ? 31:53)) | ||
86 | #endif /* __s390x__ */ | ||
87 | |||
88 | #define STACK_TOP_MAX STACK_TOP | ||
85 | 89 | ||
86 | #endif | 90 | #endif |
87 | 91 | ||
diff --git a/include/asm-s390/tlb.h b/include/asm-s390/tlb.h index ecac75ec6cb0..9b2ddb7aac49 100644 --- a/include/asm-s390/tlb.h +++ b/include/asm-s390/tlb.h | |||
@@ -38,7 +38,7 @@ struct mmu_gather { | |||
38 | struct mm_struct *mm; | 38 | struct mm_struct *mm; |
39 | unsigned int fullmm; | 39 | unsigned int fullmm; |
40 | unsigned int nr_ptes; | 40 | unsigned int nr_ptes; |
41 | unsigned int nr_pmds; | 41 | unsigned int nr_pxds; |
42 | void *array[TLB_NR_PTRS]; | 42 | void *array[TLB_NR_PTRS]; |
43 | }; | 43 | }; |
44 | 44 | ||
@@ -53,7 +53,7 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, | |||
53 | tlb->fullmm = full_mm_flush || (num_online_cpus() == 1) || | 53 | tlb->fullmm = full_mm_flush || (num_online_cpus() == 1) || |
54 | (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm); | 54 | (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm); |
55 | tlb->nr_ptes = 0; | 55 | tlb->nr_ptes = 0; |
56 | tlb->nr_pmds = TLB_NR_PTRS; | 56 | tlb->nr_pxds = TLB_NR_PTRS; |
57 | if (tlb->fullmm) | 57 | if (tlb->fullmm) |
58 | __tlb_flush_mm(mm); | 58 | __tlb_flush_mm(mm); |
59 | return tlb; | 59 | return tlb; |
@@ -62,12 +62,13 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, | |||
62 | static inline void tlb_flush_mmu(struct mmu_gather *tlb, | 62 | static inline void tlb_flush_mmu(struct mmu_gather *tlb, |
63 | unsigned long start, unsigned long end) | 63 | unsigned long start, unsigned long end) |
64 | { | 64 | { |
65 | if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pmds < TLB_NR_PTRS)) | 65 | if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < TLB_NR_PTRS)) |
66 | __tlb_flush_mm(tlb->mm); | 66 | __tlb_flush_mm(tlb->mm); |
67 | while (tlb->nr_ptes > 0) | 67 | while (tlb->nr_ptes > 0) |
68 | pte_free(tlb->mm, tlb->array[--tlb->nr_ptes]); | 68 | pte_free(tlb->mm, tlb->array[--tlb->nr_ptes]); |
69 | while (tlb->nr_pmds < TLB_NR_PTRS) | 69 | while (tlb->nr_pxds < TLB_NR_PTRS) |
70 | pmd_free(tlb->mm, (pmd_t *) tlb->array[tlb->nr_pmds++]); | 70 | /* pgd_free frees the pointer as region or segment table */ |
71 | pgd_free(tlb->mm, tlb->array[tlb->nr_pxds++]); | ||
71 | } | 72 | } |
72 | 73 | ||
73 | static inline void tlb_finish_mmu(struct mmu_gather *tlb, | 74 | static inline void tlb_finish_mmu(struct mmu_gather *tlb, |
@@ -99,7 +100,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte) | |||
99 | { | 100 | { |
100 | if (!tlb->fullmm) { | 101 | if (!tlb->fullmm) { |
101 | tlb->array[tlb->nr_ptes++] = pte; | 102 | tlb->array[tlb->nr_ptes++] = pte; |
102 | if (tlb->nr_ptes >= tlb->nr_pmds) | 103 | if (tlb->nr_ptes >= tlb->nr_pxds) |
103 | tlb_flush_mmu(tlb, 0, 0); | 104 | tlb_flush_mmu(tlb, 0, 0); |
104 | } else | 105 | } else |
105 | pte_free(tlb->mm, pte); | 106 | pte_free(tlb->mm, pte); |
@@ -113,15 +114,29 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd) | |||
113 | { | 114 | { |
114 | #ifdef __s390x__ | 115 | #ifdef __s390x__ |
115 | if (!tlb->fullmm) { | 116 | if (!tlb->fullmm) { |
116 | tlb->array[--tlb->nr_pmds] = (struct page *) pmd; | 117 | tlb->array[--tlb->nr_pxds] = pmd; |
117 | if (tlb->nr_ptes >= tlb->nr_pmds) | 118 | if (tlb->nr_ptes >= tlb->nr_pxds) |
118 | tlb_flush_mmu(tlb, 0, 0); | 119 | tlb_flush_mmu(tlb, 0, 0); |
119 | } else | 120 | } else |
120 | pmd_free(tlb->mm, pmd); | 121 | pmd_free(tlb->mm, pmd); |
121 | #endif | 122 | #endif |
122 | } | 123 | } |
123 | 124 | ||
124 | #define pud_free_tlb(tlb, pud) do { } while (0) | 125 | /* |
126 | * pud_free_tlb frees a pud table and clears the CRSTE for the | ||
127 | * region third table entry from the tlb. | ||
128 | */ | ||
129 | static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud) | ||
130 | { | ||
131 | #ifdef __s390x__ | ||
132 | if (!tlb->fullmm) { | ||
133 | tlb->array[--tlb->nr_pxds] = pud; | ||
134 | if (tlb->nr_ptes >= tlb->nr_pxds) | ||
135 | tlb_flush_mmu(tlb, 0, 0); | ||
136 | } else | ||
137 | pud_free(tlb->mm, pud); | ||
138 | #endif | ||
139 | } | ||
125 | 140 | ||
126 | #define tlb_start_vma(tlb, vma) do { } while (0) | 141 | #define tlb_start_vma(tlb, vma) do { } while (0) |
127 | #define tlb_end_vma(tlb, vma) do { } while (0) | 142 | #define tlb_end_vma(tlb, vma) do { } while (0) |