git: 650c012e519f - stable/14 - nvmecontrol: Fix to128 for big endian targets

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 27 Aug 2024 01:06:39 UTC
The branch stable/14 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=650c012e519fe027fdab6561d35380dcd0ac8e4b

commit 650c012e519fe027fdab6561d35380dcd0ac8e4b
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2024-04-16 22:35:59 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-08-26 18:31:02 +0000

    nvmecontrol: Fix to128 for big endian targets
    
    The source is always 128-bits in little endian format. For big endian
    hosts, we have to convert, or we print bogus numbers.
    
    Sponsored by:           Netflix
    Reviewed by:            chuck
    Differential Revision:  https://reviews.freebsd.org/D44651
    
    (cherry picked from commit 1c4b7effa7f9df64bf72c6291b4719cffb2ffe22)
---
 sbin/nvmecontrol/Makefile      |  1 -
 sbin/nvmecontrol/nvmecontrol.h | 27 +++++++++++++++++++--------
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile
index facb5f09835d..e3d363b123ed 100644
--- a/sbin/nvmecontrol/Makefile
+++ b/sbin/nvmecontrol/Makefile
@@ -1,4 +1,3 @@
-
 .include <src.opts.mk>
 
 PACKAGE=nvme-tools
diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h
index ed331327ae9e..4187c9bee432 100644
--- a/sbin/nvmecontrol/nvmecontrol.h
+++ b/sbin/nvmecontrol/nvmecontrol.h
@@ -91,22 +91,33 @@ void print_intel_add_smart(const struct nvme_controller_data *cdata __unused, vo
 
 /* Utility Routines */
 /*
- * 128-bit integer augments to standard values. On i386 this
- * doesn't exist, so we use 64-bit values. So, on 32-bit systems,
- * you'll get truncated values until someone implement 128bit
- * ints in software.
+ * C23 supports 128-bit integers via _BitInt(128). clang 16 and gcc 13 support
+ * this. Older compilers will support 128-bit ints on 64-bit
+ * platforms. Otherwise we truncate this to 64-bit on 32-bit systems with older
+ * compilers. We also check for > C18 instead of >= C23 because clang 17 was
+ * released before the the __STDC_VERSION__ was defined.
  */
 #define UINT128_DIG	39
-#ifdef __ILP32__
-typedef uint64_t uint128_t;
-#else
+#if __STDC_VERSION__ >= 202311L
+typedef unsigned _BitInt(128) uint128_t;
+#elif defined(__SIZEOF_INT128__)
 typedef __uint128_t uint128_t;
+#else
+typedef uint64_t uint128_t;
 #endif
 
 static __inline uint128_t
 to128(void *p)
 {
-	return *(uint128_t *)p;
+#if __STDC_VERSION__ >= 202311L || defined(__SIZEOF_INT128__)
+	uint64_t lo, hi;
+
+	lo = le64dec(p);
+	hi = le64dec((const char *)p + 8);
+	return ((uint128_t)hi << 64 | lo);
+#else
+	return (le64dec(p));
+#endif
 }
 
 uint64_t le48dec(const void *pp);