qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Corey Minyard <minyard@acm.org>
To: Hao Wu <wuhaotsh@google.com>
Cc: peter.maydell@linaro.org, titusr@google.com, venture@google.com,
	hskinnemoen@google.com, qemu-devel@nongnu.org,
	kfting@nuvoton.com, qemu-arm@nongnu.org, Avi.Fishman@nuvoton.com
Subject: Re: [PATCH 7/8] hw/ipmi: Add an IPMI external host device
Date: Thu, 9 Sep 2021 19:53:11 -0500	[thread overview]
Message-ID: <20210910005311.GR545073@minyard.net> (raw)
In-Reply-To: <20210909230620.511815-8-wuhaotsh@google.com>

On Thu, Sep 09, 2021 at 04:06:19PM -0700, Hao Wu wrote:
> The IPMI external host device works for Baseband Management Controller
> (BMC) emulations. It works as a representation of a host class that
> connects to a given BMC.  It can connect to a real host hardware or a
> emulated or simulated host device. In particular it can connect to a
> host QEMU instance with device ipmi-bmc-extern.

This is reasonable, I think.

The terminology here is confusing, though.  I'm not sure exactly what to
do about it.  So we have right now:

  host interfaces - KCS, BT, SSIF
  bmc - either an emulated or extern BMC the host talks to

And what you are proposing is:

  core - anything that supplies IPMI message for processing by
    the code in the VM.  So this is the internal/external BMC
    and the bmc-side of things.
  bmc - either an emulated or extern BMC the host talks to
  bmc-side - Receives messages from a host running ipmi_bmc_extern
  interfaces - KCS, BT, SSIF, and the interface to the bmc-side
    VM.

What I would propose is something like:

  core - anything that supplies IPMI message for processing by
    the code in the VM.  So this is the internal/external BMC
    and the bmc-side of things.
  bmc-host - either an emulated or extern BMC the host talks to
  bmc-client - Receives messages from a host running ipmi_bmc_extern
  interfaces - All IPMI interfaces
  interfaces-host - KCS, BT, SSIF
  interfaces-client - the interface to the bmc-side VM.

I'm not too excited about the name "client", though.  But I think a
class hierarchy like above would be more clear about what things are,
and it's not that different than what you are proposing.

I'm really just thinking out loud, though.

-corey

> 
> For more details of IPMI host device in BMC emulation, see
> docs/specs/ipmi.rst.
> 
> Signed-off-by: Hao Wu <wuhaotsh@google.com>
> ---
>  configs/devices/arm-softmmu/default.mak |   2 +
>  hw/ipmi/Kconfig                         |   5 +
>  hw/ipmi/ipmi_extern.c                   |  18 ++-
>  hw/ipmi/ipmi_host_extern.c              | 170 ++++++++++++++++++++++++
>  hw/ipmi/meson.build                     |   1 +
>  5 files changed, 194 insertions(+), 2 deletions(-)
>  create mode 100644 hw/ipmi/ipmi_host_extern.c
> 
> diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-softmmu/default.mak
> index 6985a25377..82f0c6f8c3 100644
> --- a/configs/devices/arm-softmmu/default.mak
> +++ b/configs/devices/arm-softmmu/default.mak
> @@ -25,6 +25,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..6722b1fbb0 100644
> --- a/hw/ipmi/Kconfig
> +++ b/hw/ipmi/Kconfig
> @@ -11,6 +11,11 @@ config IPMI_EXTERN
>      default y
>      depends on IPMI
>  
> +config IPMI_HOST
> +    bool
> +    default y
> +    depends on IPMI
> +
>  config ISA_IPMI_KCS
>      bool
>      depends on ISA_BUS
> diff --git a/hw/ipmi/ipmi_extern.c b/hw/ipmi/ipmi_extern.c
> index 97dfed085f..0952dc5992 100644
> --- a/hw/ipmi/ipmi_extern.c
> +++ b/hw/ipmi/ipmi_extern.c
> @@ -145,11 +145,25 @@ void ipmi_extern_handle_command(IPMIExtern *ibe,
>      if (err) {
>          IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
>          unsigned char rsp[3];
> +
>          rsp[0] = cmd[0] | 0x04;
>          rsp[1] = cmd[1];
>          rsp[2] = err;
> -        ibe->waiting_rsp = false;
> -        k->handle_msg(s, msg_id, rsp, 3);
> +
> +        if (ibe->bmc_side) {
> +            /* For BMC Side, send out an error message. */
> +            addchar(ibe, msg_id);
> +            for (i = 0; i < 3; ++i) {
> +                addchar(ibe, rsp[i]);
> +            }
> +            csum = ipmb_checksum(&msg_id, 1, 0);
> +            addchar(ibe, -ipmb_checksum(rsp, 3, csum));
> +            continue_send(ibe);
> +        } else {
> +            /* For Core side, handle an error message. */
> +            ibe->waiting_rsp = false;
> +            k->handle_msg(s, msg_id, rsp, 3);
> +        }
>          goto out;
>      }
>  
> diff --git a/hw/ipmi/ipmi_host_extern.c b/hw/ipmi/ipmi_host_extern.c
> new file mode 100644
> index 0000000000..4530631901
> --- /dev/null
> +++ b/hw/ipmi/ipmi_host_extern.c
> @@ -0,0 +1,170 @@
> +/*
> + * IPMI Host external connection
> + *
> + * Copyright 2021 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.
> + */
> +
> +/*
> + * This is designed to connect to a host QEMU VM that runs ipmi_bmc_extern.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "qemu/module.h"
> +#include "qapi/error.h"
> +#include "chardev/char-fe.h"
> +#include "hw/ipmi/ipmi.h"
> +#include "hw/ipmi/ipmi_extern.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/qdev-properties-system.h"
> +#include "migration/vmstate.h"
> +#include "qom/object.h"
> +
> +#define TYPE_IPMI_HOST_EXTERN "ipmi-host-extern"
> +OBJECT_DECLARE_SIMPLE_TYPE(IPMIHostExtern, IPMI_HOST_EXTERN)
> +
> +typedef struct IPMIHostExtern {
> +    IPMICore parent;
> +
> +    IPMIExtern conn;
> +
> +    IPMIInterface *responder;
> +
> +    uint8_t capability;
> +} IPMIHostExtern;
> +
> +/*
> + * Handle a command (typically IPMI response) from IPMI interface
> + * and send it out to the external host.
> + */
> +static void ipmi_host_extern_handle_command(IPMICore *h, uint8_t *cmd,
> +        unsigned cmd_len, unsigned max_cmd_len, uint8_t msg_id)
> +{
> +    IPMIHostExtern *ihe = IPMI_HOST_EXTERN(h);
> +
> +    ipmi_extern_handle_command(&ihe->conn, cmd, cmd_len, max_cmd_len, msg_id);
> +}
> +
> +/* This function handles a control command from the host. */
> +static void ipmi_host_extern_handle_hw_op(IPMICore *ic, uint8_t cmd,
> +                                          uint8_t operand)
> +{
> +    IPMIHostExtern *ihe = IPMI_HOST_EXTERN(ic);
> +
> +    switch (cmd) {
> +    case VM_CMD_VERSION:
> +        /* The host informs us the protocol version. */
> +        if (unlikely(operand != VM_PROTOCOL_VERSION)) {
> +            ipmi_debug("Host protocol version %u is different from our version"
> +                    " %u\n", operand, VM_PROTOCOL_VERSION);
> +        }
> +        break;
> +
> +    case VM_CMD_RESET:
> +        /* The host tells us a reset has happened. */
> +        break;
> +
> +    case VM_CMD_CAPABILITIES:
> +        /* The host tells us its capability. */
> +        ihe->capability = operand;
> +        break;
> +
> +    default:
> +        /* The host shouldn't send us this command. Just ignore if they do. */
> +        ipmi_debug("Host cmd type %02x is invalid.\n", cmd);
> +        break;
> +    }
> +}
> +
> +static void ipmi_host_extern_realize(DeviceState *dev, Error **errp)
> +{
> +    IPMIHostExtern *ihe = IPMI_HOST_EXTERN(dev);
> +    IPMIInterfaceClass *rk;
> +
> +    if (ihe->responder == NULL) {
> +        error_setg(errp, "IPMI host extern requires responder attribute");
> +        return;
> +    }
> +    rk = IPMI_INTERFACE_GET_CLASS(ihe->responder);
> +    rk->set_ipmi_handler(ihe->responder, IPMI_CORE(ihe));
> +    ihe->conn.core->intf = ihe->responder;
> +
> +    if (!qdev_realize(DEVICE(&ihe->conn), NULL, errp)) {
> +        return;
> +    }
> +}
> +
> +static int ipmi_host_extern_post_migrate(void *opaque, int version_id)
> +{
> +    IPMIHostExtern *ihe = IPMI_HOST_EXTERN(opaque);
> +
> +    return ipmi_extern_post_migrate(&ihe->conn, version_id);
> +}
> +
> +static const VMStateDescription vmstate_ipmi_host_extern = {
> +    .name = TYPE_IPMI_HOST_EXTERN,
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .post_load = ipmi_host_extern_post_migrate,
> +    .fields      = (VMStateField[]) {
> +        VMSTATE_UINT8(capability, IPMIHostExtern),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void ipmi_host_extern_init(Object *obj)
> +{
> +    IPMICore *ic = IPMI_CORE(obj);
> +    IPMIHostExtern *ihe = IPMI_HOST_EXTERN(obj);
> +
> +    object_initialize_child(obj, "extern", &ihe->conn,
> +                            TYPE_IPMI_EXTERN);
> +    ihe->conn.core = ic;
> +    ihe->conn.bmc_side = true;
> +    vmstate_register(NULL, 0, &vmstate_ipmi_host_extern, ihe);
> +}
> +
> +static Property ipmi_host_extern_properties[] = {
> +    DEFINE_PROP_CHR("chardev", IPMIHostExtern, conn.chr),
> +    DEFINE_PROP_LINK("responder", IPMIHostExtern, responder,
> +                     TYPE_IPMI_INTERFACE, IPMIInterface *),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void ipmi_host_extern_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    IPMICoreClass *ck = IPMI_CORE_CLASS(oc);
> +
> +    device_class_set_props(dc, ipmi_host_extern_properties);
> +
> +    ck->handle_command = ipmi_host_extern_handle_command;
> +    ck->handle_hw_op = ipmi_host_extern_handle_hw_op;
> +    dc->hotpluggable = false;
> +    dc->realize = ipmi_host_extern_realize;
> +}
> +
> +static const TypeInfo ipmi_host_extern_type = {
> +    .name          = TYPE_IPMI_HOST_EXTERN,
> +    .parent        = TYPE_IPMI_CORE,
> +    .instance_size = sizeof(IPMIHostExtern),
> +    .instance_init = ipmi_host_extern_init,
> +    .class_init    = ipmi_host_extern_class_init,
> +};
> +
> +static void ipmi_host_extern_register_types(void)
> +{
> +    type_register_static(&ipmi_host_extern_type);
> +}
> +
> +type_init(ipmi_host_extern_register_types)
> diff --git a/hw/ipmi/meson.build b/hw/ipmi/meson.build
> index edd0bf9af9..b1dd4710dc 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_extern.c'))
>  
>  softmmu_ss.add_all(when: 'CONFIG_IPMI', if_true: ipmi_ss)
> -- 
> 2.33.0.309.g3052b89438-goog
> 


  reply	other threads:[~2021-09-10  0:54 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-09 23:06 [PATCH 0/8] Handing IPMI for emulating BMC Hao Wu
2021-09-09 23:06 ` [PATCH 1/8] docs: enable sphinx blockdiag extension Hao Wu
2021-09-09 23:40   ` Corey Minyard
2021-09-09 23:06 ` [PATCH 2/8] docs/specs: IPMI device emulation: main processor Hao Wu
2021-09-09 23:48   ` Corey Minyard
2021-09-09 23:06 ` [PATCH 3/8] docs/specs: IPMI device emulation: BMC Hao Wu
2021-09-09 23:06 ` [PATCH 4/8] hw/ipmi: Refactor IPMI interface Hao Wu
2021-09-10  0:26   ` Corey Minyard
2021-09-09 23:06 ` [PATCH 5/8] hw/ipmi: Take out common from ipmi_bmc_extern.c Hao Wu
2021-09-10  0:27   ` Corey Minyard
2021-09-09 23:06 ` [PATCH 6/8] hw/ipmi: Move handle_command to IPMICoreClass Hao Wu
2021-09-09 23:06 ` [PATCH 7/8] hw/ipmi: Add an IPMI external host device Hao Wu
2021-09-10  0:53   ` Corey Minyard [this message]
2021-09-09 23:06 ` [PATCH 8/8] hw/ipmi: Add a KCS Module for NPCM7XX Hao Wu

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=20210910005311.GR545073@minyard.net \
    --to=minyard@acm.org \
    --cc=Avi.Fishman@nuvoton.com \
    --cc=hskinnemoen@google.com \
    --cc=kfting@nuvoton.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=titusr@google.com \
    --cc=venture@google.com \
    --cc=wuhaotsh@google.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).