[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: Reindent smpboot.c and clean up a little.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1274111904 -3600 # Node ID 89a2f9ad02f23c24a06274a1217991181f19930b # Parent c7dde06ba1c35176e69e65dc3c7e6067e713bc47 x86: Reindent smpboot.c and clean up a little. No semantic changes. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/cpu/common.c | 7 xen/arch/x86/smpboot.c | 1709 +++++++++++------------- xen/include/asm-x86/mach-default/mach_wakecpu.h | 8 xen/include/asm-x86/smp.h | 2 4 files changed, 837 insertions(+), 889 deletions(-) diff -r c7dde06ba1c3 -r 89a2f9ad02f2 xen/arch/x86/cpu/common.c --- a/xen/arch/x86/cpu/common.c Mon May 17 16:28:56 2010 +0100 +++ b/xen/arch/x86/cpu/common.c Mon May 17 16:58:24 2010 +0100 @@ -550,7 +550,7 @@ void __cpuinit print_cpu_info(unsigned i printk("\n"); } -cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; +static cpumask_t cpu_initialized; /* This is hacky. :) * We're emulating future behavior. @@ -629,8 +629,7 @@ void __cpuinit cpu_init(void) #undef CD } -void __cpuinit cpu_uninit(void) -{ - int cpu = raw_smp_processor_id(); +void cpu_uninit(unsigned int cpu) +{ cpu_clear(cpu, cpu_initialized); } diff -r c7dde06ba1c3 -r 89a2f9ad02f2 xen/arch/x86/smpboot.c --- a/xen/arch/x86/smpboot.c Mon May 17 16:28:56 2010 +0100 +++ b/xen/arch/x86/smpboot.c Mon May 17 16:58:24 2010 +0100 @@ -1,37 +1,24 @@ /* - * x86 SMP booting functions + * x86 SMP booting functions * - * (c) 1995 Alan Cox, Building #3 <alan@xxxxxxxxxx> - * (c) 1998, 1999, 2000 Ingo Molnar <mingo@xxxxxxxxxx> - * - * Much of the core SMP work is based on previous work by Thomas Radke, to - * whom a great many thanks are extended. - * - * Thanks to Intel for making available several different Pentium, - * Pentium Pro and Pentium-II/Xeon MP machines. - * Original development of Linux SMP code supported by Caldera. - * - * This code is released under the GNU General Public License version 2 or - * later. - * - * Fixes - * Felix Koop : NR_CPUS used properly - * Jose Renau : Handle single CPU case. - * Alan Cox : By repeated request 8) - Total BogoMIPS report. - * Greg Wright : Fix for kernel stacks panic. - * Erich Boleyn : MP v1.4 and additional changes. - * Matthias Sattler : Changes for 2.1 kernel map. - * Michel Lespinasse : Changes for 2.1 kernel map. - * Michael Chastain : Change trampoline.S to gnu as. - * Alan Cox : Dumb bug: 'B' step PPro's are fine - * Ingo Molnar : Added APIC timers, based on code - * from Jose Renau - * Ingo Molnar : various cleanups and rewrites - * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug. - * Maciej W. Rozycki : Bits for genuine 82489DX APICs - * Martin J. Bligh : Added support for multi-quad systems - * Dave Jones : Report invalid combinations of Athlon CPUs. -* Rusty Russell : Hacked into shape for new "hotplug" boot process. */ + * This inherits a great deal from Linux's SMP boot code: + * (c) 1995 Alan Cox, Building #3 <alan@xxxxxxxxxx> + * (c) 1998, 1999, 2000 Ingo Molnar <mingo@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #include <xen/config.h> #include <xen/init.h> @@ -85,8 +72,7 @@ static cpumask_t smp_commenced_mask; struct cpuinfo_x86 cpu_data[NR_CPUS]; -u32 x86_cpu_to_apicid[NR_CPUS] __read_mostly = - { [0 ... NR_CPUS-1] = -1U }; +u32 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = -1U }; static void map_cpu_to_logical_apicid(void); @@ -96,947 +82,918 @@ void *stack_base[NR_CPUS]; static void smp_store_cpu_info(int id) { - struct cpuinfo_x86 *c = cpu_data + id; - - *c = boot_cpu_data; - if (id!=0) - identify_cpu(c); - /* - * 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)) { - - /* 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, it's not a certified SMP capable AMD system. */ - add_taint(TAINT_UNSAFE_SMP); - } - -valid_k7: - ; + struct cpuinfo_x86 *c = cpu_data + id; + + *c = boot_cpu_data; + if ( id != 0 ) + identify_cpu(c); + + /* Mask B, Pentium, but not Pentium MMX -- remember it, as it has bugs. */ + if ( (c->x86_vendor == X86_VENDOR_INTEL) && + (c->x86 == 5) && + ((c->x86_mask >= 1) && (c->x86_mask <= 4)) && + (c->x86_model <= 3) ) + 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) ) + { + /* 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, it's not a certified SMP capable AMD system. */ + add_taint(TAINT_UNSAFE_SMP); + } + + valid_k7: + ; } static atomic_t init_deasserted; void smp_callin(void) { - int cpuid, phys_id, i; - - /* - * 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); - - if ( x2apic_enabled ) - enable_x2apic(); - - /* - * (This works even if the APIC is not enabled.) - */ - phys_id = get_apic_id(); - cpuid = smp_processor_id(); - if (cpu_isset(cpuid, cpu_callin_map)) { - printk("huh, phys CPU#%d, CPU#%d already present??\n", - phys_id, cpuid); - BUG(); - } - 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 - */ - for (i = 0; i < 200; i++) { - /* - * Has the boot CPU finished it's STARTUP sequence? - */ - if (cpu_isset(cpuid, cpu_callout_map)) - break; - cpu_relax(); - mdelay(10); - } - - if (!cpu_isset(cpuid, cpu_callout_map)) { - printk("BUG: CPU%d started up but did not get a callout!\n", - cpuid); - BUG(); - } - - /* - * 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(); - map_cpu_to_logical_apicid(); - - /* - * Save our processor parameters - */ - smp_store_cpu_info(cpuid); - - /* - * Allow the master to continue. - */ - cpu_set(cpuid, cpu_callin_map); + int cpuid, phys_id, i; + + /* + * 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); + + if ( x2apic_enabled ) + enable_x2apic(); + + /* + * (This works even if the APIC is not enabled.) + */ + phys_id = get_apic_id(); + cpuid = smp_processor_id(); + if ( cpu_isset(cpuid, cpu_callin_map) ) + { + printk("huh, phys CPU#%d, CPU#%d already present??\n", + phys_id, cpuid); + BUG(); + } + 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. + */ + + /* Wait 2s total for startup. */ + for ( i = 0; (i < 200) && !cpu_isset(cpuid, cpu_callout_map); i++ ) + { + cpu_relax(); + mdelay(10); + } + + if ( !cpu_isset(cpuid, cpu_callout_map) ) + { + printk("BUG: CPU%d started up but did not get a callout!\n", + cpuid); + BUG(); + } + + /* + * 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(); + map_cpu_to_logical_apicid(); + + /* Save our processor parameters. */ + smp_store_cpu_info(cpuid); + + /* Allow the master to continue. */ + cpu_set(cpuid, cpu_callin_map); } static int booting_cpu; -/* representing cpus for which sibling maps can be computed */ +/* CPUs for which sibling maps can be computed. */ static cpumask_t cpu_sibling_setup_map; -static inline void -set_cpu_sibling_map(int cpu) -{ - int i; - struct cpuinfo_x86 *c = cpu_data; - - cpu_set(cpu, cpu_sibling_setup_map); - - if (c[cpu].x86_num_siblings > 1) { - for_each_cpu_mask(i, cpu_sibling_setup_map) { - if (phys_proc_id[cpu] == phys_proc_id[i] && - cpu_core_id[cpu] == cpu_core_id[i]) { - cpu_set(i, per_cpu(cpu_sibling_map, cpu)); - cpu_set(cpu, per_cpu(cpu_sibling_map, i)); - cpu_set(i, per_cpu(cpu_core_map, cpu)); - cpu_set(cpu, per_cpu(cpu_core_map, i)); - } - } - } else { - cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); - } - - if (c[cpu].x86_max_cores == 1) { - per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu); - c[cpu].booted_cores = 1; - return; - } - - for_each_cpu_mask(i, cpu_sibling_setup_map) { - if (phys_proc_id[cpu] == phys_proc_id[i]) { - cpu_set(i, per_cpu(cpu_core_map, cpu)); - cpu_set(cpu, per_cpu(cpu_core_map, i)); - /* - * Does this new cpu bringup a new core? - */ - if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) { - /* - * for each core in package, increment - * the booted_cores for this new cpu - */ - if (first_cpu(per_cpu(cpu_sibling_map, i)) == i) - c[cpu].booted_cores++; - /* - * increment the core count for all - * the other cpus in this package - */ - if (i != cpu) - c[i].booted_cores++; - } else if (i != cpu && !c[cpu].booted_cores) - c[cpu].booted_cores = c[i].booted_cores; - } - } +static void set_cpu_sibling_map(int cpu) +{ + int i; + struct cpuinfo_x86 *c = cpu_data; + + cpu_set(cpu, cpu_sibling_setup_map); + + if ( c[cpu].x86_num_siblings > 1 ) + { + for_each_cpu_mask ( i, cpu_sibling_setup_map ) + { + if ( (phys_proc_id[cpu] == phys_proc_id[i]) && + (cpu_core_id[cpu] == cpu_core_id[i]) ) + { + cpu_set(i, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, per_cpu(cpu_sibling_map, i)); + cpu_set(i, per_cpu(cpu_core_map, cpu)); + cpu_set(cpu, per_cpu(cpu_core_map, i)); + } + } + } + else + { + cpu_set(cpu, per_cpu(cpu_sibling_map, cpu)); + } + + if ( c[cpu].x86_max_cores == 1 ) + { + per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu); + c[cpu].booted_cores = 1; + return; + } + + for_each_cpu_mask ( i, cpu_sibling_setup_map ) + { + if ( phys_proc_id[cpu] == phys_proc_id[i] ) + { + cpu_set(i, per_cpu(cpu_core_map, cpu)); + cpu_set(cpu, per_cpu(cpu_core_map, i)); + /* + * Does this new cpu bringup a new core? + */ + if ( cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1 ) + { + /* + * for each core in package, increment + * the booted_cores for this new cpu + */ + if ( first_cpu(per_cpu(cpu_sibling_map, i)) == i ) + c[cpu].booted_cores++; + /* + * increment the core count for all + * the other cpus in this package + */ + if ( i != cpu ) + c[i].booted_cores++; + } + else if ( (i != cpu) && !c[cpu].booted_cores ) + { + c[cpu].booted_cores = c[i].booted_cores; + } + } + } } static void construct_percpu_idt(unsigned int cpu) { - unsigned char idt_load[10]; - - *(unsigned short *)(&idt_load[0]) = (IDT_ENTRIES*sizeof(idt_entry_t))-1; - *(unsigned long *)(&idt_load[2]) = (unsigned long)idt_tables[cpu]; - __asm__ __volatile__ ( "lidt %0" : "=m" (idt_load) ); -} - -/* - * Activate a secondary processor. - */ + unsigned char idt_load[10]; + + *(unsigned short *)(&idt_load[0]) = (IDT_ENTRIES*sizeof(idt_entry_t))-1; + *(unsigned long *)(&idt_load[2]) = (unsigned long)idt_tables[cpu]; + __asm__ __volatile__ ( "lidt %0" : "=m" (idt_load) ); +} + void start_secondary(void *unused) { - /* - * Dont put anything before smp_callin(), SMP - * booting is too fragile that we want to limit the - * things done here to the most necessary things. - */ - unsigned int cpu = booting_cpu; - - set_processor_id(cpu); - set_current(idle_vcpu[cpu]); - this_cpu(curr_vcpu) = idle_vcpu[cpu]; - if ( cpu_has_efer ) - rdmsrl(MSR_EFER, this_cpu(efer)); - asm volatile ( "mov %%cr4,%0" : "=r" (this_cpu(cr4)) ); - - /* - * Just as during early bootstrap, it is convenient here to disable - * spinlock checking while we have IRQs disabled. This allows us to - * acquire IRQ-unsafe locks when it would otherwise be disallowed. - * - * It is safe because the race we are usually trying to avoid involves - * a group of CPUs rendezvousing in an IPI handler, where one cannot - * join because it is spinning with IRQs disabled waiting to acquire a - * lock held by another in the rendezvous group (the lock must be an - * IRQ-unsafe lock since the CPU took the IPI after acquiring it, and - * hence had IRQs enabled). This is a deadlock scenario. - * - * However, no CPU can be involved in rendezvous until it is online, - * hence no such group can be waiting for this CPU until it is - * visible in cpu_online_map. Hence such a deadlock is not possible. - */ - spin_debug_disable(); - - percpu_traps_init(); - - cpu_init(); - - smp_callin(); - while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) - cpu_relax(); - - /* - * At this point, boot CPU has fully initialised the IDT. It is - * now safe to make ourselves a private copy. - */ - construct_percpu_idt(cpu); - - setup_secondary_APIC_clock(); - enable_APIC_timer(); - /* - * low-memory mappings have been cleared, flush them from - * the local TLBs too. - */ - flush_tlb_local(); - - /* This must be done before setting cpu_online_map */ - spin_debug_enable(); - set_cpu_sibling_map(raw_smp_processor_id()); - wmb(); - - /* - * We need to hold vector_lock so there the set of online cpus - * does not change while we are assigning vectors to cpus. Holding - * this lock ensures we don't half assign or remove an irq from a cpu. - */ - lock_vector_lock(); - __setup_vector_irq(smp_processor_id()); - cpu_set(smp_processor_id(), cpu_online_map); - unlock_vector_lock(); - - per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; - - init_percpu_time(); - - /* We can take interrupts now: we're officially "up". */ - local_irq_enable(); - mtrr_ap_init(); - - microcode_resume_cpu(cpu); - - wmb(); - startup_cpu_idle_loop(); + /* + * Dont put anything before smp_callin(), SMP booting is so fragile that we + * want to limit the things done here to the most necessary things. + */ + unsigned int cpu = booting_cpu; + + set_processor_id(cpu); + set_current(idle_vcpu[cpu]); + this_cpu(curr_vcpu) = idle_vcpu[cpu]; + if ( cpu_has_efer ) + rdmsrl(MSR_EFER, this_cpu(efer)); + asm volatile ( "mov %%cr4,%0" : "=r" (this_cpu(cr4)) ); + + /* + * Just as during early bootstrap, it is convenient here to disable + * spinlock checking while we have IRQs disabled. This allows us to + * acquire IRQ-unsafe locks when it would otherwise be disallowed. + * + * It is safe because the race we are usually trying to avoid involves + * a group of CPUs rendezvousing in an IPI handler, where one cannot + * join because it is spinning with IRQs disabled waiting to acquire a + * lock held by another in the rendezvous group (the lock must be an + * IRQ-unsafe lock since the CPU took the IPI after acquiring it, and + * hence had IRQs enabled). This is a deadlock scenario. + * + * However, no CPU can be involved in rendezvous until it is online, + * hence no such group can be waiting for this CPU until it is + * visible in cpu_online_map. Hence such a deadlock is not possible. + */ + spin_debug_disable(); + + percpu_traps_init(); + + cpu_init(); + + smp_callin(); + while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) + cpu_relax(); + + /* + * At this point, boot CPU has fully initialised the IDT. It is + * now safe to make ourselves a private copy. + */ + construct_percpu_idt(cpu); + + setup_secondary_APIC_clock(); + enable_APIC_timer(); + /* + * low-memory mappings have been cleared, flush them from + * the local TLBs too. + */ + flush_tlb_local(); + + /* This must be done before setting cpu_online_map */ + spin_debug_enable(); + set_cpu_sibling_map(raw_smp_processor_id()); + wmb(); + + /* + * We need to hold vector_lock so there the set of online cpus + * does not change while we are assigning vectors to cpus. Holding + * this lock ensures we don't half assign or remove an irq from a cpu. + */ + lock_vector_lock(); + __setup_vector_irq(smp_processor_id()); + cpu_set(smp_processor_id(), cpu_online_map); + unlock_vector_lock(); + + per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; + + init_percpu_time(); + + /* We can take interrupts now: we're officially "up". */ + local_irq_enable(); + mtrr_ap_init(); + + microcode_resume_cpu(cpu); + + wmb(); + startup_cpu_idle_loop(); } extern struct { - void * esp; - unsigned short ss; + void * esp; + unsigned short ss; } stack_start; -u32 cpu_2_logical_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; +u32 cpu_2_logical_apicid[NR_CPUS] __read_mostly = + { [0 ... NR_CPUS-1] = BAD_APICID }; static void map_cpu_to_logical_apicid(void) { - int cpu = smp_processor_id(); - int apicid = logical_smp_processor_id(); - - cpu_2_logical_apicid[cpu] = apicid; + int cpu = smp_processor_id(); + int apicid = logical_smp_processor_id(); + + cpu_2_logical_apicid[cpu] = apicid; } static void unmap_cpu_to_logical_apicid(int cpu) { - cpu_2_logical_apicid[cpu] = BAD_APICID; + cpu_2_logical_apicid[cpu] = BAD_APICID; } #if APIC_DEBUG -static inline void __inquire_remote_apic(int apicid) -{ - int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; - char *names[] = { "ID", "VERSION", "SPIV" }; - int timeout, status; - - printk("Inquiring remote APIC #%d...\n", apicid); - - for (i = 0; i < ARRAY_SIZE(regs); i++) { - printk("... APIC #%d %s: ", apicid, names[i]); - - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - - apic_icr_write(APIC_DM_REMRD | regs[i], apicid); - - 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("%08x\n", status); - break; - default: - printk("failed\n"); - } - } +static void __inquire_remote_apic(int apicid) +{ + int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; + char *names[] = { "ID", "VERSION", "SPIV" }; + int timeout, status; + + printk("Inquiring remote APIC #%d...\n", apicid); + + for ( i = 0; i < ARRAY_SIZE(regs); i++ ) + { + printk("... APIC #%d %s: ", apicid, names[i]); + + /* + * Wait for idle. + */ + apic_wait_icr_idle(); + + apic_icr_write(APIC_DM_REMRD | regs[i], apicid); + + 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("%08x\n", status); + break; + default: + printk("failed\n"); + } + } } #endif static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) { - unsigned long send_status = 0, accept_status = 0; - int maxlvt, timeout, 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 via IPI - */ - apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, - phys_apicid); - - Dprintk("Waiting for send to finish...\n"); - timeout = 0; - do { - Dprintk("+"); - udelay(100); - if ( !x2apic_enabled ) - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - else - send_status = 0; /* We go out of the loop dirctly. */ - } while (send_status && (timeout++ < 1000)); - - mdelay(10); - - Dprintk("Deasserting INIT.\n"); - - apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); - - Dprintk("Waiting for send to finish...\n"); - timeout = 0; - do { - Dprintk("+"); - udelay(100); - if ( !x2apic_enabled ) - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - else - send_status = 0; /* We go out of the loop dirctly. */ - } while (send_status && (timeout++ < 1000)); - - 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; - - /* - * Run STARTUP IPI loop. - */ - Dprintk("#startup loops: %d.\n", num_starts); - - maxlvt = 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 - * Boot on the stack - */ - apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12), phys_apicid); - - /* - * Give the other CPU some time to accept the IPI. - */ - udelay(300); - - Dprintk("Startup point 1.\n"); - - Dprintk("Waiting for send to finish...\n"); - timeout = 0; - do { - Dprintk("+"); - udelay(100); - send_status = (x2apic_enabled ? 0 : - apic_read(APIC_ICR) & APIC_ICR_BUSY); - } while (send_status && (timeout++ < 1000)); - - /* - * 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("APIC never delivered???\n"); - if (accept_status) - printk("APIC delivery error (%lx).\n", accept_status); - - return (send_status | accept_status); -} - -extern cpumask_t cpu_initialized; -/* - * Caller should hold cpu_add_remove_lock if not called when booting - */ + unsigned long send_status = 0, accept_status = 0; + int maxlvt, timeout, num_starts, i; + + /* + * 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 via IPI + */ + apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, + phys_apicid); + + Dprintk("Waiting for send to finish...\n"); + timeout = 0; + do { + Dprintk("+"); + udelay(100); + if ( !x2apic_enabled ) + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; + } while ( send_status && (timeout++ < 1000) ); + + mdelay(10); + + Dprintk("Deasserting INIT.\n"); + + apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); + + Dprintk("Waiting for send to finish...\n"); + timeout = 0; + do { + Dprintk("+"); + udelay(100); + if ( !x2apic_enabled ) + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; + } while ( send_status && (timeout++ < 1000) ); + + 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. + */ + num_starts = APIC_INTEGRATED(apic_version[phys_apicid]) ? 2 : 0; + + /* Run STARTUP IPI loop. */ + Dprintk("#startup loops: %d.\n", num_starts); + + maxlvt = get_maxlvt(); + + for ( i = 0; i < num_starts; i++ ) + { + 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 + * Boot on the stack + */ + apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12), phys_apicid); + + /* Give the other CPU some time to accept the IPI. */ + udelay(300); + + Dprintk("Startup point 1.\n"); + + Dprintk("Waiting for send to finish...\n"); + timeout = 0; + do { + Dprintk("+"); + udelay(100); + if ( !x2apic_enabled ) + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; + } while ( send_status && (timeout++ < 1000) ); + + /* 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("APIC never delivered???\n"); + if ( accept_status ) + printk("APIC delivery error (%lx).\n", accept_status); + + return (send_status | accept_status); +} + 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; + cpumask_t tmp_map; + int cpu; + cpus_complement(tmp_map, cpu_present_map); + cpu = first_cpu(tmp_map); + return (cpu < NR_CPUS) ? cpu : -ENODEV; } static void *prepare_idle_stack(unsigned int cpu) { - if (!stack_base[cpu]) - stack_base[cpu] = alloc_xenheap_pages(STACK_ORDER, 0); - - return stack_base[cpu]; + if ( !stack_base[cpu] ) + stack_base[cpu] = alloc_xenheap_pages(STACK_ORDER, 0); + return stack_base[cpu]; } static int 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; - unsigned int order; - int timeout; - unsigned long start_eip; - unsigned short nmi_high = 0, nmi_low = 0; - struct vcpu *v; - struct desc_struct *gdt; +{ + unsigned long boot_error; + unsigned int order; + int timeout; + unsigned long start_eip; + struct vcpu *v; + struct desc_struct *gdt; #ifdef __x86_64__ - struct page_info *page; + struct page_info *page; #endif - /* - * 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(); - - booting_cpu = cpu; - - v = alloc_idle_vcpu(cpu); - BUG_ON(v == NULL); - - /* start_eip had better be page-aligned! */ - start_eip = setup_trampoline(); - - /* So we see what's up */ - if (opt_cpu_info) - printk("Booting processor %d/%d eip %lx\n", - cpu, apicid, start_eip); - - stack_start.esp = prepare_idle_stack(cpu); - - /* Debug build: detect stack overflow by setting up a guard page. */ - memguard_guard_stack(stack_start.esp); - - gdt = per_cpu(gdt_table, cpu); - if (gdt == boot_cpu_gdt_table) { - order = get_order_from_pages(NR_RESERVED_GDT_PAGES); + /* + * 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(); + + booting_cpu = cpu; + + v = alloc_idle_vcpu(cpu); + BUG_ON(v == NULL); + + /* start_eip had better be page-aligned! */ + start_eip = setup_trampoline(); + + /* So we see what's up */ + if (opt_cpu_info) + printk("Booting processor %d/%d eip %lx\n", + cpu, apicid, start_eip); + + stack_start.esp = prepare_idle_stack(cpu); + + /* Debug build: detect stack overflow by setting up a guard page. */ + memguard_guard_stack(stack_start.esp); + + gdt = per_cpu(gdt_table, cpu); + if ( gdt == boot_cpu_gdt_table ) + { + order = get_order_from_pages(NR_RESERVED_GDT_PAGES); #ifdef __x86_64__ - page = alloc_domheap_pages(NULL, order, - MEMF_node(cpu_to_node(cpu))); - per_cpu(compat_gdt_table, cpu) = gdt = page_to_virt(page); - memcpy(gdt, boot_cpu_compat_gdt_table, - NR_RESERVED_GDT_PAGES * PAGE_SIZE); - gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu; - page = alloc_domheap_pages(NULL, order, - MEMF_node(cpu_to_node(cpu))); - per_cpu(gdt_table, cpu) = gdt = page_to_virt(page); + page = alloc_domheap_pages(NULL, order, + MEMF_node(cpu_to_node(cpu))); + per_cpu(compat_gdt_table, cpu) = gdt = page_to_virt(page); + memcpy(gdt, boot_cpu_compat_gdt_table, + NR_RESERVED_GDT_PAGES * PAGE_SIZE); + gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu; + page = alloc_domheap_pages(NULL, order, + MEMF_node(cpu_to_node(cpu))); + per_cpu(gdt_table, cpu) = gdt = page_to_virt(page); #else - per_cpu(gdt_table, cpu) = gdt = alloc_xenheap_pages(order, 0); + per_cpu(gdt_table, cpu) = gdt = alloc_xenheap_pages(order, 0); #endif - memcpy(gdt, boot_cpu_gdt_table, - NR_RESERVED_GDT_PAGES * PAGE_SIZE); - BUILD_BUG_ON(NR_CPUS > 0x10000); - gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu; - } + memcpy(gdt, boot_cpu_gdt_table, + NR_RESERVED_GDT_PAGES * PAGE_SIZE); + BUILD_BUG_ON(NR_CPUS > 0x10000); + gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu; + } #ifdef __i386__ - if (!per_cpu(doublefault_tss, cpu)) { - per_cpu(doublefault_tss, cpu) = alloc_xenheap_page(); - memset(per_cpu(doublefault_tss, cpu), 0, PAGE_SIZE); - } + if ( !per_cpu(doublefault_tss, cpu) ) + { + per_cpu(doublefault_tss, cpu) = alloc_xenheap_page(); + memset(per_cpu(doublefault_tss, cpu), 0, PAGE_SIZE); + } #else - if (!per_cpu(compat_arg_xlat, cpu)) - setup_compat_arg_xlat(cpu, cpu_to_node[cpu]); + if ( !per_cpu(compat_arg_xlat, cpu) ) + setup_compat_arg_xlat(cpu, cpu_to_node[cpu]); #endif - if (!idt_tables[cpu]) { - idt_tables[cpu] = xmalloc_array(idt_entry_t, IDT_ENTRIES); - memcpy(idt_tables[cpu], idt_table, - IDT_ENTRIES*sizeof(idt_entry_t)); - } - - /* - * 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_eip); - - /* - * Starting actual IPI sequence... - */ - boot_error = wakeup_secondary_cpu(apicid, start_eip); - - 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"); - print_cpu_info(cpu); - Dprintk("CPU has booted.\n"); - } else { - boot_error = 1; - mb(); - if (bootsym(trampoline_cpu_started) == 0xA5) - /* trampoline started but...? */ - printk("Stuck ??\n"); - else - /* trampoline code not run */ - printk("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); - cpu_clear(cpu, cpu_callout_map); /* was set here */ - cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ - - /* Mark the CPU as non-present */ - x86_cpu_to_apicid[cpu] = BAD_APICID; - cpu_clear(cpu, cpu_present_map); - } - - /* mark "stuck" area as not stuck */ - bootsym(trampoline_cpu_started) = 0; - mb(); - - smpboot_restore_warm_reset_vector(); - - return boot_error ? -EIO : 0; + if ( !idt_tables[cpu] ) + { + idt_tables[cpu] = xmalloc_array(idt_entry_t, IDT_ENTRIES); + memcpy(idt_tables[cpu], idt_table, + IDT_ENTRIES*sizeof(idt_entry_t)); + } + + /* This grunge runs the startup process for the targeted processor. */ + + atomic_set(&init_deasserted, 0); + + Dprintk("Setting warm reset code and vector.\n"); + + smpboot_setup_warm_reset_vector(start_eip); + + /* Starting actual IPI sequence... */ + boot_error = wakeup_secondary_cpu(apicid, start_eip); + + if ( !boot_error ) + { + /* Allow AP 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"); + print_cpu_info(cpu); + Dprintk("CPU has booted.\n"); + } + else + { + boot_error = 1; + mb(); + if ( bootsym(trampoline_cpu_started) == 0xA5 ) + /* trampoline started but...? */ + printk("Stuck ??\n"); + else + /* trampoline code not run */ + printk("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); + cpu_clear(cpu, cpu_callout_map); /* was set here */ + cpu_uninit(cpu); /* undoes cpu_init() */ + + /* Mark the CPU as non-present */ + x86_cpu_to_apicid[cpu] = BAD_APICID; + cpu_clear(cpu, cpu_present_map); + } + + /* mark "stuck" area as not stuck */ + bootsym(trampoline_cpu_started) = 0; + mb(); + + smpboot_restore_warm_reset_vector(); + + return boot_error ? -EIO : 0; } void cpu_exit_clear(void) { - int cpu = raw_smp_processor_id(); - - cpu_uninit(); - - cpu_clear(cpu, cpu_callout_map); - cpu_clear(cpu, cpu_callin_map); - - cpu_clear(cpu, smp_commenced_mask); - unmap_cpu_to_logical_apicid(cpu); + int cpu = raw_smp_processor_id(); + + cpu_uninit(cpu); + + cpu_clear(cpu, cpu_callout_map); + cpu_clear(cpu, cpu_callin_map); + + cpu_clear(cpu, smp_commenced_mask); + unmap_cpu_to_logical_apicid(cpu); } void __init smp_prepare_cpus(unsigned int max_cpus) { - mtrr_aps_sync_begin(); - - /* - * Setup boot CPU information - */ - smp_store_cpu_info(0); /* Final full version of the data */ - print_cpu_info(0); - - boot_cpu_physical_apicid = get_apic_id(); - x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; - - stack_base[0] = stack_start.esp; - - set_cpu_sibling_map(0); - - /* - * 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"); - init_uniprocessor: - phys_cpu_present_map = physid_mask_of_physid(0); - 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; - } - - /* - * Should not be necessary because the MP table should list the boot - * CPU too, but we do it for the sake of robustness anyway. - * Makes no sense to do this check in clustered apic mode, so skip it - */ - if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { - printk("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); - goto init_uniprocessor; - } - - verify_local_APIC(); - - connect_bsp_APIC(); - setup_local_APIC(); - map_cpu_to_logical_apicid(); - - /* - * construct cpu_sibling_map, so that we can tell sibling CPUs - * efficiently. - */ - cpu_set(0, per_cpu(cpu_sibling_map, 0)); - cpu_set(0, per_cpu(cpu_core_map, 0)); - - smpboot_setup_io_apic(); - - setup_boot_APIC_clock(); + mtrr_aps_sync_begin(); + + /* Setup boot CPU information */ + smp_store_cpu_info(0); /* Final full version of the data */ + print_cpu_info(0); + + boot_cpu_physical_apicid = get_apic_id(); + x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; + + stack_base[0] = stack_start.esp; + + set_cpu_sibling_map(0); + + /* + * 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"); + init_uniprocessor: + phys_cpu_present_map = physid_mask_of_physid(0); + 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; + } + + /* + * Should not be necessary because the MP table should list the boot + * CPU too, but we do it for the sake of robustness anyway. + * Makes no sense to do this check in clustered apic mode, so skip it + */ + if ( !check_phys_apicid_present(boot_cpu_physical_apicid) ) + { + printk("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); + goto init_uniprocessor; + } + + verify_local_APIC(); + + connect_bsp_APIC(); + setup_local_APIC(); + map_cpu_to_logical_apicid(); + + /* + * construct cpu_sibling_map, so that we can tell sibling CPUs + * efficiently. + */ + cpu_set(0, per_cpu(cpu_sibling_map, 0)); + cpu_set(0, per_cpu(cpu_core_map, 0)); + + smpboot_setup_io_apic(); + + setup_boot_APIC_clock(); } void __init smp_prepare_boot_cpu(void) { - cpu_set(smp_processor_id(), smp_commenced_mask); - cpu_set(smp_processor_id(), cpu_callin_map); - cpu_set(smp_processor_id(), cpu_online_map); - cpu_set(smp_processor_id(), cpu_callout_map); - cpu_set(smp_processor_id(), cpu_present_map); - cpu_set(smp_processor_id(), cpu_possible_map); - per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; + cpu_set(smp_processor_id(), smp_commenced_mask); + cpu_set(smp_processor_id(), cpu_callin_map); + cpu_set(smp_processor_id(), cpu_online_map); + cpu_set(smp_processor_id(), cpu_callout_map); + cpu_set(smp_processor_id(), cpu_present_map); + cpu_set(smp_processor_id(), cpu_possible_map); + per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; } static void remove_siblinginfo(int cpu) { - int sibling; - struct cpuinfo_x86 *c = cpu_data; - - for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) { - cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); - /* - * last thread sibling in this cpu core going down - */ - if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) - c[sibling].booted_cores--; - } - - for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) - cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); - cpus_clear(per_cpu(cpu_sibling_map, cpu)); - cpus_clear(per_cpu(cpu_core_map, cpu)); - phys_proc_id[cpu] = BAD_APICID; - cpu_core_id[cpu] = BAD_APICID; - cpu_clear(cpu, cpu_sibling_setup_map); + int sibling; + struct cpuinfo_x86 *c = cpu_data; + + for_each_cpu_mask ( sibling, per_cpu(cpu_core_map, cpu) ) + { + cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); + /* Last thread sibling in this cpu core going down. */ + if ( cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1 ) + c[sibling].booted_cores--; + } + + for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu)) + cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); + cpus_clear(per_cpu(cpu_sibling_map, cpu)); + cpus_clear(per_cpu(cpu_core_map, cpu)); + phys_proc_id[cpu] = BAD_APICID; + cpu_core_id[cpu] = BAD_APICID; + cpu_clear(cpu, cpu_sibling_setup_map); } void __cpu_disable(void) { - extern void fixup_irqs(void); - int cpu = smp_processor_id(); - - local_irq_disable(); - clear_local_APIC(); - /* Allow any queued timer interrupts to get serviced */ - local_irq_enable(); - mdelay(1); - local_irq_disable(); - - time_suspend(); - - remove_siblinginfo(cpu); - - /* It's now safe to remove this processor from the online map */ - cpu_clear(cpu, cpupool0->cpu_valid); - cpu_clear(cpu, cpu_online_map); - fixup_irqs(); - - cpu_disable_scheduler(cpu); + extern void fixup_irqs(void); + int cpu = smp_processor_id(); + + local_irq_disable(); + clear_local_APIC(); + /* Allow any queued timer interrupts to get serviced */ + local_irq_enable(); + mdelay(1); + local_irq_disable(); + + time_suspend(); + + remove_siblinginfo(cpu); + + /* It's now safe to remove this processor from the online map */ + cpu_clear(cpu, cpupool0->cpu_valid); + cpu_clear(cpu, cpu_online_map); + fixup_irqs(); + + cpu_disable_scheduler(cpu); } void __cpu_die(unsigned int cpu) { - /* We don't do anything here: idle task is faking death itself. */ - unsigned int i = 0; - - for (;;) { - /* They ack this in play_dead by setting CPU_DEAD */ - if (per_cpu(cpu_state, cpu) == CPU_DEAD) - break; - mdelay(100); - cpu_relax(); - process_pending_softirqs(); - if ((++i % 10) == 0) - printk(KERN_ERR "CPU %u still not dead...\n", cpu); - } + /* We don't do anything here: idle task is faking death itself. */ + unsigned int i = 0; + + while ( per_cpu(cpu_state, cpu) != CPU_DEAD ) + { + mdelay(100); + cpu_relax(); + process_pending_softirqs(); + if ( (++i % 10) == 0 ) + printk(KERN_ERR "CPU %u still not dead...\n", cpu); + } } int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm) { - int node, cpu = -1; - - dprintk(XENLOG_DEBUG, "cpu_add apic_id %x acpi_id %x pxm %x\n", - apic_id, acpi_id, pxm); - - if ( acpi_id > MAX_MADT_ENTRIES || apic_id > MAX_APICS || pxm > 256 ) - return -EINVAL; - - if ( !cpu_hotplug_begin() ) - return -EBUSY; - - /* Detect if the cpu has been added before */ - if ( x86_acpiid_to_apicid[acpi_id] != 0xff ) - { - cpu = (x86_acpiid_to_apicid[acpi_id] != apic_id) - ? -EINVAL : -EEXIST; - goto out; - } - - if ( physid_isset(apic_id, phys_cpu_present_map) ) - { - cpu = -EEXIST; - goto out; - } - - if ( (cpu = mp_register_lapic(apic_id, 1)) < 0 ) - goto out; - - x86_acpiid_to_apicid[acpi_id] = apic_id; - - if ( !srat_disabled() ) - { - if ( (node = setup_node(pxm)) < 0 ) - { - dprintk(XENLOG_WARNING, - "Setup node failed for pxm %x\n", pxm); - x86_acpiid_to_apicid[acpi_id] = 0xff; - mp_unregister_lapic(apic_id, cpu); - cpu = node; - goto out; - } - apicid_to_node[apic_id] = node; - } - - srat_detect_node(cpu); - numa_add_cpu(cpu); - dprintk(XENLOG_INFO, "Add CPU %x with index %x\n", apic_id, cpu); + int node, cpu = -1; + + dprintk(XENLOG_DEBUG, "cpu_add apic_id %x acpi_id %x pxm %x\n", + apic_id, acpi_id, pxm); + + if ( acpi_id > MAX_MADT_ENTRIES || apic_id > MAX_APICS || pxm > 256 ) + return -EINVAL; + + if ( !cpu_hotplug_begin() ) + return -EBUSY; + + /* Detect if the cpu has been added before */ + if ( x86_acpiid_to_apicid[acpi_id] != 0xff ) + { + cpu = (x86_acpiid_to_apicid[acpi_id] != apic_id) + ? -EINVAL : -EEXIST; + goto out; + } + + if ( physid_isset(apic_id, phys_cpu_present_map) ) + { + cpu = -EEXIST; + goto out; + } + + if ( (cpu = mp_register_lapic(apic_id, 1)) < 0 ) + goto out; + + x86_acpiid_to_apicid[acpi_id] = apic_id; + + if ( !srat_disabled() ) + { + if ( (node = setup_node(pxm)) < 0 ) + { + dprintk(XENLOG_WARNING, + "Setup node failed for pxm %x\n", pxm); + x86_acpiid_to_apicid[acpi_id] = 0xff; + mp_unregister_lapic(apic_id, cpu); + cpu = node; + goto out; + } + apicid_to_node[apic_id] = node; + } + + srat_detect_node(cpu); + numa_add_cpu(cpu); + dprintk(XENLOG_INFO, "Add CPU %x with index %x\n", apic_id, cpu); out: - cpu_hotplug_done(); - return cpu; + cpu_hotplug_done(); + return cpu; } int __cpu_up(unsigned int cpu) { - int apicid, ret; - - BUG_ON(cpu_isset(cpu, cpu_callin_map)); - - if ((apicid = x86_cpu_to_apicid[cpu]) == BAD_APICID) - return -ENODEV; - - if ((ret = do_boot_cpu(apicid, cpu)) != 0) - return ret; - - cpu_set(cpu, smp_commenced_mask); - while (!cpu_isset(cpu, cpu_online_map)) { - cpu_relax(); - process_pending_softirqs(); - } - - return 0; + int apicid, ret; + + BUG_ON(cpu_isset(cpu, cpu_callin_map)); + + if ( (apicid = x86_cpu_to_apicid[cpu]) == BAD_APICID ) + return -ENODEV; + + if ( (ret = do_boot_cpu(apicid, cpu)) != 0 ) + return ret; + + cpu_set(cpu, smp_commenced_mask); + while ( !cpu_isset(cpu, cpu_online_map) ) + { + cpu_relax(); + process_pending_softirqs(); + } + + return 0; } void __init smp_cpus_done(unsigned int max_cpus) { - 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 (num_online_cpus() > 1) - printk(KERN_INFO "WARNING: This combination of AMD " - "processors is not suitable for SMP.\n"); - else - tainted &= ~TAINT_UNSAFE_SMP; - } - - if (nmi_watchdog == NMI_LOCAL_APIC) - check_nmi_watchdog(); - - setup_ioapic_dest(); - - mtrr_save_state(); - mtrr_aps_sync_end(); + 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 ( num_online_cpus() > 1 ) + printk(KERN_INFO "WARNING: This combination of AMD " + "processors is not suitable for SMP.\n"); + else + tainted &= ~TAINT_UNSAFE_SMP; + } + + if ( nmi_watchdog == NMI_LOCAL_APIC ) + check_nmi_watchdog(); + + setup_ioapic_dest(); + + mtrr_save_state(); + mtrr_aps_sync_end(); } void __init smp_intr_init(void) { - int irq, seridx, cpu = smp_processor_id(); - - /* - * IRQ0 must be given a fixed assignment and initialized, - * because it's used before the IO-APIC is set up. - */ - irq_vector[0] = FIRST_HIPRIORITY_VECTOR; - - /* - * Also ensure serial interrupts are high priority. We do not - * want them to be blocked by unacknowledged guest-bound interrupts. - */ - for (seridx = 0; seridx < 2; seridx++) { - if ((irq = serial_irq(seridx)) < 0) - continue; - irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1; - per_cpu(vector_irq, cpu)[FIRST_HIPRIORITY_VECTOR + seridx + 1] = irq; - irq_cfg[irq].vector = FIRST_HIPRIORITY_VECTOR + seridx + 1; - irq_cfg[irq].domain = (cpumask_t)CPU_MASK_ALL; - } - - /* IPI for cleanuping vectors after irq move */ - set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); - - /* IPI for event checking. */ - set_intr_gate(EVENT_CHECK_VECTOR, event_check_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); -} + int irq, seridx, cpu = smp_processor_id(); + + /* + * IRQ0 must be given a fixed assignment and initialized, + * because it's used before the IO-APIC is set up. + */ + irq_vector[0] = FIRST_HIPRIORITY_VECTOR; + + /* + * Also ensure serial interrupts are high priority. We do not + * want them to be blocked by unacknowledged guest-bound interrupts. + */ + for ( seridx = 0; seridx < 2; seridx++ ) + { + if ( (irq = serial_irq(seridx)) < 0 ) + continue; + irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1; + per_cpu(vector_irq, cpu)[FIRST_HIPRIORITY_VECTOR + seridx + 1] = irq; + irq_cfg[irq].vector = FIRST_HIPRIORITY_VECTOR + seridx + 1; + irq_cfg[irq].domain = (cpumask_t)CPU_MASK_ALL; + } + + /* IPI for cleanuping vectors after irq move */ + set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); + + /* IPI for event checking. */ + set_intr_gate(EVENT_CHECK_VECTOR, event_check_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); +} diff -r c7dde06ba1c3 -r 89a2f9ad02f2 xen/include/asm-x86/mach-default/mach_wakecpu.h --- a/xen/include/asm-x86/mach-default/mach_wakecpu.h Mon May 17 16:28:56 2010 +0100 +++ b/xen/include/asm-x86/mach-default/mach_wakecpu.h Mon May 17 16:58:24 2010 +0100 @@ -24,14 +24,6 @@ static inline void smp_callin_clear_loca { } -static inline void store_NMI_vector(unsigned short *high, unsigned short *low) -{ -} - -static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) -{ -} - #if APIC_DEBUG #define inquire_remote_apic(apicid) __inquire_remote_apic(apicid) #else diff -r c7dde06ba1c3 -r 89a2f9ad02f2 xen/include/asm-x86/smp.h --- a/xen/include/asm-x86/smp.h Mon May 17 16:28:56 2010 +0100 +++ b/xen/include/asm-x86/smp.h Mon May 17 16:58:24 2010 +0100 @@ -57,7 +57,7 @@ DECLARE_PER_CPU(int, cpu_state); #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu)) extern void cpu_exit_clear(void); -extern void cpu_uninit(void); +extern void cpu_uninit(unsigned int cpu); int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm); /* _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |