Merge commit 'v2.6.28-rc6' into irq/urgent
[linux-2.6] / arch / x86 / kernel / ds.c
1 /*
2  * Debug Store support
3  *
4  * This provides a low-level interface to the hardware's Debug Store
5  * feature that is used for branch trace store (BTS) and
6  * precise-event based sampling (PEBS).
7  *
8  * It manages:
9  * - per-thread and per-cpu allocation of BTS and PEBS
10  * - buffer memory allocation (optional)
11  * - buffer overflow handling
12  * - buffer access
13  *
14  * It assumes:
15  * - get_task_struct on all parameter tasks
16  * - current is allowed to trace parameter tasks
17  *
18  *
19  * Copyright (C) 2007-2008 Intel Corporation.
20  * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008
21  */
22
23
24 #ifdef CONFIG_X86_DS
25
26 #include <asm/ds.h>
27
28 #include <linux/errno.h>
29 #include <linux/string.h>
30 #include <linux/slab.h>
31 #include <linux/sched.h>
32 #include <linux/mm.h>
33
34
35 /*
36  * The configuration for a particular DS hardware implementation.
37  */
38 struct ds_configuration {
39         /* the size of the DS structure in bytes */
40         unsigned char  sizeof_ds;
41         /* the size of one pointer-typed field in the DS structure in bytes;
42            this covers the first 8 fields related to buffer management. */
43         unsigned char  sizeof_field;
44         /* the size of a BTS/PEBS record in bytes */
45         unsigned char  sizeof_rec[2];
46 };
47 static struct ds_configuration ds_cfg;
48
49
50 /*
51  * Debug Store (DS) save area configuration (see Intel64 and IA32
52  * Architectures Software Developer's Manual, section 18.5)
53  *
54  * The DS configuration consists of the following fields; different
55  * architetures vary in the size of those fields.
56  * - double-word aligned base linear address of the BTS buffer
57  * - write pointer into the BTS buffer
58  * - end linear address of the BTS buffer (one byte beyond the end of
59  *   the buffer)
60  * - interrupt pointer into BTS buffer
61  *   (interrupt occurs when write pointer passes interrupt pointer)
62  * - double-word aligned base linear address of the PEBS buffer
63  * - write pointer into the PEBS buffer
64  * - end linear address of the PEBS buffer (one byte beyond the end of
65  *   the buffer)
66  * - interrupt pointer into PEBS buffer
67  *   (interrupt occurs when write pointer passes interrupt pointer)
68  * - value to which counter is reset following counter overflow
69  *
70  * Later architectures use 64bit pointers throughout, whereas earlier
71  * architectures use 32bit pointers in 32bit mode.
72  *
73  *
74  * We compute the base address for the first 8 fields based on:
75  * - the field size stored in the DS configuration
76  * - the relative field position
77  * - an offset giving the start of the respective region
78  *
79  * This offset is further used to index various arrays holding
80  * information for BTS and PEBS at the respective index.
81  *
82  * On later 32bit processors, we only access the lower 32bit of the
83  * 64bit pointer fields. The upper halves will be zeroed out.
84  */
85
86 enum ds_field {
87         ds_buffer_base = 0,
88         ds_index,
89         ds_absolute_maximum,
90         ds_interrupt_threshold,
91 };
92
93 enum ds_qualifier {
94         ds_bts  = 0,
95         ds_pebs
96 };
97
98 static inline unsigned long ds_get(const unsigned char *base,
99                                    enum ds_qualifier qual, enum ds_field field)
100 {
101         base += (ds_cfg.sizeof_field * (field + (4 * qual)));
102         return *(unsigned long *)base;
103 }
104
105 static inline void ds_set(unsigned char *base, enum ds_qualifier qual,
106                           enum ds_field field, unsigned long value)
107 {
108         base += (ds_cfg.sizeof_field * (field + (4 * qual)));
109         (*(unsigned long *)base) = value;
110 }
111
112
113 /*
114  * Locking is done only for allocating BTS or PEBS resources and for
115  * guarding context and buffer memory allocation.
116  *
117  * Most functions require the current task to own the ds context part
118  * they are going to access. All the locking is done when validating
119  * access to the context.
120  */
121 static spinlock_t ds_lock = __SPIN_LOCK_UNLOCKED(ds_lock);
122
123 /*
124  * Validate that the current task is allowed to access the BTS/PEBS
125  * buffer of the parameter task.
126  *
127  * Returns 0, if access is granted; -Eerrno, otherwise.
128  */
129 static inline int ds_validate_access(struct ds_context *context,
130                                      enum ds_qualifier qual)
131 {
132         if (!context)
133                 return -EPERM;
134
135         if (context->owner[qual] == current)
136                 return 0;
137
138         return -EPERM;
139 }
140
141
142 /*
143  * We either support (system-wide) per-cpu or per-thread allocation.
144  * We distinguish the two based on the task_struct pointer, where a
145  * NULL pointer indicates per-cpu allocation for the current cpu.
146  *
147  * Allocations are use-counted. As soon as resources are allocated,
148  * further allocations must be of the same type (per-cpu or
149  * per-thread). We model this by counting allocations (i.e. the number
150  * of tracers of a certain type) for one type negatively:
151  *   =0  no tracers
152  *   >0  number of per-thread tracers
153  *   <0  number of per-cpu tracers
154  *
155  * The below functions to get and put tracers and to check the
156  * allocation type require the ds_lock to be held by the caller.
157  *
158  * Tracers essentially gives the number of ds contexts for a certain
159  * type of allocation.
160  */
161 static long tracers;
162
163 static inline void get_tracer(struct task_struct *task)
164 {
165         tracers += (task ? 1 : -1);
166 }
167
168 static inline void put_tracer(struct task_struct *task)
169 {
170         tracers -= (task ? 1 : -1);
171 }
172
173 static inline int check_tracer(struct task_struct *task)
174 {
175         return (task ? (tracers >= 0) : (tracers <= 0));
176 }
177
178
179 /*
180  * The DS context is either attached to a thread or to a cpu:
181  * - in the former case, the thread_struct contains a pointer to the
182  *   attached context.
183  * - in the latter case, we use a static array of per-cpu context
184  *   pointers.
185  *
186  * Contexts are use-counted. They are allocated on first access and
187  * deallocated when the last user puts the context.
188  *
189  * We distinguish between an allocating and a non-allocating get of a
190  * context:
191  * - the allocating get is used for requesting BTS/PEBS resources. It
192  *   requires the caller to hold the global ds_lock.
193  * - the non-allocating get is used for all other cases. A
194  *   non-existing context indicates an error. It acquires and releases
195  *   the ds_lock itself for obtaining the context.
196  *
197  * A context and its DS configuration are allocated and deallocated
198  * together. A context always has a DS configuration of the
199  * appropriate size.
200  */
201 static DEFINE_PER_CPU(struct ds_context *, system_context);
202
203 #define this_system_context per_cpu(system_context, smp_processor_id())
204
205 /*
206  * Returns the pointer to the parameter task's context or to the
207  * system-wide context, if task is NULL.
208  *
209  * Increases the use count of the returned context, if not NULL.
210  */
211 static inline struct ds_context *ds_get_context(struct task_struct *task)
212 {
213         struct ds_context *context;
214
215         spin_lock(&ds_lock);
216
217         context = (task ? task->thread.ds_ctx : this_system_context);
218         if (context)
219                 context->count++;
220
221         spin_unlock(&ds_lock);
222
223         return context;
224 }
225
226 /*
227  * Same as ds_get_context, but allocates the context and it's DS
228  * structure, if necessary; returns NULL; if out of memory.
229  *
230  * pre: requires ds_lock to be held
231  */
232 static inline struct ds_context *ds_alloc_context(struct task_struct *task)
233 {
234         struct ds_context **p_context =
235                 (task ? &task->thread.ds_ctx : &this_system_context);
236         struct ds_context *context = *p_context;
237
238         if (!context) {
239                 spin_unlock(&ds_lock);
240
241                 context = kzalloc(sizeof(*context), GFP_KERNEL);
242
243                 if (!context) {
244                         spin_lock(&ds_lock);
245                         return NULL;
246                 }
247
248                 context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL);
249                 if (!context->ds) {
250                         kfree(context);
251                         spin_lock(&ds_lock);
252                         return NULL;
253                 }
254
255                 spin_lock(&ds_lock);
256                 /*
257                  * Check for race - another CPU could have allocated
258                  * it meanwhile:
259                  */
260                 if (*p_context) {
261                         kfree(context->ds);
262                         kfree(context);
263                         return *p_context;
264                 }
265
266                 *p_context = context;
267
268                 context->this = p_context;
269                 context->task = task;
270
271                 if (task)
272                         set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
273
274                 if (!task || (task == current))
275                         wrmsr(MSR_IA32_DS_AREA, (unsigned long)context->ds, 0);
276
277                 get_tracer(task);
278         }
279
280         context->count++;
281
282         return context;
283 }
284
285 /*
286  * Decreases the use count of the parameter context, if not NULL.
287  * Deallocates the context, if the use count reaches zero.
288  */
289 static inline void ds_put_context(struct ds_context *context)
290 {
291         if (!context)
292                 return;
293
294         spin_lock(&ds_lock);
295
296         if (--context->count)
297                 goto out;
298
299         *(context->this) = NULL;
300
301         if (context->task)
302                 clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR);
303
304         if (!context->task || (context->task == current))
305                 wrmsrl(MSR_IA32_DS_AREA, 0);
306
307         put_tracer(context->task);
308
309         /* free any leftover buffers from tracers that did not
310          * deallocate them properly. */
311         kfree(context->buffer[ds_bts]);
312         kfree(context->buffer[ds_pebs]);
313         kfree(context->ds);
314         kfree(context);
315  out:
316         spin_unlock(&ds_lock);
317 }
318
319
320 /*
321  * Handle a buffer overflow
322  *
323  * task: the task whose buffers are overflowing;
324  *       NULL for a buffer overflow on the current cpu
325  * context: the ds context
326  * qual: the buffer type
327  */
328 static void ds_overflow(struct task_struct *task, struct ds_context *context,
329                         enum ds_qualifier qual)
330 {
331         if (!context)
332                 return;
333
334         if (context->callback[qual])
335                 (*context->callback[qual])(task);
336
337         /* todo: do some more overflow handling */
338 }
339
340
341 /*
342  * Allocate a non-pageable buffer of the parameter size.
343  * Checks the memory and the locked memory rlimit.
344  *
345  * Returns the buffer, if successful;
346  *         NULL, if out of memory or rlimit exceeded.
347  *
348  * size: the requested buffer size in bytes
349  * pages (out): if not NULL, contains the number of pages reserved
350  */
351 static inline void *ds_allocate_buffer(size_t size, unsigned int *pages)
352 {
353         unsigned long rlim, vm, pgsz;
354         void *buffer;
355
356         pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT;
357
358         rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
359         vm   = current->mm->total_vm  + pgsz;
360         if (rlim < vm)
361                 return NULL;
362
363         rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
364         vm   = current->mm->locked_vm  + pgsz;
365         if (rlim < vm)
366                 return NULL;
367
368         buffer = kzalloc(size, GFP_KERNEL);
369         if (!buffer)
370                 return NULL;
371
372         current->mm->total_vm  += pgsz;
373         current->mm->locked_vm += pgsz;
374
375         if (pages)
376                 *pages = pgsz;
377
378         return buffer;
379 }
380
381 static int ds_request(struct task_struct *task, void *base, size_t size,
382                       ds_ovfl_callback_t ovfl, enum ds_qualifier qual)
383 {
384         struct ds_context *context;
385         unsigned long buffer, adj;
386         const unsigned long alignment = (1 << 3);
387         int error = 0;
388
389         if (!ds_cfg.sizeof_ds)
390                 return -EOPNOTSUPP;
391
392         /* we require some space to do alignment adjustments below */
393         if (size < (alignment + ds_cfg.sizeof_rec[qual]))
394                 return -EINVAL;
395
396         /* buffer overflow notification is not yet implemented */
397         if (ovfl)
398                 return -EOPNOTSUPP;
399
400
401         spin_lock(&ds_lock);
402
403         error = -ENOMEM;
404         context = ds_alloc_context(task);
405         if (!context)
406                 goto out_unlock;
407
408         error = -EPERM;
409         if (!check_tracer(task))
410                 goto out_unlock;
411
412         error = -EALREADY;
413         if (context->owner[qual] == current)
414                 goto out_unlock;
415         error = -EPERM;
416         if (context->owner[qual] != NULL)
417                 goto out_unlock;
418         context->owner[qual] = current;
419
420         spin_unlock(&ds_lock);
421
422
423         error = -ENOMEM;
424         if (!base) {
425                 base = ds_allocate_buffer(size, &context->pages[qual]);
426                 if (!base)
427                         goto out_release;
428
429                 context->buffer[qual]   = base;
430         }
431         error = 0;
432
433         context->callback[qual] = ovfl;
434
435         /* adjust the buffer address and size to meet alignment
436          * constraints:
437          * - buffer is double-word aligned
438          * - size is multiple of record size
439          *
440          * We checked the size at the very beginning; we have enough
441          * space to do the adjustment.
442          */
443         buffer = (unsigned long)base;
444
445         adj = ALIGN(buffer, alignment) - buffer;
446         buffer += adj;
447         size   -= adj;
448
449         size /= ds_cfg.sizeof_rec[qual];
450         size *= ds_cfg.sizeof_rec[qual];
451
452         ds_set(context->ds, qual, ds_buffer_base, buffer);
453         ds_set(context->ds, qual, ds_index, buffer);
454         ds_set(context->ds, qual, ds_absolute_maximum, buffer + size);
455
456         if (ovfl) {
457                 /* todo: select a suitable interrupt threshold */
458         } else
459                 ds_set(context->ds, qual,
460                        ds_interrupt_threshold, buffer + size + 1);
461
462         /* we keep the context until ds_release */
463         return error;
464
465  out_release:
466         context->owner[qual] = NULL;
467         ds_put_context(context);
468         return error;
469
470  out_unlock:
471         spin_unlock(&ds_lock);
472         ds_put_context(context);
473         return error;
474 }
475
476 int ds_request_bts(struct task_struct *task, void *base, size_t size,
477                    ds_ovfl_callback_t ovfl)
478 {
479         return ds_request(task, base, size, ovfl, ds_bts);
480 }
481
482 int ds_request_pebs(struct task_struct *task, void *base, size_t size,
483                     ds_ovfl_callback_t ovfl)
484 {
485         return ds_request(task, base, size, ovfl, ds_pebs);
486 }
487
488 static int ds_release(struct task_struct *task, enum ds_qualifier qual)
489 {
490         struct ds_context *context;
491         int error;
492
493         context = ds_get_context(task);
494         error = ds_validate_access(context, qual);
495         if (error < 0)
496                 goto out;
497
498         kfree(context->buffer[qual]);
499         context->buffer[qual] = NULL;
500
501         current->mm->total_vm  -= context->pages[qual];
502         current->mm->locked_vm -= context->pages[qual];
503         context->pages[qual] = 0;
504         context->owner[qual] = NULL;
505
506         /*
507          * we put the context twice:
508          *   once for the ds_get_context
509          *   once for the corresponding ds_request
510          */
511         ds_put_context(context);
512  out:
513         ds_put_context(context);
514         return error;
515 }
516
517 int ds_release_bts(struct task_struct *task)
518 {
519         return ds_release(task, ds_bts);
520 }
521
522 int ds_release_pebs(struct task_struct *task)
523 {
524         return ds_release(task, ds_pebs);
525 }
526
527 static int ds_get_index(struct task_struct *task, size_t *pos,
528                         enum ds_qualifier qual)
529 {
530         struct ds_context *context;
531         unsigned long base, index;
532         int error;
533
534         context = ds_get_context(task);
535         error = ds_validate_access(context, qual);
536         if (error < 0)
537                 goto out;
538
539         base  = ds_get(context->ds, qual, ds_buffer_base);
540         index = ds_get(context->ds, qual, ds_index);
541
542         error = ((index - base) / ds_cfg.sizeof_rec[qual]);
543         if (pos)
544                 *pos = error;
545  out:
546         ds_put_context(context);
547         return error;
548 }
549
550 int ds_get_bts_index(struct task_struct *task, size_t *pos)
551 {
552         return ds_get_index(task, pos, ds_bts);
553 }
554
555 int ds_get_pebs_index(struct task_struct *task, size_t *pos)
556 {
557         return ds_get_index(task, pos, ds_pebs);
558 }
559
560 static int ds_get_end(struct task_struct *task, size_t *pos,
561                       enum ds_qualifier qual)
562 {
563         struct ds_context *context;
564         unsigned long base, end;
565         int error;
566
567         context = ds_get_context(task);
568         error = ds_validate_access(context, qual);
569         if (error < 0)
570                 goto out;
571
572         base = ds_get(context->ds, qual, ds_buffer_base);
573         end  = ds_get(context->ds, qual, ds_absolute_maximum);
574
575         error = ((end - base) / ds_cfg.sizeof_rec[qual]);
576         if (pos)
577                 *pos = error;
578  out:
579         ds_put_context(context);
580         return error;
581 }
582
583 int ds_get_bts_end(struct task_struct *task, size_t *pos)
584 {
585         return ds_get_end(task, pos, ds_bts);
586 }
587
588 int ds_get_pebs_end(struct task_struct *task, size_t *pos)
589 {
590         return ds_get_end(task, pos, ds_pebs);
591 }
592
593 static int ds_access(struct task_struct *task, size_t index,
594                      const void **record, enum ds_qualifier qual)
595 {
596         struct ds_context *context;
597         unsigned long base, idx;
598         int error;
599
600         if (!record)
601                 return -EINVAL;
602
603         context = ds_get_context(task);
604         error = ds_validate_access(context, qual);
605         if (error < 0)
606                 goto out;
607
608         base = ds_get(context->ds, qual, ds_buffer_base);
609         idx = base + (index * ds_cfg.sizeof_rec[qual]);
610
611         error = -EINVAL;
612         if (idx > ds_get(context->ds, qual, ds_absolute_maximum))
613                 goto out;
614
615         *record = (const void *)idx;
616         error = ds_cfg.sizeof_rec[qual];
617  out:
618         ds_put_context(context);
619         return error;
620 }
621
622 int ds_access_bts(struct task_struct *task, size_t index, const void **record)
623 {
624         return ds_access(task, index, record, ds_bts);
625 }
626
627 int ds_access_pebs(struct task_struct *task, size_t index, const void **record)
628 {
629         return ds_access(task, index, record, ds_pebs);
630 }
631
632 static int ds_write(struct task_struct *task, const void *record, size_t size,
633                     enum ds_qualifier qual, int force)
634 {
635         struct ds_context *context;
636         int error;
637
638         if (!record)
639                 return -EINVAL;
640
641         error = -EPERM;
642         context = ds_get_context(task);
643         if (!context)
644                 goto out;
645
646         if (!force) {
647                 error = ds_validate_access(context, qual);
648                 if (error < 0)
649                         goto out;
650         }
651
652         error = 0;
653         while (size) {
654                 unsigned long base, index, end, write_end, int_th;
655                 unsigned long write_size, adj_write_size;
656
657                 /*
658                  * write as much as possible without producing an
659                  * overflow interrupt.
660                  *
661                  * interrupt_threshold must either be
662                  * - bigger than absolute_maximum or
663                  * - point to a record between buffer_base and absolute_maximum
664                  *
665                  * index points to a valid record.
666                  */
667                 base   = ds_get(context->ds, qual, ds_buffer_base);
668                 index  = ds_get(context->ds, qual, ds_index);
669                 end    = ds_get(context->ds, qual, ds_absolute_maximum);
670                 int_th = ds_get(context->ds, qual, ds_interrupt_threshold);
671
672                 write_end = min(end, int_th);
673
674                 /* if we are already beyond the interrupt threshold,
675                  * we fill the entire buffer */
676                 if (write_end <= index)
677                         write_end = end;
678
679                 if (write_end <= index)
680                         goto out;
681
682                 write_size = min((unsigned long) size, write_end - index);
683                 memcpy((void *)index, record, write_size);
684
685                 record = (const char *)record + write_size;
686                 size  -= write_size;
687                 error += write_size;
688
689                 adj_write_size = write_size / ds_cfg.sizeof_rec[qual];
690                 adj_write_size *= ds_cfg.sizeof_rec[qual];
691
692                 /* zero out trailing bytes */
693                 memset((char *)index + write_size, 0,
694                        adj_write_size - write_size);
695                 index += adj_write_size;
696
697                 if (index >= end)
698                         index = base;
699                 ds_set(context->ds, qual, ds_index, index);
700
701                 if (index >= int_th)
702                         ds_overflow(task, context, qual);
703         }
704
705  out:
706         ds_put_context(context);
707         return error;
708 }
709
710 int ds_write_bts(struct task_struct *task, const void *record, size_t size)
711 {
712         return ds_write(task, record, size, ds_bts, /* force = */ 0);
713 }
714
715 int ds_write_pebs(struct task_struct *task, const void *record, size_t size)
716 {
717         return ds_write(task, record, size, ds_pebs, /* force = */ 0);
718 }
719
720 int ds_unchecked_write_bts(struct task_struct *task,
721                            const void *record, size_t size)
722 {
723         return ds_write(task, record, size, ds_bts, /* force = */ 1);
724 }
725
726 int ds_unchecked_write_pebs(struct task_struct *task,
727                             const void *record, size_t size)
728 {
729         return ds_write(task, record, size, ds_pebs, /* force = */ 1);
730 }
731
732 static int ds_reset_or_clear(struct task_struct *task,
733                              enum ds_qualifier qual, int clear)
734 {
735         struct ds_context *context;
736         unsigned long base, end;
737         int error;
738
739         context = ds_get_context(task);
740         error = ds_validate_access(context, qual);
741         if (error < 0)
742                 goto out;
743
744         base = ds_get(context->ds, qual, ds_buffer_base);
745         end  = ds_get(context->ds, qual, ds_absolute_maximum);
746
747         if (clear)
748                 memset((void *)base, 0, end - base);
749
750         ds_set(context->ds, qual, ds_index, base);
751
752         error = 0;
753  out:
754         ds_put_context(context);
755         return error;
756 }
757
758 int ds_reset_bts(struct task_struct *task)
759 {
760         return ds_reset_or_clear(task, ds_bts, /* clear = */ 0);
761 }
762
763 int ds_reset_pebs(struct task_struct *task)
764 {
765         return ds_reset_or_clear(task, ds_pebs, /* clear = */ 0);
766 }
767
768 int ds_clear_bts(struct task_struct *task)
769 {
770         return ds_reset_or_clear(task, ds_bts, /* clear = */ 1);
771 }
772
773 int ds_clear_pebs(struct task_struct *task)
774 {
775         return ds_reset_or_clear(task, ds_pebs, /* clear = */ 1);
776 }
777
778 int ds_get_pebs_reset(struct task_struct *task, u64 *value)
779 {
780         struct ds_context *context;
781         int error;
782
783         if (!value)
784                 return -EINVAL;
785
786         context = ds_get_context(task);
787         error = ds_validate_access(context, ds_pebs);
788         if (error < 0)
789                 goto out;
790
791         *value = *(u64 *)(context->ds + (ds_cfg.sizeof_field * 8));
792
793         error = 0;
794  out:
795         ds_put_context(context);
796         return error;
797 }
798
799 int ds_set_pebs_reset(struct task_struct *task, u64 value)
800 {
801         struct ds_context *context;
802         int error;
803
804         context = ds_get_context(task);
805         error = ds_validate_access(context, ds_pebs);
806         if (error < 0)
807                 goto out;
808
809         *(u64 *)(context->ds + (ds_cfg.sizeof_field * 8)) = value;
810
811         error = 0;
812  out:
813         ds_put_context(context);
814         return error;
815 }
816
817 static const struct ds_configuration ds_cfg_var = {
818         .sizeof_ds    = sizeof(long) * 12,
819         .sizeof_field = sizeof(long),
820         .sizeof_rec[ds_bts]   = sizeof(long) * 3,
821         .sizeof_rec[ds_pebs]  = sizeof(long) * 10
822 };
823 static const struct ds_configuration ds_cfg_64 = {
824         .sizeof_ds    = 8 * 12,
825         .sizeof_field = 8,
826         .sizeof_rec[ds_bts]   = 8 * 3,
827         .sizeof_rec[ds_pebs]  = 8 * 10
828 };
829
830 static inline void
831 ds_configure(const struct ds_configuration *cfg)
832 {
833         ds_cfg = *cfg;
834 }
835
836 void __cpuinit ds_init_intel(struct cpuinfo_x86 *c)
837 {
838         switch (c->x86) {
839         case 0x6:
840                 switch (c->x86_model) {
841                 case 0xD:
842                 case 0xE: /* Pentium M */
843                         ds_configure(&ds_cfg_var);
844                         break;
845                 case 0xF: /* Core2 */
846                 case 0x1C: /* Atom */
847                         ds_configure(&ds_cfg_64);
848                         break;
849                 default:
850                         /* sorry, don't know about them */
851                         break;
852                 }
853                 break;
854         case 0xF:
855                 switch (c->x86_model) {
856                 case 0x0:
857                 case 0x1:
858                 case 0x2: /* Netburst */
859                         ds_configure(&ds_cfg_var);
860                         break;
861                 default:
862                         /* sorry, don't know about them */
863                         break;
864                 }
865                 break;
866         default:
867                 /* sorry, don't know about them */
868                 break;
869         }
870 }
871
872 void ds_free(struct ds_context *context)
873 {
874         /* This is called when the task owning the parameter context
875          * is dying. There should not be any user of that context left
876          * to disturb us, anymore. */
877         unsigned long leftovers = context->count;
878         while (leftovers--)
879                 ds_put_context(context);
880 }
881 #endif /* CONFIG_X86_DS */