debuggers.hg

view xen/arch/x86/flushtlb.c @ 3674:fb875591fd72

bitkeeper revision 1.1159.223.63 (42028527-fv-d9BM0_LRp8UKGP19gQ)

Fix NMI deferral.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Thu Feb 03 20:10:15 2005 +0000 (2005-02-03)
parents 2c7a372de2d0
children 0a4b76b6b5a0
line source
1 /******************************************************************************
2 * flushtlb.c
3 *
4 * TLB flushes are timestamped using a global virtual 'clock' which ticks
5 * on any TLB flush on any processor.
6 *
7 * Copyright (c) 2003-2004, K A Fraser
8 */
10 #include <xen/config.h>
11 #include <xen/sched.h>
12 #include <xen/softirq.h>
13 #include <asm/flushtlb.h>
15 /* Debug builds: Wrap frequently to stress-test the wrap logic. */
16 #ifdef NDEBUG
17 #define WRAP_MASK (0xFFFFFFFFU)
18 #else
19 #define WRAP_MASK (0x000003FFU)
20 #endif
22 u32 tlbflush_clock = 1U;
23 u32 tlbflush_time[NR_CPUS];
25 void write_cr3(unsigned long cr3)
26 {
27 u32 t, t1, t2;
28 unsigned long flags;
30 /* This non-reentrant function is sometimes called in interrupt context. */
31 local_irq_save(flags);
33 /*
34 * STEP 1. Increment the virtual clock *before* flushing the TLB.
35 * If we do it after, we race other CPUs invalidating PTEs.
36 * (e.g., a page invalidated after the flush might get the old
37 * timestamp, but this CPU can speculatively fetch the mapping
38 * into its TLB after the flush but before inc'ing the clock).
39 */
41 t = tlbflush_clock;
42 do {
43 t1 = t2 = t;
44 /* Clock wrapped: someone else is leading a global TLB shootdown. */
45 if ( unlikely(t1 == 0) )
46 goto skip_clocktick;
47 t2 = (t + 1) & WRAP_MASK;
48 }
49 while ( unlikely((t = cmpxchg(&tlbflush_clock, t1, t2)) != t1) );
51 /* Clock wrapped: we will lead a global TLB shootdown. */
52 if ( unlikely(t2 == 0) )
53 raise_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ);
55 /*
56 * STEP 2. Update %CR3, thereby flushing the TLB.
57 */
59 skip_clocktick:
60 __asm__ __volatile__ ( "mov"__OS" %0, %%cr3" : : "r" (cr3) : "memory" );
62 /*
63 * STEP 3. Update this CPU's timestamp. Note that this happens *after*
64 * flushing the TLB, as otherwise we can race a NEED_FLUSH() test
65 * on another CPU. (e.g., other CPU sees the updated CPU stamp and
66 * so does not force a synchronous TLB flush, but the flush in this
67 * function hasn't yet occurred and so the TLB might be stale).
68 * The ordering would only actually matter if this function were
69 * interruptible, and something that abuses the stale mapping could
70 * exist in an interrupt handler. In fact neither of these is the
71 * case, so really we are being ultra paranoid.
72 */
74 tlbflush_time[smp_processor_id()] = t2;
76 local_irq_restore(flags);
77 }