void-packages/srcpkgs/jitterentropy/patches/0001-JENT-add-replacement-if-cache-sysconf-flags-not-avai.patch
2021-09-11 16:57:54 +02:00

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