smpboot integration
cover smpboot integration
Hi,
This is a complement to my last patch series. In this one, I integrate smpboot.c The end result is that i386 also uses the new hotplug state machine, and boot cpus via cpu_up, instead of booting them in the preparation step, and only activating later.
The final diffstat says:
59 files changed, 1974 insertions(+), 2752 deletions(-)
Leftovers:
smp.h could also be easily integrated. But this series was too big already setup64.c could also be completely moved to setup.c
Testing and bisectability:
The end result was tested in all my hardware (which includes qemu ;-). It does not mean it will boot _your_ hardware, but I did my best ;-)
The tree at least compiles in more than 20 randconfigs (for each of x86_64 and i386) For i386, each of the subarchitectures was compiled at least once. (By compile, I obviously mean, every patch, individually)
Full diffstat:
a/arch/x86/kernel/smpboot_32.c | 68 - a/arch/x86/kernel/smpboot_64.c | 73 - a/include/asm-x86/nmi_64.h | 89 - arch/x86/kernel/Makefile | 4 arch/x86/kernel/apic_32.c | 81 - arch/x86/kernel/mpparse_32.c | 19 arch/x86/kernel/mpparse_64.c | 12 arch/x86/kernel/nmi_32.c | 2 arch/x86/kernel/smpboot.c | 1071 ++++++++++++++++ arch/x86/kernel/smpboot_32.c | 1617 ++++--------------------- arch/x86/kernel/smpboot_64.c | 949 +------------- b/arch/x86/Kconfig | 2 b/arch/x86/Makefile | 2 b/arch/x86/kernel/Makefile | 2 b/arch/x86/kernel/acpi/boot.c | 2 b/arch/x86/kernel/apic_32.c | 23 b/arch/x86/kernel/apic_64.c | 13 b/arch/x86/kernel/bugs_64.c | 3 b/arch/x86/kernel/mpparse_32.c | 12 b/arch/x86/kernel/mpparse_64.c | 2 b/arch/x86/kernel/nmi_32.c | 2 b/arch/x86/kernel/nmi_64.c | 2 b/arch/x86/kernel/process_32.c | 10 b/arch/x86/kernel/setup.c | 103 + b/arch/x86/kernel/setup64.c | 77 - b/arch/x86/kernel/setup_32.c | 25 b/arch/x86/kernel/setup_64.c | 15 b/arch/x86/kernel/smpboot.c | 77 + b/arch/x86/kernel/smpboot_32.c | 5 b/arch/x86/kernel/smpboot_64.c | 19 b/arch/x86/kernel/traps_64.c | 2 b/arch/x86/mach-voyager/voyager_smp.c | 7 b/arch/x86/mm/k8topology_64.c | 7 b/arch/x86/pci/numa.c | 8 b/arch/x86/vdso/Makefile | 2 b/include/asm-x86/apic.h | 3 b/include/asm-x86/apicdef.h | 7 b/include/asm-x86/mach-bigsmp/mach_apic.h | 7 b/include/asm-x86/mach-default/mach_apic.h | 11 b/include/asm-x86/mach-default/mach_apicdef.h | 5 b/include/asm-x86/mach-default/smpboot_hooks.h | 3 b/include/asm-x86/mach-es7000/mach_apic.h | 8 b/include/asm-x86/mach-summit/mach_apic.h | 4 b/include/asm-x86/mach-visws/smpboot_hooks.h | 5 b/include/asm-x86/mmzone_32.h | 3 b/include/asm-x86/nmi.h | 92 + b/include/asm-x86/nmi_64.h | 3 b/include/asm-x86/smp.h | 3 b/include/asm-x86/smp_32.h | 5 b/include/asm-x86/smp_64.h | 12 b/include/asm-x86/topology.h | 9 include/asm-x86/apic.h | 2 include/asm-x86/apicdef.h | 6 include/asm-x86/mach-default/smpboot_hooks.h | 5 include/asm-x86/nmi.h | 5 include/asm-x86/nmi_32.h | 61 include/asm-x86/smp.h | 29 include/asm-x86/smp_32.h | 16 include/asm-x86/smp_64.h | 15 59 files changed, 1974 insertions(+), 2752 deletions(-)
PATCH 1/79 change var types in __inquire_remote_apic
change some variables' types in __inquire_remote_apic to match x86_64
--- arch/x86/kernel/smpboot_32.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/smpboot_32.c +2 -2
@@ -368,10 +368,10 @@ static void unmap_cpu_to_logical_apicid(int cpu)static inline void __inquire_remote_apic (int apicid) { -int i, regs[] = {APIC_ID >>4 ,APIC_LVR >>4 ,APIC_SPIV >>4 }; +unsigned i, regs[] = {APIC_ID >>4 ,APIC_LVR >>4 ,APIC_SPIV >>4 };char *names[] = {"ID" ,"VERSION" ,"SPIV" };int timeout; -unsigned long status; +u32 status;printk ("Inquiring remote APIC #%d...\n" , apicid);
Signature · 1 line
1.5.0.6
PATCH 2/79 add loglevel to printks
Add loglevel facilities to printks in __inquire_remote_apic. the levels are the ones to match x86_64 ones.
--- arch/x86/kernel/smpboot_32.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-)
arch/x86/kernel/smpboot_32.c +6 -5
@@ -373,17 +373,18 @@ static inline void __inquire_remote_apic(int apicid)int timeout;u32 status; -printk ("Inquiring remote APIC #%d...\n" , apicid); +printk (KERN_INFO "Inquiring remote APIC #%d...\n" , apicid);for (i =0 ; i <ARRAY_SIZE (regs); i++) { -printk ("... APIC #%d %s: " , apicid, names[i]); +printk (KERN_INFO "... APIC #%d %s: " , apicid, names[i]);/* * Wait for idle. */ status =safe_apic_wait_icr_idle ();if (status) -printk ("a previous APIC delivery may have failed\n" ); +printk (KERN_CONT +"a previous APIC delivery may have failed\n" );apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (apicid));apic_write_around (APIC_ICR ,APIC_DM_REMRD | regs[i]);
@@ -397,10 +398,10 @@ static inline void __inquire_remote_apic(int apicid)switch (status) {case APIC_ICR_RR_VALID : status =apic_read (APIC_RRR ); -printk ("%lx\n" , status); +printk (KERN_CONT "%08x\n" , status);break ;default : -printk ("failed\n" ); +printk (KERN_CONT "failed\n" ); } } }
Signature · 1 line
1.5.0.6
PATCH 3/79 use apic_*_around instead of apic_write in x86_64
This patch replaces apic_read() for apic_read_around() and apic_write for apic_write_around() in smpboot_64.c We do it to have a common usage between x86_64 and i386. In the former, it will always simply expand to apic_write
--- arch/x86/kernel/smpboot_64.c | 18 ++++++++++-------- 1 files changed, 10 insertions(+), 8 deletions(-)
arch/x86/kernel/smpboot_64.c +10 -8
@@ -281,8 +281,8 @@ static void inquire_remote_apic(int apicid)printk (KERN_CONT "a previous APIC delivery may have failed\n" ); -apic_write (APIC_ICR2 ,SET_APIC_DEST_FIELD (apicid)); -apic_write (APIC_ICR ,APIC_DM_REMRD | regs[i]); +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (apicid)); +apic_write_around (APIC_ICR ,APIC_DM_REMRD | regs[i]); timeout =0 ; do {
@@ -315,12 +315,12 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta/* * Turn INIT on target chip */ -apic_write (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid)); +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid));/* * Send IPI */ -apic_write (APIC_ICR ,APIC_INT_LEVELTRIG |APIC_INT_ASSERT +apic_write_around (APIC_ICR ,APIC_INT_LEVELTRIG |APIC_INT_ASSERT |APIC_DM_INIT );Dprintk ("Waiting for send to finish...\n" );
@@ -331,10 +331,10 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int staDprintk ("Deasserting INIT.\n" );/* Target chip */ -apic_write (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid)); +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid));/* Send IPI */ -apic_write (APIC_ICR ,APIC_INT_LEVELTRIG |APIC_DM_INIT ); +apic_write_around (APIC_ICR ,APIC_INT_LEVELTRIG |APIC_DM_INIT );Dprintk ("Waiting for send to finish...\n" ); send_status =safe_apic_wait_icr_idle ();
@@ -353,6 +353,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int stafor (j =1 ; j <= num_starts; j++) {Dprintk ("Sending STARTUP #%d.\n" ,j); +apic_read_around (APIC_SPIV );apic_write (APIC_ESR ,0 );apic_read (APIC_ESR );Dprintk ("After apic_write.\n" );
@@ -362,11 +363,11 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta*/ /* Target chip */ -apic_write (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid)); +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid));/* Boot on the stack */ /* Kick the second */ -apic_write (APIC_ICR ,APIC_DM_STARTUP | (start_rip >>12 )); +apic_write_around (APIC_ICR ,APIC_DM_STARTUP | (start_rip>>12 ));/* * Give the other CPU some time to accept the IPI.
@@ -386,6 +387,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta* Due to the Pentium erratum 3AP. */ if (maxlvt >3 ) { +apic_read_around (APIC_SPIV );apic_write (APIC_ESR ,0 ); } accept_status = (apic_read (APIC_ESR ) &0xEF );
Signature · 1 line
1.5.0.6
PATCH 4/79 use start_ipi_hook in x86_64
From: Glauber Costa <[email protected]>
It is used to match i386. The definition for the non-paravirt case is moved to smp.h instead of smp_32.h
--- arch/x86/kernel/smpboot_64.c | 8 ++++++++ include/asm-x86/smp.h | 3 +++ include/asm-x86/smp_32.h | 4 ---- 3 files changed, 11 insertions(+), 4 deletions(-)
arch/x86/kernel/smpboot_64.c +8 -0
@@ -345,6 +345,14 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta num_starts =2 ;/* +* Paravirt / VMI wants a startup IPI hook here to set up the +* target processor state. +*/ +startup_ipi_hook (phys_apicid, (unsigned long ) start_secondary, + (unsigned long ) init_rsp); + + +/* * Run STARTUP IPI loop. */ Dprintk ("#startup loops: %d.\n" , num_starts);
include/asm-x86/smp.h +3 -0
@@ -33,6 +33,9 @@ struct smp_ops {extern void set_cpu_sibling_map (int cpu);#ifdef CONFIG_SMP +#ifndef CONFIG_PARAVIRT +#define startup_ipi_hook (phys_apicid, start_eip, start_esp) do { } while (0) +#endif extern struct smp_ops smp_ops;static inline void smp_send_stop (void )
include/asm-x86/smp_32.h +0 -4
@@ -30,10 +30,6 @@ DECLARE_PER_CPU(u16, cpu_llc_id);DECLARE_PER_CPU (u16, x86_cpu_to_apicid);#ifdef CONFIG_SMP -#ifndef CONFIG_PARAVIRT -#define startup_ipi_hook (phys_apicid, start_eip, start_esp) do { } while (0) -#endif -/* * 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(),
Signature · 1 line
1.5.0.6
PATCH 5/79 add an smp_apply_quirks to smpboot_32.c
From: Glauber Costa <[email protected]>
The split of smp_store_cpu_info in a quirks-only part will ease integration with x86_64
--- arch/x86/kernel/smpboot_32.c | 30 ++++++++++++++++++------------ 1 files changed, 18 insertions(+), 12 deletions(-)
arch/x86/kernel/smpboot_32.c +18 -12
@@ -78,19 +78,8 @@ static void map_cpu_to_logical_apicid(void);/* State of each CPU. */ DEFINE_PER_CPU(int, cpu_state) = { 0 }; -/* -* The bootstrap kernel entry code has set these up. Save them for -* a given CPU -*/ - -void __cpuinit smp_store_cpu_info (int id) +static void __cpuinit smp_apply_quirks (struct cpuinfo_x86 *c) { -struct cpuinfo_x86 *c = &cpu_data (id); - - *c = boot_cpu_data; - c->cpu_index = id; -if (id!=0 ) -identify_secondary_cpu (c);/* * Mask B, Pentium, but not Pentium MMX */
@@ -138,6 +127,23 @@ void __cpuinit smp_store_cpu_info(int id) valid_k7: ; + +} + +/* +* The bootstrap kernel entry code has set these up. Save them for +* a given CPU +*/ + +void __cpuinit smp_store_cpu_info (int id) +{ +struct cpuinfo_x86 *c = &cpu_data (id); + + *c = boot_cpu_data; + c->cpu_index = id; +if (id !=0 ) +identify_secondary_cpu (c); +smp_apply_quirks (c); }static atomic_t init_deasserted;
Signature · 1 line
1.5.0.6
PATCH 6/79 decouple call to print_cpu_info from smp_store_cpu_info
From: Glauber Costa <[email protected]>
This will ease integration with i386
--- arch/x86/kernel/smpboot_64.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
arch/x86/kernel/smpboot_64.c +4 -1
@@ -97,7 +97,6 @@ static void __cpuinit smp_store_cpu_info(int id) *c = boot_cpu_data; c->cpu_index = id;identify_cpu (c); -print_cpu_info (c); }static inline void wait_for_init_deassert (atomic_t *deassert)
@@ -568,6 +567,8 @@ do_rest:if (cpu_isset (cpu, cpu_callin_map)) {/* number CPUs logically, starting from 1 (BSP is 0) */ Dprintk ("CPU has booted.\n" ); +printk (KERN_INFO "CPU%d: " , cpu); +print_cpu_info (&cpu_data (cpu)); }else { boot_error =1 ; if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE))
@@ -751,6 +752,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)*/ setup_boot_clock (); +printk (KERN_INFO "CPU%d: " ,0 ); +print_cpu_info (&cpu_data (0 )); }/*
Signature · 1 line
1.5.0.6
PATCH 7/79 provide specialized identification routines for x86_64
From: Glauber Costa <[email protected]>
provide two specialized identify_secondary_cpu() and identify_boot_cpu() routines for x86_64. Although not strictly needed, they are functionally correct, and will ease integration with i386
--- arch/x86/kernel/setup_64.c | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-)
arch/x86/kernel/setup_64.c +12 -2
@@ -1051,14 +1051,24 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)#endif select_idle_routine (c); -if (c != &boot_cpu_data) -mtrr_ap_init ();#ifdef CONFIG_NUMA numa_add_cpu (smp_processor_id ());#endif } +void __cpuinit identify_boot_cpu (void ) +{ +identify_cpu (&boot_cpu_data); +} + +void __cpuinit identify_secondary_cpu (struct cpuinfo_x86 *c) +{ +BUG_ON (c == &boot_cpu_data); +identify_cpu (c); +mtrr_ap_init (); +} +static __init int setup_noclflush (char *arg) {setup_clear_cpu_cap (X86_FEATURE_CLFLSH );
Signature · 1 line
1.5.0.6
PATCH 8/79 use identify_boot_cpu
From: Glauber Costa <[email protected]>
Call this function instead of identify_cpu in bugs_64.c
--- arch/x86/kernel/bugs_64.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kernel/bugs_64.c +1 -1
@@ -12,7 +12,7 @@void __init check_bugs (void ) { -identify_cpu (&boot_cpu_data); +identify_boot_cpu ();#if !defined(CONFIG_SMP )printk ("CPU: " );print_cpu_info (&boot_cpu_data);
Signature · 1 line
1.5.0.6
PATCH 9/79 call identify_secondary_cpu in smp_store_cpu_info
From: Glauber Costa <[email protected]>
Call it conditionally for secondary cpus. This behaviour matches i386
--- arch/x86/kernel/smpboot_64.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
arch/x86/kernel/smpboot_64.c +2 -1
@@ -96,7 +96,8 @@ static void __cpuinit smp_store_cpu_info(int id) *c = boot_cpu_data; c->cpu_index = id; -identify_cpu (c); +if (id !=0 ) +identify_secondary_cpu (c); }static inline void wait_for_init_deassert (atomic_t *deassert)
Signature · 1 line
1.5.0.6
PATCH 10/79 merge smp_store_cpu_info
From: Glauber Costa <[email protected]>
now that it is the same between arches, put it into smpboot.c
--- arch/x86/kernel/smpboot.c | 77 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 71 +-------------------------------------- arch/x86/kernel/smpboot_64.c | 15 -------- include/asm-x86/smp.h | 2 + include/asm-x86/smp_32.h | 2 - 5 files changed, 80 insertions(+), 87 deletions(-)
arch/x86/kernel/smpboot.c +77 -0
@@ -45,6 +45,83 @@ unsigned char *trampoline_base = __va(SMP_TRAMPOLINE_BASE);/* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; +#ifdef CONFIG_X86_32 +/* Set if we find a B stepping CPU */ +int __cpuinitdata smp_b_stepping; +#endif + +static void __cpuinit smp_apply_quirks (struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_X86_32 +/* +* Mask B, Pentium, but not Pentium MMX +*/ +if (c->x86_vendor ==X86_VENDOR_INTEL && + c->x86 ==5 && + c->x86_mask >=1 && c->x86_mask <=4 && + c->x86_model <=3 ) +/* +* Remember we have B step Pentia with bugs +*/ + smp_b_stepping =1 ; + +/* +* Certain Athlons might work (for various values of 'work') in SMP +* but they are not certified as MP capable. +*/ +if ((c->x86_vendor ==X86_VENDOR_AMD ) && (c->x86 ==6 )) { + +if (num_possible_cpus () ==1 ) + goto valid_k7; + +/* 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. */ +add_taint (TAINT_UNSAFE_SMP ); + } + +valid_k7: + ; +#endif +} + +/* +* The bootstrap kernel entry code has set these up. Save them for +* a given CPU +*/ + +void __cpuinit smp_store_cpu_info (int id) +{ +struct cpuinfo_x86 *c = &cpu_data (id); + + *c = boot_cpu_data; + c->cpu_index = id; +if (id !=0 ) +identify_secondary_cpu (c); +smp_apply_quirks (c); +} + +void __cpuinit set_cpu_sibling_map (int cpu) {int i;
arch/x86/kernel/smpboot_32.c +1 -70
83 lines not on this page · raw message
arch/x86/kernel/smpboot_64.c +0 -15
@@ -85,21 +85,6 @@ struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;#define set_idle_for_cpu (x,p) (idle_thread_array[(x)] = (p))#endif -/* -* The bootstrap kernel entry code has set these up. Save them for -* a given CPU -*/ - -static void __cpuinit smp_store_cpu_info (int id) -{ -struct cpuinfo_x86 *c = &cpu_data (id); - - *c = boot_cpu_data; - c->cpu_index = id; -if (id !=0 ) -identify_secondary_cpu (c); -} -static inline void wait_for_init_deassert (atomic_t *deassert) {while (!atomic_read (deassert))
include/asm-x86/smp.h +2 -0
@@ -88,6 +88,8 @@ extern void prefill_possible_map(void);#define SMP_TRAMPOLINE_BASE 0x6000extern unsigned long setup_trampoline (void ); + +void smp_store_cpu_info (int id);#endif #ifdef CONFIG_X86_32
include/asm-x86/smp_32.h +0 -2
@@ -42,8 +42,6 @@ DECLARE_PER_CPU(int, cpu_number);extern int safe_smp_processor_id (void ); -void __cpuinit smp_store_cpu_info (int id); -/* We don't mark CPUs online until __cpu_up(), so we need another measure */ static inline int num_booting_cpus (void ) {
Signature · 1 line
1.5.0.6
PATCH 11/79 always enable irqs when entering idle
From: Glauber Costa <[email protected]>
This matches x86_64 behaviour, which is a superior one IMHO
--- arch/x86/kernel/process_32.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-)
arch/x86/kernel/process_32.c +7 -2
@@ -127,6 +127,7 @@ void default_idle(void)local_irq_enable ();current_thread_info ()->status |=TS_POLLING ; }else { +local_irq_enable ();/* loop is done by the caller */ cpu_relax (); }
@@ -142,6 +143,7 @@ EXPORT_SYMBOL(default_idle);*/ static void poll_idle (void ) { +local_irq_enable ();cpu_relax (); }
@@ -248,8 +250,11 @@ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)__monitor ((void *)¤t_thread_info ()->flags,0 ,0 );smp_mb ();if (!need_resched ()) -__mwait (ax, cx); - } +__sti_mwait (ax, cx); +else +local_irq_enable (); + }else +local_irq_enable (); }/* Default MONITOR/MWAIT with no hints, used for default C1 state */
Signature · 1 line
1.5.0.6
PATCH 12/79 don't call local_irq_enable before entering idle
From: Glauber Costa <[email protected]>
the call to idle is guaranteed to do it.
--- arch/x86/kernel/smpboot_32.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
arch/x86/kernel/smpboot_32.c +0 -3
@@ -214,9 +214,6 @@ static void __cpuinit start_secondary(void *unused)unlock_ipi_call_lock ();per_cpu (cpu_state,smp_processor_id ()) =CPU_ONLINE ; -/* We can take interrupts now: we're officially "up". */ -local_irq_enable (); -wmb ();cpu_idle (); }
Signature · 1 line
1.5.0.6
PATCH 13/79 move setup_secondary_clock a little bit down in the function
From: Glauber Costa <[email protected]>
This is done so we call setup_secondary_clock() in the same place x86_64 does. A separate patch for this is appearantly not needed. But clock initialization is such a delicate thing, that it's safer to do this way
--- arch/x86/kernel/smpboot_32.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
arch/x86/kernel/smpboot_32.c +2 -1
@@ -185,7 +185,6 @@ static void __cpuinit start_secondary(void *unused)*/ check_tsc_sync_target (); -setup_secondary_clock ();if (nmi_watchdog ==NMI_IO_APIC ) {disable_8259A_irq (0 );enable_NMI_through_LVT0 ();
@@ -214,6 +213,8 @@ static void __cpuinit start_secondary(void *unused)unlock_ipi_call_lock ();per_cpu (cpu_state,smp_processor_id ()) =CPU_ONLINE ; +setup_secondary_clock (); +wmb ();cpu_idle (); }
Signature · 1 line
1.5.0.6
PATCH 14/79 move state update out of ipi_lock
From: Glauber Costa <[email protected]>
it does not need to be inside lock. Do the way i386 does.
--- arch/x86/kernel/smpboot_64.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/smpboot_64.c +2 -2
@@ -233,10 +233,10 @@ void __cpuinit start_secondary(void)*/ spin_unlock (&vector_lock);cpu_set (smp_processor_id (), cpu_online_map); -per_cpu (cpu_state,smp_processor_id ()) =CPU_ONLINE ; -unlock_ipi_call_lock (); +per_cpu (cpu_state,smp_processor_id ()) =CPU_ONLINE ; +setup_secondary_clock ();cpu_idle ();
Signature · 1 line
1.5.0.6
PATCH 15/79 provide APIC_INTEGRATED definition for x86_64
From: Glauber Costa <[email protected]>
it is always integrated, so define as 1.
--- include/asm-x86/apicdef.h | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
include/asm-x86/apicdef.h +5 -1
@@ -22,7 +22,11 @@#define APIC_LVR_MASK 0xFF00FF#define GET_APIC_VERSION (x) ((x)&0xFFu)#define GET_APIC_MAXLVT (x) (((x)>>16)&0xFFu) -#define APIC_INTEGRATED (x) ((x)&0xF0u) +#ifdef CONFIG_X86_32 +# define APIC_INTEGRATED (x) ((x)&0xF0u) +#else +# define APIC_INTEGRATED (x) (1) +#endif #define APIC_XAPIC (x) ((x) >= 0x14)#define APIC_TASKPRI 0x80#define APIC_TPRI_MASK 0xFFu
Signature · 1 line
1.5.0.6
PATCH 16/79 use APIC_INTEGRATED tests in x86_64
From: Glauber Costa <[email protected]>
This patch does not change the behaviour of x86_64, since APIC_INTEGRATED is always defined as (1). But the code now matches exactly i386 version (well, this part of the code, at least)
--- arch/x86/kernel/smpboot_64.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
arch/x86/kernel/smpboot_64.c +13 -1
@@ -295,6 +295,15 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int staunsigned long send_status, accept_status =0 ;int maxlvt, num_starts, j; +/* +* Be paranoid about clearing APIC errors. +*/ +if (APIC_INTEGRATED (apic_version[phys_apicid])) { +apic_read_around (APIC_SPIV ); +apic_write (APIC_ESR ,0 ); +apic_read (APIC_ESR ); + } +Dprintk ("Asserting INIT.\n" );/*
@@ -327,7 +336,10 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int stamb ();atomic_set (&init_deasserted,1 ); - num_starts =2 ; +if (APIC_INTEGRATED (apic_version[phys_apicid])) + num_starts =2 ; +else + num_starts =0 ;/* * Paravirt / VMI wants a startup IPI hook here to set up the
Signature · 1 line
1.5.0.6
PATCH 17/79 add barriers statement
goal is to have i386 and x86_64 closer, so we
add barriers to match
--- arch/x86/kernel/smpboot_32.c | 4 ++++ arch/x86/kernel/smpboot_64.c | 1 + 2 files changed, 5 insertions(+), 0 deletions(-)
arch/x86/kernel/smpboot_32.c +4 -0
@@ -180,6 +180,9 @@ static void __cpuinit start_secondary(void *unused)smp_callin ();while (!cpu_isset (smp_processor_id (), smp_commenced_mask))cpu_relax (); + +/* otherwise gcc will move up smp_processor_id before the cpu_init */ +barrier ();/* * Check TSC synchronization with the BP: */
@@ -432,6 +435,7 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)Dprintk ("Waiting for send to finish...\n" ); send_status =safe_apic_wait_icr_idle (); +mb ();atomic_set (&init_deasserted,1 );/*
arch/x86/kernel/smpboot_64.c +1 -0
@@ -239,6 +239,7 @@ void __cpuinit start_secondary(void)setup_secondary_clock (); +wmb ();cpu_idle (); }
Signature · 1 line
1.5.0.6
PATCH 18/79 isolate sanity checking
From: Glauber Costa <[email protected]>
Isolate all sanity checking in a smp_sanity_check() function as x86_64 does.
--- arch/x86/kernel/smpboot_32.c | 57 ++++++++++++++++++++++------------------- 1 files changed, 31 insertions(+), 26 deletions(-)
arch/x86/kernel/smpboot_32.c +31 -26
@@ -735,10 +735,6 @@ exit: }#endif -/* -* Cycle through the processors sending APIC IPIs to boot each. -*/ -static int boot_cpu_logical_apicid;/* Where the IO area was mapped on multiquad, always 0 otherwise */ void *xquad_portio;
@@ -746,26 +742,8 @@ void *xquad_portio;EXPORT_SYMBOL (xquad_portio);#endif -static void __init smp_boot_cpus (unsigned int max_cpus) +static int __init smp_sanity_check (unsigned max_cpus) { -int apicid, cpu, bit, kicked; -unsigned long bogosum =0 ; - -/* -* Setup boot CPU information -*/ -smp_store_cpu_info (0 );/* Final full version of the data */ -printk ("CPU%d: " ,0 ); -print_cpu_info (&cpu_data (0 )); - - boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); - boot_cpu_logical_apicid =logical_smp_processor_id (); -per_cpu (x86_cpu_to_apicid,0 ) = boot_cpu_physical_apicid; - -current_thread_info ()->cpu =0 ; - -set_cpu_sibling_map (0 ); -/* * If we couldn't find an SMP configuration at boot time, * get out of here now!
@@ -780,7 +758,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)map_cpu_to_logical_apicid ();cpu_set (0 ,per_cpu (cpu_sibling_map,0 ));cpu_set (0 ,per_cpu (cpu_core_map,0 )); -return ; +return -1 ; }/*
@@ -806,7 +784,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)map_cpu_to_logical_apicid ();cpu_set (0 ,per_cpu (cpu_sibling_map,0 ));cpu_set (0 ,per_cpu (cpu_core_map,0 )); -return ; +return -1 ; }verify_local_APIC ();
@@ -828,9 +806,36 @@ static void __init smp_boot_cpus(unsigned int max_cpus)map_cpu_to_logical_apicid ();cpu_set (0 ,per_cpu (cpu_sibling_map,0 ));cpu_set (0 ,per_cpu (cpu_core_map,0 )); -return ; +return -1 ; } +return 0 ; +} + + +/* +* Cycle through the processors sending APIC IPIs to boot each. +*/ +static void __init smp_boot_cpus (unsigned int max_cpus) +{ +int apicid, cpu, bit, kicked; +unsigned long bogosum =0 ; + +/* +* Setup boot CPU information +*/ +smp_store_cpu_info (0 );/* Final full version of the data */ +printk (KERN_INFO "CPU%d: " ,0 ); +print_cpu_info (&cpu_data (0 )); + + boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); + boot_cpu_logical_apicid =logical_smp_processor_id (); +per_cpu (x86_cpu_to_apicid,0 ) = boot_cpu_physical_apicid; + +current_thread_info ()->cpu =0 ; + +set_cpu_sibling_map (0 ); +smp_sanity_check (max_cpus);connect_bsp_APIC ();setup_local_APIC ();map_cpu_to_logical_apicid ();
Signature · 1 line
1.5.0.6
PATCH 19/79 isolate logic to disable smp
From: Glauber Costa <[email protected]>
Put it in a disable_smp() function, as x86_64 does
--- arch/x86/kernel/smpboot_32.c | 32 ++++++++++++++++---------------- 1 files changed, 16 insertions(+), 16 deletions(-)
arch/x86/kernel/smpboot_32.c +16 -16
@@ -742,6 +742,15 @@ void *xquad_portio;EXPORT_SYMBOL (xquad_portio);#endif +static void __init disable_smp (void ) +{ +smpboot_clear_io_apic_irqs (); + phys_cpu_present_map =physid_mask_of_physid (0 ); +map_cpu_to_logical_apicid (); +cpu_set (0 ,per_cpu (cpu_sibling_map,0 )); +cpu_set (0 ,per_cpu (cpu_core_map,0 )); +} +static int __init smp_sanity_check (unsigned max_cpus) {/*
@@ -750,14 +759,10 @@ static int __init smp_sanity_check(unsigned max_cpus)*/ if (!smp_found_config && !acpi_lapic) {printk (KERN_NOTICE "SMP motherboard not detected.\n" ); -smpboot_clear_io_apic_irqs (); - phys_cpu_present_map =physid_mask_of_physid (0 ); +disable_smp ();if (APIC_init_uniprocessor ())printk (KERN_NOTICE "Local APIC not detected." " Using dummy APIC emulation.\n" ); -map_cpu_to_logical_apicid (); -cpu_set (0 ,per_cpu (cpu_sibling_map,0 )); -cpu_set (0 ,per_cpu (cpu_core_map,0 ));return -1 ; }
@@ -779,11 +784,6 @@ static int __init smp_sanity_check(unsigned max_cpus)printk (KERN_ERR "BIOS bug, local APIC #%d not detected!...\n" , boot_cpu_physical_apicid);printk (KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n" ); -smpboot_clear_io_apic_irqs (); - phys_cpu_present_map =physid_mask_of_physid (0 ); -map_cpu_to_logical_apicid (); -cpu_set (0 ,per_cpu (cpu_sibling_map,0 )); -cpu_set (0 ,per_cpu (cpu_core_map,0 ));return -1 ; }
@@ -801,11 +801,6 @@ static int __init smp_sanity_check(unsigned max_cpus)connect_bsp_APIC ();setup_local_APIC (); } -smpboot_clear_io_apic_irqs (); - phys_cpu_present_map =physid_mask_of_physid (0 ); -map_cpu_to_logical_apicid (); -cpu_set (0 ,per_cpu (cpu_sibling_map,0 )); -cpu_set (0 ,per_cpu (cpu_core_map,0 ));return -1 ; }return 0 ;
@@ -835,7 +830,12 @@ static void __init smp_boot_cpus(unsigned int max_cpus)set_cpu_sibling_map (0 ); -smp_sanity_check (max_cpus); +if (smp_sanity_check (max_cpus) <0 ) { +printk (KERN_INFO "SMP disabled\n" ); +disable_smp (); +return ; + } +connect_bsp_APIC ();setup_local_APIC ();map_cpu_to_logical_apicid ();
Signature · 1 line
1.5.0.6
PATCH 20/79 do tests before do_boot_cpu in i386
From: Glauber Costa <[email protected]>
Do tests before do_boot_cpu in native_cpu_up for i386. Tests are a little bit broader than originally, and are the same as x86_64. Test for smp_callin is not applicable right now and is deferred.
--- arch/x86/kernel/smpboot_32.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-)
arch/x86/kernel/smpboot_32.c +13 -5
@@ -711,10 +711,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu)int apicid, ret; apicid =per_cpu (x86_cpu_to_apicid, cpu); -if (apicid ==BAD_APICID ) { - ret = -ENODEV ; - goto exit; - } info.complete = &done; info.apicid = apicid;
@@ -952,10 +948,22 @@ void __init native_smp_prepare_boot_cpu(void)int __cpuinit native_cpu_up (unsigned int cpu) { +int apicid =cpu_present_to_apicid (cpu);unsigned long flags; -#ifdef CONFIG_HOTPLUG_CPU int ret =0 ; +WARN_ON (irqs_disabled ()); + +Dprintk ("++++++++++++++++++++=_---CPU UP %u\n" , cpu); + +if (apicid ==BAD_APICID || apicid == boot_cpu_physical_apicid || + !physid_isset (apicid, phys_cpu_present_map)) { +printk (KERN_ERR "%s: bad cpu %d\n" , __func__, cpu); +return -EINVAL ; + } + +#ifdef CONFIG_HOTPLUG_CPU +/* * We do warm boot only on cpus that had booted earlier * Otherwise cold boot is all handled from smp_boot_cpus().
Signature · 1 line
1.5.0.6
PATCH 21/79 make __smp_prepare_cpu void
From: Glauber Costa <[email protected]>
We have already removed the only condition that could fail here. so just don't test for any return value
--- arch/x86/kernel/smpboot_32.c | 13 +++---------- 1 files changed, 3 insertions(+), 10 deletions(-)
arch/x86/kernel/smpboot_32.c +3 -10
@@ -704,11 +704,11 @@ static void __cpuinit do_warm_boot_cpu(struct work_struct *work)complete (info->complete); } -static int __cpuinit __smp_prepare_cpu (int cpu) +static void __cpuinit __smp_prepare_cpu (int cpu) {DECLARE_COMPLETION_ONSTACK (done);struct warm_boot_cpu_info info; -int apicid, ret; +int apicid; apicid =per_cpu (x86_cpu_to_apicid, cpu);
@@ -725,9 +725,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu)wait_for_completion (&done); zap_low_mappings(); - ret =0 ; -exit: - return ret; }#endif
@@ -950,7 +947,6 @@ int __cpuinit native_cpu_up(unsigned int cpu) {int apicid =cpu_present_to_apicid (cpu);unsigned long flags; -int ret =0 ;WARN_ON (irqs_disabled ());
@@ -971,10 +967,7 @@ int __cpuinit native_cpu_up(unsigned int cpu)* when a cpu is taken offline from cpu_exit_clear(). */ if (!cpu_isset (cpu, cpu_callin_map)) - ret =__smp_prepare_cpu (cpu); - -if (ret) -return -EIO ; +__smp_prepare_cpu (cpu);#endif /* In case one didn't come up */
Signature · 1 line
1.5.0.6
PATCH 22/79 move assignment of CPU_PREPARE before do_boot_cpu
From: Glauber Costa <[email protected]>
Done to match x86_64
--- arch/x86/kernel/smpboot_32.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kernel/smpboot_32.c +1 -1
@@ -958,6 +958,7 @@ int __cpuinit native_cpu_up(unsigned int cpu)return -EINVAL ; } +per_cpu (cpu_state, cpu) =CPU_UP_PREPARE ;#ifdef CONFIG_HOTPLUG_CPU /*
@@ -976,7 +977,6 @@ int __cpuinit native_cpu_up(unsigned int cpu)return -EIO ; } -per_cpu (cpu_state, cpu) =CPU_UP_PREPARE ;/* Unleash the CPU! */ cpu_set (cpu, smp_commenced_mask);
Signature · 1 line
1.5.0.6
PATCH 23/79 unify extern masks declaration
From: Glauber Costa <[email protected]>
take them off smp_{32,64}.h and move to smp.h
--- include/asm-x86/smp.h | 12 ++++++++++++ include/asm-x86/smp_32.h | 8 -------- include/asm-x86/smp_64.h | 11 ----------- 3 files changed, 12 insertions(+), 19 deletions(-)
include/asm-x86/smp.h +12 -0
@@ -3,12 +3,24 @@#ifndef __ASSEMBLY__#include <linux/cpumask.h> #include <linux/init.h> +#include <asm/percpu.h> extern cpumask_t cpu_callout_map;extern int smp_num_siblings;extern unsigned int num_processors; +extern u16 x86_cpu_to_apicid_init[]; +extern u16 x86_bios_cpu_apicid_init[]; +extern void *x86_cpu_to_apicid_early_ptr; +extern void *x86_bios_cpu_apicid_early_ptr; + +DECLARE_PER_CPU (cpumask_t, cpu_sibling_map); +DECLARE_PER_CPU (cpumask_t, cpu_core_map); +DECLARE_PER_CPU (u16, cpu_llc_id); +DECLARE_PER_CPU (u16, x86_cpu_to_apicid); +DECLARE_PER_CPU (u16, x86_bios_cpu_apicid); +/* * Trampoline 80x86 program as an array. */
include/asm-x86/smp_32.h +0 -8
@@ -21,14 +21,6 @@ extern cpumask_t cpu_callin_map;extern void (*mtrr_hook) (void );extern void zap_low_mappings (void ); -extern u16 __initdata x86_cpu_to_apicid_init[]; -extern void *x86_cpu_to_apicid_early_ptr; - -DECLARE_PER_CPU (cpumask_t, cpu_sibling_map); -DECLARE_PER_CPU (cpumask_t, cpu_core_map); -DECLARE_PER_CPU (u16, cpu_llc_id); -DECLARE_PER_CPU (u16, x86_cpu_to_apicid); -#ifdef CONFIG_SMP /* * This function is needed by all SMP systems. It must _always_ be valid
include/asm-x86/smp_64.h +0 -11
@@ -19,17 +19,6 @@ extern cpumask_t cpu_callin_map;extern int smp_call_function_mask (cpumask_t mask,void (*func)(void *),void *info,int wait); -extern u16 __initdata x86_cpu_to_apicid_init[]; -extern u16 __initdata x86_bios_cpu_apicid_init[]; -extern void *x86_cpu_to_apicid_early_ptr; -extern void *x86_bios_cpu_apicid_early_ptr; - -DECLARE_PER_CPU (cpumask_t, cpu_sibling_map); -DECLARE_PER_CPU (cpumask_t, cpu_core_map); -DECLARE_PER_CPU (u16, cpu_llc_id); -DECLARE_PER_CPU (u16, x86_cpu_to_apicid); -DECLARE_PER_CPU (u16, x86_bios_cpu_apicid); -static inline int cpu_present_to_apicid (int mps_cpu) {if (cpu_present (mps_cpu))
Signature · 1 line
1.5.0.6
PATCH 24/79 define bios to apicid mapping
From: Glauber Costa <[email protected]>
This mapping already exists in x86_64, just provide it for i386
--- arch/x86/kernel/smpboot_32.c | 6 ++++++ include/asm-x86/mach-bigsmp/mach_apic.h | 7 ++----- include/asm-x86/mach-es7000/mach_apic.h | 8 +++----- include/asm-x86/mach-summit/mach_apic.h | 3 +-- 4 files changed, 12 insertions(+), 12 deletions(-)
arch/x86/kernel/smpboot_32.c +6 -0
@@ -70,6 +70,12 @@ void *x86_cpu_to_apicid_early_ptr;DEFINE_PER_CPU (u16, x86_cpu_to_apicid) =BAD_APICID ;EXPORT_PER_CPU_SYMBOL (x86_cpu_to_apicid); +u16 x86_bios_cpu_apicid_init[NR_CPUS ]__initdata + = { [0 ...NR_CPUS -1 ] =BAD_APICID }; +void *x86_bios_cpu_apicid_early_ptr; +DEFINE_PER_CPU (u16, x86_bios_cpu_apicid) =BAD_APICID ; +EXPORT_PER_CPU_SYMBOL (x86_bios_cpu_apicid); +u8 apicid_2_node[MAX_APICID ];static void map_cpu_to_logical_apicid (void );
include/asm-x86/mach-bigsmp/mach_apic.h +2 -5
@@ -1,10 +1,7 @@#ifndef __ASM_MACH_APIC_H#define __ASM_MACH_APIC_H - -extern u8 bios_cpu_apicid[]; - -#define xapic_phys_to_log_apicid (cpu) (bios_cpu_apicid[cpu]) +#define xapic_phys_to_log_apicid (cpu) (per_cpu(x86_bios_cpu_apicid, cpu))#define esr_disable (1)static inline int apic_id_registered (void )
@@ -90,7 +87,7 @@ static inline int apicid_to_node(int logical_apicid)static inline int cpu_present_to_apicid (int mps_cpu) {if (mps_cpu <NR_CPUS ) -return (int ) bios_cpu_apicid[mps_cpu]; +return (int )per_cpu (x86_bios_cpu_apicid, mps_cpu);return BAD_APICID ; }
include/asm-x86/mach-es7000/mach_apic.h +3 -5
@@ -1,9 +1,7 @@#ifndef __ASM_MACH_APIC_H#define __ASM_MACH_APIC_H -extern u8 bios_cpu_apicid[]; - -#define xapic_phys_to_log_apicid (cpu) (bios_cpu_apicid[cpu]) +#define xapic_phys_to_log_apicid (cpu) per_cpu(x86_bios_cpu_apicid, cpu)#define esr_disable (1)static inline int apic_id_registered (void )
@@ -80,7 +78,7 @@ extern void enable_apic_mode(void);extern int apic_version [MAX_APICS ];static inline void setup_apic_routing (void ) { -int apic = bios_cpu_apicid[smp_processor_id ()]; +int apic =per_cpu (x86_bios_cpu_apicid,smp_processor_id ());printk ("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n" , (apic_version[apic] ==0x14 ) ?"Physical Cluster" :"Logical Cluster" , nr_ioapics,cpus_addr (TARGET_CPUS )[0 ]);
@@ -102,7 +100,7 @@ static inline int cpu_present_to_apicid(int mps_cpu)if (!mps_cpu)return boot_cpu_physical_apicid;else if (mps_cpu <NR_CPUS ) -return (int ) bios_cpu_apicid[mps_cpu]; +return (int )per_cpu (x86_bios_cpu_apicid, mps_cpu);else return BAD_APICID ; }
include/asm-x86/mach-summit/mach_apic.h +1 -2
@@ -40,7 +40,6 @@ static inline unsigned long check_apicid_present(int bit)#define apicid_cluster (apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) -extern u8 bios_cpu_apicid[];extern u8 cpu_2_logical_apicid[];static inline void init_apic_ldr (void )
@@ -110,7 +109,7 @@ static inline int cpu_to_logical_apicid(int cpu)static inline int cpu_present_to_apicid (int mps_cpu) {if (mps_cpu <NR_CPUS ) -return (int )bios_cpu_apicid[mps_cpu]; +return (int )per_cpu (x86_bios_cpu_apicid, mps_cpu);else return BAD_APICID ; }
Signature · 1 line
1.5.0.6
PATCH 25/79 initialize map pointers in setup_32.c
From: Glauber Costa <[email protected]>
this will serve as a reference as to whether or not to use the per_cpu variables in mpparse. Done the same way as x86_64
--- arch/x86/kernel/setup_32.c | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+), 0 deletions(-)
arch/x86/kernel/setup_32.c +24 -0
@@ -724,6 +724,18 @@ char * __init __attribute__((weak)) memory_setup(void)return machine_specific_memory_setup (); } +#ifdef CONFIG_NUMA +/* +* In the golden day, when everything among i386 and x86_64 will be +* integrated, this will not live here +*/ +void *x86_cpu_to_node_map_early_ptr; +int x86_cpu_to_node_map_init[NR_CPUS ] = { + [0 ...NR_CPUS -1 ] =NUMA_NO_NODE +}; +DEFINE_PER_CPU (int, x86_cpu_to_node_map) =NUMA_NO_NODE ; +#endif +/* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures
@@ -856,6 +868,18 @@ void __init setup_arch(char **cmdline_p)io_delay_init (); +#ifdef CONFIG_X86_SMP +/* +* setup to use the early static init tables during kernel startup +* X86_SMP will exclude sub-arches that don't deal well with it. +*/ + x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init; + x86_bios_cpu_apicid_early_ptr = (void *)x86_bios_cpu_apicid_init; +#ifdef CONFIG_NUMA + x86_cpu_to_node_map_early_ptr = (void *)x86_cpu_to_node_map_init; +#endif +#endif +#ifdef CONFIG_X86_GENERICARCH generic_apic_probe ();#endif
Signature · 1 line
1.5.0.6
PATCH 26/79 make node to apic mapping declarations unconditional
From: Glauber Costa <[email protected]>
Instead of declaring them inside of X86_64 ifdef, do it unconditionally
--- include/asm-x86/topology.h | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
include/asm-x86/topology.h +4 -4
@@ -33,15 +33,15 @@ struct pci_bus;/* Mappings between logical cpu number and node number */ #ifdef CONFIG_X86_32 extern int cpu_to_node_map[]; -#else -DECLARE_PER_CPU (int, x86_cpu_to_node_map); -extern int x86_cpu_to_node_map_init[]; -extern void *x86_cpu_to_node_map_early_ptr;/* Returns the number of the current Node. */ #define numa_node_id () (early_cpu_to_node(raw_smp_processor_id()))#endif +DECLARE_PER_CPU (int, x86_cpu_to_node_map); +extern int x86_cpu_to_node_map_init[]; +extern void *x86_cpu_to_node_map_early_ptr; +extern cpumask_t node_to_cpumask_map[];#define NUMA_NO_NODE (-1)
Signature · 1 line
1.5.0.6
PATCH 27/79 fix alloc_bootmem_pages_node macro
From: Glauber Costa <[email protected]>
missing a semicolon
--- include/asm-x86/mmzone_32.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/asm-x86/mmzone_32.h +1 -1
@@ -129,7 +129,7 @@ static inline int pfn_valid(int pfn) struct pglist_data __maybe_unused \ *__alloc_bootmem_node__pgdat = (pgdat); \__alloc_bootmem_node (NODE_DATA (0 ), (x),PAGE_SIZE , \ - __pa(MAX_DMA_ADDRESS)) \ +__pa (MAX_DMA_ADDRESS )); \ })#define alloc_bootmem_low_pages_node (pgdat, x) \ ({ \
Signature · 1 line
1.5.0.6
PATCH 28/79 use specialized routine for setup per-cpu area
From: Glauber Costa <[email protected]>
We use the same routing as x86_64, moved now to setup.c. Just with a few ifdefs inside.
Note that this routing uses prefill_possible_map(). It has the very nice side effect of allowing hotplugging of cpus that are marked as present but disabled by acpi bios.
--- arch/x86/Kconfig | 2 +- arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/setup.c | 103 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/setup64.c | 77 ------------------------------- arch/x86/kernel/smpboot_32.c | 2 + 5 files changed, 107 insertions(+), 79 deletions(-) create mode 100644 arch/x86/kernel/setup.c
arch/x86/Kconfig +1 -1
@@ -121,7 +121,7 @@ config ARCH_HAS_CPU_RELAX def_bool y config HAVE_SETUP_PER_CPU_AREA - def_bool X86_64 + def_bool X86_64 || (X86_SMP && !X86_VOYAGER) config ARCH_HIBERNATION_POSSIBLE def_bool y
arch/x86/kernel/Makefile +1 -1
@@ -19,7 +19,7 @@ CFLAGS_paravirt.o := $(nostackp) obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o obj-y += traps_$(BITS).o irq_$(BITS).o obj-y += time_$(BITS).o ioport.o ldt.o -obj-y += setup_$(BITS).o i8259_$(BITS).o +obj-y += setup_$(BITS).o i8259_$(BITS).o setup.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o
arch/x86/kernel/setup.c new file +103 -0
103 lines not on this page · raw message
arch/x86/kernel/setup64.c +0 -77
83 lines not on this page · raw message
arch/x86/kernel/smpboot_32.c +2 -0
@@ -665,6 +665,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)unmap_cpu_to_logical_apicid (cpu);cpu_clear (cpu, cpu_callout_map);/* was set here (do_boot_cpu()) */ cpu_clear (cpu, cpu_initialized);/* was set by cpu_init() */ +cpu_clear (cpu, cpu_possible_map); cpucount--; }else {per_cpu (x86_cpu_to_apicid, cpu) = apicid;
@@ -743,6 +744,7 @@ EXPORT_SYMBOL(xquad_portio);static void __init disable_smp (void ) { + cpu_possible_map =cpumask_of_cpu (0 );smpboot_clear_io_apic_irqs (); phys_cpu_present_map =physid_mask_of_physid (0 );map_cpu_to_logical_apicid ();
Signature · 1 line
1.5.0.6
PATCH 29/79 fill bios cpu to apicid maps
From: Glauber Costa <[email protected]>
We fill the per-cpu (or array) that maps
bios cpu id to apicid in mpparse_32.c, the way x86_64 does
--- arch/x86/kernel/mpparse_32.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)
arch/x86/kernel/mpparse_32.c +8 -3
@@ -76,8 +76,6 @@ unsigned disabled_cpus __cpuinitdata;/* Bitmask of physically existing CPUs */ physid_mask_t phys_cpu_present_map; -u8 bios_cpu_apicid[NR_CPUS ] = { [0 ...NR_CPUS -1 ] =BAD_APICID }; -/* * Intel MP BIOS table parsing routines: */
@@ -221,7 +219,14 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m) def_to_bigsmp =1 ; } } - bios_cpu_apicid[num_processors -1 ] = m->mpc_apicid; +/* are we being called early in kernel startup? */ +if (x86_cpu_to_apicid_early_ptr) { +u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr; + bios_cpu_apicid[num_processors -1 ] = m->mpc_apicid; + }else { +int cpu = num_processors -1 ; +per_cpu (x86_bios_cpu_apicid, cpu) = m->mpc_apicid; + } }static void __init MP_bus_info (struct mpc_config_bus *m)
Signature · 1 line
1.5.0.6
PATCH 30/79 fill cpu to apicid and present map in mpparse
From: Glauber Costa <[email protected]>
This is the way x86_64 does, and complement the already present patch that does the bios cpu to apicid mapping here
--- arch/x86/kernel/mpparse_32.c | 19 +++++++++++++++++-- arch/x86/kernel/smpboot_32.c | 24 +++++++----------------- 2 files changed, 24 insertions(+), 19 deletions(-)
arch/x86/kernel/mpparse_32.c +17 -2
@@ -106,7 +106,8 @@ static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitstatic void __cpuinit MP_processor_info (struct mpc_config_processor *m) { -int ver, apicid; +int ver, apicid, cpu; +cpumask_t tmp_map;physid_mask_t phys_cpu;if (!(m->mpc_cpuflag &CPU_ENABLED )) {
@@ -199,6 +200,16 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m)cpu_set (num_processors, cpu_possible_map); num_processors++; +cpus_complement (tmp_map, cpu_present_map); + cpu =first_cpu (tmp_map); + +if (m->mpc_cpuflag &CPU_BOOTPROCESSOR ) +/* +* x86_bios_cpu_apicid is required to have processors listed +* in same order as logical cpu numbers. Hence the first +* entry is BSP, and so on. +*/ + cpu =0 ;/* * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
@@ -221,12 +232,16 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m) }/* are we being called early in kernel startup? */ if (x86_cpu_to_apicid_early_ptr) { +u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr; + + cpu_to_apicid[cpu] = m->mpc_apicid; bios_cpu_apicid[num_processors -1 ] = m->mpc_apicid; }else { -int cpu = num_processors -1 ; +per_cpu (x86_cpu_to_apicid, cpu) = m->mpc_apicid;per_cpu (x86_bios_cpu_apicid, cpu) = m->mpc_apicid; } +cpu_set (cpu, cpu_present_map); }static void __init MP_bus_info (struct mpc_config_bus *m)
arch/x86/kernel/smpboot_32.c +7 -17
@@ -525,16 +525,6 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)#endif /* WAKE_SECONDARY_VIA_INIT */ extern cpumask_t cpu_initialized; -static inline int alloc_cpu_id (void ) -{ -cpumask_t tmp_map; -int cpu; -cpus_complement (tmp_map, cpu_present_map); - cpu =first_cpu (tmp_map); -if (cpu >=NR_CPUS ) -return -ENODEV ; -return cpu; -}#ifdef CONFIG_HOTPLUG_CPU static struct task_struct *__cpuinitdata cpu_idle_tasks[NR_CPUS ];
@@ -605,7 +595,6 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)irq_ctx_init (cpu); -per_cpu (x86_cpu_to_apicid, cpu) = apicid;/* * This grunge runs the startup process for * the targeted processor.
@@ -666,10 +655,8 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)cpu_clear (cpu, cpu_callout_map);/* was set here (do_boot_cpu()) */ cpu_clear (cpu, cpu_initialized);/* was set by cpu_init() */ cpu_clear (cpu, cpu_possible_map); +per_cpu (x86_cpu_to_apicid, cpu) =BAD_APICID ; cpucount--; - }else { -per_cpu (x86_cpu_to_apicid, cpu) = apicid; -cpu_set (cpu, cpu_present_map); }/* mark "stuck" area as not stuck */
@@ -745,6 +732,7 @@ EXPORT_SYMBOL(xquad_portio);static void __init disable_smp (void ) { cpu_possible_map =cpumask_of_cpu (0 ); + cpu_present_map =cpumask_of_cpu (0 );smpboot_clear_io_apic_irqs (); phys_cpu_present_map =physid_mask_of_physid (0 );map_cpu_to_logical_apicid ();
@@ -825,7 +813,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); boot_cpu_logical_apicid =logical_smp_processor_id (); -per_cpu (x86_cpu_to_apicid,0 ) = boot_cpu_physical_apicid;current_thread_info ()->cpu =0 ;
@@ -866,8 +853,11 @@ static void __init smp_boot_cpus(unsigned int max_cpus)continue ;if (max_cpus <= cpucount+1 )continue ; - -if (((cpu =alloc_cpu_id ()) <=0 ) ||do_boot_cpu (apicid, cpu)) +/* Utterly temporary */ +for (cpu =0 ; cpu <NR_CPUS ; cpu++) +if (per_cpu (x86_cpu_to_apicid, cpu) == apicid) +break ; +if (do_boot_cpu (apicid, cpu))printk ("CPU #%d not responding - cannot use it.\n" , apicid);else
Signature · 1 line
1.5.0.6
PATCH 31/79 get rid of cpucount
From: Glauber Costa <[email protected]>
weighting a map will do.
--- arch/x86/kernel/smpboot_32.c | 12 +++--------- 1 files changed, 3 insertions(+), 9 deletions(-)
arch/x86/kernel/smpboot_32.c +3 -9
@@ -166,8 +166,6 @@ static void __cpuinit smp_callin(void)cpu_set (cpuid, cpu_callin_map); } -static int cpucount; -/* * Activate a secondary processor. */
@@ -585,7 +583,6 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)/* start_eip had better be page-aligned! */ start_eip =setup_trampoline (); - ++cpucount;alternatives_smp_switch (1 );/* So we see what's up */
@@ -656,7 +653,6 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)cpu_clear (cpu, cpu_initialized);/* was set by cpu_init() */ cpu_clear (cpu, cpu_possible_map);per_cpu (x86_cpu_to_apicid, cpu) =BAD_APICID ; - cpucount--; }/* mark "stuck" area as not stuck */
@@ -672,7 +668,6 @@ void cpu_exit_clear(void)idle_task_exit (); - cpucount --;cpu_uninit ();irq_ctx_exit (cpu);
@@ -795,7 +790,6 @@ static int __init smp_sanity_check(unsigned max_cpus)return 0 ; } -/* * Cycle through the processors sending APIC IPIs to boot each. */
@@ -851,7 +845,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)if (!check_apicid_present (bit))continue ; -if (max_cpus <= cpucount+1 ) +if (max_cpus <=cpus_weight (cpu_present_map))continue ;/* Utterly temporary */ for (cpu =0 ; cpu <NR_CPUS ; cpu++)
@@ -878,7 +872,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) bogosum +=cpu_data (cpu).loops_per_jiffy;printk (KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n" , - cpucount+1 , +cpus_weight (cpu_present_map), bogosum/(500000 /HZ ), (bogosum/(5000 /HZ ))%100 );
@@ -892,7 +886,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)* approved Athlon */ if (tainted &TAINT_UNSAFE_SMP ) { -if (cpucount) +if (cpus_weight (cpu_present_map))printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n" );else tainted &= ~TAINT_UNSAFE_SMP ;
Signature · 1 line
1.5.0.6
PATCH 32/79 allow user to impress friends.
From: Glauber Costa <[email protected]>
Impressing friends is a very important thing.
Do it in a separate function to make it even more
explicit, and ease integration.
--- arch/x86/kernel/smpboot.c | 20 ++++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 17 ++--------------- 2 files changed, 22 insertions(+), 15 deletions(-)
arch/x86/kernel/smpboot.c +20 -0
@@ -228,6 +228,26 @@ void __init smp_alloc_memory(void) }#endif +void impress_friends (void ) +{ +int cpu; +unsigned long bogosum =0 ; +/* +* Allow the user to impress friends. +*/ +Dprintk ("Before bogomips.\n" ); +for_each_possible_cpu (cpu) +if (cpu_isset (cpu, cpu_callout_map)) + bogosum +=cpu_data (cpu).loops_per_jiffy; +printk (KERN_INFO +"Total of %d processors activated (%lu.%02lu BogoMIPS).\n" , +cpus_weight (cpu_present_map), + bogosum/(500000 /HZ ), + (bogosum/(5000 /HZ ))%100 ); + +Dprintk ("Before bogocount - setting activated=1.\n" ); +} +#ifdef CONFIG_HOTPLUG_CPU void remove_siblinginfo (int cpu) {
arch/x86/kernel/smpboot_32.c +2 -15
@@ -790,13 +790,13 @@ static int __init smp_sanity_check(unsigned max_cpus)return 0 ; } +extern void impress_friends (void );/* * Cycle through the processors sending APIC IPIs to boot each. */ static void __init smp_boot_cpus (unsigned int max_cpus) {int apicid, cpu, bit, kicked; -unsigned long bogosum =0 ;/* * Setup boot CPU information
@@ -863,20 +863,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)*/ smpboot_restore_warm_reset_vector (); -/* -* Allow the user to impress friends. -*/ -Dprintk ("Before bogomips.\n" ); -for_each_possible_cpu (cpu) -if (cpu_isset (cpu, cpu_callout_map)) - bogosum +=cpu_data (cpu).loops_per_jiffy; -printk (KERN_INFO -"Total of %d processors activated (%lu.%02lu BogoMIPS).\n" , -cpus_weight (cpu_present_map), - bogosum/(500000 /HZ ), - (bogosum/(5000 /HZ ))%100 ); - -Dprintk ("Before bogocount - setting activated=1.\n" ); +impress_friends ();if (smp_b_stepping)printk (KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n" );
Signature · 1 line
1.5.0.6
PATCH 33/79 do smp tainting checks in a separate function
From: Glauber Costa <[email protected]>
It will ease integration for x86_64
--- arch/x86/kernel/smpboot.c | 21 +++++++++++++++++++-- arch/x86/kernel/smpboot_32.c | 20 ++------------------ 2 files changed, 21 insertions(+), 20 deletions(-)
arch/x86/kernel/smpboot.c +19 -2
@@ -45,10 +45,8 @@ unsigned char *trampoline_base = __va(SMP_TRAMPOLINE_BASE);/* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; -#ifdef CONFIG_X86_32 /* Set if we find a B stepping CPU */ int __cpuinitdata smp_b_stepping; -#endif static void __cpuinit smp_apply_quirks (struct cpuinfo_x86 *c) {
@@ -105,6 +103,25 @@ valid_k7:#endif } +void smp_checks (void ) +{ +if (smp_b_stepping) +printk (KERN_WARNING "WARNING: SMP operation may be unreliable" +"with B stepping processors.\n" ); + +/* +* Don't taint if we are running SMP kernel on a single non-MP +* approved Athlon +*/ +if (tainted &TAINT_UNSAFE_SMP ) { +if (cpus_weight (cpu_present_map)) +printk (KERN_INFO "WARNING: This combination of AMD" +"processors is not suitable for SMP.\n" ); +else + tainted &= ~TAINT_UNSAFE_SMP ; + } +} +/* * The bootstrap kernel entry code has set these up. Save them for * a given CPU
arch/x86/kernel/smpboot_32.c +2 -18
@@ -59,8 +59,6 @@#include <asm/vmi.h> #include <asm/mtrr.h> -extern int smp_b_stepping; -static cpumask_t smp_commenced_mask;/* which logical CPU number maps to which CPU (physical APIC ID) */
@@ -791,6 +789,7 @@ static int __init smp_sanity_check(unsigned max_cpus) }extern void impress_friends (void ); +extern void smp_checks (void );/* * Cycle through the processors sending APIC IPIs to boot each. */
@@ -865,22 +864,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)impress_friends (); -if (smp_b_stepping) -printk (KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n" ); - -/* -* Don't taint if we are running SMP kernel on a single non-MP -* approved Athlon -*/ -if (tainted &TAINT_UNSAFE_SMP ) { -if (cpus_weight (cpu_present_map)) -printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n" ); -else - tainted &= ~TAINT_UNSAFE_SMP ; - } - -Dprintk ("Boot done.\n" ); - +smp_checks ();/* * construct cpu_sibling_map, so that we can tell sibling CPUs * efficiently.
Signature · 1 line
1.5.0.6
PATCH 34/79 move impress_friends and smp_check to cpus_done
From: Glauber Costa <[email protected]>
the cpu count is changed accordingly: now, what matters is online cpus.
Also, we add those functions for x86_64
--- arch/x86/kernel/smpboot.c | 4 ++-- arch/x86/kernel/smpboot_32.c | 22 ++++++++++++---------- arch/x86/kernel/smpboot_64.c | 8 ++++++++ 3 files changed, 22 insertions(+), 12 deletions(-)
arch/x86/kernel/smpboot.c +2 -2
@@ -114,7 +114,7 @@ void smp_checks(void)* approved Athlon */ if (tainted &TAINT_UNSAFE_SMP ) { -if (cpus_weight (cpu_present_map)) +if (num_online_cpus ())printk (KERN_INFO "WARNING: This combination of AMD" "processors is not suitable for SMP.\n" );else
@@ -258,7 +258,7 @@ void impress_friends(void) bogosum +=cpu_data (cpu).loops_per_jiffy;printk (KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n" , -cpus_weight (cpu_present_map), +num_online_cpus (), bogosum/(500000 /HZ ), (bogosum/(5000 /HZ ))%100 );
arch/x86/kernel/smpboot_32.c +12 -10
@@ -788,8 +788,6 @@ static int __init smp_sanity_check(unsigned max_cpus)return 0 ; } -extern void impress_friends (void ); -extern void smp_checks (void );/* * Cycle through the processors sending APIC IPIs to boot each. */
@@ -858,14 +856,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) }/* -* Cleanup possible dangling ends... -*/ -smpboot_restore_warm_reset_vector (); - -impress_friends (); - -smp_checks (); -/* * construct cpu_sibling_map, so that we can tell sibling CPUs * efficiently. */
@@ -959,8 +949,20 @@ int __cpuinit native_cpu_up(unsigned int cpu)return 0 ; } +extern void impress_friends (void ); +extern void smp_checks (void ); +void __init native_smp_cpus_done (unsigned int max_cpus) { +/* +* Cleanup possible dangling ends... +*/ +smpboot_restore_warm_reset_vector (); + +Dprintk ("Boot done.\n" ); + +impress_friends (); +smp_checks ();#ifdef CONFIG_X86_IO_APIC setup_ioapic_dest ();#endif
arch/x86/kernel/smpboot_64.c +8 -0
@@ -824,12 +824,20 @@ int __cpuinit native_cpu_up(unsigned int cpu)return err; } +extern void impress_friends (void ); +extern void smp_checks (void ); +/* * Finish the SMP boot. */ void __init native_smp_cpus_done (unsigned int max_cpus) {smp_cleanup_boot (); + +Dprintk ("Boot done.\n" ); + +impress_friends (); +smp_checks ();setup_ioapic_dest ();check_nmi_watchdog (); }
Signature · 1 line
1.5.0.6
PATCH 35/79 add subarch support (for headers) to x86_64
From: Glauber Costa <[email protected]>
this patch allows x86_64 to use subarch mach_ headers in practice, since x86_64 does not have any subarch, it will use mach_default. But it will allow for substantially less code duplication
--- arch/x86/Makefile | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
arch/x86/Makefile +0 -1
@@ -151,7 +151,6 @@ mflags-y += -Iinclude/asm-x86/mach-default # 64 bit does not support subarch support - clear sub arch variables fcore-$(CONFIG_X86_64) := mcore-$(CONFIG_X86_64) := -mflags-$(CONFIG_X86_64) := KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y)
Signature · 1 line
1.5.0.6
PATCH 36/79 include mach_wakecpu.h in smpboot_64
From: Glauber Costa <[email protected]>
Do it and also fix conflicts, which automatically makes x86_64 look closer to i386
--- arch/x86/kernel/smpboot_64.c | 11 +++-------- 1 files changed, 3 insertions(+), 8 deletions(-)
arch/x86/kernel/smpboot_64.c +3 -8
@@ -60,6 +60,8 @@#include <asm/hw_irq.h> #include <asm/numa.h> +#include <mach_wakecpu.h> +/* Set when the idlers are all forked */ int smp_threads_ready;
@@ -85,13 +87,6 @@ struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;#define set_idle_for_cpu (x,p) (idle_thread_array[(x)] = (p))#endif -static inline void wait_for_init_deassert (atomic_t *deassert) -{ -while (!atomic_read (deassert)) -cpu_relax (); -return ; -} -static atomic_t init_deasserted__cpuinitdata ;/*
@@ -247,7 +242,7 @@ extern volatile unsigned long init_rsp;extern void (*initial_code)(void );#ifdef APIC_DEBUG -static void inquire_remote_apic (int apicid) +static void __inquire_remote_apic (int apicid) {unsigned i, regs[] = {APIC_ID >>4 ,APIC_LVR >>4 ,APIC_SPIV >>4 };char *names[] = {"ID" ,"VERSION" ,"SPIV" };
Signature · 1 line
1.5.0.6
PATCH 37/79 include smpboot_hooks.h in smpboot_64.c
From: Glauber Costa <[email protected]>
We do it and also fix conflicts, which makes x86_64 automatically closer to i386
--- arch/x86/kernel/smpboot_64.c | 29 +++-------------------------- 1 files changed, 3 insertions(+), 26 deletions(-)
arch/x86/kernel/smpboot_64.c +3 -26
@@ -61,6 +61,7 @@#include <asm/numa.h> #include <mach_wakecpu.h> +#include <smpboot_hooks.h> /* Set when the idlers are all forked */ int smp_threads_ready;
@@ -517,14 +518,7 @@ do_rest:Dprintk ("Setting warm reset code and vector.\n" ); -CMOS_WRITE (0xa ,0xf ); -local_flush_tlb (); -Dprintk ("1.\n" ); - *((volatile unsigned short *)phys_to_virt (0x469 )) = start_rip >>4 ; -Dprintk ("2.\n" ); - *((volatile unsigned short *)phys_to_virt (0x467 )) = start_rip &0xf ; -Dprintk ("3.\n" ); - +smpboot_setup_warm_reset_vector (start_rip);/* * Be paranoid about clearing APIC errors. */
@@ -594,23 +588,6 @@ cycles_t cacheflush_time;unsigned long cache_decay_ticks;/* -* Cleanup possible dangling ends... -*/ -static __cpuinit void smp_cleanup_boot (void ) -{ -/* -* Paranoid: Set warm reset code and vector here back -* to default values. -*/ -CMOS_WRITE (0 ,0xf ); - -/* -* Reset trampoline flag -*/ - *((volatile int *)phys_to_virt (0x467 )) =0 ; -} - -/* * Fall back to non SMP mode after errors. * * RED-PEN audit/test this more. I bet there is more state messed up here.
@@ -827,7 +804,7 @@ extern void smp_checks(void);*/ void __init native_smp_cpus_done (unsigned int max_cpus) { -smp_cleanup_boot (); +smpboot_restore_warm_reset_vector ();Dprintk ("Boot done.\n" );
Signature · 1 line
1.5.0.6
PATCH 38/79 move smp_intr_init away from smpboot_32.c
From: Glauber Costa <[email protected]>
We move it to apic_32.c, since it's irq related anyway, and only called from that file.
--- arch/x86/kernel/apic_32.c | 23 +++++++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 21 --------------------- 2 files changed, 23 insertions(+), 21 deletions(-)
arch/x86/kernel/apic_32.c +23 -0
@@ -1317,6 +1317,29 @@ void smp_error_interrupt(struct pt_regs *regs)irq_exit (); } +#ifdef CONFIG_SMP +void __init smp_intr_init (void ) +{ +/* +* IRQ0 must be given a fixed assignment and initialized, +* because it's used before the IO-APIC is set up. +*/ +set_intr_gate (FIRST_DEVICE_VECTOR , interrupt[0 ]); + +/* +* The reschedule interrupt is a CPU-to-CPU reschedule-helper +* IPI, driven by wakeup. +*/ +set_intr_gate (RESCHEDULE_VECTOR , reschedule_interrupt); + +/* IPI for invalidation */ +set_intr_gate (INVALIDATE_TLB_VECTOR , invalidate_interrupt); + +/* IPI for generic function call */ +set_intr_gate (CALL_FUNCTION_VECTOR , call_function_interrupt); +} +#endif +/* * Initialize APIC interrupts */
arch/x86/kernel/smpboot_32.c +0 -21
@@ -968,24 +968,3 @@ void __init native_smp_cpus_done(unsigned int max_cpus)#endif zap_low_mappings (); } - -void __init smp_intr_init (void ) -{ -/* -* IRQ0 must be given a fixed assignment and initialized, -* because it's used before the IO-APIC is set up. -*/ -set_intr_gate (FIRST_DEVICE_VECTOR , interrupt[0 ]); - -/* -* The reschedule interrupt is a CPU-to-CPU reschedule-helper -* IPI, driven by wakeup. -*/ -set_intr_gate (RESCHEDULE_VECTOR , reschedule_interrupt); - -/* IPI for invalidation */ -set_intr_gate (INVALIDATE_TLB_VECTOR , invalidate_interrupt); - -/* IPI for generic function call */ -set_intr_gate (CALL_FUNCTION_VECTOR , call_function_interrupt); -}
Signature · 1 line
1.5.0.6
PATCH 39/79 don't set maps in native_smp_prepare_boot_cpu()
From: Glauber Costa <[email protected]>
By this time, they are already set in init routines
--- arch/x86/kernel/smpboot_32.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
arch/x86/kernel/smpboot_32.c +0 -3
@@ -889,10 +889,7 @@ void __init native_smp_prepare_boot_cpu(void)init_gdt (cpu);switch_to_new_gdt (); -cpu_set (cpu, cpu_online_map);cpu_set (cpu, cpu_callout_map); -cpu_set (cpu, cpu_present_map); -cpu_set (cpu, cpu_possible_map);__get_cpu_var (cpu_state) =CPU_ONLINE ; }
Signature · 1 line
1.5.0.6
PATCH 40/79 wipe get_nmi_reason out of nmi_64.h
From: Glauber Costa <[email protected]>
use mach_traps when it is supposed to be used.
--- arch/x86/kernel/nmi_64.c | 2 ++ arch/x86/kernel/traps_64.c | 2 ++ include/asm-x86/nmi_64.h | 2 -- 3 files changed, 4 insertions(+), 2 deletions(-)
arch/x86/kernel/nmi_64.c +2 -0
@@ -26,6 +26,8 @@#include <asm/proto.h> #include <asm/mce.h> +#include <mach_traps.h> +int unknown_nmi_panic;int nmi_watchdog_enabled;int panic_on_unrecovered_nmi;
arch/x86/kernel/traps_64.c +2 -0
@@ -33,6 +33,8 @@#include <linux/kdebug.h> #include <linux/utsname.h> +#include <mach_traps.h> +#if defined(CONFIG_EDAC )#include <linux/edac.h> #endif
include/asm-x86/nmi_64.h +0 -2
@@ -36,8 +36,6 @@ static inline void unset_nmi_pm_callback(struct pm_dev * dev)extern void default_do_nmi (struct pt_regs *);extern void die_nmi (char *str,struct pt_regs *regs,int do_panic); -#define get_nmi_reason () inb(0x61) -extern int unknown_nmi_panic;extern int nmi_watchdog_enabled;
Signature · 1 line
1.5.0.6
PATCH 41/79 unify nmi_32.h and nmi_64.h
From: Glauber Costa <[email protected]>
Two more files goes away. nmi_64.h and nmi_32.h gives birth to nmi.h
--- arch/x86/kernel/nmi_32.c | 2 +- include/asm-x86/nmi.h | 92 ++++++++++++++++++++++++++++++++++++++++++++- include/asm-x86/nmi_32.h | 61 ------------------------------ include/asm-x86/nmi_64.h | 88 -------------------------------------------- 4 files changed, 90 insertions(+), 153 deletions(-) delete mode 100644 include/asm-x86/nmi_32.h delete mode 100644 include/asm-x86/nmi_64.h
arch/x86/kernel/nmi_32.c +1 -1
@@ -67,7 +67,7 @@ static __init void nmi_cpu_busy(void *data) }#endif -static int __init check_nmi_watchdog (void ) +int __init check_nmi_watchdog (void ) {unsigned int *prev_nmi_count;int cpu;
include/asm-x86/nmi.h +89 -3
94 lines not on this page · raw message
include/asm-x86/nmi_32.h deleted +0 -61
61 lines not on this page · raw message
include/asm-x86/nmi_64.h deleted +0 -88
88 lines not on this page · raw message
Signature · 1 line
1.5.0.6
PATCH 42/79 call check_nmi_watchdog explicitly in native_smp_cpus_done
From: Glauber Costa <[email protected]>
With this, remove its late_initcall marker from nmi_32.c
--- arch/x86/kernel/nmi_32.c | 2 -- arch/x86/kernel/smpboot_32.c | 1 + 2 files changed, 1 insertions(+), 2 deletions(-)
arch/x86/kernel/nmi_32.c +0 -2
@@ -129,8 +129,6 @@ int __init check_nmi_watchdog(void)kfree (prev_nmi_count);return 0 ; } -/* This needs to happen later in boot so counters are working */ -late_initcall (check_nmi_watchdog);static int __init setup_nmi_watchdog (char *str) {
arch/x86/kernel/smpboot_32.c +1 -0
@@ -963,5 +963,6 @@ void __init native_smp_cpus_done(unsigned int max_cpus)#ifdef CONFIG_X86_IO_APIC setup_ioapic_dest ();#endif +check_nmi_watchdog ();zap_low_mappings (); }
Signature · 1 line
1.5.0.6
PATCH 43/79 call nmi_watchdog_default in i386
From: Glauber Costa <[email protected]>
this does not exist, so it will be an empty macro
--- arch/x86/kernel/smpboot_32.c | 1 + include/asm-x86/nmi.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletions(-)
arch/x86/kernel/smpboot_32.c +1 -0
@@ -876,6 +876,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ void __init native_smp_prepare_cpus (unsigned int max_cpus) { +nmi_watchdog_default (); smp_commenced_mask =cpumask_of_cpu (0 ); cpu_callin_map =cpumask_of_cpu (0 );mb ();
include/asm-x86/nmi.h +3 -1
@@ -39,6 +39,9 @@ static inline void unset_nmi_pm_callback(struct pm_dev *dev)#ifdef CONFIG_X86_64 extern void default_do_nmi (struct pt_regs *);extern void die_nmi (char *str,struct pt_regs *regs,int do_panic); +extern void nmi_watchdog_default (void ); +#else +#define nmi_watchdog_default () do {} while (0)#endif extern int check_nmi_watchdog (void );
@@ -50,7 +53,6 @@ extern int reserve_perfctr_nmi(unsigned int);extern void release_perfctr_nmi (unsigned int );extern int reserve_evntsel_nmi (unsigned int );extern void release_evntsel_nmi (unsigned int ); -extern void nmi_watchdog_default (void );extern void setup_apic_nmi_watchdog (void *);extern void stop_apic_nmi_watchdog (void *);
Signature · 1 line
1.5.0.6
PATCH 44/79 don't initialize sibling and core maps during preparation
From: Glauber Costa <[email protected]>
it is redundant, since it is already done by set_cpu_sibling_map()
--- arch/x86/kernel/smpboot_32.c | 12 ------------ 1 files changed, 0 insertions(+), 12 deletions(-)
arch/x86/kernel/smpboot_32.c +0 -12
@@ -855,18 +855,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) ++kicked; } -/* -* construct cpu_sibling_map, so that we can tell sibling CPUs -* efficiently. -*/ -for_each_possible_cpu (cpu) { -cpus_clear (per_cpu (cpu_sibling_map, cpu)); -cpus_clear (per_cpu (cpu_core_map, cpu)); - } - -cpu_set (0 ,per_cpu (cpu_sibling_map,0 )); -cpu_set (0 ,per_cpu (cpu_core_map,0 )); -smpboot_setup_io_apic ();setup_boot_clock ();
Signature · 1 line
1.5.0.6
PATCH 45/79 fix apic acking of irqs
From: Glauber Costa <[email protected]>
EOI is a write-only register. Using write around will have the effect of reading it, which will make all subsequent reads of the ESR register to return an error code. It was unnotices for quite a while because main sources of reading the ESR register where done prior to apic interrupt enabling.
--- include/asm-x86/apic.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/asm-x86/apic.h +1 -1
@@ -103,7 +103,7 @@ static inline void ack_APIC_irq(void)*/ /* Docs say use 0 for future compatibility */ -apic_write_around (APIC_EOI ,0 ); +apic_write (APIC_EOI ,0 ); }extern int lapic_get_maxlvt (void );
Signature · 1 line
1.5.0.6
PATCH 46/79 schedule work only if keventd is already running
From: Glauber Costa <[email protected]>
Only call schedule_work if keventd is already running. This is already the way x86_64 does
--- arch/x86/kernel/smpboot_32.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
arch/x86/kernel/smpboot_32.c +6 -2
@@ -708,8 +708,12 @@ static void __cpuinit __smp_prepare_cpu(int cpu)clone_pgd_range (swapper_pg_dir, swapper_pg_dir +USER_PGD_PTRS , min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));flush_tlb_all (); -schedule_work (&info.task); -wait_for_completion (&done); +if (!keventd_up () ||current_is_keventd ()) + info.task.func (&info.task); +else { +schedule_work (&info.task); +wait_for_completion (&done); + }zap_low_mappings (); }
Signature · 1 line
1.5.0.6
PATCH 47/79 do not zap_low_mappings in __smp_prepare_cpus
From: Glauber Costa <[email protected]>
It was okay when cpus were cold booted before this point. But with the new state machine, they will not have arrived to the trampoline yet. zapping low mappings will have the bad effect of breaking it completely after paging enablement
--- arch/x86/kernel/smpboot_32.c | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-)
arch/x86/kernel/smpboot_32.c +0 -7
@@ -195,11 +195,6 @@ static void __cpuinit start_secondary(void *unused)enable_NMI_through_LVT0 ();enable_8259A_irq (0 ); } -/* -* low-memory mappings have been cleared, flush them from -* the local TLBs too. -*/ -local_flush_tlb ();/* This must be done before setting cpu_online_map */ set_cpu_sibling_map (raw_smp_processor_id ());
@@ -714,8 +709,6 @@ static void __cpuinit __smp_prepare_cpu(int cpu)schedule_work (&info.task); wait_for_completion(&done); } - -zap_low_mappings (); }#endif
Signature · 1 line
1.5.0.6
PATCH 48/79 boot cpus from cpu_up, instead of prepare_cpus
From: Glauber Costa <[email protected]>
After all the infrastructure work, we're now prepared to boot the cpus from cpu_up, and not from prepare_cpus. So the difference between cold boot and hotplug is effectively over, and the functions are used to the purposes they're meant to.
--- arch/x86/kernel/smpboot_32.c | 48 +---------------------------------------- 1 files changed, 2 insertions(+), 46 deletions(-)
arch/x86/kernel/smpboot_32.c +2 -46
@@ -670,6 +670,7 @@ void cpu_exit_clear(void)cpu_clear (cpu, smp_commenced_mask);unmap_cpu_to_logical_apicid (cpu); } +#endif struct warm_boot_cpu_info {struct completion *complete;
@@ -710,7 +711,6 @@ static void __cpuinit __smp_prepare_cpu(int cpu)wait_for_completion (&done); } } -#endif static int boot_cpu_logical_apicid;/* Where the IO area was mapped on multiquad, always 0 otherwise */
@@ -790,8 +790,6 @@ static int __init smp_sanity_check(unsigned max_cpus)*/ static void __init smp_boot_cpus (unsigned int max_cpus) { -int apicid, cpu, bit, kicked; -/* * Setup boot CPU information */
@@ -819,39 +817,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)setup_portio_remap (); -/* -* Scan the CPU present map and fire up the other CPUs via do_boot_cpu -* -* In clustered apic mode, phys_cpu_present_map is a constructed thus: -* bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the -* clustered apic ID. -*/ -Dprintk ("CPU present map: %lx\n" ,physids_coerce (phys_cpu_present_map)); - - kicked =1 ; -for (bit =0 ; kicked <NR_CPUS && bit <MAX_APICS ; bit++) { - apicid =cpu_present_to_apicid (bit); -/* -* Don't even attempt to start the boot CPU! -*/ -if ((apicid == boot_cpu_apicid) || (apicid ==BAD_APICID )) -continue ; - -if (!check_apicid_present (bit)) -continue ; -if (max_cpus <=cpus_weight (cpu_present_map)) -continue ; -/* Utterly temporary */ -for (cpu =0 ; cpu <NR_CPUS ; cpu++) -if (per_cpu (x86_cpu_to_apicid, cpu) == apicid) -break ; -if (do_boot_cpu (apicid, cpu)) -printk ("CPU #%d not responding - cannot use it.\n" , - apicid); -else - ++kicked; - } -smpboot_setup_io_apic ();setup_boot_clock ();
@@ -895,17 +860,8 @@ int __cpuinit native_cpu_up(unsigned int cpu) }per_cpu (cpu_state, cpu) =CPU_UP_PREPARE ; -#ifdef CONFIG_HOTPLUG_CPU -/* -* We do warm boot only on cpus that had booted earlier -* Otherwise cold boot is all handled from smp_boot_cpus(). -* cpu_callin_map is set during AP kickstart process. Its reset -* when a cpu is taken offline from cpu_exit_clear(). -*/ -if (!cpu_isset (cpu, cpu_callin_map)) -__smp_prepare_cpu (cpu); -#endif +__smp_prepare_cpu (cpu);/* In case one didn't come up */ if (!cpu_isset (cpu, cpu_callin_map)) {
Signature · 1 line
1.5.0.6
PATCH 49/79 get rid of commenced mask.
From: Glauber Costa <[email protected]>
As we now boot cpus from cpu_up, we don't need it.
--- arch/x86/kernel/smpboot_32.c | 8 -------- 1 files changed, 0 insertions(+), 8 deletions(-)
arch/x86/kernel/smpboot_32.c +0 -8
@@ -59,8 +59,6 @@#include <asm/vmi.h> #include <asm/mtrr.h> -static cpumask_t smp_commenced_mask; -/* which logical CPU number maps to which CPU (physical APIC ID) */ u16 x86_cpu_to_apicid_init[NR_CPUS ]__initdata = { [0 ...NR_CPUS -1 ] =BAD_APICID };
@@ -180,8 +178,6 @@ static void __cpuinit start_secondary(void *unused)cpu_init ();preempt_disable ();smp_callin (); -while (!cpu_isset (smp_processor_id (), smp_commenced_mask)) -cpu_relax ();/* otherwise gcc will move up smp_processor_id before the cpu_init */ barrier ();
@@ -667,7 +663,6 @@ void cpu_exit_clear(void)cpu_clear (cpu, cpu_callout_map);cpu_clear (cpu, cpu_callin_map); -cpu_clear (cpu, smp_commenced_mask); unmap_cpu_to_logical_apicid(cpu); }#endif
@@ -827,7 +822,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)void __init native_smp_prepare_cpus (unsigned int max_cpus) {nmi_watchdog_default (); - smp_commenced_mask =cpumask_of_cpu (0 ); cpu_callin_map =cpumask_of_cpu (0 );mb ();smp_boot_cpus (max_cpus);
@@ -869,8 +863,6 @@ int __cpuinit native_cpu_up(unsigned int cpu)return -EIO ; } -/* Unleash the CPU! */ -cpu_set (cpu, smp_commenced_mask);/* * Check TSC synchronization with the AP (keep irqs disabled
Signature · 1 line
1.5.0.6
PATCH 50/79 use create_idle struct in do_boot_cpu
From: Glauber Costa <[email protected]>
Use a new worker, with help of the create_idle struct to fork the idle thread. We now have two workers, the first of them triggered by __smp_prepare_cpu. But the later is going away soon.
--- arch/x86/kernel/smpboot_32.c | 86 ++++++++++++++++++++++++++++------------- 1 files changed, 59 insertions(+), 27 deletions(-)
arch/x86/kernel/smpboot_32.c +59 -27
@@ -79,6 +79,24 @@ static void map_cpu_to_logical_apicid(void);/* State of each CPU. */ DEFINE_PER_CPU(int, cpu_state) = { 0 }; +/* Store all idle threads, this can be reused instead of creating +* a new thread. Also avoids complicated thread destroy functionality +* for idle threads. +*/ +#ifdef CONFIG_HOTPLUG_CPU +/* +* Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is +* removed after init for !CONFIG_HOTPLUG_CPU. +*/ +static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); +#define get_idle_for_cpu (x) (per_cpu(idle_thread_array, x)) +#define set_idle_for_cpu (x, p) (per_cpu(idle_thread_array, x) = (p)) +#else +struct task_struct *idle_thread_array[NR_CPUS ]__cpuinitdata ; +#define get_idle_for_cpu (x) (idle_thread_array[(x)]) +#define set_idle_for_cpu (x, p) (idle_thread_array[(x)] = (p)) +#endif +static atomic_t init_deasserted;static void __cpuinit smp_callin (void )
@@ -513,30 +531,21 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)extern cpumask_t cpu_initialized; -#ifdef CONFIG_HOTPLUG_CPU -static struct task_struct *__cpuinitdata cpu_idle_tasks[NR_CPUS ]; -static inline struct task_struct *__cpuinit alloc_idle_task (int cpu) -{ +struct create_idle { +struct work_struct work;struct task_struct *idle; +struct completion done; +int cpu; +}; -if ((idle = cpu_idle_tasks[cpu]) !=NULL ) { -/* initialize thread_struct. we really want to avoid destroy -* idle tread -*/ - idle->thread.sp = (unsigned long )task_pt_regs (idle); -init_idle (idle, cpu); -return idle; - } - idle =fork_idle (cpu); +static void __cpuinit do_fork_idle (struct work_struct *work) +{ +struct create_idle *c_idle = + container_of(work, struct create_idle, work); -if (!IS_ERR (idle)) - cpu_idle_tasks[cpu] = idle; -return idle; + c_idle->idle =fork_idle (c_idle->cpu); +complete (&c_idle->done); } -#else -#define alloc_idle_task (cpu) fork_idle(cpu) -#endif -static int __cpuinit do_boot_cpu (int apicid,int cpu)/* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
@@ -544,11 +553,15 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)* Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. */ { -struct task_struct *idle;unsigned long boot_error;int timeout;unsigned long start_eip;unsigned short nmi_high =0 , nmi_low =0 ; +struct create_idle c_idle = { + .cpu = cpu, + .done =COMPLETION_INITIALIZER_ONSTACK (c_idle.done), + }; +INIT_WORK (&c_idle.work, do_fork_idle);/* * Save current MTRR state in case it was changed since early boot
@@ -556,19 +569,38 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)*/ mtrr_save_state (); + c_idle.idle =get_idle_for_cpu (cpu); +/* * We can't use kernel_thread since we must avoid to * reschedule the child. */ - idle =alloc_idle_task (cpu); -if (IS_ERR (idle)) -panic ("failed fork for CPU %d" , cpu); +if (c_idle.idle) { + c_idle.idle->thread.sp = (unsigned long ) (((struct pt_regs *) + (THREAD_SIZE +task_stack_page (c_idle.idle))) -1 ); +init_idle (c_idle.idle, cpu); + goto do_rest; + } + +if (!keventd_up () ||current_is_keventd ()) + c_idle.work.func (&c_idle.work); +else { +schedule_work (&c_idle.work); +wait_for_completion (&c_idle.done); + } + +if (IS_ERR (c_idle.idle)) { +printk (KERN_ERR "failed fork for CPU %d\n" , cpu); +return PTR_ERR (c_idle.idle); + } +set_idle_for_cpu (cpu, c_idle.idle); +do_rest: +per_cpu (current_task, cpu) = c_idle.idle;init_gdt (cpu); -per_cpu (current_task, cpu) = idle; early_gdt_descr.address = (unsigned long )get_cpu_gdt_table (cpu); - idle->thread.ip = (unsigned long ) start_secondary; + c_idle.idle->thread.ip = (unsigned long ) start_secondary;/* start_eip had better be page-aligned! */ start_eip =setup_trampoline ();
@@ -577,7 +609,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)/* So we see what's up */ printk ("Booting processor %d/%d ip %lx\n" , cpu, apicid, start_eip);/* Stack for startup_32 can be just as for start_secondary onwards */ - stack_start.sp = (void *) idle->thread.sp; + stack_start.sp = (void *) c_idle.idle->thread.sp;irq_ctx_init (cpu);
Signature · 1 line
1.5.0.6
PATCH 51/79 don't span a new worker in __smp_prepare_cpu
From: Glauber Costa <[email protected]>
We can do it now that do_boot_cpu has its own worker.
--- arch/x86/kernel/smpboot_32.c | 30 ++---------------------------- 1 files changed, 2 insertions(+), 28 deletions(-)
arch/x86/kernel/smpboot_32.c +2 -28
@@ -699,44 +699,18 @@ void cpu_exit_clear(void) }#endif -struct warm_boot_cpu_info { -struct completion *complete; -struct work_struct task; -int apicid; -int cpu; -}; - -static void __cpuinit do_warm_boot_cpu (struct work_struct *work) -{ -struct warm_boot_cpu_info *info = - container_of(work, struct warm_boot_cpu_info, task); -do_boot_cpu (info->apicid, info->cpu); -complete (info->complete); -} -static void __cpuinit __smp_prepare_cpu (int cpu) { -DECLARE_COMPLETION_ONSTACK (done); -struct warm_boot_cpu_info info;int apicid; apicid =per_cpu (x86_cpu_to_apicid, cpu); - info.complete = &done; - info.apicid = apicid; - info.cpu = cpu; -INIT_WORK (&info.task, do_warm_boot_cpu); -/* init low mem mapping */ clone_pgd_range (swapper_pg_dir, swapper_pg_dir +USER_PGD_PTRS , min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));flush_tlb_all (); -if (!keventd_up () ||current_is_keventd ()) - info.task.func (&info.task); -else { -schedule_work (&info.task); -wait_for_completion (&done); - } + +do_boot_cpu (apicid, cpu); }static int boot_cpu_logical_apicid;
Signature · 1 line
1.5.0.6
PATCH 52/79 modify smp_callin in x86_64 to look like i386
From: Glauber Costa <[email protected]>
We introduce empty macros just to make them look like the same
--- arch/x86/kernel/smpboot_64.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
arch/x86/kernel/smpboot_64.c +5 -0
@@ -90,6 +90,9 @@ struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;static atomic_t init_deasserted__cpuinitdata ; +#define smp_callin_clear_local_apic () do {} while (0) +#define map_cpu_to_logical_apicid () do {} while (0) +/* * Report back to the Boot Processor. * Running on AP.
@@ -152,8 +155,10 @@ void __cpuinit smp_callin(void)*/ Dprintk ("CALLIN, before setup_local_APIC().\n" ); +smp_callin_clear_local_apic ();setup_local_APIC ();end_local_APIC_setup (); +map_cpu_to_logical_apicid ();/* * Get our bogomips.
Signature · 1 line
1.5.0.6
PATCH 53/79 wrap esr setting up in i386 in lapic_setup_esr
From: Glauber Costa <[email protected]>
it is a little bit more complicated than x86_64 due to erratas and other stuff, but its existance will ease integration
--- arch/x86/kernel/apic_32.c | 73 ++++++++++++++++++++++++-------------------- 1 files changed, 40 insertions(+), 33 deletions(-)
arch/x86/kernel/apic_32.c +40 -33
@@ -897,12 +897,50 @@ void __init init_bsp_APIC(void)apic_write_around (APIC_LVT1 , value); } +void __cpuinit lapic_setup_esr (void ) +{ +unsigned long oldvalue, value, maxlvt; +if (lapic_is_integrated () && !esr_disable) { +/* !82489DX */ + maxlvt =lapic_get_maxlvt (); +if (maxlvt >3 )/* Due to the Pentium erratum 3AP. */ +apic_write (APIC_ESR ,0 ); + oldvalue =apic_read (APIC_ESR ); + +/* enables sending errors */ + value =ERROR_APIC_VECTOR ; +apic_write_around (APIC_LVTERR , value); +/* +* spec says clear errors after enabling vector. +*/ +if (maxlvt >3 ) +apic_write (APIC_ESR ,0 ); + value =apic_read (APIC_ESR ); +if (value != oldvalue) +apic_printk (APIC_VERBOSE ,"ESR value before enabling " +"vector: 0x%08lx after: 0x%08lx\n" , + oldvalue, value); + }else { +if (esr_disable) +/* +* Something untraceable is creating bad interrupts on +* secondary quads ... for the moment, just leave the +* ESR disabled - we can't do anything useful with the +* errors anyway - mbligh +*/ +printk (KERN_INFO "Leaving ESR disabled.\n" ); +else +printk (KERN_INFO "No ESR for 82489DX.\n" ); + } +} + +/** * setup_local_APIC - setup the local APIC */ void __cpuinit setup_local_APIC (void ) { -unsigned long oldvalue, value, maxlvt, integrated; +unsigned long value, integrated;int i, j;/* Pound the ESR really hard over the head with a big hammer - mbligh */
@@ -1027,38 +1065,7 @@ void __cpuinit setup_local_APIC(void) value |=APIC_LVT_LEVEL_TRIGGER ;apic_write_around (APIC_LVT1 , value); -if (integrated && !esr_disable) { -/* !82489DX */ - maxlvt =lapic_get_maxlvt (); -if (maxlvt >3 )/* Due to the Pentium erratum 3AP. */ -apic_write (APIC_ESR ,0 ); - oldvalue =apic_read (APIC_ESR ); - -/* enables sending errors */ - value =ERROR_APIC_VECTOR ; -apic_write_around (APIC_LVTERR , value); -/* -* spec says clear errors after enabling vector. -*/ -if (maxlvt >3 ) -apic_write (APIC_ESR ,0 ); - value =apic_read (APIC_ESR ); -if (value != oldvalue) -apic_printk (APIC_VERBOSE ,"ESR value before enabling " -"vector: 0x%08lx after: 0x%08lx\n" , - oldvalue, value); - }else { -if (esr_disable) -/* -* Something untraceable is creating bad interrupts on -* secondary quads ... for the moment, just leave the -* ESR disabled - we can't do anything useful with the -* errors anyway - mbligh -*/ -printk (KERN_INFO "Leaving ESR disabled.\n" ); -else -printk (KERN_INFO "No ESR for 82489DX.\n" ); - } +lapic_setup_esr ();/* Disable the local apic timer */ value =apic_read (APIC_LVTT );
Signature · 1 line
1.5.0.6
PATCH 54/79 provide an end_local_APIC_setup function
From: Glauber Costa <[email protected]>
It splits setup_local_APIC in two, providing a function corresponding to the ending part of it. As a side effect, smp_callin looks the same between i386 and x86_64.
--- arch/x86/kernel/apic_32.c | 7 ++++++- arch/x86/kernel/smpboot_32.c | 3 +++ 2 files changed, 9 insertions(+), 1 deletions(-)
arch/x86/kernel/apic_32.c +6 -1
@@ -1064,9 +1064,13 @@ void __cpuinit setup_local_APIC(void)if (!integrated)/* 82489DX */ value |=APIC_LVT_LEVEL_TRIGGER ;apic_write_around (APIC_LVT1 , value); +} -lapic_setup_esr (); +void __cpuinit end_local_APIC_setup (void ) +{ +unsigned long value; +lapic_setup_esr ();/* Disable the local apic timer */ value =apic_read (APIC_LVTT ); value |= (APIC_LVT_MASKED |LOCAL_TIMER_VECTOR );
@@ -1256,6 +1260,7 @@ int __init APIC_init_uniprocessor(void)setup_local_APIC (); +end_local_APIC_setup ();#ifdef CONFIG_X86_IO_APIC if (smp_found_config)if (!skip_ioapic_setup && nr_ioapics)
arch/x86/kernel/smpboot_32.c +3 -0
@@ -161,6 +161,7 @@ static void __cpuinit smp_callin(void)Dprintk ("CALLIN, before setup_local_APIC().\n" );smp_callin_clear_local_apic ();setup_local_APIC (); +end_local_APIC_setup ();map_cpu_to_logical_apicid ();/*
@@ -780,6 +781,7 @@ static int __init smp_sanity_check(unsigned max_cpus)printk (KERN_INFO "activating minimal APIC for NMI watchdog use.\n" );connect_bsp_APIC ();setup_local_APIC (); +end_local_APIC_setup (); }return -1 ; }
@@ -813,6 +815,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)connect_bsp_APIC ();setup_local_APIC (); +end_local_APIC_setup ();map_cpu_to_logical_apicid ();
Signature · 1 line
1.5.0.6
PATCH 55/79 calibrate delay with irqs enabled
From: Glauber Costa <[email protected]>
We do it to make it close to x86_64. The later needs it, otherwise the nmi watchdog can get into the scene and kill us with a hammer.
Enabling irqs here used to trigger a bug in i386. This is because time irq handling relies upon structures that are only initialized after smp initcalls (More precisely, it will find per_cpu(hrtimer_bases, cpu)->cb_pending list not initialized and crash)
--- arch/x86/kernel/smpboot_32.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/x86/kernel/smpboot_32.c +2 -0
@@ -167,7 +167,9 @@ static void __cpuinit smp_callin(void)/* * Get our bogomips. */ +local_irq_enable ();calibrate_delay (); +local_irq_disable ();Dprintk ("Stack at about %p\n" ,&cpuid);/*
Signature · 1 line
1.5.0.6
PATCH 56/79 minor adjustments for do_boot_cpu
From: Glauber Costa <[email protected]>
This patch provides minor adjustments for do_boot_cpus in both architectures to allow for integration
--- arch/x86/kernel/smpboot_32.c | 22 ++++++++++++++-------- arch/x86/kernel/smpboot_64.c | 15 ++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-)
arch/x86/kernel/smpboot_32.c +14 -8
@@ -556,7 +556,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)* Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. */ { -unsigned long boot_error; +unsigned long boot_error =0 ;int timeout;unsigned long start_eip;unsigned short nmi_high =0 , nmi_low =0 ;
@@ -566,11 +566,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) };INIT_WORK (&c_idle.work, do_fork_idle); -/* -* Save current MTRR state in case it was changed since early boot -* (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync: -*/ -mtrr_save_state (); +alternatives_smp_switch (1 ); c_idle.idle =get_idle_for_cpu (cpu);
@@ -607,8 +603,6 @@ do_rest:/* start_eip had better be page-aligned! */ start_eip =setup_trampoline (); -alternatives_smp_switch (1 ); -/* So we see what's up */ printk ("Booting processor %d/%d ip %lx\n" , cpu, apicid, start_eip);/* Stack for startup_32 can be just as for start_secondary onwards */
@@ -628,6 +622,12 @@ do_rest:store_NMI_vector (&nmi_high, &nmi_low);smpboot_setup_warm_reset_vector (start_eip); +/* +* Be paranoid about clearing APIC errors. +*/ +apic_write (APIC_ESR ,0 ); +apic_read (APIC_ESR ); +/* * Starting actual IPI sequence...
@@ -864,6 +864,12 @@ int __cpuinit native_cpu_up(unsigned int cpu)return -EINVAL ; } +/* +* Save current MTRR state in case it was changed since early boot +* (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync: +*/ +mtrr_save_state (); +per_cpu (cpu_state, cpu) =CPU_UP_PREPARE ;__smp_prepare_cpu (cpu);
arch/x86/kernel/smpboot_64.c +6 -9
@@ -432,7 +432,7 @@ static void __cpuinit do_fork_idle(struct work_struct *work)*/ static int __cpuinit do_boot_cpu (int cpu,int apicid) { -unsigned long boot_error; +unsigned long boot_error =0 ;int timeout;unsigned long start_rip;struct create_idle c_idle = {
@@ -531,11 +531,6 @@ do_rest:apic_read (APIC_ESR );/* -* Status is now clean -*/ - boot_error =0 ; - -/* * Starting actual IPI sequence... */ boot_error =wakeup_secondary_via_INIT (apicid, start_rip);
@@ -564,7 +559,7 @@ do_rest:print_cpu_info (&cpu_data (cpu)); }else { boot_error =1 ; -if (*((volatile unsigned char *)phys_to_virt (SMP_TRAMPOLINE_BASE )) +if (*((volatile unsigned char *)trampoline_base) ==0xA5 )/* trampoline started but...? */ printk ("Stuck ??\n" );
@@ -583,10 +578,12 @@ do_rest:cpu_clear (cpu, cpu_present_map);cpu_clear (cpu, cpu_possible_map);per_cpu (x86_cpu_to_apicid, cpu) =BAD_APICID ; -return -EIO ; } -return 0 ; +/* mark "stuck" area as not stuck */ + *((volatile unsigned long *)trampoline_base) =0 ; + +return boot_error; }cycles_t cacheflush_time;
Signature · 1 line
1.5.0.6
PATCH 57/79 call do_boot_cpu directly from native_cpu_up
From: Glauber Costa <[email protected]>
We don't need __smp_prepare_cpu anymore.
--- arch/x86/kernel/smpboot_32.c | 21 ++++++--------------- 1 files changed, 6 insertions(+), 15 deletions(-)
arch/x86/kernel/smpboot_32.c +6 -15
@@ -702,20 +702,6 @@ void cpu_exit_clear(void) }#endif -static void __cpuinit __smp_prepare_cpu (int cpu) -{ -int apicid; - - apicid =per_cpu (x86_cpu_to_apicid, cpu); - -/* init low mem mapping */ -clone_pgd_range (swapper_pg_dir, swapper_pg_dir +USER_PGD_PTRS , - min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); -flush_tlb_all (); - -do_boot_cpu (apicid, cpu); -} -static int boot_cpu_logical_apicid;/* Where the IO area was mapped on multiquad, always 0 otherwise */ void *xquad_portio;
@@ -872,7 +858,12 @@ int __cpuinit native_cpu_up(unsigned int cpu)per_cpu (cpu_state, cpu) =CPU_UP_PREPARE ; -__smp_prepare_cpu (cpu); +/* init low mem mapping */ +clone_pgd_range (swapper_pg_dir, swapper_pg_dir +USER_PGD_PTRS , + min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); +flush_tlb_all (); + +do_boot_cpu (apicid, cpu);/* In case one didn't come up */ if (!cpu_isset (cpu, cpu_callin_map)) {
Signature · 1 line
1.5.0.6
PATCH 58/79 include mach_apic.h in smpboot_64.c and smpboot.c
From: Glauber Costa <[email protected]>
After the inclusion, a lot of files needs fixing for conflicts, some of them in the headers themselves, to accomodate for both i386 and x86_64 versions.
--- arch/x86/kernel/acpi/boot.c | 2 ++ arch/x86/kernel/mpparse_64.c | 2 ++ arch/x86/kernel/smpboot.c | 2 ++ arch/x86/kernel/smpboot_64.c | 1 + arch/x86/vdso/Makefile | 2 +- include/asm-x86/apic.h | 1 - include/asm-x86/apicdef.h | 6 ------ include/asm-x86/mach-default/mach_apic.h | 11 +++++++++++ include/asm-x86/mach-default/mach_apicdef.h | 5 +++++ include/asm-x86/smp_64.h | 9 +-------- 10 files changed, 25 insertions(+), 16 deletions(-)
arch/x86/kernel/acpi/boot.c +2 -0
@@ -40,6 +40,8 @@#include <asm/io.h> #include <asm/mpspec.h> +#include <mach_apic.h> +static int __initdata acpi_force =0 ;#ifdef CONFIG_ACPI
arch/x86/kernel/mpparse_64.c +2 -0
@@ -30,6 +30,8 @@#include <asm/proto.h> #include <asm/acpi.h> +#include <mach_apic.h> +/* Have we found an MP table */ int smp_found_config;unsigned int __cpuinitdata maxcpus =NR_CPUS ;
arch/x86/kernel/smpboot.c +2 -0
@@ -11,6 +11,8 @@#include <asm/cpu.h> #include <asm/numa.h> +#include <mach_apic.h> +/* Number of siblings per CPU package */ int smp_num_siblings =1 ;EXPORT_SYMBOL (smp_num_siblings);
arch/x86/kernel/smpboot_64.c +1 -0
@@ -61,6 +61,7 @@#include <asm/numa.h> #include <mach_wakecpu.h> +#include <mach_apic.h> #include <smpboot_hooks.h> /* Set when the idlers are all forked */
arch/x86/vdso/Makefile +1 -1
@@ -39,7 +39,7 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE CFL := $(PROFILING) -mcmodel=small -fPIC -g0 -O2 -fasynchronous-unwind-tables -m64 -$(vobjs): KBUILD_CFLAGS = $(CFL) +$(vobjs): KBUILD_CFLAGS += $(CFL) targets += vdso-syms.lds obj-$(VDSO64-y) += vdso-syms.lds
include/asm-x86/apic.h +0 -1
@@ -128,7 +128,6 @@ extern void enable_NMI_through_LVT0(void);* On 32bit this is mach-xxx local */ #ifdef CONFIG_X86_64 -extern void setup_apic_routing (void );extern void early_init_lapic_mapping (void );#endif
include/asm-x86/apicdef.h +0 -6
@@ -12,12 +12,6 @@#define APIC_ID 0x20 -#ifdef CONFIG_X86_64 -# define APIC_ID_MASK (0xFFu<<24) -# define GET_APIC_ID (x) (((x)>>24)&0xFFu) -# define SET_APIC_ID (x) (((x)<<24)) -#endif -#define APIC_LVR 0x30#define APIC_LVR_MASK 0xFF00FF#define GET_APIC_VERSION (x) ((x)&0xFFu)
include/asm-x86/mach-default/mach_apic.h +11 -0
@@ -54,21 +54,27 @@ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)return phys_map; } +#ifdef CONFIG_X86_64 +extern void setup_apic_routing (void ); +#else static inline void setup_apic_routing (void ) {printk ("Enabling APIC mode: %s. Using %d I/O APICs\n" ,"Flat" , nr_ioapics); } +#endif static inline int multi_timer_check (int apic,int irq) {return 0 ; } +#ifdef CONFIG_X86_32 static inline int apicid_to_node (int logical_apicid) {return 0 ; } +#endif /* Mapping from cpu number to logical apicid */ static inline int cpu_to_logical_apicid (int cpu)
@@ -78,8 +84,13 @@ static inline int cpu_to_logical_apicid(int cpu)static inline int cpu_present_to_apicid (int mps_cpu) { +#ifdef CONFIG_X86_64 +if (cpu_present (mps_cpu)) +return (int )per_cpu (x86_bios_cpu_apicid, mps_cpu); +#else if (mps_cpu <get_physical_broadcast ())return mps_cpu; +#endif else return BAD_APICID; }
include/asm-x86/mach-default/mach_apicdef.h +5 -0
@@ -3,7 +3,12 @@#include <asm/apic.h> +#ifdef CONFIG_X86_64 +#define APIC_ID_MASK (0xFFu<<24) +#define SET_APIC_ID (x) (((x)<<24)) +#else #define APIC_ID_MASK (0xF<<24) +#endif static inline unsigned get_apic_id (unsigned long x) {
include/asm-x86/smp_64.h +1 -8
@@ -19,14 +19,6 @@ extern cpumask_t cpu_callin_map;extern int smp_call_function_mask (cpumask_t mask,void (*func)(void *),void *info,int wait); -static inline int cpu_present_to_apicid (int mps_cpu) -{ -if (cpu_present (mps_cpu)) -return (int )per_cpu (x86_bios_cpu_apicid, mps_cpu); -else -return BAD_APICID ; -} -#ifdef CONFIG_SMP #define raw_smp_processor_id () read_pda(cpunumber)
@@ -64,6 +56,7 @@ static __inline int logical_smp_processor_id(void)return GET_APIC_LOGICAL_ID (*(u32 *)(APIC_BASE +APIC_LDR )); } +#include <mach_apicdef.h> static inline int hard_smp_processor_id (void ) {/* we don't want to mark this access volatile - bad code generation */
Signature · 1 line
1.5.0.6
PATCH 59/79 change wakeup_secondary name
From: Glauber Costa <[email protected]>
wakeup_secondary_via_INIT => wakeup_secondary_cpu.
This is to match i386, where init is not always used.
--- arch/x86/kernel/smpboot_64.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
arch/x86/kernel/smpboot_64.c +4 -2
@@ -63,6 +63,7 @@#include <mach_wakecpu.h> #include <mach_apic.h> #include <smpboot_hooks.h> +#include <mach_apic.h> /* Set when the idlers are all forked */ int smp_threads_ready;
@@ -293,7 +294,8 @@ static void __inquire_remote_apic(int apicid)/* * Kick the secondary to wake up. */ -static int __cpuinit wakeup_secondary_via_INIT (int phys_apicid,unsigned int start_rip) +static int __cpuinit wakeup_secondary_cpu (int phys_apicid, +unsigned int start_rip) {unsigned long send_status, accept_status =0 ;int maxlvt, num_starts, j;
@@ -534,7 +536,7 @@ do_rest:/* * Starting actual IPI sequence... */ - boot_error =wakeup_secondary_via_INIT (apicid, start_rip); + boot_error =wakeup_secondary_cpu (apicid, start_rip);if (!boot_error) {/*
Signature · 1 line
1.5.0.6
PATCH 60/79 add callin tests to cpu_up
From: Glauber Costa <[email protected]>
Now that we boot cpus here, callin_map has this meaning (same as x86_64)
--- arch/x86/kernel/smpboot_32.c | 20 +++++++++++++------- 1 files changed, 13 insertions(+), 7 deletions(-)
arch/x86/kernel/smpboot_32.c +13 -7
@@ -839,6 +839,7 @@ int __cpuinit native_cpu_up(unsigned int cpu) {int apicid =cpu_present_to_apicid (cpu);unsigned long flags; +int err;WARN_ON (irqs_disabled ());
@@ -851,6 +852,14 @@ int __cpuinit native_cpu_up(unsigned int cpu) }/* +* Already booted CPU? +*/ +if (cpu_isset (cpu, cpu_callin_map)) { +Dprintk ("do_boot_cpu %d Already started\n" , cpu); +return -ENOSYS ; + } + +/* * Save current MTRR state in case it was changed since early boot * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync: */
@@ -863,15 +872,12 @@ int __cpuinit native_cpu_up(unsigned int cpu) min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));flush_tlb_all (); -do_boot_cpu (apicid, cpu); - -/* In case one didn't come up */ -if (!cpu_isset (cpu, cpu_callin_map)) { -printk (KERN_DEBUG "skipping cpu%d, didn't come online\n" , cpu); -return -EIO ; + err =do_boot_cpu (apicid, cpu); +if (err <0 ) { +Dprintk ("do_boot_cpu failed %d\n" , err); +return err; } -/* * Check TSC synchronization with the AP (keep irqs disabled * while doing so):
Signature · 1 line
1.5.0.6
PATCH 61/79 move {un}map_cpu_to_logical_apicid to smpboot.c
From: Glauber Costa <[email protected]>
Move map_cpu_to_logical_apicid() and unmap_cpu_to_logical_apicid() to smpboot.c. They take together all the bunch of static functions they rely upon
--- arch/x86/kernel/smpboot.c | 60 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 59 +--------------------------------------- 2 files changed, 62 insertions(+), 57 deletions(-)
arch/x86/kernel/smpboot.c +60 -0
@@ -50,6 +50,66 @@ static cpumask_t cpu_sibling_setup_map;/* Set if we find a B stepping CPU */ int __cpuinitdata smp_b_stepping; +#if defined(CONFIG_NUMA ) && defined(CONFIG_X86_32 ) + +/* which logical CPUs are on which nodes */ +cpumask_t node_to_cpumask_map[MAX_NUMNODES ]__read_mostly = + { [0 ...MAX_NUMNODES -1 ] =CPU_MASK_NONE }; +EXPORT_SYMBOL (node_to_cpumask_map); +/* which node each logical CPU is on */ +int cpu_to_node_map[NR_CPUS ]__read_mostly = { [0 ...NR_CPUS -1 ] =0 }; +EXPORT_SYMBOL (cpu_to_node_map); + +/* set up a mapping between cpu and node. */ +static void map_cpu_to_node (int cpu,int node) +{ +printk (KERN_INFO "Mapping cpu %d to node %d\n" , cpu, node); +cpu_set (cpu, node_to_cpumask_map[node]); + cpu_to_node_map[cpu] = node; +} + +/* undo a mapping between cpu and node. */ +static void unmap_cpu_to_node (int cpu) +{ +int node; + +printk (KERN_INFO "Unmapping cpu %d from all nodes\n" , cpu); +for (node =0 ; node <MAX_NUMNODES ; node++) +cpu_clear (cpu, node_to_cpumask_map[node]); + cpu_to_node_map[cpu] =0 ; +} +#else /* !(CONFIG_NUMA && CONFIG_X86_32) */ +#define map_cpu_to_node (cpu, node) ({}) +#define unmap_cpu_to_node (cpu) ({}) +#endif + +#ifdef CONFIG_X86_32 +u8 cpu_2_logical_apicid[NR_CPUS ]__read_mostly = + { [0 ...NR_CPUS -1 ] =BAD_APICID }; + +void map_cpu_to_logical_apicid (void ) +{ +int cpu =smp_processor_id (); +int apicid =logical_smp_processor_id (); +int node =apicid_to_node (apicid); + +if (!node_online (node)) + node = first_online_node; + + cpu_2_logical_apicid[cpu] = apicid; +map_cpu_to_node (cpu, node); +} + +void unmap_cpu_to_logical_apicid (int cpu) +{ + cpu_2_logical_apicid[cpu] =BAD_APICID ; +unmap_cpu_to_node (cpu); +} +#else +#define unmap_cpu_to_logical_apicid (cpu) do {} while (0) +#define map_cpu_to_logical_apicid () do {} while (0) +#endif +static void __cpuinit smp_apply_quirks (struct cpuinfo_x86 *c) {#ifdef CONFIG_X86_32
arch/x86/kernel/smpboot_32.c +2 -57
71 lines not on this page · raw message
Signature · 1 line
1.5.0.6
PATCH 62/79 move stack_start to smp.h
From: Glauber Costa <[email protected]>
voyager would conflict with it, but the types are ultimately compatible. So remove the extern definition from voyager_smp.c in favour of the common one
--- arch/x86/kernel/smpboot_32.c | 6 ------ arch/x86/mach-voyager/voyager_smp.c | 7 ------- include/asm-x86/smp.h | 7 +++++++ 3 files changed, 7 insertions(+), 13 deletions(-)
arch/x86/kernel/smpboot_32.c +0 -6
@@ -257,12 +257,6 @@ void __devinit initialize_secondary(void) :"m" (current->thread.sp),"m" (current->thread.ip)); } -/* Static state in head.S used to set up a CPU */ -extern struct { -void * sp; -unsigned short ss; -} stack_start; -static inline void __inquire_remote_apic (int apicid) {unsigned i, regs[] = {APIC_ID >>4 ,APIC_LVR >>4 ,APIC_SPIV >>4 };
arch/x86/mach-voyager/voyager_smp.c +0 -7
@@ -518,13 +518,6 @@ static void __init do_boot_cpu(__u8 cpu) & ~(voyager_extended_vic_processors & voyager_allowed_boot_processors); -/* This is an area in head.S which was used to set up the -* initial kernel stack. We need to alter this to give the -* booting CPU a new stack (taken from its idle process) */ -extern struct { -__u8 *sp; -unsigned short ss; - } stack_start;/* This is the format of the CPI IDT gate (in real mode) which * we're hijacking to boot the CPU */ union IDTFormat {
include/asm-x86/smp.h +7 -0
@@ -28,6 +28,13 @@ extern const unsigned char trampoline_data [];extern const unsigned char trampoline_end [];extern unsigned char *trampoline_base; +/* Static state in head.S used to set up a CPU */ +extern struct { +void *sp; +unsigned short ss; +} stack_start; + +struct smp_ops {void (*smp_prepare_boot_cpu)(void );void (*smp_prepare_cpus)(unsigned max_cpus);
Signature · 1 line
1.5.0.6
PATCH 63/79 change boot_cpu_id to boot_cpu_physical_apicid
From: Glauber Costa <[email protected]>
This is to match i386. The former name was cuter, but the current is more meaningful and more general, since cpu_id can be a logical id.
--- arch/x86/kernel/apic_64.c | 13 +++++++------ arch/x86/kernel/mpparse_64.c | 12 ++++++------ arch/x86/kernel/smpboot_64.c | 18 ++++++++++-------- arch/x86/mm/k8topology_64.c | 7 ++++--- include/asm-x86/apic.h | 1 - include/asm-x86/smp.h | 3 +++ include/asm-x86/smp_32.h | 5 ----- include/asm-x86/smp_64.h | 4 ---- 8 files changed, 30 insertions(+), 33 deletions(-)
arch/x86/kernel/apic_64.c +7 -6
@@ -431,7 +431,8 @@ void __cpuinit check_boot_apic_timer_broadcast(void) lapic_clockevent.features |=CLOCK_EVT_FEAT_DUMMY ;local_irq_enable (); -clockevents_notify (CLOCK_EVT_NOTIFY_BROADCAST_FORCE , &boot_cpu_id); +clockevents_notify (CLOCK_EVT_NOTIFY_BROADCAST_FORCE , + &boot_cpu_physical_apicid);local_irq_disable (); }
@@ -857,7 +858,7 @@ static int __init detect_init_APIC(void) } mp_lapic_addr =APIC_DEFAULT_PHYS_BASE ; - boot_cpu_id =0 ; + boot_cpu_physical_apicid =0 ;return 0 ; }
@@ -882,7 +883,7 @@ void __init early_init_lapic_mapping(void)* Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - boot_cpu_id =GET_APIC_ID (apic_read (APIC_ID )); + boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); }/**
@@ -909,7 +910,7 @@ void __init init_apic_mappings(void)* Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - boot_cpu_id =GET_APIC_ID (apic_read (APIC_ID )); + boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); }/*
@@ -930,8 +931,8 @@ int __init APIC_init_uniprocessor(void)verify_local_APIC (); - phys_cpu_present_map =physid_mask_of_physid (boot_cpu_id); -apic_write (APIC_ID ,SET_APIC_ID (boot_cpu_id)); + phys_cpu_present_map =physid_mask_of_physid (boot_cpu_physical_apicid); +apic_write (APIC_ID ,SET_APIC_ID (boot_cpu_physical_apicid));setup_local_APIC ();
arch/x86/kernel/mpparse_64.c +6 -6
@@ -59,8 +59,8 @@ unsigned long mp_lapic_addr = 0;/* Processor that is doing the boot up */ -unsigned int boot_cpu_id =-1U ; -EXPORT_SYMBOL (boot_cpu_id); +unsigned int boot_cpu_physical_apicid =-1U ; +EXPORT_SYMBOL (boot_cpu_physical_apicid);/* Internal processor count */ unsigned int num_processors;
@@ -107,7 +107,7 @@ static void __cpuinit MP_processor_info(struct mpc_config_processor *m) }if (m->mpc_cpuflag &CPU_BOOTPROCESSOR ) { bootup_cpu =" (Bootup-CPU)" ; - boot_cpu_id = m->mpc_apicid; + boot_cpu_physical_apicid = m->mpc_apicid; }printk (KERN_INFO "Processor #%d%s\n" , m->mpc_apicid, bootup_cpu);
@@ -665,8 +665,8 @@ void __init mp_register_lapic_address(u64 address) { mp_lapic_addr = (unsigned long ) address;set_fixmap_nocache (FIX_APIC_BASE , mp_lapic_addr); -if (boot_cpu_id ==-1U ) - boot_cpu_id =GET_APIC_ID (apic_read (APIC_ID )); +if (boot_cpu_physical_apicid ==-1U ) + boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); }void __cpuinit mp_register_lapic (u8 id,u8 enabled)
@@ -674,7 +674,7 @@ void __cpuinit mp_register_lapic (u8 id, u8 enabled)struct mpc_config_processor processor;int boot_cpu =0 ; -if (id == boot_cpu_id) +if (id == boot_cpu_physical_apicid) boot_cpu =1 ; processor.mpc_type =MP_PROCESSOR ;
arch/x86/kernel/smpboot_64.c +10 -8
@@ -602,7 +602,8 @@ static __init void disable_smp(void) cpu_present_map =cpumask_of_cpu (0 ); cpu_possible_map =cpumask_of_cpu (0 );if (smp_found_config) - phys_cpu_present_map =physid_mask_of_physid (boot_cpu_id); + phys_cpu_present_map = +physid_mask_of_physid (boot_cpu_physical_apicid);else phys_cpu_present_map =physid_mask_of_physid (0 );cpu_set (0 ,per_cpu (cpu_sibling_map,0 ));
@@ -637,9 +638,10 @@ static int __init smp_sanity_check(unsigned max_cpus)* Should not be necessary because the MP table should list the boot * CPU too, but we do it for the sake of robustness anyway. */ -if (!physid_isset (boot_cpu_id, phys_cpu_present_map)) { -printk (KERN_NOTICE "weird, boot CPU (#%d) not listed by the BIOS.\n" , - boot_cpu_id); +if (!physid_isset (boot_cpu_physical_apicid, phys_cpu_present_map)) { +printk (KERN_NOTICE +"weird, boot CPU (#%d) not listed by the BIOS.\n" , + boot_cpu_physical_apicid);physid_set (hard_smp_processor_id (), phys_cpu_present_map); }
@@ -648,7 +650,7 @@ static int __init smp_sanity_check(unsigned max_cpus)*/ if (!cpu_has_apic) {printk (KERN_ERR "BIOS bug, local APIC #%d not detected!...\n" , - boot_cpu_id); + boot_cpu_physical_apicid);printk (KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n" ); nr_ioapics =0 ;return -1 ;
@@ -709,9 +711,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)enable_IO_APIC ();end_local_APIC_setup (); -if (GET_APIC_ID (apic_read (APIC_ID )) != boot_cpu_id) { +if (GET_APIC_ID (apic_read (APIC_ID )) != boot_cpu_physical_apicid) {panic ("Boot APIC ID in local APIC unexpected (%d vs %d)" , -GET_APIC_ID (apic_read (APIC_ID )), boot_cpu_id); +GET_APIC_ID (apic_read (APIC_ID )), boot_cpu_physical_apicid);/* Or can we switch back to PIC here? */ }
@@ -756,7 +758,7 @@ int __cpuinit native_cpu_up(unsigned int cpu)Dprintk ("++++++++++++++++++++=_---CPU UP %u\n" , cpu); -if (apicid ==BAD_APICID || apicid == boot_cpu_id || +if (apicid ==BAD_APICID || apicid == boot_cpu_physical_apicid || !physid_isset (apicid, phys_cpu_present_map)) {printk ("__cpu_up: bad cpu %d\n" , cpu);return -EINVAL ;
arch/x86/mm/k8topology_64.c +4 -3
@@ -205,9 +205,10 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) apicid_base =0 ;/* need to get boot_cpu_id early for system with apicid lifting */ early_get_boot_cpu_id (); -if (boot_cpu_id >0 ) { -printk (KERN_INFO "BSP APIC ID: %02x\n" , boot_cpu_id); - apicid_base = boot_cpu_id; +if (boot_cpu_physical_apicid >0 ) { +printk (KERN_INFO "BSP APIC ID: %02x\n" , + boot_cpu_physical_apicid); + apicid_base = boot_cpu_physical_apicid; }for (i =0 ; i <8 ; i++) {
include/asm-x86/apic.h +0 -1
@@ -44,7 +44,6 @@ extern int apic_runs_main_timer;extern int ioapic_force;extern int disable_apic;extern int disable_apic_timer; -extern unsigned boot_cpu_id;/* * Basic functions accessing APICs.
include/asm-x86/smp.h +3 -0
@@ -109,6 +109,9 @@ extern void prefill_possible_map(void);extern unsigned long setup_trampoline (void );void smp_store_cpu_info (int id); +#define cpu_physical_id (cpu) per_cpu(x86_cpu_to_apicid, cpu) +#else +#define cpu_physical_id (cpu) boot_cpu_physical_apicid#endif #ifdef CONFIG_X86_32
include/asm-x86/smp_32.h +0 -5
@@ -30,8 +30,6 @@ extern void zap_low_mappings (void);DECLARE_PER_CPU (int, cpu_number);#define raw_smp_processor_id () (x86_read_percpu(cpu_number)) -#define cpu_physical_id (cpu) per_cpu(x86_cpu_to_apicid, cpu) -extern int safe_smp_processor_id (void );/* We don't mark CPUs online until __cpu_up(), so we need another measure */
@@ -41,10 +39,7 @@ static inline int num_booting_cpus(void) }#else /* CONFIG_SMP */ -#define safe_smp_processor_id () 0 -#define cpu_physical_id (cpu) boot_cpu_physical_apicid -#endif /* !CONFIG_SMP */ #ifdef CONFIG_X86_LOCAL_APIC
include/asm-x86/smp_64.h +0 -4
@@ -22,7 +22,6 @@ extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),#ifdef CONFIG_SMP #define raw_smp_processor_id () read_pda(cpunumber) -#define cpu_physical_id (cpu) per_cpu(x86_cpu_to_apicid, cpu)#define stack_smp_processor_id () \ ({ \
@@ -41,9 +40,6 @@ static inline int num_booting_cpus(void) }#else /* CONFIG_SMP */ - -extern unsigned int boot_cpu_id; -#define cpu_physical_id (cpu) boot_cpu_id#define stack_smp_processor_id () 0#endif /* !CONFIG_SMP */
Signature · 1 line
1.5.0.6
PATCH 64/79 integrate do_boot_cpu
From: Glauber Costa <[email protected]>
This is a very large patch, because it depends on a lot of auxiliary static functions. But they all have been modified to the point that they're sufficiently close now. So they're just merged in smpboot.c
--- arch/x86/kernel/smpboot.c | 588 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 532 +------------------------------------- arch/x86/kernel/smpboot_64.c | 515 +------------------------------------ include/asm-x86/smp.h | 3 + 4 files changed, 594 insertions(+), 1044 deletions(-)
arch/x86/kernel/smpboot.c +588 -0
@@ -4,14 +4,42 @@#include <linux/sched.h> #include <linux/percpu.h> #include <linux/bootmem.h> +#include <linux/err.h> +#include <linux/nmi.h> +#include <asm/desc.h> #include <asm/nmi.h> #include <asm/irq.h> #include <asm/smp.h> #include <asm/cpu.h> #include <asm/numa.h> +#include <asm/pgtable.h> +#include <asm/tlbflush.h> +#include <asm/mtrr.h> +#include <asm/nmi.h> +#include <linux/mc146818rtc.h> #include <mach_apic.h> +#include <mach_wakecpu.h> +#include <smpboot_hooks.h> + +/* Store all idle threads, this can be reused instead of creating +* a new thread. Also avoids complicated thread destroy functionality +* for idle threads. +*/ +#ifdef CONFIG_HOTPLUG_CPU +/* +* Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is +* removed after init for !CONFIG_HOTPLUG_CPU. +*/ +static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); +#define get_idle_for_cpu (x) (per_cpu(idle_thread_array, x)) +#define set_idle_for_cpu (x, p) (per_cpu(idle_thread_array, x) = (p)) +#else +struct task_struct *idle_thread_array[NR_CPUS ]__cpuinitdata ; +#define get_idle_for_cpu (x) (idle_thread_array[(x)]) +#define set_idle_for_cpu (x, p) (idle_thread_array[(x)] = (p)) +#endif /* Number of siblings per CPU package */ int smp_num_siblings =1 ;
@@ -41,6 +69,8 @@ EXPORT_PER_CPU_SYMBOL(cpu_core_map); DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);EXPORT_PER_CPU_SYMBOL (cpu_info); +static atomic_t init_deasserted; +/* ready for x86_64, no harm for x86, since it will overwrite after alloc */ unsigned char *trampoline_base =__va (SMP_TRAMPOLINE_BASE );
@@ -110,6 +140,96 @@ void unmap_cpu_to_logical_apicid(int cpu)#define map_cpu_to_logical_apicid () do {} while (0)#endif +/* +* Report back to the Boot Processor. +* Running on AP. +*/ +void __cpuinit smp_callin (void ) +{ +int cpuid, phys_id; +unsigned long timeout; + +/* +* If waken up by an INIT in an 82489DX configuration +* we may get here before an INIT-deassert IPI reaches +* our local APIC. We have to wait for the IPI or we'll +* lock up on an APIC access. +*/ +wait_for_init_deassert (&init_deasserted); + +/* +* (This works even if the APIC is not enabled.) +*/ + phys_id =GET_APIC_ID (apic_read (APIC_ID )); + cpuid =smp_processor_id (); +if (cpu_isset (cpuid, cpu_callin_map)) { +panic ("%s: phys CPU#%d, CPU#%d already present??\n" , __func__, + phys_id, cpuid); + } +Dprintk ("CPU#%d (phys ID: %d) waiting for CALLOUT\n" , cpuid, phys_id); + +/* +* STARTUP IPIs are fragile beasts as they might sometimes +* trigger some glue motherboard logic. Complete APIC bus +* silence for 1 second, this overestimates the time the +* boot CPU is spending to send the up to 2 STARTUP IPIs +* by a factor of two. This should be enough. +*/ + +/* +* Waiting 2s total for startup (udelay is not yet working) +*/ + timeout = jiffies +2 *HZ ; +while (time_before (jiffies, timeout)) { +/* +* Has the boot CPU finished it's STARTUP sequence? +*/ +if (cpu_isset (cpuid, cpu_callout_map)) +break ; +cpu_relax (); + } + +if (!time_before (jiffies, timeout)) { +panic ("%s: CPU%d started up but did not get a callout!\n" , + __func__, cpuid); + } + +/* +* the boot CPU has finished the init stage and is spinning +* on callin_map until we finish. We are free to set up this +* CPU, first the APIC. (this is probably redundant on most +* boards) +*/ + +Dprintk ("CALLIN, before setup_local_APIC().\n" ); +smp_callin_clear_local_apic (); +setup_local_APIC (); +end_local_APIC_setup (); +map_cpu_to_logical_apicid (); + +/* +* Get our bogomips. +* +* Need to enable IRQs because it can take longer and then +* the NMI watchdog might kill us. +*/ +local_irq_enable (); +calibrate_delay (); +local_irq_disable (); +Dprintk ("Stack at about %p\n" , &cpuid); + +/* +* Save our processor parameters +*/ +smp_store_cpu_info (cpuid); + +/* +* Allow the master to continue. +*/ +cpu_set (cpuid, cpu_callin_map); +} + +static void __cpuinit smp_apply_quirks (struct cpuinfo_x86 *c) {#ifdef CONFIG_X86_32
@@ -327,6 +447,474 @@ void impress_friends(void)Dprintk ("Before bogocount - setting activated=1.\n" ); } +static inline void __inquire_remote_apic (int apicid) +{ +unsigned i, regs[] = {APIC_ID >>4 ,APIC_LVR >>4 ,APIC_SPIV >>4 }; +char *names[] = {"ID" ,"VERSION" ,"SPIV" }; +int timeout; +u32 status; + +printk (KERN_INFO "Inquiring remote APIC #%d...\n" , apicid); + +for (i =0 ; i <ARRAY_SIZE (regs); i++) { +printk (KERN_INFO "... APIC #%d %s: " , apicid, names[i]); + +/* +* Wait for idle. +*/ + status =safe_apic_wait_icr_idle (); +if (status) +printk (KERN_CONT +"a previous APIC delivery may have failed\n" ); + +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (apicid)); +apic_write_around (APIC_ICR ,APIC_DM_REMRD | regs[i]); + + timeout =0 ; +do { +udelay (100 ); + status =apic_read (APIC_ICR ) &APIC_ICR_RR_MASK ; + }while (status ==APIC_ICR_RR_INPROG && timeout++ <1000 ); + +switch (status) { +case APIC_ICR_RR_VALID : + status =apic_read (APIC_RRR ); +printk (KERN_CONT "%08x\n" , status); +break ; +default : +printk (KERN_CONT "failed\n" ); + } + } +} + +#ifdef WAKE_SECONDARY_VIA_NMI +/* +* Poke the other CPU in the eye via NMI to wake it up. Remember that the normal +* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this +* won't ... remember to clear down the APIC, etc later. +*/ +static int __devinit +wakeup_secondary_cpu (int logical_apicid,unsigned long start_eip) +{ +unsigned long send_status, accept_status =0 ; +int maxlvt; + +/* Target chip */ +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (logical_apicid)); + +/* Boot on the stack */ +/* Kick the second */ +apic_write_around (APIC_ICR ,APIC_DM_NMI |APIC_DEST_LOGICAL ); + +Dprintk ("Waiting for send to finish...\n" ); + send_status =safe_apic_wait_icr_idle (); + +/* +* Give the other CPU some time to accept the IPI. +*/ +udelay (200 ); +/* +* Due to the Pentium erratum 3AP. +*/ + maxlvt =lapic_get_maxlvt (); +if (maxlvt >3 ) { +apic_read_around (APIC_SPIV ); +apic_write (APIC_ESR ,0 ); + } + accept_status = (apic_read (APIC_ESR ) &0xEF ); +Dprintk ("NMI sent.\n" ); + +if (send_status) +printk (KERN_ERR "APIC never delivered???\n" ); +if (accept_status) +printk (KERN_ERR "APIC delivery error (%lx).\n" , accept_status); + +return (send_status | accept_status); +} +#endif /* WAKE_SECONDARY_VIA_NMI */ + +extern void start_secondary (void *unused); +#ifdef WAKE_SECONDARY_VIA_INIT +static int __devinit +wakeup_secondary_cpu (int phys_apicid,unsigned long start_eip) +{ +unsigned long send_status, accept_status =0 ; +int maxlvt, num_starts, j; + +/* +* Be paranoid about clearing APIC errors. +*/ +if (APIC_INTEGRATED (apic_version[phys_apicid])) { +apic_read_around (APIC_SPIV ); +apic_write (APIC_ESR ,0 ); +apic_read (APIC_ESR ); + } + +Dprintk ("Asserting INIT.\n" ); + +/* +* Turn INIT on target chip +*/ +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid)); + +/* +* Send IPI +*/ +apic_write_around (APIC_ICR ,APIC_INT_LEVELTRIG |APIC_INT_ASSERT + |APIC_DM_INIT ); + +Dprintk ("Waiting for send to finish...\n" ); + send_status =safe_apic_wait_icr_idle (); + +mdelay (10 ); + +Dprintk ("Deasserting INIT.\n" ); + +/* Target chip */ +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid)); + +/* Send IPI */ +apic_write_around (APIC_ICR ,APIC_INT_LEVELTRIG |APIC_DM_INIT ); + +Dprintk ("Waiting for send to finish...\n" ); + send_status =safe_apic_wait_icr_idle (); + +mb (); +atomic_set (&init_deasserted,1 ); + +/* +* Should we send STARTUP IPIs ? +* +* Determine this based on the APIC version. +* If we don't have an integrated APIC, don't send the STARTUP IPIs. +*/ +if (APIC_INTEGRATED (apic_version[phys_apicid])) + num_starts =2 ; +else + num_starts =0 ; + +/* +* Paravirt / VMI wants a startup IPI hook here to set up the +* target processor state. +*/ +startup_ipi_hook (phys_apicid, (unsigned long ) start_secondary, +#ifdef CONFIG_X86_64 + (unsigned long)init_rsp); +#else + (unsigned long)stack_start.sp); +#endif + +/* +* Run STARTUP IPI loop. +*/ +Dprintk ("#startup loops: %d.\n" , num_starts); + + maxlvt =lapic_get_maxlvt (); + +for (j =1 ; j <= num_starts; j++) { +Dprintk ("Sending STARTUP #%d.\n" , j); +apic_read_around (APIC_SPIV ); +apic_write (APIC_ESR ,0 ); +apic_read (APIC_ESR ); +Dprintk ("After apic_write.\n" ); + +/* +* STARTUP IPI +*/ + +/* Target chip */ +apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (phys_apicid)); + +/* Boot on the stack */ +/* Kick the second */ +apic_write_around (APIC_ICR ,APIC_DM_STARTUP + | (start_eip >>12 )); + +/* +* Give the other CPU some time to accept the IPI. +*/ +udelay (300 ); + +Dprintk ("Startup point 1.\n" ); + +Dprintk ("Waiting for send to finish...\n" ); + send_status =safe_apic_wait_icr_idle (); + +/* +* Give the other CPU some time to accept the IPI. +*/ +udelay (200 ); +/* +* Due to the Pentium erratum 3AP. +*/ +if (maxlvt >3 ) { +apic_read_around (APIC_SPIV ); +apic_write (APIC_ESR ,0 ); + } + accept_status = (apic_read (APIC_ESR ) &0xEF ); +if (send_status || accept_status) +break ; + } +Dprintk ("After Startup.\n" ); + +if (send_status) +printk (KERN_ERR "APIC never delivered???\n" ); +if (accept_status) +printk (KERN_ERR "APIC delivery error (%lx).\n" , accept_status); + +return (send_status | accept_status); +} +#endif /* WAKE_SECONDARY_VIA_INIT */ + +struct create_idle { +struct work_struct work; +struct task_struct *idle; +struct completion done; +int cpu; +}; + +static void __cpuinit do_fork_idle (struct work_struct *work) +{ +struct create_idle *c_idle = + container_of(work, struct create_idle, work); + + c_idle->idle =fork_idle (c_idle->cpu); +complete (&c_idle->done); +} + +static int __cpuinit do_boot_cpu (int apicid,int cpu) +/* +* NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad +* (ie clustered apic addressing mode), this is a LOGICAL apic ID. +* Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. +*/ +{ +unsigned long boot_error =0 ; +int timeout; +unsigned long start_ip; +unsigned short nmi_high =0 , nmi_low =0 ; +struct create_idle c_idle = { + .cpu = cpu, + .done =COMPLETION_INITIALIZER_ONSTACK (c_idle.done), + }; +INIT_WORK (&c_idle.work, do_fork_idle); +#ifdef CONFIG_X86_64 +/* allocate memory for gdts of secondary cpus. Hotplug is considered */ +if (!cpu_gdt_descr[cpu].address && + !(cpu_gdt_descr[cpu].address =get_zeroed_page (GFP_KERNEL ))) { +printk (KERN_ERR "Failed to allocate GDT for CPU %d\n" , cpu); +return -1 ; + } + +/* Allocate node local memory for AP pdas */ +if (cpu_pda (cpu) == &boot_cpu_pda[cpu]) { +struct x8664_pda *newpda, *pda; +int node =cpu_to_node (cpu); + pda =cpu_pda (cpu); + newpda =kmalloc_node (sizeof (struct x8664_pda ),GFP_ATOMIC , + node); +if (newpda) { +memcpy (newpda, pda,sizeof (struct x8664_pda )); +cpu_pda (cpu) = newpda; + }else +printk (KERN_ERR +"Could not allocate node local PDA for CPU %d on node %d\n" , + cpu, node); + } +#endif + +alternatives_smp_switch (1 ); + + c_idle.idle =get_idle_for_cpu (cpu); + +/* +* We can't use kernel_thread since we must avoid to +* reschedule the child. +*/ +if (c_idle.idle) { + c_idle.idle->thread.sp = (unsigned long ) (((struct pt_regs *) + (THREAD_SIZE +task_stack_page (c_idle.idle))) -1 ); +init_idle (c_idle.idle, cpu); + goto do_rest; + } + +if (!keventd_up () ||current_is_keventd ()) + c_idle.work.func (&c_idle.work); +else { +schedule_work (&c_idle.work); +wait_for_completion (&c_idle.done); + } + +if (IS_ERR (c_idle.idle)) { +printk ("failed fork for CPU %d\n" , cpu); +return PTR_ERR (c_idle.idle); + } + +set_idle_for_cpu (cpu, c_idle.idle); +do_rest: +#ifdef CONFIG_X86_32 +per_cpu (current_task ,cpu ) = c_idle.idle; +init_gdt (cpu); + early_gdt_descr.address = (unsigned long )get_cpu_gdt_table (cpu); + c_idle.idle->thread.ip = (unsigned long ) start_secondary; +/* Stack for startup_32 can be just as for start_secondary onwards */ + stack_start.sp = (void *) c_idle.idle->thread.sp; +irq_ctx_init (cpu); +#else +cpu_pda (cpu)->pcurrent = c_idle.idle; + init_rsp = c_idle.idle->thread.sp; +load_sp0 (&per_cpu (init_tss, cpu), &c_idle.idle->thread); + initial_code = (unsigned long )start_secondary; +clear_tsk_thread_flag (c_idle.idle,TIF_FORK ); +#endif + +/* start_ip had better be page-aligned! */ + start_ip =setup_trampoline (); + +/* So we see what's up */ +printk (KERN_INFO "Booting processor %d/%d ip %lx\n" , + cpu, apicid, start_ip); + +/* +* This grunge runs the startup process for +* the targeted processor. +*/ + +atomic_set (&init_deasserted,0 ); + +Dprintk ("Setting warm reset code and vector.\n" ); + +store_NMI_vector (&nmi_high, &nmi_low); + +smpboot_setup_warm_reset_vector (start_ip); +/* +* Be paranoid about clearing APIC errors. +*/ +apic_write (APIC_ESR ,0 ); +apic_read (APIC_ESR ); + + +/* +* Starting actual IPI sequence... +*/ + boot_error =wakeup_secondary_cpu (apicid, start_ip); + +if (!boot_error) { +/* +* allow APs to start initializing. +*/ +Dprintk ("Before Callout %d.\n" , cpu); +cpu_set (cpu, cpu_callout_map); +Dprintk ("After Callout %d.\n" , cpu); + +/* +* Wait 5s total for a response +*/ +for (timeout =0 ; timeout <50000 ; timeout++) { +if (cpu_isset (cpu, cpu_callin_map)) +break ;/* It has booted */ +udelay (100 ); + } + +if (cpu_isset (cpu, cpu_callin_map)) { +/* number CPUs logically, starting from 1 (BSP is 0) */ +Dprintk ("OK.\n" ); +printk (KERN_INFO "CPU%d: " , cpu); +print_cpu_info (&cpu_data (cpu)); +Dprintk ("CPU has booted.\n" ); + }else { + boot_error =1 ; +if (*((volatile unsigned char *)trampoline_base) + ==0xA5 ) +/* trampoline started but...? */ +printk (KERN_ERR "Stuck ??\n" ); +else +/* trampoline code not run */ +printk (KERN_ERR "Not responding.\n" ); +inquire_remote_apic (apicid); + } + } + +if (boot_error) { +/* Try to put things back the way they were before ... */ +unmap_cpu_to_logical_apicid (cpu); +#ifdef CONFIG_X86_64 +clear_node_cpumask (cpu);/* was set by numa_add_cpu */ +#endif +cpu_clear (cpu, cpu_callout_map);/* was set by do_boot_cpu() */ +cpu_clear (cpu, cpu_initialized);/* was set by cpu_init() */ +cpu_clear (cpu, cpu_possible_map); +cpu_clear (cpu, cpu_present_map); +per_cpu (x86_cpu_to_apicid, cpu) =BAD_APICID ; + } + +/* mark "stuck" area as not stuck */ + *((volatile unsigned long *)trampoline_base) =0 ; + +return boot_error; +} + +int __cpuinit native_cpu_up (unsigned int cpu) +{ +int apicid =cpu_present_to_apicid (cpu); +unsigned long flags; +int err; + +WARN_ON (irqs_disabled ()); + +Dprintk ("++++++++++++++++++++=_---CPU UP %u\n" , cpu); + +if (apicid ==BAD_APICID || apicid == boot_cpu_physical_apicid || + !physid_isset (apicid, phys_cpu_present_map)) { +printk (KERN_ERR "%s: bad cpu %d\n" , __func__, cpu); +return -EINVAL ; + } + +/* +* Already booted CPU? +*/ +if (cpu_isset (cpu, cpu_callin_map)) { +Dprintk ("do_boot_cpu %d Already started\n" , cpu); +return -ENOSYS ; + } + +/* +* Save current MTRR state in case it was changed since early boot +* (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync: +*/ +mtrr_save_state (); + +per_cpu (cpu_state, cpu) =CPU_UP_PREPARE ; + +#ifdef CONFIG_X86_32 +/* init low mem mapping */ +clone_pgd_range (swapper_pg_dir, swapper_pg_dir +USER_PGD_PTRS , + min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); +flush_tlb_all (); +#endif + + err =do_boot_cpu (apicid, cpu); +if (err <0 ) { +Dprintk ("do_boot_cpu failed %d\n" , err); +return err; + } + +/* +* Check TSC synchronization with the AP (keep irqs disabled +* while doing so): +*/ +local_irq_save (flags); +check_tsc_sync_source (cpu); +local_irq_restore (flags); + +while (!cpu_isset (cpu, cpu_online_map)) { +cpu_relax (); +touch_nmi_watchdog (); + } + +return 0 ; +} +#ifdef CONFIG_HOTPLUG_CPU void remove_siblinginfo (int cpu) {
arch/x86/kernel/smpboot_32.c +2 -530
554 lines not on this page · raw message
arch/x86/kernel/smpboot_64.c +1 -514
533 lines not on this page · raw message
include/asm-x86/smp.h +3 -0
@@ -9,6 +9,7 @@ extern cpumask_t cpu_callout_map;extern int smp_num_siblings;extern unsigned int num_processors; +extern cpumask_t cpu_initialized;extern u16 x86_cpu_to_apicid_init[];extern u16 x86_bios_cpu_apicid_init[];
@@ -34,6 +35,8 @@ extern struct {unsigned short ss; } stack_start; +extern unsigned long init_rsp; +extern unsigned long initial_code;struct smp_ops {void (*smp_prepare_boot_cpu)(void );
Signature · 1 line
1.5.0.6
PATCH 65/79 integrate start_secondary
From: Glauber Costa <[email protected]>
It now looks the same between architectures, so we merge it in smpboot.c. Minor differences goes inside an ifdef
--- arch/x86/kernel/smpboot.c | 86 +++++++++++++++++++++++++++++++++++++++++- arch/x86/kernel/smpboot_32.c | 75 ------------------------------------ arch/x86/kernel/smpboot_64.c | 63 ------------------------------ 3 files changed, 85 insertions(+), 139 deletions(-)
arch/x86/kernel/smpboot.c +85 -1
@@ -17,6 +17,7 @@#include <asm/tlbflush.h> #include <asm/mtrr.h> #include <asm/nmi.h> +#include <asm/vmi.h> #include <linux/mc146818rtc.h> #include <mach_apic.h>
@@ -229,6 +230,90 @@ void __cpuinit smp_callin(void)cpu_set (cpuid, cpu_callin_map); } +/* +* Activate a secondary processor. +*/ +void __cpuinit start_secondary (void *unused) +{ +/* +* Don't put *anything* before cpu_init(), SMP booting is too +* fragile that we want to limit the things done here to the +* most necessary things. +*/ +#ifdef CONFIG_VMI +vmi_bringup (); +#endif +cpu_init (); +preempt_disable (); +smp_callin (); + +/* otherwise gcc will move up smp_processor_id before the cpu_init */ +barrier (); +/* +* Check TSC synchronization with the BP: +*/ +check_tsc_sync_target (); + +if (nmi_watchdog ==NMI_IO_APIC ) { +disable_8259A_irq (0 ); +enable_NMI_through_LVT0 (); +enable_8259A_irq (0 ); + } + +/* This must be done before setting cpu_online_map */ +set_cpu_sibling_map (raw_smp_processor_id ()); +wmb (); + +/* +* We need to hold call_lock, so there is no inconsistency +* between the time smp_call_function() determines number of +* IPI recipients, and the time when the determination is made +* for which cpus receive the IPI. Holding this +* lock helps us to not include this cpu in a currently in progress +* smp_call_function(). +*/ +lock_ipi_call_lock (); +#ifdef CONFIG_X86_64 +spin_lock (&vector_lock); + +/* Setup the per cpu irq handling data structures */ +__setup_vector_irq (smp_processor_id ()); +/* +* Allow the master to continue. +*/ +spin_unlock (&vector_lock); +#endif +cpu_set (smp_processor_id (), cpu_online_map); +unlock_ipi_call_lock (); +per_cpu (cpu_state,smp_processor_id ()) =CPU_ONLINE ; + +setup_secondary_clock (); + +wmb (); +cpu_idle (); +} + +#ifdef CONFIG_X86_32 +/* +* Everything has been set up for the secondary +* CPUs - they just need to reload everything +* from the task structure +* This function must not return. +*/ +void __devinit initialize_secondary (void ) +{ +/* +* We don't actually need to load the full TSS, +* basically just the stack pointer and the ip. +*/ + + asmvolatile ( +"movl %0,%%esp\n\t" +"jmp *%1" + : + :"m" (current->thread.sp),"m" (current->thread.ip)); +} +#endif static void __cpuinit smp_apply_quirks (struct cpuinfo_x86 *c) {
@@ -533,7 +618,6 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) }#endif /* WAKE_SECONDARY_VIA_NMI */ -extern void start_secondary (void *unused);#ifdef WAKE_SECONDARY_VIA_INIT static int __devinit wakeup_secondary_cpu (int phys_apicid,unsigned long start_eip)
arch/x86/kernel/smpboot_32.c +0 -75
81 lines not on this page · raw message
arch/x86/kernel/smpboot_64.c +0 -63
69 lines not on this page · raw message
Signature · 1 line
1.5.0.6
PATCH 66/79 merge smp_prepare_boot_cpu
From: Glauber Costa <[email protected]>
it is practically the same between arches now, so it is moved to smpboot.c. Minor differences (gdt initialization) live inside an ifdef
--- arch/x86/kernel/smpboot.c | 18 ++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 14 -------------- arch/x86/kernel/smpboot_64.c | 14 -------------- 3 files changed, 18 insertions(+), 28 deletions(-)
arch/x86/kernel/smpboot.c +18 -0
@@ -24,6 +24,9 @@#include <mach_wakecpu.h> #include <smpboot_hooks.h> +/* State of each CPU */ +DEFINE_PER_CPU(int, cpu_state) = { 0 }; +/* Store all idle threads, this can be reused instead of creating * a new thread. Also avoids complicated thread destroy functionality * for idle threads.
@@ -999,6 +1002,21 @@ int __cpuinit native_cpu_up(unsigned int cpu)return 0 ; } +/* +* Early setup to make printk work. +*/ +void __init native_smp_prepare_boot_cpu (void ) +{ +int me =smp_processor_id (); +#ifdef CONFIG_X86_32 +init_gdt (me); +switch_to_new_gdt (); +#endif +/* already set me in cpu_online_map in boot_cpu_init() */ +cpu_set (me, cpu_callout_map); +per_cpu (cpu_state, me) =CPU_ONLINE ; +} +#ifdef CONFIG_HOTPLUG_CPU void remove_siblinginfo (int cpu) {
arch/x86/kernel/smpboot_32.c +0 -14
@@ -77,9 +77,6 @@ u8 apicid_2_node[MAX_APICID];extern void map_cpu_to_logical_apicid (void );extern void unmap_cpu_to_logical_apicid (int cpu); -/* State of each CPU. */ -DEFINE_PER_CPU(int, cpu_state) = { 0 }; -#ifdef CONFIG_HOTPLUG_CPU void cpu_exit_clear (void ) {
@@ -219,17 +216,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)smp_boot_cpus (max_cpus); } -void __init native_smp_prepare_boot_cpu (void ) -{ -unsigned int cpu =smp_processor_id (); - -init_gdt (cpu); -switch_to_new_gdt (); - -cpu_set (cpu, cpu_callout_map); -__get_cpu_var (cpu_state) =CPU_ONLINE ; -} -extern void impress_friends (void );extern void smp_checks (void );
arch/x86/kernel/smpboot_64.c +0 -14
@@ -68,9 +68,6 @@/* Set when the idlers are all forked */ int smp_threads_ready; -/* State of each CPU */ -DEFINE_PER_CPU(int, cpu_state) = { 0 }; -cycles_t cacheflush_time;unsigned long cache_decay_ticks;
@@ -216,17 +213,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)print_cpu_info (&cpu_data (0 )); } -/* -* Early setup to make printk work. -*/ -void __init native_smp_prepare_boot_cpu (void ) -{ -int me =smp_processor_id (); -/* already set me in cpu_online_map in boot_cpu_init() */ -cpu_set (me, cpu_callout_map); -per_cpu (cpu_state, me) =CPU_ONLINE ; -} -extern void impress_friends (void );extern void smp_checks (void );
Signature · 1 line
1.5.0.6
PATCH 67/79 merge native_smp_cpus_done
From: Glauber Costa <[email protected]>
They look similar enough, and are merged. Only difference (zap_low_mapping for i386) is inside ifdef
--- arch/x86/kernel/smpboot.c | 21 ++++++++++++++++++++- arch/x86/kernel/smpboot_32.c | 21 --------------------- arch/x86/kernel/smpboot_64.c | 18 ------------------ 3 files changed, 20 insertions(+), 40 deletions(-)
arch/x86/kernel/smpboot.c +20 -1
@@ -880,7 +880,6 @@ do_rest:apic_write (APIC_ESR ,0 );apic_read (APIC_ESR ); -/* * Starting actual IPI sequence... */
@@ -1017,6 +1016,26 @@ void __init native_smp_prepare_boot_cpu(void)per_cpu (cpu_state, me) =CPU_ONLINE ; } +void __init native_smp_cpus_done (unsigned int max_cpus) +{ +/* +* Cleanup possible dangling ends... +*/ +smpboot_restore_warm_reset_vector (); + +Dprintk ("Boot done.\n" ); + +impress_friends (); +smp_checks (); +#ifdef CONFIG_X86_IO_APIC +setup_ioapic_dest (); +#endif +check_nmi_watchdog (); +#ifdef CONFIG_X86_32 +zap_low_mappings (); +#endif +} +#ifdef CONFIG_HOTPLUG_CPU void remove_siblinginfo (int cpu) {
arch/x86/kernel/smpboot_32.c +0 -21
@@ -215,24 +215,3 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)mb ();smp_boot_cpus (max_cpus); } - -extern void impress_friends (void ); -extern void smp_checks (void ); - -void __init native_smp_cpus_done (unsigned int max_cpus) -{ -/* -* Cleanup possible dangling ends... -*/ -smpboot_restore_warm_reset_vector (); - -Dprintk ("Boot done.\n" ); - -impress_friends (); -smp_checks (); -#ifdef CONFIG_X86_IO_APIC -setup_ioapic_dest (); -#endif -check_nmi_watchdog (); -zap_low_mappings (); -}
arch/x86/kernel/smpboot_64.c +0 -18
@@ -212,21 +212,3 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)printk (KERN_INFO "CPU%d: " ,0 );print_cpu_info (&cpu_data (0 )); } - -extern void impress_friends (void ); -extern void smp_checks (void ); - -/* -* Finish the SMP boot. -*/ -void __init native_smp_cpus_done (unsigned int max_cpus) -{ -smpboot_restore_warm_reset_vector (); - -Dprintk ("Boot done.\n" ); - -impress_friends (); -smp_checks (); -setup_ioapic_dest (); -check_nmi_watchdog (); -}
Signature · 1 line
1.5.0.6
PATCH 68/79 use physical id when disabling smp
From: Glauber Costa <[email protected]>
if smp configuration is not found at all, hook into 0. This is done to match x86_64
--- arch/x86/kernel/smpboot_32.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
arch/x86/kernel/smpboot_32.c +5 -1
@@ -106,7 +106,11 @@ static void __init disable_smp(void) cpu_possible_map =cpumask_of_cpu (0 ); cpu_present_map =cpumask_of_cpu (0 );smpboot_clear_io_apic_irqs (); - phys_cpu_present_map =physid_mask_of_physid (0 ); +if (smp_found_config) + phys_cpu_present_map = +physid_mask_of_physid (boot_cpu_physical_apicid); +else + phys_cpu_present_map =physid_mask_of_physid (0 );map_cpu_to_logical_apicid ();cpu_set (0 ,per_cpu (cpu_sibling_map,0 ));cpu_set (0 ,per_cpu (cpu_core_map,0 ));
Signature · 1 line
1.5.0.6
PATCH 69/79 get rid of smp_boot_cpus
From: Glauber Costa <[email protected]>
This patch get rid of smp_boot_cpus(), since it does not boot any cpu anymore. Its code is split in a way to make it closer to x86_64
--- arch/x86/kernel/smpboot_32.c | 30 +++++++++++------------------- 1 files changed, 11 insertions(+), 19 deletions(-)
arch/x86/kernel/smpboot_32.c +11 -19
@@ -172,21 +172,19 @@ static int __init smp_sanity_check(unsigned max_cpus)return 0 ; } -/* -* Cycle through the processors sending APIC IPIs to boot each. -*/ -static void __init smp_boot_cpus (unsigned int max_cpus) +/* These are wrappers to interface to the new boot process. Someone +who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ +void __init native_smp_prepare_cpus (unsigned int max_cpus) { +nmi_watchdog_default (); + cpu_callin_map =cpumask_of_cpu (0 ); +mb (); +/* * Setup boot CPU information */ smp_store_cpu_info (0 );/* Final full version of the data */ -printk (KERN_INFO "CPU%d: " ,0 ); -print_cpu_info (&cpu_data (0 )); - - boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); boot_cpu_logical_apicid =logical_smp_processor_id (); -current_thread_info ()->cpu =0 ;set_cpu_sibling_map (0 );
@@ -197,25 +195,19 @@ static void __init smp_boot_cpus(unsigned int max_cpus)return ; } + boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); +connect_bsp_APIC ();setup_local_APIC ();end_local_APIC_setup ();map_cpu_to_logical_apicid (); -setup_portio_remap ();smpboot_setup_io_apic (); +printk (KERN_INFO "CPU%d: " ,0 ); +print_cpu_info (&cpu_data (0 ));setup_boot_clock (); } -/* These are wrappers to interface to the new boot process. Someone -who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ -void __init native_smp_prepare_cpus (unsigned int max_cpus) -{ -nmi_watchdog_default (); - cpu_callin_map =cpumask_of_cpu (0 ); -mb (); -smp_boot_cpus (max_cpus); -}
Signature · 1 line
1.5.0.6
PATCH 70/79 additions to i386 native_smp_prepare_cpus.
From: Glauber Costa <[email protected]>
Add function calls to native_smp_prepare_cpus in i386 to match x86_64
--- arch/x86/kernel/smpboot_32.c | 22 +++++++++++++++++++--- 1 files changed, 19 insertions(+), 3 deletions(-)
arch/x86/kernel/smpboot_32.c +19 -3
@@ -172,11 +172,23 @@ static int __init smp_sanity_check(unsigned max_cpus)return 0 ; } -/* These are wrappers to interface to the new boot process. Someone -who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ +static void __init smp_cpu_index_default (void ) +{ +int i; +struct cpuinfo_x86 *c; + +for_each_cpu_mask (i, cpu_possible_map) { + c = &cpu_data (i); +/* mark all to hotplug */ + c->cpu_index =NR_CPUS ; + } +} +void __init native_smp_prepare_cpus (unsigned int max_cpus) {nmi_watchdog_default (); +smp_cpu_index_default (); + current_cpu_data = boot_cpu_data; cpu_callin_map =cpumask_of_cpu (0 );mb ();
@@ -195,7 +207,11 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)return ; } - boot_cpu_physical_apicid =GET_APIC_ID (apic_read (APIC_ID )); +if (GET_APIC_ID (apic_read (APIC_ID )) != boot_cpu_physical_apicid) { +panic ("Boot APIC ID in local APIC unexpected (%d vs %d)" , +GET_APIC_ID (apic_read (APIC_ID )), boot_cpu_physical_apicid); +/* Or can we switch back to PIC here? */ + }connect_bsp_APIC ();setup_local_APIC ();
Signature · 1 line
1.5.0.6
PATCH 71/79 assign nr_ioapics = 0 in smpboot_hooks.h
From: Glauber Costa <[email protected]>
change smpboot_setup_io_apic() by to match x86_64 behaviour
--- include/asm-x86/mach-default/smpboot_hooks.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
include/asm-x86/mach-default/smpboot_hooks.h +2 -0
@@ -41,4 +41,6 @@ static inline void smpboot_setup_io_apic(void)*/ if (!skip_ioapic_setup && nr_ioapics)setup_IO_APIC (); +else + nr_ioapics =0 ; }
Signature · 1 line
1.5.0.6
PATCH 72/79 change x86_64 native_smp_prepare_cpus to match i386
From: Glauber Costa <[email protected]>
An APIC test is moved, and code is replaced by the mach-default already defined function (smpboot_setup_io_apic). setup_portio_remap() is added, but it is a nop in mach-default.
--- arch/x86/kernel/smpboot_64.c | 24 ++++++++++-------------- 1 files changed, 10 insertions(+), 14 deletions(-)
arch/x86/kernel/smpboot_64.c +10 -14
@@ -71,6 +71,7 @@ int smp_threads_ready;cycles_t cacheflush_time;unsigned long cache_decay_ticks; +static int boot_cpu_logical_apicid;/* * Fall back to non SMP mode after errors. *
@@ -167,7 +168,11 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) {nmi_watchdog_default ();smp_cpu_index_default (); + cpu_callin_map =cpumask_of_cpu (0 ); +mb (); + current_cpu_data = boot_cpu_data; + boot_cpu_logical_apicid =logical_smp_processor_id ();current_thread_info ()->cpu =0 ;/* needed? */ set_cpu_sibling_map (0 );
@@ -177,6 +182,11 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)return ; } +if (GET_APIC_ID (apic_read (APIC_ID )) != boot_cpu_physical_apicid) { +panic ("Boot APIC ID in local APIC unexpected (%d vs %d)" , +GET_APIC_ID (apic_read (APIC_ID )), boot_cpu_physical_apicid); +/* Or can we switch back to PIC here? */ + }/* * Switch from PIC to APIC mode.
@@ -190,20 +200,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)enable_IO_APIC ();end_local_APIC_setup (); -if (GET_APIC_ID (apic_read (APIC_ID )) != boot_cpu_physical_apicid) { -panic ("Boot APIC ID in local APIC unexpected (%d vs %d)" , -GET_APIC_ID (apic_read (APIC_ID )), boot_cpu_physical_apicid); -/* Or can we switch back to PIC here? */ - } - -/* -* Now start the IO-APICs -*/ -if (!skip_ioapic_setup && nr_ioapics) -setup_IO_APIC (); -else - nr_ioapics =0 ; -/* * Set up local APIC timer on boot CPU. */
Signature · 1 line
1.5.0.6
PATCH 73/79 add extra sanity check
From: Glauber Costa <[email protected]>
This test exists in x86_64 and also applies to i386. So we add it
--- arch/x86/kernel/smpboot_32.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
arch/x86/kernel/smpboot_32.c +6 -0
@@ -118,6 +118,12 @@ static void __init disable_smp(void)static int __init smp_sanity_check (unsigned max_cpus) { +if (!physid_isset (hard_smp_processor_id (), phys_cpu_present_map)) { +printk (KERN_WARNING "weird, boot CPU (#%d) not listed" +"by the BIOS.\n" ,hard_smp_processor_id ()); +physid_set (hard_smp_processor_id (), phys_cpu_present_map); + } +/* * If we couldn't find an SMP configuration at boot time, * get out of here now!
Signature · 1 line
1.5.0.6
PATCH 74/79 change x86_64 sanity checks to match i386.
From: Glauber Costa <[email protected]>
They are mostly inocuous. APIC_INTEGRATED will expand to 1, check_phys_apicid_present is checking for the same thing it was before, etc. But the code is identical to i386 now, and will allow us to integrate it.
--- arch/x86/kernel/smpboot_64.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-)
arch/x86/kernel/smpboot_64.c +7 -3
@@ -50,6 +50,7 @@#include <linux/smp.h> #include <linux/kdebug.h> +#include <asm/acpi.h> #include <asm/mtrr.h> #include <asm/pgalloc.h> #include <asm/desc.h>
@@ -105,7 +106,7 @@ static int __init smp_sanity_check(unsigned max_cpus)* If we couldn't find an SMP configuration at boot time, * get out of here now! */ -if (!smp_found_config) { +if (!smp_found_config && !acpi_lapic) {printk (KERN_NOTICE "SMP motherboard not detected.\n" );disable_smp ();if (APIC_init_uniprocessor ())
@@ -118,7 +119,7 @@ static int __init smp_sanity_check(unsigned max_cpus)* Should not be necessary because the MP table should list the boot * CPU too, but we do it for the sake of robustness anyway. */ -if (!physid_isset (boot_cpu_physical_apicid, phys_cpu_present_map)) { +if (!check_phys_apicid_present (boot_cpu_physical_apicid)) {printk (KERN_NOTICE "weird, boot CPU (#%d) not listed by the BIOS.\n" , boot_cpu_physical_apicid);
@@ -128,7 +129,8 @@ static int __init smp_sanity_check(unsigned max_cpus)/* * If we couldn't find a local APIC, then get out of here now! */ -if (!cpu_has_apic) { +if (APIC_INTEGRATED (apic_version[boot_cpu_physical_apicid]) && + !cpu_has_apic) {printk (KERN_ERR "BIOS bug, local APIC #%d not detected!...\n" , boot_cpu_physical_apicid);printk (KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n" );
@@ -136,6 +138,8 @@ static int __init smp_sanity_check(unsigned max_cpus)return -1 ; } +verify_local_APIC (); +/* * If SMP should be disabled, then really disable it! */
Signature · 1 line
1.5.0.6
PATCH 75/79 introduce smpboot_clear_io_apic
From: Glauber Costa <[email protected]>
x86_64 has two nr_ioapics = 0 statements. In 32-bit, it can be done too. We do it through the smpboot_clear_io_apic() inline function, to cope with subarchitectures (visws) that does not compile mpparse in
--- arch/x86/kernel/smpboot_32.c | 2 ++ arch/x86/kernel/smpboot_64.c | 4 ++-- include/asm-x86/mach-default/smpboot_hooks.h | 5 +++++ include/asm-x86/mach-visws/smpboot_hooks.h | 4 ++++ 4 files changed, 13 insertions(+), 2 deletions(-)
arch/x86/kernel/smpboot_32.c +2 -0
@@ -155,6 +155,7 @@ static int __init smp_sanity_check(unsigned max_cpus)printk (KERN_ERR "BIOS bug, local APIC #%d not detected!...\n" , boot_cpu_physical_apicid);printk (KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n" ); +smpboot_clear_io_apic ();return -1 ; }
@@ -173,6 +174,7 @@ static int __init smp_sanity_check(unsigned max_cpus)setup_local_APIC ();end_local_APIC_setup (); } +smpboot_clear_io_apic ();return -1 ; }return 0 ;
arch/x86/kernel/smpboot_64.c +2 -2
@@ -134,7 +134,7 @@ static int __init smp_sanity_check(unsigned max_cpus)printk (KERN_ERR "BIOS bug, local APIC #%d not detected!...\n" , boot_cpu_physical_apicid);printk (KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n" ); - nr_ioapics =0 ; +smpboot_clear_io_apic ();return -1 ; }
@@ -145,7 +145,7 @@ static int __init smp_sanity_check(unsigned max_cpus)*/ if (!max_cpus) {printk (KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n" ); - nr_ioapics =0 ; +smpboot_clear_io_apic ();return -1 ; }
include/asm-x86/mach-default/smpboot_hooks.h +5 -0
@@ -44,3 +44,8 @@ static inline void smpboot_setup_io_apic(void)else nr_ioapics =0 ; } + +static inline void smpboot_clear_io_apic (void ) +{ + nr_ioapics =0 ; +}
include/asm-x86/mach-visws/smpboot_hooks.h +4 -0
@@ -22,3 +22,7 @@ static inline void smpboot_restore_warm_reset_vector(void)static inline void smpboot_setup_io_apic (void ) { } + +static inline void smpboot_clear_io_apic (void ) +{ +}
Signature · 1 line
1.5.0.6
PATCH 76/79 merge native_smp_prepare_cpus
From: Glauber Costa <[email protected]>
With the previous changes, code for native_smp_prepare_cpus() in i386 and x86_64 now look very similar. merge them into smpboot.c. Minor differences are inside ifdef
--- arch/x86/kernel/smpboot.c | 170 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 137 --------------------------------- arch/x86/kernel/smpboot_64.c | 141 ---------------------------------- 3 files changed, 170 insertions(+), 278 deletions(-)
arch/x86/kernel/smpboot.c +170 -0
@@ -7,6 +7,7 @@#include <linux/err.h> #include <linux/nmi.h> +#include <asm/acpi.h> #include <asm/desc.h> #include <asm/nmi.h> #include <asm/irq.h>
@@ -75,6 +76,8 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);static atomic_t init_deasserted; +static int boot_cpu_logical_apicid; +/* ready for x86_64, no harm for x86, since it will overwrite after alloc */ unsigned char *trampoline_base =__va (SMP_TRAMPOLINE_BASE );
@@ -1002,6 +1005,173 @@ int __cpuinit native_cpu_up(unsigned int cpu) }/* +* Fall back to non SMP mode after errors. +* +* RED-PEN audit/test this more. I bet there is more state messed up here. +*/ +static __init void disable_smp (void ) +{ + cpu_present_map =cpumask_of_cpu (0 ); + cpu_possible_map =cpumask_of_cpu (0 ); +#ifdef CONFIG_X86_32 +smpboot_clear_io_apic_irqs (); +#endif +if (smp_found_config) + phys_cpu_present_map = +physid_mask_of_physid (boot_cpu_physical_apicid); +else + phys_cpu_present_map =physid_mask_of_physid (0 ); +map_cpu_to_logical_apicid (); +cpu_set (0 ,per_cpu (cpu_sibling_map,0 )); +cpu_set (0 ,per_cpu (cpu_core_map,0 )); +} + +/* +* Various sanity checks. +*/ +static int __init smp_sanity_check (unsigned max_cpus) +{ +if (!physid_isset (hard_smp_processor_id (), phys_cpu_present_map)) { +printk (KERN_WARNING "weird, boot CPU (#%d) not listed" +"by the BIOS.\n" ,hard_smp_processor_id ()); +physid_set (hard_smp_processor_id (), phys_cpu_present_map); + } + +/* +* If we couldn't find an SMP configuration at boot time, +* get out of here now! +*/ +if (!smp_found_config && !acpi_lapic) { +printk (KERN_NOTICE "SMP motherboard not detected.\n" ); +disable_smp (); +if (APIC_init_uniprocessor ()) +printk (KERN_NOTICE "Local APIC not detected." +" Using dummy APIC emulation.\n" ); +return -1 ; + } + +/* +* Should not be necessary because the MP table should list the boot +* CPU too, but we do it for the sake of robustness anyway. +*/ +if (!check_phys_apicid_present (boot_cpu_physical_apicid)) { +printk (KERN_NOTICE +"weird, boot CPU (#%d) not listed by the BIOS.\n" , + boot_cpu_physical_apicid); +physid_set (hard_smp_processor_id (), phys_cpu_present_map); + } + +/* +* If we couldn't find a local APIC, then get out of here now! +*/ +if (APIC_INTEGRATED (apic_version[boot_cpu_physical_apicid]) && + !cpu_has_apic) { +printk (KERN_ERR "BIOS bug, local APIC #%d not detected!...\n" , + boot_cpu_physical_apicid); +printk (KERN_ERR "... forcing use of dummy APIC emulation." +"(tell your hw vendor)\n" ); +smpboot_clear_io_apic (); +return -1 ; + } + +verify_local_APIC (); + +/* +* If SMP should be disabled, then really disable it! +*/ +if (!max_cpus) { +printk (KERN_INFO "SMP mode deactivated," +"forcing use of dummy APIC emulation.\n" ); +smpboot_clear_io_apic (); +#ifdef CONFIG_X86_32 +if (nmi_watchdog ==NMI_LOCAL_APIC ) { +printk (KERN_INFO "activating minimal APIC for" +"NMI watchdog use.\n" ); +connect_bsp_APIC (); +setup_local_APIC (); +end_local_APIC_setup (); + } +#endif +return -1 ; + } + +return 0 ; +} + +static void __init smp_cpu_index_default (void ) +{ +int i; +struct cpuinfo_x86 *c; + +for_each_cpu_mask (i, cpu_possible_map) { + c = &cpu_data (i); +/* mark all to hotplug */ + c->cpu_index =NR_CPUS ; + } +} + +/* +* Prepare for SMP bootup. The MP table or ACPI has been read +* earlier. Just do some sanity checking here and enable APIC mode. +*/ +void __init native_smp_prepare_cpus (unsigned int max_cpus) +{ +nmi_watchdog_default (); +smp_cpu_index_default (); + current_cpu_data = boot_cpu_data; + cpu_callin_map =cpumask_of_cpu (0 ); +mb (); +/* +* Setup boot CPU information +*/ +smp_store_cpu_info (0 );/* Final full version of the data */ + boot_cpu_logical_apicid =logical_smp_processor_id (); +current_thread_info ()->cpu =0 ;/* needed? */ +set_cpu_sibling_map (0 ); + +if (smp_sanity_check (max_cpus) <0 ) { +printk (KERN_INFO "SMP disabled\n" ); +disable_smp (); +return ; + } + +if (GET_APIC_ID (apic_read (APIC_ID )) != boot_cpu_physical_apicid) { +panic ("Boot APIC ID in local APIC unexpected (%d vs %d)" , +GET_APIC_ID (apic_read (APIC_ID )), boot_cpu_physical_apicid); +/* Or can we switch back to PIC here? */ + } + +#ifdef CONFIG_X86_32 +connect_bsp_APIC (); +#endif +/* +* Switch from PIC to APIC mode. +*/ +setup_local_APIC (); + +#ifdef CONFIG_X86_64 +/* +* Enable IO APIC before setting up error vector +*/ +if (!skip_ioapic_setup && nr_ioapics) +enable_IO_APIC (); +#endif +end_local_APIC_setup (); + +map_cpu_to_logical_apicid (); + +setup_portio_remap (); + +smpboot_setup_io_apic (); +/* +* Set up local APIC timer on boot CPU. +*/ + +printk (KERN_INFO "CPU%d: " ,0 ); +print_cpu_info (&cpu_data (0 )); +setup_boot_clock (); +} +/* * Early setup to make printk work. */ void __init native_smp_prepare_boot_cpu (void )
arch/x86/kernel/smpboot_32.c +0 -137
151 lines not on this page · raw message
arch/x86/kernel/smpboot_64.c +0 -141
144 lines not on this page · raw message
Signature · 1 line
1.5.0.6
PATCH 77/79 merge cpu_exit_clear
From: Glauber Costa <[email protected]>
this is the last remaining function in smpboot_32.c Since it is i386 specific, move it around an ifdef to smpboot.c
--- arch/x86/kernel/smpboot.c | 18 ++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 19 ------------------- 2 files changed, 18 insertions(+), 19 deletions(-)
arch/x86/kernel/smpboot.c +18 -0
@@ -1207,6 +1207,24 @@ void __init native_smp_cpus_done(unsigned int max_cpus) }#ifdef CONFIG_HOTPLUG_CPU + +# ifdef CONFIG_X86_32 +void cpu_exit_clear (void ) +{ +int cpu =raw_smp_processor_id (); + +idle_task_exit (); + +cpu_uninit (); +irq_ctx_exit (cpu); + +cpu_clear (cpu, cpu_callout_map); +cpu_clear (cpu, cpu_callin_map); + +unmap_cpu_to_logical_apicid (cpu); +} +# endif /* CONFIG_X86_32 */ +void remove_siblinginfo (int cpu) {int sibling;
arch/x86/kernel/smpboot_32.c +0 -19
@@ -74,25 +74,6 @@ EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);u8 apicid_2_node[MAX_APICID ]; -extern void unmap_cpu_to_logical_apicid (int cpu); - -#ifdef CONFIG_HOTPLUG_CPU -void cpu_exit_clear (void ) -{ -int cpu =raw_smp_processor_id (); - -idle_task_exit (); - -cpu_uninit (); -irq_ctx_exit (cpu); - -cpu_clear (cpu, cpu_callout_map); -cpu_clear (cpu, cpu_callin_map); - -unmap_cpu_to_logical_apicid (cpu); -} -#endif -/* Where the IO area was mapped on multiquad, always 0 otherwise */ void *xquad_portio;#ifdef CONFIG_X86_NUMAQ
Signature · 1 line
1.5.0.6
PATCH 78/79 move apicid mappings to smpboot.c
From: Glauber Costa <[email protected]>
They are i386 specific (the x86_64 definitions live elsewhere, and should remain there), so are enclosed around an ifdef
--- arch/x86/kernel/smpboot.c | 21 +++++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 13 ------------- 2 files changed, 21 insertions(+), 13 deletions(-)
arch/x86/kernel/smpboot.c +21 -0
@@ -25,6 +25,27 @@#include <mach_wakecpu.h> #include <smpboot_hooks.h> +/* +* FIXME: For x86_64, those are defined in other files. But moving them here, +* would make the setup areas dependent on smp, which is a loss. When we +* integrate apic between arches, we can probably do a better job, but +* right now, they'll stay here -- glommer +*/ +#ifdef CONFIG_X86_32 +/* which logical CPU number maps to which CPU (physical APIC ID) */ +u16 x86_cpu_to_apicid_init[NR_CPUS ]__initdata = + { [0 ...NR_CPUS -1 ] =BAD_APICID }; +void *x86_cpu_to_apicid_early_ptr; +DEFINE_PER_CPU (u16, x86_cpu_to_apicid) =BAD_APICID ; +EXPORT_PER_CPU_SYMBOL (x86_cpu_to_apicid); + +u16 x86_bios_cpu_apicid_init[NR_CPUS ]__initdata + = { [0 ...NR_CPUS -1 ] =BAD_APICID }; +void *x86_bios_cpu_apicid_early_ptr; +DEFINE_PER_CPU (u16, x86_bios_cpu_apicid) =BAD_APICID ; +EXPORT_PER_CPU_SYMBOL (x86_bios_cpu_apicid); +#endif +/* State of each CPU */ DEFINE_PER_CPU(int, cpu_state) = { 0 };
arch/x86/kernel/smpboot_32.c +0 -13
@@ -59,19 +59,6 @@#include <asm/vmi.h> #include <asm/mtrr.h> -/* which logical CPU number maps to which CPU (physical APIC ID) */ -u16 x86_cpu_to_apicid_init[NR_CPUS ]__initdata = - { [0 ...NR_CPUS -1 ] =BAD_APICID }; -void *x86_cpu_to_apicid_early_ptr; -DEFINE_PER_CPU (u16, x86_cpu_to_apicid) =BAD_APICID ; -EXPORT_PER_CPU_SYMBOL (x86_cpu_to_apicid); - -u16 x86_bios_cpu_apicid_init[NR_CPUS ]__initdata - = { [0 ...NR_CPUS -1 ] =BAD_APICID }; -void *x86_bios_cpu_apicid_early_ptr; -DEFINE_PER_CPU (u16, x86_bios_cpu_apicid) =BAD_APICID ; -EXPORT_PER_CPU_SYMBOL (x86_bios_cpu_apicid); -u8 apicid_2_node[MAX_APICID ];/* Where the IO area was mapped on multiquad, always 0 otherwise */
Signature · 1 line
1.5.0.6
PATCH 79/79 remove smpboot_32.c and smpboot_64.c
From: Glauber Costa <[email protected]>
Remove the last leftovers from the files. Move the ones that are still used to the files they belong, the others that grep can't reach, simply throw away.
Merge comments ontop of file and that's it: smpboot integrated
--- arch/x86/kernel/Makefile | 4 +- arch/x86/kernel/smpboot.c | 42 ++++++++++++++++++++++++ arch/x86/kernel/smpboot_32.c | 68 --------------------------------------- arch/x86/kernel/smpboot_64.c | 73 ------------------------------------------ arch/x86/pci/numa.c | 7 +++- 5 files changed, 50 insertions(+), 144 deletions(-) delete mode 100644 arch/x86/kernel/smpboot_32.c delete mode 100644 arch/x86/kernel/smpboot_64.c
arch/x86/kernel/Makefile +2 -2
@@ -47,10 +47,10 @@ obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_PCI) += early-quirks.o apm-y := apm_32.o obj-$(CONFIG_APM) += apm.o -obj-$(CONFIG_X86_SMP) += smpboot_$(BITS).o smp.o +obj-$(CONFIG_X86_SMP) += smp.o obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o tlb_$(BITS).o obj-$(CONFIG_X86_32_SMP) += smpcommon.o -obj-$(CONFIG_X86_64_SMP) += smpboot_64.o tsc_sync.o smpcommon.o +obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o obj-$(CONFIG_X86_MPPARSE) += mpparse_$(BITS).o obj-$(CONFIG_X86_LOCAL_APIC) += apic_$(BITS).o nmi_$(BITS).o
arch/x86/kernel/smpboot.c +42 -0
51 lines not on this page · raw message
arch/x86/kernel/smpboot_32.c deleted +0 -68
68 lines not on this page · raw message
arch/x86/kernel/smpboot_64.c deleted +0 -73
73 lines not on this page · raw message
arch/x86/pci/numa.c +6 -1
@@ -20,7 +20,12 @@ int mp_bus_id_to_local[MAX_MP_BUSSES];int quad_local_to_mp_bus_id [NR_CPUS /4 ][4 ];#define QUADLOCAL2BUS (quad,local) (quad_local_to_mp_bus_id[quad][local]) -extern void *xquad_portio;/* Where the IO area was mapped */ +/* Where the IO area was mapped on multiquad, always 0 otherwise */ +void *xquad_portio; +#ifdef CONFIG_X86_NUMAQ +EXPORT_SYMBOL (xquad_portio); +#endif +#define XQUAD_PORT_ADDR (port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)#define PCI_CONF1_MQ_ADDRESS (bus, devfn, reg) \
Signature · 1 line
1.5.0.6
Re: [PATCH 58/79] [PATCH] include mach_apic.h in smpboot_64.c and smpboot.c
In reply to Glauber de Oliveira CostaQuoted 8 lines · Glauber de Oliveira Costa
From: Glauber Costa <[email protected]>
After the inclusion, a lot of files needs fixing for conflicts, some of them in the headers themselves, to accomodate for both i386 and
x86_64versions.Signed-off-by Glauber Costa <[email protected]>---
Quoted 11 lines
arch/x86/kernel/acpi/boot.c | 2 ++ arch/x86/kernel/mpparse_64.c | 2 ++ arch/x86/kernel/smpboot.c | 2 ++ arch/x86/kernel/smpboot_64.c | 1 + arch/x86/vdso/Makefile | 2 +- include/asm-x86/apic.h | 1 - include/asm-x86/apicdef.h | 6 ------ include/asm-x86/mach-default/mach_apic.h | 11 +++++++++++ include/asm-x86/mach-default/mach_apicdef.h | 5 +++++ include/asm-x86/smp_64.h | 9 +-------- 10 files changed, 25 insertions(+), 16 deletions(-)
please don't.
before this patchinclude/asm-x86/mach_apic.h is only for x86_64 only include/asm-x86/mach-default/mach_apic.h is for i386 only.
and both have __ASM_MACH_APIC_H defined.
may need another name?
YH
Re: [PATCH 58/79] [PATCH] include mach_apic.h in smpboot_64.c and smpboot.c
Quoted 28 lines · Yinghai Lu
Quoted 8 lines · Glauber de Oliveira Costa
From: Glauber Costa <[email protected]>
After the inclusion, a lot of files needs fixing for conflicts, some of them in the headers themselves, to accomodate for both i386 and
x86_64versions.Signed-off-by Glauber Costa <[email protected]>---
Quoted 11 lines
arch/x86/kernel/acpi/boot.c | 2 ++ arch/x86/kernel/mpparse_64.c | 2 ++ arch/x86/kernel/smpboot.c | 2 ++ arch/x86/kernel/smpboot_64.c | 1 + arch/x86/vdso/Makefile | 2 +- include/asm-x86/apic.h | 1 - include/asm-x86/apicdef.h | 6 ------ include/asm-x86/mach-default/mach_apic.h | 11 +++++++++++ include/asm-x86/mach-default/mach_apicdef.h | 5 +++++ include/asm-x86/smp_64.h | 9 +-------- 10 files changed, 25 insertions(+), 16 deletions(-)please don't.
before this patch
include/asm-x86/mach_apic.his only forx86_64onlyinclude/asm-x86/mach-default/mach_apic.his for i386 only.
Quoted 5 lines
and both have
__ASM_MACH_APIC_Hdefined.may need another name?
YH
Another name is possible, but I'd prefer to get rid of the asm-x86/mach_apic.h. The goal here is to have things integrated, so unless really necessary, this is prefered.
Is this related to your problem anyhow? (just in curiosity)
Re: [PATCH 58/79] [PATCH] include mach_apic.h in smpboot_64.c and smpboot.c
Quoted 12 lines · Glauber Costa
Quoted 10 lines · Yinghai Lu
Quoted 1 line
10 files changed, 25 insertions(+), 16 deletions(-)please don't.
before this patch
include/asm-x86/mach_apic.his only forx86_64onlyinclude/asm-x86/mach-default/mach_apic.his for i386 only.and both have
__ASM_MACH_APIC_Hdefined.
Quoted 8 lines
Quoted 3 lines
may need another name?
YH
Another name is possible, but I'd prefer to get rid of the
asm-x86/mach_apic.h. The goal here is to have things integrated, so unless really necessary, this is prefered.Is this related to your problem anyhow? (just in curiosity)
No
YH
Re: [PATCH 58/79] [PATCH] include mach_apic.h in smpboot_64.c and smpboot.c
In reply to Glauber CostaQuoted 30 lines · Glauber Costa
Quoted 28 lines · Yinghai Lu
Quoted 8 lines · Glauber de Oliveira Costa
From: Glauber Costa <[email protected]>
After the inclusion, a lot of files needs fixing for conflicts, some of them in the headers themselves, to accomodate for both i386 and
x86_64versions.Signed-off-by Glauber Costa <[email protected]>---
Quoted 11 lines
arch/x86/kernel/acpi/boot.c | 2 ++ arch/x86/kernel/mpparse_64.c | 2 ++ arch/x86/kernel/smpboot.c | 2 ++ arch/x86/kernel/smpboot_64.c | 1 + arch/x86/vdso/Makefile | 2 +- include/asm-x86/apic.h | 1 - include/asm-x86/apicdef.h | 6 ------ include/asm-x86/mach-default/mach_apic.h | 11 +++++++++++ include/asm-x86/mach-default/mach_apicdef.h | 5 +++++ include/asm-x86/smp_64.h | 9 +-------- 10 files changed, 25 insertions(+), 16 deletions(-)please don't.
before this patch
include/asm-x86/mach_apic.his only forx86_64onlyinclude/asm-x86/mach-default/mach_apic.his for i386 only.
Quoted 8 lines
Quoted 5 lines
and both have
__ASM_MACH_APIC_Hdefined.may need another name?
YH
Another name is possible, but I'd prefer to get rid of the
asm-x86/mach_apic.h. The goal here is to have things integrated, so unless really necessary, this is prefered.
anyway, before that I hope you can rename include/asm-x86/mach_apic.h to include/asm-x86/apic_ext.h
you may move bits from apic_ext.h to mach-default/mach_apic.h later.
YH
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
In reply to Glauber de Oliveira CostaQuoted 4 lines · Glauber de Oliveira Costa
EOI is a write-only register. Using write around will have the effect of reading it, which will make all subsequent reads of the ESR register to return an error code. It was unnotices for quite a while because main sources of reading the ESR register where done prior to apic interrupt enabling.
Are you sure this actually triggers for APIC chips affected by the
erratum in question? And please note that for them the effect of two consecutive writes will be much more disastrous than setting a bit in the ESR register.
Maciej
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
Quoted 11 lines · Maciej W. Rozycki
Quoted 4 lines · Glauber de Oliveira Costa
EOI is a write-only register. Using write around will have the effect of reading it, which will make all subsequent reads of the ESR register to return an error code. It was unnotices for quite a while because main sources of reading the ESR register where done prior to apic interrupt enabling.
Are you sure this actually triggers for APIC chips affected by the
erratum in question? And please note that for them the effect of two consecutive writes will be much more disastrous than setting a bit in the ESR register.Maciej
I'm not _sure_, but I can't find anything in the errata list that states otherwise. It would be great that anyone has such a system to test it. But with the current conditions, it will break bootup code. In case it is really a problem, we'd need to make a special case for that.
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
Quoted 8 lines · Glauber Costa
Quoted 3 lines
Are you sure this actually triggers for APIC chips affected by the erratum
in question? And please note that for them the effect of two consecutive writes will be much more disastrous than setting a bit in the ESR register.I'm not _sure_, but I can't find anything in the errata list that states otherwise. It would be great that anyone has such a system to test it. But with the current conditions, it will break bootup code. In case it is really a problem, we'd need to make a special case for that.
I have dug out the relevant erratum -- it is the 11AP one as referred to
from arch/x86/kernel/smp_32.c and the text even mentions the EOI register explicitly:
"This problem affects systems that use HOLD/HLDA or BOFF# and enable the local APIC of the CPU. If the second APIC write cycle is an EOI (End of Interrupt) cycle, the CPU will stop servicing subsequent interrupts of equal or less priority. This may cause the system to hang. If the second APIC write cycle is not an EOI, the failure mode would depend on the particular APIC register that is not updated correctly."
But on this occasion I took the opportunity to refresh my memory on the
ESR register and there is apparently no bit there, at least up to Pentium4, that would signify an error resulting from an incorrect access type -- only accesses to invalid register indices are marked as errors.
Which bit of the ESR can you see set as a result of using an RMW cycle to
the EOI register and with what kind of CPU/APIC? And why wouldn't it have affected older kernels? -- the error interrupt has been kept enabled by Linux for ages and writes to the EOI register are frequent enough it would be hard to miss the resulting flood of errors. Hmm...
Maciej
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
Quoted 13 lines · Maciej W. Rozycki
Quoted 7 lines · Glauber Costa
Quoted 3 lines
Are you sure this actually triggers for APIC chips affected by the erratum
in question? And please note that for them the effect of two consecutive writes will be much more disastrous than setting a bit in the ESR register.I'm not _sure_, but I can't find anything in the errata list that states otherwise. It would be great that anyone has such a system to test it. But with the current conditions, it will break bootup code. In case it is really a problem, we'd need to make a special case for that.
I have dug out the relevant erratum -- it is the 11AP one as referred to
fromarch/x86/kernel/smp_32.cand the text even mentions the EOI register explicitly:
Quoted 8 lines
"This problem affects systems that use HOLD/HLDA or BOFF# and enable the local APIC of the CPU. If the second APIC write cycle is an EOI (End of Interrupt) cycle, the CPU will stop servicing subsequent interrupts of equal or less priority. This may cause the system to hang. If the second APIC write cycle is not an EOI, the failure mode would depend on the particular APIC register that is not updated correctly."
But on this occasion I took the opportunity to refresh my memory on the
ESR register and there is apparently no bit there, at least up to Pentium4, that would signify an error resulting from an incorrect access type -- only accesses to invalid register indices are marked as errors.Which bit of the ESR can you see set as a result of using an RMW cycle to
the EOI register and with what kind of CPU/APIC? And why wouldn't it have affected older kernels? -- the error interrupt has been kept enabled by Linux for ages and writes to the EOI register are frequent enough it would be hard to miss the resulting flood of errors. Hmm...
I see bit 7 - Illegal Register Address being set.
I believe the reason we never saw it, is that the ESR register is not checked that often when interrupts are enabled. In the new bootup state machine, that is inherited from x86_64, we call do_boot_cpu with irqs clearly enabled, and check esr in the process.
But I can understand from the spec you posted that this is clearly an error. So I'd have better come up with a new solution from this
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
Quoted 1 line · Glauber Costa
I see bit 7 - Illegal Register Address being set.
Hmm, it looks like the only one to be reasonably set under these
conditions, but I have never seen it reported for a read cycle to the EOI register anyway, so I suppose it has to be a relatively recent addition.
Quoted 2 lines
I believe the reason we never saw it, is that the ESR register is not checked that often when interrupts are enabled. In the new bootup state machine, that
Well, as I wrote, the error interrupt handler is always enabled,
reporting the state recorded in the ESR register as soon as an error condition triggers and if an RMW cycle was a problem before, we would have seen a flood of reports from people -- like we indeed have many times for inter-APIC bus data corruption that triggers the same event (using bits 3:0 in the ESR as relevant).
Quoted 2 lines
is inherited from
x86_64, we calldo_boot_cpuwith irqs clearly enabled, and check esr in the process.
Please note that ESR may hold some leftover state from whatever happened
before Linux has taken control, so it is reasonable and I think actually recommended by Intel (FWIW) to clear the register before enabling the error interrupt. For how to clear the ESR properly, please see setup_local_APIC() -- subtle differences and errata in various APIC implementations have made it more complicated than necessary, sigh...
Quoted 2 lines
But I can understand from the spec you posted that this is clearly an error. So I'd have better come up with a new solution from this
Well, with CONFIG_X86_GOOD_APIC set there is no RMW access to the ESR asapic_write_around() expands to apic_write(). And the option is meant to be clear only for the original integrated APIC as included in the Pentium processor ("Pentium-Classic" in the Kconfig nomenclature). I have no means to test such a system, but I still have a working dual-Pentium-MMX machine, which features local APICs that should be the same modulo errata. I may check and see whether a RMW cycle to the ESR triggers any problems with this computer, but the box is currently at the other end of the continent, so it will take a while.
I have asked this question already: what kind of CPU are you running on?
Do you really need to have CONFIG_X86_GOOD_APIC clear with it?
Maciej
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
Quoted 7 lines · Maciej W. Rozycki
Please note that ESR may hold some leftover state from whatever happened
before Linux has taken control, so it is reasonable and I think actually recommended by Intel (FWIW) to clear the register before enabling the error interrupt. For how to clear the ESR properly, please seesetup_local_APIC()-- subtle differences and errata in various APIC implementations have made it more complicated than necessary, sigh...
iirc a lot of the ESR weirdness was on NUMAQ only, which is down to one of two last machines running Linux which will hopefully die soon ...
-Andi
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
In reply to Maciej W. RozyckiQuoted 5 lines · Maciej W. Rozycki
Quoted 2 lines
is inherited from
x86_64, we calldo_boot_cpuwith irqs clearly enabled, and check esr in the process.Please note that ESR may hold some leftover state from whatever happened
before Linux has taken control, so it is reasonable and I think actually recommended by Intel (FWIW) to clear the register before enabling the error interrupt. For how to clear the ESR properly, please seesetup_local_APIC()-- subtle differences and errata in various APIC implementations have made it more complicated than necessary, sigh...
which excerpt specifically are you talking about ? the only ESR mention I see in setup_local_APIC() is this:
/* Pound the ESR really hard over the head with a big hammer -
mbligh */
if (esr_disable) {
apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0);
}which seems more like a disablement.
the bootup code does clean it, tough, by writing and reading the ESR.
Quoted 9 lines
Quoted 2 lines
But I can understand from the spec you posted that this is clearly an error. So I'd have better come up with a new solution from this
Well, with
CONFIG_X86_GOOD_APICset there is no RMW access to the ESR asapic_write_around()expands toapic_write(). And the option is meant to be clear only for the original integrated APIC as included in the Pentium processor ("Pentium-Classic" in theKconfignomenclature). I have no means to test such a system, but I still have a working dual-Pentium-MMX machine, which features local APICs that should be the same modulo errata. I may check and see whether a RMW cycle to the ESR triggers any problems with this computer, but the box is currently at the other end of the continent, so it will take a while.I have asked this question already: what kind of CPU are you running on?
Do you really need to haveCONFIG_X86_GOOD_APICclear with it?
My testings that triggered that were with qemu, with randconfigs. Probably it has a good apic, but it is good that it triggered anyway. Otherwise I'd never see it.
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
Quoted 11 lines · Glauber Costa
the only ESR mention I see in
setup_local_APIC()is this:/* Pound the ESR really hard over the head with a big hammer - mbligh */ if (esr_disable) { apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); }which seems more like a disablement.
There is more later on...
Quoted 1 line
the bootup code does clean it, tough, by writing and reading the ESR.
... basically for the original Pentium and Pentium/MMX APIC you only had to read the ESR to get at the bits. The read would clear them as well as a side-effect. Although at that stage already it was mentioned in the spec that for future compatibility a write of zero beforehand (ignored as the register was r/o) should be performed. Which indeed became a requirement from PentiumPro onwards as with these processors it was the write that copied the internal error latches into the visible ESR register. Except that some Pentium APICs had an erratum, where ESR was indeed r/w and the leading write of zero would actually clear the register losing the recorded state, so it had to be avoided despite the recommendation. Hence the code you can see within:
if (integrated && !esr_disable) {
}
I suppose other APIC implementers were not that keen on keeping bug compatibility, so chances are other APIC core work just fine as specified by the architecture (for whatever the meaning of "fine" is).
Note the usual APIC error interrupt handler is smp_error_interrupt().
Quoted 6 lines
Quoted 3 lines
I have asked this question already: what kind of CPU are you running on?
Do you really need to haveCONFIG_X86_GOOD_APICclear with it?My testings that triggered that were with qemu, with randconfigs. Probably it has a good apic, but it is good that it triggered anyway. Otherwise I'd never see it.
Ah, I see -- it may be worth checking what actual hardware does and
fixing QEMU if necessary for it to match reality then. ;-)
OTOH, if actual modern hardware triggered such an error, then for the
sake of a generic "runs everywhere" kernel either ack_APIC_irq() or even apic_write_around() could be modified to perform a run-time check if configured with !CONFIG_X86_GOOD_APIC and avoid the read if unnecessary; it's an erratum workaround after all and SMP Pentium systems suffering from this bug (UP Pentium systems did not nor had a way to enable the local APIC normally) are probably an insignificant minority if any at all left these days. Therefore it should be a negligible sacrifice of performance.
Maciej
Re: [PATCH 45/79] [PATCH] fix apic acking of irqs
Quoted 34 lines · Maciej W. Rozycki
Quoted 11 lines · Glauber Costa
the only ESR mention I see in
setup_local_APIC()is this:/* Pound the ESR really hard over the head with a big hammer - mbligh */ if (esr_disable) { apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0); }which seems more like a disablement.
There is more later on...
Quoted 1 line
the bootup code does clean it, tough, by writing and reading the ESR.
... basically for the original Pentium and Pentium/MMX APIC you only had to read the ESR to get at the bits. The read would clear them as well as a side-effect. Although at that stage already it was mentioned in the spec that for future compatibility a write of zero beforehand (ignored as the register was r/o) should be performed. Which indeed became a requirement from PentiumPro onwards as with these processors it was the write that copied the internal error latches into the visible ESR register. Except that some Pentium APICs had an erratum, where ESR was indeed r/w and the leading write of zero would actually clear the register losing the recorded state, so it had to be avoided despite the recommendation. Hence the code you can see within:
if (integrated && !esr_disable) {
}I suppose other APIC implementers were not that keen on keeping bug compatibility, so chances are other APIC core work just fine as specified by the architecture (for whatever the meaning of "fine" is).
Note the usual APIC error interrupt handler is
smp_error_interrupt().Quoted 6 lines
Quoted 3 lines
I have asked this question already: what kind of CPU are you running on?
Do you really need to haveCONFIG_X86_GOOD_APICclear with it?My testings that triggered that were with qemu, with randconfigs. Probably it has a good apic, but it is good that it triggered anyway. Otherwise I'd never see it.
Quoted 5 lines
Ah, I see -- it may be worth checking what actual hardware does and
fixing QEMU if necessary for it to match reality then. ;-)OTOH, if actual modern hardware triggered such an error, then for the
sake of a generic "runs everywhere" kernel eitherack_APIC_irq()or evenapic_write_around()could be modified to perform a run-time check if configured with !CONFIG_X86_GOOD_APIC and avoid the read if unnecessary; it's an erratum workaround after all and SMP Pentium systems suffering from this bug (UP Pentium systems did not nor had a way to enable the local APIC normally) are probably an insignificant minority if any at all left these days. Therefore it should be a negligible sacrifice of performance.
I just tested in some real i386 that I have around here, and the reading of EOI does not seem to be illegal. (Well, at least in those I've tested).
OTOH, ignoring the read in qemu makes the tree boot just okay. So I agree with you now, we might well fix qemu, and revert this patch.
Ingo, any word on that?
Quoted 1 line
Maciej
the small fix below was needed - it is possible to build ACPI on 32-bit with APIC support disabled. Otherwise it's looking good in my testing.
Ingo
-----------------
Subject: x86: smp unify2 include mach apic h in smpboot 64 c and smpboot c fix
From: Ingo Molnar <[email protected]>
Date: Wed Mar 19 19:25:58 CET 2008
--- arch/x86/kernel/acpi/boot.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kernel/acpi/boot.c +3 -1
@@ -40,7 +40,9 @@#include <asm/io.h> #include <asm/mpspec.h> -#include <mach_apic.h> +#ifdef CONFIG_X86_LOCAL_APIC +# include <mach_apic.h> +#endif static int __initdata acpi_force =0 ;
Quoted 3 lines · Ingo Molnar
the small fix below was needed - it is possible to build ACPI on 32-bit with APIC support disabled. Otherwise it's looking good in my testing.
another fix for a small (and rare) build bug i found is below: it is possible to build a kernel with CONFIG_X86_MPPARSE but without CONFIG_SMP. In that case x86_bios_cpu_apicid has to be provided, and the use of the early-apicids has to be inhibited.
Ingo
--- arch/x86/kernel/mpparse_32.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/x86/kernel/mpparse_32.c +6 -0
@@ -76,6 +76,10 @@ unsigned disabled_cpus __cpuinitdata;/* Bitmask of physically existing CPUs */ physid_mask_t phys_cpu_present_map; +#ifndef CONFIG_SMP +DEFINE_PER_CPU (u16, x86_bios_cpu_apicid) =BAD_APICID ; +#endif +/* * Intel MP BIOS table parsing routines: */
@@ -230,6 +234,7 @@ static void __cpuinit MP_processor_info def_to_bigsmp =1 ; } } +#ifdef CONFIG_SMP /* are we being called early in kernel startup? */ if (x86_cpu_to_apicid_early_ptr) {u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
@@ -241,6 +246,7 @@ static void __cpuinit MP_processor_infoper_cpu (x86_cpu_to_apicid, cpu) = m->mpc_apicid; per_cpu(x86_bios_cpu_apicid, cpu) = m->mpc_apicid; } +#endif cpu_set (cpu, cpu_present_map); }
Quoted 9 lines · Glauber de Oliveira Costa
Testing and bisectability:
The end result was tested in all my hardware (which includes qemu ;-). It does not mean it will boot _your_ hardware, but I did my best ;-)
The tree at least compiles in more than 20 randconfigs (for each of
x86_64and i386) For i386, each of the subarchitectures was compiled at least once. (By compile, I obviously mean, every patch, individually)
very nice work! I'll pick it up - and i'm not too worried about breakages because at 80 patches granularity any problem should be identifiable in a very finegrained way.
Ingo
Quoted 8 lines · Ingo Molnar
Quoted 5 lines · Glauber de Oliveira Costa
Testing and bisectability:
The end result was tested in all my hardware (which includes qemu ;-). It does not mean it will boot _your_ hardware, but I did my best ;-)
Quoted 9 lines
Quoted 4 lines
The tree at least compiles in more than 20 randconfigs (for each of
x86_64and i386) For i386, each of the subarchitectures was compiled at least once. (By compile, I obviously mean, every patch, individually)very nice work! I'll pick it up - and i'm not too worried about breakages because at 80 patches granularity any problem should be identifiable in a very finegrained way.
it broke 4 sockets quad core above with 64 bit
Booting processor 11/15 ip 6000
Initializing CPU#11
masked ExtINT on CPU#11
Calibrating delay using timer specific routine.. 4589.46 BogoMIPS (lpj=9178934)
CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
CPU: L2 Cache: 512K (64 bytes/line)
CPU 11/f -> Node 2
CPU: Physical Processor ID: 2
CPU: Processor Core ID: 3
CPU11: Quad-Core AMD Opteron(tm) Processor 8356 stepping 03 checking TSC synchronization [CPU#0 -> CPU#11]: passed.
Booting processor 12/16 ip 6000
looks like local apic id up 4 bit is masked out. so can not start 0x10 above any more.
YH
Quoted 34 lines · Yinghai Lu
Quoted 8 lines · Ingo Molnar
Quoted 5 lines · Glauber de Oliveira Costa
Testing and bisectability:
The end result was tested in all my hardware (which includes qemu ;-). It does not mean it will boot _your_ hardware, but I did my best ;-)
Quoted 9 lines
Quoted 4 lines
The tree at least compiles in more than 20 randconfigs (for each of
x86_64and i386) For i386, each of the subarchitectures was compiled at least once. (By compile, I obviously mean, every patch, individually)very nice work! I'll pick it up - and i'm not too worried about breakages because at 80 patches granularity any problem should be identifiable in a very finegrained way.
it broke 4 sockets quad core above with 64 bit
Booting processor 11/15 ip 6000
Initializing CPU#11
masked ExtINT on CPU#11
Calibrating delay using timer specific routine.. 4589.46 BogoMIPS (lpj=9178934)
CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
CPU: L2 Cache: 512K (64 bytes/line)
CPU 11/f -> Node 2
CPU: Physical Processor ID: 2
CPU: Processor Core ID: 3
CPU11: Quad-Core AMD Opteron(tm) Processor 8356 stepping 03 checking TSC synchronization [CPU#0 -> CPU#11]: passed.
Booting processor 12/16 ip 6000
Quoted 2 lines
looks like local apic id up 4 bit is masked out. so can not start
0x10above any more.
in wakeup_secondary_via_INIT
before the patchsets
64 bit code:
/*
* Send IPI
*/
apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
| APIC_DM_INIT);after patchset
/* Boot on the stack */
/* Kick the second */
apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);So that is wrong! esp for system has ext apic id that is has 8 bits instead of 4 bits.
YH
Quoted 50 lines · Yinghai Lu
Quoted 34 lines · Yinghai Lu
Quoted 8 lines · Ingo Molnar
Quoted 5 lines · Glauber de Oliveira Costa
Testing and bisectability:
The end result was tested in all my hardware (which includes qemu ;-). It does not mean it will boot _your_ hardware, but I did my best ;-)
Quoted 9 lines
Quoted 4 lines
The tree at least compiles in more than 20 randconfigs (for each of
x86_64and i386) For i386, each of the subarchitectures was compiled at least once. (By compile, I obviously mean, every patch, individually)very nice work! I'll pick it up - and i'm not too worried about breakages because at 80 patches granularity any problem should be identifiable in a very finegrained way.
it broke 4 sockets quad core above with 64 bit
Booting processor 11/15 ip 6000
Initializing CPU#11
masked ExtINT on CPU#11
Calibrating delay using timer specific routine.. 4589.46 BogoMIPS (lpj=9178934)
CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
CPU: L2 Cache: 512K (64 bytes/line)
CPU 11/f -> Node 2
CPU: Physical Processor ID: 2
CPU: Processor Core ID: 3
CPU11: Quad-Core AMD Opteron(tm) Processor 8356 stepping 03 checking TSC synchronization [CPU#0 -> CPU#11]: passed.
Booting processor 12/16 ip 6000Quoted 2 lines
looks like local apic id up 4 bit is masked out. so can not start
0x10above any more.in
wakeup_secondary_via_INIT
before the patchsets
64 bit code:/* * Send IPI */ apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
Quoted 9 lines
after patchset
/* Boot on the stack */ /* Kick the second */ apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);So that is wrong! esp for system has ext apic id that is has 8 bits instead of 4 bits.
it seems there is two wakeup_secondary_cpu. one for NMI and one INIT.
but should have
#define WAKE_SECONDARY_VIA_INIT
for x86_64
but after
#ifdef CONFIG_X86_64
#undef WAKE_SECONDARY_VIA_NMI
#define WAKE_SECONDARY_VIA_INIT
#endif
it still doesn't work.
YH
Quoted 70 lines · Yinghai Lu
Quoted 49 lines · Yinghai Lu
Quoted 34 lines · Yinghai Lu
Quoted 8 lines · Ingo Molnar
Quoted 5 lines · Glauber de Oliveira Costa
Testing and bisectability:
The end result was tested in all my hardware (which includes qemu ;-). It does not mean it will boot _your_ hardware, but I did my best ;-)
Quoted 9 lines
Quoted 4 lines
The tree at least compiles in more than 20 randconfigs (for each of
x86_64and i386) For i386, each of the subarchitectures was compiled at least once. (By compile, I obviously mean, every patch, individually)very nice work! I'll pick it up - and i'm not too worried about breakages because at 80 patches granularity any problem should be identifiable in a very finegrained way.
it broke 4 sockets quad core above with 64 bit
Booting processor 11/15 ip 6000
Initializing CPU#11
masked ExtINT on CPU#11
Calibrating delay using timer specific routine.. 4589.46 BogoMIPS (lpj=9178934)
CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
CPU: L2 Cache: 512K (64 bytes/line)
CPU 11/f -> Node 2
CPU: Physical Processor ID: 2
CPU: Processor Core ID: 3
CPU11: Quad-Core AMD Opteron(tm) Processor 8356 stepping 03 checking TSC synchronization [CPU#0 -> CPU#11]: passed.
Booting processor 12/16 ip 6000Quoted 2 lines
looks like local apic id up 4 bit is masked out. so can not start
0x10above any more.in
wakeup_secondary_via_INIT
before the patchsets
64 bit code:/* * Send IPI */ apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);Quoted 9 lines
after patchset
/* Boot on the stack */ /* Kick the second */ apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);So that is wrong! esp for system has ext apic id that is has 8 bits instead of 4 bits.
it seems there is two
wakeup_secondary_cpu. one for NMI and one INIT.but should have
#define
WAKE_SECONDARY_VIA_INITfor
x86_64but after
Quoted 8 lines
#ifdef
CONFIG_X86_64
#undefWAKE_SECONDARY_VIA_NMI
#defineWAKE_SECONDARY_VIA_INIT
#endifit still doesn't work.
YH
Thanks for the testing Yinghai. I'll take a deeper look as soon as I can. The two routines are provided, since i386 numa-q inits the startup sequence through NMIs. The _VIA_INIT is already defined in x86_64 in the mach-default/ headers.
What happens exactly? Does it hang indefinitely ? Or just for a while? Also, can you provide the exact commit in which this problem start? (just to be sure)
As a debugging aid, can you also define the Dprintks in the code? I've seen hangs before in which the processor was indeed executing its init sequence, (although it did not seem to), but was hanging in the calibrate loop.
Thanks
Quoted 80 lines · Glauber Costa
Quoted 70 lines · Yinghai Lu
Quoted 49 lines · Yinghai Lu
Quoted 34 lines · Yinghai Lu
Quoted 8 lines · Ingo Molnar
Quoted 5 lines · Glauber de Oliveira Costa
Testing and bisectability:
The end result was tested in all my hardware (which includes qemu ;-). It does not mean it will boot _your_ hardware, but I did my best ;-)
Quoted 9 lines
Quoted 4 lines
The tree at least compiles in more than 20 randconfigs (for each of
x86_64and i386) For i386, each of the subarchitectures was compiled at least once. (By compile, I obviously mean, every patch, individually)very nice work! I'll pick it up - and i'm not too worried about breakages because at 80 patches granularity any problem should be identifiable in a very finegrained way.
it broke 4 sockets quad core above with 64 bit
Booting processor 11/15 ip 6000
Initializing CPU#11
masked ExtINT on CPU#11
Calibrating delay using timer specific routine.. 4589.46 BogoMIPS (lpj=9178934)
CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
CPU: L2 Cache: 512K (64 bytes/line)
CPU 11/f -> Node 2
CPU: Physical Processor ID: 2
CPU: Processor Core ID: 3
CPU11: Quad-Core AMD Opteron(tm) Processor 8356 stepping 03 checking TSC synchronization [CPU#0 -> CPU#11]: passed.
Booting processor 12/16 ip 6000Quoted 2 lines
looks like local apic id up 4 bit is masked out. so can not start
0x10above any more.in
wakeup_secondary_via_INIT
before the patchsets
64 bit code:/* * Send IPI */ apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);Quoted 9 lines
after patchset
/* Boot on the stack */ /* Kick the second */ apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);So that is wrong! esp for system has ext apic id that is has 8 bits instead of 4 bits.
it seems there is two
wakeup_secondary_cpu. one for NMI and one INIT.but should have
#define
WAKE_SECONDARY_VIA_INITfor
x86_64but after
Quoted 8 lines
#ifdef
CONFIG_X86_64
#undefWAKE_SECONDARY_VIA_NMI
#defineWAKE_SECONDARY_VIA_INIT
#endifit still doesn't work.
YH
Quoted 8 lines
Thanks for the testing Yinghai. I'll take a deeper look as soon as I can. The two routines are provided, since i386 numa-q inits the startup sequence through NMIs. The
_VIA_INITis already defined inx86_64in the mach-default/ headers.What happens exactly? Does it hang indefinitely ? Or just for a while? Also, can you provide the exact commit in which this problem start? (just to be sure)
hang indefinitely.
maybe some apic code merge problem...
YH
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 44 lines · Yinghai Lu
Quoted 20 lines · Yinghai Lu
Quoted 18 lines · Ingo Molnar
Quoted 2 lines · Yinghai Lu
how to bisect x86.git tree?. it always said it can not bisect seeked tree.
ah. Does this work:
git-checkout my-tree x86/latest
git-bisect start
git-bisect good x86/base
git-bisect bad x86/latestx86/base is the Linus tree that x86.git is based against. You can see all the x86.git/latest changes by doing:
Quoted 7 lines
Quoted 4 lines
git-log x86/base..x86/latest
Ingo
works. will let you know the result.
yhlu@mpk:~/xx/xx/kernel/x86/linux-2.6> git-bisect bad
d1c707188ad646c8094cac9afb1738e7d0196ff2is first bad commit commitd1c707188ad646c8094cac9afb1738e7d0196ff2
Author: Glauber de Oliveira Costa <[email protected]>
Date: Wed Mar 19 14:25:53 2008 -0300x86: include
mach_apic.hinsmpboot_64.candsmpboot.cAfter the inclusion, a lot of files needs fixing for conflicts, some of them in the headers themselves, to accomodate for both i386 and
x86_64versions.[ [email protected]: build fix ]
Quoted 9 lines
Signed-off-by Glauber Costa <[email protected]>Signed-off-by Ingo Molnar <[email protected]>:040000 040000
19f574e64bb8003bbe984f3a8c1315db969dfdcd
6ffe96588c77bc936705599fa110107856201115M arch
:040000 04000061269347ad4f384ed85cc87c4f2d004ed94492ac
8f5c713da25579a3cdf63db3d4c2f795261d0521M include
yhlu@mpk:~/xx/xx/kernel/x86/linux-2.6>
attached patch fix that.
YH
include/asm-x86/mach-default/mach_apicdef.h +3 -3
@@ -5,13 +5,12 @@#ifdef CONFIG_X86_64 #define APIC_ID_MASK (0xFFu<<24) +#define GET_APIC_ID (x) (((x)>>24)&0xFFu)#define SET_APIC_ID (x) (((x)<<24))#else #define APIC_ID_MASK (0xF<<24) -#endif -static inline unsigned get_apic_id (unsigned long x) -{ +{unsigned int ver =GET_APIC_VERSION (apic_read (APIC_LVR ));if (APIC_XAPIC (ver))return (((x)>>24 )&0xFF );
@@ -20,5 +19,6 @@ static inline unsigned get_apic_id(unsigned long x) }#define GET_APIC_ID (x) get_apic_id(x) +#endif #endif
Quoted 1 line · Yinghai Lu
attached patch fix that.
thanks Yinghai, applied.
Ingo
Quoted 5 lines · Ingo Molnar
Quoted 1 line · Yinghai Lu
attached patch fix that.
thanks Yinghai, applied.
Thanks for seeking and patching this, Yinghai. The granularity proved quite useful once more ;-)