ia64/linux-2.6.18-xen.hg

view drivers/xen/core/smpboot.c @ 869:271d9b9bee40

xen: miscellaneous cleanup

- add two missing unwind annotations
- mark remaining struct file_operations instances const
- use get_capacity() instead of raw access to the capacity field
- use assert_spin_locked() instead of BUG_ON(!spin_is_locked())
- use clear_tsk_thread_flag() instead of clear_ti_thread_flag()
- remove dead variable cpu_state

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 14 10:08:10 2009 +0100 (2009-05-14)
parents 26e1e96bd46a
children
line source
1 /*
2 * Xen SMP booting functions
3 *
4 * See arch/i386/kernel/smpboot.c for copyright and credits for derived
5 * portions of this file.
6 */
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/mm.h>
12 #include <linux/sched.h>
13 #include <linux/kernel_stat.h>
14 #include <linux/smp_lock.h>
15 #include <linux/irq.h>
16 #include <linux/bootmem.h>
17 #include <linux/notifier.h>
18 #include <linux/cpu.h>
19 #include <linux/percpu.h>
20 #include <asm/desc.h>
21 #include <asm/arch_hooks.h>
22 #include <asm/pgalloc.h>
23 #include <xen/evtchn.h>
24 #include <xen/interface/vcpu.h>
25 #include <xen/cpu_hotplug.h>
26 #include <xen/xenbus.h>
28 extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
29 extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
31 extern int local_setup_timer(unsigned int cpu);
32 extern void local_teardown_timer(unsigned int cpu);
34 extern void hypervisor_callback(void);
35 extern void failsafe_callback(void);
36 extern void system_call(void);
37 extern void smp_trap_init(trap_info_t *);
39 /* Number of siblings per CPU package */
40 int smp_num_siblings = 1;
42 cpumask_t cpu_online_map;
43 EXPORT_SYMBOL(cpu_online_map);
44 cpumask_t cpu_possible_map;
45 EXPORT_SYMBOL(cpu_possible_map);
46 cpumask_t cpu_initialized_map;
48 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
49 EXPORT_SYMBOL(cpu_data);
51 static DEFINE_PER_CPU(int, resched_irq);
52 static DEFINE_PER_CPU(int, callfunc_irq);
53 static char resched_name[NR_CPUS][15];
54 static char callfunc_name[NR_CPUS][15];
56 u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
58 cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
59 cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
60 EXPORT_SYMBOL(cpu_core_map);
62 #if defined(__i386__)
63 u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = 0xff };
64 EXPORT_SYMBOL(x86_cpu_to_apicid);
65 #elif !defined(CONFIG_X86_IO_APIC)
66 unsigned int maxcpus = NR_CPUS;
67 #endif
69 void __init prefill_possible_map(void)
70 {
71 int i, rc;
73 for_each_possible_cpu(i)
74 if (i != smp_processor_id())
75 return;
77 for (i = 0; i < NR_CPUS; i++) {
78 rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
79 if (rc >= 0)
80 cpu_set(i, cpu_possible_map);
81 }
82 }
84 void __init smp_alloc_memory(void)
85 {
86 }
88 static inline void
89 set_cpu_sibling_map(unsigned int cpu)
90 {
91 cpu_data[cpu].phys_proc_id = cpu;
92 cpu_data[cpu].cpu_core_id = 0;
94 cpu_sibling_map[cpu] = cpumask_of_cpu(cpu);
95 cpu_core_map[cpu] = cpumask_of_cpu(cpu);
97 cpu_data[cpu].booted_cores = 1;
98 }
100 static void
101 remove_siblinginfo(unsigned int cpu)
102 {
103 cpu_data[cpu].phys_proc_id = BAD_APICID;
104 cpu_data[cpu].cpu_core_id = BAD_APICID;
106 cpus_clear(cpu_sibling_map[cpu]);
107 cpus_clear(cpu_core_map[cpu]);
109 cpu_data[cpu].booted_cores = 0;
110 }
112 static int __cpuinit xen_smp_intr_init(unsigned int cpu)
113 {
114 int rc;
116 per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
118 sprintf(resched_name[cpu], "resched%u", cpu);
119 rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
120 cpu,
121 smp_reschedule_interrupt,
122 SA_INTERRUPT,
123 resched_name[cpu],
124 NULL);
125 if (rc < 0)
126 goto fail;
127 per_cpu(resched_irq, cpu) = rc;
129 sprintf(callfunc_name[cpu], "callfunc%u", cpu);
130 rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR,
131 cpu,
132 smp_call_function_interrupt,
133 SA_INTERRUPT,
134 callfunc_name[cpu],
135 NULL);
136 if (rc < 0)
137 goto fail;
138 per_cpu(callfunc_irq, cpu) = rc;
140 if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0))
141 goto fail;
143 return 0;
145 fail:
146 if (per_cpu(resched_irq, cpu) >= 0)
147 unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
148 if (per_cpu(callfunc_irq, cpu) >= 0)
149 unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
150 return rc;
151 }
153 #ifdef CONFIG_HOTPLUG_CPU
154 static void xen_smp_intr_exit(unsigned int cpu)
155 {
156 if (cpu != 0)
157 local_teardown_timer(cpu);
159 unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
160 unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
161 }
162 #endif
164 void __cpuinit cpu_bringup(void)
165 {
166 cpu_init();
167 identify_cpu(cpu_data + smp_processor_id());
168 touch_softlockup_watchdog();
169 preempt_disable();
170 local_irq_enable();
171 }
173 static void __cpuinit cpu_bringup_and_idle(void)
174 {
175 cpu_bringup();
176 cpu_idle();
177 }
179 static void __cpuinit cpu_initialize_context(unsigned int cpu)
180 {
181 /* vcpu_guest_context_t is too large to allocate on the stack.
182 * Hence we allocate statically and protect it with a lock */
183 static vcpu_guest_context_t ctxt;
184 static DEFINE_SPINLOCK(ctxt_lock);
186 struct task_struct *idle = idle_task(cpu);
187 #ifdef __x86_64__
188 struct desc_ptr *gdt_descr = &cpu_gdt_descr[cpu];
189 #else
190 struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
191 #endif
193 if (cpu_test_and_set(cpu, cpu_initialized_map))
194 return;
196 spin_lock(&ctxt_lock);
198 memset(&ctxt, 0, sizeof(ctxt));
200 ctxt.flags = VGCF_IN_KERNEL;
201 ctxt.user_regs.ds = __USER_DS;
202 ctxt.user_regs.es = __USER_DS;
203 ctxt.user_regs.fs = 0;
204 ctxt.user_regs.gs = 0;
205 ctxt.user_regs.ss = __KERNEL_DS;
206 ctxt.user_regs.eip = (unsigned long)cpu_bringup_and_idle;
207 ctxt.user_regs.eflags = X86_EFLAGS_IF | 0x1000; /* IOPL_RING1 */
209 memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
211 smp_trap_init(ctxt.trap_ctxt);
213 ctxt.ldt_ents = 0;
215 ctxt.gdt_frames[0] = virt_to_mfn(gdt_descr->address);
216 ctxt.gdt_ents = gdt_descr->size / 8;
218 #ifdef __i386__
219 ctxt.user_regs.cs = __KERNEL_CS;
220 ctxt.user_regs.esp = idle->thread.esp0 - sizeof(struct pt_regs);
222 ctxt.kernel_ss = __KERNEL_DS;
223 ctxt.kernel_sp = idle->thread.esp0;
225 ctxt.event_callback_cs = __KERNEL_CS;
226 ctxt.event_callback_eip = (unsigned long)hypervisor_callback;
227 ctxt.failsafe_callback_cs = __KERNEL_CS;
228 ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
230 ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
231 #else /* __x86_64__ */
232 ctxt.user_regs.cs = __KERNEL_CS;
233 ctxt.user_regs.esp = idle->thread.rsp0 - sizeof(struct pt_regs);
235 ctxt.kernel_ss = __KERNEL_DS;
236 ctxt.kernel_sp = idle->thread.rsp0;
238 ctxt.event_callback_eip = (unsigned long)hypervisor_callback;
239 ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
240 ctxt.syscall_callback_eip = (unsigned long)system_call;
242 ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(init_level4_pgt));
244 ctxt.gs_base_kernel = (unsigned long)(cpu_pda(cpu));
245 #endif
247 if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, &ctxt))
248 BUG();
250 spin_unlock(&ctxt_lock);
251 }
253 void __init smp_prepare_cpus(unsigned int max_cpus)
254 {
255 unsigned int cpu;
256 struct task_struct *idle;
257 int apicid, acpiid;
258 struct vcpu_get_physid cpu_id;
259 #ifdef __x86_64__
260 struct desc_ptr *gdt_descr;
261 #else
262 struct Xgt_desc_struct *gdt_descr;
263 #endif
265 apicid = 0;
266 if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, 0, &cpu_id) == 0) {
267 apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
268 acpiid = xen_vcpu_physid_to_x86_acpiid(cpu_id.phys_id);
269 #ifdef CONFIG_ACPI
270 if (acpiid != 0xff)
271 x86_acpiid_to_apicid[acpiid] = apicid;
272 #endif
273 }
274 boot_cpu_data.apicid = apicid;
275 cpu_data[0] = boot_cpu_data;
277 cpu_2_logical_apicid[0] = apicid;
278 x86_cpu_to_apicid[0] = apicid;
280 current_thread_info()->cpu = 0;
282 for (cpu = 0; cpu < NR_CPUS; cpu++) {
283 cpus_clear(cpu_sibling_map[cpu]);
284 cpus_clear(cpu_core_map[cpu]);
285 }
287 set_cpu_sibling_map(0);
289 if (xen_smp_intr_init(0))
290 BUG();
292 cpu_initialized_map = cpumask_of_cpu(0);
294 /* Restrict the possible_map according to max_cpus. */
295 while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
296 for (cpu = NR_CPUS-1; !cpu_isset(cpu, cpu_possible_map); cpu--)
297 continue;
298 cpu_clear(cpu, cpu_possible_map);
299 }
301 for_each_possible_cpu (cpu) {
302 if (cpu == 0)
303 continue;
305 #ifdef __x86_64__
306 gdt_descr = &cpu_gdt_descr[cpu];
307 #else
308 gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
309 #endif
310 gdt_descr->address = get_zeroed_page(GFP_KERNEL);
311 if (unlikely(!gdt_descr->address)) {
312 printk(KERN_CRIT "CPU%d failed to allocate GDT\n",
313 cpu);
314 continue;
315 }
316 gdt_descr->size = GDT_SIZE;
317 memcpy((void *)gdt_descr->address, cpu_gdt_table, GDT_SIZE);
318 make_page_readonly(
319 (void *)gdt_descr->address,
320 XENFEAT_writable_descriptor_tables);
322 apicid = cpu;
323 if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, cpu, &cpu_id) == 0) {
324 apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
325 acpiid = xen_vcpu_physid_to_x86_acpiid(cpu_id.phys_id);
326 #ifdef CONFIG_ACPI
327 if (acpiid != 0xff)
328 x86_acpiid_to_apicid[acpiid] = apicid;
329 #endif
330 }
331 cpu_data[cpu] = boot_cpu_data;
332 cpu_data[cpu].apicid = apicid;
334 cpu_2_logical_apicid[cpu] = apicid;
335 x86_cpu_to_apicid[cpu] = apicid;
337 idle = fork_idle(cpu);
338 if (IS_ERR(idle))
339 panic("failed fork for CPU %d", cpu);
341 #ifdef __x86_64__
342 cpu_pda(cpu)->pcurrent = idle;
343 cpu_pda(cpu)->cpunumber = cpu;
344 clear_tsk_thread_flag(idle, TIF_FORK);
345 #endif
347 irq_ctx_init(cpu);
349 #ifdef CONFIG_HOTPLUG_CPU
350 if (is_initial_xendomain())
351 cpu_set(cpu, cpu_present_map);
352 #else
353 cpu_set(cpu, cpu_present_map);
354 #endif
355 }
357 init_xenbus_allowed_cpumask();
359 #ifdef CONFIG_X86_IO_APIC
360 /*
361 * Here we can be sure that there is an IO-APIC in the system. Let's
362 * go and set it up:
363 */
364 if (!skip_ioapic_setup && nr_ioapics)
365 setup_IO_APIC();
366 #endif
367 }
369 void __devinit smp_prepare_boot_cpu(void)
370 {
371 prefill_possible_map();
372 }
374 #ifdef CONFIG_HOTPLUG_CPU
376 /*
377 * Initialize cpu_present_map late to skip SMP boot code in init/main.c.
378 * But do it early enough to catch critical for_each_present_cpu() loops
379 * in i386-specific code.
380 */
381 static int __init initialize_cpu_present_map(void)
382 {
383 cpu_present_map = cpu_possible_map;
384 return 0;
385 }
386 core_initcall(initialize_cpu_present_map);
388 int __cpu_disable(void)
389 {
390 cpumask_t map = cpu_online_map;
391 unsigned int cpu = smp_processor_id();
393 if (cpu == 0)
394 return -EBUSY;
396 remove_siblinginfo(cpu);
398 cpu_clear(cpu, map);
399 fixup_irqs(map);
400 cpu_clear(cpu, cpu_online_map);
402 return 0;
403 }
405 void __cpu_die(unsigned int cpu)
406 {
407 while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
408 current->state = TASK_UNINTERRUPTIBLE;
409 schedule_timeout(HZ/10);
410 }
412 xen_smp_intr_exit(cpu);
414 if (num_online_cpus() == 1)
415 alternatives_smp_switch(0);
416 }
418 #endif /* CONFIG_HOTPLUG_CPU */
420 int __cpuinit __cpu_up(unsigned int cpu)
421 {
422 int rc;
424 rc = cpu_up_check(cpu);
425 if (rc)
426 return rc;
428 cpu_initialize_context(cpu);
430 if (num_online_cpus() == 1)
431 alternatives_smp_switch(1);
433 /* This must be done before setting cpu_online_map */
434 set_cpu_sibling_map(cpu);
435 wmb();
437 rc = xen_smp_intr_init(cpu);
438 if (rc) {
439 remove_siblinginfo(cpu);
440 return rc;
441 }
443 cpu_set(cpu, cpu_online_map);
445 rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
446 BUG_ON(rc);
448 return 0;
449 }
451 void __init smp_cpus_done(unsigned int max_cpus)
452 {
453 }
455 #ifndef CONFIG_X86_LOCAL_APIC
456 int setup_profiling_timer(unsigned int multiplier)
457 {
458 return -EINVAL;
459 }
460 #endif