diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-07-18 23:59:03 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-07-18 23:59:03 +0100 |
commit | b4421193299c09dfe690ec93c9b4713ed710aa3e (patch) | |
tree | f03617b252ac8cc07daa6a44d66ace74e835561e | |
parent | 939ab64b400b9bec4b59795a87817784093e1acd (diff) | |
parent | e3f7320caa1cc08a9b752e555b79abd6218c7c7a (diff) |
Merge remote-tracking branch 'remotes/cminyard/tags/for-qemu-ipmi-5' into staging
Man page update and new set sensor command
Some minor man page updates for fairly obvious things.
The set sensor command addition has been in the Power group's tree for a
long time and I have neglected to submit it.
-corey
# gpg: Signature made Fri 17 Jul 2020 17:45:32 BST
# gpg: using RSA key FD0D5CE67CE0F59A6688268661F38C90919BFF81
# gpg: Good signature from "Corey Minyard <cminyard@mvista.com>" [unknown]
# gpg: aka "Corey Minyard <minyard@acm.org>" [unknown]
# gpg: aka "Corey Minyard <corey@minyard.net>" [unknown]
# gpg: aka "Corey Minyard <minyard@mvista.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: FD0D 5CE6 7CE0 F59A 6688 2686 61F3 8C90 919B FF81
* remotes/cminyard/tags/for-qemu-ipmi-5:
ipmi: add SET_SENSOR_READING command
ipmi: Fix a man page entry
ipmi: Add man page pieces for the IPMI PCI devices
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/ipmi/ipmi_bmc_sim.c | 223 | ||||
-rw-r--r-- | qemu-options.hx | 11 |
2 files changed, 233 insertions, 1 deletions
diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c index 0b97e04774..f78e92d3d5 100644 --- a/hw/ipmi/ipmi_bmc_sim.c +++ b/hw/ipmi/ipmi_bmc_sim.c @@ -49,6 +49,7 @@ #define IPMI_CMD_GET_SENSOR_READING 0x2d #define IPMI_CMD_SET_SENSOR_TYPE 0x2e #define IPMI_CMD_GET_SENSOR_TYPE 0x2f +#define IPMI_CMD_SET_SENSOR_READING 0x30 /* #define IPMI_NETFN_APP 0x06 In ipmi.h */ @@ -1747,6 +1748,227 @@ static void get_sensor_type(IPMIBmcSim *ibs, rsp_buffer_push(rsp, sens->evt_reading_type_code); } +/* + * bytes parameter + * 1 sensor number + * 2 operation (see below for bits meaning) + * 3 sensor reading + * 4:5 assertion states (optional) + * 6:7 deassertion states (optional) + * 8:10 event data 1,2,3 (optional) + */ +static void set_sensor_reading(IPMIBmcSim *ibs, + uint8_t *cmd, unsigned int cmd_len, + RspBuffer *rsp) +{ + IPMISensor *sens; + uint8_t evd1 = 0; + uint8_t evd2 = 0; + uint8_t evd3 = 0; + uint8_t new_reading = 0; + uint16_t new_assert_states = 0; + uint16_t new_deassert_states = 0; + bool change_reading = false; + bool change_assert = false; + bool change_deassert = false; + enum { + SENSOR_GEN_EVENT_NONE, + SENSOR_GEN_EVENT_DATA, + SENSOR_GEN_EVENT_BMC, + } do_gen_event = SENSOR_GEN_EVENT_NONE; + + if ((cmd[2] >= MAX_SENSORS) || + !IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) { + rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT); + return; + } + + sens = ibs->sensors + cmd[2]; + + /* [1:0] Sensor Reading operation */ + switch ((cmd[3]) & 0x3) { + case 0: /* Do not change */ + break; + case 1: /* write given value to sensor reading byte */ + new_reading = cmd[4]; + if (sens->reading != new_reading) { + change_reading = true; + } + break; + case 2: + case 3: + rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); + return; + } + + /* [3:2] Deassertion bits operation */ + switch ((cmd[3] >> 2) & 0x3) { + case 0: /* Do not change */ + break; + case 1: /* write given value */ + if (cmd_len > 7) { + new_deassert_states = cmd[7]; + change_deassert = true; + } + if (cmd_len > 8) { + new_deassert_states |= (cmd[8] << 8); + } + break; + + case 2: /* mask on */ + if (cmd_len > 7) { + new_deassert_states = (sens->deassert_states | cmd[7]); + change_deassert = true; + } + if (cmd_len > 8) { + new_deassert_states |= (sens->deassert_states | (cmd[8] << 8)); + } + break; + + case 3: /* mask off */ + if (cmd_len > 7) { + new_deassert_states = (sens->deassert_states & cmd[7]); + change_deassert = true; + } + if (cmd_len > 8) { + new_deassert_states |= (sens->deassert_states & (cmd[8] << 8)); + } + break; + } + + if (change_deassert && (new_deassert_states == sens->deassert_states)) { + change_deassert = false; + } + + /* [5:4] Assertion bits operation */ + switch ((cmd[3] >> 4) & 0x3) { + case 0: /* Do not change */ + break; + case 1: /* write given value */ + if (cmd_len > 5) { + new_assert_states = cmd[5]; + change_assert = true; + } + if (cmd_len > 6) { + new_assert_states |= (cmd[6] << 8); + } + break; + + case 2: /* mask on */ + if (cmd_len > 5) { + new_assert_states = (sens->assert_states | cmd[5]); + change_assert = true; + } + if (cmd_len > 6) { + new_assert_states |= (sens->assert_states | (cmd[6] << 8)); + } + break; + + case 3: /* mask off */ + if (cmd_len > 5) { + new_assert_states = (sens->assert_states & cmd[5]); + change_assert = true; + } + if (cmd_len > 6) { + new_assert_states |= (sens->assert_states & (cmd[6] << 8)); + } + break; + } + + if (change_assert && (new_assert_states == sens->assert_states)) { + change_assert = false; + } + + if (cmd_len > 9) { + evd1 = cmd[9]; + } + if (cmd_len > 10) { + evd2 = cmd[10]; + } + if (cmd_len > 11) { + evd3 = cmd[11]; + } + + /* [7:6] Event Data Bytes operation */ + switch ((cmd[3] >> 6) & 0x3) { + case 0: /* + * Don’t use Event Data bytes from this command. BMC will + * generate it's own Event Data bytes based on its sensor + * implementation. + */ + evd1 = evd2 = evd3 = 0x0; + do_gen_event = SENSOR_GEN_EVENT_BMC; + break; + case 1: /* + * Write given values to event data bytes including bits + * [3:0] Event Data 1. + */ + do_gen_event = SENSOR_GEN_EVENT_DATA; + break; + case 2: /* + * Write given values to event data bytes excluding bits + * [3:0] Event Data 1. + */ + evd1 &= 0xf0; + do_gen_event = SENSOR_GEN_EVENT_DATA; + break; + case 3: + rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); + return; + } + + /* + * Event Data Bytes operation and parameter are inconsistent. The + * Specs are not clear on that topic but generating an error seems + * correct. + */ + if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) { + rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD); + return; + } + + /* commit values */ + if (change_reading) { + sens->reading = new_reading; + } + + if (change_assert) { + sens->assert_states = new_assert_states; + } + + if (change_deassert) { + sens->deassert_states = new_deassert_states; + } + + /* TODO: handle threshold sensor */ + if (!IPMI_SENSOR_IS_DISCRETE(sens)) { + return; + } + + switch (do_gen_event) { + case SENSOR_GEN_EVENT_DATA: { + unsigned int bit = evd1 & 0xf; + uint16_t mask = (1 << bit); + + if (sens->assert_states & mask & sens->assert_enable) { + gen_event(ibs, cmd[2], 0, evd1, evd2, evd3); + } + + if (sens->deassert_states & mask & sens->deassert_enable) { + gen_event(ibs, cmd[2], 1, evd1, evd2, evd3); + } + break; + } + case SENSOR_GEN_EVENT_BMC: + /* + * TODO: generate event and event data bytes depending on the + * sensor + */ + break; + case SENSOR_GEN_EVENT_NONE: + break; + } +} static const IPMICmdHandler chassis_cmds[] = { [IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities }, @@ -1768,6 +1990,7 @@ static const IPMICmdHandler sensor_event_cmds[] = { [IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 }, [IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 }, [IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 }, + [IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 }, }; static const IPMINetfn sensor_event_netfn = { .cmd_nums = ARRAY_SIZE(sensor_event_cmds), diff --git a/qemu-options.hx b/qemu-options.hx index 65147ad971..708583b4ce 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -806,7 +806,7 @@ SRST Some drivers are: -``-device ipmi-bmc-sim,id=id[,slave_addr=val][,sdrfile=file][,furareasize=val][,furdatafile=file][,guid=uuid]`` +``-device ipmi-bmc-sim,id=id[,prop[=value][,...]]`` Add an IPMI BMC. This is a simulation of a hardware management interface processor that normally sits on a system. It provides a watchdog and the ability to reset and power control the system. You @@ -876,6 +876,15 @@ SRST ``-device isa-ipmi-bt,bmc=id[,ioport=val][,irq=val]`` Like the KCS interface, but defines a BT interface. The default port is 0xe4 and the default interrupt is 5. + +``-device pci-ipmi-kcs,bmc=id`` + Add a KCS IPMI interafce on the PCI bus. + + ``bmc=id`` + The BMC to connect to, one of ipmi-bmc-sim or ipmi-bmc-extern above. + +``-device pci-ipmi-bt,bmc=id`` + Like the KCS interface, but defines a BT interface on the PCI bus. ERST DEF("name", HAS_ARG, QEMU_OPTION_name, |