21474bad39d1666ad55e34bac47a835794f65da2
[pintos-anon] / src / misc / checkbochs.patch
1 This patch must be applied to Pintos before Checkbochs may be usefully
2 applied to it.  To apply it, `cd' to pintos/src and type
3         patch -p2 < misc/checkbochs.patch
4
5 Written by Sorav Bansal <sbansal@stanford.edu>.
6 Modified by Ben Pfaff <blp@cs.stanford.edu>.
7
8 diff -X ignore -urpN pintos.orig/src/lib/debug.h pintos.eraser/src/lib/debug.h
9 --- pintos.orig/src/lib/debug.h 2005-06-18 20:20:49.000000000 -0700
10 +++ pintos.eraser/src/lib/debug.h       2005-06-29 22:38:01.000000000 -0700
11 @@ -1,6 +1,8 @@
12  #ifndef __LIB_DEBUG_H
13  #define __LIB_DEBUG_H
14  
15 +#include <eraser.h>
16 +
17  /* GCC lets us add "attributes" to functions, function
18     parameters, etc. to indicate their properties.
19     See the GCC manual for details. */
20 @@ -27,10 +29,13 @@ void debug_backtrace (void);
21  #undef NOT_REACHED
22  
23  #ifndef NDEBUG
24 -#define ASSERT(CONDITION)                                       \
25 -        if (CONDITION) { } else {                               \
26 -                PANIC ("assertion `%s' failed.", #CONDITION);   \
27 -        }
28 +#define ASSERT(CONDITION)                                               \
29 +        do {                                                            \
30 +          eraser_ignore_on ();                                         \
31 +          if (!(CONDITION))                                             \
32 +            PANIC ("assertion `%s' failed.", #CONDITION);               \
33 +          eraser_ignore_off ();                                         \
34 +        } while (0)
35  #define NOT_REACHED() PANIC ("executed an unreachable statement");
36  #else
37  #define ASSERT(CONDITION) ((void) 0)
38 diff -X ignore -urpN pintos.orig/src/lib/eraser.h pintos.eraser/src/lib/eraser.h
39 --- pintos.orig/src/lib/eraser.h        1969-12-31 16:00:00.000000000 -0800
40 +++ pintos.eraser/src/lib/eraser.h      2005-07-02 16:12:28.000000000 -0700
41 @@ -0,0 +1,115 @@
42 +#ifndef __LIB_ERASER_H
43 +#define __LIB_ERASER_H
44 +
45 +/* New instruction to indicate the lock at ECX is locked. */
46 +#define ERASER_LOCK ".byte 0x0f, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00;"
47 +
48 +/* New instruction to indicate the lock at ECX is unlocked. */
49 +#define ERASER_UNLOCK ".byte 0x0f, 0x04, 0x18, 0x00, 0x00, 0x00, 0x00;"
50 +
51 +/* New instruction for various Eraser purposes.
52 +   EAX indicates an operation subcode.
53 +   ECX, EDX may be used for arguments. */
54 +#define ERASER_OPS ".byte 0x0f, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00;"
55 +
56 +/* Operation subcodes for ERASER_OPS. */
57 +#define ERASER_OP_IGNORE        0 /* Suppress warnings for ECX bytes at EDX. */
58 +#define ERASER_OP_INIT_LOCK     1 /* New lock at ECX. */
59 +#define ERASER_OP_IGNORE_ON     2 /* Suppress all warnings. */
60 +#define ERASER_OP_IGNORE_OFF    3 /* Re-enable warnings. */
61 +#define ERASER_OP_REUSE         4 /* ECX bytes at EDX are (re)allocated. */
62 +#define ERASER_OP_DBG_MARK      5 /* Debug message for file EDX, line ECX. */
63 +#define ERASER_OP_STARTUP       6 /* Start tracking locks. */
64 +
65 +/* Returns true if running under Checkbochs, false otherwise. */
66 +static inline bool
67 +running_on_checkbochs (void)
68 +{
69 +  unsigned dummy, cpuid;
70 +  asm ("cpuid"
71 +       : "=a" (dummy), "=b" (cpuid)
72 +       : "0" (3), "1" (0)
73 +       : "ecx", "edx");
74 +  return cpuid == 0x6e696154;
75 +}
76 +
77 +/* Registers LOCK as a lock. */
78 +static inline void
79 +eraser_init (unsigned lock)
80 +{
81 +  if (running_on_checkbochs ())
82 +    asm volatile (ERASER_OPS :: "a" (ERASER_OP_INIT_LOCK), "c" (lock));
83 +}
84 +
85 +/* Indicates that LOCK is locked. */
86 +static inline void
87 +eraser_lock (unsigned lock)
88 +{
89 +  if (running_on_checkbochs ())
90 +    {
91 +      asm volatile (ERASER_LOCK :: "c" (lock));
92 +      eraser_ignore ((void *) lock, 4);
93 +    }
94 +}
95 +
96 +/* Indicates that LOCK is unlocked. */
97 +static inline void
98 +eraser_unlock (unsigned lock)
99 +{
100 +  if (running_on_checkbochs ())
101 +    asm volatile (ERASER_UNLOCK :: "c" (lock));
102 +}
103 +
104 +/* Suppresses warnings for LENGTH bytes starting at START. */
105 +static inline void
106 +eraser_ignore (void *start, size_t length)
107 +{
108 +  if (running_on_checkbochs ())
109 +    asm volatile (ERASER_OPS
110 +                  :: "a" (ERASER_OP_IGNORE), "d" (start), "c" (length));
111 +}
112 +
113 +/* Suppresses all warnings. */
114 +static inline void
115 +eraser_ignore_on (void)
116 +{
117 +  if (running_on_checkbochs ())
118 +    asm volatile (ERASER_OPS :: "a" (ERASER_OP_IGNORE_ON));
119 +}
120 +
121 +/* Re-enables warnings. */
122 +static inline void
123 +eraser_ignore_off (void)
124 +{
125 +  if (running_on_checkbochs ())
126 +    asm volatile (ERASER_OPS :: "a" (ERASER_OP_IGNORE_OFF));
127 +}
128 +
129 +/* Indicates that LENGTH bytes starting at START have been
130 +   (re)allocated. */
131 +static inline void
132 +eraser_reuse (void *start, size_t length)
133 +{
134 +  if (running_on_checkbochs ())
135 +    asm volatile (ERASER_OPS
136 +                  :: "a" (ERASER_OP_REUSE), "d" (start), "c" (length));
137 +}
138 +
139 +/* Emits a debug message for the source file and line number of
140 +   the caller. */
141 +#define eraser_debug_mark() do {                        \
142 +  if (running_on_checkbochs ())                         \
143 +    asm volatile (ERASER_OPS                            \
144 +                  :: "a" (ERASER_OP_DBG_MARK),          \
145 +                     "d" (__FILE__), "c" (__LINE__));   \
146 +} while (0)
147 +
148 +/* Starts up the lock checking algorithm. */
149 +static inline void
150 +eraser_startup (void)
151 +{
152 +  if (running_on_checkbochs ())
153 +    asm volatile (ERASER_OPS :: "a" (ERASER_OP_STARTUP));
154 +}
155 +
156 +#endif /* lib/eraser.h */
157 diff -X ignore -urpN pintos.orig/src/threads/init.c pintos.eraser/src/threads/init.c
158 --- pintos.orig/src/threads/init.c      2005-06-18 20:21:19.000000000 -0700
159 +++ pintos.eraser/src/threads/init.c    2005-07-02 16:13:32.000000000 -0700
160 @@ -132,6 +132,8 @@ main (void)
161  #endif
162  
163    printf ("Boot complete.\n");
164 +
165 +  eraser_startup ();
166    
167    /* Run actions specified on kernel command line. */
168    run_actions (argv);
169 diff -X ignore -urpN pintos.orig/src/threads/interrupt.c pintos.eraser/src/threads/interrupt.c
170 --- pintos.orig/src/threads/interrupt.c 2005-06-18 20:21:19.000000000 -0700
171 +++ pintos.eraser/src/threads/interrupt.c       2005-06-29 22:38:37.000000000 -0700
172 @@ -135,6 +135,8 @@ intr_init (void)
173    intr_names[17] = "#AC Alignment Check Exception";
174    intr_names[18] = "#MC Machine-Check Exception";
175    intr_names[19] = "#XF SIMD Floating-Point Exception";
176 +
177 +  eraser_ignore (&in_external_intr, 4);
178  }
179  
180  /* Registers interrupt VEC_NO to invoke HANDLER with descriptor
181 diff -X ignore -urpN pintos.orig/src/threads/malloc.c pintos.eraser/src/threads/malloc.c
182 --- pintos.orig/src/threads/malloc.c    2005-06-18 20:21:19.000000000 -0700
183 +++ pintos.eraser/src/threads/malloc.c  2005-07-02 16:17:07.000000000 -0700
184 @@ -150,6 +150,7 @@ malloc (size_t size) 
185    a = block_to_arena (b);
186    a->free_cnt--;
187    lock_release (&d->lock);
188 +  eraser_reuse (b, size);
189    return b;
190  }
191  
192 @@ -171,6 +172,7 @@ calloc (size_t a, size_t b) 
193    if (p != NULL)
194      memset (p, 0, size);
195  
196 +  eraser_reuse (p, size);
197    return p;
198  }
199  
200 @@ -228,6 +230,7 @@ free (void *p) 
201          {
202            /* It's a normal block.  We handle it here. */
203  
204 +          eraser_reuse (b, d->block_size);
205  #ifndef NDEBUG
206            /* Clear the block to help detect use-after-free bugs. */
207            memset (b, 0xcc, d->block_size);
208 diff -X ignore -urpN pintos.orig/src/threads/palloc.c pintos.eraser/src/threads/palloc.c
209 --- pintos.orig/src/threads/palloc.c    2005-06-18 20:21:19.000000000 -0700
210 +++ pintos.eraser/src/threads/palloc.c  2005-07-02 16:16:18.000000000 -0700
211 @@ -104,6 +104,7 @@ palloc_get_multiple (enum palloc_flags f
212          PANIC ("palloc_get: out of pages");
213      }
214  
215 +  eraser_reuse (pages, PGSIZE * page_cnt);
216    return pages;
217  }
218  
219 @@ -139,6 +140,7 @@ palloc_free_multiple (void *pages, size_
220  
221    page_idx = pg_no (pages) - pg_no (pool->base);
222  
223 +  eraser_reuse (pages, PGSIZE * page_cnt);
224  #ifndef NDEBUG
225    memset (pages, 0xcc, PGSIZE * page_cnt);
226  #endif
227 diff -X ignore -urpN pintos.orig/src/threads/synch.c pintos.eraser/src/threads/synch.c
228 --- pintos.orig/src/threads/synch.c     2005-06-18 20:21:19.000000000 -0700
229 +++ pintos.eraser/src/threads/synch.c   2005-06-29 22:48:42.000000000 -0700
230 @@ -179,6 +179,7 @@ lock_init (struct lock *lock)
231  
232    lock->holder = NULL;
233    sema_init (&lock->semaphore, 1);
234 +  eraser_init (lock);
235  }
236  
237  /* Acquires LOCK, sleeping until it becomes available if
238 @@ -200,6 +201,7 @@ lock_acquire (struct lock *lock)
239  
240    old_level = intr_disable ();
241    sema_down (&lock->semaphore);
242 +  eraser_lock (lock);
243    lock->holder = thread_current ();
244    intr_set_level (old_level);
245  }
246 @@ -245,6 +247,7 @@ lock_release (struct lock *lock) 
247    lock->holder = NULL;
248    sema_up (&lock->semaphore);
249    intr_set_level (old_level);
250 +  eraser_unlock (lock);
251  }
252  
253  /* Returns true if the current thread holds LOCK, false
254 @@ -253,9 +256,15 @@ lock_release (struct lock *lock) 
255  bool
256  lock_held_by_current_thread (const struct lock *lock) 
257  {
258 +  bool ret;
259 +
260    ASSERT (lock != NULL);
261  
262 -  return lock->holder == thread_current ();
263 +  eraser_ignore_on ();
264 +  ret = lock->holder == thread_current ();
265 +  eraser_ignore_off ();
266 +
267 +  return ret;
268  }
269  \f
270  /* One semaphore in a list. */
271 diff -X ignore -urpN pintos.orig/src/threads/thread.c pintos.eraser/src/threads/thread.c
272 --- pintos.orig/src/threads/thread.c    2005-06-18 20:21:20.000000000 -0700
273 +++ pintos.eraser/src/threads/thread.c  2005-07-02 16:16:03.000000000 -0700
274 @@ -85,6 +85,7 @@ thread_init (void) 
275    init_thread (initial_thread, "main", PRI_DEFAULT);
276    initial_thread->status = THREAD_RUNNING;
277    initial_thread->tid = allocate_tid ();
278 +  eraser_ignore (&initial_thread->status, 4);
279  }
280  
281  /* Starts preemptive thread scheduling by enabling interrupts.
282 @@ -157,6 +158,9 @@ thread_create (const char *name, int pri
283    if (t == NULL)
284      return TID_ERROR;
285  
286 +  eraser_ignore (&t->status, 4);
287 +  eraser_ignore_on ();
288 +
289    /* Initialize thread. */
290    init_thread (t, name, priority);
291    tid = t->tid = allocate_tid ();
292 @@ -175,6 +179,8 @@ thread_create (const char *name, int pri
293    sf = alloc_frame (t, sizeof *sf);
294    sf->eip = switch_entry;
295  
296 +  eraser_ignore_off ();
297 +
298    /* Add to run queue. */
299    thread_unblock (t);
300  
301 @@ -361,6 +367,7 @@ kernel_thread (thread_func *function, vo
302  {
303    ASSERT (function != NULL);
304  
305 +  eraser_lock (thread_current ()->tid);
306    intr_enable ();       /* The scheduler runs with interrupts off. */
307    function (aux);       /* Execute the thread function. */
308    thread_exit ();       /* If function() returns, kill the thread. */
309 @@ -396,12 +403,16 @@ init_thread (struct thread *t, const cha
310    ASSERT (PRI_MIN <= priority && priority <= PRI_MAX);
311    ASSERT (name != NULL);
312  
313 +  eraser_ignore_on ();
314 +
315    memset (t, 0, sizeof *t);
316    t->status = THREAD_BLOCKED;
317    strlcpy (t->name, name, sizeof t->name);
318    t->stack = (uint8_t *) t + PGSIZE;
319    t->priority = priority;
320    t->magic = THREAD_MAGIC;
321 +
322 +  eraser_ignore_off ();
323  }
324  
325  /* Allocates a SIZE-byte frame at the top of thread T's stack and
326 @@ -471,7 +482,7 @@ schedule_tail (struct thread *prev) 
327    if (prev != NULL && prev->status == THREAD_DYING) 
328      {
329        ASSERT (prev != cur);
330 -      if (prev != initial_thread)
331 +      if (prev != initial_thread) 
332          palloc_free_page (prev);
333      }
334  }
335 diff -X ignore -urpN pintos.orig/src/userprog/tss.c pintos.eraser/src/userprog/tss.c
336 --- pintos.orig/src/userprog/tss.c      2004-09-22 17:58:29.000000000 -0700
337 +++ pintos.eraser/src/userprog/tss.c    2005-06-29 22:41:09.000000000 -0700
338 @@ -84,6 +84,8 @@ tss_init (void) 
339    tss->esp0 = ptov(0x20000);
340    tss->ss0 = SEL_KDSEG;
341    tss->bitmap = 0xdfff;
342 +
343 +  eraser_ignore (tss, sizeof *tss);
344  }
345  
346  /* Returns the kernel TSS. */