|
@@ -1420,7 +1420,7 @@ static void __init pcpu_free_bootmem(void *ptr, size_t size)
|
|
|
free_bootmem(__pa(ptr), size);
|
|
|
}
|
|
|
|
|
|
-static int pcpu_cpu_distance(unsigned int from, unsigned int to)
|
|
|
+static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
|
|
|
{
|
|
|
if (cpu_to_node(from) == cpu_to_node(to))
|
|
|
return LOCAL_DISTANCE;
|
|
@@ -1428,18 +1428,53 @@ static int pcpu_cpu_distance(unsigned int from, unsigned int to)
|
|
|
return REMOTE_DISTANCE;
|
|
|
}
|
|
|
|
|
|
+static void __init pcpu_populate_pte(unsigned long addr)
|
|
|
+{
|
|
|
+ pgd_t *pgd = pgd_offset_k(addr);
|
|
|
+ pud_t *pud;
|
|
|
+ pmd_t *pmd;
|
|
|
+
|
|
|
+ pud = pud_offset(pgd, addr);
|
|
|
+ if (pud_none(*pud)) {
|
|
|
+ pmd_t *new;
|
|
|
+
|
|
|
+ new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
|
|
+ pud_populate(&init_mm, pud, new);
|
|
|
+ }
|
|
|
+
|
|
|
+ pmd = pmd_offset(pud, addr);
|
|
|
+ if (!pmd_present(*pmd)) {
|
|
|
+ pte_t *new;
|
|
|
+
|
|
|
+ new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
|
|
|
+ pmd_populate_kernel(&init_mm, pmd, new);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void __init setup_per_cpu_areas(void)
|
|
|
{
|
|
|
unsigned long delta;
|
|
|
unsigned int cpu;
|
|
|
- int rc;
|
|
|
-
|
|
|
- rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
|
|
|
- PERCPU_DYNAMIC_RESERVE, 4 << 20,
|
|
|
- pcpu_cpu_distance, pcpu_alloc_bootmem,
|
|
|
- pcpu_free_bootmem);
|
|
|
- if (rc)
|
|
|
- panic("failed to initialize first chunk (%d)", rc);
|
|
|
+ int rc = -EINVAL;
|
|
|
+
|
|
|
+ if (pcpu_chosen_fc != PCPU_FC_PAGE) {
|
|
|
+ rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
|
|
|
+ PERCPU_DYNAMIC_RESERVE, 4 << 20,
|
|
|
+ pcpu_cpu_distance,
|
|
|
+ pcpu_alloc_bootmem,
|
|
|
+ pcpu_free_bootmem);
|
|
|
+ if (rc)
|
|
|
+ pr_warning("PERCPU: %s allocator failed (%d), "
|
|
|
+ "falling back to page size\n",
|
|
|
+ pcpu_fc_names[pcpu_chosen_fc], rc);
|
|
|
+ }
|
|
|
+ if (rc < 0)
|
|
|
+ rc = pcpu_page_first_chunk(PERCPU_MODULE_RESERVE,
|
|
|
+ pcpu_alloc_bootmem,
|
|
|
+ pcpu_free_bootmem,
|
|
|
+ pcpu_populate_pte);
|
|
|
+ if (rc < 0)
|
|
|
+ panic("cannot initialize percpu area (err=%d)", rc);
|
|
|
|
|
|
delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
|
|
|
for_each_possible_cpu(cpu)
|