Commit e933a73f48e3b2d40cfa56d81e2646f194b5a66a

Authored by Tejun Heo
1 parent 4518e6a0c0

percpu: kill lpage first chunk allocator

With x86 converted to embedding allocator, lpage doesn't have any user
left.  Kill it along with cpa handling code.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jan Beulich <JBeulich@novell.com>

Showing 4 changed files with 6 additions and 281 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1920,11 +1920,11 @@
1920 1920 See arch/parisc/kernel/pdc_chassis.c
1921 1921  
1922 1922 percpu_alloc= Select which percpu first chunk allocator to use.
1923   - Currently supported values are "embed", "page" and
1924   - "lpage". Archs may support subset or none of the
1925   - selections. See comments in mm/percpu.c for details
1926   - on each allocator. This parameter is primarily for
1927   - debugging and performance comparison.
  1923 + Currently supported values are "embed" and "page".
  1924 + Archs may support subset or none of the selections.
  1925 + See comments in mm/percpu.c for details on each
  1926 + allocator. This parameter is primarily for debugging
  1927 + and performance comparison.
1928 1928  
1929 1929 pf. [PARIDE]
1930 1930 See Documentation/blockdev/paride.txt.
arch/x86/mm/pageattr.c
... ... @@ -687,7 +687,7 @@
687 687 {
688 688 struct cpa_data alias_cpa;
689 689 unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT);
690   - unsigned long vaddr, remapped;
  690 + unsigned long vaddr;
691 691 int ret;
692 692  
693 693 if (cpa->pfn >= max_pfn_mapped)
... ... @@ -744,24 +744,6 @@
744 744 __change_page_attr_set_clr(&alias_cpa, 0);
745 745 }
746 746 #endif
747   -
748   - /*
749   - * If the PMD page was partially used for per-cpu remapping,
750   - * the recycled area needs to be split and modified. Because
751   - * the area is always proper subset of a PMD page
752   - * cpa->numpages is guaranteed to be 1 for these areas, so
753   - * there's no need to loop over and check for further remaps.
754   - */
755   - remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr);
756   - if (remapped) {
757   - WARN_ON(cpa->numpages > 1);
758   - alias_cpa = *cpa;
759   - alias_cpa.vaddr = &remapped;
760   - alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
761   - ret = __change_page_attr_set_clr(&alias_cpa, 0);
762   - if (ret)
763   - return ret;
764   - }
765 747  
766 748 return 0;
767 749 }
include/linux/percpu.h
... ... @@ -82,7 +82,6 @@
82 82 PCPU_FC_AUTO,
83 83 PCPU_FC_EMBED,
84 84 PCPU_FC_PAGE,
85   - PCPU_FC_LPAGE,
86 85  
87 86 PCPU_FC_NR,
88 87 };
... ... @@ -95,7 +94,6 @@
95 94 typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size);
96 95 typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr);
97 96 typedef int (pcpu_fc_cpu_distance_fn_t)(unsigned int from, unsigned int to);
98   -typedef void (*pcpu_fc_map_fn_t)(void *ptr, size_t size, void *addr);
99 97  
100 98 extern struct pcpu_alloc_info * __init pcpu_alloc_alloc_info(int nr_groups,
101 99 int nr_units);
... ... @@ -122,20 +120,6 @@
122 120 pcpu_fc_alloc_fn_t alloc_fn,
123 121 pcpu_fc_free_fn_t free_fn,
124 122 pcpu_fc_populate_pte_fn_t populate_pte_fn);
125   -#endif
126   -
127   -#ifdef CONFIG_NEED_PER_CPU_LPAGE_FIRST_CHUNK
128   -extern int __init pcpu_lpage_first_chunk(const struct pcpu_alloc_info *ai,
129   - pcpu_fc_alloc_fn_t alloc_fn,
130   - pcpu_fc_free_fn_t free_fn,
131   - pcpu_fc_map_fn_t map_fn);
132   -
133   -extern void *pcpu_lpage_remapped(void *kaddr);
134   -#else
135   -static inline void *pcpu_lpage_remapped(void *kaddr)
136   -{
137   - return NULL;
138   -}
139 123 #endif
140 124  
141 125 /*
... ... @@ -1713,7 +1713,6 @@
1713 1713 [PCPU_FC_AUTO] = "auto",
1714 1714 [PCPU_FC_EMBED] = "embed",
1715 1715 [PCPU_FC_PAGE] = "page",
1716   - [PCPU_FC_LPAGE] = "lpage",
1717 1716 };
1718 1717  
1719 1718 enum pcpu_fc pcpu_chosen_fc __initdata = PCPU_FC_AUTO;
... ... @@ -1730,10 +1729,6 @@
1730 1729 else if (!strcmp(str, "page"))
1731 1730 pcpu_chosen_fc = PCPU_FC_PAGE;
1732 1731 #endif
1733   -#ifdef CONFIG_NEED_PER_CPU_LPAGE_FIRST_CHUNK
1734   - else if (!strcmp(str, "lpage"))
1735   - pcpu_chosen_fc = PCPU_FC_LPAGE;
1736   -#endif
1737 1732 else
1738 1733 pr_warning("PERCPU: unknown allocator %s specified\n", str);
1739 1734  
... ... @@ -1969,242 +1964,6 @@
1969 1964 return rc;
1970 1965 }
1971 1966 #endif /* CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK */
1972   -
1973   -#ifdef CONFIG_NEED_PER_CPU_LPAGE_FIRST_CHUNK
1974   -struct pcpul_ent {
1975   - void *ptr;
1976   - void *map_addr;
1977   -};
1978   -
1979   -static size_t pcpul_size;
1980   -static size_t pcpul_lpage_size;
1981   -static int pcpul_nr_lpages;
1982   -static struct pcpul_ent *pcpul_map;
1983   -
1984   -static bool __init pcpul_unit_to_cpu(int unit, const struct pcpu_alloc_info *ai,
1985   - unsigned int *cpup)
1986   -{
1987   - int group, cunit;
1988   -
1989   - for (group = 0, cunit = 0; group < ai->nr_groups; group++) {
1990   - const struct pcpu_group_info *gi = &ai->groups[group];
1991   -
1992   - if (unit < cunit + gi->nr_units) {
1993   - if (cpup)
1994   - *cpup = gi->cpu_map[unit - cunit];
1995   - return true;
1996   - }
1997   - cunit += gi->nr_units;
1998   - }
1999   -
2000   - return false;
2001   -}
2002   -
2003   -static int __init pcpul_cpu_to_unit(int cpu, const struct pcpu_alloc_info *ai)
2004   -{
2005   - int group, unit, i;
2006   -
2007   - for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
2008   - const struct pcpu_group_info *gi = &ai->groups[group];
2009   -
2010   - for (i = 0; i < gi->nr_units; i++)
2011   - if (gi->cpu_map[i] == cpu)
2012   - return unit + i;
2013   - }
2014   - BUG();
2015   -}
2016   -
2017   -/**
2018   - * pcpu_lpage_first_chunk - remap the first percpu chunk using large page
2019   - * @ai: pcpu_alloc_info
2020   - * @alloc_fn: function to allocate percpu lpage, always called with lpage_size
2021   - * @free_fn: function to free percpu memory, @size <= lpage_size
2022   - * @map_fn: function to map percpu lpage, always called with lpage_size
2023   - *
2024   - * This allocator uses large page to build and map the first chunk.
2025   - * Unlike other helpers, the caller should provide fully initialized
2026   - * @ai. This can be done using pcpu_build_alloc_info(). This two
2027   - * stage initialization is to allow arch code to evaluate the
2028   - * parameters before committing to it.
2029   - *
2030   - * Large pages are allocated as directed by @unit_map and other
2031   - * parameters and mapped to vmalloc space. Unused holes are returned
2032   - * to the page allocator. Note that these holes end up being actively
2033   - * mapped twice - once to the physical mapping and to the vmalloc area
2034   - * for the first percpu chunk. Depending on architecture, this might
2035   - * cause problem when changing page attributes of the returned area.
2036   - * These double mapped areas can be detected using
2037   - * pcpu_lpage_remapped().
2038   - *
2039   - * RETURNS:
2040   - * 0 on success, -errno on failure.
2041   - */
2042   -int __init pcpu_lpage_first_chunk(const struct pcpu_alloc_info *ai,
2043   - pcpu_fc_alloc_fn_t alloc_fn,
2044   - pcpu_fc_free_fn_t free_fn,
2045   - pcpu_fc_map_fn_t map_fn)
2046   -{
2047   - static struct vm_struct vm;
2048   - const size_t lpage_size = ai->atom_size;
2049   - size_t chunk_size, map_size;
2050   - unsigned int cpu;
2051   - int i, j, unit, nr_units, rc;
2052   -
2053   - nr_units = 0;
2054   - for (i = 0; i < ai->nr_groups; i++)
2055   - nr_units += ai->groups[i].nr_units;
2056   -
2057   - chunk_size = ai->unit_size * nr_units;
2058   - BUG_ON(chunk_size % lpage_size);
2059   -
2060   - pcpul_size = ai->static_size + ai->reserved_size + ai->dyn_size;
2061   - pcpul_lpage_size = lpage_size;
2062   - pcpul_nr_lpages = chunk_size / lpage_size;
2063   -
2064   - /* allocate pointer array and alloc large pages */
2065   - map_size = pcpul_nr_lpages * sizeof(pcpul_map[0]);
2066   - pcpul_map = alloc_bootmem(map_size);
2067   -
2068   - /* allocate all pages */
2069   - for (i = 0; i < pcpul_nr_lpages; i++) {
2070   - size_t offset = i * lpage_size;
2071   - int first_unit = offset / ai->unit_size;
2072   - int last_unit = (offset + lpage_size - 1) / ai->unit_size;
2073   - void *ptr;
2074   -
2075   - /* find out which cpu is mapped to this unit */
2076   - for (unit = first_unit; unit <= last_unit; unit++)
2077   - if (pcpul_unit_to_cpu(unit, ai, &cpu))
2078   - goto found;
2079   - continue;
2080   - found:
2081   - ptr = alloc_fn(cpu, lpage_size, lpage_size);
2082   - if (!ptr) {
2083   - pr_warning("PERCPU: failed to allocate large page "
2084   - "for cpu%u\n", cpu);
2085   - goto enomem;
2086   - }
2087   -
2088   - pcpul_map[i].ptr = ptr;
2089   - }
2090   -
2091   - /* return unused holes */
2092   - for (unit = 0; unit < nr_units; unit++) {
2093   - size_t start = unit * ai->unit_size;
2094   - size_t end = start + ai->unit_size;
2095   - size_t off, next;
2096   -
2097   - /* don't free used part of occupied unit */
2098   - if (pcpul_unit_to_cpu(unit, ai, NULL))
2099   - start += pcpul_size;
2100   -
2101   - /* unit can span more than one page, punch the holes */
2102   - for (off = start; off < end; off = next) {
2103   - void *ptr = pcpul_map[off / lpage_size].ptr;
2104   - next = min(roundup(off + 1, lpage_size), end);
2105   - if (ptr)
2106   - free_fn(ptr + off % lpage_size, next - off);
2107   - }
2108   - }
2109   -
2110   - /* allocate address, map and copy */
2111   - vm.flags = VM_ALLOC;
2112   - vm.size = chunk_size;
2113   - vm_area_register_early(&vm, ai->unit_size);
2114   -
2115   - for (i = 0; i < pcpul_nr_lpages; i++) {
2116   - if (!pcpul_map[i].ptr)
2117   - continue;
2118   - pcpul_map[i].map_addr = vm.addr + i * lpage_size;
2119   - map_fn(pcpul_map[i].ptr, lpage_size, pcpul_map[i].map_addr);
2120   - }
2121   -
2122   - for_each_possible_cpu(cpu)
2123   - memcpy(vm.addr + pcpul_cpu_to_unit(cpu, ai) * ai->unit_size,
2124   - __per_cpu_load, ai->static_size);
2125   -
2126   - /* we're ready, commit */
2127   - pr_info("PERCPU: large pages @%p s%zu r%zu d%zu u%zu\n",
2128   - vm.addr, ai->static_size, ai->reserved_size, ai->dyn_size,
2129   - ai->unit_size);
2130   -
2131   - rc = pcpu_setup_first_chunk(ai, vm.addr);
2132   -
2133   - /*
2134   - * Sort pcpul_map array for pcpu_lpage_remapped(). Unmapped
2135   - * lpages are pushed to the end and trimmed.
2136   - */
2137   - for (i = 0; i < pcpul_nr_lpages - 1; i++)
2138   - for (j = i + 1; j < pcpul_nr_lpages; j++) {
2139   - struct pcpul_ent tmp;
2140   -
2141   - if (!pcpul_map[j].ptr)
2142   - continue;
2143   - if (pcpul_map[i].ptr &&
2144   - pcpul_map[i].ptr < pcpul_map[j].ptr)
2145   - continue;
2146   -
2147   - tmp = pcpul_map[i];
2148   - pcpul_map[i] = pcpul_map[j];
2149   - pcpul_map[j] = tmp;
2150   - }
2151   -
2152   - while (pcpul_nr_lpages && !pcpul_map[pcpul_nr_lpages - 1].ptr)
2153   - pcpul_nr_lpages--;
2154   -
2155   - return rc;
2156   -
2157   -enomem:
2158   - for (i = 0; i < pcpul_nr_lpages; i++)
2159   - if (pcpul_map[i].ptr)
2160   - free_fn(pcpul_map[i].ptr, lpage_size);
2161   - free_bootmem(__pa(pcpul_map), map_size);
2162   - return -ENOMEM;
2163   -}
2164   -
2165   -/**
2166   - * pcpu_lpage_remapped - determine whether a kaddr is in pcpul recycled area
2167   - * @kaddr: the kernel address in question
2168   - *
2169   - * Determine whether @kaddr falls in the pcpul recycled area. This is
2170   - * used by pageattr to detect VM aliases and break up the pcpu large
2171   - * page mapping such that the same physical page is not mapped under
2172   - * different attributes.
2173   - *
2174   - * The recycled area is always at the tail of a partially used large
2175   - * page.
2176   - *
2177   - * RETURNS:
2178   - * Address of corresponding remapped pcpu address if match is found;
2179   - * otherwise, NULL.
2180   - */
2181   -void *pcpu_lpage_remapped(void *kaddr)
2182   -{
2183   - unsigned long lpage_mask = pcpul_lpage_size - 1;
2184   - void *lpage_addr = (void *)((unsigned long)kaddr & ~lpage_mask);
2185   - unsigned long offset = (unsigned long)kaddr & lpage_mask;
2186   - int left = 0, right = pcpul_nr_lpages - 1;
2187   - int pos;
2188   -
2189   - /* pcpul in use at all? */
2190   - if (!pcpul_map)
2191   - return NULL;
2192   -
2193   - /* okay, perform binary search */
2194   - while (left <= right) {
2195   - pos = (left + right) / 2;
2196   -
2197   - if (pcpul_map[pos].ptr < lpage_addr)
2198   - left = pos + 1;
2199   - else if (pcpul_map[pos].ptr > lpage_addr)
2200   - right = pos - 1;
2201   - else
2202   - return pcpul_map[pos].map_addr + offset;
2203   - }
2204   -
2205   - return NULL;
2206   -}
2207   -#endif /* CONFIG_NEED_PER_CPU_LPAGE_FIRST_CHUNK */
2208 1967  
2209 1968 /*
2210 1969 * Generic percpu area setup.