This is a bit hacky, but very handy if you want to customize the
panic screen.
It allows to dump the generated images to the logs, and then a python
script can convert it to .png files. It makes it easy to check how
the panic screen will look on different resolutions, without having
to crash a VM.
To not pollute the logs, it uses a monochrome framebuffer, compress
it with zlib, and base64 encode it.
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
---
drivers/gpu/drm/Kconfig.debug | 14 ++++
drivers/gpu/drm/tests/drm_panic_test.c | 111 +++++++++++++++++++++++++
scripts/kunitpanic2png.py | 53 ++++++++++++
3 files changed, 178 insertions(+)
create mode 100755 scripts/kunitpanic2png.py
diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug
index 05dc43c0b8c5..d8ae85132d32 100644
--- a/drivers/gpu/drm/Kconfig.debug
+++ b/drivers/gpu/drm/Kconfig.debug
@@ -84,6 +84,20 @@ config DRM_KUNIT_TEST
If in doubt, say "N".
+config DRM_PANIC_KUNIT_TEST_DUMP
+ bool "Enable screen dump to logs in KUnit tests for drm_panic"
+ default n
+ depends on DRM && DRM_PANIC && DRM_KUNIT_TEST
+ select ZLIB_DEFLATE
+ help
+ This allows to dump the panic screen to the KUnit tests logs.
+ It's possible with a small python script to write pngs from the logs.
+
+ This is only to help developers customizing the drm_panic screen,
+ checking the result for different resolutions.
+
+ If in doubt, say "N"
+
config DRM_TTM_KUNIT_TEST
tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS
default n
diff --git a/drivers/gpu/drm/tests/drm_panic_test.c b/drivers/gpu/drm/tests/drm_panic_test.c
index 46ff3e5e0e5d..8cddb845aea9 100644
--- a/drivers/gpu/drm/tests/drm_panic_test.c
+++ b/drivers/gpu/drm/tests/drm_panic_test.c
@@ -115,24 +115,135 @@ static void drm_test_panic_screen_user_page(struct kunit *test)
kfree(pages);
}
+#ifdef CONFIG_DRM_PANIC_KUNIT_TEST_DUMP
+#include <linux/base64.h>
+#include <linux/delay.h>
+#include <linux/zlib.h>
+
+#define LINE_LEN 128
+
+#define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
+
+static int compress_image(u8 *src, int size, u8 *dst)
+{
+ struct z_stream_s stream;
+
+ stream.workspace = kmalloc(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL),
+ GFP_KERNEL);
+
+ if (zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+ MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
+ return -EINVAL;
+
+ stream.next_in = src;
+ stream.avail_in = size;
+ stream.total_in = 0;
+ stream.next_out = dst;
+ stream.avail_out = size;
+ stream.total_out = 0;
+
+ if (zlib_deflate(&stream, Z_FINISH) != Z_STREAM_END)
+ return -EINVAL;
+
+ if (zlib_deflateEnd(&stream) != Z_OK)
+ return -EINVAL;
+
+ kfree(stream.workspace);
+
+ return stream.total_out;
+}
+
+static void dump_image(u8 *fb, unsigned int width, unsigned int height)
+{
+ int len = 0;
+ char *dst;
+ char *compressed;
+ int sent = 0;
+ int stride = DIV_ROUND_UP(width, 8);
+ int size = stride * height;
+
+ compressed = vzalloc(size);
+ if (!compressed)
+ return;
+ len = compress_image(fb, size, compressed);
+ if (len < 0) {
+ pr_err("Compression failed %d", len);
+ return;
+ }
+
+ dst = vzalloc(4 * DIV_ROUND_UP(len, 3) + 1);
+ if (!dst)
+ return;
+
+ len = base64_encode(compressed, len, dst);
+
+ pr_info("KUNIT PANIC IMAGE DUMP START %dx%d", width, height);
+ while (len > 0) {
+ char save = dst[sent + LINE_LEN];
+
+ dst[sent + LINE_LEN] = 0;
+ pr_info("%s", dst + sent);
+ dst[sent + LINE_LEN] = save;
+ sent += LINE_LEN;
+ len -= LINE_LEN;
+ }
+ pr_info("KUNIT PANIC IMAGE DUMP END");
+ vfree(compressed);
+ vfree(dst);
+
+}
+
+// Ignore pixel format, use 1bit per pixel in monochrome.
static void drm_test_panic_set_pixel(struct drm_scanout_buffer *sb,
unsigned int x,
unsigned int y,
u32 color)
{
+ int stride = DIV_ROUND_UP(sb->width, 8);
+ size_t off = x / 8 + y * stride;
+ u8 shift = 7 - (x % 8);
+ u8 *fb = (u8 *) sb->private;
+
+ if (color)
+ fb[off] |= 1 << shift;
+ else
+ fb[off] &= ~(1 << shift);
}
+#else
+static void dump_image(u8 *fb, unsigned int width, unsigned int height) {}
+static void drm_test_panic_set_pixel(struct drm_scanout_buffer *sb,
+ unsigned int x,
+ unsigned int y,
+ u32 color)
+{
+}
+#endif
+
static void drm_test_panic_screen_user_set_pixel(struct kunit *test)
{
struct drm_scanout_buffer *sb = test->priv;
const struct drm_test_mode *params = test->param_value;
+ int fb_size;
+ u8 *fb;
sb->format = drm_format_info(params->format);
+ fb_size = DIV_ROUND_UP(params->width, 8) * params->height;
+
+ fb = vzalloc(fb_size);
+ KUNIT_ASSERT_NOT_NULL(test, fb);
+ sb->private = fb;
sb->set_pixel = drm_test_panic_set_pixel;
sb->width = params->width;
sb->height = params->height;
params->draw_screen(sb);
+ if (params->format == DRM_FORMAT_XRGB8888)
+ dump_image(fb, sb->width, sb->height);
+
+ vfree(fb);
}
static void drm_test_panic_desc(const struct drm_test_mode *t, char *desc)
diff --git a/scripts/kunitpanic2png.py b/scripts/kunitpanic2png.py
new file mode 100755
index 000000000000..e292afd7422c
--- /dev/null
+++ b/scripts/kunitpanic2png.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: MIT
+#
+# Copyright (c) 2025 Red Hat.
+# Author: Jocelyn Falempe <jfalempe@redhat.com>
+
+from argparse import ArgumentParser
+from PIL import Image
+import base64
+import zlib
+
+def get_dim(s):
+ (w, h) = s.split('x')
+ return (int(w), int(h))
+
+def draw_image(img_data, width, height, n_img):
+
+ decoded = base64.b64decode(img_data)
+ unzipped = zlib.decompress(decoded)
+
+ img = Image.frombytes("1", (width, height), unzipped)
+ fname = f"panic_screen_{n_img}.png"
+ img.save(fname)
+ print(f"Image {width}x{height} saved to {fname}")
+
+def main():
+ parser = ArgumentParser(
+ prog="kunitpanic2png",
+ description="Read drm_panic kunit logs and translate that to png files")
+
+ parser.add_argument("filename", help="log file from kunit, usually test.log")
+
+ parsing_img = False
+ img_data = ""
+ n_img = 0
+
+ args = parser.parse_args()
+ with open(args.filename, "r") as f:
+ for line in f.readlines():
+ if line.startswith("KUNIT PANIC IMAGE DUMP START"):
+ parsing_img = True
+ width, height = get_dim(line.split()[-1])
+ continue
+ if line.startswith("KUNIT PANIC IMAGE DUMP END"):
+ draw_image(img_data, width, height, n_img)
+ parsing_img = False
+ img_data = ""
+ n_img += 1
+ continue
+ if parsing_img:
+ img_data += line.strip()
+
+main()
--
2.50.1
Hi Am 21.08.25 um 11:49 schrieb Jocelyn Falempe: > This is a bit hacky, but very handy if you want to customize the > panic screen. > It allows to dump the generated images to the logs, and then a python > script can convert it to .png files. It makes it easy to check how > the panic screen will look on different resolutions, without having > to crash a VM. > To not pollute the logs, it uses a monochrome framebuffer, compress > it with zlib, and base64 encode it. May I suggest to export the raw image via debugfs? Debugfs can also export additional information in additional files, such as width/height/stride/format. This could provide the real/last image on the fly, simply by reading the files. No workarounds or encodings needed. Best regards Thomas > > Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com> > --- > drivers/gpu/drm/Kconfig.debug | 14 ++++ > drivers/gpu/drm/tests/drm_panic_test.c | 111 +++++++++++++++++++++++++ > scripts/kunitpanic2png.py | 53 ++++++++++++ > 3 files changed, 178 insertions(+) > create mode 100755 scripts/kunitpanic2png.py > > diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug > index 05dc43c0b8c5..d8ae85132d32 100644 > --- a/drivers/gpu/drm/Kconfig.debug > +++ b/drivers/gpu/drm/Kconfig.debug > @@ -84,6 +84,20 @@ config DRM_KUNIT_TEST > > If in doubt, say "N". > > +config DRM_PANIC_KUNIT_TEST_DUMP > + bool "Enable screen dump to logs in KUnit tests for drm_panic" > + default n > + depends on DRM && DRM_PANIC && DRM_KUNIT_TEST > + select ZLIB_DEFLATE > + help > + This allows to dump the panic screen to the KUnit tests logs. > + It's possible with a small python script to write pngs from the logs. > + > + This is only to help developers customizing the drm_panic screen, > + checking the result for different resolutions. > + > + If in doubt, say "N" > + > config DRM_TTM_KUNIT_TEST > tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS > default n > diff --git a/drivers/gpu/drm/tests/drm_panic_test.c b/drivers/gpu/drm/tests/drm_panic_test.c > index 46ff3e5e0e5d..8cddb845aea9 100644 > --- a/drivers/gpu/drm/tests/drm_panic_test.c > +++ b/drivers/gpu/drm/tests/drm_panic_test.c > @@ -115,24 +115,135 @@ static void drm_test_panic_screen_user_page(struct kunit *test) > kfree(pages); > } > > +#ifdef CONFIG_DRM_PANIC_KUNIT_TEST_DUMP > +#include <linux/base64.h> > +#include <linux/delay.h> > +#include <linux/zlib.h> > + > +#define LINE_LEN 128 > + > +#define COMPR_LEVEL 6 > +#define WINDOW_BITS 12 > +#define MEM_LEVEL 4 > + > +static int compress_image(u8 *src, int size, u8 *dst) > +{ > + struct z_stream_s stream; > + > + stream.workspace = kmalloc(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), > + GFP_KERNEL); > + > + if (zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, > + MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) > + return -EINVAL; > + > + stream.next_in = src; > + stream.avail_in = size; > + stream.total_in = 0; > + stream.next_out = dst; > + stream.avail_out = size; > + stream.total_out = 0; > + > + if (zlib_deflate(&stream, Z_FINISH) != Z_STREAM_END) > + return -EINVAL; > + > + if (zlib_deflateEnd(&stream) != Z_OK) > + return -EINVAL; > + > + kfree(stream.workspace); > + > + return stream.total_out; > +} > + > +static void dump_image(u8 *fb, unsigned int width, unsigned int height) > +{ > + int len = 0; > + char *dst; > + char *compressed; > + int sent = 0; > + int stride = DIV_ROUND_UP(width, 8); > + int size = stride * height; > + > + compressed = vzalloc(size); > + if (!compressed) > + return; > + len = compress_image(fb, size, compressed); > + if (len < 0) { > + pr_err("Compression failed %d", len); > + return; > + } > + > + dst = vzalloc(4 * DIV_ROUND_UP(len, 3) + 1); > + if (!dst) > + return; > + > + len = base64_encode(compressed, len, dst); > + > + pr_info("KUNIT PANIC IMAGE DUMP START %dx%d", width, height); > + while (len > 0) { > + char save = dst[sent + LINE_LEN]; > + > + dst[sent + LINE_LEN] = 0; > + pr_info("%s", dst + sent); > + dst[sent + LINE_LEN] = save; > + sent += LINE_LEN; > + len -= LINE_LEN; > + } > + pr_info("KUNIT PANIC IMAGE DUMP END"); > + vfree(compressed); > + vfree(dst); > + > +} > + > +// Ignore pixel format, use 1bit per pixel in monochrome. > static void drm_test_panic_set_pixel(struct drm_scanout_buffer *sb, > unsigned int x, > unsigned int y, > u32 color) > { > + int stride = DIV_ROUND_UP(sb->width, 8); > + size_t off = x / 8 + y * stride; > + u8 shift = 7 - (x % 8); > + u8 *fb = (u8 *) sb->private; > + > + if (color) > + fb[off] |= 1 << shift; > + else > + fb[off] &= ~(1 << shift); > } > > +#else > +static void dump_image(u8 *fb, unsigned int width, unsigned int height) {} > +static void drm_test_panic_set_pixel(struct drm_scanout_buffer *sb, > + unsigned int x, > + unsigned int y, > + u32 color) > +{ > +} > +#endif > + > static void drm_test_panic_screen_user_set_pixel(struct kunit *test) > { > struct drm_scanout_buffer *sb = test->priv; > const struct drm_test_mode *params = test->param_value; > + int fb_size; > + u8 *fb; > > sb->format = drm_format_info(params->format); > + fb_size = DIV_ROUND_UP(params->width, 8) * params->height; > + > + fb = vzalloc(fb_size); > + KUNIT_ASSERT_NOT_NULL(test, fb); > + sb->private = fb; > sb->set_pixel = drm_test_panic_set_pixel; > sb->width = params->width; > sb->height = params->height; > > params->draw_screen(sb); > + if (params->format == DRM_FORMAT_XRGB8888) > + dump_image(fb, sb->width, sb->height); > + > + vfree(fb); > } > > static void drm_test_panic_desc(const struct drm_test_mode *t, char *desc) > diff --git a/scripts/kunitpanic2png.py b/scripts/kunitpanic2png.py > new file mode 100755 > index 000000000000..e292afd7422c > --- /dev/null > +++ b/scripts/kunitpanic2png.py > @@ -0,0 +1,53 @@ > +#!/usr/bin/env python3 > +# SPDX-License-Identifier: MIT > +# > +# Copyright (c) 2025 Red Hat. > +# Author: Jocelyn Falempe <jfalempe@redhat.com> > + > +from argparse import ArgumentParser > +from PIL import Image > +import base64 > +import zlib > + > +def get_dim(s): > + (w, h) = s.split('x') > + return (int(w), int(h)) > + > +def draw_image(img_data, width, height, n_img): > + > + decoded = base64.b64decode(img_data) > + unzipped = zlib.decompress(decoded) > + > + img = Image.frombytes("1", (width, height), unzipped) > + fname = f"panic_screen_{n_img}.png" > + img.save(fname) > + print(f"Image {width}x{height} saved to {fname}") > + > +def main(): > + parser = ArgumentParser( > + prog="kunitpanic2png", > + description="Read drm_panic kunit logs and translate that to png files") > + > + parser.add_argument("filename", help="log file from kunit, usually test.log") > + > + parsing_img = False > + img_data = "" > + n_img = 0 > + > + args = parser.parse_args() > + with open(args.filename, "r") as f: > + for line in f.readlines(): > + if line.startswith("KUNIT PANIC IMAGE DUMP START"): > + parsing_img = True > + width, height = get_dim(line.split()[-1]) > + continue > + if line.startswith("KUNIT PANIC IMAGE DUMP END"): > + draw_image(img_data, width, height, n_img) > + parsing_img = False > + img_data = "" > + n_img += 1 > + continue > + if parsing_img: > + img_data += line.strip() > + > +main() -- -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Frankenstrasse 146, 90461 Nuernberg, Germany GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman HRB 36809 (AG Nuernberg)
On 27/08/2025 12:45, Thomas Zimmermann wrote: > Hi > > Am 21.08.25 um 11:49 schrieb Jocelyn Falempe: >> This is a bit hacky, but very handy if you want to customize the >> panic screen. >> It allows to dump the generated images to the logs, and then a python >> script can convert it to .png files. It makes it easy to check how >> the panic screen will look on different resolutions, without having >> to crash a VM. >> To not pollute the logs, it uses a monochrome framebuffer, compress >> it with zlib, and base64 encode it. > > May I suggest to export the raw image via debugfs? Debugfs can also > export additional information in additional files, such as width/height/ > stride/format. This could provide the real/last image on the fly, simply > by reading the files. No workarounds or encodings needed. I'm looking into that. The difficulty is to get the debugfs content outside of the test kernel. As I'm using a uml kernel for testing, I will need a special initrd, and a way to share files with the host. Best regards, -- Jocelyn > > Best regards > Thomas > >> >> Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com> >> --- >> drivers/gpu/drm/Kconfig.debug | 14 ++++ >> drivers/gpu/drm/tests/drm_panic_test.c | 111 +++++++++++++++++++++++++ >> scripts/kunitpanic2png.py | 53 ++++++++++++ >> 3 files changed, 178 insertions(+) >> create mode 100755 scripts/kunitpanic2png.py >> >> diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/ >> Kconfig.debug >> index 05dc43c0b8c5..d8ae85132d32 100644 >> --- a/drivers/gpu/drm/Kconfig.debug >> +++ b/drivers/gpu/drm/Kconfig.debug >> @@ -84,6 +84,20 @@ config DRM_KUNIT_TEST >> If in doubt, say "N". >> +config DRM_PANIC_KUNIT_TEST_DUMP >> + bool "Enable screen dump to logs in KUnit tests for drm_panic" >> + default n >> + depends on DRM && DRM_PANIC && DRM_KUNIT_TEST >> + select ZLIB_DEFLATE >> + help >> + This allows to dump the panic screen to the KUnit tests logs. >> + It's possible with a small python script to write pngs from the >> logs. >> + >> + This is only to help developers customizing the drm_panic screen, >> + checking the result for different resolutions. >> + >> + If in doubt, say "N" >> + >> config DRM_TTM_KUNIT_TEST >> tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS >> default n >> diff --git a/drivers/gpu/drm/tests/drm_panic_test.c b/drivers/gpu/drm/ >> tests/drm_panic_test.c >> index 46ff3e5e0e5d..8cddb845aea9 100644 >> --- a/drivers/gpu/drm/tests/drm_panic_test.c >> +++ b/drivers/gpu/drm/tests/drm_panic_test.c >> @@ -115,24 +115,135 @@ static void >> drm_test_panic_screen_user_page(struct kunit *test) >> kfree(pages); >> } >> +#ifdef CONFIG_DRM_PANIC_KUNIT_TEST_DUMP >> +#include <linux/base64.h> >> +#include <linux/delay.h> >> +#include <linux/zlib.h> >> + >> +#define LINE_LEN 128 >> + >> +#define COMPR_LEVEL 6 >> +#define WINDOW_BITS 12 >> +#define MEM_LEVEL 4 >> + >> +static int compress_image(u8 *src, int size, u8 *dst) >> +{ >> + struct z_stream_s stream; >> + >> + stream.workspace = >> kmalloc(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), >> + GFP_KERNEL); >> + >> + if (zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, >> + MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) >> + return -EINVAL; >> + >> + stream.next_in = src; >> + stream.avail_in = size; >> + stream.total_in = 0; >> + stream.next_out = dst; >> + stream.avail_out = size; >> + stream.total_out = 0; >> + >> + if (zlib_deflate(&stream, Z_FINISH) != Z_STREAM_END) >> + return -EINVAL; >> + >> + if (zlib_deflateEnd(&stream) != Z_OK) >> + return -EINVAL; >> + >> + kfree(stream.workspace); >> + >> + return stream.total_out; >> +} >> + >> +static void dump_image(u8 *fb, unsigned int width, unsigned int height) >> +{ >> + int len = 0; >> + char *dst; >> + char *compressed; >> + int sent = 0; >> + int stride = DIV_ROUND_UP(width, 8); >> + int size = stride * height; >> + >> + compressed = vzalloc(size); >> + if (!compressed) >> + return; >> + len = compress_image(fb, size, compressed); >> + if (len < 0) { >> + pr_err("Compression failed %d", len); >> + return; >> + } >> + >> + dst = vzalloc(4 * DIV_ROUND_UP(len, 3) + 1); >> + if (!dst) >> + return; >> + >> + len = base64_encode(compressed, len, dst); >> + >> + pr_info("KUNIT PANIC IMAGE DUMP START %dx%d", width, height); >> + while (len > 0) { >> + char save = dst[sent + LINE_LEN]; >> + >> + dst[sent + LINE_LEN] = 0; >> + pr_info("%s", dst + sent); >> + dst[sent + LINE_LEN] = save; >> + sent += LINE_LEN; >> + len -= LINE_LEN; >> + } >> + pr_info("KUNIT PANIC IMAGE DUMP END"); >> + vfree(compressed); >> + vfree(dst); >> + >> +} >> + >> +// Ignore pixel format, use 1bit per pixel in monochrome. >> static void drm_test_panic_set_pixel(struct drm_scanout_buffer *sb, >> unsigned int x, >> unsigned int y, >> u32 color) >> { >> + int stride = DIV_ROUND_UP(sb->width, 8); >> + size_t off = x / 8 + y * stride; >> + u8 shift = 7 - (x % 8); >> + u8 *fb = (u8 *) sb->private; >> + >> + if (color) >> + fb[off] |= 1 << shift; >> + else >> + fb[off] &= ~(1 << shift); >> } >> +#else >> +static void dump_image(u8 *fb, unsigned int width, unsigned int >> height) {} >> +static void drm_test_panic_set_pixel(struct drm_scanout_buffer *sb, >> + unsigned int x, >> + unsigned int y, >> + u32 color) >> +{ >> +} >> +#endif >> + >> static void drm_test_panic_screen_user_set_pixel(struct kunit *test) >> { >> struct drm_scanout_buffer *sb = test->priv; >> const struct drm_test_mode *params = test->param_value; >> + int fb_size; >> + u8 *fb; >> sb->format = drm_format_info(params->format); >> + fb_size = DIV_ROUND_UP(params->width, 8) * params->height; >> + >> + fb = vzalloc(fb_size); >> + KUNIT_ASSERT_NOT_NULL(test, fb); >> + sb->private = fb; >> sb->set_pixel = drm_test_panic_set_pixel; >> sb->width = params->width; >> sb->height = params->height; >> params->draw_screen(sb); >> + if (params->format == DRM_FORMAT_XRGB8888) >> + dump_image(fb, sb->width, sb->height); >> + >> + vfree(fb); >> } >> static void drm_test_panic_desc(const struct drm_test_mode *t, char >> *desc) >> diff --git a/scripts/kunitpanic2png.py b/scripts/kunitpanic2png.py >> new file mode 100755 >> index 000000000000..e292afd7422c >> --- /dev/null >> +++ b/scripts/kunitpanic2png.py >> @@ -0,0 +1,53 @@ >> +#!/usr/bin/env python3 >> +# SPDX-License-Identifier: MIT >> +# >> +# Copyright (c) 2025 Red Hat. >> +# Author: Jocelyn Falempe <jfalempe@redhat.com> >> + >> +from argparse import ArgumentParser >> +from PIL import Image >> +import base64 >> +import zlib >> + >> +def get_dim(s): >> + (w, h) = s.split('x') >> + return (int(w), int(h)) >> + >> +def draw_image(img_data, width, height, n_img): >> + >> + decoded = base64.b64decode(img_data) >> + unzipped = zlib.decompress(decoded) >> + >> + img = Image.frombytes("1", (width, height), unzipped) >> + fname = f"panic_screen_{n_img}.png" >> + img.save(fname) >> + print(f"Image {width}x{height} saved to {fname}") >> + >> +def main(): >> + parser = ArgumentParser( >> + prog="kunitpanic2png", >> + description="Read drm_panic kunit logs and translate that to >> png files") >> + >> + parser.add_argument("filename", help="log file from kunit, >> usually test.log") >> + >> + parsing_img = False >> + img_data = "" >> + n_img = 0 >> + >> + args = parser.parse_args() >> + with open(args.filename, "r") as f: >> + for line in f.readlines(): >> + if line.startswith("KUNIT PANIC IMAGE DUMP START"): >> + parsing_img = True >> + width, height = get_dim(line.split()[-1]) >> + continue >> + if line.startswith("KUNIT PANIC IMAGE DUMP END"): >> + draw_image(img_data, width, height, n_img) >> + parsing_img = False >> + img_data = "" >> + n_img += 1 >> + continue >> + if parsing_img: >> + img_data += line.strip() >> + >> +main() >
On Mon, Sep 01, 2025 at 03:04:26PM +0200, Jocelyn Falempe wrote: > On 27/08/2025 12:45, Thomas Zimmermann wrote: > > Hi > > > > Am 21.08.25 um 11:49 schrieb Jocelyn Falempe: > > > This is a bit hacky, but very handy if you want to customize the > > > panic screen. > > > It allows to dump the generated images to the logs, and then a python > > > script can convert it to .png files. It makes it easy to check how > > > the panic screen will look on different resolutions, without having > > > to crash a VM. > > > To not pollute the logs, it uses a monochrome framebuffer, compress > > > it with zlib, and base64 encode it. > > > > May I suggest to export the raw image via debugfs? Debugfs can also > > export additional information in additional files, such as width/height/ > > stride/format. This could provide the real/last image on the fly, simply > > by reading the files. No workarounds or encodings needed. > > I'm looking into that. The difficulty is to get the debugfs content outside > of the test kernel. As I'm using a uml kernel for testing, I will need a > special initrd, and a way to share files with the host. Yeah, I agree that it's not very practical. If only because the test context doesn't stick around once it's been executed, so you would effectively leak an arbritrarily long buffer with no hope of getting back its memory. Maxime
On 02/09/2025 18:58, Maxime Ripard wrote: > On Mon, Sep 01, 2025 at 03:04:26PM +0200, Jocelyn Falempe wrote: >> On 27/08/2025 12:45, Thomas Zimmermann wrote: >>> Hi >>> >>> Am 21.08.25 um 11:49 schrieb Jocelyn Falempe: >>>> This is a bit hacky, but very handy if you want to customize the >>>> panic screen. >>>> It allows to dump the generated images to the logs, and then a python >>>> script can convert it to .png files. It makes it easy to check how >>>> the panic screen will look on different resolutions, without having >>>> to crash a VM. >>>> To not pollute the logs, it uses a monochrome framebuffer, compress >>>> it with zlib, and base64 encode it. >>> >>> May I suggest to export the raw image via debugfs? Debugfs can also >>> export additional information in additional files, such as width/height/ >>> stride/format. This could provide the real/last image on the fly, simply >>> by reading the files. No workarounds or encodings needed. >> >> I'm looking into that. The difficulty is to get the debugfs content outside >> of the test kernel. As I'm using a uml kernel for testing, I will need a >> special initrd, and a way to share files with the host. > > Yeah, I agree that it's not very practical. If only because the test > context doesn't stick around once it's been executed, so you would > effectively leak an arbritrarily long buffer with no hope of getting > back its memory. I've made a prototype with debugfs, a small ramdisk with busybox, and using hostfs to mount the host filesystem in the uml kernel, and it allows to dump the raw panic buffer easily. Even if it's a bit more complex to setup, I think this use case is not really a kunit test, so it's probably better that way. Let me a few days to clean that up, and I will send a v2 of the kunit tests, and a new series to add a debugfs interface. Thanks for your reviews, -- Jocelyn > > Maxime
On Wed, Sep 03, 2025 at 09:30:23AM +0200, Jocelyn Falempe wrote: > On 02/09/2025 18:58, Maxime Ripard wrote: > > On Mon, Sep 01, 2025 at 03:04:26PM +0200, Jocelyn Falempe wrote: > > > On 27/08/2025 12:45, Thomas Zimmermann wrote: > > > > Hi > > > > > > > > Am 21.08.25 um 11:49 schrieb Jocelyn Falempe: > > > > > This is a bit hacky, but very handy if you want to customize the > > > > > panic screen. > > > > > It allows to dump the generated images to the logs, and then a python > > > > > script can convert it to .png files. It makes it easy to check how > > > > > the panic screen will look on different resolutions, without having > > > > > to crash a VM. > > > > > To not pollute the logs, it uses a monochrome framebuffer, compress > > > > > it with zlib, and base64 encode it. > > > > > > > > May I suggest to export the raw image via debugfs? Debugfs can also > > > > export additional information in additional files, such as width/height/ > > > > stride/format. This could provide the real/last image on the fly, simply > > > > by reading the files. No workarounds or encodings needed. > > > > > > I'm looking into that. The difficulty is to get the debugfs content outside > > > of the test kernel. As I'm using a uml kernel for testing, I will need a > > > special initrd, and a way to share files with the host. > > > > Yeah, I agree that it's not very practical. If only because the test > > context doesn't stick around once it's been executed, so you would > > effectively leak an arbritrarily long buffer with no hope of getting > > back its memory. > > I've made a prototype with debugfs, a small ramdisk with busybox, and using > hostfs to mount the host filesystem in the uml kernel, and it allows to dump > the raw panic buffer easily. > Even if it's a bit more complex to setup, I think this use case is not > really a kunit test, so it's probably better that way. > > Let me a few days to clean that up, and I will send a v2 of the kunit tests, > and a new series to add a debugfs interface. > > Thanks for your reviews, We also have to think about how it's going to be shipped and used. If your debugfs integration has to be disabled everytime we're running kunit through uml, qemu, and in CI (because we can't retrieve the result), on a live system (because it would leak memory indefinitely), how is it useful? The diagnostic lines are part of the test result, are in the logs, and can be distributed. You're having all those problems solved already, without having any additional work to do. Maxime
On 03/09/2025 10:19, Maxime Ripard wrote: > On Wed, Sep 03, 2025 at 09:30:23AM +0200, Jocelyn Falempe wrote: >> On 02/09/2025 18:58, Maxime Ripard wrote: >>> On Mon, Sep 01, 2025 at 03:04:26PM +0200, Jocelyn Falempe wrote: >>>> On 27/08/2025 12:45, Thomas Zimmermann wrote: >>>>> Hi >>>>> >>>>> Am 21.08.25 um 11:49 schrieb Jocelyn Falempe: >>>>>> This is a bit hacky, but very handy if you want to customize the >>>>>> panic screen. >>>>>> It allows to dump the generated images to the logs, and then a python >>>>>> script can convert it to .png files. It makes it easy to check how >>>>>> the panic screen will look on different resolutions, without having >>>>>> to crash a VM. >>>>>> To not pollute the logs, it uses a monochrome framebuffer, compress >>>>>> it with zlib, and base64 encode it. >>>>> >>>>> May I suggest to export the raw image via debugfs? Debugfs can also >>>>> export additional information in additional files, such as width/height/ >>>>> stride/format. This could provide the real/last image on the fly, simply >>>>> by reading the files. No workarounds or encodings needed. >>>> >>>> I'm looking into that. The difficulty is to get the debugfs content outside >>>> of the test kernel. As I'm using a uml kernel for testing, I will need a >>>> special initrd, and a way to share files with the host. >>> >>> Yeah, I agree that it's not very practical. If only because the test >>> context doesn't stick around once it's been executed, so you would >>> effectively leak an arbritrarily long buffer with no hope of getting >>> back its memory. >> >> I've made a prototype with debugfs, a small ramdisk with busybox, and using >> hostfs to mount the host filesystem in the uml kernel, and it allows to dump >> the raw panic buffer easily. >> Even if it's a bit more complex to setup, I think this use case is not >> really a kunit test, so it's probably better that way. >> >> Let me a few days to clean that up, and I will send a v2 of the kunit tests, >> and a new series to add a debugfs interface. >> >> Thanks for your reviews, > > We also have to think about how it's going to be shipped and used. If > your debugfs integration has to be disabled everytime we're running > kunit through uml, qemu, and in CI (because we can't retrieve the > result), on a live system (because it would leak memory indefinitely), > how is it useful? There is already a kconfig for this: CONFIG_DRM_PANIC_DEBUG Also I have an implementation that doesn't leak memory. (memory is freed when the debugfs file is closed). It's also more flexible, as you can change the parameters, and test any color format, and check the binary result. I think the goal of this is not to test for regression, but to help building a new panic screen. > > The diagnostic lines are part of the test result, are in the logs, and > can be distributed. You're having all those problems solved already, > without having any additional work to do. I feel sending an image through log is not really efficient, and I don't want to pollute all the CI with that. I will send the v2 soon. Best regards, -- Jocelyn > > Maxime
On Mon, Sep 08, 2025 at 10:55:17AM +0200, Jocelyn Falempe wrote: > On 03/09/2025 10:19, Maxime Ripard wrote: > > On Wed, Sep 03, 2025 at 09:30:23AM +0200, Jocelyn Falempe wrote: > > > On 02/09/2025 18:58, Maxime Ripard wrote: > > > > On Mon, Sep 01, 2025 at 03:04:26PM +0200, Jocelyn Falempe wrote: > > > > > On 27/08/2025 12:45, Thomas Zimmermann wrote: > > > > > > Hi > > > > > > > > > > > > Am 21.08.25 um 11:49 schrieb Jocelyn Falempe: > > > > > > > This is a bit hacky, but very handy if you want to customize the > > > > > > > panic screen. > > > > > > > It allows to dump the generated images to the logs, and then a python > > > > > > > script can convert it to .png files. It makes it easy to check how > > > > > > > the panic screen will look on different resolutions, without having > > > > > > > to crash a VM. > > > > > > > To not pollute the logs, it uses a monochrome framebuffer, compress > > > > > > > it with zlib, and base64 encode it. > > > > > > > > > > > > May I suggest to export the raw image via debugfs? Debugfs can also > > > > > > export additional information in additional files, such as width/height/ > > > > > > stride/format. This could provide the real/last image on the fly, simply > > > > > > by reading the files. No workarounds or encodings needed. > > > > > > > > > > I'm looking into that. The difficulty is to get the debugfs content outside > > > > > of the test kernel. As I'm using a uml kernel for testing, I will need a > > > > > special initrd, and a way to share files with the host. > > > > > > > > Yeah, I agree that it's not very practical. If only because the test > > > > context doesn't stick around once it's been executed, so you would > > > > effectively leak an arbritrarily long buffer with no hope of getting > > > > back its memory. > > > > > > I've made a prototype with debugfs, a small ramdisk with busybox, and using > > > hostfs to mount the host filesystem in the uml kernel, and it allows to dump > > > the raw panic buffer easily. > > > Even if it's a bit more complex to setup, I think this use case is not > > > really a kunit test, so it's probably better that way. > > > > > > Let me a few days to clean that up, and I will send a v2 of the kunit tests, > > > and a new series to add a debugfs interface. > > > > > > Thanks for your reviews, > > > > We also have to think about how it's going to be shipped and used. If > > your debugfs integration has to be disabled everytime we're running > > kunit through uml, qemu, and in CI (because we can't retrieve the > > result), on a live system (because it would leak memory indefinitely), > > how is it useful? > > There is already a kconfig for this: > CONFIG_DRM_PANIC_DEBUG > > Also I have an implementation that doesn't leak memory. (memory is freed > when the debugfs file is closed). So, if userspace completely ignores it, you still leak it. > It's also more flexible, as you can change the parameters, and test any > color format, and check the binary result. > > I think the goal of this is not to test for regression, but to help building > a new panic screen. > > > > > The diagnostic lines are part of the test result, are in the logs, and > > can be distributed. You're having all those problems solved already, > > without having any additional work to do. > > I feel sending an image through log is not really efficient, and I don't > want to pollute all the CI with that. Then maybe we should just ignore that part of your series for now. But having a framebuffer lingering around in the system is a no-go for me. Maxime
On 09/09/2025 10:01, Maxime Ripard wrote: > On Mon, Sep 08, 2025 at 10:55:17AM +0200, Jocelyn Falempe wrote: >> On 03/09/2025 10:19, Maxime Ripard wrote: >>> On Wed, Sep 03, 2025 at 09:30:23AM +0200, Jocelyn Falempe wrote: >>>> On 02/09/2025 18:58, Maxime Ripard wrote: >>>>> On Mon, Sep 01, 2025 at 03:04:26PM +0200, Jocelyn Falempe wrote: >>>>>> On 27/08/2025 12:45, Thomas Zimmermann wrote: >>>>>>> Hi >>>>>>> >>>>>>> Am 21.08.25 um 11:49 schrieb Jocelyn Falempe: >>>>>>>> This is a bit hacky, but very handy if you want to customize the >>>>>>>> panic screen. >>>>>>>> It allows to dump the generated images to the logs, and then a python >>>>>>>> script can convert it to .png files. It makes it easy to check how >>>>>>>> the panic screen will look on different resolutions, without having >>>>>>>> to crash a VM. >>>>>>>> To not pollute the logs, it uses a monochrome framebuffer, compress >>>>>>>> it with zlib, and base64 encode it. >>>>>>> >>>>>>> May I suggest to export the raw image via debugfs? Debugfs can also >>>>>>> export additional information in additional files, such as width/height/ >>>>>>> stride/format. This could provide the real/last image on the fly, simply >>>>>>> by reading the files. No workarounds or encodings needed. >>>>>> >>>>>> I'm looking into that. The difficulty is to get the debugfs content outside >>>>>> of the test kernel. As I'm using a uml kernel for testing, I will need a >>>>>> special initrd, and a way to share files with the host. >>>>> >>>>> Yeah, I agree that it's not very practical. If only because the test >>>>> context doesn't stick around once it's been executed, so you would >>>>> effectively leak an arbritrarily long buffer with no hope of getting >>>>> back its memory. >>>> >>>> I've made a prototype with debugfs, a small ramdisk with busybox, and using >>>> hostfs to mount the host filesystem in the uml kernel, and it allows to dump >>>> the raw panic buffer easily. >>>> Even if it's a bit more complex to setup, I think this use case is not >>>> really a kunit test, so it's probably better that way. >>>> >>>> Let me a few days to clean that up, and I will send a v2 of the kunit tests, >>>> and a new series to add a debugfs interface. >>>> >>>> Thanks for your reviews, >>> >>> We also have to think about how it's going to be shipped and used. If >>> your debugfs integration has to be disabled everytime we're running >>> kunit through uml, qemu, and in CI (because we can't retrieve the >>> result), on a live system (because it would leak memory indefinitely), >>> how is it useful? >> >> There is already a kconfig for this: >> CONFIG_DRM_PANIC_DEBUG >> >> Also I have an implementation that doesn't leak memory. (memory is freed >> when the debugfs file is closed). > > So, if userspace completely ignores it, you still leak it. I think we should discuss that on the v2 I sent yesterday. But basically memory is allocated when the debugfs file is written, and freed when the file is closed. So if userspace ignores it, no memory is allocated, nothing happens. The drawback is you can't do: echo 1024x768:XR24 > /sys/kernel/debug/drm_panic/draw_test cat /sys/kernel/debug/drm_panic/draw_test > panic_screen.raw You need to keep the file opened in bash between write and read: cd /sys/kernel/debug/drm_panic/ exec 3<> draw_test echo 1024x768:XR24 >&3 cat <&3 > ~/panic_screen.raw exec 3<&- I hope that clarify things. -- Jocelyn > >> It's also more flexible, as you can change the parameters, and test any >> color format, and check the binary result. >> >> I think the goal of this is not to test for regression, but to help building >> a new panic screen. >> >>> >>> The diagnostic lines are part of the test result, are in the logs, and >>> can be distributed. You're having all those problems solved already, >>> without having any additional work to do. >> >> I feel sending an image through log is not really efficient, and I don't >> want to pollute all the CI with that. > > Then maybe we should just ignore that part of your series for now. But > having a framebuffer lingering around in the system is a no-go for me. > > Maxime
Hi, On Thu, Aug 21, 2025 at 11:49:07AM +0200, Jocelyn Falempe wrote: > This is a bit hacky, but very handy if you want to customize the > panic screen. > It allows to dump the generated images to the logs, and then a python > script can convert it to .png files. It makes it easy to check how > the panic screen will look on different resolutions, without having > to crash a VM. > To not pollute the logs, it uses a monochrome framebuffer, compress > it with zlib, and base64 encode it. > > Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com> > --- > drivers/gpu/drm/Kconfig.debug | 14 ++++ > drivers/gpu/drm/tests/drm_panic_test.c | 111 +++++++++++++++++++++++++ > scripts/kunitpanic2png.py | 53 ++++++++++++ > 3 files changed, 178 insertions(+) > create mode 100755 scripts/kunitpanic2png.py > > diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug > index 05dc43c0b8c5..d8ae85132d32 100644 > --- a/drivers/gpu/drm/Kconfig.debug > +++ b/drivers/gpu/drm/Kconfig.debug > @@ -84,6 +84,20 @@ config DRM_KUNIT_TEST > > If in doubt, say "N". > > +config DRM_PANIC_KUNIT_TEST_DUMP > + bool "Enable screen dump to logs in KUnit tests for drm_panic" > + default n > + depends on DRM && DRM_PANIC && DRM_KUNIT_TEST > + select ZLIB_DEFLATE > + help > + This allows to dump the panic screen to the KUnit tests logs. > + It's possible with a small python script to write pngs from the logs. > + > + This is only to help developers customizing the drm_panic screen, > + checking the result for different resolutions. > + > + If in doubt, say "N" > + > config DRM_TTM_KUNIT_TEST > tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS > default n > diff --git a/drivers/gpu/drm/tests/drm_panic_test.c b/drivers/gpu/drm/tests/drm_panic_test.c > index 46ff3e5e0e5d..8cddb845aea9 100644 > --- a/drivers/gpu/drm/tests/drm_panic_test.c > +++ b/drivers/gpu/drm/tests/drm_panic_test.c > @@ -115,24 +115,135 @@ static void drm_test_panic_screen_user_page(struct kunit *test) > kfree(pages); > } > > +#ifdef CONFIG_DRM_PANIC_KUNIT_TEST_DUMP > +#include <linux/base64.h> > +#include <linux/delay.h> > +#include <linux/zlib.h> > + > +#define LINE_LEN 128 > + > +#define COMPR_LEVEL 6 > +#define WINDOW_BITS 12 > +#define MEM_LEVEL 4 > + > +static int compress_image(u8 *src, int size, u8 *dst) > +{ > + struct z_stream_s stream; > + > + stream.workspace = kmalloc(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), > + GFP_KERNEL); > + > + if (zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, > + MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) > + return -EINVAL; > + > + stream.next_in = src; > + stream.avail_in = size; > + stream.total_in = 0; > + stream.next_out = dst; > + stream.avail_out = size; > + stream.total_out = 0; > + > + if (zlib_deflate(&stream, Z_FINISH) != Z_STREAM_END) > + return -EINVAL; > + > + if (zlib_deflateEnd(&stream) != Z_OK) > + return -EINVAL; > + > + kfree(stream.workspace); > + > + return stream.total_out; > +} > + > +static void dump_image(u8 *fb, unsigned int width, unsigned int height) > +{ > + int len = 0; > + char *dst; > + char *compressed; > + int sent = 0; > + int stride = DIV_ROUND_UP(width, 8); > + int size = stride * height; > + > + compressed = vzalloc(size); > + if (!compressed) > + return; > + len = compress_image(fb, size, compressed); > + if (len < 0) { > + pr_err("Compression failed %d", len); > + return; > + } > + > + dst = vzalloc(4 * DIV_ROUND_UP(len, 3) + 1); > + if (!dst) > + return; > + > + len = base64_encode(compressed, len, dst); > + > + pr_info("KUNIT PANIC IMAGE DUMP START %dx%d", width, height); > + while (len > 0) { > + char save = dst[sent + LINE_LEN]; > + > + dst[sent + LINE_LEN] = 0; > + pr_info("%s", dst + sent); > + dst[sent + LINE_LEN] = save; > + sent += LINE_LEN; > + len -= LINE_LEN; > + } > + pr_info("KUNIT PANIC IMAGE DUMP END"); The kunit test output format is defined, and we should probably use a diagnostic line for this: https://docs.kernel.org/dev-tools/ktap.html#diagnostic-lines We should probably cc the kunit maintainers about this too. Maxime
On 27/08/2025 11:52, Maxime Ripard wrote: > Hi, > > On Thu, Aug 21, 2025 at 11:49:07AM +0200, Jocelyn Falempe wrote: >> This is a bit hacky, but very handy if you want to customize the >> panic screen. >> It allows to dump the generated images to the logs, and then a python >> script can convert it to .png files. It makes it easy to check how >> the panic screen will look on different resolutions, without having >> to crash a VM. >> To not pollute the logs, it uses a monochrome framebuffer, compress >> it with zlib, and base64 encode it. >> >> Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com> >> --- >> drivers/gpu/drm/Kconfig.debug | 14 ++++ >> drivers/gpu/drm/tests/drm_panic_test.c | 111 +++++++++++++++++++++++++ >> scripts/kunitpanic2png.py | 53 ++++++++++++ >> 3 files changed, 178 insertions(+) >> create mode 100755 scripts/kunitpanic2png.py >> >> diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug >> index 05dc43c0b8c5..d8ae85132d32 100644 >> --- a/drivers/gpu/drm/Kconfig.debug >> +++ b/drivers/gpu/drm/Kconfig.debug >> @@ -84,6 +84,20 @@ config DRM_KUNIT_TEST >> >> If in doubt, say "N". >> >> +config DRM_PANIC_KUNIT_TEST_DUMP >> + bool "Enable screen dump to logs in KUnit tests for drm_panic" >> + default n >> + depends on DRM && DRM_PANIC && DRM_KUNIT_TEST >> + select ZLIB_DEFLATE >> + help >> + This allows to dump the panic screen to the KUnit tests logs. >> + It's possible with a small python script to write pngs from the logs. >> + >> + This is only to help developers customizing the drm_panic screen, >> + checking the result for different resolutions. >> + >> + If in doubt, say "N" >> + >> config DRM_TTM_KUNIT_TEST >> tristate "KUnit tests for TTM" if !KUNIT_ALL_TESTS >> default n >> diff --git a/drivers/gpu/drm/tests/drm_panic_test.c b/drivers/gpu/drm/tests/drm_panic_test.c >> index 46ff3e5e0e5d..8cddb845aea9 100644 >> --- a/drivers/gpu/drm/tests/drm_panic_test.c >> +++ b/drivers/gpu/drm/tests/drm_panic_test.c >> @@ -115,24 +115,135 @@ static void drm_test_panic_screen_user_page(struct kunit *test) >> kfree(pages); >> } >> >> +#ifdef CONFIG_DRM_PANIC_KUNIT_TEST_DUMP >> +#include <linux/base64.h> >> +#include <linux/delay.h> >> +#include <linux/zlib.h> >> + >> +#define LINE_LEN 128 >> + >> +#define COMPR_LEVEL 6 >> +#define WINDOW_BITS 12 >> +#define MEM_LEVEL 4 >> + >> +static int compress_image(u8 *src, int size, u8 *dst) >> +{ >> + struct z_stream_s stream; >> + >> + stream.workspace = kmalloc(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), >> + GFP_KERNEL); >> + >> + if (zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, >> + MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) >> + return -EINVAL; >> + >> + stream.next_in = src; >> + stream.avail_in = size; >> + stream.total_in = 0; >> + stream.next_out = dst; >> + stream.avail_out = size; >> + stream.total_out = 0; >> + >> + if (zlib_deflate(&stream, Z_FINISH) != Z_STREAM_END) >> + return -EINVAL; >> + >> + if (zlib_deflateEnd(&stream) != Z_OK) >> + return -EINVAL; >> + >> + kfree(stream.workspace); >> + >> + return stream.total_out; >> +} >> + >> +static void dump_image(u8 *fb, unsigned int width, unsigned int height) >> +{ >> + int len = 0; >> + char *dst; >> + char *compressed; >> + int sent = 0; >> + int stride = DIV_ROUND_UP(width, 8); >> + int size = stride * height; >> + >> + compressed = vzalloc(size); >> + if (!compressed) >> + return; >> + len = compress_image(fb, size, compressed); >> + if (len < 0) { >> + pr_err("Compression failed %d", len); >> + return; >> + } >> + >> + dst = vzalloc(4 * DIV_ROUND_UP(len, 3) + 1); >> + if (!dst) >> + return; >> + >> + len = base64_encode(compressed, len, dst); >> + >> + pr_info("KUNIT PANIC IMAGE DUMP START %dx%d", width, height); >> + while (len > 0) { >> + char save = dst[sent + LINE_LEN]; >> + >> + dst[sent + LINE_LEN] = 0; >> + pr_info("%s", dst + sent); >> + dst[sent + LINE_LEN] = save; >> + sent += LINE_LEN; >> + len -= LINE_LEN; >> + } >> + pr_info("KUNIT PANIC IMAGE DUMP END"); > > The kunit test output format is defined, and we should probably use a > diagnostic line for this: > https://docs.kernel.org/dev-tools/ktap.html#diagnostic-lines > > We should probably cc the kunit maintainers about this too. Thanks for the pointer, I will also experiment with debugfs, as suggested by Thomas. Best regards, -- Jocelyn > > Maxime
© 2016 - 2025 Red Hat, Inc.