diff options
-rw-r--r-- | arch/powerpc/include/asm/mmu-hash64.h | 35 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pgalloc-64.h | 5 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pte-hash64-64k.h | 37 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 6 | ||||
-rw-r--r-- | arch/powerpc/mm/mmu_context_hash64.c | 2 | ||||
-rw-r--r-- | arch/powerpc/mm/subpage-prot.c | 15 |
6 files changed, 51 insertions, 49 deletions
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index 7514ec2f8540..9d9551840f4a 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h | |||
@@ -373,6 +373,38 @@ extern void slb_set_size(u16 size); | |||
373 | 373 | ||
374 | #ifndef __ASSEMBLY__ | 374 | #ifndef __ASSEMBLY__ |
375 | 375 | ||
376 | #ifdef CONFIG_PPC_SUBPAGE_PROT | ||
377 | /* | ||
378 | * For the sub-page protection option, we extend the PGD with one of | ||
379 | * these. Basically we have a 3-level tree, with the top level being | ||
380 | * the protptrs array. To optimize speed and memory consumption when | ||
381 | * only addresses < 4GB are being protected, pointers to the first | ||
382 | * four pages of sub-page protection words are stored in the low_prot | ||
383 | * array. | ||
384 | * Each page of sub-page protection words protects 1GB (4 bytes | ||
385 | * protects 64k). For the 3-level tree, each page of pointers then | ||
386 | * protects 8TB. | ||
387 | */ | ||
388 | struct subpage_prot_table { | ||
389 | unsigned long maxaddr; /* only addresses < this are protected */ | ||
390 | unsigned int **protptrs[2]; | ||
391 | unsigned int *low_prot[4]; | ||
392 | }; | ||
393 | |||
394 | #define SBP_L1_BITS (PAGE_SHIFT - 2) | ||
395 | #define SBP_L2_BITS (PAGE_SHIFT - 3) | ||
396 | #define SBP_L1_COUNT (1 << SBP_L1_BITS) | ||
397 | #define SBP_L2_COUNT (1 << SBP_L2_BITS) | ||
398 | #define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS) | ||
399 | #define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS) | ||
400 | |||
401 | extern void subpage_prot_free(struct mm_struct *mm); | ||
402 | extern void subpage_prot_init_new_context(struct mm_struct *mm); | ||
403 | #else | ||
404 | static inline void subpage_prot_free(pgd_t *pgd) {} | ||
405 | static inline void subpage_prot_init_new_context(struct mm_struct *mm) { } | ||
406 | #endif /* CONFIG_PPC_SUBPAGE_PROT */ | ||
407 | |||
376 | typedef unsigned long mm_context_id_t; | 408 | typedef unsigned long mm_context_id_t; |
377 | 409 | ||
378 | typedef struct { | 410 | typedef struct { |
@@ -386,6 +418,9 @@ typedef struct { | |||
386 | u16 sllp; /* SLB page size encoding */ | 418 | u16 sllp; /* SLB page size encoding */ |
387 | #endif | 419 | #endif |
388 | unsigned long vdso_base; | 420 | unsigned long vdso_base; |
421 | #ifdef CONFIG_PPC_SUBPAGE_PROT | ||
422 | struct subpage_prot_table spt; | ||
423 | #endif /* CONFIG_PPC_SUBPAGE_PROT */ | ||
389 | } mm_context_t; | 424 | } mm_context_t; |
390 | 425 | ||
391 | 426 | ||
diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h index 5c1cd73dafa8..605f5c5398d1 100644 --- a/arch/powerpc/include/asm/pgalloc-64.h +++ b/arch/powerpc/include/asm/pgalloc-64.h | |||
@@ -28,10 +28,6 @@ | |||
28 | */ | 28 | */ |
29 | #define MAX_PGTABLE_INDEX_SIZE 0xf | 29 | #define MAX_PGTABLE_INDEX_SIZE 0xf |
30 | 30 | ||
31 | #ifndef CONFIG_PPC_SUBPAGE_PROT | ||
32 | static inline void subpage_prot_free(pgd_t *pgd) {} | ||
33 | #endif | ||
34 | |||
35 | extern struct kmem_cache *pgtable_cache[]; | 31 | extern struct kmem_cache *pgtable_cache[]; |
36 | #define PGT_CACHE(shift) (pgtable_cache[(shift)-1]) | 32 | #define PGT_CACHE(shift) (pgtable_cache[(shift)-1]) |
37 | 33 | ||
@@ -42,7 +38,6 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) | |||
42 | 38 | ||
43 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | 39 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) |
44 | { | 40 | { |
45 | subpage_prot_free(pgd); | ||
46 | kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd); | 41 | kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd); |
47 | } | 42 | } |
48 | 43 | ||
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h index 82b72207c51c..c4490f9c67c4 100644 --- a/arch/powerpc/include/asm/pte-hash64-64k.h +++ b/arch/powerpc/include/asm/pte-hash64-64k.h | |||
@@ -76,41 +76,4 @@ | |||
76 | remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ | 76 | remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ |
77 | __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) | 77 | __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) |
78 | 78 | ||
79 | |||
80 | #ifdef CONFIG_PPC_SUBPAGE_PROT | ||
81 | /* | ||
82 | * For the sub-page protection option, we extend the PGD with one of | ||
83 | * these. Basically we have a 3-level tree, with the top level being | ||
84 | * the protptrs array. To optimize speed and memory consumption when | ||
85 | * only addresses < 4GB are being protected, pointers to the first | ||
86 | * four pages of sub-page protection words are stored in the low_prot | ||
87 | * array. | ||
88 | * Each page of sub-page protection words protects 1GB (4 bytes | ||
89 | * protects 64k). For the 3-level tree, each page of pointers then | ||
90 | * protects 8TB. | ||
91 | */ | ||
92 | struct subpage_prot_table { | ||
93 | unsigned long maxaddr; /* only addresses < this are protected */ | ||
94 | unsigned int **protptrs[2]; | ||
95 | unsigned int *low_prot[4]; | ||
96 | }; | ||
97 | |||
98 | #undef PGD_TABLE_SIZE | ||
99 | #define PGD_TABLE_SIZE ((sizeof(pgd_t) << PGD_INDEX_SIZE) + \ | ||
100 | sizeof(struct subpage_prot_table)) | ||
101 | |||
102 | #define SBP_L1_BITS (PAGE_SHIFT - 2) | ||
103 | #define SBP_L2_BITS (PAGE_SHIFT - 3) | ||
104 | #define SBP_L1_COUNT (1 << SBP_L1_BITS) | ||
105 | #define SBP_L2_COUNT (1 << SBP_L2_BITS) | ||
106 | #define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS) | ||
107 | #define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS) | ||
108 | |||
109 | extern void subpage_prot_free(pgd_t *pgd); | ||
110 | |||
111 | static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd) | ||
112 | { | ||
113 | return (struct subpage_prot_table *)(pgd + PTRS_PER_PGD); | ||
114 | } | ||
115 | #endif /* CONFIG_PPC_SUBPAGE_PROT */ | ||
116 | #endif /* __ASSEMBLY__ */ | 79 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 6810128aba30..50f867d657df 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -835,9 +835,9 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr) | |||
835 | * Result is 0: full permissions, _PAGE_RW: read-only, | 835 | * Result is 0: full permissions, _PAGE_RW: read-only, |
836 | * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access. | 836 | * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access. |
837 | */ | 837 | */ |
838 | static int subpage_protection(pgd_t *pgdir, unsigned long ea) | 838 | static int subpage_protection(struct mm_struct *mm, unsigned long ea) |
839 | { | 839 | { |
840 | struct subpage_prot_table *spt = pgd_subpage_prot(pgdir); | 840 | struct subpage_prot_table *spt = &mm->context.spt; |
841 | u32 spp = 0; | 841 | u32 spp = 0; |
842 | u32 **sbpm, *sbpp; | 842 | u32 **sbpm, *sbpp; |
843 | 843 | ||
@@ -865,7 +865,7 @@ static int subpage_protection(pgd_t *pgdir, unsigned long ea) | |||
865 | } | 865 | } |
866 | 866 | ||
867 | #else /* CONFIG_PPC_SUBPAGE_PROT */ | 867 | #else /* CONFIG_PPC_SUBPAGE_PROT */ |
868 | static inline int subpage_protection(pgd_t *pgdir, unsigned long ea) | 868 | static inline int subpage_protection(struct mm_struct *mm, unsigned long ea) |
869 | { | 869 | { |
870 | return 0; | 870 | return 0; |
871 | } | 871 | } |
diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c index b9e4cc2c2057..b910d37aea1a 100644 --- a/arch/powerpc/mm/mmu_context_hash64.c +++ b/arch/powerpc/mm/mmu_context_hash64.c | |||
@@ -76,6 +76,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) | |||
76 | */ | 76 | */ |
77 | if (slice_mm_new_context(mm)) | 77 | if (slice_mm_new_context(mm)) |
78 | slice_set_user_psize(mm, mmu_virtual_psize); | 78 | slice_set_user_psize(mm, mmu_virtual_psize); |
79 | subpage_prot_init_new_context(mm); | ||
79 | mm->context.id = index; | 80 | mm->context.id = index; |
80 | 81 | ||
81 | return 0; | 82 | return 0; |
@@ -92,5 +93,6 @@ EXPORT_SYMBOL_GPL(__destroy_context); | |||
92 | void destroy_context(struct mm_struct *mm) | 93 | void destroy_context(struct mm_struct *mm) |
93 | { | 94 | { |
94 | __destroy_context(mm->context.id); | 95 | __destroy_context(mm->context.id); |
96 | subpage_prot_free(mm); | ||
95 | mm->context.id = NO_CONTEXT; | 97 | mm->context.id = NO_CONTEXT; |
96 | } | 98 | } |
diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c index 4cafc0c33d0a..a040b81e93bd 100644 --- a/arch/powerpc/mm/subpage-prot.c +++ b/arch/powerpc/mm/subpage-prot.c | |||
@@ -24,9 +24,9 @@ | |||
24 | * Also makes sure that the subpage_prot_table structure is | 24 | * Also makes sure that the subpage_prot_table structure is |
25 | * reinitialized for the next user. | 25 | * reinitialized for the next user. |
26 | */ | 26 | */ |
27 | void subpage_prot_free(pgd_t *pgd) | 27 | void subpage_prot_free(struct mm_struct *mm) |
28 | { | 28 | { |
29 | struct subpage_prot_table *spt = pgd_subpage_prot(pgd); | 29 | struct subpage_prot_table *spt = &mm->context.spt; |
30 | unsigned long i, j, addr; | 30 | unsigned long i, j, addr; |
31 | u32 **p; | 31 | u32 **p; |
32 | 32 | ||
@@ -51,6 +51,13 @@ void subpage_prot_free(pgd_t *pgd) | |||
51 | spt->maxaddr = 0; | 51 | spt->maxaddr = 0; |
52 | } | 52 | } |
53 | 53 | ||
54 | void subpage_prot_init_new_context(struct mm_struct *mm) | ||
55 | { | ||
56 | struct subpage_prot_table *spt = &mm->context.spt; | ||
57 | |||
58 | memset(spt, 0, sizeof(*spt)); | ||
59 | } | ||
60 | |||
54 | static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, | 61 | static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, |
55 | int npages) | 62 | int npages) |
56 | { | 63 | { |
@@ -87,7 +94,7 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr, | |||
87 | static void subpage_prot_clear(unsigned long addr, unsigned long len) | 94 | static void subpage_prot_clear(unsigned long addr, unsigned long len) |
88 | { | 95 | { |
89 | struct mm_struct *mm = current->mm; | 96 | struct mm_struct *mm = current->mm; |
90 | struct subpage_prot_table *spt = pgd_subpage_prot(mm->pgd); | 97 | struct subpage_prot_table *spt = &mm->context.spt; |
91 | u32 **spm, *spp; | 98 | u32 **spm, *spp; |
92 | int i, nw; | 99 | int i, nw; |
93 | unsigned long next, limit; | 100 | unsigned long next, limit; |
@@ -136,7 +143,7 @@ static void subpage_prot_clear(unsigned long addr, unsigned long len) | |||
136 | long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map) | 143 | long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map) |
137 | { | 144 | { |
138 | struct mm_struct *mm = current->mm; | 145 | struct mm_struct *mm = current->mm; |
139 | struct subpage_prot_table *spt = pgd_subpage_prot(mm->pgd); | 146 | struct subpage_prot_table *spt = &mm->context.spt; |
140 | u32 **spm, *spp; | 147 | u32 **spm, *spp; |
141 | int i, nw; | 148 | int i, nw; |
142 | unsigned long next, limit; | 149 | unsigned long next, limit; |