[PATCH] x86: mmap kernel for direct kernel boot

Gerd Hoffmann posted 1 patch 2 days, 14 hours ago
hw/i386/x86-common.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
[PATCH] x86: mmap kernel for direct kernel boot
Posted by Gerd Hoffmann 2 days, 14 hours ago
Reduce memory footprint by mapping the kernel into memory instead of
reading into allocated memory in the common case (no -dtb $file on the
qemu command line).

Cc: John Snow <jsnow@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/i386/x86-common.c | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
index fa18bf1aeceb..25e141aa8537 100644
--- a/hw/i386/x86-common.c
+++ b/hw/i386/x86-common.c
@@ -911,16 +911,31 @@ void x86_load_linux(X86MachineState *x86ms,
     }
 
     setup  = g_malloc(setup_size);
-    kernel = g_malloc(kernel_size);
     fseek(f, 0, SEEK_SET);
     if (fread(setup, 1, setup_size, f) != setup_size) {
         fprintf(stderr, "fread() failed\n");
         exit(1);
     }
-    fseek(f, 0, SEEK_SET);
-    if (fread(kernel, 1, kernel_size, f) != kernel_size) {
-        fprintf(stderr, "fread() failed\n");
-        exit(1);
+    if (dtb_filename) {
+        /* read kernel into allocated memory, so we can realloc for the dtb */
+        kernel = g_malloc(kernel_size);
+        fseek(f, 0, SEEK_SET);
+        if (fread(kernel, 1, kernel_size, f) != kernel_size) {
+            fprintf(stderr, "fread() failed\n");
+            exit(1);
+        }
+    } else {
+        /* mmap kernel */
+        GMappedFile *mapped_file;
+        GError *gerr = NULL;
+
+        mapped_file = g_mapped_file_new(kernel_filename, false, &gerr);
+        if (!mapped_file) {
+            fprintf(stderr, "qemu: error reading kernel %s: %s\n",
+                    kernel_filename, gerr->message);
+            exit(1);
+        }
+        kernel = (uint8_t *)g_mapped_file_get_contents(mapped_file);
     }
     fclose(f);
 
-- 
2.56.0
Re: [PATCH] x86: mmap kernel for direct kernel boot
Posted by John Snow 2 days, 4 hours ago
On Wed, Oct 21, 2026 at 2:31 AM Gerd Hoffmann <kraxel@redhat.com> wrote:
>
> Reduce memory footprint by mapping the kernel into memory instead of
> reading into allocated memory in the common case (no -dtb $file on the
> qemu command line).
>
> Cc: John Snow <jsnow@redhat.com>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

Tested-by: John Snow <jsnow@redhat.com>

Using this patch, I shifted about 19MiB of resources from RssAnon to
RssFile. This theoretically allows sharing resources between multiple
QEMU instances in the trivial case using -kernel and -initrd. This
matches how we already load initrd.

--js

> ---
>  hw/i386/x86-common.c | 25 ++++++++++++++++++++-----
>  1 file changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
> index fa18bf1aeceb..25e141aa8537 100644
> --- a/hw/i386/x86-common.c
> +++ b/hw/i386/x86-common.c
> @@ -911,16 +911,31 @@ void x86_load_linux(X86MachineState *x86ms,
>      }
>
>      setup  = g_malloc(setup_size);
> -    kernel = g_malloc(kernel_size);
>      fseek(f, 0, SEEK_SET);
>      if (fread(setup, 1, setup_size, f) != setup_size) {
>          fprintf(stderr, "fread() failed\n");
>          exit(1);
>      }
> -    fseek(f, 0, SEEK_SET);
> -    if (fread(kernel, 1, kernel_size, f) != kernel_size) {
> -        fprintf(stderr, "fread() failed\n");
> -        exit(1);
> +    if (dtb_filename) {
> +        /* read kernel into allocated memory, so we can realloc for the dtb */
> +        kernel = g_malloc(kernel_size);
> +        fseek(f, 0, SEEK_SET);
> +        if (fread(kernel, 1, kernel_size, f) != kernel_size) {
> +            fprintf(stderr, "fread() failed\n");
> +            exit(1);
> +        }
> +    } else {
> +        /* mmap kernel */
> +        GMappedFile *mapped_file;
> +        GError *gerr = NULL;
> +
> +        mapped_file = g_mapped_file_new(kernel_filename, false, &gerr);
> +        if (!mapped_file) {
> +            fprintf(stderr, "qemu: error reading kernel %s: %s\n",
> +                    kernel_filename, gerr->message);
> +            exit(1);
> +        }
> +        kernel = (uint8_t *)g_mapped_file_get_contents(mapped_file);
>      }
>      fclose(f);
>
> --
> 2.56.0
>