Hotplug CPU Boot Change 2/2
.... And this fixes up x86.
Name: Hot-plug CPU Boot Rewrite for i386
Author: Rusty Russell
Status: Tested 2.5.25, dual SMP
Depends: Hotcpu/hotcpu-boot.patch.gz
D: This modifies the i386 boot sequence to "plug in" CPUs one at a
D: time. This is the minimal change to make it work (the CPUs are
D: brought up as normal during the "smp_prepare_cpus()" probe phase).
arch/i386/kernel/apic.c +11 -7
@@ -798,9 +798,9 @@apic_write_around (APIC_TMICT , clocks/APIC_DIVISOR ); } -void setup_APIC_timer (void * data) +static void setup_APIC_timer (unsigned int clocks) { -unsigned int clocks = (unsigned int ) data, slice, t0, t1; +unsigned int slice, t0, t1;unsigned long flags;int delta;
@@ -926,7 +926,7 @@int dont_use_local_apic_timer__initdata =0 ; -void __init setup_APIC_clocks (void ) +void __init setup_boot_APIC_clock (void ) {/* Disabled by DMI scan or kernel option? */ if (dont_use_local_apic_timer)
@@ -941,12 +941,16 @@/* * Now set up the timer for real. */ -setup_APIC_timer ((void *)calibration_result); +setup_APIC_timer (calibration_result);__sti (); +} -/* and update all other cpus */ -smp_call_function (setup_APIC_timer, (void *)calibration_result,1 ,1 ); +void __init setup_secondary_APIC_clock (void ) +{ +__cli ();/* FIXME: Do we need this? --RR */ +setup_APIC_timer (calibration_result); +__sti (); }void __init disable_APIC_timer (void )
@@ -1178,7 +1182,7 @@if (!skip_ioapic_setup && nr_ioapics)setup_IO_APIC ();#endif -setup_APIC_clocks (); +setup_boot_APIC_clock ();return 0 ; }
arch/i386/kernel/apm.c +5 -9
@@ -1587,7 +1587,7 @@ p = buf; -if ((num_online_cpus () ==1 ) && +if ((num_possible_cpus () ==1 ) && !(error =apm_get_power_status (&bx, &cx, &dx))) { ac_line_status = (bx >>8 ) &0xff ; battery_status = bx &0xff ;
@@ -1718,7 +1718,7 @@ } } -if (debug && (num_online_cpus () ==1 )) { +if (debug && (num_possible_cpus () ==1 )) { error =apm_get_power_status (&bx, &cx, &dx);if (error)printk (KERN_INFO "apm: power status not available\n" );
@@ -1762,7 +1762,7 @@ pm_power_off = apm_power_off;register_sysrq_key ('o' , &sysrq_poweroff_op); -if (num_online_cpus () ==1 ) { +if (num_possible_cpus () ==1 ) {#if defined(CONFIG_APM_DISPLAY_BLANK ) && defined(CONFIG_VT ) console_blank_hook = apm_console_blank;#endif
@@ -1905,9 +1905,7 @@printk (KERN_NOTICE "apm: disabled on user request.\n" );return -ENODEV ; } -/* FIXME: When boot code changes, this will need to be -deactivated when/if a CPU comes up --RR */ -if ((num_online_cpus () >1 ) && !power_off) { +if ((num_possible_cpus () >1 ) && !power_off) {printk (KERN_NOTICE "apm: disabled - APM is not SMP safe.\n" );return -ENODEV ; }
@@ -1961,9 +1959,7 @@kernel_thread (apm,NULL ,CLONE_FS |CLONE_FILES |CLONE_SIGHAND |SIGCHLD ); -/* FIXME: When boot code changes, this will need to be -deactivated when/if a CPU comes up --RR */ -if (num_online_cpus () >1 ) { +if (num_possible_cpus () >1 ) {printk (KERN_NOTICE "apm: disabled - APM is not SMP safe (power off active).\n" );return 0 ;
arch/i386/kernel/mtrr.c +3 -3
@@ -1055,7 +1055,7 @@ wait_barrier_cache_disable = TRUE; wait_barrier_execute = TRUE; wait_barrier_cache_enable = TRUE; -atomic_set (&undone_count,num_online_cpus () -1 ); +atomic_set (&undone_count,num_booting_cpus () -1 );/* Start the ball rolling on other CPUs */ if (smp_call_function (ipi_handler, &data,1 ,0 ) !=0 )panic ("mtrr: timed out waiting for other CPUs\n" );
@@ -1064,14 +1064,14 @@/* Wait for all other CPUs to flush and disable their caches */ while (atomic_read (&undone_count) >0 ) {rep_nop ();barrier (); }/* Set up for completion wait and then release other CPUs to change MTRRs*/ -atomic_set (&undone_count,num_online_cpus () -1 ); +atomic_set (&undone_count,num_booting_cpus () -1 ); wait_barrier_cache_disable = FALSE;set_mtrr_cache_disable (&ctxt);/* Wait for all other CPUs to flush and disable their caches */ while (atomic_read (&undone_count) >0 ) {rep_nop ();barrier (); }/* Set up for completion wait and then release other CPUs to change MTRRs*/ -atomic_set (&undone_count,num_online_cpus () -1 ); +atomic_set (&undone_count,num_booting_cpus () -1 ); wait_barrier_execute = FALSE; (*set_mtrr_up) (reg, base, size, type, FALSE);/* Now wait for other CPUs to complete the function */
arch/i386/kernel/nmi.c +2 -0
@@ -81,6 +81,8 @@sti ();mdelay ((10 *1000 )/nmi_hz);// wait 10 ticks +/* FIXME: Only boot CPU is online at this stage. Check CPUs +as they come up. */ for (cpu =0 ; cpu <NR_CPUS ; cpu++) {if (!cpu_online (cpu))continue ;
arch/i386/kernel/smpboot.c +57 -84
310 lines not on this page · raw message
include/asm-i386/apic.h +2 -1
@@ -76,7 +76,8 @@extern void setup_local_APIC (void );extern void init_apic_mappings (void );extern void smp_local_timer_interrupt (struct pt_regs * regs); -extern void setup_APIC_clocks (void ); +extern void setup_boot_APIC_clock (void ); +extern void setup_secondary_APIC_clock (void );extern void setup_apic_nmi_watchdog (void );extern inline void nmi_watchdog_tick (struct pt_regs * regs);extern int APIC_init_uniprocessor (void );
include/asm-i386/smp.h +8 -7
@@ -79,19 +79,13 @@extern volatile int logical_apicid_to_cpu[MAX_APICID ];/* -* General functions that each host system must provide. -*/ - -extern void smp_boot_cpus (void ); -extern void smp_store_cpu_info (int id);/* Store per CPU info (like the initial udelay numbers */ - -/* * This function is needed by all SMP systems. It must _always_ be valid * from the initial startup. We map APIC_BASE very early in page_setup(), * so this is correct in the x86 case. */ #define smp_processor_id () (current_thread_info()->cpu) +#define cpu_possible (cpu) (phys_cpu_present_map & (1<<(cpu)))#define cpu_online (cpu) (cpu_online_map & (1<<(cpu)))extern inline unsigned int num_online_cpus (void )
@@ -117,6 +111,13 @@ {/* we don't want to mark this access volatile - bad code generation */ return GET_APIC_LOGICAL_ID (*(unsigned long *)(APIC_BASE +APIC_LDR )); +} + +extern volatile unsigned long cpu_callout_map; +/* We don't mark CPUs online until __cpu_up(), so we need another measure */ +static inline int num_booting_cpus (void ) +{ +return hweight32 (cpu_callout_map); }#endif /* !__ASSEMBLY__ */
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.