Message ID | 20210909230620.511815-5-wuhaotsh@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Handing IPMI for emulating BMC | expand |
On Thu, Sep 09, 2021 at 04:06:16PM -0700, Hao Wu wrote: > This patch refactors the IPMI interface so that it can be used by both > the BMC side and core-side simulation. > > Detail changes: > (1) rename handle_rsp -> handle_msg so the name fits both BMC side and > Core side. > (2) Add a new class IPMICore. This class represents a simulator/external > connection for both BMC and Core side emulation. The old IPMIBmc is > a sub-class of IPMICore. > (3) Change all ibe->parent.intf in hw/ipmi/ipmi_bmc_*.c to use type > cast to IPMICore. Directly accessing parent QOM is against QEMU > guide and by using type casting the code can fit both core side and > BMC side emulation. I think I'm ok with this. It fixes some fundamental issues (maybe that should be separate patches, but I think it's ok here). I was kind of against this at first, I was thinking a completely separate code for the BMC-side hardware emulation. But I can see that so much code would be duplicated that it would be silly. It would be better if there was an ipmi_bmc.[ch] that had the BMC-specific things, split out from the ipmi.[ch] code. I'm not 100% sure how important that is, but it would be less confusing. Do you agree? A couple of comments inline... -corey > > Signed-off-by: Hao Wu <wuhaotsh@google.com> > --- > hw/ipmi/ipmi.c | 15 +++++++++++--- > hw/ipmi/ipmi_bmc_extern.c | 37 +++++++++++++++++++++-------------- > hw/ipmi/ipmi_bmc_sim.c | 41 ++++++++++++++++++++++++++------------- > hw/ipmi/ipmi_bt.c | 2 +- > hw/ipmi/ipmi_kcs.c | 2 +- > hw/ipmi/isa_ipmi_bt.c | 4 +++- > hw/ipmi/isa_ipmi_kcs.c | 4 +++- > hw/ipmi/pci_ipmi_bt.c | 4 +++- > hw/ipmi/pci_ipmi_kcs.c | 4 +++- > hw/ipmi/smbus_ipmi.c | 6 ++++-- > include/hw/ipmi/ipmi.h | 40 ++++++++++++++++++++++++++++++-------- > 11 files changed, 111 insertions(+), 48 deletions(-) > > diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c > index 8d35c9fdd6..7da1b36fab 100644 > --- a/hw/ipmi/ipmi.c > +++ b/hw/ipmi/ipmi.c > @@ -92,13 +92,21 @@ static TypeInfo ipmi_interface_type_info = { > .class_init = ipmi_interface_class_init, > }; > > +static TypeInfo ipmi_core_type_info = { > + .name = TYPE_IPMI_CORE, > + .parent = TYPE_DEVICE, > + .instance_size = sizeof(IPMICore), > + .abstract = true, > +}; > + > static void isa_ipmi_bmc_check(const Object *obj, const char *name, > Object *val, Error **errp) > { > - IPMIBmc *bmc = IPMI_BMC(val); > + IPMICore *ic = IPMI_CORE(val); > > - if (bmc->intf) > + if (ic->intf) { > error_setg(errp, "BMC object is already in use"); > + } > } > > void ipmi_bmc_find_and_link(Object *obj, Object **bmc) > @@ -122,7 +130,7 @@ static void bmc_class_init(ObjectClass *oc, void *data) > > static TypeInfo ipmi_bmc_type_info = { > .name = TYPE_IPMI_BMC, > - .parent = TYPE_DEVICE, > + .parent = TYPE_IPMI_CORE, > .instance_size = sizeof(IPMIBmc), > .abstract = true, > .class_size = sizeof(IPMIBmcClass), > @@ -132,6 +140,7 @@ static TypeInfo ipmi_bmc_type_info = { > static void ipmi_register_types(void) > { > type_register_static(&ipmi_interface_type_info); > + type_register_static(&ipmi_core_type_info); > type_register_static(&ipmi_bmc_type_info); > } > > diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c > index acf2bab35f..a0c3a40e7c 100644 > --- a/hw/ipmi/ipmi_bmc_extern.c > +++ b/hw/ipmi/ipmi_bmc_extern.c > @@ -147,8 +147,9 @@ static void continue_send(IPMIBmcExtern *ibe) > > static void extern_timeout(void *opaque) > { > + IPMICore *ic = opaque; > IPMIBmcExtern *ibe = opaque; Shouldn't the above be a cast from ic? > - IPMIInterface *s = ibe->parent.intf; > + IPMIInterface *s = ic->intf; > > if (ibe->connected) { > if (ibe->waiting_rsp && (ibe->outlen == 0)) { > @@ -158,7 +159,7 @@ static void extern_timeout(void *opaque) > ibe->inbuf[1] = ibe->outbuf[1] | 0x04; > ibe->inbuf[2] = ibe->outbuf[2]; > ibe->inbuf[3] = IPMI_CC_TIMEOUT; > - k->handle_rsp(s, ibe->outbuf[0], ibe->inbuf + 1, 3); > + k->handle_msg(s, ibe->outbuf[0], ibe->inbuf + 1, 3); > } else { > continue_send(ibe); > } > @@ -186,8 +187,9 @@ static void ipmi_bmc_extern_handle_command(IPMIBmc *b, > unsigned int max_cmd_len, > uint8_t msg_id) > { > + IPMICore *ic = IPMI_CORE(b); > IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(b); > - IPMIInterface *s = ibe->parent.intf; > + IPMIInterface *s = ic->intf; > uint8_t err = 0, csum; > unsigned int i; > > @@ -213,7 +215,7 @@ static void ipmi_bmc_extern_handle_command(IPMIBmc *b, > rsp[1] = cmd[1]; > rsp[2] = err; > ibe->waiting_rsp = false; > - k->handle_rsp(s, msg_id, rsp, 3); > + k->handle_msg(s, msg_id, rsp, 3); > goto out; > } > > @@ -236,7 +238,8 @@ static void ipmi_bmc_extern_handle_command(IPMIBmc *b, > > static void handle_hw_op(IPMIBmcExtern *ibe, unsigned char hw_op) > { > - IPMIInterface *s = ibe->parent.intf; > + IPMICore *ic = IPMI_CORE(ibe); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > switch (hw_op) { > @@ -284,7 +287,9 @@ static void handle_hw_op(IPMIBmcExtern *ibe, unsigned char hw_op) > > static void handle_msg(IPMIBmcExtern *ibe) > { > - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(ibe->parent.intf); > + IPMICore *ic = IPMI_CORE(ibe); > + IPMIInterface *s = ic->intf; > + IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > if (ibe->in_escape) { > ipmi_debug("msg escape not ended\n"); > @@ -306,7 +311,7 @@ static void handle_msg(IPMIBmcExtern *ibe) > > timer_del(ibe->extern_timer); > ibe->waiting_rsp = false; > - k->handle_rsp(ibe->parent.intf, ibe->inbuf[0], ibe->inbuf + 1, ibe->inpos - 1); > + k->handle_msg(s, ibe->inbuf[0], ibe->inbuf + 1, ibe->inpos - 1); > } > > static int can_receive(void *opaque) > @@ -382,8 +387,9 @@ static void receive(void *opaque, const uint8_t *buf, int size) > > static void chr_event(void *opaque, QEMUChrEvent event) > { > + IPMICore *ic = opaque; > IPMIBmcExtern *ibe = opaque; Shouldn't the above be a cast from ic? > - IPMIInterface *s = ibe->parent.intf; > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > unsigned char v; > > @@ -398,17 +404,17 @@ static void chr_event(void *opaque, QEMUChrEvent event) > ibe->outlen++; > addchar(ibe, VM_CMD_CAPABILITIES); > v = VM_CAPABILITIES_IRQ | VM_CAPABILITIES_ATTN; > - if (k->do_hw_op(ibe->parent.intf, IPMI_POWEROFF_CHASSIS, 1) == 0) { > + if (k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1) == 0) { > v |= VM_CAPABILITIES_POWER; > } > - if (k->do_hw_op(ibe->parent.intf, IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 1) > + if (k->do_hw_op(s, IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 1) > == 0) { > v |= VM_CAPABILITIES_GRACEFUL_SHUTDOWN; > } > - if (k->do_hw_op(ibe->parent.intf, IPMI_RESET_CHASSIS, 1) == 0) { > + if (k->do_hw_op(s, IPMI_RESET_CHASSIS, 1) == 0) { > v |= VM_CAPABILITIES_RESET; > } > - if (k->do_hw_op(ibe->parent.intf, IPMI_SEND_NMI, 1) == 0) { > + if (k->do_hw_op(s, IPMI_SEND_NMI, 1) == 0) { > v |= VM_CAPABILITIES_NMI; > } > addchar(ibe, v); > @@ -433,7 +439,7 @@ static void chr_event(void *opaque, QEMUChrEvent event) > ibe->inbuf[1] = ibe->outbuf[1] | 0x04; > ibe->inbuf[2] = ibe->outbuf[2]; > ibe->inbuf[3] = IPMI_CC_BMC_INIT_IN_PROGRESS; > - k->handle_rsp(s, ibe->outbuf[0], ibe->inbuf + 1, 3); > + k->handle_msg(s, ibe->outbuf[0], ibe->inbuf + 1, 3); > } > break; > > @@ -475,14 +481,15 @@ static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id) > * error on the interface if a response was being waited for. > */ > if (ibe->waiting_rsp) { > - IPMIInterface *ii = ibe->parent.intf; > + IPMICore *ic = opaque; > + IPMIInterface *ii = ic->intf; > IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); > > ibe->waiting_rsp = false; > ibe->inbuf[1] = ibe->outbuf[1] | 0x04; > ibe->inbuf[2] = ibe->outbuf[2]; > ibe->inbuf[3] = IPMI_CC_BMC_INIT_IN_PROGRESS; > - iic->handle_rsp(ii, ibe->outbuf[0], ibe->inbuf + 1, 3); > + iic->handle_msg(ii, ibe->outbuf[0], ibe->inbuf + 1, 3); > } > return 0; > } > diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c > index 905e091094..7cc4a22456 100644 > --- a/hw/ipmi/ipmi_bmc_sim.c > +++ b/hw/ipmi/ipmi_bmc_sim.c > @@ -451,7 +451,8 @@ static int attn_irq_enabled(IPMIBmcSim *ibs) > void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log) > { > IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b); > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) { > @@ -475,7 +476,8 @@ void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log) > static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert, > uint8_t evd1, uint8_t evd2, uint8_t evd3) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > uint8_t evt[16]; > IPMISensor *sens = ibs->sensors + sens_num; > @@ -644,7 +646,8 @@ static void ipmi_sim_handle_command(IPMIBmc *b, > uint8_t msg_id) > { > IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b); > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > const IPMICmdHandler *hdl; > RspBuffer rsp = RSP_BUFFER_INITIALIZER; > @@ -690,14 +693,15 @@ static void ipmi_sim_handle_command(IPMIBmc *b, > hdl->cmd_handler(ibs, cmd, cmd_len, &rsp); > > out: > - k->handle_rsp(s, msg_id, rsp.buffer, rsp.len); > + k->handle_msg(s, msg_id, rsp.buffer, rsp.len); > > next_timeout(ibs); > } > > static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > if (!ibs->watchdog_running) { > @@ -788,7 +792,8 @@ static void chassis_control(IPMIBmcSim *ibs, > uint8_t *cmd, unsigned int cmd_len, > RspBuffer *rsp) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > switch (cmd[2] & 0xf) { > @@ -845,7 +850,8 @@ static void get_device_id(IPMIBmcSim *ibs, > > static void set_global_enables(IPMIBmcSim *ibs, uint8_t val) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > bool irqs_on; > > @@ -861,7 +867,8 @@ static void cold_reset(IPMIBmcSim *ibs, > uint8_t *cmd, unsigned int cmd_len, > RspBuffer *rsp) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > /* Disable all interrupts */ > @@ -876,7 +883,8 @@ static void warm_reset(IPMIBmcSim *ibs, > uint8_t *cmd, unsigned int cmd_len, > RspBuffer *rsp) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > if (k->reset) { > @@ -939,7 +947,8 @@ static void clr_msg_flags(IPMIBmcSim *ibs, > uint8_t *cmd, unsigned int cmd_len, > RspBuffer *rsp) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > ibs->msg_flags &= ~cmd[2]; > @@ -957,7 +966,8 @@ static void read_evt_msg_buf(IPMIBmcSim *ibs, > uint8_t *cmd, unsigned int cmd_len, > RspBuffer *rsp) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > unsigned int i; > > @@ -989,7 +999,8 @@ static void get_msg(IPMIBmcSim *ibs, > g_free(msg); > > if (QTAILQ_EMPTY(&ibs->rcvbufs)) { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > > ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE; > @@ -1014,7 +1025,8 @@ static void send_msg(IPMIBmcSim *ibs, > uint8_t *cmd, unsigned int cmd_len, > RspBuffer *rsp) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > IPMIRcvBufEntry *msg; > uint8_t *buf; > @@ -1130,7 +1142,8 @@ static void set_watchdog_timer(IPMIBmcSim *ibs, > uint8_t *cmd, unsigned int cmd_len, > RspBuffer *rsp) > { > - IPMIInterface *s = ibs->parent.intf; > + IPMICore *ic = IPMI_CORE(ibs); > + IPMIInterface *s = ic->intf; > IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); > unsigned int val; > > diff --git a/hw/ipmi/ipmi_bt.c b/hw/ipmi/ipmi_bt.c > index 22f94fb98d..f76c369e4a 100644 > --- a/hw/ipmi/ipmi_bt.c > +++ b/hw/ipmi/ipmi_bt.c > @@ -430,7 +430,7 @@ void ipmi_bt_class_init(IPMIInterfaceClass *iic) > { > iic->init = ipmi_bt_init; > iic->set_atn = ipmi_bt_set_atn; > - iic->handle_rsp = ipmi_bt_handle_rsp; > + iic->handle_msg = ipmi_bt_handle_rsp; > iic->handle_if_event = ipmi_bt_handle_event; > iic->set_irq_enable = ipmi_bt_set_irq_enable; > iic->reset = ipmi_bt_handle_reset; > diff --git a/hw/ipmi/ipmi_kcs.c b/hw/ipmi/ipmi_kcs.c > index a77612946a..e0f870e13a 100644 > --- a/hw/ipmi/ipmi_kcs.c > +++ b/hw/ipmi/ipmi_kcs.c > @@ -417,7 +417,7 @@ void ipmi_kcs_class_init(IPMIInterfaceClass *iic) > { > iic->init = ipmi_kcs_init; > iic->set_atn = ipmi_kcs_set_atn; > - iic->handle_rsp = ipmi_kcs_handle_rsp; > + iic->handle_msg = ipmi_kcs_handle_rsp; > iic->handle_if_event = ipmi_kcs_handle_event; > iic->set_irq_enable = ipmi_kcs_set_irq_enable; > } > diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c > index 02625eb94e..0f52fc4262 100644 > --- a/hw/ipmi/isa_ipmi_bt.c > +++ b/hw/ipmi/isa_ipmi_bt.c > @@ -74,6 +74,7 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp) > ISAIPMIBTDevice *iib = ISA_IPMI_BT(dev); > IPMIInterface *ii = IPMI_INTERFACE(dev); > IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); > + IPMICore *ic; > > if (!iib->bt.bmc) { > error_setg(errp, "IPMI device requires a bmc attribute to be set"); > @@ -82,7 +83,8 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp) > > iib->uuid = ipmi_next_uuid(); > > - iib->bt.bmc->intf = ii; > + ic = IPMI_CORE(iib->bt.bmc); > + ic->intf = ii; > iib->bt.opaque = iib; > > iic->init(ii, 0, &err); > diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c > index 3b23ad08b3..60cab90a21 100644 > --- a/hw/ipmi/isa_ipmi_kcs.c > +++ b/hw/ipmi/isa_ipmi_kcs.c > @@ -73,6 +73,7 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp) > ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(dev); > IPMIInterface *ii = IPMI_INTERFACE(dev); > IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); > + IPMICore *ic; > > if (!iik->kcs.bmc) { > error_setg(errp, "IPMI device requires a bmc attribute to be set"); > @@ -81,7 +82,8 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp) > > iik->uuid = ipmi_next_uuid(); > > - iik->kcs.bmc->intf = ii; > + ic = IPMI_CORE(iik->kcs.bmc); > + ic->intf = ii; > iik->kcs.opaque = iik; > > iic->init(ii, 0, &err); > diff --git a/hw/ipmi/pci_ipmi_bt.c b/hw/ipmi/pci_ipmi_bt.c > index b6e52730d3..751c15a31f 100644 > --- a/hw/ipmi/pci_ipmi_bt.c > +++ b/hw/ipmi/pci_ipmi_bt.c > @@ -58,6 +58,7 @@ static void pci_ipmi_bt_realize(PCIDevice *pd, Error **errp) > PCIIPMIBTDevice *pik = PCI_IPMI_BT(pd); > IPMIInterface *ii = IPMI_INTERFACE(pd); > IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); > + IPMICore *ic; > > if (!pik->bt.bmc) { > error_setg(errp, "IPMI device requires a bmc attribute to be set"); > @@ -66,7 +67,8 @@ static void pci_ipmi_bt_realize(PCIDevice *pd, Error **errp) > > pik->uuid = ipmi_next_uuid(); > > - pik->bt.bmc->intf = ii; > + ic = IPMI_CORE(pik->bt.bmc); > + ic->intf = ii; > pik->bt.opaque = pik; > > pci_config_set_prog_interface(pd->config, 0x02); /* BT */ > diff --git a/hw/ipmi/pci_ipmi_kcs.c b/hw/ipmi/pci_ipmi_kcs.c > index de13418862..44a645723c 100644 > --- a/hw/ipmi/pci_ipmi_kcs.c > +++ b/hw/ipmi/pci_ipmi_kcs.c > @@ -58,6 +58,7 @@ static void pci_ipmi_kcs_realize(PCIDevice *pd, Error **errp) > PCIIPMIKCSDevice *pik = PCI_IPMI_KCS(pd); > IPMIInterface *ii = IPMI_INTERFACE(pd); > IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); > + IPMICore *ic; > > if (!pik->kcs.bmc) { > error_setg(errp, "IPMI device requires a bmc attribute to be set"); > @@ -66,7 +67,8 @@ static void pci_ipmi_kcs_realize(PCIDevice *pd, Error **errp) > > pik->uuid = ipmi_next_uuid(); > > - pik->kcs.bmc->intf = ii; > + ic = IPMI_CORE(pik->kcs.bmc); > + ic->intf = ii; > pik->kcs.opaque = pik; > > pci_config_set_prog_interface(pd->config, 0x01); /* KCS */ > diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c > index 1fdf0a66b6..a2383f1212 100644 > --- a/hw/ipmi/smbus_ipmi.c > +++ b/hw/ipmi/smbus_ipmi.c > @@ -315,6 +315,7 @@ static void smbus_ipmi_realize(DeviceState *dev, Error **errp) > { > SMBusIPMIDevice *sid = SMBUS_IPMI(dev); > IPMIInterface *ii = IPMI_INTERFACE(dev); > + IPMICore *ic; > > if (!sid->bmc) { > error_setg(errp, "IPMI device requires a bmc attribute to be set"); > @@ -323,7 +324,8 @@ static void smbus_ipmi_realize(DeviceState *dev, Error **errp) > > sid->uuid = ipmi_next_uuid(); > > - sid->bmc->intf = ii; > + ic = IPMI_CORE(sid->bmc); > + ic->intf = ii; > } > > static void smbus_ipmi_init(Object *obj) > @@ -359,7 +361,7 @@ static void smbus_ipmi_class_init(ObjectClass *oc, void *data) > dc->vmsd = &vmstate_smbus_ipmi; > dc->realize = smbus_ipmi_realize; > iic->set_atn = smbus_ipmi_set_atn; > - iic->handle_rsp = smbus_ipmi_handle_rsp; > + iic->handle_msg = smbus_ipmi_handle_rsp; > iic->handle_if_event = smbus_ipmi_handle_event; > iic->set_irq_enable = smbus_ipmi_set_irq_enable; > iic->get_fwinfo = smbus_ipmi_get_fwinfo; > diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h > index 77a7213ed9..1fa8cd12e5 100644 > --- a/include/hw/ipmi/ipmi.h > +++ b/include/hw/ipmi/ipmi.h > @@ -111,11 +111,11 @@ uint32_t ipmi_next_uuid(void); > #define TYPE_IPMI_INTERFACE "ipmi-interface" > #define IPMI_INTERFACE(obj) \ > INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE) > +typedef struct IPMIInterface IPMIInterface; > typedef struct IPMIInterfaceClass IPMIInterfaceClass; > DECLARE_CLASS_CHECKERS(IPMIInterfaceClass, IPMI_INTERFACE, > TYPE_IPMI_INTERFACE) > - > -typedef struct IPMIInterface IPMIInterface; > +struct IPMICore; > > struct IPMIInterfaceClass { > InterfaceClass parent; > @@ -156,9 +156,9 @@ struct IPMIInterfaceClass { > void (*reset)(struct IPMIInterface *s, bool is_cold); > > /* > - * Handle a response from the bmc. > + * Handle an IPMI message. Could you add a little more explaination here. Like: Handle an IPMI message from the remote side. This is either a message from the BMC being handled by an IPMI interface on the host side, or a message from the host side being handled by a BMC emulator running in this VM. > */ > - void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id, > + void (*handle_msg)(struct IPMIInterface *s, uint8_t msg_id, > unsigned char *rsp, unsigned int rsp_len); > > /* > @@ -166,12 +166,38 @@ struct IPMIInterfaceClass { > */ > void *(*get_backend_data)(struct IPMIInterface *s); > > + /* > + * Set the IPMI core. > + */ > + void (*set_ipmi_handler)(struct IPMIInterface *s, struct IPMICore *ic); > + > /* > * Return the firmware info for a device. > */ > void (*get_fwinfo)(struct IPMIInterface *s, IPMIFwInfo *info); > }; > > +/* > + * Define an IPMI core (Either BMC or Host simulator.) > + */ > +#define TYPE_IPMI_CORE "ipmi-core" > +OBJECT_DECLARE_TYPE(IPMICore, IPMICoreClass, IPMI_CORE) > + > +struct IPMICore { > + DeviceState parent; > + > + IPMIInterface *intf; > +}; > + > +struct IPMICoreClass { > + DeviceClass parent; > + > + /* > + * Handle a hardware command. > + */ > + void (*handle_hw_op)(struct IPMICore *s, uint8_t hw_op, uint8_t operand); > +}; > + > /* > * Define a BMC simulator (or perhaps a connection to a real BMC) > */ > @@ -180,15 +206,13 @@ OBJECT_DECLARE_TYPE(IPMIBmc, IPMIBmcClass, > IPMI_BMC) > > struct IPMIBmc { > - DeviceState parent; > + IPMICore parent; > > uint8_t slave_addr; > - > - IPMIInterface *intf; > }; > > struct IPMIBmcClass { > - DeviceClass parent; > + IPMICoreClass parent; > > /* Called when the system resets to report to the bmc. */ > void (*handle_reset)(struct IPMIBmc *s); > -- > 2.33.0.309.g3052b89438-goog >
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c index 8d35c9fdd6..7da1b36fab 100644 --- a/hw/ipmi/ipmi.c +++ b/hw/ipmi/ipmi.c @@ -92,13 +92,21 @@ static TypeInfo ipmi_interface_type_info = { .class_init = ipmi_interface_class_init, }; +static TypeInfo ipmi_core_type_info = { + .name = TYPE_IPMI_CORE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(IPMICore), + .abstract = true, +}; + static void isa_ipmi_bmc_check(const Object *obj, const char *name, Object *val, Error **errp) { - IPMIBmc *bmc = IPMI_BMC(val); + IPMICore *ic = IPMI_CORE(val); - if (bmc->intf) + if (ic->intf) { error_setg(errp, "BMC object is already in use"); + } } void ipmi_bmc_find_and_link(Object *obj, Object **bmc) @@ -122,7 +130,7 @@ static void bmc_class_init(ObjectClass *oc, void *data) static TypeInfo ipmi_bmc_type_info = { .name = TYPE_IPMI_BMC, - .parent = TYPE_DEVICE, + .parent = TYPE_IPMI_CORE, .instance_size = sizeof(IPMIBmc), .abstract = true, .class_size = sizeof(IPMIBmcClass), @@ -132,6 +140,7 @@ static TypeInfo ipmi_bmc_type_info = { static void ipmi_register_types(void) { type_register_static(&ipmi_interface_type_info); + type_register_static(&ipmi_core_type_info); type_register_static(&ipmi_bmc_type_info); } diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c index acf2bab35f..a0c3a40e7c 100644 --- a/hw/ipmi/ipmi_bmc_extern.c +++ b/hw/ipmi/ipmi_bmc_extern.c @@ -147,8 +147,9 @@ static void continue_send(IPMIBmcExtern *ibe) static void extern_timeout(void *opaque) { + IPMICore *ic = opaque; IPMIBmcExtern *ibe = opaque; - IPMIInterface *s = ibe->parent.intf; + IPMIInterface *s = ic->intf; if (ibe->connected) { if (ibe->waiting_rsp && (ibe->outlen == 0)) { @@ -158,7 +159,7 @@ static void extern_timeout(void *opaque) ibe->inbuf[1] = ibe->outbuf[1] | 0x04; ibe->inbuf[2] = ibe->outbuf[2]; ibe->inbuf[3] = IPMI_CC_TIMEOUT; - k->handle_rsp(s, ibe->outbuf[0], ibe->inbuf + 1, 3); + k->handle_msg(s, ibe->outbuf[0], ibe->inbuf + 1, 3); } else { continue_send(ibe); } @@ -186,8 +187,9 @@ static void ipmi_bmc_extern_handle_command(IPMIBmc *b, unsigned int max_cmd_len, uint8_t msg_id) { + IPMICore *ic = IPMI_CORE(b); IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(b); - IPMIInterface *s = ibe->parent.intf; + IPMIInterface *s = ic->intf; uint8_t err = 0, csum; unsigned int i; @@ -213,7 +215,7 @@ static void ipmi_bmc_extern_handle_command(IPMIBmc *b, rsp[1] = cmd[1]; rsp[2] = err; ibe->waiting_rsp = false; - k->handle_rsp(s, msg_id, rsp, 3); + k->handle_msg(s, msg_id, rsp, 3); goto out; } @@ -236,7 +238,8 @@ static void ipmi_bmc_extern_handle_command(IPMIBmc *b, static void handle_hw_op(IPMIBmcExtern *ibe, unsigned char hw_op) { - IPMIInterface *s = ibe->parent.intf; + IPMICore *ic = IPMI_CORE(ibe); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); switch (hw_op) { @@ -284,7 +287,9 @@ static void handle_hw_op(IPMIBmcExtern *ibe, unsigned char hw_op) static void handle_msg(IPMIBmcExtern *ibe) { - IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(ibe->parent.intf); + IPMICore *ic = IPMI_CORE(ibe); + IPMIInterface *s = ic->intf; + IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); if (ibe->in_escape) { ipmi_debug("msg escape not ended\n"); @@ -306,7 +311,7 @@ static void handle_msg(IPMIBmcExtern *ibe) timer_del(ibe->extern_timer); ibe->waiting_rsp = false; - k->handle_rsp(ibe->parent.intf, ibe->inbuf[0], ibe->inbuf + 1, ibe->inpos - 1); + k->handle_msg(s, ibe->inbuf[0], ibe->inbuf + 1, ibe->inpos - 1); } static int can_receive(void *opaque) @@ -382,8 +387,9 @@ static void receive(void *opaque, const uint8_t *buf, int size) static void chr_event(void *opaque, QEMUChrEvent event) { + IPMICore *ic = opaque; IPMIBmcExtern *ibe = opaque; - IPMIInterface *s = ibe->parent.intf; + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); unsigned char v; @@ -398,17 +404,17 @@ static void chr_event(void *opaque, QEMUChrEvent event) ibe->outlen++; addchar(ibe, VM_CMD_CAPABILITIES); v = VM_CAPABILITIES_IRQ | VM_CAPABILITIES_ATTN; - if (k->do_hw_op(ibe->parent.intf, IPMI_POWEROFF_CHASSIS, 1) == 0) { + if (k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 1) == 0) { v |= VM_CAPABILITIES_POWER; } - if (k->do_hw_op(ibe->parent.intf, IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 1) + if (k->do_hw_op(s, IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 1) == 0) { v |= VM_CAPABILITIES_GRACEFUL_SHUTDOWN; } - if (k->do_hw_op(ibe->parent.intf, IPMI_RESET_CHASSIS, 1) == 0) { + if (k->do_hw_op(s, IPMI_RESET_CHASSIS, 1) == 0) { v |= VM_CAPABILITIES_RESET; } - if (k->do_hw_op(ibe->parent.intf, IPMI_SEND_NMI, 1) == 0) { + if (k->do_hw_op(s, IPMI_SEND_NMI, 1) == 0) { v |= VM_CAPABILITIES_NMI; } addchar(ibe, v); @@ -433,7 +439,7 @@ static void chr_event(void *opaque, QEMUChrEvent event) ibe->inbuf[1] = ibe->outbuf[1] | 0x04; ibe->inbuf[2] = ibe->outbuf[2]; ibe->inbuf[3] = IPMI_CC_BMC_INIT_IN_PROGRESS; - k->handle_rsp(s, ibe->outbuf[0], ibe->inbuf + 1, 3); + k->handle_msg(s, ibe->outbuf[0], ibe->inbuf + 1, 3); } break; @@ -475,14 +481,15 @@ static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id) * error on the interface if a response was being waited for. */ if (ibe->waiting_rsp) { - IPMIInterface *ii = ibe->parent.intf; + IPMICore *ic = opaque; + IPMIInterface *ii = ic->intf; IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); ibe->waiting_rsp = false; ibe->inbuf[1] = ibe->outbuf[1] | 0x04; ibe->inbuf[2] = ibe->outbuf[2]; ibe->inbuf[3] = IPMI_CC_BMC_INIT_IN_PROGRESS; - iic->handle_rsp(ii, ibe->outbuf[0], ibe->inbuf + 1, 3); + iic->handle_msg(ii, ibe->outbuf[0], ibe->inbuf + 1, 3); } return 0; } diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c index 905e091094..7cc4a22456 100644 --- a/hw/ipmi/ipmi_bmc_sim.c +++ b/hw/ipmi/ipmi_bmc_sim.c @@ -451,7 +451,8 @@ static int attn_irq_enabled(IPMIBmcSim *ibs) void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log) { IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b); - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) { @@ -475,7 +476,8 @@ void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log) static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t deassert, uint8_t evd1, uint8_t evd2, uint8_t evd3) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); uint8_t evt[16]; IPMISensor *sens = ibs->sensors + sens_num; @@ -644,7 +646,8 @@ static void ipmi_sim_handle_command(IPMIBmc *b, uint8_t msg_id) { IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b); - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); const IPMICmdHandler *hdl; RspBuffer rsp = RSP_BUFFER_INITIALIZER; @@ -690,14 +693,15 @@ static void ipmi_sim_handle_command(IPMIBmc *b, hdl->cmd_handler(ibs, cmd, cmd_len, &rsp); out: - k->handle_rsp(s, msg_id, rsp.buffer, rsp.len); + k->handle_msg(s, msg_id, rsp.buffer, rsp.len); next_timeout(ibs); } static void ipmi_sim_handle_timeout(IPMIBmcSim *ibs) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); if (!ibs->watchdog_running) { @@ -788,7 +792,8 @@ static void chassis_control(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); switch (cmd[2] & 0xf) { @@ -845,7 +850,8 @@ static void get_device_id(IPMIBmcSim *ibs, static void set_global_enables(IPMIBmcSim *ibs, uint8_t val) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); bool irqs_on; @@ -861,7 +867,8 @@ static void cold_reset(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); /* Disable all interrupts */ @@ -876,7 +883,8 @@ static void warm_reset(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); if (k->reset) { @@ -939,7 +947,8 @@ static void clr_msg_flags(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); ibs->msg_flags &= ~cmd[2]; @@ -957,7 +966,8 @@ static void read_evt_msg_buf(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); unsigned int i; @@ -989,7 +999,8 @@ static void get_msg(IPMIBmcSim *ibs, g_free(msg); if (QTAILQ_EMPTY(&ibs->rcvbufs)) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); ibs->msg_flags &= ~IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE; @@ -1014,7 +1025,8 @@ static void send_msg(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); IPMIRcvBufEntry *msg; uint8_t *buf; @@ -1130,7 +1142,8 @@ static void set_watchdog_timer(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, RspBuffer *rsp) { - IPMIInterface *s = ibs->parent.intf; + IPMICore *ic = IPMI_CORE(ibs); + IPMIInterface *s = ic->intf; IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); unsigned int val; diff --git a/hw/ipmi/ipmi_bt.c b/hw/ipmi/ipmi_bt.c index 22f94fb98d..f76c369e4a 100644 --- a/hw/ipmi/ipmi_bt.c +++ b/hw/ipmi/ipmi_bt.c @@ -430,7 +430,7 @@ void ipmi_bt_class_init(IPMIInterfaceClass *iic) { iic->init = ipmi_bt_init; iic->set_atn = ipmi_bt_set_atn; - iic->handle_rsp = ipmi_bt_handle_rsp; + iic->handle_msg = ipmi_bt_handle_rsp; iic->handle_if_event = ipmi_bt_handle_event; iic->set_irq_enable = ipmi_bt_set_irq_enable; iic->reset = ipmi_bt_handle_reset; diff --git a/hw/ipmi/ipmi_kcs.c b/hw/ipmi/ipmi_kcs.c index a77612946a..e0f870e13a 100644 --- a/hw/ipmi/ipmi_kcs.c +++ b/hw/ipmi/ipmi_kcs.c @@ -417,7 +417,7 @@ void ipmi_kcs_class_init(IPMIInterfaceClass *iic) { iic->init = ipmi_kcs_init; iic->set_atn = ipmi_kcs_set_atn; - iic->handle_rsp = ipmi_kcs_handle_rsp; + iic->handle_msg = ipmi_kcs_handle_rsp; iic->handle_if_event = ipmi_kcs_handle_event; iic->set_irq_enable = ipmi_kcs_set_irq_enable; } diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c index 02625eb94e..0f52fc4262 100644 --- a/hw/ipmi/isa_ipmi_bt.c +++ b/hw/ipmi/isa_ipmi_bt.c @@ -74,6 +74,7 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp) ISAIPMIBTDevice *iib = ISA_IPMI_BT(dev); IPMIInterface *ii = IPMI_INTERFACE(dev); IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); + IPMICore *ic; if (!iib->bt.bmc) { error_setg(errp, "IPMI device requires a bmc attribute to be set"); @@ -82,7 +83,8 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp) iib->uuid = ipmi_next_uuid(); - iib->bt.bmc->intf = ii; + ic = IPMI_CORE(iib->bt.bmc); + ic->intf = ii; iib->bt.opaque = iib; iic->init(ii, 0, &err); diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c index 3b23ad08b3..60cab90a21 100644 --- a/hw/ipmi/isa_ipmi_kcs.c +++ b/hw/ipmi/isa_ipmi_kcs.c @@ -73,6 +73,7 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp) ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(dev); IPMIInterface *ii = IPMI_INTERFACE(dev); IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); + IPMICore *ic; if (!iik->kcs.bmc) { error_setg(errp, "IPMI device requires a bmc attribute to be set"); @@ -81,7 +82,8 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp) iik->uuid = ipmi_next_uuid(); - iik->kcs.bmc->intf = ii; + ic = IPMI_CORE(iik->kcs.bmc); + ic->intf = ii; iik->kcs.opaque = iik; iic->init(ii, 0, &err); diff --git a/hw/ipmi/pci_ipmi_bt.c b/hw/ipmi/pci_ipmi_bt.c index b6e52730d3..751c15a31f 100644 --- a/hw/ipmi/pci_ipmi_bt.c +++ b/hw/ipmi/pci_ipmi_bt.c @@ -58,6 +58,7 @@ static void pci_ipmi_bt_realize(PCIDevice *pd, Error **errp) PCIIPMIBTDevice *pik = PCI_IPMI_BT(pd); IPMIInterface *ii = IPMI_INTERFACE(pd); IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); + IPMICore *ic; if (!pik->bt.bmc) { error_setg(errp, "IPMI device requires a bmc attribute to be set"); @@ -66,7 +67,8 @@ static void pci_ipmi_bt_realize(PCIDevice *pd, Error **errp) pik->uuid = ipmi_next_uuid(); - pik->bt.bmc->intf = ii; + ic = IPMI_CORE(pik->bt.bmc); + ic->intf = ii; pik->bt.opaque = pik; pci_config_set_prog_interface(pd->config, 0x02); /* BT */ diff --git a/hw/ipmi/pci_ipmi_kcs.c b/hw/ipmi/pci_ipmi_kcs.c index de13418862..44a645723c 100644 --- a/hw/ipmi/pci_ipmi_kcs.c +++ b/hw/ipmi/pci_ipmi_kcs.c @@ -58,6 +58,7 @@ static void pci_ipmi_kcs_realize(PCIDevice *pd, Error **errp) PCIIPMIKCSDevice *pik = PCI_IPMI_KCS(pd); IPMIInterface *ii = IPMI_INTERFACE(pd); IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); + IPMICore *ic; if (!pik->kcs.bmc) { error_setg(errp, "IPMI device requires a bmc attribute to be set"); @@ -66,7 +67,8 @@ static void pci_ipmi_kcs_realize(PCIDevice *pd, Error **errp) pik->uuid = ipmi_next_uuid(); - pik->kcs.bmc->intf = ii; + ic = IPMI_CORE(pik->kcs.bmc); + ic->intf = ii; pik->kcs.opaque = pik; pci_config_set_prog_interface(pd->config, 0x01); /* KCS */ diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c index 1fdf0a66b6..a2383f1212 100644 --- a/hw/ipmi/smbus_ipmi.c +++ b/hw/ipmi/smbus_ipmi.c @@ -315,6 +315,7 @@ static void smbus_ipmi_realize(DeviceState *dev, Error **errp) { SMBusIPMIDevice *sid = SMBUS_IPMI(dev); IPMIInterface *ii = IPMI_INTERFACE(dev); + IPMICore *ic; if (!sid->bmc) { error_setg(errp, "IPMI device requires a bmc attribute to be set"); @@ -323,7 +324,8 @@ static void smbus_ipmi_realize(DeviceState *dev, Error **errp) sid->uuid = ipmi_next_uuid(); - sid->bmc->intf = ii; + ic = IPMI_CORE(sid->bmc); + ic->intf = ii; } static void smbus_ipmi_init(Object *obj) @@ -359,7 +361,7 @@ static void smbus_ipmi_class_init(ObjectClass *oc, void *data) dc->vmsd = &vmstate_smbus_ipmi; dc->realize = smbus_ipmi_realize; iic->set_atn = smbus_ipmi_set_atn; - iic->handle_rsp = smbus_ipmi_handle_rsp; + iic->handle_msg = smbus_ipmi_handle_rsp; iic->handle_if_event = smbus_ipmi_handle_event; iic->set_irq_enable = smbus_ipmi_set_irq_enable; iic->get_fwinfo = smbus_ipmi_get_fwinfo; diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h index 77a7213ed9..1fa8cd12e5 100644 --- a/include/hw/ipmi/ipmi.h +++ b/include/hw/ipmi/ipmi.h @@ -111,11 +111,11 @@ uint32_t ipmi_next_uuid(void); #define TYPE_IPMI_INTERFACE "ipmi-interface" #define IPMI_INTERFACE(obj) \ INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE) +typedef struct IPMIInterface IPMIInterface; typedef struct IPMIInterfaceClass IPMIInterfaceClass; DECLARE_CLASS_CHECKERS(IPMIInterfaceClass, IPMI_INTERFACE, TYPE_IPMI_INTERFACE) - -typedef struct IPMIInterface IPMIInterface; +struct IPMICore; struct IPMIInterfaceClass { InterfaceClass parent; @@ -156,9 +156,9 @@ struct IPMIInterfaceClass { void (*reset)(struct IPMIInterface *s, bool is_cold); /* - * Handle a response from the bmc. + * Handle an IPMI message. */ - void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id, + void (*handle_msg)(struct IPMIInterface *s, uint8_t msg_id, unsigned char *rsp, unsigned int rsp_len); /* @@ -166,12 +166,38 @@ struct IPMIInterfaceClass { */ void *(*get_backend_data)(struct IPMIInterface *s); + /* + * Set the IPMI core. + */ + void (*set_ipmi_handler)(struct IPMIInterface *s, struct IPMICore *ic); + /* * Return the firmware info for a device. */ void (*get_fwinfo)(struct IPMIInterface *s, IPMIFwInfo *info); }; +/* + * Define an IPMI core (Either BMC or Host simulator.) + */ +#define TYPE_IPMI_CORE "ipmi-core" +OBJECT_DECLARE_TYPE(IPMICore, IPMICoreClass, IPMI_CORE) + +struct IPMICore { + DeviceState parent; + + IPMIInterface *intf; +}; + +struct IPMICoreClass { + DeviceClass parent; + + /* + * Handle a hardware command. + */ + void (*handle_hw_op)(struct IPMICore *s, uint8_t hw_op, uint8_t operand); +}; + /* * Define a BMC simulator (or perhaps a connection to a real BMC) */ @@ -180,15 +206,13 @@ OBJECT_DECLARE_TYPE(IPMIBmc, IPMIBmcClass, IPMI_BMC) struct IPMIBmc { - DeviceState parent; + IPMICore parent; uint8_t slave_addr; - - IPMIInterface *intf; }; struct IPMIBmcClass { - DeviceClass parent; + IPMICoreClass parent; /* Called when the system resets to report to the bmc. */ void (*handle_reset)(struct IPMIBmc *s);
This patch refactors the IPMI interface so that it can be used by both the BMC side and core-side simulation. Detail changes: (1) rename handle_rsp -> handle_msg so the name fits both BMC side and Core side. (2) Add a new class IPMICore. This class represents a simulator/external connection for both BMC and Core side emulation. The old IPMIBmc is a sub-class of IPMICore. (3) Change all ibe->parent.intf in hw/ipmi/ipmi_bmc_*.c to use type cast to IPMICore. Directly accessing parent QOM is against QEMU guide and by using type casting the code can fit both core side and BMC side emulation. Signed-off-by: Hao Wu <wuhaotsh@google.com> --- hw/ipmi/ipmi.c | 15 +++++++++++--- hw/ipmi/ipmi_bmc_extern.c | 37 +++++++++++++++++++++-------------- hw/ipmi/ipmi_bmc_sim.c | 41 ++++++++++++++++++++++++++------------- hw/ipmi/ipmi_bt.c | 2 +- hw/ipmi/ipmi_kcs.c | 2 +- hw/ipmi/isa_ipmi_bt.c | 4 +++- hw/ipmi/isa_ipmi_kcs.c | 4 +++- hw/ipmi/pci_ipmi_bt.c | 4 +++- hw/ipmi/pci_ipmi_kcs.c | 4 +++- hw/ipmi/smbus_ipmi.c | 6 ++++-- include/hw/ipmi/ipmi.h | 40 ++++++++++++++++++++++++++++++-------- 11 files changed, 111 insertions(+), 48 deletions(-)