aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--arch/x86/kernel/setup_percpu.c24
-rw-r--r--include/linux/percpu.h12
-rw-r--r--mm/percpu.c32
4 files changed, 56 insertions, 23 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 12e9eb77ee0d..dee9ce2e6cfa 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1919,11 +1919,12 @@ and is between 256 and 4096 characters. It is defined in the file
1919 Format: { 0 | 1 } 1919 Format: { 0 | 1 }
1920 See arch/parisc/kernel/pdc_chassis.c 1920 See arch/parisc/kernel/pdc_chassis.c
1921 1921
1922 percpu_alloc= [X86] Select which percpu first chunk allocator to use. 1922 percpu_alloc= Select which percpu first chunk allocator to use.
1923 Allowed values are one of "lpage", "embed" and "page". 1923 Currently supported values are "embed", "page" and
1924 See comments in arch/x86/kernel/setup_percpu.c for 1924 "lpage". Archs may support subset or none of the
1925 details on each allocator. This parameter is primarily 1925 selections. See comments in mm/percpu.c for details
1926 for debugging and performance comparison. 1926 on each allocator. This parameter is primarily for
1927 debugging and performance comparison.
1927 1928
1928 pf. [PARIDE] 1929 pf. [PARIDE]
1929 See Documentation/blockdev/paride.txt. 1930 See Documentation/blockdev/paride.txt.
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 1e17711c29d6..b961d99e6416 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -267,16 +267,6 @@ static ssize_t __init setup_pcpu_page(size_t static_size)
267 pcpup_populate_pte); 267 pcpup_populate_pte);
268} 268}
269 269
270/* for explicit first chunk allocator selection */
271static char pcpu_chosen_alloc[16] __initdata;
272
273static int __init percpu_alloc_setup(char *str)
274{
275 strncpy(pcpu_chosen_alloc, str, sizeof(pcpu_chosen_alloc) - 1);
276 return 0;
277}
278early_param("percpu_alloc", percpu_alloc_setup);
279
280static inline void setup_percpu_segment(int cpu) 270static inline void setup_percpu_segment(int cpu)
281{ 271{
282#ifdef CONFIG_X86_32 272#ifdef CONFIG_X86_32
@@ -307,19 +297,17 @@ void __init setup_per_cpu_areas(void)
307 * each allocator for details. 297 * each allocator for details.
308 */ 298 */
309 ret = -EINVAL; 299 ret = -EINVAL;
310 if (strlen(pcpu_chosen_alloc)) { 300 if (pcpu_chosen_fc != PCPU_FC_AUTO) {
311 if (strcmp(pcpu_chosen_alloc, "page")) { 301 if (pcpu_chosen_fc != PCPU_FC_PAGE) {
312 if (!strcmp(pcpu_chosen_alloc, "lpage")) 302 if (pcpu_chosen_fc == PCPU_FC_LPAGE)
313 ret = setup_pcpu_lpage(static_size, true); 303 ret = setup_pcpu_lpage(static_size, true);
314 else if (!strcmp(pcpu_chosen_alloc, "embed"))
315 ret = setup_pcpu_embed(static_size, true);
316 else 304 else
317 pr_warning("PERCPU: unknown allocator %s " 305 ret = setup_pcpu_embed(static_size, true);
318 "specified\n", pcpu_chosen_alloc); 306
319 if (ret < 0) 307 if (ret < 0)
320 pr_warning("PERCPU: %s allocator failed (%zd), " 308 pr_warning("PERCPU: %s allocator failed (%zd), "
321 "falling back to page size\n", 309 "falling back to page size\n",
322 pcpu_chosen_alloc, ret); 310 pcpu_fc_names[pcpu_chosen_fc], ret);
323 } 311 }
324 } else { 312 } else {
325 ret = setup_pcpu_lpage(static_size, false); 313 ret = setup_pcpu_lpage(static_size, false);
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index e26788e0da4a..9be05cbe5ee0 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -59,6 +59,18 @@
59extern void *pcpu_base_addr; 59extern void *pcpu_base_addr;
60extern const int *pcpu_unit_map; 60extern const int *pcpu_unit_map;
61 61
62enum pcpu_fc {
63 PCPU_FC_AUTO,
64 PCPU_FC_EMBED,
65 PCPU_FC_PAGE,
66 PCPU_FC_LPAGE,
67
68 PCPU_FC_NR,
69};
70extern const char *pcpu_fc_names[PCPU_FC_NR];
71
72extern enum pcpu_fc pcpu_chosen_fc;
73
62typedef void * (*pcpu_fc_alloc_fn_t)(unsigned int cpu, size_t size); 74typedef void * (*pcpu_fc_alloc_fn_t)(unsigned int cpu, size_t size);
63typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size); 75typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size);
64typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr); 76typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr);
diff --git a/mm/percpu.c b/mm/percpu.c
index 7971997de310..7fb40bb1555a 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1414,6 +1414,38 @@ size_t __init pcpu_setup_first_chunk(size_t static_size, size_t reserved_size,
1414 return pcpu_unit_size; 1414 return pcpu_unit_size;
1415} 1415}
1416 1416
1417const char *pcpu_fc_names[PCPU_FC_NR] __initdata = {
1418 [PCPU_FC_AUTO] = "auto",
1419 [PCPU_FC_EMBED] = "embed",
1420 [PCPU_FC_PAGE] = "page",
1421 [PCPU_FC_LPAGE] = "lpage",
1422};
1423
1424enum pcpu_fc pcpu_chosen_fc __initdata = PCPU_FC_AUTO;
1425
1426static int __init percpu_alloc_setup(char *str)
1427{
1428 if (0)
1429 /* nada */;
1430#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK
1431 else if (!strcmp(str, "embed"))
1432 pcpu_chosen_fc = PCPU_FC_EMBED;
1433#endif
1434#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
1435 else if (!strcmp(str, "page"))
1436 pcpu_chosen_fc = PCPU_FC_PAGE;
1437#endif
1438#ifdef CONFIG_NEED_PER_CPU_LPAGE_FIRST_CHUNK
1439 else if (!strcmp(str, "lpage"))
1440 pcpu_chosen_fc = PCPU_FC_LPAGE;
1441#endif
1442 else
1443 pr_warning("PERCPU: unknown allocator %s specified\n", str);
1444
1445 return 0;
1446}
1447early_param("percpu_alloc", percpu_alloc_setup);
1448
1417static inline size_t pcpu_calc_fc_sizes(size_t static_size, 1449static inline size_t pcpu_calc_fc_sizes(size_t static_size,
1418 size_t reserved_size, 1450 size_t reserved_size,
1419 ssize_t *dyn_sizep) 1451 ssize_t *dyn_sizep)