git: 719721ca4b4e - stable/14 - LinuxKPI: add seq_hex_dump()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Apr 2025 14:36:57 UTC
The branch stable/14 has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=719721ca4b4e03f9e4945fb6ba31a18023a45a0c
commit 719721ca4b4e03f9e4945fb6ba31a18023a45a0c
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-04-02 18:06:05 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-04-18 14:35:58 +0000
LinuxKPI: add seq_hex_dump()
Move the implementation of print_hex_dump() into linux_compat.c as
lkpi_hex_dump() taking an extra function pointer and argument.
Add two internal wrappers for printf and sbuf_printf to get a common
function definition (sbuf_printf takes the extra argument).
Use these to implement print_hex_dump() and the newly added
seq_hex_dump().
This allows us to re-use the same implementation of print_hex_dump()
for both functions without duplicating the code.
Initial implementation: D49381 by dumbbell
Sponsored by: The FreeBSD Foundation
Reviewed by: dumbbell
Differential Revision: https://reviews.freebsd.org/D49637
(cherry picked from commit 4359672e656af5e6758d0aae147212e58f445f5b)
---
sys/compat/linuxkpi/common/include/linux/printk.h | 54 +++------------
.../linuxkpi/common/include/linux/seq_file.h | 14 ++++
sys/compat/linuxkpi/common/src/linux_compat.c | 80 ++++++++++++++++++++++
3 files changed, 102 insertions(+), 46 deletions(-)
diff --git a/sys/compat/linuxkpi/common/include/linux/printk.h b/sys/compat/linuxkpi/common/include/linux/printk.h
index 3840a6e5fb8a..da9d45122d4d 100644
--- a/sys/compat/linuxkpi/common/include/linux/printk.h
+++ b/sys/compat/linuxkpi/common/include/linux/printk.h
@@ -44,57 +44,19 @@ enum {
DUMP_PREFIX_OFFSET
};
+int __lkpi_hexdump_printf(void *, const char *, ...) __printflike(2, 3);
+
+void lkpi_hex_dump(int(*)(void *, const char *, ...), void *arg1,
+ const char *, const char *, const int, const int, const int,
+ const void *, size_t, const bool);
+
static inline void
print_hex_dump(const char *level, const char *prefix_str,
const int prefix_type, const int rowsize, const int groupsize,
const void *buf, size_t len, const bool ascii)
{
- typedef const struct { long long value; } __packed *print_64p_t;
- typedef const struct { uint32_t value; } __packed *print_32p_t;
- typedef const struct { uint16_t value; } __packed *print_16p_t;
- const void *buf_old = buf;
- int row;
-
- while (len > 0) {
- if (level != NULL)
- printf("%s", level);
- if (prefix_str != NULL)
- printf("%s ", prefix_str);
-
- switch (prefix_type) {
- case DUMP_PREFIX_ADDRESS:
- printf("[%p] ", buf);
- break;
- case DUMP_PREFIX_OFFSET:
- printf("[%#tx] ", ((const char *)buf -
- (const char *)buf_old));
- break;
- default:
- break;
- }
- for (row = 0; row != rowsize; row++) {
- if (groupsize == 8 && len > 7) {
- printf("%016llx ", ((print_64p_t)buf)->value);
- buf = (const uint8_t *)buf + 8;
- len -= 8;
- } else if (groupsize == 4 && len > 3) {
- printf("%08x ", ((print_32p_t)buf)->value);
- buf = (const uint8_t *)buf + 4;
- len -= 4;
- } else if (groupsize == 2 && len > 1) {
- printf("%04x ", ((print_16p_t)buf)->value);
- buf = (const uint8_t *)buf + 2;
- len -= 2;
- } else if (len > 0) {
- printf("%02x ", *(const uint8_t *)buf);
- buf = (const uint8_t *)buf + 1;
- len--;
- } else {
- break;
- }
- }
- printf("\n");
- }
+ lkpi_hex_dump(__lkpi_hexdump_printf, NULL, level, prefix_str, prefix_type,
+ rowsize, groupsize, buf, len, ascii);
}
static inline void
diff --git a/sys/compat/linuxkpi/common/include/linux/seq_file.h b/sys/compat/linuxkpi/common/include/linux/seq_file.h
index d8b327f59538..876ef9e8dfe5 100644
--- a/sys/compat/linuxkpi/common/include/linux/seq_file.h
+++ b/sys/compat/linuxkpi/common/include/linux/seq_file.h
@@ -28,9 +28,13 @@
#ifndef _LINUXKPI_LINUX_SEQ_FILE_H_
#define _LINUXKPI_LINUX_SEQ_FILE_H_
+#include <sys/types.h>
+#include <sys/sbuf.h>
+
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/string_helpers.h>
+#include <linux/printk.h>
#undef file
#define inode vnode
@@ -89,6 +93,16 @@ void lkpi_seq_printf(struct seq_file *m, const char *fmt, ...);
#define seq_vprintf(...) lkpi_seq_vprintf(__VA_ARGS__)
#define seq_printf(...) lkpi_seq_printf(__VA_ARGS__)
+int __lkpi_hexdump_sbuf_printf(void *, const char *, ...) __printflike(2, 3);
+
+static inline void
+seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type,
+ int rowsize, int groupsize, const void *buf, size_t len, bool ascii)
+{
+ lkpi_hex_dump(__lkpi_hexdump_sbuf_printf, m->buf, NULL, prefix_str, prefix_type,
+ rowsize, groupsize, buf, len, ascii);
+}
+
#define file linux_file
#endif /* _LINUXKPI_LINUX_SEQ_FILE_H_ */
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index a30523e88864..a2c2d18c8185 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -95,6 +95,8 @@
#include <linux/rcupdate.h>
#include <linux/interval_tree.h>
#include <linux/interval_tree_generic.h>
+#include <linux/printk.h>
+#include <linux/seq_file.h>
#if defined(__i386__) || defined(__amd64__)
#include <asm/smp.h>
@@ -1917,6 +1919,84 @@ kasprintf(gfp_t gfp, const char *fmt, ...)
return (p);
}
+int
+__lkpi_hexdump_printf(void *arg1 __unused, const char *fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, fmt);
+ result = vprintf(fmt, ap);
+ va_end(ap);
+ return (result);
+}
+
+int
+__lkpi_hexdump_sbuf_printf(void *arg1, const char *fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ va_start(ap, fmt);
+ result = sbuf_vprintf(arg1, fmt, ap);
+ va_end(ap);
+ return (result);
+}
+
+void
+lkpi_hex_dump(int(*_fpf)(void *, const char *, ...), void *arg1,
+ const char *level, const char *prefix_str,
+ const int prefix_type, const int rowsize, const int groupsize,
+ const void *buf, size_t len, const bool ascii)
+{
+ typedef const struct { long long value; } __packed *print_64p_t;
+ typedef const struct { uint32_t value; } __packed *print_32p_t;
+ typedef const struct { uint16_t value; } __packed *print_16p_t;
+ const void *buf_old = buf;
+ int row;
+
+ while (len > 0) {
+ if (level != NULL)
+ _fpf(arg1, "%s", level);
+ if (prefix_str != NULL)
+ _fpf(arg1, "%s ", prefix_str);
+
+ switch (prefix_type) {
+ case DUMP_PREFIX_ADDRESS:
+ _fpf(arg1, "[%p] ", buf);
+ break;
+ case DUMP_PREFIX_OFFSET:
+ _fpf(arg1, "[%#tx] ", ((const char *)buf -
+ (const char *)buf_old));
+ break;
+ default:
+ break;
+ }
+ for (row = 0; row != rowsize; row++) {
+ if (groupsize == 8 && len > 7) {
+ _fpf(arg1, "%016llx ", ((print_64p_t)buf)->value);
+ buf = (const uint8_t *)buf + 8;
+ len -= 8;
+ } else if (groupsize == 4 && len > 3) {
+ _fpf(arg1, "%08x ", ((print_32p_t)buf)->value);
+ buf = (const uint8_t *)buf + 4;
+ len -= 4;
+ } else if (groupsize == 2 && len > 1) {
+ _fpf(arg1, "%04x ", ((print_16p_t)buf)->value);
+ buf = (const uint8_t *)buf + 2;
+ len -= 2;
+ } else if (len > 0) {
+ _fpf(arg1, "%02x ", *(const uint8_t *)buf);
+ buf = (const uint8_t *)buf + 1;
+ len--;
+ } else {
+ break;
+ }
+ }
+ _fpf(arg1, "\n");
+ }
+}
+
static void
linux_timer_callback_wrapper(void *context)
{