All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: qemu-devel@nongnu.org
Cc: julien@xen.org, masami.hiramatsu@linaro.org,
	andre.przywara@arm.com, stefano.stabellini@linaro.org,
	takahiro.akashi@linaro.org, stefano.stabellini@xilinx.com,
	"Alex Bennée" <alex.bennee@linaro.org>,
	stratos-dev@op-lists.linaro.org
Subject: [RFC PATCH 04/15] hw/core: implement a guest-loader to support static hypervisor guests
Date: Thu,  5 Nov 2020 17:51:42 +0000	[thread overview]
Message-ID: <20201105175153.30489-5-alex.bennee@linaro.org> (raw)
In-Reply-To: <20201105175153.30489-1-alex.bennee@linaro.org>

Hypervisors, especially type-1 ones, need the firmware/bootcode to put
their initial guest somewhere in memory and pass the information to it
via platform data. The guest-loader is modelled after the generic
loader for exactly this sort of purpose:

  $QEMU $ARGS  -kernel ~/xen.git/xen/xen \
    -append "dom0_mem=1G,max:1G loglvl=all guest_loglvl=all" \
    -device guest-loader,addr=0x42000000,kernel=Image,bootargs="root=/dev/sda2 ro console=hvc0 earlyprintk=xen" \
    -device guest-loader,addr=0x47000000,initrd=rootfs.cpio

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20201021170842.25762-5-alex.bennee@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/core/guest-loader.h |  34 ++++++++++
 hw/core/guest-loader.c | 140 +++++++++++++++++++++++++++++++++++++++++
 hw/core/meson.build    |   2 +
 3 files changed, 176 insertions(+)
 create mode 100644 hw/core/guest-loader.h
 create mode 100644 hw/core/guest-loader.c

diff --git a/hw/core/guest-loader.h b/hw/core/guest-loader.h
new file mode 100644
index 0000000000..07f4b4884b
--- /dev/null
+++ b/hw/core/guest-loader.h
@@ -0,0 +1,34 @@
+/*
+ * Guest Loader
+ *
+ * Copyright (C) 2020 Linaro
+ * Written by Alex Bennée <alex.bennee@linaro.org>
+ * (based on the generic-loader by Li Guang <lig.fnst@cn.fujitsu.com>)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef GUEST_LOADER_H
+#define GUEST_LOADER_H
+
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+struct GuestLoaderState {
+    /* <private> */
+    DeviceState parent_obj;
+
+    /* <public> */
+    uint64_t addr;
+    char *kernel;
+    char *args;
+    char *initrd;
+};
+
+#define TYPE_GUEST_LOADER "guest-loader"
+OBJECT_DECLARE_SIMPLE_TYPE(GuestLoaderState, GUEST_LOADER)
+
+#endif
diff --git a/hw/core/guest-loader.c b/hw/core/guest-loader.c
new file mode 100644
index 0000000000..1ce39842be
--- /dev/null
+++ b/hw/core/guest-loader.c
@@ -0,0 +1,140 @@
+/*
+ * Guest Loader
+ *
+ * Copyright (C) 2020 Linaro
+ * Written by Alex Bennée <alex.bennee@linaro.org>
+ * (based on the generic-loader by Li Guang <lig.fnst@cn.fujitsu.com>)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * Much like the generic-loader this is treated as a special device
+ * inside QEMU. However unlike the generic-loader this device is used
+ * to load guest images for hypervisors. As part of that process the
+ * hypervisor needs to have platform information passed to it by the
+ * lower levels of the stack (e.g. firmware/bootloader). If you boot
+ * the hypervisor directly you use the guest-loader to load the Dom0
+ * or equivalent guest images in the right place in the same way a
+ * boot loader would.
+ *
+ * This is only relevant for full system emulation.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/core/cpu.h"
+#include "hw/sysbus.h"
+#include "sysemu/dma.h"
+#include "hw/loader.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "guest-loader.h"
+#include "sysemu/device_tree.h"
+#include "hw/boards.h"
+
+/*
+ * Insert some FDT nodes for the loaded blob.
+ */
+static void loader_insert_platform_data(GuestLoaderState *s, int size, Error **errp)
+{
+    MachineState *machine = MACHINE(qdev_get_machine());
+    void *fdt = machine->fdt;
+    g_autofree char *node = g_strdup_printf("/chosen/module@%#08lx", s->addr);
+    uint64_t reg_attr[2] = {cpu_to_be64(s->addr), cpu_to_be64(size)};
+
+    if (!fdt) {
+        error_setg(errp, "Cannot modify FDT fields if the machine has none");
+        return;
+    }
+
+    qemu_fdt_add_subnode(fdt, node);
+    qemu_fdt_setprop(fdt, node, "reg", &reg_attr, sizeof(reg_attr));
+
+    if (s->kernel) {
+        const char *compat[2] = { "multiboot,module", "multiboot,kernel" };
+        if (qemu_fdt_setprop_string_array
+            (fdt, node, "compatible", (char **) &compat, ARRAY_SIZE(compat)) < 0) {
+            error_setg(errp, "couldn't set %s/compatible", node);
+            return;
+        }
+        if (s->args) {
+            if (qemu_fdt_setprop_string(fdt, node, "bootargs", s->args) < 0) {
+                error_setg(errp, "couldn't set %s/bootargs", node);
+            }
+        }
+    } else if (s->initrd) {
+        const char * compat[2] = { "multiboot,module", "multiboot,ramdisk" };
+        if (qemu_fdt_setprop_string_array
+            (fdt, node, "compatible", (char **) &compat, ARRAY_SIZE(compat)) < 0) {
+            error_setg(errp, "couldn't set %s/compatible", node);
+            return;
+        }
+    }
+}
+
+static void guest_loader_realize(DeviceState *dev, Error **errp)
+{
+    GuestLoaderState *s = GUEST_LOADER(dev);
+    char *file = s->kernel ? s->kernel : s->initrd;
+    int size = 0;
+
+    /* Perform some error checking on the user's options */
+    if (s->kernel && s->initrd) {
+        error_setg(errp, "Cannot specify a kernel and initrd in the same stanza");
+        return;
+    } else if (!s->kernel && !s->initrd)  {
+        error_setg(errp, "Need to specify a kernel or initrd image");
+        return;
+    } else if (!s->addr) {
+        error_setg(errp, "Need to specify the address of guest blob");
+        return;
+    } else if (s->args && !s->kernel) {
+        error_setg(errp, "Boot args only relevant to kernel blobs");
+    }
+
+    /* Default to the maximum size being the machine's ram size */
+    size = load_image_targphys_as(file, s->addr, ram_size, NULL);
+    if (size < 0) {
+        error_setg(errp, "Cannot load specified image %s", file);
+        return;
+    }
+
+    /* Now the image is loaded we need to update the platform data */
+    loader_insert_platform_data(s, size, errp);
+}
+
+static Property guest_loader_props[] = {
+    DEFINE_PROP_UINT64("addr", GuestLoaderState, addr, 0),
+    DEFINE_PROP_STRING("kernel", GuestLoaderState, kernel),
+    DEFINE_PROP_STRING("bootargs", GuestLoaderState, args),
+    DEFINE_PROP_STRING("initrd", GuestLoaderState, initrd),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void guest_loader_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = guest_loader_realize;
+    device_class_set_props(dc, guest_loader_props);
+    dc->desc = "Guest Loader";
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static TypeInfo guest_loader_info = {
+    .name = TYPE_GUEST_LOADER,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(GuestLoaderState),
+    .class_init = guest_loader_class_init,
+};
+
+static void guest_loader_register_type(void)
+{
+    type_register_static(&guest_loader_info);
+}
+
+type_init(guest_loader_register_type)
diff --git a/hw/core/meson.build b/hw/core/meson.build
index 4a744f3b5e..27a69fc578 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -37,6 +37,8 @@ softmmu_ss.add(files(
   'clock-vmstate.c',
 ))
 
+softmmu_ss.add(when: 'CONFIG_TCG', if_true: files('guest-loader.c'))
+
 specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files(
   'machine-qmp-cmds.c',
   'numa.c',
-- 
2.20.1



  parent reply	other threads:[~2020-11-05 18:00 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-05 17:51 [RFC PATCH 00/15] Xen guest-loader and arm64 build fixes/enhancements Alex Bennée
2020-11-05 17:51 ` [RFC PATCH 01/15] hw/board: promote fdt from ARM VirtMachineState to MachineState Alex Bennée
2020-11-05 19:27   ` Philippe Mathieu-Daudé
2020-11-05 20:37     ` Alex Bennée
2020-11-05 17:51 ` [RFC PATCH 02/15] hw/riscv: migrate fdt field to generic MachineState Alex Bennée
2020-11-05 17:51   ` Alex Bennée
2020-11-05 19:24   ` Philippe Mathieu-Daudé
2020-11-06  3:15   ` Bin Meng
2020-11-06  3:15     ` Bin Meng
2020-11-06 10:21     ` Alex Bennée
2020-11-06 10:21       ` Alex Bennée
2020-11-06 11:32       ` Bin Meng
2020-11-06 11:32         ` Bin Meng
2020-11-05 17:51 ` [RFC PATCH 03/15] device_tree: add qemu_fdt_setprop_string_array helper Alex Bennée
2020-11-05 17:51 ` Alex Bennée [this message]
2020-11-05 17:51 ` [RFC PATCH 05/15] docs: move generic-loader documentation into the main manual Alex Bennée
2020-11-05 17:51 ` [RFC PATCH 06/15] docs: add some documentation for the guest-loader Alex Bennée
2020-11-19 20:06   ` Alistair Francis
2020-11-19 20:58     ` Peter Maydell
2020-11-05 17:51 ` [RFC PATCH 07/15] accel/meson: you only need accelerator stubs for softmmu builds Alex Bennée
2020-11-05 18:18   ` Philippe Mathieu-Daudé
2020-11-05 17:51 ` [RFC PATCH 08/15] meson.build: fix building of Xen support for aarch64 Alex Bennée
2020-11-05 18:20   ` Philippe Mathieu-Daudé
2020-11-05 17:51 ` [RFC PATCH 09/15] meson.build: introduce CONFIG_XEN_HVM flag Alex Bennée
2020-11-05 18:21   ` Philippe Mathieu-Daudé
2020-11-05 18:47   ` Philippe Mathieu-Daudé
2020-11-05 17:51 ` [RFC PATCH 10/15] meson.build: clean-up summary reporting of XEN and it's features Alex Bennée
2020-11-05 19:11   ` Philippe Mathieu-Daudé
2020-11-05 17:51 ` [RFC PATCH 11/15] include/hw/xen.h: drop superfluous struct Alex Bennée
2020-11-05 17:51   ` Alex Bennée
2020-11-05 19:15   ` Philippe Mathieu-Daudé
2020-11-05 17:51 ` [RFC PATCH 12/15] stubs/xen-hw-stub: drop xenstore_store_pv_console_info stub Alex Bennée
2020-11-05 17:51   ` Alex Bennée
2020-11-05 19:20   ` Philippe Mathieu-Daudé
2020-11-05 19:20     ` Philippe Mathieu-Daudé
2020-11-06 10:27     ` Alex Bennée
2020-11-06 10:27       ` Alex Bennée
2020-11-05 17:51 ` [RFC PATCH 13/15] accel/stubs: drop unused cpu.h include Alex Bennée
2020-11-05 19:20   ` Philippe Mathieu-Daudé
2020-11-05 17:51 ` [RFC PATCH 14/15] xen: only build HVM support under CONFIG_XEN_HVM Alex Bennée
2020-11-05 17:51   ` Alex Bennée
2020-11-05 17:51 ` [RFC PATCH 15/15] meson.build: build a Xen aware qemu-aarch64-system Alex Bennée
2020-11-05 18:15 ` [RFC PATCH 00/15] Xen guest-loader and arm64 build fixes/enhancements no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201105175153.30489-5-alex.bennee@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=andre.przywara@arm.com \
    --cc=julien@xen.org \
    --cc=masami.hiramatsu@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefano.stabellini@linaro.org \
    --cc=stefano.stabellini@xilinx.com \
    --cc=stratos-dev@op-lists.linaro.org \
    --cc=takahiro.akashi@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.