summaryrefslogtreecommitdiffstats
path: root/src/havege.h
blob: 1483c690a657926bca70cfb908b62b2d1c5a030b (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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/**
 ** Simple entropy harvester based upon the havege RNG
 **
 ** Copyright 2018-2021 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 HAVEGE_H
#define HAVEGE_H

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif
/**
 * header/package version as a numeric major, minor, patch triple. See havege_version()
 * below for usage.
 */
#define  HAVEGE_PREP_VERSION  "1.9.14"
/**
 * Basic types
 */
#define  H_UINT   uint32_t
#define  H_UINT8  uint8_t
/**
 * Optional metering call-back. Called with event=0 at start of collection buffer fill.
 * Called with event=1 at end of collection buffer fill. The nCollect parameter indicates
 * the calling process if multiple collection processes are enabled. Use a value of 0
 * to disable metering.
 */
typedef void (*pMeter)(H_UINT nCollect, H_UINT event);
/**
 * Optional message display call-back. This printf style method is used for all diagnostic
 * output including havege_status(). Use a value of 0 to disable output.
 */
typedef void (*pMsg)(const char *format, ...);
/**
 * Injection call-back for RAW diagnostics. Use a value of 0 to disable diagnostic. Ignored
 * except for diaqnotic builds.
 */
typedef int (*pRawIn)(volatile H_UINT *pData, H_UINT szData);
/**
 * options for H_PARAMS below. Lower byte transferred from verbose settings
 * upper byte set by diagnositic run options 
 */
#define H_VERBOSE         0x001           /* deprecated from ver 1.7       */
#define H_DEBUG_INFO      0x001           /* Show config info, retries     */
#define H_DEBUG_OLTR      0x002           /* Show detailed test retry info */
#define H_DEBUG_TIME      0x004           /* Show collection times         */
#define H_DEBUG_LOOP      0x008           /* Show loop parameters          */
#define H_DEBUG_COMPILE   0x010           /* Show assembly info            */
#define H_DEBUG_OLT       0x020           /* Show all test info            */

#define H_DEBUG_RAW_OUT   0x100           /* diagnostic output             */
#define H_DEBUG_RAW_IN    0x200           /* diagnostic input              */
#define H_DEBUG_TEST_IN   0x400           /* input test data               */
/**
 * Initialization parameters. Use non-zero values to override default values.
 * Notes:
 * 
 * 1) Correspondence between provided value and value of H_PTR members are:
 *    ioSz <==> i_readSz, collectSize <==> i_collectSz, nCores <==> n_cores,
 *    options <==> havege_opts
 * 2) ioSz is specified in bytes. collectSize sizes is specified as number
 *    of H_UINT. The default for ioSz is 1024*sizeof(H_UINT). The default
 *    for collecSize is 128K * sizeof(H_UINT).
 * 3) The icacheSize and dcacheSize override cache sizes. Both are specified in KB.
 *    Either may be specified to override the tuning value. If both are provided,
 *    tuning code is bypassed. The fallback tuning values can be overridden
 *    by defining GENERIC_DCACHE and GENERIC_ICACHE (16 will be used if not
 *    otherwise defined)
 * 4) null callback values suppress the function.
 * 5) sysFs default is '/sys', procFs default is '/proc'.
 * 6) testSpec same as haveged option "[t<x>][c<x>] x=[a[n][w]][b[w]]". If
 *    not specified (NULL) the default is "ta8b" - i.e. run the tot tests
 */
typedef struct {
   H_UINT      ioSz;                      /* size of write buffer          */
   H_UINT      collectSize;               /* size of collection buffer     */
   H_UINT      icacheSize;                /* Instruction cache size        */
   H_UINT      dcacheSize;                /* Data cache size               */
   H_UINT      options;                   /* Other options                 */
   H_UINT      nCores;                    /* If multi-core                 */
   pMeter      metering;                  /* meterming method              */
   pMsg        msg_out;                   /* output display method         */
   pRawIn      injection;                 /* injection  method             */
   char        *procFs;                   /* proc mount point override     */
   char        *sysFs;                    /* sys mount point override      */
   char        *testSpec;                 /* test specification            */
} H_PARAMS;
/**
 * Status codes used in the error member of h_anchor
 */
typedef enum {
   H_NOERR,                               /* 00 No error                         */
   H_NOHANDLE,                            /* 01 No memory for handle             */
   H_NOBUF,                               /* 02 Output buffer allocation failed  */
   H_NOINIT,                              /* 03 semaphore init failed            */
   H_NOCOLLECT,                           /* 04 H_COLLECT allocation failed      */
   H_NOWALK,                              /* 05 Walk buffer allocation failed    */
   H_NOTESTSPEC,                          /* 06 invalid test specification       */
   H_NOTESTINIT,                          /* 07 test setup failed                */
   H_NOTESTMEM,                           /* 08 Unable to allocate test memory   */
   H_NOTESTTOT,                           /* 09 tot test failed                  */
   H_NOTESTRUN,                           /* 10 production test failed           */
   H_NOCORES,                             /* 11 too many cores specified         */
   H_NOTASK,                              /* 12 Unable to create child task      */
   H_NOWAIT,                              /* 13 sem_wait failed                  */
   H_NOPOST,                              /* 14 sem_post failed                  */
   H_NODONE,                              /* 15 sem_post done failed             */
   H_NORQST,                              /* 16 sem_post request failed          */
   H_NOCOMP,                              /* 17 wait for completion failed       */
   H_EXIT,                                /* 18 Exit signal                      */
   H_NOTIMER                              /* 19 timer failed                     */
} H_ERR;
/**
 * Keep compiler honest
 */
typedef volatile void *H_VOL;
/**
 * Anchor for the RNG. Should be read only at devel level and above.
 */
typedef struct h_anchor {
   H_UINT      *io_buf;                   /* output buffer                    */
   char        *arch;                     /* "x86","sparc","ppc","ia64",etc   */
   void        *cpu;                      /* information on the cpu           */
   void        *instCache;                /* instruction cache info           */
   void        *dataCache;                /* data cache info                  */
   pMsg        print_msg;                 /* output display method            */
   pMeter      metering;                  /* metering method                  */
   pRawIn      inject;                    /* Injection diagnostic only        */
   H_VOL       collector;                 /* single thread collector          */
   H_VOL       threads;                   /* multi thread collectors          */
   void        *testData;                 /* online test data                 */
   void        *tuneData;                 /* tuning data                      */
   H_UINT      error;                     /* H_ERR enum for status            */
   H_UINT      havege_opts;               /* option flags                     */
   H_UINT      i_maxidx;                  /* maximum instruction loop index   */
   H_UINT      i_maxsz;                   /* maximum code size                */
   H_UINT      i_idx;                     /* code index used                  */
   H_UINT      i_sz;                      /* code size used                   */
   H_UINT      i_collectSz;               /* size of collection buffer        */
   H_UINT      i_readSz;                  /* size of read buffer (bytes)      */
   H_UINT      m_sz;                      /* size of thread ipc area (bytes)  */
   H_UINT      n_cores;                   /* number of cores                  */
   H_UINT      n_fills;                   /* number of buffer fills           */
} *H_PTR;
/**
 * Fail/Success counters for tot and production tests.
 */
typedef enum {
   H_OLT_TOT_A_F,       /* tot Procedure A failed   */
   H_OLT_TOT_A_P,       /* tot Procedure A passed   */
   H_OLT_TOT_B_F,       /* tot Procedure B failed   */
   H_OLT_TOT_B_P,       /* tot Procedure B passed   */
   H_OLT_PROD_A_F,      /* prod Procedure A failed  */
   H_OLT_PROD_A_P,      /* prod Procedure A passed  */
   H_OLT_PROD_B_F,      /* prod Procedure B failed  */
   H_OLT_PROD_B_P       /* prod Procedure B passed  */
} H_OLT_METERS;
/**
 * Structure used to query RNG anchor settings for information not exposed by
 * H_PTR. List formats are strings with one or more tokens separated by space.
 * Sources lists show how tuning parameters are derived. D is a build default,
 * P is a run time override, items V* come from linux virtual file system,
 * other items trace various cpuid sources. Tuning is skipped if both cache
 * sizes have 'P' sources.
 * 
 * Notes:
 *
 *    1) Build: package version of source
 *    2) Build options: compiler version followed by build configuration encoded
 *       as string of: [C][I][M][T][V] where  C=clock_gettime, I=tune with cpuid,
 *       M=multi-core, T=online-test, V=tune with vfs
 *    3) Tuning source lists: D=default, P=parameter, C=cpuid present,
 *          H=hyperthreading, A=AMD cpuid, A5=AMD fn5, A6=AMD fn6, A8=AMD fn8
 *          L2=Intel has leaf2, L4=Intel has leaf4, B=Intel leaf b,
 *          4=intel leaf4, V=virtual file system available
 *          VS=/sys/devices/system/cpu/cpu%d/cache/index<n>/level,
 *          VO=/sys/devices/system/cpu/online, VI=/proc/cpuinfo
 *          VC=/sys/devices/system/cpu
 *    4) test spec [A[1..8]][B], see H_PARAMS above.
 *    5) zero unless tests are enabled
 *    6) Last Coron's entropy estimate from Procedure B, test 8
 */
typedef struct h_status {
   const char    *version;                   /* Package version [1]             */
   const char    *buildOptions;              /* Options [2]                     */
   const char    *vendor;                    /* cpuid machines only             */
   const char    *cpuSources;                /* Tuning sources list   [3]       */
   const char    *i_cacheSources;            /* Tuning sources list   [3]       */
   const char    *d_cacheSources;            /* Tuning sources list   [3]       */
   const char    *tot_tests;                 /* tot test spec [4]               */
   const char    *prod_tests;                /* prod test spec [4]              */
   H_UINT        i_cache;                    /* size of L1 instruction cache KB */
   H_UINT        d_cache;                    /* size of L1 data cache KB        */
   H_UINT        n_tests[H_OLT_PROD_B_P+1];  /* test statistics [5]             */
   double        last_test8;                 /* last test8 result [6]           */
} *H_STATUS;
/**
 * Standard presentation formats for havege_status_dump.
 */
typedef enum {
   H_SD_TOPIC_BUILD,
/* ver: %s; arch: %s; vend: %s; build: (%s); collect: %dK */
   H_SD_TOPIC_TUNE,
/* cpu: (%s); data: %dK (%s); inst: %dK (%s); idx: %d/%d; sz: %d/%d */
   H_SD_TOPIC_TEST,
/* [tot tests (%s): A:%d/%d B: %d/%d;][continuous tests (%s): A:%d/%d B: %d/%d;][last entropy estimate %g] */
   H_SD_TOPIC_SUM,
/* fills: %d, generated: %.4g %c bytes */
} H_SD_TOPIC;
/**
 * Public prototypes. Library users note that "havege_*" is reserved for library
 * public functions. Note that the multi-core option is experimental and must
 * enabled in the build.
 */
/**
 * Create an anchor. The caller should check for a non-null return value with
 * a error value of H_NOERR. Any non-null return should be disposed of by a
 * call to havege_destroy() to free all allocated resources.
 *
 * Possible error values: H_NOERR, H_NOTESTSPEC, H_NOBUF, H_NOTESTMEM,
 *                        H_NOINIT
 */
H_PTR       havege_create(H_PARAMS *params);

/**
 * haveger_create() remembers parent pid and uses it to identify deallocating thread.
 * daemonize() forks parent and effectively loses parent thread.
 * havege_reparent(void) allows recovering new parent pid before havege_run() is started.
 */
void        havege_reparent(H_PTR hptr);

/**
 * Frees all allocated anchor resources. If the multi-core option is used, this
 * method should be called from a signal handler to prevent zombie processes.
 * If called by the process that called haveged_create(), hptr will be freed
 * when all child processes (if any) have terminated. If called by a child
 * process, H_EXIT will be set and all children awakened to exit.
 */
void        havege_destroy(H_PTR hptr);
/**
 * Read random words from an active anchor. The RNG must have been readied
 * by a previous call to havege_run(). The read must take place within the
 * allocated buffer, hptr->io_buf, and the range is specified in number of
 * H_UINT to read. If the multi-core option is used, this buffer is
 * memory-mapped between collectors.
 *
 * Returns the number of H_UINT read.
 * 
 * Possible error values: H_NOERR, H_NOTESRUN, H_NOPOST, H_NODONE,
 *                        H_NORQST, H_NOCOMP, H_EXIT
 */
int         havege_rng(H_PTR hptr, H_UINT *buf, H_UINT sz);
/**
 * Warm up the RNG and run the start-up tests. The operation suceeded if the
 * error member of the handle is H_NOERR. A failed handle should be disposed
 * of by a call to havege_destroy().
 *
 *  Returns non-zero on failure.
 *
 *  Possible error values: H_NOERR, H_NOCOLLECT, H_NOWALK, H_NOTESTMEM,
 *                         H_NOTASK, H_NOTESTTOT, H_NOWAIT,
 *                         any havege_rng error
 */
int         havege_run(H_PTR hptr);
/**
 * Fill in the h_status structure with read-only information collected from
 * the package build, run-time tuning, and test components.
 */
void        havege_status(H_PTR hptr, H_STATUS hsts);
/**
 * Call havege_status() and generate a standard presentation of H_STATUS content.
 * See the H_SD_TOPIC enum above for the formats.
 *
 * Returns the number of bytes placed in buf.
 */
int         havege_status_dump(H_PTR hptr, H_SD_TOPIC topic, char *buf, size_t len);
/**
 * Return/check library prep version. Calling havege_version() with a NULL version
 * returns the definition of HAVEGE_PREP_VERSION used to build the library. Calling
 * with HAVEGE_PREP_VERSION as the version checks if this headers definition is
 * compatible with that of the library, returning NULL if the input is incompatible
 * with the library. 
 */
const char *havege_version(const char *version);

#ifdef __cplusplus
}
#endif

#endif