Loading arch/blackfin/include/asm/percpu.h +0 −10 Original line number Diff line number Diff line Loading @@ -3,14 +3,4 @@ #include <asm-generic/percpu.h> #ifdef CONFIG_MODULES #define PERCPU_MODULE_RESERVE 8192 #else #define PERCPU_MODULE_RESERVE 0 #endif #define PERCPU_ENOUGH_ROOM \ (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \ PERCPU_MODULE_RESERVE) #endif /* __ARCH_BLACKFIN_PERCPU__ */ arch/x86/include/asm/linkage.h +10 −6 Original line number Diff line number Diff line Loading @@ -4,11 +4,6 @@ #undef notrace #define notrace __attribute__((no_instrument_function)) #ifdef CONFIG_X86_64 #define __ALIGN .p2align 4,,15 #define __ALIGN_STR ".p2align 4,,15" #endif #ifdef CONFIG_X86_32 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) /* Loading Loading @@ -50,16 +45,25 @@ __asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \ "g" (arg4), "g" (arg5), "g" (arg6)) #endif #endif /* CONFIG_X86_32 */ #ifdef __ASSEMBLY__ #define GLOBAL(name) \ .globl name; \ name: #ifdef CONFIG_X86_64 #define __ALIGN .p2align 4,,15 #define __ALIGN_STR ".p2align 4,,15" #endif #ifdef CONFIG_X86_ALIGNMENT_16 #define __ALIGN .align 16,0x90 #define __ALIGN_STR ".align 16,0x90" #endif #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_LINKAGE_H */ arch/x86/kernel/cpu/amd.c +52 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ #include <asm/io.h> #include <asm/processor.h> #include <asm/apic.h> #include <asm/cpu.h> #ifdef CONFIG_X86_64 # include <asm/numa_64.h> Loading Loading @@ -141,6 +142,55 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) } } static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP /* calling is from identify_secondary_cpu() ? */ if (c->cpu_index == boot_cpu_id) return; /* * Certain Athlons might work (for various values of 'work') in SMP * but they are not certified as MP capable. */ /* Athlon 660/661 is valid. */ if ((c->x86_model == 6) && ((c->x86_mask == 0) || (c->x86_mask == 1))) goto valid_k7; /* Duron 670 is valid */ if ((c->x86_model == 7) && (c->x86_mask == 0)) goto valid_k7; /* * Athlon 662, Duron 671, and Athlon >model 7 have capability * bit. It's worth noting that the A5 stepping (662) of some * Athlon XP's have the MP bit set. * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for * more. */ if (((c->x86_model == 6) && (c->x86_mask >= 2)) || ((c->x86_model == 7) && (c->x86_mask >= 1)) || (c->x86_model > 7)) if (cpu_has_mp) goto valid_k7; /* If we get here, not a certified SMP capable AMD system. */ /* * Don't taint if we are running SMP kernel on a single non-MP * approved Athlon */ WARN_ONCE(1, "WARNING: This combination of AMD" "processors is not suitable for SMP.\n"); if (!test_taint(TAINT_UNSAFE_SMP)) add_taint(TAINT_UNSAFE_SMP); valid_k7: ; #endif } static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) { u32 l, h; Loading Loading @@ -175,6 +225,8 @@ static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) } set_cpu_cap(c, X86_FEATURE_K7); amd_k7_smp_check(c); } #endif Loading arch/x86/kernel/cpu/intel.c +25 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <asm/uaccess.h> #include <asm/ds.h> #include <asm/bugs.h> #include <asm/cpu.h> #ifdef CONFIG_X86_64 #include <asm/topology.h> Loading Loading @@ -116,6 +117,28 @@ static void __cpuinit trap_init_f00f_bug(void) } #endif static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP /* calling is from identify_secondary_cpu() ? */ if (c->cpu_index == boot_cpu_id) return; /* * Mask B, Pentium, but not Pentium MMX */ if (c->x86 == 5 && c->x86_mask >= 1 && c->x86_mask <= 4 && c->x86_model <= 3) { /* * Remember we have B step Pentia with bugs */ WARN_ONCE(1, "WARNING: SMP operation may be unreliable" "with B stepping processors.\n"); } #endif } static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) { unsigned long lo, hi; Loading Loading @@ -192,6 +215,8 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) #ifdef CONFIG_X86_NUMAQ numaq_tsc_disable(); #endif intel_smp_check(c); } #else static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) Loading arch/x86/kernel/setup_percpu.c +52 −21 Original line number Diff line number Diff line Loading @@ -42,6 +42,19 @@ unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { }; EXPORT_SYMBOL(__per_cpu_offset); /* * On x86_64 symbols referenced from code should be reachable using * 32bit relocations. Reserve space for static percpu variables in * modules so that they are always served from the first chunk which * is located at the percpu segment base. On x86_32, anything can * address anywhere. No need to reserve space in the first chunk. */ #ifdef CONFIG_X86_64 #define PERCPU_FIRST_CHUNK_RESERVE PERCPU_MODULE_RESERVE #else #define PERCPU_FIRST_CHUNK_RESERVE 0 #endif /** * pcpu_need_numa - determine percpu allocation needs to consider NUMA * Loading Loading @@ -141,7 +154,7 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) { static struct vm_struct vm; pg_data_t *last; size_t ptrs_size; size_t ptrs_size, dyn_size; unsigned int cpu; ssize_t ret; Loading Loading @@ -169,12 +182,14 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) * Currently supports only single page. Supporting multiple * pages won't be too difficult if it ever becomes necessary. */ pcpur_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE); if (pcpur_size > PMD_SIZE) { pr_warning("PERCPU: static data is larger than large page, " "can't use large page\n"); return -EINVAL; } dyn_size = pcpur_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; /* allocate pointer array and alloc large pages */ ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0])); Loading Loading @@ -217,8 +232,9 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) pr_info("PERCPU: Remapped at %p with large pages, static data " "%zu bytes\n", vm.addr, static_size); ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, PMD_SIZE, pcpur_size - static_size, vm.addr, NULL); ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, PERCPU_FIRST_CHUNK_RESERVE, PMD_SIZE, dyn_size, vm.addr, NULL); goto out_free_ar; enomem: Loading @@ -241,24 +257,31 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) * Embedding allocator * * The first chunk is sized to just contain the static area plus * PERCPU_DYNAMIC_RESERVE and allocated as a contiguous area using * bootmem allocator and used as-is without being mapped into vmalloc * area. This enables the first chunk to piggy back on the linear * physical PMD mapping and doesn't add any additional pressure to * TLB. * module and dynamic reserves, and allocated as a contiguous area * using bootmem allocator and used as-is without being mapped into * vmalloc area. This enables the first chunk to piggy back on the * linear physical PMD mapping and doesn't add any additional pressure * to TLB. Note that if the needed size is smaller than the minimum * unit size, the leftover is returned to the bootmem allocator. */ static void *pcpue_ptr __initdata; static size_t pcpue_size __initdata; static size_t pcpue_unit_size __initdata; static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) { return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + ((size_t)pageno << PAGE_SHIFT)); size_t off = (size_t)pageno << PAGE_SHIFT; if (off >= pcpue_size) return NULL; return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + off); } static ssize_t __init setup_pcpu_embed(size_t static_size) { unsigned int cpu; size_t dyn_size; /* * If large page isn't supported, there's no benefit in doing Loading @@ -269,25 +292,32 @@ static ssize_t __init setup_pcpu_embed(size_t static_size) return -EINVAL; /* allocate and copy */ pcpue_unit_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); pcpue_unit_size = max_t(size_t, pcpue_unit_size, PCPU_MIN_UNIT_SIZE); pcpue_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE); pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); dyn_size = pcpue_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size, PAGE_SIZE); if (!pcpue_ptr) return -ENOMEM; for_each_possible_cpu(cpu) memcpy(pcpue_ptr + cpu * pcpue_unit_size, __per_cpu_load, static_size); for_each_possible_cpu(cpu) { void *ptr = pcpue_ptr + cpu * pcpue_unit_size; free_bootmem(__pa(ptr + pcpue_size), pcpue_unit_size - pcpue_size); memcpy(ptr, __per_cpu_load, static_size); } /* we're ready, commit */ pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n", pcpue_unit_size >> PAGE_SHIFT, pcpue_ptr, static_size); pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size); return pcpu_setup_first_chunk(pcpue_get_page, static_size, pcpue_unit_size, pcpue_unit_size - static_size, pcpue_ptr, NULL); PERCPU_FIRST_CHUNK_RESERVE, pcpue_unit_size, dyn_size, pcpue_ptr, NULL); } /* Loading Loading @@ -344,7 +374,8 @@ static ssize_t __init setup_pcpu_4k(size_t static_size) pr_info("PERCPU: Allocated %d 4k pages, static data %zu bytes\n", pcpu4k_nr_static_pages, static_size); ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size, 0, 0, NULL, ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size, PERCPU_FIRST_CHUNK_RESERVE, -1, -1, NULL, pcpu4k_populate_pte); goto out_free_ar; Loading Loading
arch/blackfin/include/asm/percpu.h +0 −10 Original line number Diff line number Diff line Loading @@ -3,14 +3,4 @@ #include <asm-generic/percpu.h> #ifdef CONFIG_MODULES #define PERCPU_MODULE_RESERVE 8192 #else #define PERCPU_MODULE_RESERVE 0 #endif #define PERCPU_ENOUGH_ROOM \ (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \ PERCPU_MODULE_RESERVE) #endif /* __ARCH_BLACKFIN_PERCPU__ */
arch/x86/include/asm/linkage.h +10 −6 Original line number Diff line number Diff line Loading @@ -4,11 +4,6 @@ #undef notrace #define notrace __attribute__((no_instrument_function)) #ifdef CONFIG_X86_64 #define __ALIGN .p2align 4,,15 #define __ALIGN_STR ".p2align 4,,15" #endif #ifdef CONFIG_X86_32 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) /* Loading Loading @@ -50,16 +45,25 @@ __asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \ "g" (arg4), "g" (arg5), "g" (arg6)) #endif #endif /* CONFIG_X86_32 */ #ifdef __ASSEMBLY__ #define GLOBAL(name) \ .globl name; \ name: #ifdef CONFIG_X86_64 #define __ALIGN .p2align 4,,15 #define __ALIGN_STR ".p2align 4,,15" #endif #ifdef CONFIG_X86_ALIGNMENT_16 #define __ALIGN .align 16,0x90 #define __ALIGN_STR ".align 16,0x90" #endif #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_LINKAGE_H */
arch/x86/kernel/cpu/amd.c +52 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ #include <asm/io.h> #include <asm/processor.h> #include <asm/apic.h> #include <asm/cpu.h> #ifdef CONFIG_X86_64 # include <asm/numa_64.h> Loading Loading @@ -141,6 +142,55 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) } } static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP /* calling is from identify_secondary_cpu() ? */ if (c->cpu_index == boot_cpu_id) return; /* * Certain Athlons might work (for various values of 'work') in SMP * but they are not certified as MP capable. */ /* Athlon 660/661 is valid. */ if ((c->x86_model == 6) && ((c->x86_mask == 0) || (c->x86_mask == 1))) goto valid_k7; /* Duron 670 is valid */ if ((c->x86_model == 7) && (c->x86_mask == 0)) goto valid_k7; /* * Athlon 662, Duron 671, and Athlon >model 7 have capability * bit. It's worth noting that the A5 stepping (662) of some * Athlon XP's have the MP bit set. * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for * more. */ if (((c->x86_model == 6) && (c->x86_mask >= 2)) || ((c->x86_model == 7) && (c->x86_mask >= 1)) || (c->x86_model > 7)) if (cpu_has_mp) goto valid_k7; /* If we get here, not a certified SMP capable AMD system. */ /* * Don't taint if we are running SMP kernel on a single non-MP * approved Athlon */ WARN_ONCE(1, "WARNING: This combination of AMD" "processors is not suitable for SMP.\n"); if (!test_taint(TAINT_UNSAFE_SMP)) add_taint(TAINT_UNSAFE_SMP); valid_k7: ; #endif } static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) { u32 l, h; Loading Loading @@ -175,6 +225,8 @@ static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) } set_cpu_cap(c, X86_FEATURE_K7); amd_k7_smp_check(c); } #endif Loading
arch/x86/kernel/cpu/intel.c +25 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <asm/uaccess.h> #include <asm/ds.h> #include <asm/bugs.h> #include <asm/cpu.h> #ifdef CONFIG_X86_64 #include <asm/topology.h> Loading Loading @@ -116,6 +117,28 @@ static void __cpuinit trap_init_f00f_bug(void) } #endif static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP /* calling is from identify_secondary_cpu() ? */ if (c->cpu_index == boot_cpu_id) return; /* * Mask B, Pentium, but not Pentium MMX */ if (c->x86 == 5 && c->x86_mask >= 1 && c->x86_mask <= 4 && c->x86_model <= 3) { /* * Remember we have B step Pentia with bugs */ WARN_ONCE(1, "WARNING: SMP operation may be unreliable" "with B stepping processors.\n"); } #endif } static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) { unsigned long lo, hi; Loading Loading @@ -192,6 +215,8 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) #ifdef CONFIG_X86_NUMAQ numaq_tsc_disable(); #endif intel_smp_check(c); } #else static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) Loading
arch/x86/kernel/setup_percpu.c +52 −21 Original line number Diff line number Diff line Loading @@ -42,6 +42,19 @@ unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { }; EXPORT_SYMBOL(__per_cpu_offset); /* * On x86_64 symbols referenced from code should be reachable using * 32bit relocations. Reserve space for static percpu variables in * modules so that they are always served from the first chunk which * is located at the percpu segment base. On x86_32, anything can * address anywhere. No need to reserve space in the first chunk. */ #ifdef CONFIG_X86_64 #define PERCPU_FIRST_CHUNK_RESERVE PERCPU_MODULE_RESERVE #else #define PERCPU_FIRST_CHUNK_RESERVE 0 #endif /** * pcpu_need_numa - determine percpu allocation needs to consider NUMA * Loading Loading @@ -141,7 +154,7 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) { static struct vm_struct vm; pg_data_t *last; size_t ptrs_size; size_t ptrs_size, dyn_size; unsigned int cpu; ssize_t ret; Loading Loading @@ -169,12 +182,14 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) * Currently supports only single page. Supporting multiple * pages won't be too difficult if it ever becomes necessary. */ pcpur_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE); if (pcpur_size > PMD_SIZE) { pr_warning("PERCPU: static data is larger than large page, " "can't use large page\n"); return -EINVAL; } dyn_size = pcpur_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; /* allocate pointer array and alloc large pages */ ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0])); Loading Loading @@ -217,8 +232,9 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) pr_info("PERCPU: Remapped at %p with large pages, static data " "%zu bytes\n", vm.addr, static_size); ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, PMD_SIZE, pcpur_size - static_size, vm.addr, NULL); ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, PERCPU_FIRST_CHUNK_RESERVE, PMD_SIZE, dyn_size, vm.addr, NULL); goto out_free_ar; enomem: Loading @@ -241,24 +257,31 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) * Embedding allocator * * The first chunk is sized to just contain the static area plus * PERCPU_DYNAMIC_RESERVE and allocated as a contiguous area using * bootmem allocator and used as-is without being mapped into vmalloc * area. This enables the first chunk to piggy back on the linear * physical PMD mapping and doesn't add any additional pressure to * TLB. * module and dynamic reserves, and allocated as a contiguous area * using bootmem allocator and used as-is without being mapped into * vmalloc area. This enables the first chunk to piggy back on the * linear physical PMD mapping and doesn't add any additional pressure * to TLB. Note that if the needed size is smaller than the minimum * unit size, the leftover is returned to the bootmem allocator. */ static void *pcpue_ptr __initdata; static size_t pcpue_size __initdata; static size_t pcpue_unit_size __initdata; static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) { return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + ((size_t)pageno << PAGE_SHIFT)); size_t off = (size_t)pageno << PAGE_SHIFT; if (off >= pcpue_size) return NULL; return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + off); } static ssize_t __init setup_pcpu_embed(size_t static_size) { unsigned int cpu; size_t dyn_size; /* * If large page isn't supported, there's no benefit in doing Loading @@ -269,25 +292,32 @@ static ssize_t __init setup_pcpu_embed(size_t static_size) return -EINVAL; /* allocate and copy */ pcpue_unit_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); pcpue_unit_size = max_t(size_t, pcpue_unit_size, PCPU_MIN_UNIT_SIZE); pcpue_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE); pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); dyn_size = pcpue_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size, PAGE_SIZE); if (!pcpue_ptr) return -ENOMEM; for_each_possible_cpu(cpu) memcpy(pcpue_ptr + cpu * pcpue_unit_size, __per_cpu_load, static_size); for_each_possible_cpu(cpu) { void *ptr = pcpue_ptr + cpu * pcpue_unit_size; free_bootmem(__pa(ptr + pcpue_size), pcpue_unit_size - pcpue_size); memcpy(ptr, __per_cpu_load, static_size); } /* we're ready, commit */ pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n", pcpue_unit_size >> PAGE_SHIFT, pcpue_ptr, static_size); pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size); return pcpu_setup_first_chunk(pcpue_get_page, static_size, pcpue_unit_size, pcpue_unit_size - static_size, pcpue_ptr, NULL); PERCPU_FIRST_CHUNK_RESERVE, pcpue_unit_size, dyn_size, pcpue_ptr, NULL); } /* Loading Loading @@ -344,7 +374,8 @@ static ssize_t __init setup_pcpu_4k(size_t static_size) pr_info("PERCPU: Allocated %d 4k pages, static data %zu bytes\n", pcpu4k_nr_static_pages, static_size); ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size, 0, 0, NULL, ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size, PERCPU_FIRST_CHUNK_RESERVE, -1, -1, NULL, pcpu4k_populate_pte); goto out_free_ar; Loading