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, <miny...@acm.org> wrote:

> From: Corey Minyard <cminy...@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 <cminy...@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
>
>

Reply via email to