aboutsummaryrefslogtreecommitdiffstats
path: root/mm/percpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/percpu.c')
-rw-r--r--mm/percpu.c60
1 files changed, 56 insertions, 4 deletions
diff --git a/mm/percpu.c b/mm/percpu.c
index 58c572b18b07..fa70122dfdd0 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -76,6 +76,7 @@
76#define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */ 76#define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */
77#define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */ 77#define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */
78 78
79#ifdef CONFIG_SMP
79/* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */ 80/* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */
80#ifndef __addr_to_pcpu_ptr 81#ifndef __addr_to_pcpu_ptr
81#define __addr_to_pcpu_ptr(addr) \ 82#define __addr_to_pcpu_ptr(addr) \
@@ -89,6 +90,11 @@
89 (unsigned long)pcpu_base_addr - \ 90 (unsigned long)pcpu_base_addr - \
90 (unsigned long)__per_cpu_start) 91 (unsigned long)__per_cpu_start)
91#endif 92#endif
93#else /* CONFIG_SMP */
94/* on UP, it's always identity mapped */
95#define __addr_to_pcpu_ptr(addr) (void __percpu *)(addr)
96#define __pcpu_ptr_to_addr(ptr) (void __force *)(ptr)
97#endif /* CONFIG_SMP */
92 98
93struct pcpu_chunk { 99struct pcpu_chunk {
94 struct list_head list; /* linked to pcpu_slot lists */ 100 struct list_head list; /* linked to pcpu_slot lists */
@@ -949,6 +955,7 @@ EXPORT_SYMBOL_GPL(free_percpu);
949 */ 955 */
950bool is_kernel_percpu_address(unsigned long addr) 956bool is_kernel_percpu_address(unsigned long addr)
951{ 957{
958#ifdef CONFIG_SMP
952 const size_t static_size = __per_cpu_end - __per_cpu_start; 959 const size_t static_size = __per_cpu_end - __per_cpu_start;
953 void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr); 960 void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
954 unsigned int cpu; 961 unsigned int cpu;
@@ -959,6 +966,8 @@ bool is_kernel_percpu_address(unsigned long addr)
959 if ((void *)addr >= start && (void *)addr < start + static_size) 966 if ((void *)addr >= start && (void *)addr < start + static_size)
960 return true; 967 return true;
961 } 968 }
969#endif
970 /* on UP, can't distinguish from other static vars, always false */
962 return false; 971 return false;
963} 972}
964 973
@@ -1066,6 +1075,8 @@ void __init pcpu_free_alloc_info(struct pcpu_alloc_info *ai)
1066 free_bootmem(__pa(ai), ai->__ai_size); 1075 free_bootmem(__pa(ai), ai->__ai_size);
1067} 1076}
1068 1077
1078#if defined(CONFIG_SMP) && (defined(CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK) || \
1079 defined(CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK))
1069/** 1080/**
1070 * pcpu_build_alloc_info - build alloc_info considering distances between CPUs 1081 * pcpu_build_alloc_info - build alloc_info considering distances between CPUs
1071 * @reserved_size: the size of reserved percpu area in bytes 1082 * @reserved_size: the size of reserved percpu area in bytes
@@ -1220,6 +1231,8 @@ static struct pcpu_alloc_info * __init pcpu_build_alloc_info(
1220 1231
1221 return ai; 1232 return ai;
1222} 1233}
1234#endif /* CONFIG_SMP && (CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK ||
1235 CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK) */
1223 1236
1224/** 1237/**
1225 * pcpu_dump_alloc_info - print out information about pcpu_alloc_info 1238 * pcpu_dump_alloc_info - print out information about pcpu_alloc_info
@@ -1363,7 +1376,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1363 1376
1364 /* sanity checks */ 1377 /* sanity checks */
1365 PCPU_SETUP_BUG_ON(ai->nr_groups <= 0); 1378 PCPU_SETUP_BUG_ON(ai->nr_groups <= 0);
1379#ifdef CONFIG_SMP
1366 PCPU_SETUP_BUG_ON(!ai->static_size); 1380 PCPU_SETUP_BUG_ON(!ai->static_size);
1381#endif
1367 PCPU_SETUP_BUG_ON(!base_addr); 1382 PCPU_SETUP_BUG_ON(!base_addr);
1368 PCPU_SETUP_BUG_ON(ai->unit_size < size_sum); 1383 PCPU_SETUP_BUG_ON(ai->unit_size < size_sum);
1369 PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK); 1384 PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK);
@@ -1488,6 +1503,8 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1488 return 0; 1503 return 0;
1489} 1504}
1490 1505
1506#ifdef CONFIG_SMP
1507
1491const char *pcpu_fc_names[PCPU_FC_NR] __initdata = { 1508const char *pcpu_fc_names[PCPU_FC_NR] __initdata = {
1492 [PCPU_FC_AUTO] = "auto", 1509 [PCPU_FC_AUTO] = "auto",
1493 [PCPU_FC_EMBED] = "embed", 1510 [PCPU_FC_EMBED] = "embed",
@@ -1758,8 +1775,9 @@ out_free_ar:
1758} 1775}
1759#endif /* CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK */ 1776#endif /* CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK */
1760 1777
1778#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
1761/* 1779/*
1762 * Generic percpu area setup. 1780 * Generic SMP percpu area setup.
1763 * 1781 *
1764 * The embedding helper is used because its behavior closely resembles 1782 * The embedding helper is used because its behavior closely resembles
1765 * the original non-dynamic generic percpu area setup. This is 1783 * the original non-dynamic generic percpu area setup. This is
@@ -1770,7 +1788,6 @@ out_free_ar:
1770 * on the physical linear memory mapping which uses large page 1788 * on the physical linear memory mapping which uses large page
1771 * mappings on applicable archs. 1789 * mappings on applicable archs.
1772 */ 1790 */
1773#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
1774unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; 1791unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
1775EXPORT_SYMBOL(__per_cpu_offset); 1792EXPORT_SYMBOL(__per_cpu_offset);
1776 1793
@@ -1799,13 +1816,48 @@ void __init setup_per_cpu_areas(void)
1799 PERCPU_DYNAMIC_RESERVE, PAGE_SIZE, NULL, 1816 PERCPU_DYNAMIC_RESERVE, PAGE_SIZE, NULL,
1800 pcpu_dfl_fc_alloc, pcpu_dfl_fc_free); 1817 pcpu_dfl_fc_alloc, pcpu_dfl_fc_free);
1801 if (rc < 0) 1818 if (rc < 0)
1802 panic("Failed to initialized percpu areas."); 1819 panic("Failed to initialize percpu areas.");
1803 1820
1804 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; 1821 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
1805 for_each_possible_cpu(cpu) 1822 for_each_possible_cpu(cpu)
1806 __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu]; 1823 __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
1807} 1824}
1808#endif /* CONFIG_HAVE_SETUP_PER_CPU_AREA */ 1825#endif /* CONFIG_HAVE_SETUP_PER_CPU_AREA */
1826
1827#else /* CONFIG_SMP */
1828
1829/*
1830 * UP percpu area setup.
1831 *
1832 * UP always uses km-based percpu allocator with identity mapping.
1833 * Static percpu variables are indistinguishable from the usual static
1834 * variables and don't require any special preparation.
1835 */
1836void __init setup_per_cpu_areas(void)
1837{
1838 const size_t unit_size =
1839 roundup_pow_of_two(max_t(size_t, PCPU_MIN_UNIT_SIZE,
1840 PERCPU_DYNAMIC_RESERVE));
1841 struct pcpu_alloc_info *ai;
1842 void *fc;
1843
1844 ai = pcpu_alloc_alloc_info(1, 1);
1845 fc = __alloc_bootmem(unit_size, PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
1846 if (!ai || !fc)
1847 panic("Failed to allocate memory for percpu areas.");
1848
1849 ai->dyn_size = unit_size;
1850 ai->unit_size = unit_size;
1851 ai->atom_size = unit_size;
1852 ai->alloc_size = unit_size;
1853 ai->groups[0].nr_units = 1;
1854 ai->groups[0].cpu_map[0] = 0;
1855
1856 if (pcpu_setup_first_chunk(ai, fc) < 0)
1857 panic("Failed to initialize percpu areas.");
1858}
1859
1860#endif /* CONFIG_SMP */
1809 1861
1810/* 1862/*
1811 * First and reserved chunks are initialized with temporary allocation 1863 * First and reserved chunks are initialized with temporary allocation