]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4util/include/ARCH-ppc32/rdtsc.h
update
[l4.git] / l4 / pkg / l4util / include / ARCH-ppc32 / rdtsc.h
1 /**
2  * \file
3  * \brief  time stamp counter related functions
4  *
5  * \date   Frank Mehnert <fm3@os.inf.tu-dresden.de>
6  * \ingroup l4util_tsc
7  */
8
9 /*
10  * (c) 2003-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
11  *     economic rights: Technische Universität Dresden (Germany)
12  * This file is part of TUD:OS and distributed under the terms of the
13  * GNU Lesser General Public License 2.1.
14  * Please see the COPYING-LGPL-2.1 file for details.
15  */
16
17 #ifndef __l4_rdtsc_h
18 #define __l4_rdtsc_h
19
20 /**
21  * \defgroup l4util_tsc Timestamp Counter
22  * \ingroup l4util_api
23  */
24
25 #include <l4/sys/compiler.h>
26 #include <l4/sys/l4int.h>
27 #include <l4/sys/kip.h>
28
29
30 EXTERN_C_BEGIN
31
32 extern l4_uint32_t l4_scaler_tsc_to_us;
33 extern l4_uint32_t l4_scaler_timer_to_tsc;
34
35 /* interface */
36 /**
37  * \addtogroup l4util_tsc
38  */
39 /*@{*/
40
41 #define L4_TSC_INIT_AUTO             0 ///< Automatic init
42 #define L4_TSC_INIT_KERNEL           1 ///< Initialized by kernel
43 #define L4_TSC_INIT_CALIBRATE        2 ///< Initialized by user-level
44
45 /**
46  * \brief Read current value of CPU-internal time stamp counter.
47  * \return 64-bit time stamp
48  */
49 L4_INLINE l4_cpu_time_t
50 l4_rdtsc (void);
51
52 /**
53  * \brief Read the lest significant 32 bit of the TSC.
54  *
55  * Useful for smaller differences, needs less cycles.
56  */
57 L4_INLINE
58 l4_uint32_t l4_rdtsc_32(void);
59
60 /** Convert time stamp into micro seconds value.
61  * \param tsc time value in CPU ticks
62  * \return time value in micro seconds
63  */
64 L4_INLINE l4_uint64_t
65 l4_tsc_to_us (l4_cpu_time_t tsc);
66
67 EXTERN_C_BEGIN
68
69 /**
70  * \brief Calibrate scalers for time stamp calculations.
71  *
72  * Determine some scalers to be able to convert between real time and CPU
73  * ticks. This test uses channel 0 of the PIT (i8254) or the kernel KIP,
74  * depending on availability.
75  * Just calls l4_tsc_init(L4_TSC_INIT_AUTO).
76  */
77 L4_INLINE l4_uint32_t
78 l4_calibrate_tsc (l4_kernel_info_t *kip);
79
80 /**
81  * \brief Initialitze scaler for TSC calicaltions.
82  *
83  * Initialize the scalers needed by l4_tsc_to_ns()/l4_ns_to_tsc() and so on.
84  * Current versions of Fiasco export these scalers from kernel into userland.
85  * The programmer may decide whether he allows to use these scalers or if an
86  * calibration should be performed.
87  * \param   constraint   programmers constraint:
88  *                       - #L4_TSC_INIT_AUTO if the kernel exports the scalers
89  *                         then use them. If not, perform calibration using
90  *                         channel 0 of the PIT (i8254). The latter case may
91  *                         lead into short (unpredictable) periods where
92  *                         interrupts are disabled.
93  *                       - #L4_TSC_INIT_KERNEL depend on retrieving the scalers
94  *                         from kernel. If the scalers are not available,
95  *                         return 0.
96  *                       - #L4_TSC_INIT_CALIBRATE Ignore possible scalers
97  *                         exported by the scaler, instead insist on
98  *                         calibration using the PIT.
99  * \param kip            KIP pointer
100  * \return 0 on error (no scalers exported by kernel, calibrating failed ...)
101  *         otherwise returns (2^32 / (tsc per µsec)). This value has the
102  *         same semantics as the value returned by the calibrate_delay_loop()
103  *         function of the Linux kernel.
104  */
105 L4_CV l4_uint32_t
106 l4_tsc_init (int constraint, l4_kernel_info_t *kip);
107 /*@}*/
108
109 EXTERN_C_END
110
111 EXTERN_C_BEGIN
112
113 L4_INLINE l4_uint32_t
114 l4_calibrate_tsc (l4_kernel_info_t *kip)
115 {
116   return l4_tsc_init(0, kip);
117 }
118
119 L4_INLINE l4_cpu_time_t
120 l4_rdtsc (void)
121 {
122   l4_uint32_t upper = 0, lower = 0;
123   l4_cpu_time_t tb;
124
125   __asm__ __volatile__
126     (" 1:                    \n"
127      " mftbu %[upper]        \n"
128      " mftb  %[lower]        \n"
129      " mftbu %%r12           \n"
130      " cmpw  %[upper], %%r12 \n"
131      " bne- 1b               \n"
132      : [upper] "=r" (upper),
133        [lower] "=r" (lower)
134      : "0"(upper),
135        "1"(lower)
136      : "r12");
137
138   tb = upper;
139   tb = (tb << 32 | lower);
140   return tb * l4_scaler_timer_to_tsc;
141 }
142
143 L4_INLINE
144 l4_uint32_t l4_rdtsc_32(void) 
145 {
146   l4_uint32_t lower;
147
148   __asm__ __volatile__
149     (" mftb %[lower]\n"
150      : [lower] "=r" (lower));
151
152  return lower * l4_scaler_timer_to_tsc;
153 }
154
155 L4_INLINE l4_uint64_t
156 l4_tsc_to_us (l4_cpu_time_t tsc)
157 {
158   return tsc / l4_scaler_tsc_to_us;
159 }
160
161 EXTERN_C_END
162 #endif /* __l4_rdtsc_h */
163