diff mbox series

[5/7] hw/ipmi: Add an IPMI host interface

Message ID 20201211015156.2053372-6-wuhaotsh@google.com (mailing list archive)
State New, archived
Headers show
Series Additional NPCM7xx devices and IPMI BMC emulation support | expand

Commit Message

Hao Wu Dec. 11, 2020, 1:51 a.m. UTC
The IPMI host interface is used to emulate IPMI related devices on a
System-on-Chip (SoC) used for Baseband Management Controller (BMC).
This interface consists of two components: IPMI host and IPMI responder.
An IPMI responder is a device to intercept reads and writes to the
system interface registers in the host. An IPMI host emulates the host
behavior on a BMC emulation.

For more information see docs/spec/ipmi.rst.

Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Signed-off-by: Hao Wu <wuhaotsh@google.com>
---
 default-configs/devices/arm-softmmu.mak |  2 +
 hw/ipmi/Kconfig                         |  5 ++
 hw/ipmi/ipmi_host.c                     | 40 +++++++++++++++
 hw/ipmi/meson.build                     |  1 +
 include/hw/ipmi/ipmi_host.h             | 56 +++++++++++++++++++++
 include/hw/ipmi/ipmi_responder.h        | 66 +++++++++++++++++++++++++
 6 files changed, 170 insertions(+)
 create mode 100644 hw/ipmi/ipmi_host.c
 create mode 100644 include/hw/ipmi/ipmi_host.h
 create mode 100644 include/hw/ipmi/ipmi_responder.h
diff mbox series

Patch

diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
index 08a32123b4..864bac4501 100644
--- a/default-configs/devices/arm-softmmu.mak
+++ b/default-configs/devices/arm-softmmu.mak
@@ -27,6 +27,8 @@  CONFIG_GUMSTIX=y
 CONFIG_SPITZ=y
 CONFIG_TOSA=y
 CONFIG_Z2=y
+CONFIG_IPMI=y
+CONFIG_IPMI_HOST=y
 CONFIG_NPCM7XX=y
 CONFIG_COLLIE=y
 CONFIG_ASPEED_SOC=y
diff --git a/hw/ipmi/Kconfig b/hw/ipmi/Kconfig
index 9befd4f422..9e487eb42f 100644
--- a/hw/ipmi/Kconfig
+++ b/hw/ipmi/Kconfig
@@ -6,6 +6,11 @@  config IPMI_LOCAL
     default y
     depends on IPMI
 
+config IPMI_HOST
+    bool
+    default y
+    depends on IPMI
+
 config IPMI_EXTERN
     bool
     default y
diff --git a/hw/ipmi/ipmi_host.c b/hw/ipmi/ipmi_host.c
new file mode 100644
index 0000000000..7a6d4eb323
--- /dev/null
+++ b/hw/ipmi/ipmi_host.c
@@ -0,0 +1,40 @@ 
+/*
+ * IPMI Host emulation
+ *
+ * Copyright 2020 Google LLC
+ *
+ * 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.
+ */
+
+#include "hw/ipmi/ipmi_host.h"
+#include "hw/ipmi/ipmi_responder.h"
+
+static TypeInfo ipmi_responder_type_info = {
+    .name = TYPE_IPMI_RESPONDER,
+    .parent = TYPE_INTERFACE,
+    .class_size = sizeof(IPMIResponderClass),
+};
+
+static TypeInfo ipmi_host_type_info = {
+    .name = TYPE_IPMI_HOST,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(IPMIHost),
+    .abstract = true,
+    .class_size = sizeof(IPMIHostClass),
+};
+
+static void ipmi_register_types(void)
+{
+    type_register_static(&ipmi_responder_type_info);
+    type_register_static(&ipmi_host_type_info);
+}
+
+type_init(ipmi_register_types)
diff --git a/hw/ipmi/meson.build b/hw/ipmi/meson.build
index 9622ea2a2c..9ec4dcb957 100644
--- a/hw/ipmi/meson.build
+++ b/hw/ipmi/meson.build
@@ -7,5 +7,6 @@  ipmi_ss.add(when: 'CONFIG_PCI_IPMI_KCS', if_true: files('pci_ipmi_kcs.c'))
 ipmi_ss.add(when: 'CONFIG_ISA_IPMI_BT', if_true: files('isa_ipmi_bt.c'))
 ipmi_ss.add(when: 'CONFIG_PCI_IPMI_BT', if_true: files('pci_ipmi_bt.c'))
 ipmi_ss.add(when: 'CONFIG_IPMI_SSIF', if_true: files('smbus_ipmi.c'))
+ipmi_ss.add(when: 'CONFIG_IPMI_HOST', if_true: files('ipmi_host.c'))
 
 softmmu_ss.add_all(when: 'CONFIG_IPMI', if_true: ipmi_ss)
diff --git a/include/hw/ipmi/ipmi_host.h b/include/hw/ipmi/ipmi_host.h
new file mode 100644
index 0000000000..a703cc3854
--- /dev/null
+++ b/include/hw/ipmi/ipmi_host.h
@@ -0,0 +1,56 @@ 
+/*
+ * IPMI host interface
+ *
+ * Copyright 2020 Google LLC
+ *
+ * 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.
+ */
+
+#ifndef HW_IPMI_HOST_H
+#define HW_IPMI_HOST_H
+
+#include "hw/ipmi/ipmi_responder.h"
+
+#define TYPE_IPMI_HOST "ipmi-host"
+#define IPMI_HOST(obj) \
+     OBJECT_CHECK(IPMIHost, (obj), TYPE_IPMI_HOST)
+#define IPMI_HOST_CLASS(obj_class) \
+     OBJECT_CLASS_CHECK(IPMIHostClass, (obj_class), TYPE_IPMI_HOST)
+#define IPMI_HOST_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(IPMIHostClass, (obj), TYPE_IPMI_HOST)
+
+/**
+ * struct IPMIHost defines an IPMI host interface. It can be a simulator or a
+ * connection to an emulated or real host.
+ * @responder: The IPMI responder that handles an IPMI message.
+ */
+typedef struct IPMIHost {
+    DeviceState parent;
+
+    IPMIResponder *responder;
+} IPMIHost;
+
+/**
+ * struct IPMIHostClass defines an IPMI host class.
+ * @handle_command: Handle a command to the host.
+ */
+typedef struct IPMIHostClass {
+    DeviceClass parent;
+
+    /*
+     * Handle a command to the bmc.
+     */
+    void (*handle_command)(struct IPMIHost *s,
+                           uint8_t *cmd, unsigned int cmd_len,
+                           unsigned int max_cmd_len, uint8_t msg_id);
+} IPMIHostClass;
+
+#endif /* HW_IPMI_HOST_H */
diff --git a/include/hw/ipmi/ipmi_responder.h b/include/hw/ipmi/ipmi_responder.h
new file mode 100644
index 0000000000..e3e4ef39d4
--- /dev/null
+++ b/include/hw/ipmi/ipmi_responder.h
@@ -0,0 +1,66 @@ 
+/*
+ * IPMI responder interface
+ *
+ * Copyright 2020 Google LLC
+ *
+ * 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.
+ */
+
+#ifndef HW_IPMI_RESPONDER_H
+#define HW_IPMI_RESPONDER_H
+
+#include "qemu/osdep.h"
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+
+#define TYPE_IPMI_RESPONDER_PREFIX "ipmi-responder-"
+#define TYPE_IPMI_RESPONDER "ipmi-responder"
+#define IPMI_RESPONDER(obj) \
+     INTERFACE_CHECK(IPMIResponder, (obj), TYPE_IPMI_RESPONDER)
+#define IPMI_RESPONDER_CLASS(class) \
+     OBJECT_CLASS_CHECK(IPMIResponderClass, (class), TYPE_IPMI_RESPONDER)
+#define IPMI_RESPONDER_GET_CLASS(class) \
+     OBJECT_GET_CLASS(IPMIResponderClass, (class), TYPE_IPMI_RESPONDER)
+
+struct IPMIHost;
+
+/**
+ * This interface is implemented by each IPMI responder device (KCS, BT, PCI,
+ * etc.) An IPMI host device uses it to transfer data to the emulated BMC.
+ */
+typedef struct IPMIResponder IPMIResponder;
+
+/**
+ * struct IPMIResponderClass implemented by an IPMI responder device like KCS to
+ * handle commands from connected IPMI host device.
+ * @get_host: Return the IPMI host (e.g. ipmi-host-extern) that uses this
+ *  responder.
+ * @set_host: Set the IPMI host (e.g. ipmi-host-extern) that uses this
+ *  responder.
+ * @get_backend_data: Return the backend device (e.g. KCS, BT) of the
+ *  corresponding responder.
+ * @handle_req: The IPMI Host device calls this function when it receives a sane
+ *  IPMI message. A responder should handle this message.
+ */
+typedef struct IPMIResponderClass {
+    InterfaceClass parent;
+
+    struct IPMIHost *(*get_host)(struct IPMIResponder *s);
+
+    void (*set_host)(struct IPMIResponder *s, struct IPMIHost *h);
+
+    void *(*get_backend_data)(struct IPMIResponder *s);
+
+    void (*handle_req)(struct IPMIResponder *s, uint8_t msg_id,
+            unsigned char *req, unsigned req_len);
+} IPMIResponderClass;
+
+#endif /* HW_IPMI_RESPONDER_H */