hw/i386/x86-common.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
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
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
>
© 2016 - 2026 Red Hat, Inc.