Adding upstream version 1.9.14.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
ddf4b25f8f
commit
49fcf7364a
88 changed files with 62468 additions and 0 deletions
34
src/Makefile.am
Normal file
34
src/Makefile.am
Normal file
|
@ -0,0 +1,34 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
if ENABLE_BIN
|
||||
bin_PROGRAMS = haveged
|
||||
else
|
||||
sbin_PROGRAMS = haveged
|
||||
endif
|
||||
|
||||
AM_CFLAGS=-Wall -Wextra -Wpedantic -I..
|
||||
|
||||
####nolibtool_start##
|
||||
##haveged_SOURCES = haveged.c havege.c havegetune.c havegecollect.c havegetest.c havegecmd.c \
|
||||
## cpuid-43.h haveged.h havege.h havegetune.h havegecollect.h havegetest.h oneiteration.h \
|
||||
## havegecmd.h
|
||||
##
|
||||
##haveged_LDADD = @HA_LDFLAGS@
|
||||
####nolibtool_end##
|
||||
##libtool_start##
|
||||
lib_LTLIBRARIES = libhavege.la
|
||||
libhavege_la_CPPFLAGS =
|
||||
libhavege_la_LDFLAGS = -version-number @HAVEGE_LT_VERSION@
|
||||
libhavege_la_LIBADD = @HA_LDFLAGS@
|
||||
|
||||
libhavege_la_SOURCES = havege.c havegetune.c havegecollect.c havegetest.c \
|
||||
cpuid-43.h havege.h havegetune.h havegecollect.h havegetest.h oneiteration.h
|
||||
|
||||
pkginclude_HEADERS = havege.h
|
||||
|
||||
haveged_SOURCES = haveged.c haveged.h havegecmd.c havegecmd.h
|
||||
|
||||
haveged_LDADD = @HA_LDFLAGS@ libhavege.la
|
||||
##libtool_end##
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
794
src/Makefile.in
Normal file
794
src/Makefile.in
Normal file
|
@ -0,0 +1,794 @@
|
|||
# Makefile.in generated by automake 1.16.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
@ENABLE_BIN_TRUE@bin_PROGRAMS = haveged$(EXEEXT)
|
||||
@ENABLE_BIN_FALSE@sbin_PROGRAMS = haveged$(EXEEXT)
|
||||
subdir = src
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \
|
||||
$(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \
|
||||
"$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"
|
||||
PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libhavege_la_DEPENDENCIES =
|
||||
am_libhavege_la_OBJECTS = libhavege_la-havege.lo \
|
||||
libhavege_la-havegetune.lo libhavege_la-havegecollect.lo \
|
||||
libhavege_la-havegetest.lo
|
||||
libhavege_la_OBJECTS = $(am_libhavege_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
am__v_lt_1 =
|
||||
libhavege_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(libhavege_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
am_haveged_OBJECTS = haveged.$(OBJEXT) havegecmd.$(OBJEXT)
|
||||
haveged_OBJECTS = $(am_haveged_OBJECTS)
|
||||
haveged_DEPENDENCIES = libhavege.la
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp =
|
||||
am__maybe_remake_depfiles =
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CC_1 =
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(libhavege_la_SOURCES) $(haveged_SOURCES)
|
||||
DIST_SOURCES = $(libhavege_la_SOURCES) $(haveged_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
HEADERS = $(pkginclude_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
HAVEGE_LT_VERSION = @HAVEGE_LT_VERSION@
|
||||
HA_DISTRO = @HA_DISTRO@
|
||||
HA_LDFLAGS = @HA_LDFLAGS@
|
||||
HA_UNITD = @HA_UNITD@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AM_CFLAGS = -Wall -Wextra -Wpedantic -I..
|
||||
|
||||
####nolibtool_start##
|
||||
####nolibtool_end##
|
||||
lib_LTLIBRARIES = libhavege.la
|
||||
libhavege_la_CPPFLAGS =
|
||||
libhavege_la_LDFLAGS = -version-number @HAVEGE_LT_VERSION@
|
||||
libhavege_la_LIBADD = @HA_LDFLAGS@
|
||||
libhavege_la_SOURCES = havege.c havegetune.c havegecollect.c havegetest.c \
|
||||
cpuid-43.h havege.h havegetune.h havegecollect.h havegetest.h oneiteration.h
|
||||
|
||||
pkginclude_HEADERS = havege.h
|
||||
haveged_SOURCES = haveged.c haveged.h havegecmd.c havegecmd.h
|
||||
haveged_LDADD = @HA_LDFLAGS@ libhavege.la
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps src/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu --ignore-deps src/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p \
|
||||
|| test -f $$p1 \
|
||||
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' \
|
||||
-e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' \
|
||||
`; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list || exit $$?; \
|
||||
test -n "$(EXEEXT)" || exit 0; \
|
||||
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list
|
||||
install-sbinPROGRAMS: $(sbin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p \
|
||||
|| test -f $$p1 \
|
||||
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' \
|
||||
-e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-sbinPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' \
|
||||
`; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
|
||||
|
||||
clean-sbinPROGRAMS:
|
||||
@list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list || exit $$?; \
|
||||
test -n "$(EXEEXT)" || exit 0; \
|
||||
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list
|
||||
|
||||
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
|
||||
list2=; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
list2="$$list2 $$p"; \
|
||||
else :; fi; \
|
||||
done; \
|
||||
test -z "$$list2" || { \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
|
||||
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
|
||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
|
||||
}
|
||||
|
||||
uninstall-libLTLIBRARIES:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
|
||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
|
||||
done
|
||||
|
||||
clean-libLTLIBRARIES:
|
||||
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
|
||||
@list='$(lib_LTLIBRARIES)'; \
|
||||
locs=`for p in $$list; do echo $$p; done | \
|
||||
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
|
||||
sort -u`; \
|
||||
test -z "$$locs" || { \
|
||||
echo rm -f $${locs}; \
|
||||
rm -f $${locs}; \
|
||||
}
|
||||
|
||||
libhavege.la: $(libhavege_la_OBJECTS) $(libhavege_la_DEPENDENCIES) $(EXTRA_libhavege_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(libhavege_la_LINK) -rpath $(libdir) $(libhavege_la_OBJECTS) $(libhavege_la_LIBADD) $(LIBS)
|
||||
|
||||
haveged$(EXEEXT): $(haveged_OBJECTS) $(haveged_DEPENDENCIES) $(EXTRA_haveged_DEPENDENCIES)
|
||||
@rm -f haveged$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(haveged_OBJECTS) $(haveged_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
.c.o:
|
||||
$(AM_V_CC)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
$(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
libhavege_la-havege.lo: havege.c
|
||||
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhavege_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhavege_la-havege.lo `test -f 'havege.c' || echo '$(srcdir)/'`havege.c
|
||||
|
||||
libhavege_la-havegetune.lo: havegetune.c
|
||||
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhavege_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhavege_la-havegetune.lo `test -f 'havegetune.c' || echo '$(srcdir)/'`havegetune.c
|
||||
|
||||
libhavege_la-havegecollect.lo: havegecollect.c
|
||||
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhavege_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhavege_la-havegecollect.lo `test -f 'havegecollect.c' || echo '$(srcdir)/'`havegecollect.c
|
||||
|
||||
libhavege_la-havegetest.lo: havegetest.c
|
||||
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhavege_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhavege_la-havegetest.lo `test -f 'havegetest.c' || echo '$(srcdir)/'`havegetest.c
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-pkgincludeHEADERS: $(pkginclude_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
|
||||
$(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
|
||||
done
|
||||
|
||||
uninstall-pkgincludeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
|
||||
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||
dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(HEADERS)
|
||||
install-binPROGRAMS: install-libLTLIBRARIES
|
||||
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
|
||||
clean-libtool clean-sbinPROGRAMS mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-pkgincludeHEADERS
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \
|
||||
install-sbinPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
|
||||
uninstall-pkgincludeHEADERS uninstall-sbinPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
|
||||
clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
|
||||
clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \
|
||||
distclean distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-libLTLIBRARIES \
|
||||
install-man install-pdf install-pdf-am \
|
||||
install-pkgincludeHEADERS install-ps install-ps-am \
|
||||
install-sbinPROGRAMS install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
|
||||
uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS \
|
||||
uninstall-sbinPROGRAMS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
181
src/cpuid-43.h
Normal file
181
src/cpuid-43.h
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* Under Section 7 of GPL version 3, you are granted additional
|
||||
* permissions described in the GCC Runtime Library Exception, version
|
||||
* 3.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License and
|
||||
* a copy of the GCC Runtime Library Exception along with this program;
|
||||
* see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* %ecx */
|
||||
#define bit_SSE3 (1 << 0)
|
||||
#define bit_PCLMUL (1 << 1)
|
||||
#define bit_SSSE3 (1 << 9)
|
||||
#define bit_FMA (1 << 12)
|
||||
#define bit_CMPXCHG16B (1 << 13)
|
||||
#define bit_SSE4_1 (1 << 19)
|
||||
#define bit_SSE4_2 (1 << 20)
|
||||
#define bit_MOVBE (1 << 22)
|
||||
#define bit_POPCNT (1 << 23)
|
||||
#define bit_AES (1 << 25)
|
||||
#define bit_XSAVE (1 << 26)
|
||||
#define bit_OSXSAVE (1 << 27)
|
||||
#define bit_AVX (1 << 28)
|
||||
|
||||
/* %edx */
|
||||
#define bit_CMPXCHG8B (1 << 8)
|
||||
#define bit_CMOV (1 << 15)
|
||||
#define bit_MMX (1 << 23)
|
||||
#define bit_FXSAVE (1 << 24)
|
||||
#define bit_SSE (1 << 25)
|
||||
#define bit_SSE2 (1 << 26)
|
||||
|
||||
/* Extended Features */
|
||||
/* %ecx */
|
||||
#define bit_LAHF_LM (1 << 0)
|
||||
#define bit_ABM (1 << 5)
|
||||
#define bit_SSE4a (1 << 6)
|
||||
#define bit_XOP (1 << 11)
|
||||
#define bit_LWP (1 << 15)
|
||||
#define bit_FMA4 (1 << 16)
|
||||
|
||||
/* %edx */
|
||||
#define bit_LM (1 << 29)
|
||||
#define bit_3DNOWP (1 << 30)
|
||||
#define bit_3DNOW (1 << 31)
|
||||
|
||||
|
||||
#if defined(__i386__) && defined(__PIC__)
|
||||
/* %ebx may be the PIC register. */
|
||||
#if __GNUC__ >= 3
|
||||
#define __cpuid(level, a, b, c, d) \
|
||||
__asm__ ("xchg{l}\t{%%}ebx, %1\n\t" \
|
||||
"cpuid\n\t" \
|
||||
"xchg{l}\t{%%}ebx, %1\n\t" \
|
||||
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (level))
|
||||
|
||||
#define __cpuid_count(level, count, a, b, c, d) \
|
||||
__asm__ ("xchg{l}\t{%%}ebx, %1\n\t" \
|
||||
"cpuid\n\t" \
|
||||
"xchg{l}\t{%%}ebx, %1\n\t" \
|
||||
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (level), "2" (count))
|
||||
#else
|
||||
/* Host GCCs older than 3.0 weren't supporting Intel asm syntax
|
||||
nor alternatives in i386 code. */
|
||||
#define __cpuid(level, a, b, c, d) \
|
||||
__asm__ ("xchgl\t%%ebx, %1\n\t" \
|
||||
"cpuid\n\t" \
|
||||
"xchgl\t%%ebx, %1\n\t" \
|
||||
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (level))
|
||||
|
||||
#define __cpuid_count(level, count, a, b, c, d) \
|
||||
__asm__ ("xchgl\t%%ebx, %1\n\t" \
|
||||
"cpuid\n\t" \
|
||||
"xchgl\t%%ebx, %1\n\t" \
|
||||
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (level), "2" (count))
|
||||
#endif
|
||||
#else
|
||||
#define __cpuid(level, a, b, c, d) \
|
||||
__asm__ ("cpuid\n\t" \
|
||||
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (level))
|
||||
|
||||
#define __cpuid_count(level, count, a, b, c, d) \
|
||||
__asm__ ("cpuid\n\t" \
|
||||
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (level), "2" (count))
|
||||
#endif
|
||||
|
||||
/* Return highest supported input value for cpuid instruction. ext can
|
||||
be either 0x0 or 0x8000000 to return highest supported value for
|
||||
basic or extended cpuid information. Function returns 0 if cpuid
|
||||
is not supported or whatever cpuid returns in eax register. If sig
|
||||
pointer is non-null, then first four bytes of the signature
|
||||
(as found in ebx register) are returned in location pointed by sig. */
|
||||
|
||||
static __inline unsigned int
|
||||
__get_cpuid_max (unsigned int __ext, unsigned int *__sig)
|
||||
{
|
||||
unsigned int __eax, __ebx, __ecx, __edx;
|
||||
|
||||
#ifndef __x86_64__
|
||||
/* See if we can use cpuid. On AMD64 we always can. */
|
||||
#if __GNUC__ >= 3
|
||||
__asm__ ("pushf{l|d}\n\t"
|
||||
"pushf{l|d}\n\t"
|
||||
"pop{l}\t%0\n\t"
|
||||
"mov{l}\t{%0, %1|%1, %0}\n\t"
|
||||
"xor{l}\t{%2, %0|%0, %2}\n\t"
|
||||
"push{l}\t%0\n\t"
|
||||
"popf{l|d}\n\t"
|
||||
"pushf{l|d}\n\t"
|
||||
"pop{l}\t%0\n\t"
|
||||
"popf{l|d}\n\t"
|
||||
: "=&r" (__eax), "=&r" (__ebx)
|
||||
: "i" (0x00200000));
|
||||
#else
|
||||
/* Host GCCs older than 3.0 weren't supporting Intel asm syntax
|
||||
nor alternatives in i386 code. */
|
||||
__asm__ ("pushfl\n\t"
|
||||
"pushfl\n\t"
|
||||
"popl\t%0\n\t"
|
||||
"movl\t%0, %1\n\t"
|
||||
"xorl\t%2, %0\n\t"
|
||||
"pushl\t%0\n\t"
|
||||
"popfl\n\t"
|
||||
"pushfl\n\t"
|
||||
"popl\t%0\n\t"
|
||||
"popfl\n\t"
|
||||
: "=&r" (__eax), "=&r" (__ebx)
|
||||
: "i" (0x00200000));
|
||||
#endif
|
||||
|
||||
if (!((__eax ^ __ebx) & 0x00200000))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* Host supports cpuid. Return highest supported cpuid input value. */
|
||||
__cpuid (__ext, __eax, __ebx, __ecx, __edx);
|
||||
|
||||
if (__sig)
|
||||
*__sig = __ebx;
|
||||
|
||||
return __eax;
|
||||
}
|
||||
|
||||
/* Return cpuid data for requested cpuid level, as found in returned
|
||||
eax, ebx, ecx and edx registers. The function checks if cpuid is
|
||||
supported and returns 1 for valid cpuid information or 0 for
|
||||
unsupported cpuid level. All pointers are required to be non-null. */
|
||||
|
||||
static __inline int
|
||||
__get_cpuid (unsigned int __level,
|
||||
unsigned int *__eax, unsigned int *__ebx,
|
||||
unsigned int *__ecx, unsigned int *__edx)
|
||||
{
|
||||
unsigned int __ext = __level & 0x80000000;
|
||||
|
||||
if (__get_cpuid_max (__ext, 0) < __level)
|
||||
return 0;
|
||||
|
||||
__cpuid (__level, *__eax, *__ebx, *__ecx, *__edx);
|
||||
return 1;
|
||||
}
|
785
src/havege.c
Normal file
785
src/havege.c
Normal file
|
@ -0,0 +1,785 @@
|
|||
/**
|
||||
** 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/>.
|
||||
**
|
||||
*/
|
||||
/**
|
||||
* This compile unit implements the havege algorithm as an inteface to
|
||||
* either a single collector in the calling process or an interface to
|
||||
* multiple collector processes (experimental).
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "havegetest.h"
|
||||
#include "havegetune.h"
|
||||
/**
|
||||
* The library version interface results in a pair of version definitions
|
||||
* which must agree yet must also be string literals. No foolproof build
|
||||
* mechanism could be devised to ensure this, so a run-time check was added
|
||||
* instead - if the two definitions do not agree, the interface is diabled.
|
||||
*/
|
||||
#define INTERFACE_DISABLED() strcmp(PACKAGE_VERSION,HAVEGE_PREP_VERSION)
|
||||
|
||||
#if NUMBER_CORES>1
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <semaphore.h>
|
||||
#include <sched.h>
|
||||
/**
|
||||
* Collection thread directory
|
||||
*/
|
||||
typedef struct {
|
||||
pid_t main; /* the main thread */
|
||||
H_UINT exit_ct; /* shutdown counter */
|
||||
H_UINT count; /* associated count */
|
||||
H_UINT last; /* last output */
|
||||
H_UINT *out; /* buffer pointer */
|
||||
H_UINT fatal; /* fatal error in last */
|
||||
sem_t flags[1]; /* thread signals */
|
||||
} H_THREAD;
|
||||
/**
|
||||
* Local prototypes
|
||||
*/
|
||||
static int havege_exit(H_PTR h_ptr);
|
||||
static void havege_ipc(H_PTR h_ptr, H_UINT n, H_UINT sz);
|
||||
static int havege_rngChild(H_PTR h_ptr, H_UINT cNumber);
|
||||
static void havege_unipc(H_PTR h_ptr);
|
||||
#endif
|
||||
/**
|
||||
* Main allocation
|
||||
*/
|
||||
#ifdef ONLINE_TESTS_ENABLE
|
||||
typedef struct {
|
||||
struct h_anchor info; /* Application anchor */
|
||||
HOST_CFG cfg; /* Runtime environment */
|
||||
procShared std; /* Shared test data */
|
||||
} H_SETUP;
|
||||
|
||||
static int testsConfigure(H_UINT *tot, H_UINT *run, char *options);
|
||||
static void testsStatus(procShared *tps, char *tot, char *prod);
|
||||
|
||||
static void testReport(H_COLLECT * h_ctxt, H_UINT action, H_UINT prod, H_UINT state, H_UINT ct);
|
||||
static void testReportA(H_PTR h, procA *context);
|
||||
static void testReportB(H_PTR h, procB *context);
|
||||
|
||||
#else
|
||||
typedef struct {
|
||||
struct h_anchor info; /* Application anchor */
|
||||
HOST_CFG cfg; /* Runtime environment */
|
||||
} H_SETUP;
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Local prototypes
|
||||
*/
|
||||
static void havege_mute(const char *format, ...);
|
||||
/**
|
||||
* Initialize the environment based upon the tuning survey. This includes,
|
||||
* allocation the output buffer (in shared memory if mult-threaded) and
|
||||
* fitting the collection code to the tuning inputs.
|
||||
*/
|
||||
H_PTR havege_create( /* RETURN: app state */
|
||||
H_PARAMS *params) /* IN: input params */
|
||||
{
|
||||
H_SETUP *anchor;
|
||||
HOST_CFG *env;
|
||||
H_PTR h = 0;
|
||||
H_UINT n = params->nCores;
|
||||
H_UINT sz = params->ioSz;
|
||||
|
||||
if (INTERFACE_DISABLED())
|
||||
return NULL;
|
||||
if (0 == n)
|
||||
n = 1;
|
||||
if (0 == sz)
|
||||
sz = DEFAULT_BUFSZ;
|
||||
anchor = (H_SETUP *)calloc(sizeof(H_SETUP),1);
|
||||
if (NULL==anchor)
|
||||
return h;
|
||||
h = &anchor->info;
|
||||
h->print_msg = params->msg_out==0? havege_mute : params->msg_out;
|
||||
h->metering = params->metering;
|
||||
env = &anchor->cfg;
|
||||
havege_tune(env, params);
|
||||
h->error = H_NOERR;
|
||||
h->arch = ARCH;
|
||||
h->inject = params->injection;
|
||||
h->n_cores = n;
|
||||
h->havege_opts = params->options;
|
||||
h->i_collectSz = params->collectSize==0? NDSIZECOLLECT : params->collectSize;
|
||||
h->i_readSz = sz;
|
||||
h->tuneData = env;
|
||||
h->cpu = &env->cpus[env->a_cpu];
|
||||
h->instCache = &env->caches[env->i_tune];
|
||||
h->dataCache = &env->caches[env->d_tune];
|
||||
#ifdef ONLINE_TESTS_ENABLE
|
||||
{
|
||||
static const H_UINT tests[5] = {B_RUN, A_RUN};
|
||||
|
||||
H_UINT tot=0,run=0;
|
||||
H_UINT i, j;
|
||||
|
||||
procShared *tps = (procShared *)&anchor->std;
|
||||
if (testsConfigure(&tot, &run, params->testSpec)) {
|
||||
h->error = H_NOTESTSPEC;
|
||||
return h;
|
||||
}
|
||||
for(i=j=0;i<2;i++)
|
||||
if (0!=(tot & tests[i])) {
|
||||
tps->testsUsed |= tests[i];
|
||||
tps->totTests[j].action = tests[i];
|
||||
tps->totTests[j++].options = tot;
|
||||
}
|
||||
for(i=j=0;i<2;i++)
|
||||
if (0!=(run & tests[i])) {
|
||||
tps->testsUsed |= tests[i];
|
||||
tps->runTests[j].action = tests[i];
|
||||
tps->runTests[j++].options = run;
|
||||
}
|
||||
testsStatus(tps, tps->totText, tps->prodText);
|
||||
tps->report = testReport;
|
||||
h->testData = tps;
|
||||
if (havege_test(tps, params)) {
|
||||
h->error = H_NOTESTMEM;
|
||||
return h;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if NUMBER_CORES>1
|
||||
havege_ipc(h, n, sz);
|
||||
#else
|
||||
h->io_buf = malloc(sz);
|
||||
h->threads = NULL;
|
||||
#endif
|
||||
if (NULL==h->io_buf) {
|
||||
h->error = H_NOBUF;
|
||||
return h;
|
||||
}
|
||||
havege_ndsetup(h);
|
||||
return h;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
void havege_reparent(
|
||||
H_PTR hptr)
|
||||
{
|
||||
#if NUMBER_CORES>1
|
||||
H_THREAD *t = (H_THREAD *)hptr->threads;
|
||||
if (0 == t)
|
||||
return; /* single-threaded */
|
||||
|
||||
t->main = getpid();
|
||||
#endif
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
/**
|
||||
* Destructor. In a multi-collector build, this method should be called from a signal handler
|
||||
* to avoid creating processes.
|
||||
*/
|
||||
void havege_destroy( /* RETURN: none */
|
||||
H_PTR hptr) /* IN-OUT: app anchor */
|
||||
{
|
||||
if (NULL != hptr) {
|
||||
H_COLLECT *htemp;
|
||||
void *temp;
|
||||
#if NUMBER_CORES>1
|
||||
if (!havege_exit(hptr))
|
||||
return; /* only main thread continues */
|
||||
#endif
|
||||
if (0 != (temp=hptr->io_buf)) {
|
||||
hptr->io_buf = 0;
|
||||
free(temp);
|
||||
}
|
||||
#ifdef ONLINE_TESTS_ENABLE
|
||||
if (0 != (temp=hptr->testData)) {
|
||||
double *g = ((procShared *)temp)->G;
|
||||
hptr->testData = 0;
|
||||
if (0 != g)
|
||||
free(g);
|
||||
}
|
||||
#endif
|
||||
if (0 != (htemp=hptr->collector)) {
|
||||
hptr->collector = 0;
|
||||
havege_nddestroy(htemp);
|
||||
}
|
||||
free(hptr);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Read random words. In the single-collector case, input is read by the calling
|
||||
* the collection method directly. In the multi-collector case, the request info is
|
||||
* signaled to the collector last read and the caller waits for a completion signal.
|
||||
*/
|
||||
int havege_rng( /* RETURN: number words read */
|
||||
H_PTR h, /* IN-OUT: app state */
|
||||
H_UINT *buffer, /* OUT: read buffer */
|
||||
H_UINT sz) /* IN: number words to read */
|
||||
{
|
||||
#if NUMBER_CORES>1
|
||||
H_THREAD *t = (H_THREAD *) h->threads;
|
||||
|
||||
t->count = sz;
|
||||
t->out = buffer;
|
||||
if (0!=sem_post(&t->flags[t->last]))
|
||||
h->error = H_NORQST;
|
||||
else if (0!=sem_wait(&t->flags[h->n_cores]))
|
||||
h->error = H_NOCOMP;
|
||||
else if (H_NOERR != t->fatal)
|
||||
h->error = t->fatal;
|
||||
#else
|
||||
H_UINT i;
|
||||
|
||||
for(i=0;i<sz;i++)
|
||||
buffer[i] = havege_ndread((H_COLLECT *)h->collector);
|
||||
h->error = ((H_COLLECT *)h->collector)->havege_err;
|
||||
#endif
|
||||
return h->error==(H_UINT)H_NOERR? (int) sz : -1;
|
||||
}
|
||||
/**
|
||||
* Start the entropy collector.
|
||||
*/
|
||||
int havege_run( /* RETURN: NZ on failure */
|
||||
H_PTR h) /* IN-OUT: app anchor */
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#if NUMBER_CORES>1
|
||||
for(i = 0; i < h->n_cores;i++)
|
||||
if (0 == havege_rngChild(h, i))
|
||||
return 1;
|
||||
#else
|
||||
if (NULL==(h->collector = havege_ndcreate(h, i)))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Report concealed setup data
|
||||
*/
|
||||
void havege_status( /* RETURN: none */
|
||||
H_PTR h_ptr, /* IN: app state */
|
||||
H_STATUS h_sts) /* OUT: app state */
|
||||
{
|
||||
if (0 != h_sts) {
|
||||
HOST_CFG *en = (HOST_CFG *) (h_ptr->tuneData);
|
||||
CACHE_INST *cd = (CACHE_INST *)(h_ptr->dataCache);
|
||||
CACHE_INST *ci = (CACHE_INST *)(h_ptr->instCache);
|
||||
CPU_INST *cp = (CPU_INST *) (h_ptr->cpu);
|
||||
procShared *ps = (procShared *)(h_ptr->testData);
|
||||
|
||||
h_sts->version = HAVEGE_PREP_VERSION;
|
||||
h_sts->buildOptions = en->buildOpts;
|
||||
h_sts->cpuSources = en->cpuOpts;
|
||||
h_sts->i_cacheSources = en->icacheOpts;
|
||||
h_sts->d_cacheSources = en->dcacheOpts;
|
||||
h_sts->vendor = cp->vendor;
|
||||
h_sts->d_cache = cd->size;
|
||||
h_sts->i_cache = ci->size;
|
||||
h_sts->tot_tests = (0 != ps)? ps->totText :"";
|
||||
h_sts->prod_tests = (0 != ps)? ps->prodText :"";
|
||||
if (0 != ps) {
|
||||
memcpy(h_sts->n_tests, ps->meters, (H_OLT_PROD_B_P+1) * sizeof(H_UINT));
|
||||
h_sts->last_test8 = ps->lastCoron;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Standard status presetations
|
||||
*/
|
||||
int havege_status_dump( /* RETURN: output length */
|
||||
H_PTR hptr, /* IN: app state */
|
||||
H_SD_TOPIC topic, /* IN: presentation topic */
|
||||
char *buf, /* OUT: output area */
|
||||
size_t len) /* IN: size of buf */
|
||||
{
|
||||
struct h_status status;
|
||||
int n = 0;
|
||||
|
||||
if (buf != 0) {
|
||||
*buf = 0;
|
||||
len -= 1;
|
||||
havege_status(hptr, &status);
|
||||
switch(topic) {
|
||||
case H_SD_TOPIC_BUILD:
|
||||
n += snprintf(buf, len, "ver: %s; arch: %s; vend: %s; build: (%s); collect: %uK",
|
||||
status.version,
|
||||
hptr->arch,
|
||||
status.vendor,
|
||||
status.buildOptions,
|
||||
hptr->i_collectSz/1024
|
||||
);
|
||||
break;
|
||||
case H_SD_TOPIC_TUNE:
|
||||
n += snprintf(buf, len, "cpu: (%s); data: %uK (%s); inst: %uK (%s); idx: %u/%u; sz: %u/%u",
|
||||
status.cpuSources,
|
||||
status.d_cache,
|
||||
status.d_cacheSources,
|
||||
status.i_cache,
|
||||
status.i_cacheSources,
|
||||
hptr->i_maxidx - hptr->i_idx, hptr->i_maxidx,
|
||||
hptr->i_sz, hptr->i_maxsz
|
||||
);
|
||||
break;
|
||||
case H_SD_TOPIC_TEST:
|
||||
{
|
||||
H_UINT m;
|
||||
|
||||
if (strlen(status.tot_tests)>0) {
|
||||
n += snprintf(buf+n, len-n, "tot tests(%s): ", status.tot_tests);
|
||||
if ((m = status.n_tests[ H_OLT_TOT_A_P] + status.n_tests[ H_OLT_TOT_A_F])>0)
|
||||
n += snprintf(buf+n, len-n, "A:%u/%u ", status.n_tests[ H_OLT_TOT_A_P], m);
|
||||
if ((m = status.n_tests[ H_OLT_TOT_B_P] + status.n_tests[ H_OLT_TOT_B_F])>0)
|
||||
n += snprintf(buf+n, len, "B:%u/%u ", status.n_tests[ H_OLT_TOT_B_P], m);
|
||||
}
|
||||
if (strlen(status.prod_tests)>0) {
|
||||
n += snprintf(buf+n, len-n, "continuous tests(%s): ", status.prod_tests);
|
||||
if ((m = status.n_tests[ H_OLT_PROD_A_P] + status.n_tests[ H_OLT_PROD_A_F])>0)
|
||||
n += snprintf(buf+n, len-n, "A:%u/%u ", status.n_tests[ H_OLT_PROD_A_P], m);
|
||||
if ((m = status.n_tests[ H_OLT_PROD_B_P] + status.n_tests[ H_OLT_PROD_B_F])>0)
|
||||
n += snprintf(buf+n, len, "B:%u/%u ", status.n_tests[ H_OLT_PROD_B_P], m);
|
||||
}
|
||||
if (n>0)
|
||||
n += snprintf(buf+n, len-n, " last entropy estimate %g", status.last_test8);
|
||||
}
|
||||
break;
|
||||
case H_SD_TOPIC_SUM:
|
||||
{
|
||||
char units[] = {'T', 'G', 'M', 'K', 0};
|
||||
double factor = 1024.0 * 1024.0 * 1024.0 * 1024.0;
|
||||
double sz = ((double)hptr->n_fills * hptr->i_collectSz) * sizeof(H_UINT);
|
||||
int i;
|
||||
|
||||
for (i=0;0 != units[i];i++) {
|
||||
if (sz >= factor)
|
||||
break;
|
||||
factor /= 1024.0;
|
||||
}
|
||||
n = snprintf(buf, len, "fills: %u, generated: %.4g %c bytes",
|
||||
hptr->n_fills,
|
||||
sz / factor,
|
||||
units[i]
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (INTERFACE_DISABLED())
|
||||
return NULL;
|
||||
/**
|
||||
* Version check academic at the moment, but initial idea is to do a table
|
||||
* lookup on the library version to get a pattern to match against the
|
||||
* input version.
|
||||
*/
|
||||
if (version) {
|
||||
H_UINT l_interface=0, l_revision=0, l_age=0;
|
||||
H_UINT p, p_interface, p_revision, p_patch;
|
||||
|
||||
#ifdef HAVEGE_LIB_VERSION
|
||||
sscanf(HAVEGE_LIB_VERSION, "%u:%u:%u", &l_interface, &l_revision, &l_age);
|
||||
#endif
|
||||
(void)l_interface;(void)l_revision;(void)l_age;(void)p_patch; /* No check for now */
|
||||
|
||||
p = sscanf(version, "%u.%u.%u", &p_interface, &p_revision, &p_patch);
|
||||
if (p!=3 || p_interface != 1 || p_revision != 9)
|
||||
return NULL;
|
||||
}
|
||||
return HAVEGE_PREP_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Place holder if output display not provided
|
||||
*/
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
static void havege_mute( /* RETURN: none */
|
||||
const char *format, /* IN: printf format */
|
||||
...) /* IN: args */
|
||||
{
|
||||
;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#if NUMBER_CORES > 1
|
||||
/**
|
||||
* Cleanup collector(s). In a multi-collector environment, need to kill
|
||||
* children to avoid zombies.
|
||||
*/
|
||||
static int havege_exit( /* RETURN: NZ if child */
|
||||
H_PTR h_ptr) /* IN: app state */
|
||||
{
|
||||
H_THREAD *t = (H_THREAD *)h_ptr->threads;
|
||||
pid_t p;
|
||||
H_UINT i;
|
||||
|
||||
if (0 == t)
|
||||
return 0; /* Must be main thread */
|
||||
t->fatal = H_EXIT;
|
||||
for(i=0;i<t->exit_ct;i++)
|
||||
(void)sem_post(&t->flags[i]);
|
||||
if (getpid() != t->main)
|
||||
return 1;
|
||||
do { /* Wait for children */
|
||||
p = wait(NULL);
|
||||
} while(p != -1 && errno != ECHILD);
|
||||
for(i=0;i<t->exit_ct;i++)
|
||||
(void)sem_destroy(&t->flags[i]);
|
||||
if (i==h_ptr->n_cores)
|
||||
(void)sem_destroy(&t->flags[i]);
|
||||
havege_unipc(h_ptr); /* unmap memory */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize IPC mechanism. This consists of setting up a shared memory area
|
||||
* containing the output buffer and the collection thread directory.
|
||||
*/
|
||||
static void havege_ipc( /* RETURN: None */
|
||||
H_PTR h, /* IN: app state */
|
||||
H_UINT n, /* IN: number of threads */
|
||||
H_UINT sz) /* IN: size of buffer */
|
||||
{
|
||||
void *m;
|
||||
H_THREAD *t;
|
||||
H_UINT m_sz;
|
||||
int i;
|
||||
|
||||
if (n > NUMBER_CORES) {
|
||||
h->error = H_NOCORES;
|
||||
return;
|
||||
}
|
||||
m = mmap(NULL,
|
||||
m_sz = sz + sizeof(H_THREAD) + n * sizeof(sem_t),
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS,
|
||||
0,
|
||||
0);
|
||||
if (m != MAP_FAILED) {
|
||||
h->io_buf = m;
|
||||
h->m_sz = m_sz;
|
||||
t = (H_THREAD *)((char *) m + sz);
|
||||
memset(t, 0, sizeof(H_THREAD));
|
||||
t->main = getpid();
|
||||
h->threads = t;
|
||||
for(i=0;i<=n;i++)
|
||||
if(sem_init(&t->flags[i],1,0) < 0) {
|
||||
h->error = H_NOINIT;
|
||||
break;
|
||||
}
|
||||
t->exit_ct = i;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Child harvester task. If task fails to start H_PTR::error will be set to reason.
|
||||
* If task fails after start, H_THREAD::fatal will be set to the reason and a completion
|
||||
* will be posted to prevent the main thread from hanging waiting for a response.
|
||||
*/
|
||||
static int havege_rngChild(/* RETURN: none */
|
||||
H_PTR h_ptr, /* IN: app state */
|
||||
H_UINT cNumber) /* IN: collector index */
|
||||
{
|
||||
H_COLLECT *h_ctxt = 0;
|
||||
H_THREAD *thds = (H_THREAD *) h_ptr->threads;
|
||||
H_UINT cNext, i, r;
|
||||
int pid;
|
||||
|
||||
switch(pid=fork()) {
|
||||
case 0:
|
||||
h_ctxt = havege_ndcreate(h_ptr, cNumber);
|
||||
if (NULL != h_ctxt) {
|
||||
cNext = (cNumber + 1) % h_ptr->n_cores;
|
||||
while(1) {
|
||||
if (0!=sem_wait(&thds->flags[cNumber])) {
|
||||
thds->fatal = H_NOWAIT;
|
||||
break;
|
||||
}
|
||||
if (H_NOERR != thds->fatal) {
|
||||
havege_nddestroy(h_ctxt);
|
||||
exit(0);
|
||||
}
|
||||
thds->last = cNumber;
|
||||
r = h_ctxt->havege_szFill - h_ctxt->havege_nptr;
|
||||
if (thds->count < r)
|
||||
r = thds->count;
|
||||
for(i=0;i<r;i++)
|
||||
thds->out[i] = havege_ndread(h_ctxt);
|
||||
thds->fatal = h_ctxt->havege_err;
|
||||
if (0==(thds->count -= i)) {
|
||||
if (0!=sem_post(&thds->flags[h_ptr->n_cores])) {
|
||||
thds->fatal = H_NODONE;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
thds->out += i;
|
||||
if (0!=sem_post(&thds->flags[cNext])) {
|
||||
thds->fatal = H_NOPOST;
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_SCHED_YIELD
|
||||
(void)sched_yield();
|
||||
#endif
|
||||
(void)havege_ndread(h_ctxt);
|
||||
h_ctxt->havege_nptr = 0;
|
||||
}
|
||||
havege_nddestroy(h_ctxt);
|
||||
}
|
||||
else thds->fatal = h_ptr->error; /* h_ptr is a copy!! */
|
||||
(void)sem_post(&thds->flags[h_ptr->n_cores]); /* announce death! */
|
||||
break;
|
||||
case -1:
|
||||
h_ptr->error = H_NOTASK;
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
/**
|
||||
* Unmap memory
|
||||
*/
|
||||
static void havege_unipc( /* RETURN: none */
|
||||
H_PTR h_ptr) /* IN: app state */
|
||||
{
|
||||
if (0 != h_ptr->m_sz) {
|
||||
munmap(h_ptr->io_buf, h_ptr->m_sz);
|
||||
h_ptr->io_buf = 0;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#ifdef ONLINE_TESTS_ENABLE
|
||||
/**
|
||||
* Interpret options string as settings. The option string consists of terms
|
||||
* like "[t|c][a[1-8][w]|b[w]]".
|
||||
*/
|
||||
static int testsConfigure( /* RETURN: non-zero on error */
|
||||
H_UINT *tot, /* OUT: tot test options */
|
||||
H_UINT *run, /* OUT: run test options */
|
||||
char *options) /* IN: option string */
|
||||
{
|
||||
H_UINT section=0;
|
||||
int c;
|
||||
|
||||
if (options==0)
|
||||
options = DEFAULT_TEST_OPTIONS;
|
||||
while(0 != (c = *options++)) {
|
||||
switch(c) {
|
||||
case 'T': case 't': /* tot test */
|
||||
section = 't';
|
||||
*tot = 0;
|
||||
break;
|
||||
case 'C': case 'c': /* production test */
|
||||
section = 'c';
|
||||
*run = 0;
|
||||
break;
|
||||
case 'A': case 'a':
|
||||
if (!section) return 1;
|
||||
c = atoi(options);
|
||||
if (c >= 1 && c < 9) {
|
||||
c = 1<<c;
|
||||
options +=1;
|
||||
}
|
||||
else c = 0;
|
||||
c |= A_RUN;
|
||||
if (*options=='W' || *options=='w') {
|
||||
c |= A_WARN;
|
||||
options++;
|
||||
}
|
||||
if (section=='t')
|
||||
*tot |= c;
|
||||
else *run |= c;
|
||||
break;
|
||||
case 'B': case 'b':
|
||||
if (!section) return 1;
|
||||
c = B_RUN;
|
||||
if (*options=='W' || *options=='w') {
|
||||
c |= B_WARN;
|
||||
options++;
|
||||
}
|
||||
if (section=='t')
|
||||
*tot |= c;
|
||||
else *run |= c;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Show test setup. Output strings are [A[N]][B]..
|
||||
*/
|
||||
static void testsStatus( /* RETURN: test config */
|
||||
procShared *tps, /* IN: shared data */
|
||||
char *tot, /* OUT: tot tests */
|
||||
char *prod) /* OUT: production tests */
|
||||
{
|
||||
procInst *p;
|
||||
char *dst = tot;
|
||||
H_UINT i, j, k, m;
|
||||
|
||||
*dst = *tot = 0;
|
||||
p = tps->totTests;
|
||||
for(i=0;i<2;i++,p = tps->runTests, dst = prod) {
|
||||
for(j=0;j<2;j++,p++) {
|
||||
switch(p->action) {
|
||||
case A_RUN:
|
||||
*dst++ = 'A';
|
||||
if (0!=(m = p->options & A_CYCLE)) {
|
||||
for(k=0;m>>=1 != 0;k++);
|
||||
*dst++ = '0' + k;
|
||||
}
|
||||
if (0 != (p->options & A_WARN))
|
||||
*dst++ = 'w';
|
||||
break;
|
||||
case B_RUN:
|
||||
*dst++ = 'B';
|
||||
if (0 != (p->options & B_WARN))
|
||||
*dst++ = 'w';
|
||||
break;
|
||||
}
|
||||
*dst = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Reporting unit for tests
|
||||
*/
|
||||
static void testReport(
|
||||
H_COLLECT * h_ctxt, /* IN-OUT: collector context */
|
||||
H_UINT action, /* IN: A_RUN or B_RUN */
|
||||
H_UINT prod, /* IN: 0==tot, else continuous */
|
||||
H_UINT state, /* IN: state variable */
|
||||
H_UINT ct) /* IN: bytes consumed */
|
||||
{
|
||||
H_PTR h_ptr = (H_PTR)(h_ctxt->havege_app);
|
||||
onlineTests *context = (onlineTests *) h_ctxt->havege_tests;
|
||||
char *result;
|
||||
|
||||
switch(state) {
|
||||
case TEST_DONE: result = "success"; break;
|
||||
case TEST_RETRY: result = "retry"; break;
|
||||
case TEST_IGNORE: result = "warning"; break;
|
||||
default: result = "failure";
|
||||
}
|
||||
h_ptr->print_msg("AIS-31 %s procedure %s: %s %d bytes fill %d\n",
|
||||
prod==0? "tot" : "continuous", action==A_RUN? "A":"B", result, ct, h_ptr->n_fills);
|
||||
if (0 != (h_ptr->havege_opts & (H_DEBUG_OLTR|H_DEBUG_OLT)))
|
||||
switch(action){
|
||||
case A_RUN:
|
||||
testReportA(h_ptr, context->pA);
|
||||
break;
|
||||
case B_RUN:
|
||||
testReportB(h_ptr, context->pB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Reporting unit for procedure A. Results are 0-257*(1-[4 or 5])
|
||||
*/
|
||||
static void testReportA( /* RETURN: nothing */
|
||||
H_PTR h_ptr, /* IN: application instance */
|
||||
procA *p) /* IN: proc instance */
|
||||
{
|
||||
static const char * pa_tests[6] = {"test0","test1","test2","test3","test4","test5"};
|
||||
|
||||
H_UINT ran[6],sum[6];
|
||||
H_UINT ct, i, j, k;
|
||||
|
||||
for (i=0;i<6;i++)
|
||||
ran[i] = sum[i] = 0;
|
||||
for(i=0;i<p->testRun;i++){
|
||||
ct = p->results[i].testResult;
|
||||
j = ct>>8;
|
||||
ran[j] += 1;
|
||||
if (0==(ct & 0xff))
|
||||
sum[j] += 1;
|
||||
}
|
||||
h_ptr->print_msg("procedure A: %s:%d/%d, %s:%d/%d, %s:%d/%d, %s:%d/%d, %s:%d/%d, %s:%d/%d\n",
|
||||
pa_tests[0], sum[0], ran[0],
|
||||
pa_tests[1], sum[1], ran[1],
|
||||
pa_tests[2], sum[2], ran[2],
|
||||
pa_tests[3], sum[3], ran[3],
|
||||
pa_tests[4], sum[4], ran[4],
|
||||
pa_tests[5], sum[5], ran[5]
|
||||
);
|
||||
for(i=k=0;i<p->testRun;i++){
|
||||
ct = p->results[i].testResult;
|
||||
j = ct>>8;
|
||||
if (j==1)
|
||||
k+=1;
|
||||
if (0!=(ct & 0xff))
|
||||
h_ptr->print_msg(" %s[%d] failed with %d\n", pa_tests[j%6],k,p->results[i].finalValue);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Reporting unit for procedure B. Results are 6a-6b-7a[0]-7a[1]-7b[0]-7b[1]-7b[2]-7b[3]-8
|
||||
*/
|
||||
static void testReportB( /* RETURN: nothing */
|
||||
H_PTR h_ptr, /* IN: application instance */
|
||||
procB *p) /* IN: proc instance */
|
||||
{
|
||||
static const char * pb_tests[5] = {"test6a","test6b","test7a","test7b","test8"};
|
||||
|
||||
H_UINT ct, i, j, ran[5],sum[5];
|
||||
|
||||
for (i=0;i<5;i++) {
|
||||
ran[i] = sum[i] = 0;
|
||||
}
|
||||
for(i=0;i<p->testNbr;i++){
|
||||
ct = p->results[i].testResult;
|
||||
j = ct>>8;
|
||||
ran[j] += 1;
|
||||
if (0==(ct & 0xff))
|
||||
sum[j] += 1;
|
||||
}
|
||||
h_ptr->print_msg("procedure B: %s:%d/%d, %s:%d/%d, %s:%d/%d, %s:%d/%d, %s:%d/%d\n",
|
||||
pb_tests[0], sum[0], ran[0],
|
||||
pb_tests[1], sum[1], ran[1],
|
||||
pb_tests[2], sum[2], ran[2],
|
||||
pb_tests[3], sum[3], ran[3],
|
||||
pb_tests[4], sum[4], ran[4]
|
||||
);
|
||||
for(i=0;i<5;i++)
|
||||
ran[i] = p->testNbr;
|
||||
for(i=0;i<p->testNbr;i++){
|
||||
ct = p->results[i].testResult;
|
||||
j = ct>>8;
|
||||
if (i < ran[j]) ran[j] = i;
|
||||
if (0!=(ct & 0xff))
|
||||
h_ptr->print_msg(" %s[%d] failed with %g\n", pb_tests[j],i-ran[j],p->results[i].finalValue);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
308
src/havege.h
Normal file
308
src/havege.h
Normal file
|
@ -0,0 +1,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
|
460
src/havegecmd.c
Normal file
460
src/havegecmd.c
Normal file
|
@ -0,0 +1,460 @@
|
|||
/**
|
||||
** Provide HAVEGE socket communication API
|
||||
**
|
||||
** Copyright 2018-2021 Jirka Hladky hladky DOT jiri AT gmail DOT com
|
||||
** Copyright 2018 Werner Fink <werner@suse.de>
|
||||
**
|
||||
** 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/>.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef NO_COMMAND_MODE
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef HAVE_STRUCT_UCRED
|
||||
struct ucred
|
||||
{
|
||||
pid_t pid; /* PID of sending process. */
|
||||
uid_t uid; /* UID of sending process. */
|
||||
gid_t gid; /* GID of sending process. */
|
||||
};
|
||||
#endif
|
||||
|
||||
#include "havegecmd.h"
|
||||
|
||||
int first_byte;
|
||||
int socket_fd;
|
||||
static char errmsg[1024];
|
||||
|
||||
static int new_root( /* RETURN: status */
|
||||
const char *root, /* IN: path of the new root file system */
|
||||
const volatile char *path, /* IN: path of the haveged executable */
|
||||
char *const argv[], /* IN: arguments for the haveged process */
|
||||
struct pparams *params) /* IN: input params */
|
||||
{
|
||||
int ret;
|
||||
struct stat st;
|
||||
const char *realtive = (const char*)&path[0];
|
||||
|
||||
ret = chdir(root);
|
||||
if (ret < 0) {
|
||||
snprintf(&errmsg[0], sizeof(errmsg)-1,
|
||||
"can't change to working directory %s: %s\n",
|
||||
root, strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
if (path[0] == '/')
|
||||
realtive++;
|
||||
ret = fstatat(AT_FDCWD, realtive, &st, 0);
|
||||
if (ret < 0) {
|
||||
snprintf(&errmsg[0], sizeof(errmsg)-1,
|
||||
"can't restart %s: %s\n",
|
||||
path, strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
ret = chroot(".");
|
||||
if (ret < 0) {
|
||||
snprintf(&errmsg[0], sizeof(errmsg)-1,
|
||||
"can't change root directory %s\n",
|
||||
strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
ret = chdir("/");
|
||||
if (ret < 0) {
|
||||
snprintf(&errmsg[0], sizeof(errmsg)-1,
|
||||
"can't change to working directory / : %s\n",
|
||||
strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
ret = execv((const char *)path, argv);
|
||||
if (ret < 0) {
|
||||
snprintf(&errmsg[0], sizeof(errmsg)-1,
|
||||
"can't restart %s: %s\n",
|
||||
path, strerror(errno));
|
||||
}
|
||||
err:
|
||||
if (ret < 0)
|
||||
print_msg("%s", errmsg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open and listen on a UNIX socket to get command from there
|
||||
*/
|
||||
int cmd_listen( /* RETURN: UNIX socket file descriptor */
|
||||
struct pparams *params) /* IN: input params */
|
||||
{
|
||||
struct sockaddr_un su = { /* The abstract UNIX socket of haveged */
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = HAVEGED_SOCKET_PATH,
|
||||
};
|
||||
const int one = 1;
|
||||
int fd, ret;
|
||||
|
||||
fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
if (fd < 0) {
|
||||
print_msg("%s: can not open UNIX socket\n", params->daemon);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, (socklen_t)sizeof(one));
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
print_msg("%s: can not set option for UNIX socket\n", params->daemon);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = bind(fd, (struct sockaddr *)&su, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(su.sun_path+1));
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
if (errno != EADDRINUSE)
|
||||
print_msg("%s: can not bind a name to UNIX socket\n", params->daemon);
|
||||
else
|
||||
fd = -2;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = listen(fd, SOMAXCONN);
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
print_msg("%s: can not listen on UNIX socket\n", params->daemon);
|
||||
goto err;
|
||||
}
|
||||
err:
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open and connect on a UNIX socket to send command over this
|
||||
*/
|
||||
int cmd_connect( /* RETURN: UNIX socket file descriptor */
|
||||
struct pparams *params) /* IN: input params */
|
||||
{
|
||||
struct sockaddr_un su = { /* The abstract UNIX socket of haveged */
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = HAVEGED_SOCKET_PATH,
|
||||
};
|
||||
const int one = 1;
|
||||
int fd, ret;
|
||||
|
||||
fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
if (fd < 0) {
|
||||
print_msg("%s: can not open UNIX socket\n", params->daemon);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, (socklen_t)sizeof(one));
|
||||
if (ret < 0) {
|
||||
print_msg("%s: can not set option for UNIX socket\n", params->daemon);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = connect(fd, (struct sockaddr *)&su, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(su.sun_path+1));
|
||||
if (ret < 0) {
|
||||
if (errno != ECONNREFUSED)
|
||||
print_msg("%s: can not connect on UNIX socket\n", params->daemon);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
goto err;
|
||||
}
|
||||
err:
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle arguments in command mode
|
||||
*/
|
||||
int getcmd( /* RETURN: success or error */
|
||||
char *arg) /* handle current known commands */
|
||||
{
|
||||
static const struct {
|
||||
const char* cmd;
|
||||
const int req;
|
||||
const int arg;
|
||||
const char* opt;
|
||||
} cmds[] = {
|
||||
{ "root=", MAGIC_CHROOT, 1, NULL }, /* New root */
|
||||
{ "close", MAGIC_CLOSE, 0, NULL }, /* Close socket */
|
||||
{0}
|
||||
}, *cmd = cmds;
|
||||
int ret = -1;
|
||||
|
||||
if (!arg || !*arg)
|
||||
goto err;
|
||||
|
||||
optarg = NULL;
|
||||
for (; cmd->cmd; cmd++)
|
||||
if (cmd->arg) {
|
||||
if (strncmp(cmd->cmd, arg, strlen(cmd->cmd)) == 0) {
|
||||
optarg = strchr(arg, '=');
|
||||
optarg++;
|
||||
ret = cmd->req;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (strcmp(cmd->cmd, arg) == 0) {
|
||||
ret = cmd->req;
|
||||
break;
|
||||
}
|
||||
}
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incomming messages from socket
|
||||
*/
|
||||
int socket_handler( /* RETURN: closed file descriptor */
|
||||
int fd, /* IN: connected socket file descriptor */
|
||||
const volatile char *path, /* IN: path of the haveged executable */
|
||||
char *const argv[], /* IN: arguments for the haveged process */
|
||||
struct pparams *params) /* IN: input params */
|
||||
{
|
||||
struct ucred cred = {0};
|
||||
unsigned char magic[2], *ptr;
|
||||
char *enqry;
|
||||
char *optarg = NULL;
|
||||
socklen_t clen;
|
||||
int ret = -1, len;
|
||||
|
||||
if (fd < 0) {
|
||||
print_msg("%s: no connection jet\n", params->daemon);
|
||||
}
|
||||
|
||||
ptr = &magic[0];
|
||||
len = sizeof(magic);
|
||||
ret = safein(fd, ptr, len);
|
||||
if (ret < 0) {
|
||||
print_msg("%s: can not read from UNIX socket\n", params->daemon);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (magic[1] == '\002') { /* ASCII start of text: read argument provided */
|
||||
uint32_t alen;
|
||||
|
||||
ret = receive_uinteger(fd, &alen);
|
||||
if (ret < 0) {
|
||||
print_msg("%s: can not read from UNIX socket\n", params->daemon);
|
||||
goto out;
|
||||
}
|
||||
|
||||
optarg = calloc(alen, sizeof(char));
|
||||
if (!optarg) {
|
||||
print_msg("can not allocate memory for message from UNIX socket");
|
||||
goto out;
|
||||
}
|
||||
ptr = (unsigned char*)optarg;
|
||||
|
||||
ret = safein(fd, ptr, alen);
|
||||
if (ret < 0) {
|
||||
print_msg("%s: can not read from UNIX socket\n", params->daemon);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
clen = sizeof(struct ucred);
|
||||
ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &clen);
|
||||
if (ret < 0) {
|
||||
print_msg("%s: can not get credentials from UNIX socket part1\n", params->daemon);
|
||||
goto out;
|
||||
}
|
||||
if (clen != sizeof(struct ucred)) {
|
||||
print_msg("%s: can not get credentials from UNIX socket part2\n", params->daemon);
|
||||
goto out;
|
||||
}
|
||||
if (cred.uid != 0) {
|
||||
enqry = ASCII_NAK;
|
||||
|
||||
ptr = (unsigned char *)enqry;
|
||||
len = (int)strlen(enqry)+1;
|
||||
safeout(fd, ptr, len);
|
||||
}
|
||||
|
||||
switch (magic[0]) {
|
||||
case MAGIC_CHROOT:
|
||||
enqry = ASCII_ACK;
|
||||
|
||||
ret = new_root(optarg, path, argv, params);
|
||||
if (ret < 0) {
|
||||
uint32_t size = strlen(errmsg);
|
||||
safeout(fd, ASCII_STX, strlen(ASCII_STX));
|
||||
send_uinteger(fd, size);
|
||||
safeout(fd, errmsg, size+1);
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = (unsigned char *)enqry;
|
||||
len = (int)strlen(enqry);
|
||||
safeout(fd, ptr, len);
|
||||
|
||||
break;
|
||||
case MAGIC_CLOSE:
|
||||
enqry = ASCII_ACK;
|
||||
|
||||
close(socket_fd);
|
||||
socket_fd = -1;
|
||||
|
||||
ptr = (unsigned char *)enqry;
|
||||
len = (int)strlen(enqry);
|
||||
safeout(fd, ptr, len);
|
||||
argv[0][0] = first_byte;
|
||||
|
||||
break;
|
||||
default:
|
||||
enqry = ASCII_NAK;
|
||||
|
||||
ptr = (unsigned char *)enqry;
|
||||
len = (int)strlen(enqry);
|
||||
safeout(fd, ptr, len);
|
||||
break;
|
||||
}
|
||||
out:
|
||||
if (optarg)
|
||||
free(optarg);
|
||||
if (fd > 0) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive incomming messages from socket
|
||||
*/
|
||||
ssize_t safein( /* RETURN: read bytes */
|
||||
int fd, /* IN: file descriptor */
|
||||
void *ptr, /* OUT: pointer to buffer */
|
||||
size_t len) /* IN: size of buffer */
|
||||
{
|
||||
int saveerr = errno, avail;
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (len > SSIZE_MAX)
|
||||
len = SSIZE_MAX;
|
||||
|
||||
ret = ioctl(fd, FIONREAD, &avail);
|
||||
if (ret < 0 || avail <=0)
|
||||
goto out;
|
||||
|
||||
if (len > (unsigned int) avail)
|
||||
len = avail;
|
||||
|
||||
do {
|
||||
errno = saveerr;
|
||||
ssize_t p = recv(fd, ptr, len, 0 /* MSG_DONTWAIT */);
|
||||
if (p < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
break;
|
||||
print_msg("Unable to read from socket %d: %s", socket_fd, strerror(errno));
|
||||
}
|
||||
ptr = (char *) ptr + p;
|
||||
ret += p;
|
||||
len -= p;
|
||||
}
|
||||
while (len > 0);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send outgoing messages to socket
|
||||
*/
|
||||
void safeout( /* RETURN: nothing */
|
||||
int fd, /* IN: file descriptor */
|
||||
const void *ptr, /* IN: pointer to buffer */
|
||||
size_t len) /* IN: size of buffer */
|
||||
{
|
||||
int saveerr = errno;
|
||||
|
||||
do {
|
||||
ssize_t p = send(fd, ptr, len, MSG_NOSIGNAL);
|
||||
if (p < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EPIPE || errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
break;
|
||||
print_msg("Unable to write to socket %d: %s", fd, strerror(errno));
|
||||
}
|
||||
ptr = (char *) ptr + p;
|
||||
len -= p;
|
||||
}
|
||||
while (len > 0);
|
||||
|
||||
errno = saveerr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send outgoing unsigned integer to socket
|
||||
*/
|
||||
void send_uinteger( /* RETURN: nothing */
|
||||
int fd, /* IN: file descriptor */
|
||||
uint32_t value) /* IN: 32 bit unsigned integer */
|
||||
{
|
||||
uint8_t buffer[4];
|
||||
|
||||
buffer[0] = (uint8_t)((value >> 24) & 0xFF);
|
||||
buffer[1] = (uint8_t)((value >> 16) & 0xFF);
|
||||
buffer[2] = (uint8_t)((value >> 8) & 0xFF);
|
||||
buffer[3] = (uint8_t)((value >> 0) & 0xFF);
|
||||
|
||||
safeout(fd, buffer, 4 * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive incomming unsigned integer from socket
|
||||
*/
|
||||
int receive_uinteger( /* RETURN: status */
|
||||
int fd, /* IN: file descriptor */
|
||||
uint32_t *value) /* OUT: 32 bit unsigned integer */
|
||||
{
|
||||
uint8_t buffer[4];
|
||||
|
||||
if (safein(fd, buffer, 4 * sizeof(uint8_t)) < 0)
|
||||
return -1;
|
||||
|
||||
*value = (((uint32_t)buffer[0]) << 24) |
|
||||
(((uint32_t)buffer[1]) << 16) |
|
||||
(((uint32_t)buffer[2]) << 8) |
|
||||
(((uint32_t)buffer[3]) << 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
103
src/havegecmd.h
Normal file
103
src/havegecmd.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
** Provide HAVEGE socket communication API
|
||||
**
|
||||
** Copyright 2018-2021 Jirka Hladky hladky DOT jiri AT gmail DOT com
|
||||
** Copyright 2018 Werner Fink <werner@suse.de>
|
||||
**
|
||||
** 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 HAVEGECMD_H
|
||||
#define HAVEGECMD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "havege.h"
|
||||
#include "haveged.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define HAVEGED_SOCKET_PATH "\0/sys/entropy/haveged"
|
||||
#define MAGIC_CHROOT 'R'
|
||||
#define MAGIC_CLOSE 'X'
|
||||
#define MAGIC_PATH 'P'
|
||||
|
||||
#define ASCII_ACK "\x6" /* ASCII acknowledge */
|
||||
#define ASCII_NAK "\x15" /* ASCII negative acknowledge */
|
||||
#define ASCII_STX "\x2" /* ASCII start of text */
|
||||
|
||||
#ifndef SOCK_CLOEXEC
|
||||
#define SOCK_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#ifndef SOCK_NONBLOCK
|
||||
#define SOCK_NONBLOCK 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Open and listen on a UNIX socket to get command from there
|
||||
*/
|
||||
int cmd_listen(struct pparams *);
|
||||
|
||||
/**
|
||||
* Open and connect on a UNIX socket to send command over this
|
||||
*/
|
||||
int cmd_connect(struct pparams *);
|
||||
|
||||
/**
|
||||
* Handle arguments in command mode
|
||||
*/
|
||||
int getcmd(char *);
|
||||
|
||||
/**
|
||||
* Handle incomming messages from socket
|
||||
*/
|
||||
int socket_handler(int, const volatile char *, char *const [], struct pparams *);
|
||||
|
||||
/**
|
||||
* Receive incomming messages from socket
|
||||
*/
|
||||
ssize_t safein(int, void *, size_t);
|
||||
|
||||
/**
|
||||
* Send outgoing messages to socket
|
||||
*/
|
||||
void safeout(int, const void *, size_t);
|
||||
|
||||
/**
|
||||
* Send outgoing unsigned integer to socket
|
||||
*/
|
||||
void send_uinteger(int, uint32_t);
|
||||
|
||||
/**
|
||||
* Receive incomming unsigned integer from socket
|
||||
*/
|
||||
int receive_uinteger(int, uint32_t *);
|
||||
|
||||
/**
|
||||
* Socket file descriptor used for communication
|
||||
*/
|
||||
|
||||
extern int socket_fd;
|
||||
extern int first_byte;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
480
src/havegecollect.c
Normal file
480
src/havegecollect.c
Normal file
|
@ -0,0 +1,480 @@
|
|||
/**
|
||||
** 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/>.
|
||||
*/
|
||||
/**
|
||||
* This compile unit isolates the operation of the HAVEGE algorithm to better
|
||||
* deal with compiler issues. Extensive macro expansion used to deal with
|
||||
* hardware variations.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "havegecollect.h"
|
||||
#include "havegetest.h"
|
||||
#include "havegetune.h"
|
||||
/**
|
||||
* Injection and capture diagnostics
|
||||
*/
|
||||
#if defined(RAW_IN_ENABLE) || defined(RAW_OUT_ENABLE)
|
||||
#define DIAGNOSTICS_ENABLE
|
||||
#endif
|
||||
/**
|
||||
* Option to use clockgettime() as timer source
|
||||
*/
|
||||
#if defined(ENABLE_CLOCK_GETTIME)
|
||||
#include <time.h>
|
||||
|
||||
#undef HARDCLOCK
|
||||
#define HARDCLOCK(x) x = havege_clock()
|
||||
/**
|
||||
* Provide a generic timer fallback
|
||||
*/
|
||||
static H_UINT havege_clock(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (H_UINT)(ts.tv_nsec + ts.tv_sec * 1000000000LL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Memory allocation sizing
|
||||
*/
|
||||
#define SZH_INIT sizeof(H_COLLECT)+sizeof(char *)*(LOOP_CT + 2)
|
||||
#define SZH_COLLECT(a) sizeof(H_COLLECT)+sizeof(H_UINT)*(a+16384-1)
|
||||
/**
|
||||
* The HAVEGE collector is created by interleaving instructions generated by
|
||||
* oneiteration.h with the LOOP() output to control the sequence. At each
|
||||
* LOOP() point, the following actions are possible.
|
||||
*/
|
||||
typedef enum {
|
||||
LOOP_NEXT, /* Next loop */
|
||||
LOOP_ENTER, /* First loop */
|
||||
LOOP_EXIT /* Last loop */
|
||||
} LOOP_BRANCH;
|
||||
/**
|
||||
* The LOOP macro labels calculation sequences generated by oneiteration.h in
|
||||
* decreasing order from LOOPCT down to 0. During a normal collection, the
|
||||
* loop construct only introduces an extra conditional branch into the instruction
|
||||
* stream. For the exceptional conditions (initialization, end-of-loop, and
|
||||
* raw HARDCLOCK capture), the return from havege_cp() is used to determine
|
||||
* the action to be taken.
|
||||
*/
|
||||
#define LOOP(n,m) loop##n: if (n < h_ctxt->havege_cdidx) { \
|
||||
switch(havege_cp(h_ctxt,i,n,LOOP_PT(n))) { \
|
||||
case LOOP_NEXT: goto loop##m; \
|
||||
case LOOP_ENTER: goto loop_enter; \
|
||||
case LOOP_EXIT: goto loop_exit; \
|
||||
} \
|
||||
}
|
||||
/**
|
||||
* These macros below bind the code contained in oneiteration.h to the H_COLLECT
|
||||
* instance defined above
|
||||
*/
|
||||
#define ANDPT (h_ctxt->havege_andpt)
|
||||
#define PTTEST (h_ctxt->havege_PTtest)
|
||||
#define PT (h_ctxt->havege_PT)
|
||||
#define PT1 (h_ctxt->havege_pt2)
|
||||
#define PT2 (h_ctxt->havege_PT2)
|
||||
#define PWALK (h_ctxt->havege_pwalk)
|
||||
#define RESULT (h_ctxt->havege_bigarray)
|
||||
/**
|
||||
* Previous diagnostic support has been replaced. The new implementation provides
|
||||
* simultaneous access to both the noise source (i.e. the timer tics) and the
|
||||
* output. The tics buffer is also used by the injection diagnostic if enabled
|
||||
*/
|
||||
#ifdef DIAGNOSTICS_ENABLE
|
||||
#define HTICK1 (h_ctxt->havege_tics[i>>3])
|
||||
#define HTICK2 (h_ctxt->havege_tics[i>>3])
|
||||
#define SZ_TICK ((h_ptr->i_collectSz)>>3)
|
||||
#else
|
||||
#define HTICK1 (h_ctxt->havege_tic)
|
||||
#define HTICK2 (h_ctxt->havege_tic)
|
||||
#define SZ_TICK 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* If the injection diagnostic is enabled, use a wrapper for the timer source
|
||||
*/
|
||||
#ifdef RAW_IN_ENABLE
|
||||
static H_UINT havege_inject(H_COLLECT *h_ctxt, H_UINT x);
|
||||
|
||||
#define HARDCLOCKR(x) x=havege_inject(h_ctxt, x)
|
||||
#else
|
||||
#define HARDCLOCKR(x) HARDCLOCK(x)
|
||||
#endif
|
||||
/**
|
||||
* inline optimization - left conditional for legacy systems
|
||||
*/
|
||||
#if 0
|
||||
#define ROR32(value,shift) ((value >> (shift)) | (value << (32-shift)))
|
||||
#else
|
||||
inline static H_UINT ror32(const H_UINT value, const H_UINT shift) {
|
||||
return (value >> shift) | (value << (32 - shift));
|
||||
}
|
||||
#define ROR32(value,shift) ror32(value, shift)
|
||||
#endif
|
||||
/**
|
||||
* Local prototypes
|
||||
*/
|
||||
static LOOP_BRANCH havege_cp(H_COLLECT *h_ctxt, H_UINT i, H_UINT n, char *p);
|
||||
/**
|
||||
* Protect the collection mechanism against ever-increasing gcc optimization
|
||||
*/
|
||||
#if defined (GCC_VERSION) && GCC_VERSION >= 40400
|
||||
static int havege_gather(H_COLLECT * h_ctxt) __attribute__((optimize(1)));
|
||||
#else
|
||||
static int havege_gather(H_COLLECT * h_ctxt);
|
||||
#endif
|
||||
static void havege_ndinit(H_PTR h_ptr, struct h_collect *h_ctxt);
|
||||
|
||||
/**
|
||||
* Create a collector
|
||||
*/
|
||||
H_COLLECT *havege_ndcreate(/* RETURN: NULL on failure */
|
||||
H_PTR h_ptr, /* IN-OUT: application instance */
|
||||
H_UINT nCollector) /* IN: The collector instance */
|
||||
{
|
||||
H_UINT i,offs,*p,d_cache;
|
||||
H_UINT szBuffer;
|
||||
H_COLLECT *h_ctxt;
|
||||
|
||||
szBuffer = h_ptr->i_collectSz;
|
||||
d_cache = ((CACHE_INST *)(h_ptr->dataCache))->size;
|
||||
h_ctxt = (H_COLLECT *) calloc(SZH_COLLECT(szBuffer + SZ_TICK),1);
|
||||
if (NULL != h_ctxt) {
|
||||
h_ctxt->havege_app = h_ptr;
|
||||
h_ctxt->havege_idx = nCollector;
|
||||
h_ctxt->havege_raw = h_ptr->havege_opts & 0xff00;
|
||||
h_ctxt->havege_rawInput = h_ptr->inject;
|
||||
h_ctxt->havege_szCollect = szBuffer;
|
||||
h_ctxt->havege_szFill = szBuffer>>3;
|
||||
h_ctxt->havege_cdidx = h_ptr->i_idx;
|
||||
p = (H_UINT *) RESULT;
|
||||
h_ctxt->havege_err = H_NOERR;
|
||||
h_ctxt->havege_tests = 0;
|
||||
h_ctxt->havege_extra = 0;
|
||||
h_ctxt->havege_tics = p+szBuffer;
|
||||
|
||||
/** An intermediate walk table twice the size of the L1 cache is allocated
|
||||
** for use in permuting time stamp readings. The is meant to exercise
|
||||
** processor TLBs.
|
||||
*/
|
||||
ANDPT = ((2*d_cache*1024)/sizeof(H_UINT))-1;
|
||||
p = (H_UINT *) calloc((ANDPT + 4097)*sizeof(H_UINT),1);
|
||||
if (NULL != p) {
|
||||
h_ctxt->havege_extra = p;
|
||||
offs = (H_UINT)((((unsigned long)&p[4096])&0xfff)/sizeof(H_UINT));
|
||||
PWALK = &p[4096-offs];
|
||||
/**
|
||||
* Warm up the generator, running the startup tests
|
||||
*/
|
||||
#if defined(RAW_IN_ENABLE)
|
||||
if (0 == (h_ctxt->havege_raw & H_DEBUG_TEST_IN))
|
||||
#endif
|
||||
{
|
||||
H_UINT t0=0;
|
||||
|
||||
(void)havege_gather(h_ctxt); /* first sample */
|
||||
t0 = HTICK1;
|
||||
for(i=1;i<MININITRAND;i++)
|
||||
(void)havege_gather(h_ctxt); /* warmup rng */
|
||||
if (HTICK1==t0) { /* timer stuck? */
|
||||
h_ptr->error = H_NOTIMER;
|
||||
havege_nddestroy(h_ctxt);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#ifdef ONLINE_TESTS_ENABLE
|
||||
{
|
||||
procShared *ps = (procShared *)(h_ptr->testData);
|
||||
while(0!=ps->run(h_ctxt, 0)) { /* run tot tests */
|
||||
(void)havege_gather(h_ctxt);
|
||||
}
|
||||
}
|
||||
if (H_NOERR != (h_ptr->error = h_ctxt->havege_err)) {
|
||||
havege_nddestroy(h_ctxt);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
h_ctxt->havege_nptr = szBuffer;
|
||||
if (0 == (h_ctxt->havege_raw & H_DEBUG_RAW_OUT))
|
||||
h_ctxt->havege_szFill = szBuffer;
|
||||
}
|
||||
else {
|
||||
havege_nddestroy(h_ctxt);
|
||||
h_ptr->error = H_NOWALK;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else h_ptr->error = H_NOCOLLECT;
|
||||
return h_ctxt;
|
||||
}
|
||||
/**
|
||||
* Destruct a collector
|
||||
*/
|
||||
void havege_nddestroy( /* RETURN: none */
|
||||
H_COLLECT *h_ctxt) /* IN: collector context */
|
||||
{
|
||||
if (0 != h_ctxt) {
|
||||
if (h_ctxt->havege_extra!=0) {
|
||||
free(h_ctxt->havege_extra);
|
||||
h_ctxt->havege_extra = 0;
|
||||
}
|
||||
if (h_ctxt->havege_tests!=0) {
|
||||
free(h_ctxt->havege_tests);
|
||||
h_ctxt->havege_tests = 0;
|
||||
}
|
||||
free((void *)h_ctxt);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Read from the collector.
|
||||
*/
|
||||
H_UINT havege_ndread( /* RETURN: data value */
|
||||
H_COLLECT *h_ctxt) /* IN: collector context */
|
||||
{
|
||||
if (h_ctxt->havege_nptr >= h_ctxt->havege_szFill) {
|
||||
H_PTR h_ptr = (H_PTR)(h_ctxt->havege_app);
|
||||
pMeter pm;
|
||||
|
||||
if (0 != (pm = h_ptr->metering))
|
||||
(*pm)(h_ctxt->havege_idx, 0);
|
||||
#ifdef ONLINE_TESTS_ENABLE
|
||||
{
|
||||
procShared *ps = (procShared *)(h_ptr->testData);
|
||||
do {
|
||||
(void) havege_gather(h_ctxt);
|
||||
(void) ps->run(h_ctxt, 1);
|
||||
} while(ps->discard(h_ctxt)>0);
|
||||
}
|
||||
#else
|
||||
(void) havege_gather(h_ctxt);
|
||||
#endif
|
||||
h_ptr->n_fills += 1;
|
||||
if (0 != pm)
|
||||
(*pm)(h_ctxt->havege_idx, 1);
|
||||
h_ctxt->havege_nptr = 0;
|
||||
}
|
||||
#ifdef RAW_OUT_ENABLE
|
||||
if (0!=(h_ctxt->havege_raw & H_DEBUG_RAW_OUT))
|
||||
return h_ctxt->havege_tics[h_ctxt->havege_nptr++];
|
||||
#endif
|
||||
return RESULT[h_ctxt->havege_nptr++];
|
||||
}
|
||||
/**
|
||||
* Setup haveged
|
||||
*/
|
||||
void havege_ndsetup( /* RETURN: None */
|
||||
H_PTR h_ptr) /* IN-OUT: application instance */
|
||||
{
|
||||
char wkspc[SZH_INIT];
|
||||
|
||||
memset(wkspc, 0, SZH_INIT);
|
||||
havege_ndinit(h_ptr, (struct h_collect *) wkspc);
|
||||
}
|
||||
/**
|
||||
* This method is called only for control points NOT part of a normal collection:
|
||||
*
|
||||
* a) For a collection loop after all iterations are performed, this function
|
||||
* determines if the collection buffer is full.
|
||||
* b) For initialization, this method saves the address of the collection point
|
||||
* for analysis at the end of the loop.
|
||||
*/
|
||||
static LOOP_BRANCH havege_cp( /* RETURN: branch to take */
|
||||
H_COLLECT *h_ctxt, /* IN: collection context */
|
||||
H_UINT i, /* IN: collection offset */
|
||||
H_UINT n, /* IN: iteration index */
|
||||
char *p) /* IN: code pointer */
|
||||
{
|
||||
|
||||
if (h_ctxt->havege_cdidx <= LOOP_CT)
|
||||
return i < h_ctxt->havege_szCollect? LOOP_ENTER : LOOP_EXIT;
|
||||
((char **)RESULT)[n] = CODE_PT(p);
|
||||
if (n==0) h_ctxt->havege_cdidx = 0;
|
||||
return LOOP_NEXT;
|
||||
}
|
||||
|
||||
/**
|
||||
* The collection loop is constructed by repetitions of oneinteration.h interleaved
|
||||
* with control points generated by the LOOP macro.
|
||||
*/
|
||||
static int havege_gather( /* RETURN: 1 if initialized */
|
||||
H_COLLECT * h_ctxt) /* IN: collector context */
|
||||
{
|
||||
H_UINT i=0,pt=0,inter=0;
|
||||
H_UINT *Pt0, *Pt1, *Pt2, *Pt3, *Ptinter;
|
||||
|
||||
#if defined(RAW_IN_ENABLE)
|
||||
if (0 != (h_ctxt->havege_raw & H_DEBUG_RAW_IN)) {
|
||||
(*h_ctxt->havege_rawInput)(h_ctxt->havege_tics, h_ctxt->havege_szCollect>>3);
|
||||
h_ctxt->havege_tic = h_ctxt->havege_tics[0];
|
||||
}
|
||||
else if (0 != (h_ctxt->havege_raw & H_DEBUG_TEST_IN)) {
|
||||
(*h_ctxt->havege_rawInput)(RESULT, h_ctxt->havege_szCollect);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
|
||||
loop_enter:
|
||||
LOOP(40,39)
|
||||
#include "oneiteration.h"
|
||||
LOOP(39,38)
|
||||
#include "oneiteration.h"
|
||||
LOOP(38,37)
|
||||
#include "oneiteration.h"
|
||||
LOOP(37,36)
|
||||
#include "oneiteration.h"
|
||||
LOOP(36,35)
|
||||
#include "oneiteration.h"
|
||||
LOOP(35,34)
|
||||
#include "oneiteration.h"
|
||||
LOOP(34,33)
|
||||
#include "oneiteration.h"
|
||||
LOOP(33,32)
|
||||
#include "oneiteration.h"
|
||||
LOOP(32,31)
|
||||
#include "oneiteration.h"
|
||||
LOOP(31,30)
|
||||
#include "oneiteration.h"
|
||||
LOOP(30,29)
|
||||
#include "oneiteration.h"
|
||||
LOOP(29,28)
|
||||
#include "oneiteration.h"
|
||||
LOOP(28,27)
|
||||
#include "oneiteration.h"
|
||||
LOOP(27,26)
|
||||
#include "oneiteration.h"
|
||||
LOOP(26,25)
|
||||
#include "oneiteration.h"
|
||||
LOOP(25,24)
|
||||
#include "oneiteration.h"
|
||||
LOOP(24,23)
|
||||
#include "oneiteration.h"
|
||||
LOOP(23,22)
|
||||
#include "oneiteration.h"
|
||||
LOOP(22,21)
|
||||
#include "oneiteration.h"
|
||||
LOOP(21,20)
|
||||
#include "oneiteration.h"
|
||||
LOOP(20,19)
|
||||
#include "oneiteration.h"
|
||||
LOOP(19,18)
|
||||
#include "oneiteration.h"
|
||||
LOOP(18,17)
|
||||
#include "oneiteration.h"
|
||||
LOOP(17,16)
|
||||
#include "oneiteration.h"
|
||||
LOOP(16,15)
|
||||
#include "oneiteration.h"
|
||||
LOOP(15,14)
|
||||
#include "oneiteration.h"
|
||||
LOOP(14,13)
|
||||
#include "oneiteration.h"
|
||||
LOOP(13,12)
|
||||
#include "oneiteration.h"
|
||||
LOOP(12,11)
|
||||
#include "oneiteration.h"
|
||||
LOOP(11,10)
|
||||
#include "oneiteration.h"
|
||||
LOOP(10,9)
|
||||
#include "oneiteration.h"
|
||||
LOOP(9,8)
|
||||
#include "oneiteration.h"
|
||||
LOOP(8,7)
|
||||
#include "oneiteration.h"
|
||||
LOOP(7,6)
|
||||
#include "oneiteration.h"
|
||||
LOOP(6,5)
|
||||
#include "oneiteration.h"
|
||||
LOOP(5,4)
|
||||
#include "oneiteration.h"
|
||||
LOOP(4,3)
|
||||
#include "oneiteration.h"
|
||||
LOOP(3,2)
|
||||
#include "oneiteration.h"
|
||||
LOOP(2,1)
|
||||
#include "oneiteration.h"
|
||||
LOOP(1,0)
|
||||
#include "oneiteration.h"
|
||||
LOOP(0,0)
|
||||
(void)havege_cp(h_ctxt, i,0,LOOP_PT(0));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
loop_exit:
|
||||
return ANDPT==0? 0 : 1;
|
||||
}
|
||||
#ifdef RAW_IN_ENABLE
|
||||
/**
|
||||
* Wrapper for noise injector. When input is injected, the hardclock
|
||||
* call is not made and the contents of the tic buffer are used
|
||||
* unchanged from when the inject call was made at the top of the
|
||||
* loop.
|
||||
*/
|
||||
static H_UINT havege_inject( /* RETURN: clock value */
|
||||
H_COLLECT *h_ctxt, /* IN: workspace */
|
||||
H_UINT x) /* IN: injected value */
|
||||
{
|
||||
if (0==(h_ctxt->havege_raw & H_DEBUG_RAW_IN)) {
|
||||
HARDCLOCK(x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Initialize the collection loop
|
||||
*/
|
||||
#if defined (GCC_VERSION) && GCC_VERSION >= 40600
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
|
||||
static void havege_ndinit( /* RETURN: None */
|
||||
H_PTR h_ptr, /* IN-OUT: application instance */
|
||||
struct h_collect *h_ctxt) /* IN: workspace */
|
||||
{
|
||||
char **addr = (char **)(&RESULT[0]);
|
||||
H_UINT sz;
|
||||
int i;
|
||||
|
||||
h_ctxt->havege_cdidx = LOOP_CT + 1;
|
||||
(void)havege_gather(h_ctxt);
|
||||
for (i=0;i<=LOOP_CT;i++) {
|
||||
if (0 != (h_ptr->havege_opts & H_DEBUG_COMPILE)) {
|
||||
h_ptr->print_msg("Address %u=%p\n", i, addr[i]);
|
||||
}
|
||||
RESULT[i] = labs(addr[i] - addr[LOOP_CT]);
|
||||
if (i > 0 && 0 != (h_ptr->havege_opts & H_DEBUG_LOOP)) {
|
||||
h_ptr->print_msg("Loop %u: offset=%u, delta=%u\n", i,RESULT[i],RESULT[i-1]-RESULT[i]);
|
||||
}
|
||||
}
|
||||
h_ptr->i_maxidx = LOOP_CT;
|
||||
h_ptr->i_maxsz = RESULT[1];
|
||||
sz = ((CACHE_INST *)(h_ptr->instCache))->size * 1024;
|
||||
for(i=LOOP_CT;i>0;i--)
|
||||
if (RESULT[i]>sz)
|
||||
break;
|
||||
h_ptr->i_idx = ++i;
|
||||
h_ptr->i_sz = RESULT[i];
|
||||
}
|
215
src/havegecollect.h
Normal file
215
src/havegecollect.h
Normal file
|
@ -0,0 +1,215 @@
|
|||
/**
|
||||
** 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 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
|
1008
src/haveged.c
Normal file
1008
src/haveged.c
Normal file
File diff suppressed because it is too large
Load diff
100
src/haveged.h
Normal file
100
src/haveged.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
** 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
|
||||
**
|
||||
** 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 HAVEGED_H
|
||||
#define HAVEGED_H
|
||||
|
||||
#include "havege.h"
|
||||
/**
|
||||
* Settings - default values declared in haveged.c
|
||||
*/
|
||||
struct pparams {
|
||||
char *daemon; /* Daemon name - default is "haveged" */
|
||||
H_UINT exit_code; /* Exit code */
|
||||
H_UINT setup; /* setup options */
|
||||
H_UINT ncores; /* number of cores to use */
|
||||
H_UINT buffersz; /* size of collection buffer (kb) */
|
||||
H_UINT detached; /* non-zero if daemonized */
|
||||
H_UINT foreground; /* non-zero if running in foreground */
|
||||
H_UINT run_level; /* type of run 0=daemon,1=setup,2=pip,sample kb */
|
||||
H_UINT d_cache; /* size of data cache (kb) */
|
||||
H_UINT i_cache; /* size of instruction cache (kb) */
|
||||
H_UINT low_water; /* write threshold to set - 0 for none */
|
||||
char *tests_config; /* online test configuration */
|
||||
char *os_rel; /* path to operating system release */
|
||||
char *pid_file; /* name of pid file */
|
||||
char *poolsize; /* path to poolsize */
|
||||
char *random_device; /* path to random device */
|
||||
char *sample_in; /* input path for injection diagnostic */
|
||||
char *sample_out; /* path to sample file */
|
||||
H_UINT verbose; /* Output level for log or stdout */
|
||||
char *version; /* Our version */
|
||||
char *watermark; /* path to write_wakeup_threshold */
|
||||
char *command; /* command which will be send/received */
|
||||
};
|
||||
/**
|
||||
* Buffer size used when not running as daemon
|
||||
*/
|
||||
#define APP_BUFF_SIZE 1024
|
||||
#define INPUT_DEFAULT "data"
|
||||
#define OUTPUT_DEFAULT "sample"
|
||||
#define PID_DEFAULT "/var/run/haveged.pid"
|
||||
/**
|
||||
* Setup options (for app)
|
||||
*/
|
||||
#define RUN_AS_APP 0x001
|
||||
#define RANGE_SPEC 0x002
|
||||
#define USE_STDOUT 0x004
|
||||
#define CAPTURE 0x008
|
||||
#define INJECT 0x010
|
||||
#define RUN_IN_FG 0x020
|
||||
#define SET_LWM 0x040
|
||||
#define MULTI_CORE 0x080
|
||||
#define CMD_MODE 0x100
|
||||
/**
|
||||
* Default tests settings
|
||||
*/
|
||||
#define TESTS_DEFAULT_APP "ta8b" /* startup tests */
|
||||
#define TESTS_DEFAULT_RUN "ta8bcb" /* startup + continuous B */
|
||||
/**
|
||||
* Run levels for diagnostic build
|
||||
*/
|
||||
#define DIAG_RUN_CAPTURE 2 /* output clock ticks */
|
||||
#define DIAG_RUN_INJECT 4 /* inject clock ticks */
|
||||
#define DIAG_RUN_TEST 8 /* inject test data */
|
||||
/**
|
||||
* Status/monitoring information
|
||||
*/
|
||||
typedef struct {
|
||||
H_UINT n_fill; /* number times filled */
|
||||
double etime; /* milliseconds for last collection */
|
||||
double estart; /* start time for calculation */
|
||||
} H_METER;
|
||||
|
||||
/**
|
||||
* Bail....
|
||||
*/
|
||||
void error_exit(const char *, ...);
|
||||
|
||||
/**
|
||||
* Execution notices - to stderr or syslog
|
||||
*/
|
||||
void print_msg(const char *, ...);
|
||||
|
||||
#endif
|
1030
src/havegetest.c
Normal file
1030
src/havegetest.c
Normal file
File diff suppressed because it is too large
Load diff
225
src/havegetest.h
Normal file
225
src/havegetest.h
Normal file
|
@ -0,0 +1,225 @@
|
|||
/**
|
||||
** Simple entropy harvester based upon the havege RNG
|
||||
**
|
||||
** Copyright 2018-2021 Jirka Hladky hladky DOT jiri AT gmail DOT com
|
||||
** Copyright 2012-2014 Gary Wuertz gary@issiweb.com
|
||||
** Copyright 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 HAVEGETEST_H
|
||||
#define HAVEGETEST_H
|
||||
/**
|
||||
* The haveged test suite is built from the 8 tests specified in AIS-31
|
||||
* organized into test procedure A and test procedure B and structured
|
||||
* as state machines capable of processing segmented input streams.
|
||||
*/
|
||||
#include "havegecollect.h"
|
||||
/**
|
||||
* All individual tests and the test procedures use the following
|
||||
* simple state machine to manage input.
|
||||
*/
|
||||
typedef enum {
|
||||
TEST_INIT, /* initialize test (internal) */
|
||||
TEST_INPUT, /* test input needed */
|
||||
TEST_EVAL, /* evaluating results (internal) */
|
||||
TEST_DONE, /* test complete */
|
||||
TEST_RETRY, /* retry the test */
|
||||
TEST_IGNORE, /* ignore failure and continue */
|
||||
TEST_FAIL /* Test has failed */
|
||||
} TEST_STATE;
|
||||
/**
|
||||
* AIS-31 procedure A uses the FIPS140-1 as test1 thru test4. A disjointedness test is
|
||||
* used as test0 and a autocorrelation test is used as test5. test0 is executed only
|
||||
* once, the other tests are repeated in sequence 257 times.
|
||||
*/
|
||||
#define AIS_A_REPS 257 /* reps for test1 through test 5 */
|
||||
/**
|
||||
* Constants for the fips tests. Note AIS-31 v1 uses the unamended FIPS test limits
|
||||
*/
|
||||
#define FIPS_USED 20000
|
||||
#ifndef USE_AMENDED_FIPS
|
||||
#define FIPS_MAX_RUN 34
|
||||
#define FIPS_ONES_LOW 9654
|
||||
#define FIPS_ONES_HIGH 10346
|
||||
#define FIPS_POKER_LOW 1562822 /* 1.03 */
|
||||
#define FIPS_POKER_HIGH 1580438 /* 57.4 */
|
||||
#define FIPS_RUNS_LOW 2267,1079,502,223,90,90
|
||||
#define FIPS_RUNS_HIGH 2733,1421,748,402,223,223
|
||||
#else
|
||||
#define FIPS_MAX_RUN 25
|
||||
#define FIPS_ONES_LOW 9725
|
||||
#define FIPS_ONES_HIGH 10275
|
||||
#define FIPS_POKER_LOW 1576928 /* 2.16 */
|
||||
#define FIPS_POKER_HIGH 1576928 /* 46.17 */
|
||||
#define FIPS_RUNS_LOW 2315,1114,525,240,103,103
|
||||
#define FIPS_RUNS_HIGH 2685,1386,723,384,209,209
|
||||
#endif
|
||||
/**
|
||||
* test 0 consumes 64k * 48 bits
|
||||
*/
|
||||
#define TEST0_LENGTH 65536
|
||||
#define TEST0_USED (TEST0_LENGTH * 48)
|
||||
#define TEST5_LENGTH 5000
|
||||
/**
|
||||
* Fixed size input for procedure A
|
||||
*/
|
||||
#define AIS_A_SIZE (TEST0_USED+(2500*257))
|
||||
/**
|
||||
* AIS-31 procedure A results
|
||||
*/
|
||||
typedef struct {
|
||||
H_UINT testResult; /* id 8 bits, pass/fail 8bits */
|
||||
H_UINT finalValue; /* end result */
|
||||
} resultA;
|
||||
/**
|
||||
* AIS-31 procedure A context. Options are defined in haveged.h
|
||||
* This puppy weighs in at ~3 MB.
|
||||
*/
|
||||
typedef struct {
|
||||
H_UINT8 *data; /* input for test */
|
||||
H_UINT range; /* number of bits of input */
|
||||
H_UINT procState; /* procedure state */
|
||||
H_UINT procRetry; /* retry indication */
|
||||
H_UINT testId; /* test selector 0-5 */
|
||||
H_UINT testRun; /* test index 1 - 1285 */
|
||||
H_UINT testState; /* FSM state of current test */
|
||||
H_UINT bridge; /* index for data bridge */
|
||||
H_UINT bytesUsed; /* number of bytes used */
|
||||
H_UINT options; /* duty cycle for test5 */
|
||||
H_UINT8 aux[TEST0_USED]; /* extra work space */
|
||||
resultA results[1286]; /* test results */
|
||||
} procA;
|
||||
/**
|
||||
* AIS-31 procedure B is a set of multinomial distribution tests
|
||||
* and an entropy estimate (Coron' test). The distribution tests,
|
||||
* test6 and test7, require at least AIS_LENGTH sequences of 1, 2
|
||||
* 4, and 8 bits.
|
||||
*/
|
||||
/*
|
||||
* Bit range of AIS-31 procedure B distribution tests
|
||||
*/
|
||||
#define AIS_LENGTH 100000
|
||||
/**
|
||||
* AIS-31 test8 constants (Coron's test)
|
||||
*/
|
||||
#define Q 2560
|
||||
#define K 256000
|
||||
#define LN2 0.69314718055994530941
|
||||
/**
|
||||
* AIS-31 procedure B results
|
||||
*/
|
||||
typedef struct {
|
||||
H_UINT testResult; /* id 8 bits, pass/fail 8bits */
|
||||
double finalValue; /* final value */
|
||||
} resultB;
|
||||
/**
|
||||
* AIS-31 procedure B context, a svelt 1.25 KB
|
||||
*/
|
||||
typedef struct {
|
||||
H_UINT *noise; /* input for test */
|
||||
H_UINT range; /* number of bits of input */
|
||||
H_UINT procState; /* procedure state */
|
||||
H_UINT procRetry; /* retry indication */
|
||||
H_UINT testId; /* test selector 6-8 */
|
||||
H_UINT testNbr; /* current test number */
|
||||
H_UINT testState; /* FSM state of current test */
|
||||
H_UINT seq; /* aisSeq() sequence needed */
|
||||
H_UINT bitsUsed; /* bits used by procedure */
|
||||
H_UINT bridge; /* data bridge test6,7 */
|
||||
H_UINT counter[8]; /* sequence lengths */
|
||||
H_UINT einsen[8]; /* sequence counts (ones) */
|
||||
H_UINT full; /* sequence flags */
|
||||
H_UINT lastpos[256]; /* counters for test 8 */
|
||||
H_UINT options; /* RFU */
|
||||
resultB results[9]; /* test results */
|
||||
} procB;
|
||||
/**
|
||||
* Testing options
|
||||
*/
|
||||
#define A_CYCLE 0x000001ff /* test5 duty cycle */
|
||||
#define A_WARN 0x00000200 /* Only warn of A fails */
|
||||
#define A_RUN 0x00000400 /* Run procedure A */
|
||||
#define A_OPTIONS 0x000003ff
|
||||
#define B_WARN 0x00001000 /* Only warn of B fails */
|
||||
#define B_RUN 0x00002000 /* Run proceure B */
|
||||
#define B_OPTIONS 0x00001000
|
||||
#define X_OPTIONS 0x000f0000 /* isolated test index */
|
||||
#define X_RUN 0x00100000 /* diagnostic isolated test */
|
||||
/**
|
||||
* A test procedure run consists of an indicator and options
|
||||
*/
|
||||
typedef struct {
|
||||
H_UINT action; /* action code A_RUN, B_RUN */
|
||||
H_UINT options; /* WARN and other options */
|
||||
} procInst;
|
||||
|
||||
/**
|
||||
* Services provided
|
||||
*/
|
||||
typedef int (*ptrDiscard)(H_COLLECT *rdr);
|
||||
typedef void (*ptrReport)(H_COLLECT * h_ctxt, H_UINT action, H_UINT prod, H_UINT state, H_UINT ct);
|
||||
typedef int (*ptrRun)(H_COLLECT *rdr, H_UINT prod);
|
||||
|
||||
/**
|
||||
* A test procedure is associated with a collection buffer. Some
|
||||
* resources are shared by all collection buffers. This includes
|
||||
* roll-your-own vtable used to avoid polluting the RNG name space
|
||||
* This structure ends up in hptr->testData
|
||||
*/
|
||||
typedef struct {
|
||||
ptrDiscard discard; /* release test resources */
|
||||
ptrRun run; /* run test suite */
|
||||
ptrReport report; /* report test results */
|
||||
H_UINT options; /* verbosity, etc. */
|
||||
H_UINT testsUsed; /* tests used */
|
||||
procInst totTests[2]; /* tot tests to run */
|
||||
procInst runTests[2]; /* production tests to run */
|
||||
H_UINT procReps; /* Number of A repetitions */
|
||||
H_UINT fips_low[6]; /* low runs thresholds */
|
||||
H_UINT fips_high[6]; /* high runs thresholds */
|
||||
char totText[8]; /* tot test text rep */
|
||||
char prodText[8]; /* production test text rep */
|
||||
H_UINT meters[H_OLT_PROD_B_P+1]; /* test counters */
|
||||
double lastCoron; /* last test8 result */
|
||||
double *G; /* test8 lookup table */
|
||||
} procShared;
|
||||
/**
|
||||
* How to get test context and shared data from H_COLLECT
|
||||
*/
|
||||
#define TESTS_CONTEXT(c) (onlineTests *)(c->havege_tests)
|
||||
#define TESTS_SHARED(c) (procShared *)(((H_PTR)(c->havege_app))->testData)
|
||||
/**
|
||||
* Online testing context - one per collector. Note szTotal is for diagnostic
|
||||
* use only, no effort is made to account for overflow.
|
||||
*/
|
||||
typedef struct {
|
||||
H_UINT result; /* nz if failed */
|
||||
H_UINT totIdx; /* tot test idx */
|
||||
H_UINT runIdx; /* run test idx */
|
||||
H_UINT szCarry; /* bits carried in next proc */
|
||||
H_UINT szTotal; /* total bits processed */
|
||||
procA *pA; /* procedure A instance */
|
||||
procB *pB; /* procedure B instance */
|
||||
} onlineTests;
|
||||
/**
|
||||
* Default options are to run the tot tests.
|
||||
*/
|
||||
#define DEFAULT_TEST_OPTIONS "ta8b"
|
||||
/**
|
||||
* Public interface
|
||||
*/
|
||||
int havege_test(procShared *tps, H_PARAMS *params);
|
||||
|
||||
#endif
|
926
src/havegetune.c
Normal file
926
src/havegetune.c
Normal file
|
@ -0,0 +1,926 @@
|
|||
/**
|
||||
** Determine HAVEGE environment
|
||||
**
|
||||
** 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/>.
|
||||
**
|
||||
*/
|
||||
/**
|
||||
* This compile unit implements automatic tuning for the havege algorithm. Two
|
||||
* general methods are used CPUID (intel specific) and VFS (Linux specific). The
|
||||
* best result of the available methods is returned.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "havegetune.h"
|
||||
/**
|
||||
* Text representations of build options
|
||||
*/
|
||||
#define BUILD_CLOCK 'C'
|
||||
#define BUILD_DIAGS 'D'
|
||||
#define BUILD_CPUID 'I'
|
||||
#define BUILD_THREADS 'M'
|
||||
#define BUILD_OLT 'T'
|
||||
#define BUILD_VFS 'V'
|
||||
/**
|
||||
* Text representations of TOPO_MAP sources
|
||||
*/
|
||||
static const char *topoReps[] = {
|
||||
"D", /* SRC_DEFAULT 0x00001 */
|
||||
"P", /* SRC_PARAM 0x00002 */
|
||||
"A6", /* SRC_CPUID_AMD6 0x00004 */
|
||||
"A5", /* SRC_CPUID_AMD5 0x00008 */
|
||||
"L2", /* SRC_CPUID_INTEL2 0x00010 */
|
||||
"L4", /* SRC_CPUID_INTEL4 0x00020 */
|
||||
"V", /* SRC_VFS_INDEX 0x00040 */
|
||||
"", /* not used 0x00080 */
|
||||
"C", /* SRC_CPUID_PRESENT 0x00100 */
|
||||
"H", /* SRC_CPUID_HT 0x00200 */
|
||||
"A", /* SRC_CPUID_AMD 0x00400 */
|
||||
"A8", /* SRC_CPUID_AMD8 0x00800 */
|
||||
"B", /* SRC_CPUID_LEAFB 0x01000 */
|
||||
"4", /* SRC_CPUID_LEAF4 0x02000 */
|
||||
"VS", /* SRC_VFS_STATUS 0x04000 */
|
||||
"VO" /* SRC_VFS_ONLINE 0x08000 */
|
||||
"VI", /* SRC_VFS_CPUINFO 0x10000 */
|
||||
"VC", /* SRC_VFS_CPUDIR 0x20000 */
|
||||
0
|
||||
};
|
||||
/**
|
||||
* Local debugging
|
||||
*/
|
||||
#if 0
|
||||
#define TUNE_DEBUG(...) fprintf(stderr,__VA_ARGS__)
|
||||
#define TUNE_DUMP 1
|
||||
static void cfg_dump(HOST_CFG *anchor);
|
||||
#else
|
||||
#define TUNE_DEBUG(...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Local prototypes
|
||||
*/
|
||||
#ifdef TUNING_VFS_ENABLE
|
||||
static void cfg_bitClear(TOPO_MAP *m);
|
||||
static int cfg_bitCount(TOPO_MAP *m);
|
||||
#endif
|
||||
static void cfg_bitDecode(char *dest, const char **reps, H_UINT value, H_UINT size);
|
||||
#if 0
|
||||
static void cfg_bitDisplay(TOPO_MAP *m);
|
||||
#endif
|
||||
static int cfg_bitIntersect(TOPO_MAP *m, TOPO_MAP *t);
|
||||
static void cfg_bitMerge(TOPO_MAP *m,TOPO_MAP *t);
|
||||
static int cfg_bitNext(TOPO_MAP *m, int n);
|
||||
static void cfg_bitSet(TOPO_MAP *m, int n);
|
||||
static void cfg_cacheAdd(HOST_CFG *anchor, H_UINT src, H_UINT cpu,
|
||||
H_UINT level, H_UINT type, H_UINT kb);
|
||||
static void cfg_cpuAdd(HOST_CFG *anchor, H_UINT src, CPU_INST *INST);
|
||||
/**
|
||||
* If cpuid not present, no need to generate the code
|
||||
*/
|
||||
#ifndef CPUID
|
||||
#undef TUNING_CPUID_ENABLE
|
||||
#endif
|
||||
|
||||
#ifdef TUNING_CPUID_ENABLE
|
||||
/************************* CPUID support ***************************************/
|
||||
/**
|
||||
* Register names
|
||||
*/
|
||||
typedef enum {
|
||||
EAX, EBX, ECX, EDX
|
||||
} CPUID_REGNAMES;
|
||||
|
||||
#define CPUID_CONFIG(a) cpuid_config(a)
|
||||
#define CPUID_VENDOR(r) *((H_UINT *)s) = regs[r];s+= sizeof(H_UINT)
|
||||
/**
|
||||
* Local CPUID prototypes
|
||||
*/
|
||||
#if defined (GCC_VERSION) && GCC_VERSION >= 40400
|
||||
static void cpuid(int fn, int sfn, H_UINT *regs) __attribute__((optimize(0)));
|
||||
#else
|
||||
static void cpuid(int fn, int sfn, H_UINT *regs);
|
||||
#endif
|
||||
static void cpuid_config(HOST_CFG *anchor);
|
||||
static void cpuid_configAmd(HOST_CFG *anchor, CPU_INST *w);
|
||||
static void cpuid_configIntel(HOST_CFG *anchor, CPU_INST *w);
|
||||
static void cpuid_configIntel2(HOST_CFG *anchor, CPU_INST *w, H_UINT *regs);
|
||||
static void cpuid_configIntel4(HOST_CFG *anchor, CPU_INST *w, H_UINT *regs);
|
||||
#else
|
||||
#define CPUID_CONFIG(a)
|
||||
#endif
|
||||
/************************ /CPUID support ***************************************/
|
||||
/************************ VFS support ***************************************/
|
||||
#ifdef TUNING_VFS_ENABLE
|
||||
|
||||
#define VFS_LINESIZE 256
|
||||
/**
|
||||
* Filter function used by configuration
|
||||
*/
|
||||
typedef int (*pFilter)(HOST_CFG *pAnchor, char *input);
|
||||
typedef int (*pDirFilter)(HOST_CFG *pAnchor, char *input, H_UINT *pArg);
|
||||
/**
|
||||
* Definitions
|
||||
*/
|
||||
#define VFS_CONFIG(a) vfs_config(a)
|
||||
/**
|
||||
* Local filesystem prototypes
|
||||
*/
|
||||
static void vfs_config(HOST_CFG *anchor);
|
||||
static int vfs_configCpuDir(HOST_CFG *anchor, char *input, H_UINT *pArg);
|
||||
static int vfs_configCpuInfo(HOST_CFG *anchor, char *input);
|
||||
static int vfs_configDir(HOST_CFG *pAnchor, char *path, pDirFilter filter, H_UINT *pArg);
|
||||
static int vfs_configFile(HOST_CFG *anchor, char *path, pFilter filter);
|
||||
static int vfs_configInfoCache(HOST_CFG *pAnchor, char *input, H_UINT *pArg);
|
||||
static int vfs_configOnline(HOST_CFG *anchor, char *input);
|
||||
static int vfs_configInt(HOST_CFG *anchor, char *input);
|
||||
static int vfs_configStatus(HOST_CFG *anchor, char *input);
|
||||
static int vfs_configType(HOST_CFG *anchor, char *input);
|
||||
|
||||
static void vfs_parseList(TOPO_MAP *map, char *input);
|
||||
static void vfs_parseMask(TOPO_MAP *map, char *input);
|
||||
#else
|
||||
#define VFS_CONFIG(a)
|
||||
#endif
|
||||
/************************* /VFS support ***************************************/
|
||||
|
||||
/**
|
||||
* Get tuning values for collector
|
||||
*/
|
||||
void havege_tune( /* RETURN: none */
|
||||
HOST_CFG *anchor, /* OUT: tuning info */
|
||||
H_PARAMS *param) /* IN: config parameters */
|
||||
{
|
||||
char *bp = anchor->buildOpts;
|
||||
int i;
|
||||
|
||||
/**
|
||||
* Capture build options
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
bp += snprintf(bp, 24, "gcc %d.%d.%d ", __GNUC__ ,__GNUC_MINOR__ , __GNUC_PATCHLEVEL__);
|
||||
#endif
|
||||
#if defined(ENABLE_CLOCK_GETTIME)
|
||||
*bp++ = BUILD_CLOCK;
|
||||
#endif
|
||||
#if defined(RAW_IN_ENABLE) || defined(RAW_OUT_ENABLE)
|
||||
*bp++ = BUILD_DIAGS;
|
||||
#endif
|
||||
#ifdef TUNING_CPUID_ENABLE
|
||||
*bp++ = BUILD_CPUID;
|
||||
#endif
|
||||
#if NUMBER_CORES>1
|
||||
*bp++ = BUILD_THREADS;
|
||||
#endif
|
||||
#ifdef ONLINE_TESTS_ENABLE
|
||||
*bp++ = BUILD_OLT;
|
||||
#endif
|
||||
#ifdef TUNING_VFS_ENABLE
|
||||
*bp++ = BUILD_VFS;
|
||||
#endif
|
||||
*bp = 0;
|
||||
/**
|
||||
* Virtual file system setup
|
||||
*/
|
||||
anchor->procfs = param->procFs==NULL? "/proc" : param->procFs;
|
||||
anchor->sysfs = param->sysFs==NULL? "/sys" : param->sysFs;
|
||||
/**
|
||||
* The order determines preference
|
||||
*/
|
||||
if (param->icacheSize != 0)
|
||||
cfg_cacheAdd(anchor, SRC_PARAM, -1, 1, 'I', param->icacheSize);
|
||||
if (param->dcacheSize != 0)
|
||||
cfg_cacheAdd(anchor, SRC_PARAM, -1, 1, 'D', param->dcacheSize);
|
||||
/**
|
||||
* Bypass configuration if entirely specified
|
||||
*/
|
||||
if (param->icacheSize == 0 || param->dcacheSize == 0) {
|
||||
CPUID_CONFIG(anchor);
|
||||
VFS_CONFIG(anchor);
|
||||
cfg_cacheAdd(anchor, SRC_DEFAULT, -1, 1, 'I', GENERIC_ICACHE);
|
||||
cfg_cacheAdd(anchor, SRC_DEFAULT, -1, 1, 'D', GENERIC_DCACHE);
|
||||
}
|
||||
/**
|
||||
* Make sure there is at least 1 cpu instance. cpus configuration is considered
|
||||
* homogeneous so only the first will be reported/used.
|
||||
*/
|
||||
if (0 == anchor->ctCpu)
|
||||
cfg_cpuAdd(anchor, 0, NULL);
|
||||
cfg_bitDecode(anchor->cpuOpts, topoReps, anchor->cpus[0].cpuMap.source, SZ_CPUREP);
|
||||
#ifdef TUNE_DUMP
|
||||
cfg_dump(anchor);
|
||||
#endif
|
||||
anchor->d_tune = anchor->i_tune = MAX_CACHES+2;
|
||||
for (i=0;i<anchor->ctCache;i++) {
|
||||
if (anchor->caches[i].level==1) {
|
||||
switch(anchor->caches[i].type) {
|
||||
case 'I': case 'T':
|
||||
if (i < (int)anchor->i_tune)
|
||||
anchor->i_tune = i;
|
||||
break;
|
||||
case 'D':
|
||||
if (i < (int)anchor->d_tune)
|
||||
anchor->d_tune = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg_bitDecode(anchor->icacheOpts, topoReps,
|
||||
anchor->caches[anchor->i_tune].cpuMap.source, SZ_CACHEREP);
|
||||
cfg_bitDecode(anchor->dcacheOpts, topoReps,
|
||||
anchor->caches[anchor->d_tune].cpuMap.source, SZ_CACHEREP);
|
||||
TUNE_DEBUG("havege_tune %d/%d\n", anchor->i_tune, anchor->d_tune);
|
||||
}
|
||||
#ifdef TUNING_VFS_ENABLE
|
||||
/**
|
||||
* Return number of bits set in map
|
||||
*/
|
||||
static void cfg_bitClear( /* RETURN : None */
|
||||
TOPO_MAP *m) /* IN: bitmap */
|
||||
{
|
||||
memset(&m->bits[0], 0, MAX_BIT_IDX * sizeof(H_UINT));
|
||||
}
|
||||
/**
|
||||
* Return number of bits set in map
|
||||
*/
|
||||
static int cfg_bitCount( /* RETURN : None */
|
||||
TOPO_MAP *m) /* IN: bitmap */
|
||||
{
|
||||
int n, ct=0;
|
||||
|
||||
for(n=-1;(n=cfg_bitNext(m,n))!=-1;ct++) ;
|
||||
return ct;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* decode bit representation
|
||||
*/
|
||||
static void cfg_bitDecode( /* RETURN: None */
|
||||
char *dest, /* OUT: target */
|
||||
const char **reps, /* IN: codes */
|
||||
H_UINT value, /* IN: value to decode */
|
||||
H_UINT size) /* IN: max range */
|
||||
{
|
||||
H_UINT i=0;
|
||||
const char *s;
|
||||
|
||||
size -= 1;
|
||||
while(value!= 0 && *reps != 0) {
|
||||
s = *reps++;
|
||||
if ((value & 1) != 0) {
|
||||
if (i>0 && i < size)
|
||||
dest[i++] = ' ';
|
||||
while(*s != 0 && i < size)
|
||||
dest[i++] = *s++;
|
||||
}
|
||||
value >>= 1;
|
||||
}
|
||||
dest[i] = 0;
|
||||
}
|
||||
#if 0
|
||||
/**
|
||||
* Display topo bit map - cpuset(7) convention is big-endian
|
||||
*/
|
||||
static void cfg_bitDisplay( /* RETURN : None */
|
||||
TOPO_MAP *m) /* IN: bitmap */
|
||||
{
|
||||
int n;
|
||||
|
||||
for(n=m->msw;n>=0 && n < (int)MAX_BIT_IDX;n--)
|
||||
printf(" %08x", m->bits[n]);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Test if maps intersect
|
||||
*/
|
||||
static int cfg_bitIntersect( /* RETURN: None */
|
||||
TOPO_MAP *m, /* OUT: bitmap */
|
||||
TOPO_MAP *t) /* IN: bit to set */
|
||||
{
|
||||
H_UINT i;
|
||||
|
||||
for (i=0;i < MAX_BIT_IDX;i++)
|
||||
if (0!=(m->bits[i] & t->bits[i]))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Merge two maps
|
||||
*/
|
||||
static void cfg_bitMerge( /* RETURN: None */
|
||||
TOPO_MAP *m, /* OUT: bitmap */
|
||||
TOPO_MAP *t) /* IN: bits to set */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<(int)MAX_BIT_IDX;i++) {
|
||||
m->bits[i] |= t->bits[i];
|
||||
if (0 != m->bits[i] && i > m->msw)
|
||||
m->msw = i;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Find next bit in topo bit map
|
||||
*/
|
||||
static int cfg_bitNext ( /* RETURN: index of next bit or -1 */
|
||||
TOPO_MAP *m, /* IN: bitmap */
|
||||
int n) /* IN: prev bit use -1 for first */
|
||||
{
|
||||
int bit, word;
|
||||
|
||||
bit = (n+1) % BITS_PER_H_UINT;
|
||||
for(word = (n+1) / BITS_PER_H_UINT;word <= m->msw && word < (int)MAX_BIT_IDX;word++) {
|
||||
for(;bit<(int)BITS_PER_H_UINT; bit++)
|
||||
if (m->bits[word] & 1<< bit)
|
||||
return word * BITS_PER_H_UINT + bit;
|
||||
bit = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* Set a bit in the topo bit map
|
||||
*/
|
||||
static void cfg_bitSet( /* RETURN: None */
|
||||
TOPO_MAP *m, /* OUT: bitmap */
|
||||
int n) /* IN: bit to set */
|
||||
{
|
||||
int word;
|
||||
|
||||
word = n / BITS_PER_H_UINT;
|
||||
if (word < (int)MAX_BIT_IDX) {
|
||||
if (word > m->msw)
|
||||
m->msw = word;
|
||||
m->bits[word] |= 1 << (n % BITS_PER_H_UINT);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add cache description to configuration
|
||||
*/
|
||||
static void cfg_cacheAdd( /* RETURN: None */
|
||||
HOST_CFG *anchor, /* IN-OUT: configuration */
|
||||
H_UINT src, /* IN: source */
|
||||
H_UINT cpu, /* IN: use -1 for all */
|
||||
H_UINT level, /* IN: cache level */
|
||||
H_UINT type, /* IN: cache type */
|
||||
H_UINT kb) /* IN: cache size in kb */
|
||||
{
|
||||
int i;
|
||||
|
||||
TUNE_DEBUG("cacheAdd(%x, %d,%d,%d,%c)\n", src, cpu, level, kb, type);
|
||||
if (3 < level || 0 ==kb) return;
|
||||
for(i = 0;i < anchor->ctCache;i++)
|
||||
if (anchor->caches[i].level == level &&
|
||||
anchor->caches[i].type == type &&
|
||||
anchor->caches[i].size == kb)
|
||||
break;
|
||||
if (i >= MAX_CACHES) return;
|
||||
if (-1 == (int)cpu)
|
||||
cfg_bitMerge(&anchor->caches[i].cpuMap, &anchor->pCacheInfo);
|
||||
else cfg_bitSet(&anchor->caches[i].cpuMap, cpu);
|
||||
anchor->caches[i].cpuMap.source |= src;
|
||||
if (i < anchor->ctCache) return;
|
||||
anchor->caches[i].level = level;
|
||||
anchor->caches[i].type = type;
|
||||
anchor->caches[i].size = kb;
|
||||
anchor->ctCache += 1;
|
||||
}
|
||||
/**
|
||||
* Add cpu description to configuration
|
||||
*/
|
||||
static void cfg_cpuAdd( /* RETURN: None */
|
||||
HOST_CFG *anchor, /* IN-OUT: configuration */
|
||||
H_UINT src, /* IN: source */
|
||||
CPU_INST *inst) /* IN: instance */
|
||||
{
|
||||
int i=0;
|
||||
|
||||
TUNE_DEBUG("cpuAdd(%x)\n", src);
|
||||
if (NULL==inst) {
|
||||
cfg_bitSet(&anchor->cpus[i].cpuMap, 0);
|
||||
anchor->ctCpu = 1;
|
||||
return;
|
||||
}
|
||||
for(i=0;i < anchor->ctCpu;i++)
|
||||
if (0 != cfg_bitIntersect(&anchor->cpus[i].cpuMap, &inst->cpuMap)) {
|
||||
cfg_bitMerge(&anchor->cpus[i].cpuMap, &inst->cpuMap);
|
||||
anchor->cpus[i].cpuMap.source |= src;
|
||||
return;
|
||||
}
|
||||
if (i >= MAX_CPUS) return;
|
||||
memcpy(&anchor->cpus[i], inst, sizeof(CPU_INST));
|
||||
anchor->cpus[i].cpuMap.source = src;
|
||||
anchor->ctCpu += 1;
|
||||
}
|
||||
#ifdef TUNE_DUMP
|
||||
/**
|
||||
* Diagnostic dump
|
||||
*/
|
||||
static void cfg_dump( /* RETURN: None */
|
||||
HOST_CFG *anchor) /* IN: configuration */
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0;i < anchor->ctCpu;i++)
|
||||
printf("Cpu: %08x\n",
|
||||
anchor->caches[i].cpuMap.source
|
||||
);
|
||||
for(i = 0;i < anchor->ctCache;i++)
|
||||
printf("Cache: %08x %d, %c, %d\n",
|
||||
anchor->caches[i].cpuMap.source,
|
||||
anchor->caches[i].level,
|
||||
anchor->caches[i].type,
|
||||
anchor->caches[i].size
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TUNING_CPUID_ENABLE
|
||||
/************************* CPUID support ***************************************/
|
||||
/**
|
||||
* Wrapper around the cpuid macro to assist in debugging
|
||||
*/
|
||||
static void cpuid( /* RETURN: none */
|
||||
int fn, /* IN: function code */
|
||||
int sfn, /* IN: subfunction */
|
||||
H_UINT *regs) /* IN-OUT: Workspace */
|
||||
{
|
||||
regs[2] = sfn;
|
||||
CPUID(fn, regs);
|
||||
}
|
||||
/**
|
||||
* Get configuration
|
||||
*/
|
||||
static void cpuid_config( /* RETURN: none */
|
||||
HOST_CFG *anchor) /* IN-OUT: result */
|
||||
{
|
||||
CPU_INST wsp;
|
||||
H_UINT regs[4];
|
||||
char *s;
|
||||
|
||||
if (HASCPUID(regs)) {
|
||||
memset(&wsp, 0, sizeof(CPU_INST));
|
||||
wsp.flags |= SRC_CPUID_PRESENT;
|
||||
cpuid(0x00,0,regs);
|
||||
wsp.maxFn = regs[EAX];
|
||||
s = wsp.vendor;
|
||||
CPUID_VENDOR(EBX);
|
||||
CPUID_VENDOR(EDX);
|
||||
CPUID_VENDOR(ECX);
|
||||
if (regs[EBX] == 0x68747541)
|
||||
wsp.flags |= SRC_CPUID_AMD;
|
||||
(void)cpuid(0x80000000,0,regs);
|
||||
wsp.maxFnx = regs[EAX];
|
||||
(void)cpuid(0x01,0,regs);
|
||||
wsp.signature = regs[EAX];
|
||||
if ((regs[EDX] & (1<<28)) != 0)
|
||||
wsp.flags |= SRC_CPUID_HT;
|
||||
TUNE_DEBUG("cpuid_config %s fn=%d fnx=%x flags=%x\n", (char *)wsp.vendor,
|
||||
wsp.maxFn, wsp.maxFnx, wsp.flags);
|
||||
if (0!=(wsp.flags & SRC_CPUID_AMD))
|
||||
cpuid_configAmd(anchor, &wsp);
|
||||
else cpuid_configIntel(anchor, &wsp);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* AMD cpuid Configuration. Reference: Publication 25481, Revision 2.34, Sept 2010
|
||||
*/
|
||||
static void cpuid_configAmd(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
CPU_INST *w) /* IN-OUT: Workspace */
|
||||
{
|
||||
H_UINT regs[4];
|
||||
int i, n;
|
||||
|
||||
switch((w->maxFnx&15)) {
|
||||
case 8:
|
||||
cpuid(0x80000008,0,regs);
|
||||
n = 1 + (regs[ECX] & 0xff);
|
||||
for(i=0;i<n;i++)
|
||||
cfg_bitSet(&w->cpuMap, i);
|
||||
cfg_cpuAdd(anchor, SRC_CPUID_AMD8, w);
|
||||
/* fallthrough */
|
||||
case 6:
|
||||
cpuid(0x80000006,0,regs);
|
||||
cfg_cacheAdd(anchor, SRC_CPUID_AMD6, -1, 2, 'U', (regs[ECX]>>16) & 0xffff);
|
||||
cfg_cacheAdd(anchor, SRC_CPUID_AMD6, -1, 3, 'U', ((regs[EDX]>>18) & 0x3fff)<<9);
|
||||
/* fallthrough */
|
||||
case 5:
|
||||
cpuid(0x80000005,0,regs);
|
||||
cfg_cacheAdd(anchor, SRC_CPUID_AMD5, -1, 1, 'D', (regs[ECX]>>24) & 0xff);
|
||||
cfg_cacheAdd(anchor, SRC_CPUID_AMD5, -1, 1, 'I', (regs[EDX]>>24) & 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Intel cpuid configuration. Reference: Publication 241618
|
||||
* Processor Identification and CPUID Instruction
|
||||
* Application node 485, Jan 2011
|
||||
*/
|
||||
static void cpuid_configIntel(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
CPU_INST *w) /* IN-OUT: Workspace */
|
||||
{
|
||||
H_UINT regs[4];
|
||||
|
||||
if (w->maxFn >=0x0b) {
|
||||
regs[ECX] = 0;
|
||||
cpuid(0x0b,0,regs);
|
||||
if (regs[EBX]!=0)
|
||||
w->flags |= SRC_CPUID_LEAFB;
|
||||
}
|
||||
#if 0
|
||||
if (w->flags & SRC_CPUID_HT)
|
||||
;
|
||||
else
|
||||
;
|
||||
#endif
|
||||
if (w->maxFn >=4)
|
||||
cpuid_configIntel4(anchor, w, regs);
|
||||
if (w->maxFn >= 2)
|
||||
cpuid_configIntel2(anchor, w, regs);
|
||||
}
|
||||
/**
|
||||
* Configure caches using cpuid leaf 2. This is a legacy method that only determines
|
||||
* level 1 cache. Still needed because trace cache is not reported elsewhere.
|
||||
*/
|
||||
static void cpuid_configIntel2(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
CPU_INST *w, /* IN-OUT: Workspace */
|
||||
H_UINT *regs) /* IN-OUT: registers */
|
||||
{
|
||||
/* L1 and Trace as per Intel application note 485, May 2012 */
|
||||
static const H_UINT defs[] = {
|
||||
0x06, 'I', 8 , /* 4-way set assoc, 32 byte line size */
|
||||
0x08, 'I', 16 , /* 4-way set assoc, 32 byte line size */
|
||||
0x09, 'I', 32 , /* 4-way set assoc, 64 byte line size + */
|
||||
0x0a, 'D', 8 , /* 2 way set assoc, 32 byte line size */
|
||||
0x0c, 'D', 16 , /* 4-way set assoc, 32 byte line size */
|
||||
0x0d, 'D', 16 , /* 4-way set assoc, 64 byte line size + */
|
||||
0x0e, 'D', 24 , /* 6-way set assoc, 64 byte line size */
|
||||
0x10, 'D', 16 , /* 4-way set assoc, 64 byte line size */
|
||||
0x15, 'I', 16 , /* 4-way set assoc, 64 byte line size */
|
||||
0x2c, 'D', 32 , /* 8-way set assoc, 64 byte line size */
|
||||
0x30, 'I', 32 , /* 8-way set assoc, 64 byte line size */
|
||||
0x60, 'D', 16 , /* 8-way set assoc, sectored cache, 64 byte line size */
|
||||
0x66, 'D', 8 , /* 4-way set assoc, sectored cache, 64 byte line size */
|
||||
0x67, 'D', 16 , /* 4-way set assoc, sectored cache, 64 byte line size */
|
||||
0x68, 'D', 32 , /* 4-way set assoc, sectored cache, 64 byte line size */
|
||||
0x70, 'T', 12 , /* 8-way set assoc, trace cache */
|
||||
0x71, 'T', 16 , /* 8-way set assoc, trace cache */
|
||||
0x72, 'T', 32 , /* 8-way set assoc, trace cache */
|
||||
0x73, 'T', 64 , /* 8-way set assoc, trace cache */
|
||||
0x00, 0, 0 /* sentinel */
|
||||
};
|
||||
H_UINT i, j, n, m;
|
||||
|
||||
cpuid(0x02,0,regs);
|
||||
n = regs[EAX]&0xff;
|
||||
while(n--) {
|
||||
for (i=0;i<4;i++) {
|
||||
if (0==(regs[i] & 0x80000000)) {
|
||||
while(0 != regs[i]) {
|
||||
m = regs[i] & 0xff;
|
||||
if (m==0xff)
|
||||
w->flags |= SRC_CPUID_LEAF4;
|
||||
else for (j=0;0 != defs[j];j += 3)
|
||||
if (defs[j]==m) {
|
||||
cfg_cacheAdd(anchor, SRC_CPUID_INTEL2, -1, 1, defs[j+1], defs[j+2]);
|
||||
break;
|
||||
}
|
||||
regs[i]>>=8;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n) cpuid(0x02,0,regs);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Configure caches using cpuid leaf 4
|
||||
*/
|
||||
static void cpuid_configIntel4(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
CPU_INST *w, /* IN-OUT: Workspace */
|
||||
H_UINT *regs) /* IN-OUT: registers */
|
||||
{
|
||||
H_UINT level, type;
|
||||
H_UINT i, j, lineSz, nParts, nWays, sz;
|
||||
|
||||
for(i=0;i<MAX_CACHES;i++) {
|
||||
cpuid(0x04,i,regs);
|
||||
if (0==i) {
|
||||
H_UINT n = 1 + (regs[EAX]>>26);
|
||||
for(j=0;j<n;j++)
|
||||
cfg_bitSet(&w->cpuMap, j);
|
||||
cfg_cpuAdd(anchor, SRC_CPUID_INTEL4, w);
|
||||
}
|
||||
switch(regs[EAX] & 31) {
|
||||
case 0: type = 0 ; break;
|
||||
case 1: type = 'D'; break;
|
||||
case 2: type = 'I'; break;
|
||||
case 3: type = 'U'; break;
|
||||
default: type = '?'; break;
|
||||
}
|
||||
if (0==type) break;
|
||||
regs[EAX] >>= 5;
|
||||
level = (H_UINT)(regs[EAX] & 7);
|
||||
lineSz = 1 + (regs[EBX] & 0xfff);
|
||||
regs[EBX] >>= 12;
|
||||
nParts = 1 + (regs[EBX] & 0x3ff);
|
||||
regs[EBX] >>= 10;
|
||||
nWays = 1 + regs[EBX];
|
||||
sz = (nWays * nParts * lineSz * (regs[ECX]+1)) / 1024;
|
||||
cfg_cacheAdd(anchor, SRC_CPUID_INTEL4, -1, level, type, sz);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/************************* CPUID support ***************************************/
|
||||
/************************* VFS support ***************************************/
|
||||
#ifdef TUNING_VFS_ENABLE
|
||||
/**
|
||||
* Get configuration
|
||||
*/
|
||||
static void vfs_config(
|
||||
HOST_CFG *anchor) /* IN-OUT: result */
|
||||
{
|
||||
char path[FILENAME_MAX];
|
||||
CPU_INST inst;
|
||||
H_UINT args[2];
|
||||
int n;
|
||||
|
||||
args[0] = args[1] = 0;
|
||||
snprintf(path, FILENAME_MAX, "%s/self/status", anchor->procfs);
|
||||
if (-1 != vfs_configFile(anchor, path, vfs_configStatus))
|
||||
args[0] |= SRC_VFS_STATUS;
|
||||
snprintf(path, FILENAME_MAX, "%s/devices/system/cpu/online", anchor->sysfs);
|
||||
if (-1 != vfs_configFile(anchor, path, vfs_configOnline))
|
||||
args[0] |= SRC_VFS_ONLINE;
|
||||
snprintf(path, FILENAME_MAX, "%s/cpuinfo", anchor->procfs);
|
||||
if (-1 != vfs_configFile(anchor, path, vfs_configCpuInfo))
|
||||
args[0] |= SRC_VFS_CPUINFO;
|
||||
snprintf(path, FILENAME_MAX, "%s/devices/system/cpu", anchor->sysfs);
|
||||
if (-1 != vfs_configDir(anchor, path, vfs_configCpuDir, args)) {
|
||||
memset(&inst, 0, sizeof(CPU_INST));
|
||||
args[0] |= SRC_VFS_CPUDIR;
|
||||
for(n=-1;(n=cfg_bitNext(&anchor->pCpuInfo,n))!=-1;)
|
||||
cfg_bitSet(&inst.cpuMap, n);
|
||||
if (cfg_bitCount(&inst.cpuMap)>0)
|
||||
cfg_cpuAdd(anchor, SRC_VFS_CPUINFO, &inst);
|
||||
}
|
||||
for(n=-1;(n=cfg_bitNext(&anchor->pCacheInfo,n))!=-1;) {
|
||||
snprintf(path, FILENAME_MAX, "%s/devices/system/cpu/cpu%d/cache", anchor->sysfs, n);
|
||||
args[1] = n;
|
||||
vfs_configDir(anchor, path, vfs_configInfoCache, args);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Call back to get cpus and from cpu subdirectories
|
||||
*/
|
||||
static int vfs_configCpuDir(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
char *input, /* filename */
|
||||
H_UINT *pArg) /* parameter */
|
||||
{
|
||||
|
||||
(void)pArg;
|
||||
if (strlen(input)> 3) {
|
||||
char term[32];
|
||||
int cpu;
|
||||
|
||||
cpu = atoi(input+3);
|
||||
(void)snprintf(term, 32, "cpu%d", cpu);
|
||||
if (!strcmp(term, input))
|
||||
cfg_bitSet(&anchor->pCacheInfo, cpu);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Call back to get cpus from cpuinfo
|
||||
*/
|
||||
static int vfs_configCpuInfo(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
char *input) /* input text */
|
||||
{
|
||||
char *s = strchr(input, ':');
|
||||
|
||||
if (NULL != s) {
|
||||
char key[32], value[32];
|
||||
*s++ = '\0';
|
||||
if (1==sscanf(input, "%31s", key) && 1==sscanf(s, "%31s", value)) {
|
||||
if (!strcmp("processor",key))
|
||||
cfg_bitSet(&anchor->pCpuInfo, atoi(value));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Process a configuration directory
|
||||
*/
|
||||
static int vfs_configDir(
|
||||
HOST_CFG *pAnchor, /* IN-OUT: result */
|
||||
char *path, /* IN: directory path */
|
||||
pDirFilter filter, /* IN: entry filter */
|
||||
H_UINT *pArg) /* IN: filter arg */
|
||||
{
|
||||
DIR *d;
|
||||
int rv=-1;
|
||||
|
||||
if (NULL != (d = opendir(path))) {
|
||||
struct dirent *ent;
|
||||
|
||||
while (NULL!=(ent = readdir(d))) {
|
||||
if (0!=(rv = (*filter)(pAnchor, ent->d_name, pArg)))
|
||||
break;
|
||||
}
|
||||
(void)closedir(d);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
/**
|
||||
* Process a configuration file
|
||||
*/
|
||||
static int vfs_configFile(
|
||||
HOST_CFG *pAnchor, /* IN-OUT: result */
|
||||
char *path, /* IN: file path */
|
||||
pFilter filter) /* IN: input filter */
|
||||
{
|
||||
FILE *f;
|
||||
int rv=-1;
|
||||
|
||||
if (NULL != (f = fopen(path, "rb"))) {
|
||||
char buf[VFS_LINESIZE];
|
||||
|
||||
while(fgets(buf, VFS_LINESIZE, f))
|
||||
if (0!=(rv = (*filter)(pAnchor, buf)))
|
||||
break;
|
||||
fclose(f);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
/**
|
||||
* Call back to get cache details
|
||||
*/
|
||||
static int vfs_configInfoCache(
|
||||
HOST_CFG *pAnchor, /* IN-OUT: result */
|
||||
char *input, /* IN: path name */
|
||||
H_UINT *pArgs)
|
||||
{
|
||||
if (strlen(input)> 5) {
|
||||
char path[FILENAME_MAX];
|
||||
int idx;
|
||||
|
||||
idx = atoi(input+5);
|
||||
(void)snprintf(path, 32, "index%d", idx);
|
||||
if (!strcmp(path, input)) {
|
||||
int plen, ctype, level, size;
|
||||
|
||||
plen = snprintf(path, FILENAME_MAX, "%s/devices/system/cpu/cpu%d/cache/index%d/level",
|
||||
pAnchor->sysfs, pArgs[1], idx) - 5;
|
||||
level = vfs_configFile(pAnchor, path, vfs_configInt);
|
||||
strcpy(path+plen, "type");
|
||||
ctype = vfs_configFile(pAnchor, path, vfs_configType);
|
||||
strcpy(path+plen, "size");
|
||||
size = vfs_configFile(pAnchor, path, vfs_configInt);
|
||||
if (size == -1)
|
||||
size = ctype == 'I' ? GENERIC_ICACHE : GENERIC_DCACHE;
|
||||
cfg_cacheAdd(pAnchor, SRC_VFS_INDEX, pArgs[1], level, ctype, size);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Call back to get cpus from online file
|
||||
*/
|
||||
static int vfs_configOnline(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
char *input) /* IN: input text */
|
||||
{
|
||||
vfs_parseList(&anchor->pOnline, input);
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* Call back to return a single integer input
|
||||
*/
|
||||
static int vfs_configInt(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
char *input) /* IN: input text */
|
||||
{
|
||||
(void)anchor;
|
||||
return atoi(input);
|
||||
}
|
||||
/**
|
||||
* Call back to get cpus and memory from status file
|
||||
*/
|
||||
static int vfs_configStatus(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
char *input) /* IN: input text */
|
||||
{
|
||||
char *s = strchr(input, ':');
|
||||
|
||||
if (NULL != s) {
|
||||
char key[32], value[VFS_LINESIZE-32];
|
||||
|
||||
*s++ = '\0';
|
||||
if (1==sscanf(input, "%31s", key) && 1==sscanf(s, "%223s", value)) {
|
||||
if (!strcmp("Cpus_allowed", key))
|
||||
vfs_parseMask(&anchor->pAllowed, value);
|
||||
else if (!strcmp("Mems_allowed", key))
|
||||
vfs_parseMask(&anchor->mAllowed, value);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Call back to return the first byte of input
|
||||
*/
|
||||
int vfs_configType(
|
||||
HOST_CFG *anchor, /* IN-OUT: result */
|
||||
char *input) /* IN: input text */
|
||||
{
|
||||
(void) anchor;
|
||||
return input[0];
|
||||
}
|
||||
/**
|
||||
* Parse the List format described in cpuset(7)
|
||||
*/
|
||||
static void vfs_parseList( /* RETURN: None */
|
||||
TOPO_MAP *map, /* OUT: bit map */
|
||||
char *input) /* IN: list text */
|
||||
{
|
||||
char *term, c;
|
||||
int bounds[2], n;
|
||||
|
||||
cfg_bitClear(map);
|
||||
for(term = strtok(input, ",");term != NULL;term = strtok(NULL, ",")) {
|
||||
n = bounds[0] = bounds[1] = 0;
|
||||
while(0 != (int)(c = *term++))
|
||||
switch(c) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
bounds[n] = bounds[n] * 10 + (int)(c - '0');
|
||||
break;
|
||||
case '-':
|
||||
n = 1;
|
||||
}
|
||||
cfg_bitSet(map, bounds[0]);
|
||||
if (0 != n)
|
||||
while(++bounds[0] <= bounds[1])
|
||||
cfg_bitSet(map, bounds[0]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parse the Mask format described in cpuset(7)
|
||||
*/
|
||||
static void vfs_parseMask( /* RETURN: None */
|
||||
TOPO_MAP *map, /* OUT: bit map */
|
||||
char *input) /* IN: list text */
|
||||
{
|
||||
char *term, c;
|
||||
int m, n;
|
||||
|
||||
cfg_bitClear(map);
|
||||
for(term = strtok(input, ",");term != NULL;term = strtok(NULL, ",")) {
|
||||
m = 0;
|
||||
while(0 != (int)(c = *term++))
|
||||
switch(c) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
m = m * 16 + (int)(c - '0');
|
||||
break;
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||
m = m * 16 + (int)(c - 'A') + 10;
|
||||
break;
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||
m = m * 16 + (int)(c - 'a') + 10;
|
||||
}
|
||||
for(n=map->msw;n>=0;n--)
|
||||
map->bits[n+1] = map->bits[n];
|
||||
if (0 != map->bits[map->msw+1])
|
||||
map->msw++;
|
||||
map->bits[0] = 0;
|
||||
for(n=0;n<32;n++)
|
||||
if (m & (1<<n))
|
||||
cfg_bitSet(map, n);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************* VFS support ***************************************/
|
||||
|
121
src/havegetune.h
Normal file
121
src/havegetune.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
** 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
|
||||
**
|
||||
** 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 HAVEGETUNE_H
|
||||
#define HAVEGETUNE_H
|
||||
|
||||
#include "havegecollect.h"
|
||||
/**
|
||||
* Some systems supply a maximum
|
||||
*/
|
||||
#ifndef FILENAME_MAX
|
||||
#define FILENAME_MAX 256 /* Max path length */
|
||||
#endif
|
||||
/**
|
||||
* Limits
|
||||
*/
|
||||
#define MAX_BIT_IDX (256/BITS_PER_H_UINT) /* Size of resource bitmaps */
|
||||
#define MAX_CACHES 8 /* Max cache types */
|
||||
#define MAX_CPUS 8 /* Max cpu types */
|
||||
/**
|
||||
* Object used to represent a set of objects
|
||||
*/
|
||||
typedef struct {
|
||||
H_UINT bits[MAX_BIT_IDX];
|
||||
int msw;
|
||||
H_UINT source;
|
||||
} TOPO_MAP;
|
||||
/**
|
||||
* Cache instance
|
||||
*/
|
||||
typedef struct {
|
||||
TOPO_MAP cpuMap; /* what cpus have this cache */
|
||||
H_UINT type; /* 'I'nstruction, 'D'ata, 'U'nified, 'T'race */
|
||||
H_UINT level; /* 0-15................ */
|
||||
H_UINT size; /* size in KB */
|
||||
} CACHE_INST;
|
||||
/**
|
||||
* Sources for CACHE_INST TOPO_MAP
|
||||
*/
|
||||
#define SRC_DEFAULT 0x00001
|
||||
#define SRC_PARAM 0x00002
|
||||
#define SRC_CPUID_AMD6 0x00004
|
||||
#define SRC_CPUID_AMD5 0x00008
|
||||
#define SRC_CPUID_INTEL2 0x00010
|
||||
#define SRC_CPUID_INTEL4 0x00020
|
||||
#define SRC_VFS_INDEX 0x00040
|
||||
/**
|
||||
* CPU instance
|
||||
*/
|
||||
typedef struct {
|
||||
TOPO_MAP cpuMap; /* what cpus have this config */
|
||||
H_UINT signature; /* processor signature */
|
||||
H_UINT flags;
|
||||
H_UINT maxFn;
|
||||
H_UINT maxFnx;
|
||||
char vendor[16];
|
||||
} CPU_INST;
|
||||
/**
|
||||
* Sources for CPU_INST TOPO_MAP
|
||||
*/
|
||||
#define SRC_CPUID_PRESENT 0x00100
|
||||
#define SRC_CPUID_HT 0x00200
|
||||
#define SRC_CPUID_AMD 0x00400
|
||||
#define SRC_CPUID_AMD8 0x00800
|
||||
#define SRC_CPUID_LEAFB 0x01000
|
||||
#define SRC_CPUID_LEAF4 0x02000
|
||||
#define SRC_VFS_STATUS 0x04000
|
||||
#define SRC_VFS_ONLINE 0x08000
|
||||
#define SRC_VFS_CPUINFO 0x10000
|
||||
#define SRC_VFS_CPUDIR 0x20000
|
||||
/**
|
||||
* Size of representation fields
|
||||
*/
|
||||
#define SZ_BUILDREP 32
|
||||
#define SZ_CPUREP 64
|
||||
#define SZ_CACHEREP 32
|
||||
/**
|
||||
* The result of tuning
|
||||
*/
|
||||
typedef struct {
|
||||
char *procfs; /* where proc is mounted */
|
||||
char *sysfs; /* where sys is mounted */
|
||||
char buildOpts[SZ_BUILDREP]; /* build options */
|
||||
char cpuOpts[SZ_CPUREP]; /* cpu options */
|
||||
char icacheOpts[SZ_CACHEREP]; /* icache options */
|
||||
char dcacheOpts[SZ_CACHEREP]; /* dcache options */
|
||||
TOPO_MAP pAllowed; /* allowed processors */
|
||||
TOPO_MAP pOnline; /* processors online */
|
||||
TOPO_MAP pCpuInfo; /* processors with info */
|
||||
TOPO_MAP pCacheInfo; /* processors with cache info */
|
||||
TOPO_MAP mAllowed; /* allowed memory */
|
||||
H_UINT a_cpu; /* suggested cpu */
|
||||
H_UINT i_tune; /* suggested i cache value */
|
||||
H_UINT d_tune; /* suggested d cache value */
|
||||
int ctCpu; /* number of cpu types */
|
||||
int ctCache; /* number of cache items */
|
||||
CPU_INST cpus[MAX_CPUS]; /* cpu instances */
|
||||
CACHE_INST caches[MAX_CACHES+2]; /* cache instances */
|
||||
} HOST_CFG;
|
||||
/**
|
||||
* Tuning interface
|
||||
*/
|
||||
void havege_tune(HOST_CFG *env, H_PARAMS *params);
|
||||
|
||||
#endif
|
201
src/oneiteration.h
Normal file
201
src/oneiteration.h
Normal file
|
@ -0,0 +1,201 @@
|
|||
/**
|
||||
** Simple entropy harvester based upon the havege RNG
|
||||
**
|
||||
** Copyright 2018-2021 Jirka Hladky hladky DOT jiri AT gmail DOT com
|
||||
** Copyright 2009-2013 Gary Wuertz gary@issiweb.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/>.
|
||||
**
|
||||
** This source is an adaptation of work released as
|
||||
**
|
||||
** Copyright (C) 2006 - André Seznec - Olivier Rochecouste
|
||||
**
|
||||
** under version 2.1 of the GNU Lesser General Public License
|
||||
**
|
||||
** The original form is retained with minor variable renames for
|
||||
** more consistent macro itilization. See havegecollect.c for
|
||||
** details.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* On average, one iteration accesses two 8-word blocks in the PWALK
|
||||
* table, and generates 16 words in the RESULT array.
|
||||
*
|
||||
* The data read in the Walk table are updated and permuted after each use.
|
||||
* The result of the hardware clock counter read is used for this update.
|
||||
*
|
||||
* 21 conditional tests are present. The conditional tests are grouped in
|
||||
* two nested groups of 10 conditional tests and 1 test that controls the
|
||||
* permutation.
|
||||
*
|
||||
* In average, there should be 4 tests executed and, in average, 2 of them
|
||||
* should be mispredicted.
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
PTTEST = PT >> 20;
|
||||
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PTTEST = PTTEST >> 1;
|
||||
pt = (PT >> 18) & 7;
|
||||
|
||||
PT = PT & ANDPT;
|
||||
|
||||
HARDCLOCKR(HTICK1);
|
||||
|
||||
Pt0 = &PWALK[PT];
|
||||
Pt1 = &PWALK[PT2];
|
||||
Pt2 = &PWALK[PT ^ 1];
|
||||
Pt3 = &PWALK[PT2 ^ 4];
|
||||
|
||||
RESULT[i++] ^= *Pt0;
|
||||
RESULT[i++] ^= *Pt1;
|
||||
RESULT[i++] ^= *Pt2;
|
||||
RESULT[i++] ^= *Pt3;
|
||||
|
||||
inter = ROR32(*Pt0,1) ^ HTICK1;
|
||||
*Pt0 = ROR32(*Pt1,2) ^ HTICK1;
|
||||
*Pt1 = inter;
|
||||
*Pt2 = ROR32(*Pt2, 3) ^ HTICK1;
|
||||
*Pt3 = ROR32(*Pt3, 4) ^ HTICK1;
|
||||
|
||||
Pt0 = &PWALK[PT ^ 2];
|
||||
Pt1 = &PWALK[PT2 ^ 2];
|
||||
Pt2 = &PWALK[PT ^ 3];
|
||||
Pt3 = &PWALK[PT2 ^ 6];
|
||||
|
||||
RESULT[i++] ^= *Pt0;
|
||||
RESULT[i++] ^= *Pt1;
|
||||
RESULT[i++] ^= *Pt2;
|
||||
RESULT[i++] ^= *Pt3;
|
||||
|
||||
if (PTTEST & 1) {
|
||||
Ptinter = Pt0;
|
||||
Pt2 = Pt0;
|
||||
Pt0 = Ptinter;
|
||||
}
|
||||
|
||||
PTTEST = (PT2 >> 18);
|
||||
inter = ROR32(*Pt0, 5) ^ HTICK1;
|
||||
*Pt0 = ROR32(*Pt1, 6) ^ HTICK1;
|
||||
*Pt1 = inter;
|
||||
|
||||
HARDCLOCKR(HTICK2);
|
||||
|
||||
*Pt2 = ROR32(*Pt2, 7) ^ HTICK2;
|
||||
*Pt3 = ROR32(*Pt3, 8) ^ HTICK2;
|
||||
|
||||
Pt0 = &PWALK[PT ^ 4];
|
||||
Pt1 = &PWALK[PT2 ^ 1];
|
||||
|
||||
PT2 = (RESULT[(i - 8) ^ PT1] ^ PWALK[PT2 ^ PT1 ^ 7]);
|
||||
PT2 = ((PT2 & ANDPT) & (0xfffffff7)) ^ ((PT ^ 8) & 0x8);
|
||||
|
||||
/* avoid PT and PT2 to point on the same cache block */
|
||||
PT1 = ((PT2 >> 28) & 7);
|
||||
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
if (PTTEST & 1) {
|
||||
PTTEST ^= 3; PTTEST = PTTEST >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Pt2 = &PWALK[PT ^ 5];
|
||||
Pt3 = &PWALK[PT2 ^ 5];
|
||||
|
||||
RESULT[i++] ^= *Pt0;
|
||||
RESULT[i++] ^= *Pt1;
|
||||
RESULT[i++] ^= *Pt2;
|
||||
RESULT[i++] ^= *Pt3;
|
||||
|
||||
inter = ROR32(*Pt0 , 9) ^ HTICK2;
|
||||
*Pt0 = ROR32(*Pt1 , 10) ^ HTICK2;
|
||||
*Pt1 = inter;
|
||||
*Pt2 = ROR32(*Pt2, 11) ^ HTICK2;
|
||||
*Pt3 = ROR32(*Pt3, 12) ^ HTICK2;
|
||||
|
||||
Pt0 = &PWALK[PT ^ 6];
|
||||
Pt1 = &PWALK[PT2 ^ 3];
|
||||
Pt2 = &PWALK[PT ^ 7];
|
||||
Pt3 = &PWALK[PT2 ^ 7];
|
||||
|
||||
RESULT[i++] ^= *Pt0;
|
||||
RESULT[i++] ^= *Pt1;
|
||||
RESULT[i++] ^= *Pt2;
|
||||
RESULT[i++] ^= *Pt3;
|
||||
|
||||
inter = ROR32(*Pt0, 13) ^ HTICK2;
|
||||
*Pt0 = ROR32(*Pt1, 14) ^ HTICK2;
|
||||
*Pt1 = inter;
|
||||
*Pt2 = ROR32(*Pt2, 15) ^ HTICK2;
|
||||
*Pt3 = ROR32(*Pt3, 16) ^ HTICK2;
|
||||
|
||||
/* avoid PT and PT2 to point on the same cache block */
|
||||
PT = (((RESULT[(i - 8) ^ pt] ^ PWALK[PT ^ pt ^ 7])) &
|
||||
(0xffffffef)) ^ ((PT2 ^ 0x10) & 0x10);
|
Loading…
Add table
Add a link
Reference in a new issue