summaryrefslogtreecommitdiffstats
path: root/src/havegecollect.h
blob: 933297f7dee723146f8b41727158e59486384633 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/**
 ** Simple entropy harvester based upon the havege RNG
 **
 ** Copyright 2018-2022 Jirka Hladky hladky DOT jiri AT gmail DOT com
 ** Copyright 2009-2014 Gary Wuertz gary@issiweb.com
 ** Copyright 2011-2012 BenEleventh Consulting manolson@beneleventh.com
 **
 ** This program is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
 ** the Free Software Foundation, either version 3 of the License, or
 ** (at your option) any later version.
 **
 ** This program is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ** GNU General Public License for more details.
 **
 ** You should have received a copy of the GNU General Public License
 ** along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef HAVEGECOLLECT_H
#define HAVEGECOLLECT_H
/**
 ** Definitions needed to build haveged
 */
#include "havege.h"
/**
 * The collection context
 */
typedef struct h_collect {
   void    *havege_app;                   /* Application block             */
   H_UINT   havege_idx;                   /* Identifer                     */
   H_UINT   havege_szCollect;             /* Size of collection buffer     */
   H_UINT   havege_raw;                   /* RAW mode control flags        */
   H_UINT   havege_szFill;                /* Fill size                     */
   H_UINT   havege_nptr;                  /* Input pointer                 */
   pRawIn   havege_rawInput;              /* Injection function            */
   pRawIn   havege_testInput;             /* Injection function for test   */
   H_UINT   havege_cdidx;                 /* normal mode control flags     */
   H_UINT  *havege_pwalk;                 /* Instance variable             */
   H_UINT   havege_andpt;                 /* Instance variable             */
   H_UINT   havege_PT;                    /* Instance variable             */
   H_UINT   havege_PT2;                   /* Instance variable             */
   H_UINT   havege_pt2;                   /* Instance variable             */
   H_UINT   havege_PTtest;                /* Instance variable             */
   H_UINT   havege_tic;                   /* Instance variable             */
   H_UINT  *havege_tics;                  /* loop timer noise buffer       */
   H_UINT   havege_err;                   /* H_ERR enum for status         */
   void    *havege_tests;                 /* opague test context           */
   void    *havege_extra;                 /* other allocations             */
   H_UINT   havege_bigarray[1];           /* collection buffer             */
} volatile H_COLLECT;
/**
 ** Compiler intrinsics are used to make the build more portable and stable
 ** with fall-backs provided where the intrisics cannot be used. 
 */
#ifdef __GNUC__
/* ################################################################################# */

/**
 ** For the GNU compiler, the use of a cpuid intrinsic is somewhat garbled by the
 ** fact that some distributions (Centos 5.x) carry an empty cpuid.h (in order
 ** to back patch glicb?). AFAIK cpuid did not appear in gcc until version 4.3
 ** although it was in existence before. If we do not have a valid cpuid.h,
 ** we provide our own copy of the file (from gcc 4.3)
 **
 ** Also, gcc 4.4 and later provide an optimize attribute which remedies the
 ** effect ever increasing optimization on the collection loop
 */
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100  +  __GNUC_PATCHLEVEL__)

#define ASM __asm__ volatile
/**
 ** For the intel world...
 */
#ifdef HAVE_ISA_X86
#define ARCH "x86"

#if GCC_VERSION<40300
#undef HAVE_CPUID_H
#endif
#ifdef HAVE_CPUID_H
#include <cpuid.h>
#else
#include "cpuid-43.h"
#endif
/**
 ** Compatibility wrappers
 */
#define CPUID(level,p)\
  {\
  register int ecx asm ("ecx") = p[2];\
  __cpuid(level,p[0],p[1],p[2],p[3]);\
  (void) ecx;\
  }
#define HASCPUID(p) __get_cpuid_max(0, p)
/**
 ** The rdtsc intrinsic is called in by x86intrin.h - also a recent gcc innovation
 ** There have been some discussions of the code in 4.5 and 4.6, so you may opt
 ** to use the inline alternative based on GCC_VERSION
 */
#ifdef HAVE_X86INTRIN_H
#include <x86intrin.h>
#endif
#ifdef HAVE___RDTSC
#define HARDCLOCK(x) x=__rdtsc()
#else
#define HARDCLOCK(x) ASM("rdtsc;movl %%eax,%0":"=m"(x)::"ax","dx")
#endif
#else
/**
 * Outside the x86 family
 */
#ifdef HAVE_ISA_GENERIC
#define ARCH "generic"
#define ENABLE_CLOCKGETTIME 1
#endif

#ifdef HAVE_ISA_IA64
#define ARCH "ia64"
#define HARDCLOCK(x) ASM("mov %0=ar.itc" : "=r"(x))
#endif

#ifdef HAVE_ISA_SPARC
#define ARCH "sparc"
#define HARDCLOCK(x) ASM("rd %%tick, %0":"=r"(x):"r"(x))
#endif

#ifdef HAVE_ISA_SPARCLITE
#define ARCH "sparclite"
#define HARDCLOCK(x) ASM(".byte 0x83, 0x41, 0x00, 0x00");\
  ASM("mov   %%g1, %0" : "=r"(x))
#endif

#ifdef HAVE_ISA_PPC
#define ARCH "ppc"
#define HARDCLOCK(x) ASM("mftb %0":"=r"(x)) /* eq. to mftb %0, 268 */
#endif

#ifdef HAVE_ISA_S390
#define ARCH "s390"
#define HARDCLOCK(x) { unsigned long long tsc; ASM("stck %0":"=Q"(tsc)::"cc"); x = (unsigned int)tsc; }
#endif
/**
 * /Outside the x86 family
 */
#endif
/**
 *  Use the "&&" extension to calculate the LOOP_PT
 */
#define CODE_PT(a)   a
#define LOOP_PT(a)   &&loop##a

/* ################################################################################# */
#endif
/**
 * For the MSVC world
 */
#if _MSVC_VERS
/* ################################################################################# */
#define ARCH "x86"
/**
 * For the MSVC compilers V8 and above
 */
#include <intrin.h>
/**
 * Read the processor timestamp counter
 */
#define HARDCLOCK(x) x=__rdtsc()
/**
 * Normalize to the gcc interface
 */
#define CPUID(level,p) return __cpuidx(p, level, p[2])
#define HASCPUID(p) \
  { \
  CPUID(0,a,b,c,d) \
  }
/**
 * Use the __ReturnAddress intrinsic to calculate the LOOP_PT
 */
#define CODE_PT(a) __ReturnAddress()
#define LOOP_PT(a) 0
#endif
/* ################################################################################# */
/**
 * Configuration defaults - allow override at compile
 */
#ifndef COLLECT_BUFSIZE
#define COLLECT_BUFSIZE 128                     /* collection buffer size in KW              */
#endif
#ifndef GENERIC_DCACHE
#define GENERIC_DCACHE  16                      /* size of L1 data cache                     */
#endif
#ifndef GENERIC_ICACHE
#define GENERIC_ICACHE  16                      /* size of L1 instruction cache              */
#endif
#ifndef LOOP_CT
#define LOOP_CT 40                              /* Max interations per collection loop       */
#endif
/**
 * Other useful definitions
 */
#define BITS_PER_H_UINT (8*sizeof(H_UINT))      /* Bit packing constant                      */
#define DEFAULT_BUFSZ   1024*sizeof(H_UINT)     /* Default for ioSz                          */
#define MININITRAND     32                      /* Number of initial fills to prime RNG      */
#define NDSIZECOLLECT   (COLLECT_BUFSIZE*1024)  /* Collection size: 128K*H_UINT = .5M byte   */
/**
 ** The public collection interface
 */
H_COLLECT   *havege_ndcreate(H_PTR hptr, H_UINT nCollector);
void        havege_nddestroy(H_COLLECT *rdr);
H_UINT      havege_ndread(H_COLLECT *rdr);
void        havege_ndsetup(H_PTR hptr);

#endif