diff mbox

[v4,02/17] Add a base IPMI interface

Message ID 1447354953-18893-3-git-send-email-minyard@acm.org
State New
Headers show

Commit Message

Corey Minyard Nov. 12, 2015, 7:02 p.m. UTC
From: Corey Minyard <cminyard@mvista.com>

Add the basic IPMI types and infrastructure to QEMU.  Low-level
interfaces and simulation interfaces will register with this; it's
kind of the go-between to tie them together.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
---
 default-configs/i386-softmmu.mak   |   1 +
 default-configs/x86_64-softmmu.mak |   1 +
 hw/Makefile.objs                   |   1 +
 hw/ipmi/Makefile.objs              |   1 +
 hw/ipmi/ipmi.c                     | 125 ++++++++++++++++++++++++++
 include/hw/ipmi/ipmi.h             | 178 +++++++++++++++++++++++++++++++++++++
 qemu-doc.texi                      |   2 +
 7 files changed, 309 insertions(+)
 create mode 100644 hw/ipmi/Makefile.objs
 create mode 100644 hw/ipmi/ipmi.c
 create mode 100644 include/hw/ipmi/ipmi.h

Comments

Corey Minyard Nov. 18, 2015, 6:41 p.m. UTC | #1
I haven't heard any more comments on this series, should I resubmit with
the one shutdown change?

-corey
On Nov 12, 2015 1:02 PM, <minyard@acm.org> wrote:

> From: Corey Minyard <cminyard@mvista.com>
>
> Add the basic IPMI types and infrastructure to QEMU.  Low-level
> interfaces and simulation interfaces will register with this; it's
> kind of the go-between to tie them together.
>
> Signed-off-by: Corey Minyard <cminyard@mvista.com>
> ---
>  default-configs/i386-softmmu.mak   |   1 +
>  default-configs/x86_64-softmmu.mak |   1 +
>  hw/Makefile.objs                   |   1 +
>  hw/ipmi/Makefile.objs              |   1 +
>  hw/ipmi/ipmi.c                     | 125 ++++++++++++++++++++++++++
>  include/hw/ipmi/ipmi.h             | 178
> +++++++++++++++++++++++++++++++++++++
>  qemu-doc.texi                      |   2 +
>  7 files changed, 309 insertions(+)
>  create mode 100644 hw/ipmi/Makefile.objs
>  create mode 100644 hw/ipmi/ipmi.c
>  create mode 100644 include/hw/ipmi/ipmi.h
>
> diff --git a/default-configs/i386-softmmu.mak
> b/default-configs/i386-softmmu.mak
> index 43c96d1..8fa751a 100644
> --- a/default-configs/i386-softmmu.mak
> +++ b/default-configs/i386-softmmu.mak
> @@ -9,6 +9,7 @@ CONFIG_VGA_CIRRUS=y
>  CONFIG_VMWARE_VGA=y
>  CONFIG_VIRTIO_VGA=y
>  CONFIG_VMMOUSE=y
> +CONFIG_IPMI=y
>  CONFIG_SERIAL=y
>  CONFIG_PARALLEL=y
>  CONFIG_I8254=y
> diff --git a/default-configs/x86_64-softmmu.mak
> b/default-configs/x86_64-softmmu.mak
> index dfb8095..6767f4f 100644
> --- a/default-configs/x86_64-softmmu.mak
> +++ b/default-configs/x86_64-softmmu.mak
> @@ -9,6 +9,7 @@ CONFIG_VGA_CIRRUS=y
>  CONFIG_VMWARE_VGA=y
>  CONFIG_VIRTIO_VGA=y
>  CONFIG_VMMOUSE=y
> +CONFIG_IPMI=y
>  CONFIG_SERIAL=y
>  CONFIG_PARALLEL=y
>  CONFIG_I8254=y
> diff --git a/hw/Makefile.objs b/hw/Makefile.objs
> index 7e7c241..4a07ed4 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -13,6 +13,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += ide/
>  devices-dirs-$(CONFIG_SOFTMMU) += input/
>  devices-dirs-$(CONFIG_SOFTMMU) += intc/
>  devices-dirs-$(CONFIG_IPACK) += ipack/
> +devices-dirs-$(CONFIG_IPMI) += ipmi/
>  devices-dirs-$(CONFIG_SOFTMMU) += isa/
>  devices-dirs-$(CONFIG_SOFTMMU) += misc/
>  devices-dirs-$(CONFIG_SOFTMMU) += net/
> diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs
> new file mode 100644
> index 0000000..65bde11
> --- /dev/null
> +++ b/hw/ipmi/Makefile.objs
> @@ -0,0 +1 @@
> +common-obj-$(CONFIG_IPMI) += ipmi.o
> diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
> new file mode 100644
> index 0000000..7d17469
> --- /dev/null
> +++ b/hw/ipmi/ipmi.c
> @@ -0,0 +1,125 @@
> +/*
> + * QEMU IPMI emulation
> + *
> + * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining
> a copy
> + * of this software and associated documentation files (the "Software"),
> to deal
> + * in the Software without restriction, including without limitation the
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
> sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> IN
> + * THE SOFTWARE.
> + */
> +
> +#include "hw/hw.h"
> +#include "hw/ipmi/ipmi.h"
> +#include "sysemu/sysemu.h"
> +#include "qmp-commands.h"
> +#include "qom/object_interfaces.h"
> +#include "qapi/visitor.h"
> +
> +static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
> +{
> +    switch (op) {
> +    case IPMI_RESET_CHASSIS:
> +        if (checkonly) {
> +            return 0;
> +        }
> +        qemu_system_reset_request();
> +        return 0;
> +
> +    case IPMI_POWEROFF_CHASSIS:
> +        if (checkonly) {
> +            return 0;
> +        }
> +        qemu_system_powerdown_request();
> +        return 0;
> +
> +    case IPMI_SEND_NMI:
> +        if (checkonly) {
> +            return 0;
> +        }
> +        qemu_mutex_lock_iothread();
> +        qmp_inject_nmi(NULL);
> +        qemu_mutex_unlock_iothread();
> +        return 0;
> +
> +    case IPMI_POWERCYCLE_CHASSIS:
> +    case IPMI_PULSE_DIAG_IRQ:
> +    case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
> +    case IPMI_POWERON_CHASSIS:
> +    default:
> +        return IPMI_CC_COMMAND_NOT_SUPPORTED;
> +    }
> +}
> +
> +static void ipmi_interface_class_init(ObjectClass *class, void *data)
> +{
> +    IPMIInterfaceClass *ik = IPMI_INTERFACE_CLASS(class);
> +
> +    ik->do_hw_op = ipmi_do_hw_op;
> +}
> +
> +static TypeInfo ipmi_interface_type_info = {
> +    .name = TYPE_IPMI_INTERFACE,
> +    .parent = TYPE_INTERFACE,
> +    .class_size = sizeof(IPMIInterfaceClass),
> +    .class_init = ipmi_interface_class_init,
> +};
> +
> +static void isa_ipmi_bmc_check(Object *obj, const char *name,
> +                               Object *val, Error **errp)
> +{
> +    IPMIBmc *bmc = IPMI_BMC(val);
> +
> +    if (bmc->intf)
> +        error_setg(errp, "BMC object is already in use");
> +}
> +
> +void ipmi_bmc_find_and_link(Object *obj, Object **bmc)
> +{
> +    object_property_add_link(obj, "bmc", TYPE_IPMI_BMC, bmc,
> +                             isa_ipmi_bmc_check,
> +                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
> +                             &error_abort);
> +}
> +
> +static Property ipmi_bmc_properties[] = {
> +    DEFINE_PROP_UINT8("slave_addr",  IPMIBmc, slave_addr, 0x20),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void bmc_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    dc->props = ipmi_bmc_properties;
> +}
> +
> +static TypeInfo ipmi_bmc_type_info = {
> +    .name = TYPE_IPMI_BMC,
> +    .parent = TYPE_DEVICE,
> +    .instance_size = sizeof(IPMIBmc),
> +    .abstract = true,
> +    .class_size = sizeof(IPMIBmcClass),
> +    .class_init = bmc_class_init,
> +};
> +
> +static void ipmi_register_types(void)
> +{
> +    type_register_static(&ipmi_interface_type_info);
> +    type_register_static(&ipmi_bmc_type_info);
> +}
> +
> +type_init(ipmi_register_types)
> diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
> new file mode 100644
> index 0000000..e4f7738
> --- /dev/null
> +++ b/include/hw/ipmi/ipmi.h
> @@ -0,0 +1,178 @@
> +/*
> + * IPMI base class
> + *
> + * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining
> a copy
> + * of this software and associated documentation files (the "Software"),
> to deal
> + * in the Software without restriction, including without limitation the
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
> sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_IPMI_H
> +#define HW_IPMI_H
> +
> +#include "exec/memory.h"
> +#include "qemu-common.h"
> +#include "hw/qdev.h"
> +
> +#define MAX_IPMI_MSG_SIZE 300
> +
> +enum ipmi_op {
> +    IPMI_RESET_CHASSIS,
> +    IPMI_POWEROFF_CHASSIS,
> +    IPMI_POWERON_CHASSIS,
> +    IPMI_POWERCYCLE_CHASSIS,
> +    IPMI_PULSE_DIAG_IRQ,
> +    IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP,
> +    IPMI_SEND_NMI
> +};
> +
> +#define IPMI_CC_INVALID_CMD                              0xc1
> +#define IPMI_CC_COMMAND_INVALID_FOR_LUN                  0xc2
> +#define IPMI_CC_TIMEOUT                                  0xc3
> +#define IPMI_CC_OUT_OF_SPACE                             0xc4
> +#define IPMI_CC_INVALID_RESERVATION                      0xc5
> +#define IPMI_CC_REQUEST_DATA_TRUNCATED                   0xc6
> +#define IPMI_CC_REQUEST_DATA_LENGTH_INVALID              0xc7
> +#define IPMI_CC_PARM_OUT_OF_RANGE                        0xc9
> +#define IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES              0xca
> +#define IPMI_CC_REQ_ENTRY_NOT_PRESENT                    0xcb
> +#define IPMI_CC_INVALID_DATA_FIELD                       0xcc
> +#define IPMI_CC_BMC_INIT_IN_PROGRESS                     0xd2
> +#define IPMI_CC_COMMAND_NOT_SUPPORTED                    0xd5
> +
> +#define IPMI_NETFN_APP                0x06
> +
> +#define IPMI_DEBUG 1
> +
> +/* Specified in the SMBIOS spec. */
> +#define IPMI_SMBIOS_KCS         0x01
> +#define IPMI_SMBIOS_SMIC        0x02
> +#define IPMI_SMBIOS_BT          0x03
> +#define IPMI_SMBIOS_SSIF        0x04
> +
> +/* IPMI Interface types (KCS, SMIC, BT) are prefixed with this */
> +#define TYPE_IPMI_INTERFACE_PREFIX "ipmi-interface-"
> +
> +/*
> + * An IPMI Interface, the interface for talking between the target
> + * and the BMC.
> + */
> +#define TYPE_IPMI_INTERFACE "ipmi-interface"
> +#define IPMI_INTERFACE(obj) \
> +     INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE)
> +#define IPMI_INTERFACE_CLASS(class) \
> +     OBJECT_CLASS_CHECK(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
> +#define IPMI_INTERFACE_GET_CLASS(class) \
> +     OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
> +
> +typedef struct IPMIInterface {
> +    Object parent;
> +} IPMIInterface;
> +
> +typedef struct IPMIInterfaceClass {
> +    InterfaceClass parent;
> +
> +    void (*init)(struct IPMIInterface *s, Error **errp);
> +
> +    /*
> +     * Perform various operations on the hardware.  If checkonly is
> +     * true, it will return if the operation can be performed, but it
> +     * will not do the operation.
> +     */
> +    int (*do_hw_op)(struct IPMIInterface *s, enum ipmi_op op, int
> checkonly);
> +
> +    /*
> +     * Enable/disable irqs on the interface when the BMC requests this.
> +     */
> +    void (*set_irq_enable)(struct IPMIInterface *s, int val);
> +
> +    /*
> +     * Handle an event that occurred on the interface, generally the.
> +     * target writing to a register.
> +     */
> +    void (*handle_if_event)(struct IPMIInterface *s);
> +
> +    /*
> +     * The interfaces use this to perform certain ops
> +     */
> +    void (*set_atn)(struct IPMIInterface *s, int val, int irq);
> +
> +    /*
> +     * Got an IPMI warm/cold reset.
> +     */
> +    void (*reset)(struct IPMIInterface *s, bool is_cold);
> +
> +    /*
> +     * Handle a response from the bmc.
> +     */
> +    void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id,
> +                       unsigned char *rsp, unsigned int rsp_len);
> +
> +    /*
> +     * Set by the owner to hold the backend data for the interface.
> +     */
> +    void *(*get_backend_data)(struct IPMIInterface *s);
> +} IPMIInterfaceClass;
> +
> +/*
> + * Define a BMC simulator (or perhaps a connection to a real BMC)
> + */
> +#define TYPE_IPMI_BMC "ipmi-bmc"
> +#define IPMI_BMC(obj) \
> +     OBJECT_CHECK(IPMIBmc, (obj), TYPE_IPMI_BMC)
> +#define IPMI_BMC_CLASS(obj_class) \
> +     OBJECT_CLASS_CHECK(IPMIBmcClass, (obj_class), TYPE_IPMI_BMC)
> +#define IPMI_BMC_GET_CLASS(obj) \
> +     OBJECT_GET_CLASS(IPMIBmcClass, (obj), TYPE_IPMI_BMC)
> +
> +typedef struct IPMIBmc {
> +    DeviceState parent;
> +
> +    uint8_t slave_addr;
> +
> +    IPMIInterface *intf;
> +} IPMIBmc;
> +
> +typedef struct IPMIBmcClass {
> +    DeviceClass parent;
> +
> +    /* Called when the system resets to report to the bmc. */
> +    void (*handle_reset)(struct IPMIBmc *s);
> +
> +    /*
> +     * Handle a command to the bmc.
> +     */
> +    void (*handle_command)(struct IPMIBmc *s,
> +                           uint8_t *cmd, unsigned int cmd_len,
> +                           unsigned int max_cmd_len,
> +                           uint8_t msg_id);
> +} IPMIBmcClass;
> +
> +/*
> + * Add a link property to obj that points to a BMC.
> + */
> +void ipmi_bmc_find_and_link(Object *obj, Object **bmc);
> +
> +#ifdef IPMI_DEBUG
> +#define ipmi_debug(fs, ...) \
> +    fprintf(stderr, "IPMI (%s): " fs, __func__, ##__VA_ARGS__)
> +#else
> +#define ipmi_debug(fs, ...)
> +#endif
> +
> +#endif
> diff --git a/qemu-doc.texi b/qemu-doc.texi
> index 460ab71..3c82d30 100644
> --- a/qemu-doc.texi
> +++ b/qemu-doc.texi
> @@ -195,6 +195,8 @@ PCI and ISA network adapters
>  @item
>  Serial ports
>  @item
> +IPMI BMC, either and internal or external one
> +@item
>  Creative SoundBlaster 16 sound card
>  @item
>  ENSONIQ AudioPCI ES1370 sound card
> --
> 1.8.3.1
>
>
Michael S. Tsirkin Nov. 18, 2015, 8:42 p.m. UTC | #2
Please submit after 2.5 is out.
It's clearly a new feature so can't be merged now, after freeze.

On Wed, Nov 18, 2015 at 12:41:20PM -0600, Corey Minyard wrote:
> I haven't heard any more comments on this series, should I resubmit with the
> one shutdown change?
> 
> -corey
> 
> On Nov 12, 2015 1:02 PM, <minyard@acm.org> wrote:
> 
>     From: Corey Minyard <cminyard@mvista.com>
> 
>     Add the basic IPMI types and infrastructure to QEMU.  Low-level
>     interfaces and simulation interfaces will register with this; it's
>     kind of the go-between to tie them together.
> 
>     Signed-off-by: Corey Minyard <cminyard@mvista.com>
>     ---
>      default-configs/i386-softmmu.mak   |   1 +
>      default-configs/x86_64-softmmu.mak |   1 +
>      hw/Makefile.objs                   |   1 +
>      hw/ipmi/Makefile.objs              |   1 +
>      hw/ipmi/ipmi.c                     | 125 ++++++++++++++++++++++++++
>      include/hw/ipmi/ipmi.h             | 178
>     +++++++++++++++++++++++++++++++++++++
>      qemu-doc.texi                      |   2 +
>      7 files changed, 309 insertions(+)
>      create mode 100644 hw/ipmi/Makefile.objs
>      create mode 100644 hw/ipmi/ipmi.c
>      create mode 100644 include/hw/ipmi/ipmi.h
> 
>     diff --git a/default-configs/i386-softmmu.mak b/default-configs/
>     i386-softmmu.mak
>     index 43c96d1..8fa751a 100644
>     --- a/default-configs/i386-softmmu.mak
>     +++ b/default-configs/i386-softmmu.mak
>     @@ -9,6 +9,7 @@ CONFIG_VGA_CIRRUS=y
>      CONFIG_VMWARE_VGA=y
>      CONFIG_VIRTIO_VGA=y
>      CONFIG_VMMOUSE=y
>     +CONFIG_IPMI=y
>      CONFIG_SERIAL=y
>      CONFIG_PARALLEL=y
>      CONFIG_I8254=y
>     diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/
>     x86_64-softmmu.mak
>     index dfb8095..6767f4f 100644
>     --- a/default-configs/x86_64-softmmu.mak
>     +++ b/default-configs/x86_64-softmmu.mak
>     @@ -9,6 +9,7 @@ CONFIG_VGA_CIRRUS=y
>      CONFIG_VMWARE_VGA=y
>      CONFIG_VIRTIO_VGA=y
>      CONFIG_VMMOUSE=y
>     +CONFIG_IPMI=y
>      CONFIG_SERIAL=y
>      CONFIG_PARALLEL=y
>      CONFIG_I8254=y
>     diff --git a/hw/Makefile.objs b/hw/Makefile.objs
>     index 7e7c241..4a07ed4 100644
>     --- a/hw/Makefile.objs
>     +++ b/hw/Makefile.objs
>     @@ -13,6 +13,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += ide/
>      devices-dirs-$(CONFIG_SOFTMMU) += input/
>      devices-dirs-$(CONFIG_SOFTMMU) += intc/
>      devices-dirs-$(CONFIG_IPACK) += ipack/
>     +devices-dirs-$(CONFIG_IPMI) += ipmi/
>      devices-dirs-$(CONFIG_SOFTMMU) += isa/
>      devices-dirs-$(CONFIG_SOFTMMU) += misc/
>      devices-dirs-$(CONFIG_SOFTMMU) += net/
>     diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs
>     new file mode 100644
>     index 0000000..65bde11
>     --- /dev/null
>     +++ b/hw/ipmi/Makefile.objs
>     @@ -0,0 +1 @@
>     +common-obj-$(CONFIG_IPMI) += ipmi.o
>     diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
>     new file mode 100644
>     index 0000000..7d17469
>     --- /dev/null
>     +++ b/hw/ipmi/ipmi.c
>     @@ -0,0 +1,125 @@
>     +/*
>     + * QEMU IPMI emulation
>     + *
>     + * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
>     + *
>     + * Permission is hereby granted, free of charge, to any person obtaining a
>     copy
>     + * of this software and associated documentation files (the "Software"),
>     to deal
>     + * in the Software without restriction, including without limitation the
>     rights
>     + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>     sell
>     + * copies of the Software, and to permit persons to whom the Software is
>     + * furnished to do so, subject to the following conditions:
>     + *
>     + * The above copyright notice and this permission notice shall be included
>     in
>     + * all copies or substantial portions of the Software.
>     + *
>     + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
>     OR
>     + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>     MERCHANTABILITY,
>     + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>     + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>     OTHER
>     + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>     FROM,
>     + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
>     IN
>     + * THE SOFTWARE.
>     + */
>     +
>     +#include "hw/hw.h"
>     +#include "hw/ipmi/ipmi.h"
>     +#include "sysemu/sysemu.h"
>     +#include "qmp-commands.h"
>     +#include "qom/object_interfaces.h"
>     +#include "qapi/visitor.h"
>     +
>     +static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
>     +{
>     +    switch (op) {
>     +    case IPMI_RESET_CHASSIS:
>     +        if (checkonly) {
>     +            return 0;
>     +        }
>     +        qemu_system_reset_request();
>     +        return 0;
>     +
>     +    case IPMI_POWEROFF_CHASSIS:
>     +        if (checkonly) {
>     +            return 0;
>     +        }
>     +        qemu_system_powerdown_request();
>     +        return 0;
>     +
>     +    case IPMI_SEND_NMI:
>     +        if (checkonly) {
>     +            return 0;
>     +        }
>     +        qemu_mutex_lock_iothread();
>     +        qmp_inject_nmi(NULL);
>     +        qemu_mutex_unlock_iothread();
>     +        return 0;
>     +
>     +    case IPMI_POWERCYCLE_CHASSIS:
>     +    case IPMI_PULSE_DIAG_IRQ:
>     +    case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
>     +    case IPMI_POWERON_CHASSIS:
>     +    default:
>     +        return IPMI_CC_COMMAND_NOT_SUPPORTED;
>     +    }
>     +}
>     +
>     +static void ipmi_interface_class_init(ObjectClass *class, void *data)
>     +{
>     +    IPMIInterfaceClass *ik = IPMI_INTERFACE_CLASS(class);
>     +
>     +    ik->do_hw_op = ipmi_do_hw_op;
>     +}
>     +
>     +static TypeInfo ipmi_interface_type_info = {
>     +    .name = TYPE_IPMI_INTERFACE,
>     +    .parent = TYPE_INTERFACE,
>     +    .class_size = sizeof(IPMIInterfaceClass),
>     +    .class_init = ipmi_interface_class_init,
>     +};
>     +
>     +static void isa_ipmi_bmc_check(Object *obj, const char *name,
>     +                               Object *val, Error **errp)
>     +{
>     +    IPMIBmc *bmc = IPMI_BMC(val);
>     +
>     +    if (bmc->intf)
>     +        error_setg(errp, "BMC object is already in use");
>     +}
>     +
>     +void ipmi_bmc_find_and_link(Object *obj, Object **bmc)
>     +{
>     +    object_property_add_link(obj, "bmc", TYPE_IPMI_BMC, bmc,
>     +                             isa_ipmi_bmc_check,
>     +                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
>     +                             &error_abort);
>     +}
>     +
>     +static Property ipmi_bmc_properties[] = {
>     +    DEFINE_PROP_UINT8("slave_addr",  IPMIBmc, slave_addr, 0x20),
>     +    DEFINE_PROP_END_OF_LIST(),
>     +};
>     +
>     +static void bmc_class_init(ObjectClass *oc, void *data)
>     +{
>     +    DeviceClass *dc = DEVICE_CLASS(oc);
>     +
>     +    dc->props = ipmi_bmc_properties;
>     +}
>     +
>     +static TypeInfo ipmi_bmc_type_info = {
>     +    .name = TYPE_IPMI_BMC,
>     +    .parent = TYPE_DEVICE,
>     +    .instance_size = sizeof(IPMIBmc),
>     +    .abstract = true,
>     +    .class_size = sizeof(IPMIBmcClass),
>     +    .class_init = bmc_class_init,
>     +};
>     +
>     +static void ipmi_register_types(void)
>     +{
>     +    type_register_static(&ipmi_interface_type_info);
>     +    type_register_static(&ipmi_bmc_type_info);
>     +}
>     +
>     +type_init(ipmi_register_types)
>     diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
>     new file mode 100644
>     index 0000000..e4f7738
>     --- /dev/null
>     +++ b/include/hw/ipmi/ipmi.h
>     @@ -0,0 +1,178 @@
>     +/*
>     + * IPMI base class
>     + *
>     + * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
>     + *
>     + * Permission is hereby granted, free of charge, to any person obtaining a
>     copy
>     + * of this software and associated documentation files (the "Software"),
>     to deal
>     + * in the Software without restriction, including without limitation the
>     rights
>     + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>     sell
>     + * copies of the Software, and to permit persons to whom the Software is
>     + * furnished to do so, subject to the following conditions:
>     + *
>     + * The above copyright notice and this permission notice shall be included
>     in
>     + * all copies or substantial portions of the Software.
>     + *
>     + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
>     OR
>     + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>     MERCHANTABILITY,
>     + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>     + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>     OTHER
>     + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>     FROM,
>     + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
>     IN
>     + * THE SOFTWARE.
>     + */
>     +
>     +#ifndef HW_IPMI_H
>     +#define HW_IPMI_H
>     +
>     +#include "exec/memory.h"
>     +#include "qemu-common.h"
>     +#include "hw/qdev.h"
>     +
>     +#define MAX_IPMI_MSG_SIZE 300
>     +
>     +enum ipmi_op {
>     +    IPMI_RESET_CHASSIS,
>     +    IPMI_POWEROFF_CHASSIS,
>     +    IPMI_POWERON_CHASSIS,
>     +    IPMI_POWERCYCLE_CHASSIS,
>     +    IPMI_PULSE_DIAG_IRQ,
>     +    IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP,
>     +    IPMI_SEND_NMI
>     +};
>     +
>     +#define IPMI_CC_INVALID_CMD                              0xc1
>     +#define IPMI_CC_COMMAND_INVALID_FOR_LUN                  0xc2
>     +#define IPMI_CC_TIMEOUT                                  0xc3
>     +#define IPMI_CC_OUT_OF_SPACE                             0xc4
>     +#define IPMI_CC_INVALID_RESERVATION                      0xc5
>     +#define IPMI_CC_REQUEST_DATA_TRUNCATED                   0xc6
>     +#define IPMI_CC_REQUEST_DATA_LENGTH_INVALID              0xc7
>     +#define IPMI_CC_PARM_OUT_OF_RANGE                        0xc9
>     +#define IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES              0xca
>     +#define IPMI_CC_REQ_ENTRY_NOT_PRESENT                    0xcb
>     +#define IPMI_CC_INVALID_DATA_FIELD                       0xcc
>     +#define IPMI_CC_BMC_INIT_IN_PROGRESS                     0xd2
>     +#define IPMI_CC_COMMAND_NOT_SUPPORTED                    0xd5
>     +
>     +#define IPMI_NETFN_APP                0x06
>     +
>     +#define IPMI_DEBUG 1
>     +
>     +/* Specified in the SMBIOS spec. */
>     +#define IPMI_SMBIOS_KCS         0x01
>     +#define IPMI_SMBIOS_SMIC        0x02
>     +#define IPMI_SMBIOS_BT          0x03
>     +#define IPMI_SMBIOS_SSIF        0x04
>     +
>     +/* IPMI Interface types (KCS, SMIC, BT) are prefixed with this */
>     +#define TYPE_IPMI_INTERFACE_PREFIX "ipmi-interface-"
>     +
>     +/*
>     + * An IPMI Interface, the interface for talking between the target
>     + * and the BMC.
>     + */
>     +#define TYPE_IPMI_INTERFACE "ipmi-interface"
>     +#define IPMI_INTERFACE(obj) \
>     +     INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE)
>     +#define IPMI_INTERFACE_CLASS(class) \
>     +     OBJECT_CLASS_CHECK(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
>     +#define IPMI_INTERFACE_GET_CLASS(class) \
>     +     OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
>     +
>     +typedef struct IPMIInterface {
>     +    Object parent;
>     +} IPMIInterface;
>     +
>     +typedef struct IPMIInterfaceClass {
>     +    InterfaceClass parent;
>     +
>     +    void (*init)(struct IPMIInterface *s, Error **errp);
>     +
>     +    /*
>     +     * Perform various operations on the hardware.  If checkonly is
>     +     * true, it will return if the operation can be performed, but it
>     +     * will not do the operation.
>     +     */
>     +    int (*do_hw_op)(struct IPMIInterface *s, enum ipmi_op op, int
>     checkonly);
>     +
>     +    /*
>     +     * Enable/disable irqs on the interface when the BMC requests this.
>     +     */
>     +    void (*set_irq_enable)(struct IPMIInterface *s, int val);
>     +
>     +    /*
>     +     * Handle an event that occurred on the interface, generally the.
>     +     * target writing to a register.
>     +     */
>     +    void (*handle_if_event)(struct IPMIInterface *s);
>     +
>     +    /*
>     +     * The interfaces use this to perform certain ops
>     +     */
>     +    void (*set_atn)(struct IPMIInterface *s, int val, int irq);
>     +
>     +    /*
>     +     * Got an IPMI warm/cold reset.
>     +     */
>     +    void (*reset)(struct IPMIInterface *s, bool is_cold);
>     +
>     +    /*
>     +     * Handle a response from the bmc.
>     +     */
>     +    void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id,
>     +                       unsigned char *rsp, unsigned int rsp_len);
>     +
>     +    /*
>     +     * Set by the owner to hold the backend data for the interface.
>     +     */
>     +    void *(*get_backend_data)(struct IPMIInterface *s);
>     +} IPMIInterfaceClass;
>     +
>     +/*
>     + * Define a BMC simulator (or perhaps a connection to a real BMC)
>     + */
>     +#define TYPE_IPMI_BMC "ipmi-bmc"
>     +#define IPMI_BMC(obj) \
>     +     OBJECT_CHECK(IPMIBmc, (obj), TYPE_IPMI_BMC)
>     +#define IPMI_BMC_CLASS(obj_class) \
>     +     OBJECT_CLASS_CHECK(IPMIBmcClass, (obj_class), TYPE_IPMI_BMC)
>     +#define IPMI_BMC_GET_CLASS(obj) \
>     +     OBJECT_GET_CLASS(IPMIBmcClass, (obj), TYPE_IPMI_BMC)
>     +
>     +typedef struct IPMIBmc {
>     +    DeviceState parent;
>     +
>     +    uint8_t slave_addr;
>     +
>     +    IPMIInterface *intf;
>     +} IPMIBmc;
>     +
>     +typedef struct IPMIBmcClass {
>     +    DeviceClass parent;
>     +
>     +    /* Called when the system resets to report to the bmc. */
>     +    void (*handle_reset)(struct IPMIBmc *s);
>     +
>     +    /*
>     +     * Handle a command to the bmc.
>     +     */
>     +    void (*handle_command)(struct IPMIBmc *s,
>     +                           uint8_t *cmd, unsigned int cmd_len,
>     +                           unsigned int max_cmd_len,
>     +                           uint8_t msg_id);
>     +} IPMIBmcClass;
>     +
>     +/*
>     + * Add a link property to obj that points to a BMC.
>     + */
>     +void ipmi_bmc_find_and_link(Object *obj, Object **bmc);
>     +
>     +#ifdef IPMI_DEBUG
>     +#define ipmi_debug(fs, ...) \
>     +    fprintf(stderr, "IPMI (%s): " fs, __func__, ##__VA_ARGS__)
>     +#else
>     +#define ipmi_debug(fs, ...)
>     +#endif
>     +
>     +#endif
>     diff --git a/qemu-doc.texi b/qemu-doc.texi
>     index 460ab71..3c82d30 100644
>     --- a/qemu-doc.texi
>     +++ b/qemu-doc.texi
>     @@ -195,6 +195,8 @@ PCI and ISA network adapters
>      @item
>      Serial ports
>      @item
>     +IPMI BMC, either and internal or external one
>     +@item
>      Creative SoundBlaster 16 sound card
>      @item
>      ENSONIQ AudioPCI ES1370 sound card
>     --
>     1.8.3.1
> 
>
diff mbox

Patch

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 43c96d1..8fa751a 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -9,6 +9,7 @@  CONFIG_VGA_CIRRUS=y
 CONFIG_VMWARE_VGA=y
 CONFIG_VIRTIO_VGA=y
 CONFIG_VMMOUSE=y
+CONFIG_IPMI=y
 CONFIG_SERIAL=y
 CONFIG_PARALLEL=y
 CONFIG_I8254=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index dfb8095..6767f4f 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -9,6 +9,7 @@  CONFIG_VGA_CIRRUS=y
 CONFIG_VMWARE_VGA=y
 CONFIG_VIRTIO_VGA=y
 CONFIG_VMMOUSE=y
+CONFIG_IPMI=y
 CONFIG_SERIAL=y
 CONFIG_PARALLEL=y
 CONFIG_I8254=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 7e7c241..4a07ed4 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -13,6 +13,7 @@  devices-dirs-$(CONFIG_SOFTMMU) += ide/
 devices-dirs-$(CONFIG_SOFTMMU) += input/
 devices-dirs-$(CONFIG_SOFTMMU) += intc/
 devices-dirs-$(CONFIG_IPACK) += ipack/
+devices-dirs-$(CONFIG_IPMI) += ipmi/
 devices-dirs-$(CONFIG_SOFTMMU) += isa/
 devices-dirs-$(CONFIG_SOFTMMU) += misc/
 devices-dirs-$(CONFIG_SOFTMMU) += net/
diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs
new file mode 100644
index 0000000..65bde11
--- /dev/null
+++ b/hw/ipmi/Makefile.objs
@@ -0,0 +1 @@ 
+common-obj-$(CONFIG_IPMI) += ipmi.o
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
new file mode 100644
index 0000000..7d17469
--- /dev/null
+++ b/hw/ipmi/ipmi.c
@@ -0,0 +1,125 @@ 
+/*
+ * QEMU IPMI emulation
+ *
+ * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/ipmi/ipmi.h"
+#include "sysemu/sysemu.h"
+#include "qmp-commands.h"
+#include "qom/object_interfaces.h"
+#include "qapi/visitor.h"
+
+static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
+{
+    switch (op) {
+    case IPMI_RESET_CHASSIS:
+        if (checkonly) {
+            return 0;
+        }
+        qemu_system_reset_request();
+        return 0;
+
+    case IPMI_POWEROFF_CHASSIS:
+        if (checkonly) {
+            return 0;
+        }
+        qemu_system_powerdown_request();
+        return 0;
+
+    case IPMI_SEND_NMI:
+        if (checkonly) {
+            return 0;
+        }
+        qemu_mutex_lock_iothread();
+        qmp_inject_nmi(NULL);
+        qemu_mutex_unlock_iothread();
+        return 0;
+
+    case IPMI_POWERCYCLE_CHASSIS:
+    case IPMI_PULSE_DIAG_IRQ:
+    case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
+    case IPMI_POWERON_CHASSIS:
+    default:
+        return IPMI_CC_COMMAND_NOT_SUPPORTED;
+    }
+}
+
+static void ipmi_interface_class_init(ObjectClass *class, void *data)
+{
+    IPMIInterfaceClass *ik = IPMI_INTERFACE_CLASS(class);
+
+    ik->do_hw_op = ipmi_do_hw_op;
+}
+
+static TypeInfo ipmi_interface_type_info = {
+    .name = TYPE_IPMI_INTERFACE,
+    .parent = TYPE_INTERFACE,
+    .class_size = sizeof(IPMIInterfaceClass),
+    .class_init = ipmi_interface_class_init,
+};
+
+static void isa_ipmi_bmc_check(Object *obj, const char *name,
+                               Object *val, Error **errp)
+{
+    IPMIBmc *bmc = IPMI_BMC(val);
+
+    if (bmc->intf)
+        error_setg(errp, "BMC object is already in use");
+}
+
+void ipmi_bmc_find_and_link(Object *obj, Object **bmc)
+{
+    object_property_add_link(obj, "bmc", TYPE_IPMI_BMC, bmc,
+                             isa_ipmi_bmc_check,
+                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
+                             &error_abort);
+}
+
+static Property ipmi_bmc_properties[] = {
+    DEFINE_PROP_UINT8("slave_addr",  IPMIBmc, slave_addr, 0x20),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void bmc_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->props = ipmi_bmc_properties;
+}
+
+static TypeInfo ipmi_bmc_type_info = {
+    .name = TYPE_IPMI_BMC,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(IPMIBmc),
+    .abstract = true,
+    .class_size = sizeof(IPMIBmcClass),
+    .class_init = bmc_class_init,
+};
+
+static void ipmi_register_types(void)
+{
+    type_register_static(&ipmi_interface_type_info);
+    type_register_static(&ipmi_bmc_type_info);
+}
+
+type_init(ipmi_register_types)
diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
new file mode 100644
index 0000000..e4f7738
--- /dev/null
+++ b/include/hw/ipmi/ipmi.h
@@ -0,0 +1,178 @@ 
+/*
+ * IPMI base class
+ *
+ * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_IPMI_H
+#define HW_IPMI_H
+
+#include "exec/memory.h"
+#include "qemu-common.h"
+#include "hw/qdev.h"
+
+#define MAX_IPMI_MSG_SIZE 300
+
+enum ipmi_op {
+    IPMI_RESET_CHASSIS,
+    IPMI_POWEROFF_CHASSIS,
+    IPMI_POWERON_CHASSIS,
+    IPMI_POWERCYCLE_CHASSIS,
+    IPMI_PULSE_DIAG_IRQ,
+    IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP,
+    IPMI_SEND_NMI
+};
+
+#define IPMI_CC_INVALID_CMD                              0xc1
+#define IPMI_CC_COMMAND_INVALID_FOR_LUN                  0xc2
+#define IPMI_CC_TIMEOUT                                  0xc3
+#define IPMI_CC_OUT_OF_SPACE                             0xc4
+#define IPMI_CC_INVALID_RESERVATION                      0xc5
+#define IPMI_CC_REQUEST_DATA_TRUNCATED                   0xc6
+#define IPMI_CC_REQUEST_DATA_LENGTH_INVALID              0xc7
+#define IPMI_CC_PARM_OUT_OF_RANGE                        0xc9
+#define IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES              0xca
+#define IPMI_CC_REQ_ENTRY_NOT_PRESENT                    0xcb
+#define IPMI_CC_INVALID_DATA_FIELD                       0xcc
+#define IPMI_CC_BMC_INIT_IN_PROGRESS                     0xd2
+#define IPMI_CC_COMMAND_NOT_SUPPORTED                    0xd5
+
+#define IPMI_NETFN_APP                0x06
+
+#define IPMI_DEBUG 1
+
+/* Specified in the SMBIOS spec. */
+#define IPMI_SMBIOS_KCS         0x01
+#define IPMI_SMBIOS_SMIC        0x02
+#define IPMI_SMBIOS_BT          0x03
+#define IPMI_SMBIOS_SSIF        0x04
+
+/* IPMI Interface types (KCS, SMIC, BT) are prefixed with this */
+#define TYPE_IPMI_INTERFACE_PREFIX "ipmi-interface-"
+
+/*
+ * An IPMI Interface, the interface for talking between the target
+ * and the BMC.
+ */
+#define TYPE_IPMI_INTERFACE "ipmi-interface"
+#define IPMI_INTERFACE(obj) \
+     INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE)
+#define IPMI_INTERFACE_CLASS(class) \
+     OBJECT_CLASS_CHECK(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
+#define IPMI_INTERFACE_GET_CLASS(class) \
+     OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE)
+
+typedef struct IPMIInterface {
+    Object parent;
+} IPMIInterface;
+
+typedef struct IPMIInterfaceClass {
+    InterfaceClass parent;
+
+    void (*init)(struct IPMIInterface *s, Error **errp);
+
+    /*
+     * Perform various operations on the hardware.  If checkonly is
+     * true, it will return if the operation can be performed, but it
+     * will not do the operation.
+     */
+    int (*do_hw_op)(struct IPMIInterface *s, enum ipmi_op op, int checkonly);
+
+    /*
+     * Enable/disable irqs on the interface when the BMC requests this.
+     */
+    void (*set_irq_enable)(struct IPMIInterface *s, int val);
+
+    /*
+     * Handle an event that occurred on the interface, generally the.
+     * target writing to a register.
+     */
+    void (*handle_if_event)(struct IPMIInterface *s);
+
+    /*
+     * The interfaces use this to perform certain ops
+     */
+    void (*set_atn)(struct IPMIInterface *s, int val, int irq);
+
+    /*
+     * Got an IPMI warm/cold reset.
+     */
+    void (*reset)(struct IPMIInterface *s, bool is_cold);
+
+    /*
+     * Handle a response from the bmc.
+     */
+    void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id,
+                       unsigned char *rsp, unsigned int rsp_len);
+
+    /*
+     * Set by the owner to hold the backend data for the interface.
+     */
+    void *(*get_backend_data)(struct IPMIInterface *s);
+} IPMIInterfaceClass;
+
+/*
+ * Define a BMC simulator (or perhaps a connection to a real BMC)
+ */
+#define TYPE_IPMI_BMC "ipmi-bmc"
+#define IPMI_BMC(obj) \
+     OBJECT_CHECK(IPMIBmc, (obj), TYPE_IPMI_BMC)
+#define IPMI_BMC_CLASS(obj_class) \
+     OBJECT_CLASS_CHECK(IPMIBmcClass, (obj_class), TYPE_IPMI_BMC)
+#define IPMI_BMC_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(IPMIBmcClass, (obj), TYPE_IPMI_BMC)
+
+typedef struct IPMIBmc {
+    DeviceState parent;
+
+    uint8_t slave_addr;
+
+    IPMIInterface *intf;
+} IPMIBmc;
+
+typedef struct IPMIBmcClass {
+    DeviceClass parent;
+
+    /* Called when the system resets to report to the bmc. */
+    void (*handle_reset)(struct IPMIBmc *s);
+
+    /*
+     * Handle a command to the bmc.
+     */
+    void (*handle_command)(struct IPMIBmc *s,
+                           uint8_t *cmd, unsigned int cmd_len,
+                           unsigned int max_cmd_len,
+                           uint8_t msg_id);
+} IPMIBmcClass;
+
+/*
+ * Add a link property to obj that points to a BMC.
+ */
+void ipmi_bmc_find_and_link(Object *obj, Object **bmc);
+
+#ifdef IPMI_DEBUG
+#define ipmi_debug(fs, ...) \
+    fprintf(stderr, "IPMI (%s): " fs, __func__, ##__VA_ARGS__)
+#else
+#define ipmi_debug(fs, ...)
+#endif
+
+#endif
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 460ab71..3c82d30 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -195,6 +195,8 @@  PCI and ISA network adapters
 @item
 Serial ports
 @item
+IPMI BMC, either and internal or external one
+@item
 Creative SoundBlaster 16 sound card
 @item
 ENSONIQ AudioPCI ES1370 sound card