From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH] x86: introduce and use prefill_possible_map() Date: Tue, 04 May 2010 17:00:35 +0100 Message-ID: <4BE060C3020000780000135E@vpn.id2.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part341E92B3.0__=" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com Cc: xen-ia64-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__Part341E92B3.0__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline With the larger default NR_CPUS config setting (and the more with build time settings exceeding this default) the wasting of memory (and potentially other resources) just because cpu_possible_map doesn't get set up properly increases. Use Linux' (accordingly modified to fit Xen) prefill_possible_map() to overcome this. This makes necessary an adjustment to tasklet initialization (which must not happen before cpu_possible_map is guaranteed to be fully set up - according to my static code analysis this was a problem on ia64 anyway). Tracing code also needed a minor adjustment, as it still had a simple counted loop accessing per-CPU data in its body. Signed-off-by: Jan Beulich --- 2010-05-04.orig/xen/arch/ia64/linux-xen/smpboot.c 2010-05-04 = 16:04:09.000000000 +0200 +++ 2010-05-04/xen/arch/ia64/linux-xen/smpboot.c 2010-05-04 = 13:22:06.000000000 +0200 @@ -776,7 +776,7 @@ void __cpu_die(unsigned int cpu) #endif /* CONFIG_HOTPLUG_CPU */ =20 void -smp_cpus_done (unsigned int dummy) +smp_cpus_done(void) { int cpu; unsigned long bogosum =3D 0; --- 2010-05-04.orig/xen/arch/ia64/xen/xensetup.c 2010-05-04 = 16:04:09.000000000 +0200 +++ 2010-05-04/xen/arch/ia64/xen/xensetup.c 2010-05-04 16:42:36.0000000= 00 +0200 @@ -562,10 +562,12 @@ skip_move: end_boot_allocator(); =20 softirq_init(); - tasklet_subsys_init(); + tasklet_early_init(); =20 late_setup_arch(&cmdline); =20 + tasklet_subsys_init(); + scheduler_init(); idle_vcpu[0] =3D (struct vcpu*) ia64_r13; idle_domain =3D domain_create(IDLE_DOMAIN_ID, 0, 0); @@ -626,7 +628,7 @@ printk("num_online_cpus=3D%d, max_cpus=3D%d\ local_irq_disable(); =20 printk("Brought up %ld CPUs\n", (long)num_online_cpus()); - smp_cpus_done(max_cpus); + smp_cpus_done(); #endif =20 initialise_gdb(); /* could be moved earlier */ --- 2010-05-04.orig/xen/arch/x86/mpparse.c 2010-05-04 16:04:09.0000000= 00 +0200 +++ 2010-05-04/xen/arch/x86/mpparse.c 2010-05-04 13:22:06.000000000 = +0200 @@ -35,7 +35,6 @@ =20 /* Have we found an MP table */ int smp_found_config; -unsigned int __devinitdata maxcpus =3D NR_CPUS; =20 /* * Various Linux-internal data structures created from the @@ -66,7 +65,7 @@ unsigned int def_to_bigsmp =3D 0; /* Processor that is doing the boot up */ unsigned int boot_cpu_physical_apicid =3D -1U; /* Internal processor count */ -static unsigned int __devinitdata num_processors; +unsigned int __devinitdata num_processors; =20 /* Bitmask of physically existing CPUs */ physid_mask_t phys_cpu_present_map; @@ -105,8 +104,10 @@ static int __devinit MP_processor_info ( int ver, apicid, cpu =3D 0; physid_mask_t phys_cpu; =09 - if (!(m->mpc_cpuflag & CPU_ENABLED)) + if (!(m->mpc_cpuflag & CPU_ENABLED)) { + ++disabled_cpus; return -EINVAL; + } =20 apicid =3D mpc_apic_id(m, translation_table[mpc_record]); =20 @@ -185,9 +186,9 @@ static int __devinit MP_processor_info ( return -ENOSPC; } =20 - if (num_processors >=3D maxcpus) { - printk(KERN_WARNING "WARNING: maxcpus limit of %i = reached." - " Processor ignored.\n", maxcpus); + if (max_cpus && num_processors >=3D max_cpus) { + printk(KERN_WARNING "WARNING: maxcpus limit of %u = reached." + " Processor ignored.\n", max_cpus); return -ENOSPC; } =20 --- 2010-05-04.orig/xen/arch/x86/setup.c 2010-05-04 16:04:09.0000000= 00 +0200 +++ 2010-05-04/xen/arch/x86/setup.c 2010-05-04 16:43:22.000000000 = +0200 @@ -61,7 +61,7 @@ static int __initdata opt_nosmp =3D 0; boolean_param("nosmp", opt_nosmp); =20 /* maxcpus: maximum number of CPUs to activate. */ -static unsigned int __initdata max_cpus =3D NR_CPUS; +unsigned int __devinitdata max_cpus; integer_param("maxcpus", max_cpus); =20 /* opt_watchdog: If true, run a watchdog NMI on each processor. */ @@ -568,6 +568,11 @@ void __init __start_xen(unsigned long mb if ( ((unsigned long)cpu0_stack & (STACK_SIZE-1)) !=3D 0 ) EARLY_FAIL("Misaligned CPU0 stack.\n"); =20 + if ( opt_nosmp ) + max_cpus =3D prefill_possible_map(1); + else if ( max_cpus ) + max_cpus =3D prefill_possible_map(max_cpus); + if ( e820_raw_nr !=3D 0 ) { memmap_type =3D "Xen-e820"; @@ -978,7 +983,7 @@ void __init __start_xen(unsigned long mb #endif =20 softirq_init(); - tasklet_subsys_init(); + tasklet_early_init(); =20 early_cpu_init(); =20 @@ -1017,6 +1022,11 @@ void __init __start_xen(unsigned long mb zap_low_mappings(); #endif =20 + if ( !max_cpus ) + max_cpus =3D prefill_possible_map(0); + + tasklet_subsys_init(); + init_apic_mappings(); =20 percpu_free_unused_areas(); @@ -1049,12 +1059,9 @@ void __init __start_xen(unsigned long mb vesa_mtrr_init(); #endif =20 - if ( opt_nosmp ) - max_cpus =3D 0; - iommu_setup(); /* setup iommu if available */ =20 - smp_prepare_cpus(max_cpus); + smp_prepare_cpus(!opt_nosmp * max_cpus); =20 spin_debug_enable(); =20 @@ -1087,7 +1094,7 @@ void __init __start_xen(unsigned long mb } =20 printk("Brought up %ld CPUs\n", (long)num_online_cpus()); - smp_cpus_done(max_cpus); + smp_cpus_done(); =20 initialise_gdb(); /* could be moved earlier */ =20 --- 2010-05-04.orig/xen/arch/x86/smpboot.c 2010-05-04 16:04:09.0000000= 00 +0200 +++ 2010-05-04/xen/arch/x86/smpboot.c 2010-05-04 13:22:06.000000000 = +0200 @@ -83,10 +83,12 @@ EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_callin_map; cpumask_t cpu_callout_map; EXPORT_SYMBOL(cpu_callout_map); -cpumask_t cpu_possible_map =3D CPU_MASK_ALL; +cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); static cpumask_t smp_commenced_mask; =20 +unsigned int __devinitdata disabled_cpus; + /* TSC's upper 32 bits can't be written in eariler CPU (before prescott), = there * is no way to resync one AP against BP. TBD: for prescott and above, we * should use IA64's algorithm @@ -829,7 +831,11 @@ int alloc_cpu_id(void) { cpumask_t tmp_map; int cpu; - cpus_complement(tmp_map, cpu_present_map); + + if (max_cpus) + cpus_andnot(tmp_map, cpu_possible_map, cpu_present_map); + else + cpus_complement(tmp_map, cpu_present_map); cpu =3D first_cpu(tmp_map); if (cpu >=3D NR_CPUS) return -ENODEV; @@ -1243,6 +1249,52 @@ void __devinit smp_prepare_boot_cpu(void per_cpu(cpu_state, smp_processor_id()) =3D CPU_ONLINE; } =20 +/* + * cpu_possible_mask should be static, it cannot change as cpu's + * are onlined, or offlined. The reason is per-cpu data-structures + * are allocated by some modules at init time, and dont expect to + * do this dynamically on cpu arrival/departure. + * cpu_present_mask on the other hand can change dynamically. + * In case when cpu_hotplug is not compiled, then we resort to current + * behaviour, which is cpu_possible =3D=3D cpu_present. + * - Ashok Raj + * + * Three ways to find out the number of additional hotplug CPUs: + * - If the BIOS specified disabled CPUs in ACPI/mptables use that. + * - The user can overwrite it with max_cpus=3DNUM + * - Otherwise don't reserve additional CPUs. + * We do this because additional CPUs waste a lot of memory. + * -AK + */ +unsigned int __init prefill_possible_map(unsigned int max_cpus) +{ + unsigned int i, possible; + + /* no processor from mptable or madt */ + if (!num_processors) + num_processors =3D 1; + + if (!max_cpus) + possible =3D num_processors + disabled_cpus; + else + possible =3D max_cpus; + + if (possible > NR_CPUS) { + printk(KERN_WARNING + "%u processors exceeds NR_CPUS limit of %d\n", + possible, NR_CPUS); + possible =3D NR_CPUS; + } + + printk(KERN_INFO "SMP: Allowing %u CPUs, %d hotplug CPUs\n", + possible, max_t(int, possible - num_processors, 0)); + + for (i =3D 0; i < possible; i++) + cpu_set(i, cpu_possible_map); + + return possible; +} + static void remove_siblinginfo(int cpu) { @@ -1568,7 +1620,7 @@ int __devinit __cpu_up(unsigned int cpu) } =20 =20 -void __init smp_cpus_done(unsigned int max_cpus) +void __init smp_cpus_done(void) { #ifdef CONFIG_X86_IO_APIC setup_ioapic_dest(); --- 2010-05-04.orig/xen/common/tasklet.c 2010-04-22 14:43:25.0000000= 00 +0200 +++ 2010-05-04/xen/common/tasklet.c 2010-05-04 16:46:03.000000000 = +0200 @@ -18,7 +18,7 @@ #include =20 /* Some subsystems call into us before we are initialised. We ignore = them. */ -static bool_t tasklets_initialised; +static unsigned int __read_mostly tasklets_initialised =3D UINT_MAX; =20 /* * NB. Any modification to a tasklet_list requires the scheduler to run @@ -35,7 +35,8 @@ void tasklet_schedule_on_cpu(struct task =20 spin_lock_irqsave(&tasklet_lock, flags); =20 - if ( tasklets_initialised && !t->is_dead ) + if ( (tasklets_initialised =3D=3D NR_CPUS || tasklets_initialised = =3D=3D cpu) && + !t->is_dead ) { t->scheduled_on =3D cpu; if ( !t->is_running ) @@ -161,14 +162,24 @@ void tasklet_init( t->data =3D data; } =20 +void __init tasklet_early_init(void) +{ + unsigned int cpu =3D smp_processor_id(); + + INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu)); + + tasklets_initialised =3D cpu; +} + void __init tasklet_subsys_init(void) { unsigned int cpu; =20 for_each_possible_cpu ( cpu ) - INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu)); + if ( cpu !=3D tasklets_initialised ) + INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu)); =20 - tasklets_initialised =3D 1; + tasklets_initialised =3D NR_CPUS; } =20 /* --- 2010-05-04.orig/xen/common/trace.c 2010-04-22 14:43:25.000000000 = +0200 +++ 2010-05-04/xen/common/trace.c 2010-05-04 16:26:50.000000000 = +0200 @@ -289,7 +289,7 @@ void __init init_trace_bufs(void) return; } =20 - for(i =3D 0; i < NR_CPUS; i++) + for_each_possible_cpu(i) spin_lock_init(&per_cpu(t_lock, i)); =20 for(i=3D0; i=0A=0A--- 2010-05-04.orig/xen/arch/ia64/linux-xen/smpb= oot.c 2010-05-04 16:04:09.000000000 +0200=0A+++ 2010-05-04/xen/arch/ia64/= linux-xen/smpboot.c 2010-05-04 13:22:06.000000000 +0200=0A@@ -776,7 = +776,7 @@ void __cpu_die(unsigned int cpu)=0A #endif /* CONFIG_HOTPLUG_CPU = */=0A =0A void=0A-smp_cpus_done (unsigned int dummy)=0A+smp_cpus_done(void)= =0A {=0A int cpu;=0A unsigned long bogosum =3D 0;=0A--- = 2010-05-04.orig/xen/arch/ia64/xen/xensetup.c 2010-05-04 16:04:09.0000000= 00 +0200=0A+++ 2010-05-04/xen/arch/ia64/xen/xensetup.c 2010-05-04 = 16:42:36.000000000 +0200=0A@@ -562,10 +562,12 @@ skip_move:=0A = end_boot_allocator();=0A =0A softirq_init();=0A- tasklet_subsys_init= ();=0A+ tasklet_early_init();=0A =0A late_setup_arch(&cmdline);=0A = =0A+ tasklet_subsys_init();=0A+=0A scheduler_init();=0A = idle_vcpu[0] =3D (struct vcpu*) ia64_r13;=0A idle_domain =3D domain_cre= ate(IDLE_DOMAIN_ID, 0, 0);=0A@@ -626,7 +628,7 @@ printk("num_online_cpus=3D= %d, max_cpus=3D%d\=0A local_irq_disable();=0A =0A printk("Brought = up %ld CPUs\n", (long)num_online_cpus());=0A- smp_cpus_done(max_cpus);= =0A+ smp_cpus_done();=0A #endif=0A =0A initialise_gdb(); /* could = be moved earlier */=0A--- 2010-05-04.orig/xen/arch/x86/mpparse.c = 2010-05-04 16:04:09.000000000 +0200=0A+++ 2010-05-04/xen/arch/x86/mpparse.c= 2010-05-04 13:22:06.000000000 +0200=0A@@ -35,7 +35,6 @@=0A =0A /* = Have we found an MP table */=0A int smp_found_config;=0A-unsigned int = __devinitdata maxcpus =3D NR_CPUS;=0A =0A /*=0A * Various Linux-internal = data structures created from the=0A@@ -66,7 +65,7 @@ unsigned int = def_to_bigsmp =3D 0;=0A /* Processor that is doing the boot up */=0A = unsigned int boot_cpu_physical_apicid =3D -1U;=0A /* Internal processor = count */=0A-static unsigned int __devinitdata num_processors;=0A+unsigned = int __devinitdata num_processors;=0A =0A /* Bitmask of physically existing = CPUs */=0A physid_mask_t phys_cpu_present_map;=0A@@ -105,8 +104,10 @@ = static int __devinit MP_processor_info (=0A int ver, apicid, cpu =3D = 0;=0A physid_mask_t phys_cpu;=0A =0A- if (!(m->mpc_cpuflag & = CPU_ENABLED))=0A+ if (!(m->mpc_cpuflag & CPU_ENABLED)) {=0A+ = ++disabled_cpus;=0A return -EINVAL;=0A+ }=0A =0A = apicid =3D mpc_apic_id(m, translation_table[mpc_record]);=0A =0A@@ -185,9 = +186,9 @@ static int __devinit MP_processor_info (=0A return = -ENOSPC;=0A }=0A =0A- if (num_processors >=3D maxcpus) {=0A- = printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."=0A- = " Processor ignored.\n", maxcpus);=0A+ if (max_cpus && num_processors = >=3D max_cpus) {=0A+ printk(KERN_WARNING "WARNING: maxcpus = limit of %u reached."=0A+ " Processor ignored.\n", = max_cpus);=0A return -ENOSPC;=0A }=0A =0A--- 2010-05-04.orig= /xen/arch/x86/setup.c 2010-05-04 16:04:09.000000000 +0200=0A+++ = 2010-05-04/xen/arch/x86/setup.c 2010-05-04 16:43:22.000000000 +0200=0A@@ = -61,7 +61,7 @@ static int __initdata opt_nosmp =3D 0;=0A boolean_param("nos= mp", opt_nosmp);=0A =0A /* maxcpus: maximum number of CPUs to activate. = */=0A-static unsigned int __initdata max_cpus =3D NR_CPUS;=0A+unsigned int = __devinitdata max_cpus;=0A integer_param("maxcpus", max_cpus);=0A =0A /* = opt_watchdog: If true, run a watchdog NMI on each processor. */=0A@@ = -568,6 +568,11 @@ void __init __start_xen(unsigned long mb=0A if ( = ((unsigned long)cpu0_stack & (STACK_SIZE-1)) !=3D 0 )=0A EARLY_FAIL= ("Misaligned CPU0 stack.\n");=0A =0A+ if ( opt_nosmp )=0A+ = max_cpus =3D prefill_possible_map(1);=0A+ else if ( max_cpus )=0A+ = max_cpus =3D prefill_possible_map(max_cpus);=0A+=0A if ( e820_raw_nr = !=3D 0 )=0A {=0A memmap_type =3D "Xen-e820";=0A@@ -978,7 = +983,7 @@ void __init __start_xen(unsigned long mb=0A #endif=0A =0A = softirq_init();=0A- tasklet_subsys_init();=0A+ tasklet_early_init();= =0A =0A early_cpu_init();=0A =0A@@ -1017,6 +1022,11 @@ void __init = __start_xen(unsigned long mb=0A zap_low_mappings();=0A #endif=0A =0A+ = if ( !max_cpus )=0A+ max_cpus =3D prefill_possible_map(0);=0A+=0A+= tasklet_subsys_init();=0A+=0A init_apic_mappings();=0A =0A = percpu_free_unused_areas();=0A@@ -1049,12 +1059,9 @@ void __init __start_xe= n(unsigned long mb=0A vesa_mtrr_init();=0A #endif=0A =0A- if ( = opt_nosmp )=0A- max_cpus =3D 0;=0A-=0A iommu_setup(); /* = setup iommu if available */=0A =0A- smp_prepare_cpus(max_cpus);=0A+ = smp_prepare_cpus(!opt_nosmp * max_cpus);=0A =0A spin_debug_enable();=0A= =0A@@ -1087,7 +1094,7 @@ void __init __start_xen(unsigned long mb=0A = }=0A =0A printk("Brought up %ld CPUs\n", (long)num_online_cpus());=0A- = smp_cpus_done(max_cpus);=0A+ smp_cpus_done();=0A =0A initialise_g= db(); /* could be moved earlier */=0A =0A--- 2010-05-04.orig/xen/arch/x86/s= mpboot.c 2010-05-04 16:04:09.000000000 +0200=0A+++ 2010-05-04/xen/ar= ch/x86/smpboot.c 2010-05-04 13:22:06.000000000 +0200=0A@@ -83,10 = +83,12 @@ EXPORT_SYMBOL(cpu_online_map);=0A cpumask_t cpu_callin_map;=0A = cpumask_t cpu_callout_map;=0A EXPORT_SYMBOL(cpu_callout_map);=0A-cpumask_t = cpu_possible_map =3D CPU_MASK_ALL;=0A+cpumask_t cpu_possible_map;=0A = EXPORT_SYMBOL(cpu_possible_map);=0A static cpumask_t smp_commenced_mask;=0A= =0A+unsigned int __devinitdata disabled_cpus;=0A+=0A /* TSC's upper 32 = bits can't be written in eariler CPU (before prescott), there=0A * is no = way to resync one AP against BP. TBD: for prescott and above, we=0A * = should use IA64's algorithm=0A@@ -829,7 +831,11 @@ int alloc_cpu_id(void)= =0A {=0A cpumask_t tmp_map;=0A int cpu;=0A- cpus_comple= ment(tmp_map, cpu_present_map);=0A+=0A+ if (max_cpus)=0A+ = cpus_andnot(tmp_map, cpu_possible_map, cpu_present_map);=0A+ else=0A+ = cpus_complement(tmp_map, cpu_present_map);=0A cpu =3D first_cpu(t= mp_map);=0A if (cpu >=3D NR_CPUS)=0A return -ENODEV;=0A@= @ -1243,6 +1249,52 @@ void __devinit smp_prepare_boot_cpu(void=0A = per_cpu(cpu_state, smp_processor_id()) =3D CPU_ONLINE;=0A }=0A =0A+/*=0A+ = * cpu_possible_mask should be static, it cannot change as cpu's=0A+ * are = onlined, or offlined. The reason is per-cpu data-structures=0A+ * are = allocated by some modules at init time, and dont expect to=0A+ * do this = dynamically on cpu arrival/departure.=0A+ * cpu_present_mask on the other = hand can change dynamically.=0A+ * In case when cpu_hotplug is not = compiled, then we resort to current=0A+ * behaviour, which is cpu_possible = =3D=3D cpu_present.=0A+ * - Ashok Raj=0A+ *=0A+ * Three ways to find out = the number of additional hotplug CPUs:=0A+ * - If the BIOS specified = disabled CPUs in ACPI/mptables use that.=0A+ * - The user can overwrite it = with max_cpus=3DNUM=0A+ * - Otherwise don't reserve additional CPUs.=0A+ * = We do this because additional CPUs waste a lot of memory.=0A+ * -AK=0A+ = */=0A+unsigned int __init prefill_possible_map(unsigned int max_cpus)=0A+{= =0A+ unsigned int i, possible;=0A+=0A+ /* no processor from = mptable or madt */=0A+ if (!num_processors)=0A+ num_process= ors =3D 1;=0A+=0A+ if (!max_cpus)=0A+ possible =3D = num_processors + disabled_cpus;=0A+ else=0A+ possible = =3D max_cpus;=0A+=0A+ if (possible > NR_CPUS) {=0A+ printk(KERN= _WARNING=0A+ "%u processors exceeds NR_CPUS limit of = %d\n",=0A+ possible, NR_CPUS);=0A+ possible = =3D NR_CPUS;=0A+ }=0A+=0A+ printk(KERN_INFO "SMP: Allowing %u = CPUs, %d hotplug CPUs\n",=0A+ possible, max_t(int, possible - = num_processors, 0));=0A+=0A+ for (i =3D 0; i < possible; i++)=0A+ = cpu_set(i, cpu_possible_map);=0A+=0A+ return possible;=0A+}=0A+=0A = static void=0A remove_siblinginfo(int cpu)=0A {=0A@@ -1568,7 +1620,7 @@ = int __devinit __cpu_up(unsigned int cpu)=0A }=0A =0A =0A-void __init = smp_cpus_done(unsigned int max_cpus)=0A+void __init smp_cpus_done(void)=0A = {=0A #ifdef CONFIG_X86_IO_APIC=0A setup_ioapic_dest();=0A--- = 2010-05-04.orig/xen/common/tasklet.c 2010-04-22 14:43:25.000000000 = +0200=0A+++ 2010-05-04/xen/common/tasklet.c 2010-05-04 16:46:03.0000000= 00 +0200=0A@@ -18,7 +18,7 @@=0A #include =0A =0A /* Some = subsystems call into us before we are initialised. We ignore them. = */=0A-static bool_t tasklets_initialised;=0A+static unsigned int __read_mos= tly tasklets_initialised =3D UINT_MAX;=0A =0A /*=0A * NB. Any modification= to a tasklet_list requires the scheduler to run=0A@@ -35,7 +35,8 @@ void = tasklet_schedule_on_cpu(struct task=0A =0A spin_lock_irqsave(&tasklet_l= ock, flags);=0A =0A- if ( tasklets_initialised && !t->is_dead )=0A+ = if ( (tasklets_initialised =3D=3D NR_CPUS || tasklets_initialised =3D=3D = cpu) &&=0A+ !t->is_dead )=0A {=0A t->scheduled_on =3D = cpu;=0A if ( !t->is_running )=0A@@ -161,14 +162,24 @@ void = tasklet_init(=0A t->data =3D data;=0A }=0A =0A+void __init tasklet_earl= y_init(void)=0A+{=0A+ unsigned int cpu =3D smp_processor_id();=0A+=0A+ = INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu));=0A+=0A+ tasklets_initiali= sed =3D cpu;=0A+}=0A+=0A void __init tasklet_subsys_init(void)=0A {=0A = unsigned int cpu;=0A =0A for_each_possible_cpu ( cpu )=0A- = INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu));=0A+ if ( cpu !=3D = tasklets_initialised )=0A+ INIT_LIST_HEAD(&per_cpu(tasklet_list,= cpu));=0A =0A- tasklets_initialised =3D 1;=0A+ tasklets_initialised = =3D NR_CPUS;=0A }=0A =0A /*=0A--- 2010-05-04.orig/xen/common/trace.c = 2010-04-22 14:43:25.000000000 +0200=0A+++ 2010-05-04/xen/common/trace.c = 2010-05-04 16:26:50.000000000 +0200=0A@@ -289,7 +289,7 @@ void __init = init_trace_bufs(void)=0A return;=0A }=0A =0A- for(i =3D 0; = i < NR_CPUS; i++)=0A+ for_each_possible_cpu(i)=0A spin_lock_init= (&per_cpu(t_lock, i));=0A =0A for(i=3D0; i