2008-10-23 13:26:29 +08:00
|
|
|
#ifndef _ASM_X86_SMP_H
|
|
|
|
#define _ASM_X86_SMP_H
|
2008-03-04 01:12:29 +08:00
|
|
|
#ifndef __ASSEMBLY__
|
2008-03-04 01:12:31 +08:00
|
|
|
#include <linux/cpumask.h>
|
2008-03-20 01:25:18 +08:00
|
|
|
#include <asm/percpu.h>
|
2008-03-04 01:12:31 +08:00
|
|
|
|
2008-03-28 01:06:00 +08:00
|
|
|
/*
|
|
|
|
* We need the APIC definitions automatically as part of 'smp.h'
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
|
# include <asm/mpspec.h>
|
|
|
|
# include <asm/apic.h>
|
|
|
|
# ifdef CONFIG_X86_IO_APIC
|
|
|
|
# include <asm/io_apic.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
#include <asm/thread_info.h>
|
2009-01-10 14:50:24 +08:00
|
|
|
#include <asm/cpumask.h>
|
2011-03-03 10:34:50 +08:00
|
|
|
#include <asm/cpufeature.h>
|
2008-03-28 01:06:00 +08:00
|
|
|
|
2008-03-04 01:12:31 +08:00
|
|
|
extern int smp_num_siblings;
|
|
|
|
extern unsigned int num_processors;
|
2008-03-04 01:12:29 +08:00
|
|
|
|
2011-03-03 10:34:50 +08:00
|
|
|
static inline bool cpu_has_ht_siblings(void)
|
|
|
|
{
|
|
|
|
bool has_siblings = false;
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
has_siblings = cpu_has_ht && smp_num_siblings > 1;
|
|
|
|
#endif
|
|
|
|
return has_siblings;
|
|
|
|
}
|
|
|
|
|
x86: Add read_mostly declaration/definition to variables from smp.h
Add "read-mostly" qualifier to the following variables in
smp.h:
- cpu_sibling_map
- cpu_core_map
- cpu_llc_shared_map
- cpu_llc_id
- cpu_number
- x86_cpu_to_apicid
- x86_bios_cpu_apicid
- x86_cpu_to_logical_apicid
As long as all the variables above are only written during the
initialization, this change is meant to prevent the false
sharing. More specifically, on vSMP Foundation platform
x86_cpu_to_apicid shared the same internode_cache_line with
frequently written lapic_events.
From the analysis of the first 33 per_cpu variables out of 219
(memories they describe, to be more specific) the 8 have read_mostly
nature (tlb_vector_offset, cpu_loops_per_jiffy, xen_debug_irq, etc.)
and 25 are frequently written (irq_stack_union, gdt_page,
exception_stacks, idt_desc, etc.).
Assuming that the spread of the rest of the per_cpu variables is
similar, identifying the read mostly memories will make more sense
in terms of long-term code maintenance comparing to identifying
frequently written memories.
Signed-off-by: Vlad Zolotarov <vlad@scalemp.com>
Acked-by: Shai Fultheim <shai@scalemp.com>
Cc: Shai Fultheim (Shai@ScaleMP.com) <Shai@scalemp.com>
Cc: ido@wizery.com
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1719258.EYKzE4Zbq5@vlad
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2012-06-11 17:56:52 +08:00
|
|
|
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
|
|
|
|
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map);
|
2011-01-22 07:29:44 +08:00
|
|
|
/* cpus sharing the last level cache: */
|
x86: Add read_mostly declaration/definition to variables from smp.h
Add "read-mostly" qualifier to the following variables in
smp.h:
- cpu_sibling_map
- cpu_core_map
- cpu_llc_shared_map
- cpu_llc_id
- cpu_number
- x86_cpu_to_apicid
- x86_bios_cpu_apicid
- x86_cpu_to_logical_apicid
As long as all the variables above are only written during the
initialization, this change is meant to prevent the false
sharing. More specifically, on vSMP Foundation platform
x86_cpu_to_apicid shared the same internode_cache_line with
frequently written lapic_events.
From the analysis of the first 33 per_cpu variables out of 219
(memories they describe, to be more specific) the 8 have read_mostly
nature (tlb_vector_offset, cpu_loops_per_jiffy, xen_debug_irq, etc.)
and 25 are frequently written (irq_stack_union, gdt_page,
exception_stacks, idt_desc, etc.).
Assuming that the spread of the rest of the per_cpu variables is
similar, identifying the read mostly memories will make more sense
in terms of long-term code maintenance comparing to identifying
frequently written memories.
Signed-off-by: Vlad Zolotarov <vlad@scalemp.com>
Acked-by: Shai Fultheim <shai@scalemp.com>
Cc: Shai Fultheim (Shai@ScaleMP.com) <Shai@scalemp.com>
Cc: ido@wizery.com
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1719258.EYKzE4Zbq5@vlad
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2012-06-11 17:56:52 +08:00
|
|
|
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
|
|
|
|
DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id);
|
|
|
|
DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
|
x86: cleanup early per cpu variables/accesses v4
* Introduce a new PER_CPU macro called "EARLY_PER_CPU". This is
used by some per_cpu variables that are initialized and accessed
before there are per_cpu areas allocated.
["Early" in respect to per_cpu variables is "earlier than the per_cpu
areas have been setup".]
This patchset adds these new macros:
DEFINE_EARLY_PER_CPU(_type, _name, _initvalue)
EXPORT_EARLY_PER_CPU_SYMBOL(_name)
DECLARE_EARLY_PER_CPU(_type, _name)
early_per_cpu_ptr(_name)
early_per_cpu_map(_name, _idx)
early_per_cpu(_name, _cpu)
The DEFINE macro defines the per_cpu variable as well as the early
map and pointer. It also initializes the per_cpu variable and map
elements to "_initvalue". The early_* macros provide access to
the initial map (usually setup during system init) and the early
pointer. This pointer is initialized to point to the early map
but is then NULL'ed when the actual per_cpu areas are setup. After
that the per_cpu variable is the correct access to the variable.
The early_per_cpu() macro is not very efficient but does show how to
access the variable if you have a function that can be called both
"early" and "late". It tests the early ptr to be NULL, and if not
then it's still valid. Otherwise, the per_cpu variable is used
instead:
#define early_per_cpu(_name, _cpu) \
(early_per_cpu_ptr(_name) ? \
early_per_cpu_ptr(_name)[_cpu] : \
per_cpu(_name, _cpu))
A better method is to actually check the pointer manually. In the
case below, numa_set_node can be called both "early" and "late":
void __cpuinit numa_set_node(int cpu, int node)
{
int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map);
if (cpu_to_node_map)
cpu_to_node_map[cpu] = node;
else
per_cpu(x86_cpu_to_node_map, cpu) = node;
}
* Add a flag "arch_provides_topology_pointers" that indicates pointers
to topology cpumask_t maps are available. Otherwise, use the function
returning the cpumask_t value. This is useful if cpumask_t set size
is very large to avoid copying data on to/off of the stack.
* The coverage of CONFIG_DEBUG_PER_CPU_MAPS has been increased while
the non-debug case has been optimized a bit.
* Remove an unreferenced compiler warning in drivers/base/topology.c
* Clean up #ifdef in setup.c
For inclusion into sched-devel/latest tree.
Based on:
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+ sched-devel/latest .../mingo/linux-2.6-sched-devel.git
Signed-off-by: Mike Travis <travis@sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 03:21:12 +08:00
|
|
|
|
2009-01-04 21:18:03 +08:00
|
|
|
static inline struct cpumask *cpu_sibling_mask(int cpu)
|
|
|
|
{
|
2009-03-13 12:19:50 +08:00
|
|
|
return per_cpu(cpu_sibling_map, cpu);
|
2009-01-04 21:18:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct cpumask *cpu_core_mask(int cpu)
|
|
|
|
{
|
2009-03-13 12:19:50 +08:00
|
|
|
return per_cpu(cpu_core_map, cpu);
|
2009-01-04 21:18:03 +08:00
|
|
|
}
|
|
|
|
|
2011-01-22 07:29:44 +08:00
|
|
|
static inline struct cpumask *cpu_llc_shared_mask(int cpu)
|
|
|
|
{
|
|
|
|
return per_cpu(cpu_llc_shared_map, cpu);
|
|
|
|
}
|
|
|
|
|
x86: Add read_mostly declaration/definition to variables from smp.h
Add "read-mostly" qualifier to the following variables in
smp.h:
- cpu_sibling_map
- cpu_core_map
- cpu_llc_shared_map
- cpu_llc_id
- cpu_number
- x86_cpu_to_apicid
- x86_bios_cpu_apicid
- x86_cpu_to_logical_apicid
As long as all the variables above are only written during the
initialization, this change is meant to prevent the false
sharing. More specifically, on vSMP Foundation platform
x86_cpu_to_apicid shared the same internode_cache_line with
frequently written lapic_events.
From the analysis of the first 33 per_cpu variables out of 219
(memories they describe, to be more specific) the 8 have read_mostly
nature (tlb_vector_offset, cpu_loops_per_jiffy, xen_debug_irq, etc.)
and 25 are frequently written (irq_stack_union, gdt_page,
exception_stacks, idt_desc, etc.).
Assuming that the spread of the rest of the per_cpu variables is
similar, identifying the read mostly memories will make more sense
in terms of long-term code maintenance comparing to identifying
frequently written memories.
Signed-off-by: Vlad Zolotarov <vlad@scalemp.com>
Acked-by: Shai Fultheim <shai@scalemp.com>
Cc: Shai Fultheim (Shai@ScaleMP.com) <Shai@scalemp.com>
Cc: ido@wizery.com
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1719258.EYKzE4Zbq5@vlad
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2012-06-11 17:56:52 +08:00
|
|
|
DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid);
|
|
|
|
DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid);
|
2011-01-29 00:22:48 +08:00
|
|
|
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
|
x86: Add read_mostly declaration/definition to variables from smp.h
Add "read-mostly" qualifier to the following variables in
smp.h:
- cpu_sibling_map
- cpu_core_map
- cpu_llc_shared_map
- cpu_llc_id
- cpu_number
- x86_cpu_to_apicid
- x86_bios_cpu_apicid
- x86_cpu_to_logical_apicid
As long as all the variables above are only written during the
initialization, this change is meant to prevent the false
sharing. More specifically, on vSMP Foundation platform
x86_cpu_to_apicid shared the same internode_cache_line with
frequently written lapic_events.
From the analysis of the first 33 per_cpu variables out of 219
(memories they describe, to be more specific) the 8 have read_mostly
nature (tlb_vector_offset, cpu_loops_per_jiffy, xen_debug_irq, etc.)
and 25 are frequently written (irq_stack_union, gdt_page,
exception_stacks, idt_desc, etc.).
Assuming that the spread of the rest of the per_cpu variables is
similar, identifying the read mostly memories will make more sense
in terms of long-term code maintenance comparing to identifying
frequently written memories.
Signed-off-by: Vlad Zolotarov <vlad@scalemp.com>
Acked-by: Shai Fultheim <shai@scalemp.com>
Cc: Shai Fultheim (Shai@ScaleMP.com) <Shai@scalemp.com>
Cc: ido@wizery.com
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1719258.EYKzE4Zbq5@vlad
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2012-06-11 17:56:52 +08:00
|
|
|
DECLARE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid);
|
2011-01-23 21:37:30 +08:00
|
|
|
#endif
|
2008-03-20 01:25:18 +08:00
|
|
|
|
2008-03-20 01:25:57 +08:00
|
|
|
/* Static state in head.S used to set up a CPU */
|
2011-02-05 08:14:11 +08:00
|
|
|
extern unsigned long stack_start; /* Initial stack pointer address */
|
2008-03-20 01:25:57 +08:00
|
|
|
|
2012-04-20 21:05:42 +08:00
|
|
|
struct task_struct;
|
|
|
|
|
2008-03-04 01:12:32 +08:00
|
|
|
struct smp_ops {
|
|
|
|
void (*smp_prepare_boot_cpu)(void);
|
|
|
|
void (*smp_prepare_cpus)(unsigned max_cpus);
|
|
|
|
void (*smp_cpus_done)(unsigned max_cpus);
|
|
|
|
|
2010-10-12 05:37:08 +08:00
|
|
|
void (*stop_other_cpus)(int wait);
|
2008-03-04 01:12:32 +08:00
|
|
|
void (*smp_send_reschedule)(int cpu);
|
2008-06-26 17:21:54 +08:00
|
|
|
|
2012-04-20 21:05:47 +08:00
|
|
|
int (*cpu_up)(unsigned cpu, struct task_struct *tidle);
|
2008-08-22 18:52:11 +08:00
|
|
|
int (*cpu_disable)(void);
|
|
|
|
void (*cpu_die)(unsigned int cpu);
|
|
|
|
void (*play_dead)(void);
|
|
|
|
|
2008-12-17 09:33:59 +08:00
|
|
|
void (*send_call_func_ipi)(const struct cpumask *mask);
|
2008-06-26 17:21:54 +08:00
|
|
|
void (*send_call_func_single_ipi)(int cpu);
|
2008-03-04 01:12:32 +08:00
|
|
|
};
|
|
|
|
|
2008-03-04 01:12:59 +08:00
|
|
|
/* Globals due to paravirt */
|
|
|
|
extern void set_cpu_sibling_map(int cpu);
|
|
|
|
|
2008-03-04 01:12:33 +08:00
|
|
|
#ifdef CONFIG_SMP
|
2008-03-20 01:24:59 +08:00
|
|
|
#ifndef CONFIG_PARAVIRT
|
|
|
|
#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
|
|
|
|
#endif
|
2008-03-04 01:12:33 +08:00
|
|
|
extern struct smp_ops smp_ops;
|
2008-03-04 01:12:34 +08:00
|
|
|
|
2008-03-04 01:12:51 +08:00
|
|
|
static inline void smp_send_stop(void)
|
|
|
|
{
|
2010-10-12 05:37:08 +08:00
|
|
|
smp_ops.stop_other_cpus(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void stop_other_cpus(void)
|
|
|
|
{
|
|
|
|
smp_ops.stop_other_cpus(1);
|
2008-03-04 01:12:51 +08:00
|
|
|
}
|
|
|
|
|
2008-03-04 01:12:37 +08:00
|
|
|
static inline void smp_prepare_boot_cpu(void)
|
|
|
|
{
|
|
|
|
smp_ops.smp_prepare_boot_cpu();
|
|
|
|
}
|
|
|
|
|
2008-03-04 01:12:38 +08:00
|
|
|
static inline void smp_prepare_cpus(unsigned int max_cpus)
|
|
|
|
{
|
|
|
|
smp_ops.smp_prepare_cpus(max_cpus);
|
|
|
|
}
|
|
|
|
|
2008-03-04 01:12:39 +08:00
|
|
|
static inline void smp_cpus_done(unsigned int max_cpus)
|
|
|
|
{
|
|
|
|
smp_ops.smp_cpus_done(max_cpus);
|
|
|
|
}
|
|
|
|
|
2012-04-20 21:05:42 +08:00
|
|
|
static inline int __cpu_up(unsigned int cpu, struct task_struct *tidle)
|
2008-03-04 01:12:36 +08:00
|
|
|
{
|
2012-04-20 21:05:47 +08:00
|
|
|
return smp_ops.cpu_up(cpu, tidle);
|
2008-03-04 01:12:36 +08:00
|
|
|
}
|
|
|
|
|
2008-08-22 18:52:11 +08:00
|
|
|
static inline int __cpu_disable(void)
|
|
|
|
{
|
|
|
|
return smp_ops.cpu_disable();
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void __cpu_die(unsigned int cpu)
|
|
|
|
{
|
|
|
|
smp_ops.cpu_die(cpu);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void play_dead(void)
|
|
|
|
{
|
|
|
|
smp_ops.play_dead();
|
|
|
|
}
|
|
|
|
|
2008-03-04 01:12:34 +08:00
|
|
|
static inline void smp_send_reschedule(int cpu)
|
|
|
|
{
|
|
|
|
smp_ops.smp_send_reschedule(cpu);
|
|
|
|
}
|
2008-03-04 01:12:35 +08:00
|
|
|
|
2008-06-26 17:21:54 +08:00
|
|
|
static inline void arch_send_call_function_single_ipi(int cpu)
|
|
|
|
{
|
|
|
|
smp_ops.send_call_func_single_ipi(cpu);
|
|
|
|
}
|
|
|
|
|
2009-03-13 12:19:51 +08:00
|
|
|
static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
|
2008-03-04 01:12:35 +08:00
|
|
|
{
|
2009-03-13 12:19:51 +08:00
|
|
|
smp_ops.send_call_func_ipi(mask);
|
2008-03-04 01:12:35 +08:00
|
|
|
}
|
2008-03-04 01:12:36 +08:00
|
|
|
|
2008-08-22 18:52:14 +08:00
|
|
|
void cpu_disable_common(void);
|
2014-10-31 23:49:32 +08:00
|
|
|
void cpu_die_common(unsigned int cpu);
|
2008-03-04 01:12:37 +08:00
|
|
|
void native_smp_prepare_boot_cpu(void);
|
2008-03-04 01:12:38 +08:00
|
|
|
void native_smp_prepare_cpus(unsigned int max_cpus);
|
2008-03-04 01:12:39 +08:00
|
|
|
void native_smp_cpus_done(unsigned int max_cpus);
|
2012-04-20 21:05:47 +08:00
|
|
|
int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
|
2008-08-22 18:52:11 +08:00
|
|
|
int native_cpu_disable(void);
|
|
|
|
void native_cpu_die(unsigned int cpu);
|
|
|
|
void native_play_dead(void);
|
2008-08-22 18:52:13 +08:00
|
|
|
void play_dead_common(void);
|
2010-01-22 23:01:03 +08:00
|
|
|
void wbinvd_on_cpu(int cpu);
|
|
|
|
int wbinvd_on_all_cpus(void);
|
2008-08-22 18:52:11 +08:00
|
|
|
|
2008-12-17 09:33:59 +08:00
|
|
|
void native_send_call_func_ipi(const struct cpumask *mask);
|
2008-06-26 17:21:54 +08:00
|
|
|
void native_send_call_func_single_ipi(int cpu);
|
2012-04-20 21:05:48 +08:00
|
|
|
void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle);
|
2008-03-04 01:12:40 +08:00
|
|
|
|
2012-11-14 03:32:41 +08:00
|
|
|
void smp_store_boot_cpu_info(void);
|
2008-03-20 01:25:05 +08:00
|
|
|
void smp_store_cpu_info(int id);
|
2008-03-20 01:25:58 +08:00
|
|
|
#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
|
2008-03-28 01:06:02 +08:00
|
|
|
|
2010-01-22 23:01:03 +08:00
|
|
|
#else /* !CONFIG_SMP */
|
|
|
|
#define wbinvd_on_cpu(cpu) wbinvd()
|
|
|
|
static inline int wbinvd_on_all_cpus(void)
|
|
|
|
{
|
|
|
|
wbinvd();
|
|
|
|
return 0;
|
|
|
|
}
|
2008-09-30 06:29:42 +08:00
|
|
|
#endif /* CONFIG_SMP */
|
2008-03-28 01:06:02 +08:00
|
|
|
|
x86: delete __cpuinit usage from all x86 files
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
are flagged as __cpuinit -- so if we remove the __cpuinit from
arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
content into no-ops as early as possible, since that will get rid
of these warnings. In any case, they are temporary and harmless.
This removes all the arch/x86 uses of the __cpuinit macros from
all C files. x86 only had the one __CPUINIT used in assembly files,
and it wasn't paired off with a .previous or a __FINIT, so we can
delete it directly w/o any corresponding additional change there.
[1] https://lkml.org/lkml/2013/5/20/589
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Acked-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: H. Peter Anvin <hpa@linux.intel.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
2013-06-19 06:23:59 +08:00
|
|
|
extern unsigned disabled_cpus;
|
2008-04-05 03:41:44 +08:00
|
|
|
|
2008-03-28 01:06:02 +08:00
|
|
|
#ifdef CONFIG_X86_32_SMP
|
|
|
|
/*
|
|
|
|
* This function is needed by all SMP systems. It must _always_ be valid
|
|
|
|
* from the initial startup. We map APIC_BASE very early in page_setup(),
|
|
|
|
* so this is correct in the x86 case.
|
|
|
|
*/
|
2012-05-11 15:35:27 +08:00
|
|
|
#define raw_smp_processor_id() (this_cpu_read(cpu_number))
|
2008-03-28 01:06:02 +08:00
|
|
|
extern int safe_smp_processor_id(void);
|
|
|
|
|
|
|
|
#elif defined(CONFIG_X86_64_SMP)
|
2012-05-11 15:35:27 +08:00
|
|
|
#define raw_smp_processor_id() (this_cpu_read(cpu_number))
|
2008-03-28 01:06:02 +08:00
|
|
|
|
|
|
|
#define stack_smp_processor_id() \
|
|
|
|
({ \
|
|
|
|
struct thread_info *ti; \
|
|
|
|
__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK)); \
|
|
|
|
ti->cpu; \
|
|
|
|
})
|
|
|
|
#define safe_smp_processor_id() smp_processor_id()
|
|
|
|
|
2008-03-04 01:12:33 +08:00
|
|
|
#endif
|
2008-03-04 01:12:32 +08:00
|
|
|
|
2008-03-28 01:05:58 +08:00
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
|
|
2008-07-11 02:16:49 +08:00
|
|
|
#ifndef CONFIG_X86_64
|
2008-03-28 01:05:58 +08:00
|
|
|
static inline int logical_smp_processor_id(void)
|
|
|
|
{
|
|
|
|
/* we don't want to mark this access volatile - bad code generation */
|
x86: read apic ID in the !acpi_lapic case
Ed found that on 32-bit, boot_cpu_physical_apicid is not read right,
when the mptable is broken.
Interestingly, actually three paths use/set it:
1. acpi: at that time that is already read from reg
2. mptable: only read from mptable
3. no madt, and no mptable, that use default apic id 0 for 64-bit, -1 for 32-bit
so we could read the apic id for the 2/3 path. We trust the hardware
register more than we trust a BIOS data structure (the mptable).
We can also avoid the double set_fixmap() when acpi_lapic
is used, and also need to move cpu_has_apic earlier and
call apic_disable().
Also when need to update the apic id, we'd better read and
set the apic version as well - so that quirks are applied precisely.
v2: make path 3 with 64bit, use -1 as apic id, so could read it later.
v3: fix whitespace problem pointed out by Ed Swierk
v5: fix boot crash
[ Impact: get correct apic id for bsp other than acpi path ]
Reported-by: Ed Swierk <eswierk@aristanetworks.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
LKML-Reference: <49FC85A9.2070702@kernel.org>
[ v4: sanity-check in the ACPI case too ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-05-03 01:40:57 +08:00
|
|
|
return GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
|
2008-03-28 01:05:58 +08:00
|
|
|
}
|
|
|
|
|
2008-03-29 03:12:16 +08:00
|
|
|
#endif
|
|
|
|
|
2008-03-28 01:05:58 +08:00
|
|
|
extern int hard_smp_processor_id(void);
|
|
|
|
|
|
|
|
#else /* CONFIG_X86_LOCAL_APIC */
|
|
|
|
|
|
|
|
# ifndef CONFIG_SMP
|
|
|
|
# define hard_smp_processor_id() 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
#endif /* CONFIG_X86_LOCAL_APIC */
|
|
|
|
|
2011-10-14 03:14:26 +08:00
|
|
|
#ifdef CONFIG_DEBUG_NMI_SELFTEST
|
|
|
|
extern void nmi_selftest(void);
|
|
|
|
#else
|
|
|
|
#define nmi_selftest() do { } while (0)
|
|
|
|
#endif
|
|
|
|
|
2008-03-04 01:12:29 +08:00
|
|
|
#endif /* __ASSEMBLY__ */
|
2008-10-23 13:26:29 +08:00
|
|
|
#endif /* _ASM_X86_SMP_H */
|