2008-10-23 12:26:29 +07:00
|
|
|
#ifndef _ASM_X86_SMP_H
|
|
|
|
#define _ASM_X86_SMP_H
|
2008-03-04 00:12:29 +07:00
|
|
|
#ifndef __ASSEMBLY__
|
2008-03-04 00:12:31 +07:00
|
|
|
#include <linux/cpumask.h>
|
2008-03-04 00:12:40 +07:00
|
|
|
#include <linux/init.h>
|
2008-03-20 00:25:18 +07:00
|
|
|
#include <asm/percpu.h>
|
2008-03-04 00:12:31 +07:00
|
|
|
|
2008-03-28 00:06:00 +07: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 13:50:24 +07:00
|
|
|
#include <asm/cpumask.h>
|
2011-03-03 09:34:50 +07:00
|
|
|
#include <asm/cpufeature.h>
|
2008-03-28 00:06:00 +07:00
|
|
|
|
2008-03-04 00:12:31 +07:00
|
|
|
extern int smp_num_siblings;
|
|
|
|
extern unsigned int num_processors;
|
2008-03-04 00:12:29 +07:00
|
|
|
|
2011-03-03 09:34:50 +07: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 16:56:52 +07: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 06:29:44 +07: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 16:56:52 +07: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 02:21:12 +07:00
|
|
|
|
2009-01-04 20:18:03 +07:00
|
|
|
static inline struct cpumask *cpu_sibling_mask(int cpu)
|
|
|
|
{
|
2009-03-13 11:19:50 +07:00
|
|
|
return per_cpu(cpu_sibling_map, cpu);
|
2009-01-04 20:18:03 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct cpumask *cpu_core_mask(int cpu)
|
|
|
|
{
|
2009-03-13 11:19:50 +07:00
|
|
|
return per_cpu(cpu_core_map, cpu);
|
2009-01-04 20:18:03 +07:00
|
|
|
}
|
|
|
|
|
2011-01-22 06:29:44 +07: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 16:56:52 +07: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-28 23:22:48 +07: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 16:56:52 +07:00
|
|
|
DECLARE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid);
|
2011-01-23 20:37:30 +07:00
|
|
|
#endif
|
2008-03-20 00:25:18 +07:00
|
|
|
|
2008-03-20 00:25:57 +07:00
|
|
|
/* Static state in head.S used to set up a CPU */
|
2011-02-05 07:14:11 +07:00
|
|
|
extern unsigned long stack_start; /* Initial stack pointer address */
|
2008-03-20 00:25:57 +07:00
|
|
|
|
2012-04-20 20:05:42 +07:00
|
|
|
struct task_struct;
|
|
|
|
|
2008-03-04 00:12:32 +07: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 04:37:08 +07:00
|
|
|
void (*stop_other_cpus)(int wait);
|
2008-03-04 00:12:32 +07:00
|
|
|
void (*smp_send_reschedule)(int cpu);
|
2008-06-26 16:21:54 +07:00
|
|
|
|
2012-04-20 20:05:47 +07:00
|
|
|
int (*cpu_up)(unsigned cpu, struct task_struct *tidle);
|
2008-08-22 17:52:11 +07:00
|
|
|
int (*cpu_disable)(void);
|
|
|
|
void (*cpu_die)(unsigned int cpu);
|
|
|
|
void (*play_dead)(void);
|
|
|
|
|
2008-12-17 08:33:59 +07:00
|
|
|
void (*send_call_func_ipi)(const struct cpumask *mask);
|
2008-06-26 16:21:54 +07:00
|
|
|
void (*send_call_func_single_ipi)(int cpu);
|
2008-03-04 00:12:32 +07:00
|
|
|
};
|
|
|
|
|
2008-03-04 00:12:59 +07:00
|
|
|
/* Globals due to paravirt */
|
|
|
|
extern void set_cpu_sibling_map(int cpu);
|
|
|
|
|
2008-03-04 00:12:33 +07:00
|
|
|
#ifdef CONFIG_SMP
|
2008-03-20 00:24:59 +07:00
|
|
|
#ifndef CONFIG_PARAVIRT
|
|
|
|
#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
|
|
|
|
#endif
|
2008-03-04 00:12:33 +07:00
|
|
|
extern struct smp_ops smp_ops;
|
2008-03-04 00:12:34 +07:00
|
|
|
|
2008-03-04 00:12:51 +07:00
|
|
|
static inline void smp_send_stop(void)
|
|
|
|
{
|
2010-10-12 04:37:08 +07:00
|
|
|
smp_ops.stop_other_cpus(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void stop_other_cpus(void)
|
|
|
|
{
|
|
|
|
smp_ops.stop_other_cpus(1);
|
2008-03-04 00:12:51 +07:00
|
|
|
}
|
|
|
|
|
2008-03-04 00:12:37 +07:00
|
|
|
static inline void smp_prepare_boot_cpu(void)
|
|
|
|
{
|
|
|
|
smp_ops.smp_prepare_boot_cpu();
|
|
|
|
}
|
|
|
|
|
2008-03-04 00:12:38 +07:00
|
|
|
static inline void smp_prepare_cpus(unsigned int max_cpus)
|
|
|
|
{
|
|
|
|
smp_ops.smp_prepare_cpus(max_cpus);
|
|
|
|
}
|
|
|
|
|
2008-03-04 00:12:39 +07:00
|
|
|
static inline void smp_cpus_done(unsigned int max_cpus)
|
|
|
|
{
|
|
|
|
smp_ops.smp_cpus_done(max_cpus);
|
|
|
|
}
|
|
|
|
|
2012-04-20 20:05:42 +07:00
|
|
|
static inline int __cpu_up(unsigned int cpu, struct task_struct *tidle)
|
2008-03-04 00:12:36 +07:00
|
|
|
{
|
2012-04-20 20:05:47 +07:00
|
|
|
return smp_ops.cpu_up(cpu, tidle);
|
2008-03-04 00:12:36 +07:00
|
|
|
}
|
|
|
|
|
2008-08-22 17:52:11 +07: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 00:12:34 +07:00
|
|
|
static inline void smp_send_reschedule(int cpu)
|
|
|
|
{
|
|
|
|
smp_ops.smp_send_reschedule(cpu);
|
|
|
|
}
|
2008-03-04 00:12:35 +07:00
|
|
|
|
2008-06-26 16:21:54 +07:00
|
|
|
static inline void arch_send_call_function_single_ipi(int cpu)
|
|
|
|
{
|
|
|
|
smp_ops.send_call_func_single_ipi(cpu);
|
|
|
|
}
|
|
|
|
|
2009-03-13 11:19:51 +07:00
|
|
|
static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
|
2008-03-04 00:12:35 +07:00
|
|
|
{
|
2009-03-13 11:19:51 +07:00
|
|
|
smp_ops.send_call_func_ipi(mask);
|
2008-03-04 00:12:35 +07:00
|
|
|
}
|
2008-03-04 00:12:36 +07:00
|
|
|
|
2008-08-22 17:52:14 +07:00
|
|
|
void cpu_disable_common(void);
|
2008-03-04 00:12:37 +07:00
|
|
|
void native_smp_prepare_boot_cpu(void);
|
2008-03-04 00:12:38 +07:00
|
|
|
void native_smp_prepare_cpus(unsigned int max_cpus);
|
2008-03-04 00:12:39 +07:00
|
|
|
void native_smp_cpus_done(unsigned int max_cpus);
|
2012-04-20 20:05:47 +07:00
|
|
|
int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
|
2008-08-22 17:52:11 +07:00
|
|
|
int native_cpu_disable(void);
|
|
|
|
void native_cpu_die(unsigned int cpu);
|
|
|
|
void native_play_dead(void);
|
2008-08-22 17:52:13 +07:00
|
|
|
void play_dead_common(void);
|
2010-01-22 22:01:03 +07:00
|
|
|
void wbinvd_on_cpu(int cpu);
|
|
|
|
int wbinvd_on_all_cpus(void);
|
2008-08-22 17:52:11 +07:00
|
|
|
|
2008-12-17 08:33:59 +07:00
|
|
|
void native_send_call_func_ipi(const struct cpumask *mask);
|
2008-06-26 16:21:54 +07:00
|
|
|
void native_send_call_func_single_ipi(int cpu);
|
2012-04-20 20:05:48 +07:00
|
|
|
void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle);
|
2008-03-04 00:12:40 +07:00
|
|
|
|
2008-03-20 00:25:05 +07:00
|
|
|
void smp_store_cpu_info(int id);
|
2008-03-20 00:25:58 +07:00
|
|
|
#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
|
2008-03-28 00:06:02 +07:00
|
|
|
|
2010-01-22 22:01:03 +07:00
|
|
|
#else /* !CONFIG_SMP */
|
|
|
|
#define wbinvd_on_cpu(cpu) wbinvd()
|
|
|
|
static inline int wbinvd_on_all_cpus(void)
|
|
|
|
{
|
|
|
|
wbinvd();
|
|
|
|
return 0;
|
|
|
|
}
|
2008-09-30 05:29:42 +07:00
|
|
|
#endif /* CONFIG_SMP */
|
2008-03-28 00:06:02 +07:00
|
|
|
|
2008-04-05 02:41:44 +07:00
|
|
|
extern unsigned disabled_cpus __cpuinitdata;
|
|
|
|
|
2008-03-28 00:06:02 +07: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 14:35:27 +07:00
|
|
|
#define raw_smp_processor_id() (this_cpu_read(cpu_number))
|
2008-03-28 00:06:02 +07:00
|
|
|
extern int safe_smp_processor_id(void);
|
|
|
|
|
|
|
|
#elif defined(CONFIG_X86_64_SMP)
|
2012-05-11 14:35:27 +07:00
|
|
|
#define raw_smp_processor_id() (this_cpu_read(cpu_number))
|
2008-03-28 00:06:02 +07: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 00:12:33 +07:00
|
|
|
#endif
|
2008-03-04 00:12:32 +07:00
|
|
|
|
2008-03-28 00:05:58 +07:00
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
|
|
2008-07-11 01:16:49 +07:00
|
|
|
#ifndef CONFIG_X86_64
|
2008-03-28 00:05:58 +07: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 00:40:57 +07:00
|
|
|
return GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
|
2008-03-28 00:05:58 +07:00
|
|
|
}
|
|
|
|
|
2008-03-29 02:12:16 +07:00
|
|
|
#endif
|
|
|
|
|
2008-03-28 00:05:58 +07: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 02:14:26 +07:00
|
|
|
#ifdef CONFIG_DEBUG_NMI_SELFTEST
|
|
|
|
extern void nmi_selftest(void);
|
|
|
|
#else
|
|
|
|
#define nmi_selftest() do { } while (0)
|
|
|
|
#endif
|
|
|
|
|
2008-03-04 00:12:29 +07:00
|
|
|
#endif /* __ASSEMBLY__ */
|
2008-10-23 12:26:29 +07:00
|
|
|
#endif /* _ASM_X86_SMP_H */
|