From: "Michael S. Tsirkin" <mst@redhat.com>
To: "Cédric Le Goater" <clg@kaod.org>
Cc: Corey Minyard <cminyard@mvista.com>,
David Gibson <david@gibson.dropbear.id.au>,
qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2] ipmi: add SET_SENSOR_READING command
Date: Mon, 24 Apr 2017 20:28:20 +0300 [thread overview]
Message-ID: <20170424202145-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <1491980930-32184-1-git-send-email-clg@kaod.org>
On Wed, Apr 12, 2017 at 09:08:50AM +0200, Cédric Le Goater wrote:
> SET_SENSOR_READING is a complex IPMI command (see IPMI spec 35.17)
> which enables the host software to set the reading value and the event
> status of sensors supporting it.
>
> Below is a proposal for all the operations (reading, assert, deassert,
> event data) with the following limitations :
>
> - No event are generated for threshold-based sensors.
> - The case in which the BMC needs to generate its own events is not
> supported.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
Need to look at how guests will behave if they start on
a new QEMU and migrate to old one.
Any input? Do we need a flag to behave like 2.9 did if
we want compatibility?
> ---
>
> Corey,
>
> There is some progress but I didn't add a check on the value before
> generating events because we would not generate an event when only
> the event bytes change.
>
> Changes since v1:
>
> - created copies of the reading and the assertion bits before
> committing the values
> - added some TODOs
> - handled inconsistent Event Data Bytes operation
>
> hw/ipmi/ipmi_bmc_sim.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 213 insertions(+)
>
> Index: qemu-powernv-2.9.git/hw/ipmi/ipmi_bmc_sim.c
> ===================================================================
> --- qemu-powernv-2.9.git.orig/hw/ipmi/ipmi_bmc_sim.c
> +++ qemu-powernv-2.9.git/hw/ipmi/ipmi_bmc_sim.c
> @@ -45,6 +45,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 */
>
> @@ -1739,6 +1740,217 @@ static void get_sensor_type(IPMIBmcSim *
> 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 },
> @@ -1759,6 +1971,7 @@ static const IPMICmdHandler sensor_event
> [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),
prev parent reply other threads:[~2017-04-24 17:28 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-12 7:08 [Qemu-devel] [PATCH v2] ipmi: add SET_SENSOR_READING command Cédric Le Goater
2017-04-17 19:45 ` Corey Minyard
2017-04-24 17:28 ` Michael S. Tsirkin [this message]
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=20170424202145-mutt-send-email-mst@kernel.org \
--to=mst@redhat.com \
--cc=clg@kaod.org \
--cc=cminyard@mvista.com \
--cc=david@gibson.dropbear.id.au \
--cc=qemu-devel@nongnu.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.