2 * Xen spinlock functions
4 * See arch/x86/xen/smp.c for copyright and credits for derived
5 * portions of this file.
7 #define XEN_SPINLOCK_SOURCE
8 #include <linux/spinlock_types.h>
12 #include <linux/export.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <asm/hardirq.h>
16 #include <xen/clock.h>
17 #include <xen/evtchn.h>
20 arch_spinlock_t *lock;
22 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING
23 unsigned int irq_count;
25 struct spinning *prev;
27 static DEFINE_PER_CPU(struct spinning *, _spinning);
28 static DEFINE_PER_CPU_READ_MOSTLY(evtchn_port_t, poll_evtchn);
30 * Protect removal of objects: Addition can be done lockless, and even
31 * removal itself doesn't need protection - what needs to be prevented is
32 * removed objects going out of scope (as they're allocated on the stack).
36 #define SEQ_REMOVE_BIAS (1 << !!CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING)
39 static DEFINE_PER_CPU(struct rm_seq, rm_seq);
41 int __cpuinit xen_spinlock_init(unsigned int cpu)
43 struct evtchn_bind_ipi bind_ipi;
46 setup_runstate_area(cpu);
48 WARN_ON(per_cpu(poll_evtchn, cpu));
50 rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi);
52 per_cpu(poll_evtchn, cpu) = bind_ipi.port;
54 pr_warning("No spinlock poll event channel for CPU#%u (%d)\n",
60 void __cpuinit xen_spinlock_cleanup(unsigned int cpu)
62 struct evtchn_close close;
64 close.port = per_cpu(poll_evtchn, cpu);
65 per_cpu(poll_evtchn, cpu) = 0;
66 WARN_ON(HYPERVISOR_event_channel_op(EVTCHNOP_close, &close));
69 #ifdef CONFIG_PM_SLEEP
70 #include <linux/syscore_ops.h>
72 static void __cpuinit spinlock_resume(void)
76 for_each_online_cpu(cpu) {
77 per_cpu(poll_evtchn, cpu) = 0;
78 xen_spinlock_init(cpu);
82 static struct syscore_ops __cpuinitdata spinlock_syscore_ops = {
83 .resume = spinlock_resume
86 static int __init spinlock_register(void)
88 if (!is_initial_xendomain())
89 register_syscore_ops(&spinlock_syscore_ops);
92 core_initcall(spinlock_register);
95 static inline void sequence(unsigned int bias)
97 unsigned int rm_idx = percpu_read(rm_seq.idx);
100 percpu_write(rm_seq.idx, (rm_idx + bias) ^ (SEQ_REMOVE_BIAS / 2));
103 while (percpu_read(rm_seq.ctr[rm_idx].counter))
107 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING
108 static DEFINE_PER_CPU(unsigned int, _irq_count);
110 static __ticket_t spin_adjust(struct spinning *spinning,
111 const arch_spinlock_t *lock,
114 for (; spinning; spinning = spinning->prev) {
115 unsigned int old = spinning->ticket;
117 if (spinning->lock != lock)
119 while (likely(old + 1)) {
122 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING > 1
123 ticket = spin_adjust(spinning->prev, lock, ticket);
125 cur = cmpxchg(&spinning->ticket, old, ticket);
130 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING == 1
137 struct __raw_tickets xen_spin_adjust(const arch_spinlock_t *lock,
138 struct __raw_tickets token)
140 token.tail = spin_adjust(percpu_read(_spinning), lock, token.tail);
141 token.head = ACCESS_ONCE(lock->tickets.head);
145 static unsigned int ticket_drop(struct spinning *spinning,
146 unsigned int ticket, unsigned int cpu)
148 arch_spinlock_t *lock = spinning->lock;
150 if (cmpxchg(&spinning->ticket, ticket, -1) != ticket)
153 __add(&lock->tickets.head, 1, UNLOCK_LOCK_PREFIX);
154 ticket = (__ticket_t)(ticket + 1);
155 return ticket != lock->tickets.tail ? ticket : -1;
158 static unsigned int ticket_get(arch_spinlock_t *lock, struct spinning *prev)
160 struct __raw_tickets token = xadd(&lock->tickets,
161 (struct __raw_tickets){ .tail = 1 });
163 return token.head == token.tail ? token.tail
164 : spin_adjust(prev, lock, token.tail);
167 void xen_spin_irq_enter(void)
169 struct spinning *spinning = percpu_read(_spinning);
170 unsigned int cpu = raw_smp_processor_id();
172 percpu_inc(_irq_count);
174 for (; spinning; spinning = spinning->prev) {
175 arch_spinlock_t *lock = spinning->lock;
178 * Return the ticket if we now own the lock. While just being
179 * desirable generally (to reduce latency on spinning CPUs),
180 * this is essential in the case where interrupts get
181 * re-enabled in xen_spin_wait().
182 * Try to get a new ticket right away (to reduce latency after
183 * the current lock was released), but don't acquire the lock.
185 while (lock->tickets.head == spinning->ticket) {
186 unsigned int ticket = ticket_drop(spinning,
192 xen_spin_kick(lock, ticket);
193 spinning->ticket = ticket_get(lock, spinning->prev);
199 void xen_spin_irq_exit(void)
201 struct spinning *spinning = percpu_read(_spinning);
202 unsigned int cpu = raw_smp_processor_id();
204 * Despite its counterpart being first in xen_spin_irq_enter() (to make
205 * xen_spin_kick() properly handle locks that get owned after their
206 * tickets were obtained there), it can validly be done first here:
207 * We're guaranteed to see another invocation of xen_spin_irq_enter()
208 * if any of the tickets need to be dropped again.
210 unsigned int irq_count = this_cpu_dec_return(_irq_count);
213 * Make sure all xen_spin_kick() instances which may still have seen
214 * our old IRQ count exit their critical region (so that we won't fail
215 * to re-obtain a ticket if ticket_drop() completes only after our
216 * ticket check below).
221 * Obtain new tickets for (or acquire) all those locks at the IRQ
222 * nesting level we are about to return to where above we avoided
225 for (; spinning; spinning = spinning->prev) {
226 arch_spinlock_t *lock = spinning->lock;
228 if (spinning->irq_count < irq_count)
230 if (spinning->ticket + 1)
232 spinning->ticket = ticket_get(lock, spinning->prev);
233 if (ACCESS_ONCE(lock->tickets.head) == spinning->ticket)
239 unsigned int xen_spin_wait(arch_spinlock_t *lock, struct __raw_tickets *ptok,
242 unsigned int cpu = raw_smp_processor_id();
243 typeof(vcpu_info(0)->evtchn_upcall_mask) upcall_mask
244 = arch_local_save_flags();
245 struct spinning spinning;
247 /* If kicker interrupt not initialized yet, just spin. */
248 if (unlikely(!cpu_online(cpu))
249 || unlikely(!this_cpu_read(poll_evtchn)))
252 /* announce we're spinning */
253 spinning.ticket = ptok->tail;
254 spinning.lock = lock;
255 spinning.prev = percpu_read(_spinning);
256 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING
257 spinning.irq_count = UINT_MAX;
258 if (upcall_mask > flags) {
259 const struct spinning *other;
260 int nesting = CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING;
262 for (other = spinning.prev; other; other = other->prev)
263 if (other->lock == lock && !--nesting) {
268 arch_local_irq_disable();
271 percpu_write(_spinning, &spinning);
274 clear_evtchn(percpu_read(poll_evtchn));
277 * Check again to make sure it didn't become free while
278 * we weren't looking.
280 if (lock->tickets.head == spinning.ticket) {
282 * If we interrupted another spinlock while it was
283 * blocking, make sure it doesn't block (again)
284 * without rechecking the lock.
287 set_evtchn(percpu_read(poll_evtchn));
291 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING
292 if (upcall_mask > flags) {
293 spinning.irq_count = percpu_read(_irq_count);
295 arch_local_irq_restore(flags);
299 if (!test_evtchn(percpu_read(poll_evtchn)) &&
300 HYPERVISOR_poll_no_timeout(&__get_cpu_var(poll_evtchn), 1))
303 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING
304 arch_local_irq_disable();
306 spinning.irq_count = UINT_MAX;
309 if (test_evtchn(percpu_read(poll_evtchn))) {
310 inc_irq_stat(irq_lock_count);
316 * Leave the event pending so that any interrupted blocker will
320 /* announce we're done */
321 percpu_write(_spinning, spinning.prev);
322 if (!CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING)
323 arch_local_irq_disable();
324 sequence(SEQ_REMOVE_BIAS);
325 arch_local_irq_restore(upcall_mask);
327 if (lock->tickets.head == spinning.ticket) {
331 BUG_ON(CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING && !(spinning.ticket + 1));
332 ptok->head = lock->tickets.head;
333 ptok->tail = spinning.ticket;
338 void xen_spin_kick(const arch_spinlock_t *lock, unsigned int ticket)
340 unsigned int cpu = raw_smp_processor_id(), anchor = cpu;
342 if (unlikely(!cpu_online(cpu)))
343 cpu = -1, anchor = nr_cpu_ids;
345 while ((cpu = cpumask_next(cpu, cpu_online_mask)) != anchor) {
348 struct spinning *spinning;
350 if (cpu >= nr_cpu_ids) {
351 if (anchor == nr_cpu_ids)
353 cpu = cpumask_first(cpu_online_mask);
358 flags = arch_local_irq_save();
360 unsigned int rm_idx = per_cpu(rm_seq.idx, cpu);
362 rm_ctr = per_cpu(rm_seq.ctr, cpu) + (rm_idx & 1);
364 #ifdef CONFIG_X86 /* atomic ops are full CPU barriers */
369 spinning = per_cpu(_spinning, cpu);
371 if ((rm_idx ^ per_cpu(rm_seq.idx, cpu))
375 if (!vcpu_running(cpu))
379 for (; spinning; spinning = spinning->prev)
380 if (spinning->lock == lock &&
381 spinning->ticket == ticket) {
382 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING
383 ticket = spinning->irq_count
384 < per_cpu(_irq_count, cpu)
385 ? ticket_drop(spinning, ticket, cpu) : -2;
391 arch_local_irq_restore(flags);
393 if (unlikely(spinning)) {
394 #if CONFIG_XEN_SPINLOCK_ACQUIRE_NESTING
398 cpu = anchor < nr_cpu_ids ? anchor : -1;
402 notify_remote_via_evtchn(per_cpu(poll_evtchn, cpu));
407 EXPORT_SYMBOL(xen_spin_kick);
409 #endif /* TICKET_SHIFT */