196 lines
4.5 KiB
Diff
196 lines
4.5 KiB
Diff
src: upstream
|
|
reason: musl doesn't define these
|
|
|
|
From c185bcf2f87606b60303dc40f8fdd444f105c4b6 Mon Sep 17 00:00:00 2001
|
|
From: Stephan Mueller <smueller@chronox.de>
|
|
Date: Wed, 1 Sep 2021 07:30:08 +0200
|
|
Subject: [PATCH] JENT: add replacement if cache sysconf flags not available
|
|
|
|
If the sysconf calls for getting the cache size are not available, read
|
|
the data out of SysFS. The SysFS files for the CPU0 (which should exist
|
|
in all cases) are accessed and read. The read operation attempts to read
|
|
up to 3 cache entries, searching for data and unified caches. This
|
|
covers the same functionality as the sysconf calls.
|
|
|
|
If errors occur, the read cache sizes are zero which is appropriately
|
|
handled by the Jitter RNG code base.
|
|
|
|
Reported-by: stoickish
|
|
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
|
---
|
|
jitterentropy-base-user.h | 135 +++++++++++++++++++++++++++++++++-----
|
|
1 file changed, 119 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/jitterentropy-base-user.h b/jitterentropy-base-user.h
|
|
index 7c23c74..c2ddb5e 100644
|
|
--- a/jitterentropy-base-user.h
|
|
+++ b/jitterentropy-base-user.h
|
|
@@ -55,8 +55,10 @@
|
|
#undef OPENSSL
|
|
#endif
|
|
|
|
+#include <limits.h>
|
|
#include <time.h>
|
|
#include <stdint.h>
|
|
+#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
@@ -228,21 +230,113 @@ static inline long jent_ncpu(void)
|
|
#endif
|
|
}
|
|
|
|
+#ifdef __linux__
|
|
+
|
|
+# if defined(_SC_LEVEL1_DCACHE_SIZE) && \
|
|
+ defined(_SC_LEVEL2_CACHE_SIZE) && \
|
|
+ defined(_SC_LEVEL3_CACHE_SIZE)
|
|
+
|
|
+static inline void jent_get_cachesize(long *l1, long *l2, long *l3)
|
|
+{
|
|
+ *l1 = sysconf(_SC_LEVEL1_DCACHE_SIZE);
|
|
+ *l2 = sysconf(_SC_LEVEL2_CACHE_SIZE);
|
|
+ *l3 = sysconf(_SC_LEVEL3_CACHE_SIZE);
|
|
+}
|
|
+
|
|
+# else
|
|
+
|
|
+static inline void jent_get_cachesize(long *l1, long *l2, long *l3)
|
|
+{
|
|
+#define JENT_SYSFS_CACHE_DIR "/sys/devices/system/cpu/cpu0/cache"
|
|
+ long val;
|
|
+ unsigned int i;
|
|
+ char buf[10], file[50];
|
|
+ int fd = 0;
|
|
+
|
|
+ /* Iterate over all caches */
|
|
+ for (i = 0; i < 4; i++) {
|
|
+ unsigned int shift = 0;
|
|
+ char *ext;
|
|
+
|
|
+ /*
|
|
+ * Check the cache type - we are only interested in Unified
|
|
+ * and Data caches.
|
|
+ */
|
|
+ memset(buf, 0, sizeof(buf));
|
|
+ snprintf(file, sizeof(file), "%s/index%u/type",
|
|
+ JENT_SYSFS_CACHE_DIR, i);
|
|
+ fd = open(file, O_RDONLY);
|
|
+ if (fd < 0)
|
|
+ continue;
|
|
+ while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
|
|
+ close(fd);
|
|
+ buf[sizeof(buf) - 1] = '\0';
|
|
+
|
|
+ if (strncmp(buf, "Data", 4) && strncmp(buf, "Unified", 7))
|
|
+ continue;
|
|
+
|
|
+ /* Get size of cache */
|
|
+ memset(buf, 0, sizeof(buf));
|
|
+ snprintf(file, sizeof(file), "%s/index%u/size",
|
|
+ JENT_SYSFS_CACHE_DIR, i);
|
|
+
|
|
+ fd = open(file, O_RDONLY);
|
|
+ if (fd < 0)
|
|
+ continue;
|
|
+ while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
|
|
+ close(fd);
|
|
+ buf[sizeof(buf) - 1] = '\0';
|
|
+
|
|
+ ext = strstr(buf, "K");
|
|
+ if (ext) {
|
|
+ shift = 10;
|
|
+ ext = '\0';
|
|
+ } else {
|
|
+ ext = strstr(buf, "M");
|
|
+ if (ext) {
|
|
+ shift = 20;
|
|
+ ext = '\0';
|
|
+ }
|
|
+ }
|
|
+
|
|
+ val = strtol(buf, NULL, 10);
|
|
+ if (val == LONG_MAX)
|
|
+ continue;
|
|
+ val <<= shift;
|
|
+
|
|
+ if (!*l1)
|
|
+ *l1 = val;
|
|
+ else if (!*l2)
|
|
+ *l2 = val;
|
|
+ else {
|
|
+ *l3 = val;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+#undef JENT_SYSFS_CACHE_DIR
|
|
+}
|
|
+
|
|
+# endif
|
|
+
|
|
static inline uint32_t jent_cache_size_roundup(void)
|
|
{
|
|
-#ifdef __linux__
|
|
- long l1 = sysconf(_SC_LEVEL1_DCACHE_SIZE);
|
|
- long l2 = sysconf(_SC_LEVEL2_CACHE_SIZE);
|
|
- long l3 = sysconf(_SC_LEVEL3_CACHE_SIZE);
|
|
- uint32_t cache_size = 0;
|
|
-
|
|
- /* Cache size reported by system */
|
|
- if (l1 > 0)
|
|
- cache_size += (uint32_t)l1;
|
|
- if (l2 > 0)
|
|
- cache_size += (uint32_t)l2;
|
|
- if (l3 > 0)
|
|
- cache_size += (uint32_t)l3;
|
|
+ static int checked = 0;
|
|
+ static uint32_t cache_size = 0;
|
|
+
|
|
+ if (!checked) {
|
|
+ long l1 = 0, l2 = 0, l3 = 0;
|
|
+
|
|
+ jent_get_cachesize(&l1, &l2, &l3);
|
|
+ checked = 1;
|
|
+
|
|
+ /* Cache size reported by system */
|
|
+ if (l1 > 0)
|
|
+ cache_size += (uint32_t)l1;
|
|
+ if (l2 > 0)
|
|
+ cache_size += (uint32_t)l2;
|
|
+ if (l3 > 0)
|
|
+ cache_size += (uint32_t)l3;
|
|
+ }
|
|
|
|
/* Force the output_size to be of the form (bounding_power_of_2 - 1). */
|
|
cache_size |= (cache_size >> 1);
|
|
@@ -254,15 +348,24 @@ static inline uint32_t jent_cache_size_roundup(void)
|
|
if (cache_size == 0)
|
|
return 0;
|
|
|
|
- /* Make the output_size the smallest power of 2 strictly greater than cache_size. */
|
|
+ /*
|
|
+ * Make the output_size the smallest power of 2 strictly greater than
|
|
+ * cache_size.
|
|
+ */
|
|
cache_size++;
|
|
|
|
return cache_size;
|
|
-#else
|
|
+}
|
|
+
|
|
+#else /* __linux__ */
|
|
+
|
|
+static inline uint32_t jent_cache_size_roundup(void)
|
|
+{
|
|
return 0;
|
|
-#endif
|
|
}
|
|
|
|
+#endif /* __linux__ */
|
|
+
|
|
static inline void jent_yield(void)
|
|
{
|
|
sched_yield();
|
|
--
|
|
2.32.0
|
|
|