diff options
Diffstat (limited to 'mm/percpu.c')
-rw-r--r-- | mm/percpu.c | 60 |
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 | ||
93 | struct pcpu_chunk { | 99 | struct 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 | */ |
950 | bool is_kernel_percpu_address(unsigned long addr) | 956 | bool 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 | |||
1491 | const char *pcpu_fc_names[PCPU_FC_NR] __initdata = { | 1508 | const 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 | ||
1774 | unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; | 1791 | unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; |
1775 | EXPORT_SYMBOL(__per_cpu_offset); | 1792 | EXPORT_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 | */ | ||
1836 | void __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 |