1 #include <lwk/kernel.h>
2 #include <lwk/spinlock.h>
5 #include <arch/idt_vectors.h>
6 #include <arch/processor.h>
9 * Used to pass data to and synchronize the CPUs targeted by a cross-call.
11 struct xcall_data_struct {
12 void (*func)(void *info);
20 * Global cross-call data pointer, protected by xcall_data_lock.
22 static struct xcall_data_struct *xcall_data;
23 static DEFINE_SPINLOCK(xcall_data_lock);
26 * x86_64 specific code for carrying out inter-CPU function calls.
27 * This function should not be called directly. Call xcall_function() instead.
30 * [IN] cpu_mask: The target CPUs of the cross-call.
31 * [IN] func: The function to execute on each target CPU.
32 * [IN] info: Argument to pass to func().
33 * [IN] wait: true = wait for cross-call to fully complete.
42 void (*func)(void *info),
47 struct xcall_data_struct data;
48 unsigned int num_cpus;
51 BUG_ON(irqs_disabled());
53 /* Count how many CPUs are being targeted */
54 num_cpus = cpus_weight(cpu_mask);
58 /* Fill in the xcall data structure on our stack */
61 atomic_set(&data.started, 0);
63 atomic_set(&data.finished, 0);
66 /* Spin with IRQs enabled */
67 while (!spin_trylock_irq(&xcall_data_lock))
69 /* IRQs are now disabled */
71 /* Set the global xcall data pointer */
75 /* Send inter-processor interrupts to the target CPUs */
76 for_each_cpu_mask(cpu, cpu_mask)
77 lapic_send_ipi(cpu, XCALL_FUNCTION_VECTOR);
79 /* Wait for initiation responses */
80 while (atomic_read(&data.started) != num_cpus)
83 /* If requested, wait for completion responses */
85 while (atomic_read(&data.finished) != num_cpus)
88 spin_unlock_irq(&xcall_data_lock);
94 * The interrupt handler for inter-CPU function calls.
97 arch_xcall_function_interrupt(struct pt_regs *regs, unsigned int vector)
99 void (*func)(void *info) = xcall_data->func;
100 void *info = xcall_data->info;
101 int wait = xcall_data->wait;
103 /* Notify initiating CPU that we've started */
105 atomic_inc(&xcall_data->started);
107 /* Execute the cross-call function */
110 /* Notify initiating CPU that the cross-call function has completed */
113 atomic_inc(&xcall_data->finished);
118 * Sends a reschedule inter-processor interrupt to the target CPU.
119 * This causes the target CPU to call schedule().
122 arch_xcall_reschedule(id_t cpu)
124 lapic_send_ipi(cpu, XCALL_RESCHEDULE_VECTOR);
128 * The interrupt handler for inter-CPU reschedule calls.
131 arch_xcall_reschedule_interrupt(struct pt_regs *regs, unsigned int vector)
134 * Nothing to do, schedule() will be automatically
135 * called before returning to user-space