diff options
Diffstat (limited to 'arch/powerpc/mm/init-common.c')
-rw-r--r-- | arch/powerpc/mm/init-common.c | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/arch/powerpc/mm/init-common.c b/arch/powerpc/mm/init-common.c index 2b656e67f2ea..1e6910eb70ed 100644 --- a/arch/powerpc/mm/init-common.c +++ b/arch/powerpc/mm/init-common.c | |||
@@ -25,22 +25,40 @@ | |||
25 | #include <asm/pgalloc.h> | 25 | #include <asm/pgalloc.h> |
26 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
27 | 27 | ||
28 | static void pgd_ctor(void *addr) | 28 | #define CTOR(shift) static void ctor_##shift(void *addr) \ |
29 | { | 29 | { \ |
30 | memset(addr, 0, PGD_TABLE_SIZE); | 30 | memset(addr, 0, sizeof(void *) << (shift)); \ |
31 | } | 31 | } |
32 | 32 | ||
33 | static void pud_ctor(void *addr) | 33 | CTOR(0); CTOR(1); CTOR(2); CTOR(3); CTOR(4); CTOR(5); CTOR(6); CTOR(7); |
34 | { | 34 | CTOR(8); CTOR(9); CTOR(10); CTOR(11); CTOR(12); CTOR(13); CTOR(14); CTOR(15); |
35 | memset(addr, 0, PUD_TABLE_SIZE); | ||
36 | } | ||
37 | 35 | ||
38 | static void pmd_ctor(void *addr) | 36 | static inline void (*ctor(int shift))(void *) |
39 | { | 37 | { |
40 | memset(addr, 0, PMD_TABLE_SIZE); | 38 | BUILD_BUG_ON(MAX_PGTABLE_INDEX_SIZE != 15); |
39 | |||
40 | switch (shift) { | ||
41 | case 0: return ctor_0; | ||
42 | case 1: return ctor_1; | ||
43 | case 2: return ctor_2; | ||
44 | case 3: return ctor_3; | ||
45 | case 4: return ctor_4; | ||
46 | case 5: return ctor_5; | ||
47 | case 6: return ctor_6; | ||
48 | case 7: return ctor_7; | ||
49 | case 8: return ctor_8; | ||
50 | case 9: return ctor_9; | ||
51 | case 10: return ctor_10; | ||
52 | case 11: return ctor_11; | ||
53 | case 12: return ctor_12; | ||
54 | case 13: return ctor_13; | ||
55 | case 14: return ctor_14; | ||
56 | case 15: return ctor_15; | ||
57 | } | ||
58 | return NULL; | ||
41 | } | 59 | } |
42 | 60 | ||
43 | struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE]; | 61 | struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE + 1]; |
44 | EXPORT_SYMBOL_GPL(pgtable_cache); /* used by kvm_hv module */ | 62 | EXPORT_SYMBOL_GPL(pgtable_cache); /* used by kvm_hv module */ |
45 | 63 | ||
46 | /* | 64 | /* |
@@ -50,7 +68,7 @@ EXPORT_SYMBOL_GPL(pgtable_cache); /* used by kvm_hv module */ | |||
50 | * everything else. Caches created by this function are used for all | 68 | * everything else. Caches created by this function are used for all |
51 | * the higher level pagetables, and for hugepage pagetables. | 69 | * the higher level pagetables, and for hugepage pagetables. |
52 | */ | 70 | */ |
53 | void pgtable_cache_add(unsigned shift, void (*ctor)(void *)) | 71 | void pgtable_cache_add(unsigned int shift) |
54 | { | 72 | { |
55 | char *name; | 73 | char *name; |
56 | unsigned long table_size = sizeof(void *) << shift; | 74 | unsigned long table_size = sizeof(void *) << shift; |
@@ -71,19 +89,19 @@ void pgtable_cache_add(unsigned shift, void (*ctor)(void *)) | |||
71 | * moment, gcc doesn't seem to recognize is_power_of_2 as a | 89 | * moment, gcc doesn't seem to recognize is_power_of_2 as a |
72 | * constant expression, so so much for that. */ | 90 | * constant expression, so so much for that. */ |
73 | BUG_ON(!is_power_of_2(minalign)); | 91 | BUG_ON(!is_power_of_2(minalign)); |
74 | BUG_ON((shift < 1) || (shift > MAX_PGTABLE_INDEX_SIZE)); | 92 | BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); |
75 | 93 | ||
76 | if (PGT_CACHE(shift)) | 94 | if (PGT_CACHE(shift)) |
77 | return; /* Already have a cache of this size */ | 95 | return; /* Already have a cache of this size */ |
78 | 96 | ||
79 | align = max_t(unsigned long, align, minalign); | 97 | align = max_t(unsigned long, align, minalign); |
80 | name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift); | 98 | name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift); |
81 | new = kmem_cache_create(name, table_size, align, 0, ctor); | 99 | new = kmem_cache_create(name, table_size, align, 0, ctor(shift)); |
82 | if (!new) | 100 | if (!new) |
83 | panic("Could not allocate pgtable cache for order %d", shift); | 101 | panic("Could not allocate pgtable cache for order %d", shift); |
84 | 102 | ||
85 | kfree(name); | 103 | kfree(name); |
86 | pgtable_cache[shift - 1] = new; | 104 | pgtable_cache[shift] = new; |
87 | 105 | ||
88 | pr_debug("Allocated pgtable cache for order %d\n", shift); | 106 | pr_debug("Allocated pgtable cache for order %d\n", shift); |
89 | } | 107 | } |
@@ -91,15 +109,15 @@ EXPORT_SYMBOL_GPL(pgtable_cache_add); /* used by kvm_hv module */ | |||
91 | 109 | ||
92 | void pgtable_cache_init(void) | 110 | void pgtable_cache_init(void) |
93 | { | 111 | { |
94 | pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor); | 112 | pgtable_cache_add(PGD_INDEX_SIZE); |
95 | 113 | ||
96 | if (PMD_CACHE_INDEX && !PGT_CACHE(PMD_CACHE_INDEX)) | 114 | if (PMD_CACHE_INDEX) |
97 | pgtable_cache_add(PMD_CACHE_INDEX, pmd_ctor); | 115 | pgtable_cache_add(PMD_CACHE_INDEX); |
98 | /* | 116 | /* |
99 | * In all current configs, when the PUD index exists it's the | 117 | * In all current configs, when the PUD index exists it's the |
100 | * same size as either the pgd or pmd index except with THP enabled | 118 | * same size as either the pgd or pmd index except with THP enabled |
101 | * on book3s 64 | 119 | * on book3s 64 |
102 | */ | 120 | */ |
103 | if (PUD_CACHE_INDEX && !PGT_CACHE(PUD_CACHE_INDEX)) | 121 | if (PUD_CACHE_INDEX) |
104 | pgtable_cache_add(PUD_CACHE_INDEX, pud_ctor); | 122 | pgtable_cache_add(PUD_CACHE_INDEX); |
105 | } | 123 | } |