All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Laurent Vivier <lvivier@redhat.com>,
	Peter Maydell <peter.maydell@linaro.org>,
	Thomas Huth <thuth@redhat.com>,
	Eduardo Habkost <ehabkost@redhat.com>,
	Sergio Lopez <slp@redhat.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	Shannon Zhao <shannon.zhaosl@gmail.com>,
	qemu-arm@nongnu.org, Gerd Hoffmann <kraxel@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Igor Mammedov <imammedo@redhat.com>,
	Richard Henderson <rth@twiddle.net>
Subject: [PATCH v4 08/21] microvm/acpi: add minimal acpi support
Date: Thu,  2 Jul 2020 22:48:46 +0200	[thread overview]
Message-ID: <20200702204859.9876-9-kraxel@redhat.com> (raw)
In-Reply-To: <20200702204859.9876-1-kraxel@redhat.com>

$subject says all.  Can be controlled using -M microvm,acpi=on/off.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/i386/acpi-microvm.h    |   8 ++
 include/hw/i386/microvm.h |   9 ++
 hw/i386/acpi-microvm.c    | 181 ++++++++++++++++++++++++++++++++++++++
 hw/i386/microvm.c         |  40 +++++++++
 hw/i386/Kconfig           |   1 +
 hw/i386/Makefile.objs     |   1 +
 6 files changed, 240 insertions(+)
 create mode 100644 hw/i386/acpi-microvm.h
 create mode 100644 hw/i386/acpi-microvm.c

diff --git a/hw/i386/acpi-microvm.h b/hw/i386/acpi-microvm.h
new file mode 100644
index 000000000000..dfe853690e15
--- /dev/null
+++ b/hw/i386/acpi-microvm.h
@@ -0,0 +1,8 @@
+#ifndef HW_I386_ACPI_MICROVM_H
+#define HW_I386_ACPI_MICROVM_H
+
+#include "hw/i386/microvm.h"
+
+void acpi_setup_microvm(MicrovmMachineState *mms);
+
+#endif
diff --git a/include/hw/i386/microvm.h b/include/hw/i386/microvm.h
index 03e735723726..b6e0d4395af7 100644
--- a/include/hw/i386/microvm.h
+++ b/include/hw/i386/microvm.h
@@ -24,12 +24,18 @@
 
 #include "hw/boards.h"
 #include "hw/i386/x86.h"
+#include "hw/acpi/acpi_dev_interface.h"
 
 /* Platform virtio definitions */
 #define VIRTIO_MMIO_BASE      0xfeb00000
 #define VIRTIO_NUM_TRANSPORTS 8
 #define VIRTIO_CMDLINE_MAXLEN 64
 
+#define GED_MMIO_BASE         0xfea00000
+#define GED_MMIO_BASE_MEMHP   (GED_MMIO_BASE + 0x100)
+#define GED_MMIO_BASE_REGS    (GED_MMIO_BASE + 0x200)
+#define GED_MMIO_IRQ          9
+
 /* Machine type options */
 #define MICROVM_MACHINE_PIT                 "pit"
 #define MICROVM_MACHINE_PIC                 "pic"
@@ -58,6 +64,9 @@ typedef struct {
     /* Machine state */
     uint32_t virtio_irq_base;
     bool kernel_cmdline_fixed;
+    Notifier machine_done;
+    Notifier powerdown_req;
+    AcpiDeviceIf *acpi_dev;
 } MicrovmMachineState;
 
 #define TYPE_MICROVM_MACHINE   MACHINE_TYPE_NAME("microvm")
diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
new file mode 100644
index 000000000000..7cd830e628af
--- /dev/null
+++ b/hw/i386/acpi-microvm.c
@@ -0,0 +1,181 @@
+/* Support for generating ACPI tables and passing them to Guests
+ *
+ * Copyright (C) 2008-2010  Kevin O'Connor <kevin@koconnor.net>
+ * Copyright (C) 2006 Fabrice Bellard
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+
+#include "exec/memory.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/bios-linker-loader.h"
+#include "hw/acpi/generic_event_device.h"
+#include "hw/acpi/utils.h"
+#include "hw/boards.h"
+#include "hw/i386/fw_cfg.h"
+#include "hw/i386/microvm.h"
+
+#include "acpi-common.h"
+#include "acpi-microvm.h"
+
+static void
+build_dsdt_microvm(GArray *table_data, BIOSLinker *linker,
+                   MicrovmMachineState *mms)
+{
+    X86MachineState *x86ms = X86_MACHINE(mms);
+    Aml *dsdt, *sb_scope, *scope, *pkg;
+    bool ambiguous;
+    Object *isabus;
+
+    isabus = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous);
+    assert(isabus);
+    assert(!ambiguous);
+
+    dsdt = init_aml_allocator();
+
+    /* Reserve space for header */
+    acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
+
+    sb_scope = aml_scope("_SB");
+    fw_cfg_add_acpi_dsdt(sb_scope, x86ms->fw_cfg);
+    isa_build_aml(ISA_BUS(isabus), sb_scope);
+    build_ged_aml(sb_scope, GED_DEVICE, HOTPLUG_HANDLER(mms->acpi_dev),
+                  GED_MMIO_IRQ, AML_SYSTEM_MEMORY, GED_MMIO_BASE);
+    acpi_dsdt_add_power_button(sb_scope);
+    aml_append(dsdt, sb_scope);
+
+    scope = aml_scope("\\");
+    pkg = aml_package(4);
+    aml_append(pkg, aml_int(5)); /* SLEEP_CONTROL_REG.SLP_TYP */
+    aml_append(pkg, aml_int(0)); /* ignored */
+    aml_append(pkg, aml_int(0)); /* reserved */
+    aml_append(pkg, aml_int(0)); /* reserved */
+    aml_append(scope, aml_name_decl("_S5", pkg));
+    aml_append(dsdt, scope);
+
+    /* copy AML table into ACPI tables blob and patch header there */
+    g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
+    build_header(linker, table_data,
+        (void *)(table_data->data + table_data->len - dsdt->buf->len),
+        "DSDT", dsdt->buf->len, 5, NULL, NULL);
+    free_aml_allocator();
+}
+
+static void acpi_build_microvm(AcpiBuildTables *tables,
+                               MicrovmMachineState *mms)
+{
+    MachineState *machine = MACHINE(mms);
+    GArray *table_offsets;
+    GArray *tables_blob = tables->table_data;
+    unsigned dsdt, xsdt;
+    AcpiFadtData pmfadt = {
+        .rev = 5,
+        .minor_ver = 1,
+        .flags = ((1 << ACPI_FADT_F_HW_REDUCED_ACPI) |
+                  (1 << ACPI_FADT_F_RESET_REG_SUP)),
+        .sleep_ctl = {
+            .space_id = AML_AS_SYSTEM_MEMORY,
+            .bit_width = 8,
+            .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_SLEEP_CTL,
+        },
+        .sleep_sts = {
+            .space_id = AML_AS_SYSTEM_MEMORY,
+            .bit_width = 8,
+            .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_SLEEP_STS,
+        },
+        .reset_reg = {
+            .space_id = AML_AS_SYSTEM_MEMORY,
+            .bit_width = 8,
+            .address = GED_MMIO_BASE_REGS + ACPI_GED_REG_RESET,
+        },
+        .reset_val = ACPI_GED_RESET_VALUE,
+    };
+
+    table_offsets = g_array_new(false, true /* clear */,
+                                        sizeof(uint32_t));
+    bios_linker_loader_alloc(tables->linker,
+                             ACPI_BUILD_TABLE_FILE, tables_blob,
+                             64 /* Ensure FACS is aligned */,
+                             false /* high memory */);
+
+    dsdt = tables_blob->len;
+    build_dsdt_microvm(tables_blob, tables->linker, mms);
+
+    pmfadt.dsdt_tbl_offset = &dsdt;
+    pmfadt.xdsdt_tbl_offset = &dsdt;
+    acpi_add_table(table_offsets, tables_blob);
+    build_fadt(tables_blob, tables->linker, &pmfadt, NULL, NULL);
+
+    acpi_add_table(table_offsets, tables_blob);
+    acpi_build_madt(tables_blob, tables->linker, X86_MACHINE(machine),
+                    mms->acpi_dev, false);
+
+    xsdt = tables_blob->len;
+    build_xsdt(tables_blob, tables->linker, table_offsets, NULL, NULL);
+
+    /* RSDP is in FSEG memory, so allocate it separately */
+    {
+        AcpiRsdpData rsdp_data = {
+            .revision = 2,
+            .oem_id = ACPI_BUILD_APPNAME6,
+            .xsdt_tbl_offset = &xsdt,
+            .rsdt_tbl_offset = NULL,
+        };
+        build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
+    }
+
+    /* Cleanup memory that's no longer used. */
+    g_array_free(table_offsets, true);
+}
+
+static void acpi_build_no_update(void *build_opaque)
+{
+    /* nothing, microvm tables don't change at runtime */
+}
+
+void acpi_setup_microvm(MicrovmMachineState *mms)
+{
+    X86MachineState *x86ms = X86_MACHINE(mms);
+    AcpiBuildTables tables;
+
+    assert(x86ms->fw_cfg);
+
+    if (!x86_machine_is_acpi_enabled(x86ms)) {
+        return;
+    }
+
+    acpi_build_tables_init(&tables);
+    acpi_build_microvm(&tables, mms);
+
+    /* Now expose it all to Guest */
+    acpi_add_rom_blob(acpi_build_no_update, NULL,
+                      tables.table_data,
+                      ACPI_BUILD_TABLE_FILE,
+                      ACPI_BUILD_TABLE_MAX_SIZE);
+    acpi_add_rom_blob(acpi_build_no_update, NULL,
+                      tables.linker->cmd_blob,
+                      "etc/table-loader", 0);
+    acpi_add_rom_blob(acpi_build_no_update, NULL,
+                      tables.rsdp,
+                      ACPI_BUILD_RSDP_FILE, 0);
+
+    acpi_build_tables_cleanup(&tables, false);
+}
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index ab6ee6c67b1a..75eca7306b11 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -26,6 +26,8 @@
 #include "sysemu/cpus.h"
 #include "sysemu/numa.h"
 #include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "acpi-microvm.h"
 
 #include "hw/loader.h"
 #include "hw/irq.h"
@@ -41,6 +43,8 @@
 #include "hw/i386/e820_memory_layout.h"
 #include "hw/i386/fw_cfg.h"
 #include "hw/virtio/virtio-mmio.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/generic_event_device.h"
 
 #include "cpu.h"
 #include "elf.h"
@@ -129,6 +133,17 @@ static void microvm_devices_init(MicrovmMachineState *mms)
     }
 
     /* Optional and legacy devices */
+    if (x86_machine_is_acpi_enabled(x86ms)) {
+        DeviceState *dev = qdev_new(TYPE_ACPI_GED_X86);
+        qdev_prop_set_uint32(dev, "ged-event", ACPI_GED_PWR_DOWN_EVT);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, GED_MMIO_BASE);
+        /* sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, GED_MMIO_BASE_MEMHP); */
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, GED_MMIO_BASE_REGS);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
+                           x86ms->gsi[GED_MMIO_IRQ]);
+        sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+        mms->acpi_dev = ACPI_DEVICE_IF(dev);
+    }
 
     if (mms->pic == ON_OFF_AUTO_ON || mms->pic == ON_OFF_AUTO_AUTO) {
         qemu_irq *i8259;
@@ -438,6 +453,26 @@ static void microvm_machine_set_auto_kernel_cmdline(Object *obj, bool value,
     mms->auto_kernel_cmdline = value;
 }
 
+static void microvm_machine_done(Notifier *notifier, void *data)
+{
+    MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState,
+                                            machine_done);
+
+    acpi_setup_microvm(mms);
+}
+
+static void microvm_powerdown_req(Notifier *notifier, void *data)
+{
+    MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState,
+                                            powerdown_req);
+
+    if (mms->acpi_dev) {
+        Object *obj = OBJECT(mms->acpi_dev);
+        AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
+        adevc->send_event(mms->acpi_dev, ACPI_POWER_DOWN_STATUS);
+    }
+}
+
 static void microvm_machine_initfn(Object *obj)
 {
     MicrovmMachineState *mms = MICROVM_MACHINE(obj);
@@ -452,6 +487,11 @@ static void microvm_machine_initfn(Object *obj)
 
     /* State */
     mms->kernel_cmdline_fixed = false;
+
+    mms->machine_done.notify = microvm_machine_done;
+    qemu_add_machine_init_done_notifier(&mms->machine_done);
+    mms->powerdown_req.notify = microvm_powerdown_req;
+    qemu_register_powerdown_notifier(&mms->powerdown_req);
 }
 
 static void microvm_class_init(ObjectClass *oc, void *data)
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index c93f32f6579d..be746bcb49eb 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -102,6 +102,7 @@ config MICROVM
     select I8259
     select MC146818RTC
     select VIRTIO_MMIO
+    select ACPI_HW_REDUCED
 
 config X86_IOMMU
     bool
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 622739305882..bbb2fe78f3cd 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -19,3 +19,4 @@ obj-y += kvmvapic.o
 obj-$(CONFIG_ACPI) += acpi-common.o
 obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device_x86.o
 obj-$(CONFIG_PC) += acpi-build.o
+obj-$(CONFIG_MICROVM) += acpi-microvm.o
-- 
2.18.4



  parent reply	other threads:[~2020-07-02 20:51 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-02 20:48 [PATCH v4 00/21] microvm: add acpi support Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 01/21] microvm: name qboot binary qboot.rom Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 02/21] seabios: add microvm config, update build rules Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 03/21] seabios: add bios-microvm.bin binary Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 04/21] acpi: ged: add control regs Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 05/21] acpi: ged: add x86 device variant Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 06/21] acpi: move acpi_dsdt_add_power_button() to ged Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 07/21] microvm: make virtio irq base runtime configurable Gerd Hoffmann
2020-07-02 20:48 ` Gerd Hoffmann [this message]
2020-07-03 13:09   ` [PATCH v4 08/21] microvm/acpi: add minimal acpi support Michael S. Tsirkin
2020-07-03 19:25     ` Gerd Hoffmann
2020-07-05 11:48       ` Michael S. Tsirkin
2020-07-06 14:11         ` Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 09/21] microvm/acpi: add acpi_dsdt_add_virtio() for x86 Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 10/21] microvm/acpi: use GSI 16-23 for virtio Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 11/21] microvm/acpi: use seabios with acpi=on Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 12/21] microvm/acpi: disable virtio-mmio cmdline hack Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 13/21] x86: constify x86_machine_is_*_enabled Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 14/21] x86: move acpi_dev from pc/microvm Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 15/21] x86: move cpu plug from pc to x86 Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 16/21] microvm: wire up hotplug Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 17/21] tests/acpi: clear bios-tables-test-allowed-diff.h Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 18/21] tests/acpi: allow microvm test data updates Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 19/21] tests/acpi: allow override blkdev Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 20/21] tests/acpi: add microvm test Gerd Hoffmann
2020-07-02 20:48 ` [PATCH v4 21/21] tests/acpi: update expected data files for microvm Gerd Hoffmann
2020-07-02 21:13 ` [PATCH v4 00/21] microvm: add acpi support no-reply
2020-07-02 21:23 ` 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=20200702204859.9876-9-kraxel@redhat.com \
    --to=kraxel@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=lvivier@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=shannon.zhaosl@gmail.com \
    --cc=slp@redhat.com \
    --cc=thuth@redhat.com \
    /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.