2024-02-01 04:11:08

by David E. Box

[permalink] [raw]
Subject: [PATCH 0/8] Intel On Demand: Add netlink interface for SPDM attestation

This patch series primarily adds support for a new netlink ABI in the
Intel On Demand driver for performing attestation of the hardware state.

Attestation patches

Patch 1: The attestation mailbox command requires that the message size
register be set along with the package size. Adds that support.

Patch 2: The attestation command will need to write the SPDM message and
read the response. The current mailbox flow handles reads and writes
separately. Combines the two flows.

Patch 3: Patch 4 will create a separate c file for the netlink
interface. Add a separate header file now. No functional changes. This
mostly just makes it easier to see the changes in Patch 4.

Patch 4: Adds attestation support to the driver and provides a netlink
interface to perform the service.

Other changes

Patch 5: Adds support to read the in-band BIOS lock. If set, On Demand
controls are not available in the driver.

Patch 6: Adds a new attribute to allow reading the most current metering
state.

Patch 7: Fixes for the intel_sdsi tool

Patch 8: Adds support to the intel_sdsi tool to read the current meter
state.

David E. Box (7):
platform/x86/intel/sdsi: Set message size during writes
platform/x86/intel/sdsi: Combine read and write mailbox flows
platform/x86/intel/sdsi: Add header file
platform/x86/intel/sdsi: Add netlink SPDM transport
platform/x86/intel/sdsi: Add attribute to read the current meter state
tools: Fix errors in meter_certificate display
tools: intel_sdsi: Add current meter support

Kuppuswamy Sathyanarayanan (1):
platform/x86/intel/sdsi: Add in-band BIOS lock support

Documentation/netlink/specs/intel_sdsi.yaml | 97 ++++++
MAINTAINERS | 3 +
drivers/platform/x86/intel/Makefile | 2 +-
drivers/platform/x86/intel/sdsi.c | 317 ++++++++++++++++----
drivers/platform/x86/intel/sdsi.h | 47 +++
drivers/platform/x86/intel/sdsi_genl.c | 249 +++++++++++++++
include/uapi/linux/intel-sdsi.h | 40 +++
tools/arch/x86/intel_sdsi/intel_sdsi.c | 99 +++---
8 files changed, 754 insertions(+), 100 deletions(-)
create mode 100644 Documentation/netlink/specs/intel_sdsi.yaml
create mode 100644 drivers/platform/x86/intel/sdsi.h
create mode 100644 drivers/platform/x86/intel/sdsi_genl.c
create mode 100644 include/uapi/linux/intel-sdsi.h


base-commit: 6613476e225e090cc9aad49be7fa504e290dd33d
--
2.34.1



2024-02-01 04:14:51

by David E. Box

[permalink] [raw]
Subject: [PATCH 5/8] platform/x86/intel/sdsi: Add in-band BIOS lock support

From: Kuppuswamy Sathyanarayanan <[email protected]>

As per SDSi in-band interface specification, sec titled "BIOS lock for
in-band provisioning", when IB_LOCK bit is set in control qword, the
SDSI agent is only allowed to perform the read flow, but not allowed to
provision license blob or license key. So add check for it in
sdsi_provision().

Signed-off-by: Kuppuswamy Sathyanarayanan <[email protected]>
Signed-off-by: David E. Box <[email protected]>
---
drivers/platform/x86/intel/sdsi.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index 14821fee249c..287780fe65bb 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -61,6 +61,7 @@
#define CTRL_OWNER GENMASK(5, 4)
#define CTRL_COMPLETE BIT(6)
#define CTRL_READY BIT(7)
+#define CTRL_INBAND_LOCK BIT(32)
#define CTRL_STATUS GENMASK(15, 8)
#define CTRL_PACKET_SIZE GENMASK(31, 16)
#define CTRL_MSG_SIZE GENMASK(63, 48)
@@ -331,12 +332,21 @@ static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, s
return sdsi_mbox_cmd_read(priv, info, data_size);
}

+static bool sdsi_ib_locked(struct sdsi_priv *priv)
+{
+ return !!FIELD_GET(CTRL_INBAND_LOCK, readq(priv->control_addr));
+}
+
static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
enum sdsi_command command)
{
struct sdsi_mbox_info info = {};
int ret;

+ /* Make sure In-band lock is not set */
+ if (sdsi_ib_locked(priv))
+ return -EPERM;
+
if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
return -EOVERFLOW;

--
2.34.1


2024-02-01 05:07:57

by David E. Box

[permalink] [raw]
Subject: [PATCH 6/8] platform/x86/intel/sdsi: Add attribute to read the current meter state

The meter_certificate file provides access to metering information that may
be attested but is only updated every 8 hours. Add new attribute,
meter_current, to allow reading an untested snapshot of the current values.

Signed-off-by: David E. Box <[email protected]>
---
drivers/platform/x86/intel/sdsi.c | 42 ++++++++++++++++++++++++++++---
drivers/platform/x86/intel/sdsi.h | 2 ++
2 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index 287780fe65bb..171899b4a671 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -62,6 +62,7 @@
#define CTRL_COMPLETE BIT(6)
#define CTRL_READY BIT(7)
#define CTRL_INBAND_LOCK BIT(32)
+#define CTRL_METER_ENABLE_DRAM BIT(33)
#define CTRL_STATUS GENMASK(15, 8)
#define CTRL_PACKET_SIZE GENMASK(31, 16)
#define CTRL_MSG_SIZE GENMASK(63, 48)
@@ -235,8 +236,10 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
control = FIELD_PREP(CTRL_EOM, 1) |
FIELD_PREP(CTRL_SOM, 1) |
FIELD_PREP(CTRL_RUN_BUSY, 1) |
- FIELD_PREP(CTRL_PACKET_SIZE, info->size);
+ FIELD_PREP(CTRL_PACKET_SIZE, info->size) |
+ priv->control_flags;
writeq(control, priv->control_addr);
+ priv->control_flags = 0;

return sdsi_mbox_poll(priv, info, data_size);
}
@@ -468,11 +471,42 @@ meter_certificate_read(struct file *filp, struct kobject *kobj,
{
struct device *dev = kobj_to_dev(kobj);
struct sdsi_priv *priv = dev_get_drvdata(dev);
+ int ret;

- return certificate_read(SDSI_CMD_READ_METER, priv, buf, off, count);
+ ret = mutex_lock_interruptible(&priv->meter_lock);
+ if (ret)
+ return ret;
+
+ ret = certificate_read(SDSI_CMD_READ_METER, priv, buf, off, count);
+
+ mutex_unlock(&priv->meter_lock);
+
+ return ret;
}
static BIN_ATTR_ADMIN_RO(meter_certificate, SDSI_SIZE_READ_MSG);

+static ssize_t
+meter_current_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t off,
+ size_t count)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct sdsi_priv *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = mutex_lock_interruptible(&priv->meter_lock);
+ if (ret)
+ return ret;
+
+ priv->control_flags = CTRL_METER_ENABLE_DRAM;
+ ret = certificate_read(SDSI_CMD_READ_METER, priv, buf, off, count);
+
+ mutex_unlock(&priv->meter_lock);
+
+ return ret;
+}
+static BIN_ATTR_ADMIN_RO(meter_current, SDSI_SIZE_READ_MSG);
+
static ssize_t registers_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t off,
size_t count)
@@ -503,6 +537,7 @@ static struct bin_attribute *sdsi_bin_attrs[] = {
&bin_attr_registers,
&bin_attr_state_certificate,
&bin_attr_meter_certificate,
+ &bin_attr_meter_current,
&bin_attr_provision_akc,
&bin_attr_provision_cap,
NULL
@@ -522,7 +557,7 @@ sdsi_battr_is_visible(struct kobject *kobj, struct bin_attribute *attr, int n)
if (!(priv->features & SDSI_FEATURE_SDSI))
return 0;

- if (attr == &bin_attr_meter_certificate)
+ if (attr == &bin_attr_meter_certificate || attr == &bin_attr_meter_current)
return (priv->features & SDSI_FEATURE_METERING) ?
attr->attr.mode : 0;

@@ -725,6 +760,7 @@ static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_de
priv->dev = &auxdev->dev;
priv->id = auxdev->id;
mutex_init(&priv->mb_lock);
+ mutex_init(&priv->meter_lock);
auxiliary_set_drvdata(auxdev, priv);

/* Get the SDSi discovery table */
diff --git a/drivers/platform/x86/intel/sdsi.h b/drivers/platform/x86/intel/sdsi.h
index 256618eb3136..e20cf279212e 100644
--- a/drivers/platform/x86/intel/sdsi.h
+++ b/drivers/platform/x86/intel/sdsi.h
@@ -18,12 +18,14 @@ struct device;

struct sdsi_priv {
struct mutex mb_lock; /* Mailbox access lock */
+ struct mutex meter_lock;
struct device *dev;
struct intel_vsec_device *ivdev;
struct list_head node;
void __iomem *control_addr;
void __iomem *mbox_addr;
void __iomem *regs_addr;
+ u64 control_flags;
int control_size;
int maibox_size;
int registers_size;
--
2.34.1


2024-02-01 07:07:12

by David E. Box

[permalink] [raw]
Subject: [PATCH 3/8] platform/x86/intel/sdsi: Add header file

In preparation for new source files, move common structures to a new
header flie.

Signed-off-by: David E. Box <[email protected]>
---
MAINTAINERS | 1 +
drivers/platform/x86/intel/sdsi.c | 23 +----------------------
drivers/platform/x86/intel/sdsi.h | 31 +++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+), 22 deletions(-)
create mode 100644 drivers/platform/x86/intel/sdsi.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8d1052fa6a69..09ef8497e48a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11042,6 +11042,7 @@ INTEL SDSI DRIVER
M: David E. Box <[email protected]>
S: Supported
F: drivers/platform/x86/intel/sdsi.c
+F: drivers/platform/x86/intel/sdsi.h
F: tools/arch/x86/intel_sdsi/
F: tools/testing/selftests/drivers/sdsi/

diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index 05a35f2f85b6..d48bb648f0b2 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -22,24 +22,16 @@
#include <linux/types.h>
#include <linux/uaccess.h>

+#include "sdsi.h"
#include "vsec.h"

#define ACCESS_TYPE_BARID 2
#define ACCESS_TYPE_LOCAL 3

#define SDSI_MIN_SIZE_DWORDS 276
-#define SDSI_SIZE_MAILBOX 1024
#define SDSI_SIZE_REGS 80
#define SDSI_SIZE_CMD sizeof(u64)

-/*
- * Write messages are currently up to the size of the mailbox
- * while read messages are up to 4 times the size of the
- * mailbox, sent in packets
- */
-#define SDSI_SIZE_WRITE_MSG SDSI_SIZE_MAILBOX
-#define SDSI_SIZE_READ_MSG (SDSI_SIZE_MAILBOX * 4)
-
#define SDSI_ENABLED_FEATURES_OFFSET 16
#define SDSI_FEATURE_SDSI BIT(3)
#define SDSI_FEATURE_METERING BIT(26)
@@ -103,19 +95,6 @@ struct disc_table {
u32 offset;
};

-struct sdsi_priv {
- struct mutex mb_lock; /* Mailbox access lock */
- struct device *dev;
- void __iomem *control_addr;
- void __iomem *mbox_addr;
- void __iomem *regs_addr;
- int control_size;
- int maibox_size;
- int registers_size;
- u32 guid;
- u32 features;
-};
-
/* SDSi mailbox operations must be performed using 64bit mov instructions */
static __always_inline void
sdsi_memcpy64_toio(u64 __iomem *to, const u64 *from, size_t count_bytes)
diff --git a/drivers/platform/x86/intel/sdsi.h b/drivers/platform/x86/intel/sdsi.h
new file mode 100644
index 000000000000..d0d7450c7b2b
--- /dev/null
+++ b/drivers/platform/x86/intel/sdsi.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PDx86_SDSI_H_
+#define __PDx86_SDSI_H_
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#define SDSI_SIZE_MAILBOX 1024
+
+/*
+ * Write messages are currently up to the size of the mailbox
+ * while read messages are up to 4 times the size of the
+ * mailbox, sent in packets
+ */
+#define SDSI_SIZE_WRITE_MSG SDSI_SIZE_MAILBOX
+#define SDSI_SIZE_READ_MSG (SDSI_SIZE_MAILBOX * 4)
+
+struct device;
+
+struct sdsi_priv {
+ struct mutex mb_lock; /* Mailbox access lock */
+ struct device *dev;
+ void __iomem *control_addr;
+ void __iomem *mbox_addr;
+ void __iomem *regs_addr;
+ int control_size;
+ int maibox_size;
+ int registers_size;
+ u32 guid;
+ u32 features;
+};
+#endif
--
2.34.1


2024-02-01 07:12:00

by David E. Box

[permalink] [raw]
Subject: [PATCH 1/8] platform/x86/intel/sdsi: Set message size during writes

New mailbox commands will support sending multi packet writes and updated
firmware now requires that the message size be written for all commands
along with the packet size. Since the driver doesn't perform writes larger
than the packet size, set the message size to the same value.

Signed-off-by: David E. Box <[email protected]>
---
drivers/platform/x86/intel/sdsi.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index 556e7c6dbb05..a70c071de6e2 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -252,6 +252,7 @@ static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *in
FIELD_PREP(CTRL_SOM, 1) |
FIELD_PREP(CTRL_RUN_BUSY, 1) |
FIELD_PREP(CTRL_READ_WRITE, 1) |
+ FIELD_PREP(CTRL_MSG_SIZE, info->size) |
FIELD_PREP(CTRL_PACKET_SIZE, info->size);
writeq(control, priv->control_addr);

--
2.34.1


2024-02-01 07:12:06

by David E. Box

[permalink] [raw]
Subject: [PATCH 2/8] platform/x86/intel/sdsi: Combine read and write mailbox flows

The current mailbox commands are either read-only or write-only and the
flow is different for each. New commands will need to send and receive
data. In preparation for these commands, create a common polling function
to handle sending data and receiving in the same transaction.

Signed-off-by: David E. Box <[email protected]>
---
drivers/platform/x86/intel/sdsi.c | 79 +++++++++++++++++--------------
1 file changed, 44 insertions(+), 35 deletions(-)

diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index a70c071de6e2..05a35f2f85b6 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -15,6 +15,7 @@
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/overflow.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
@@ -156,8 +157,8 @@ static int sdsi_status_to_errno(u32 status)
}
}

-static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
- size_t *data_size)
+static int sdsi_mbox_poll(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
+ size_t *data_size)
{
struct device *dev = priv->dev;
u32 total, loop, eom, status, message_size;
@@ -166,18 +167,10 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf

lockdep_assert_held(&priv->mb_lock);

- /* Format and send the read command */
- control = FIELD_PREP(CTRL_EOM, 1) |
- FIELD_PREP(CTRL_SOM, 1) |
- FIELD_PREP(CTRL_RUN_BUSY, 1) |
- FIELD_PREP(CTRL_PACKET_SIZE, info->size);
- writeq(control, priv->control_addr);
-
/* For reads, data sizes that are larger than the mailbox size are read in packets. */
total = 0;
loop = 0;
do {
- void *buf = info->buffer + (SDSI_SIZE_MAILBOX * loop);
u32 packet_size;

/* Poll on ready bit */
@@ -195,6 +188,11 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
if (ret)
break;

+ if (!packet_size) {
+ sdsi_complete_transaction(priv);
+ break;
+ }
+
/* Only the last packet can be less than the mailbox size. */
if (!eom && packet_size != SDSI_SIZE_MAILBOX) {
dev_err(dev, "Invalid packet size\n");
@@ -208,9 +206,13 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
break;
}

- sdsi_memcpy64_fromio(buf, priv->mbox_addr, round_up(packet_size, SDSI_SIZE_CMD));
+ if (packet_size && info->buffer) {
+ void *buf = info->buffer + array_size(SDSI_SIZE_MAILBOX, loop);

- total += packet_size;
+ sdsi_memcpy64_fromio(buf, priv->mbox_addr,
+ round_up(packet_size, SDSI_SIZE_CMD));
+ total += packet_size;
+ }

sdsi_complete_transaction(priv);
} while (!eom && ++loop < MBOX_MAX_PACKETS);
@@ -230,16 +232,33 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
dev_warn(dev, "Read count %u differs from expected count %u\n",
total, message_size);

- *data_size = total;
+ if (data_size)
+ *data_size = total;

return 0;
}

-static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
+static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
+ size_t *data_size)
+{
+ u64 control;
+
+ lockdep_assert_held(&priv->mb_lock);
+
+ /* Format and send the read command */
+ control = FIELD_PREP(CTRL_EOM, 1) |
+ FIELD_PREP(CTRL_SOM, 1) |
+ FIELD_PREP(CTRL_RUN_BUSY, 1) |
+ FIELD_PREP(CTRL_PACKET_SIZE, info->size);
+ writeq(control, priv->control_addr);
+
+ return sdsi_mbox_poll(priv, info, data_size);
+}
+
+static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
+ size_t *data_size)
{
u64 control;
- u32 status;
- int ret;

lockdep_assert_held(&priv->mb_lock);

@@ -256,20 +275,7 @@ static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *in
FIELD_PREP(CTRL_PACKET_SIZE, info->size);
writeq(control, priv->control_addr);

- /* Poll on ready bit */
- ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY,
- MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
-
- if (ret)
- goto release_mbox;
-
- status = FIELD_GET(CTRL_STATUS, control);
- ret = sdsi_status_to_errno(status);
-
-release_mbox:
- sdsi_complete_transaction(priv);
-
- return ret;
+ return sdsi_mbox_poll(priv, info, data_size);
}

static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
@@ -313,7 +319,8 @@ static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info
return ret;
}

-static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
+static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
+ size_t *data_size)
{
int ret;

@@ -323,7 +330,7 @@ static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
if (ret)
return ret;

- return sdsi_mbox_cmd_write(priv, info);
+ return sdsi_mbox_cmd_write(priv, info, data_size);
}

static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, size_t *data_size)
@@ -342,7 +349,7 @@ static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, s
static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
enum sdsi_command command)
{
- struct sdsi_mbox_info info;
+ struct sdsi_mbox_info info = {};
int ret;

if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
@@ -364,7 +371,9 @@ static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
ret = mutex_lock_interruptible(&priv->mb_lock);
if (ret)
goto free_payload;
- ret = sdsi_mbox_write(priv, &info);
+
+ ret = sdsi_mbox_write(priv, &info, NULL);
+
mutex_unlock(&priv->mb_lock);

free_payload:
@@ -408,7 +417,7 @@ static ssize_t
certificate_read(u64 command, struct sdsi_priv *priv, char *buf, loff_t off,
size_t count)
{
- struct sdsi_mbox_info info;
+ struct sdsi_mbox_info info = {};
size_t size;
int ret;

--
2.34.1


2024-02-01 07:46:28

by David E. Box

[permalink] [raw]
Subject: [PATCH 7/8] tools: Fix errors in meter_certificate display

The maximum number of bundles in the meter certificate was hardcoded to
8 which caused extra bundles not to display. Instead, since the bundles
appear at the end of the file, set it to the remaining size from where
the bundles start.

Add missing 'version' field to struct meter_certificate.

Fix errors in the calculation of the start position of the counters and
in the display loop.

Fixes: aad129780bae ("platform/x86/intel/sdsi: Add support for reading the current meter state")
Signed-off-by: David E. Box <[email protected]>
---
tools/arch/x86/intel_sdsi/intel_sdsi.c | 51 +++++++++++++++-----------
1 file changed, 30 insertions(+), 21 deletions(-)

diff --git a/tools/arch/x86/intel_sdsi/intel_sdsi.c b/tools/arch/x86/intel_sdsi/intel_sdsi.c
index 2cd92761f171..a8fb6d17405f 100644
--- a/tools/arch/x86/intel_sdsi/intel_sdsi.c
+++ b/tools/arch/x86/intel_sdsi/intel_sdsi.c
@@ -43,7 +43,6 @@
#define METER_CERT_MAX_SIZE 4096
#define STATE_MAX_NUM_LICENSES 16
#define STATE_MAX_NUM_IN_BUNDLE (uint32_t)8
-#define METER_MAX_NUM_BUNDLES 8

#define __round_mask(x, y) ((__typeof__(x))((y) - 1))
#define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
@@ -154,11 +153,12 @@ struct bundle_encoding {
};

struct meter_certificate {
- uint32_t block_signature;
+ uint32_t signature;
+ uint32_t version;
+ uint64_t ppin;
uint32_t counter_unit;
- uint64_t ppin;
uint32_t bundle_length;
- uint32_t reserved;
+ uint64_t reserved;
uint32_t mmrc_encoding;
uint32_t mmrc_counter;
};
@@ -167,6 +167,9 @@ struct bundle_encoding_counter {
uint32_t encoding;
uint32_t counter;
};
+#define METER_MAX_NUM_BUNDLES \
+ (METER_CERT_MAX_SIZE - sizeof(struct meter_certificate) / \
+ sizeof(struct bundle_encoding_counter))

struct sdsi_dev {
struct sdsi_regs regs;
@@ -334,6 +337,7 @@ static int sdsi_meter_cert_show(struct sdsi_dev *s)
uint32_t count = 0;
FILE *cert_ptr;
int ret, size;
+ char name[4];

ret = sdsi_update_registers(s);
if (ret)
@@ -375,32 +379,39 @@ static int sdsi_meter_cert_show(struct sdsi_dev *s)
printf("\n");
printf("Meter certificate for device %s\n", s->dev_name);
printf("\n");
- printf("Block Signature: 0x%x\n", mc->block_signature);
- printf("Count Unit: %dms\n", mc->counter_unit);
- printf("PPIN: 0x%lx\n", mc->ppin);
- printf("Feature Bundle Length: %d\n", mc->bundle_length);
- printf("MMRC encoding: %d\n", mc->mmrc_encoding);
- printf("MMRC counter: %d\n", mc->mmrc_counter);
+
+ get_feature(mc->signature, name);
+ printf("Signature: %.4s\n", name);
+
+ printf("Version: %d\n", mc->version);
+ printf("Count Unit: %dms\n", mc->counter_unit);
+ printf("PPIN: 0x%lx\n", mc->ppin);
+ printf("Feature Bundle Length: %d\n", mc->bundle_length);
+
+ get_feature(mc->mmrc_encoding, name);
+ printf("MMRC encoding: %.4s\n", name);
+
+ printf("MMRC counter: %d\n", mc->mmrc_counter);
if (mc->bundle_length % 8) {
fprintf(stderr, "Invalid bundle length\n");
return -1;
}

if (mc->bundle_length > METER_MAX_NUM_BUNDLES * 8) {
- fprintf(stderr, "More than %d bundles: %d\n",
+ fprintf(stderr, "More than %ld bundles: actual %d\n",
METER_MAX_NUM_BUNDLES, mc->bundle_length / 8);
return -1;
}

- bec = (void *)(mc) + sizeof(mc);
+ bec = (void *)(mc) + sizeof(*mc);

- printf("Number of Feature Counters: %d\n", mc->bundle_length / 8);
- while (count++ < mc->bundle_length / 8) {
- char feature[5];
+ printf("Number of Feature Counters: %d\n", mc->bundle_length / 8);
+ while (count < mc->bundle_length / 8) {
+ char feature[4];

- feature[4] = '\0';
get_feature(bec[count].encoding, feature);
- printf(" %s: %d\n", feature, bec[count].counter);
+ printf(" %.4s: %d\n", feature, bec[count].counter);
+ ++count;
}

return 0;
@@ -480,7 +491,7 @@ static int sdsi_state_cert_show(struct sdsi_dev *s)
sizeof(*lki) + // size of the license key info
offset; // offset to this blob content
struct bundle_encoding *bundle = (void *)(lbc) + sizeof(*lbc);
- char feature[5];
+ char feature[4];
uint32_t i;

printf(" Blob %d:\n", count - 1);
@@ -493,11 +504,9 @@ static int sdsi_state_cert_show(struct sdsi_dev *s)
printf(" Blob revision ID: %u\n", lbc->rev_id);
printf(" Number of Features: %u\n", lbc->num_bundles);

- feature[4] = '\0';
-
for (i = 0; i < min(lbc->num_bundles, STATE_MAX_NUM_IN_BUNDLE); i++) {
get_feature(bundle[i].encoding, feature);
- printf(" Feature %d: %s\n", i, feature);
+ printf(" Feature %d: %.4s\n", i, feature);
}

if (lbc->num_bundles > STATE_MAX_NUM_IN_BUNDLE)
--
2.34.1


Subject: Re: [PATCH 1/8] platform/x86/intel/sdsi: Set message size during writes


On 1/31/24 5:07 PM, David E. Box wrote:
> New mailbox commands will support sending multi packet writes and updated
> firmware now requires that the message size be written for all commands

Can you include some spec reference to new mailbox commands?

What about updated firmware mean? Like a particular version?

> along with the packet size. Since the driver doesn't perform writes larger
> than the packet size, set the message size to the same value.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> drivers/platform/x86/intel/sdsi.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
> index 556e7c6dbb05..a70c071de6e2 100644
> --- a/drivers/platform/x86/intel/sdsi.c
> +++ b/drivers/platform/x86/intel/sdsi.c
> @@ -252,6 +252,7 @@ static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *in
> FIELD_PREP(CTRL_SOM, 1) |
> FIELD_PREP(CTRL_RUN_BUSY, 1) |
> FIELD_PREP(CTRL_READ_WRITE, 1) |
> + FIELD_PREP(CTRL_MSG_SIZE, info->size) |
> FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> writeq(control, priv->control_addr);
>

--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer


Subject: Re: [PATCH 0/8] Intel On Demand: Add netlink interface for SPDM attestation


On 1/31/24 5:07 PM, David E. Box wrote:
> This patch series primarily adds support for a new netlink ABI in the
> Intel On Demand driver for performing attestation of the hardware state.

Try to add some info about why you need new netlink ABI?

>
> Attestation patches
>
> Patch 1: The attestation mailbox command requires that the message size
> register be set along with the package size. Adds that support.
>
> Patch 2: The attestation command will need to write the SPDM message and
> read the response. The current mailbox flow handles reads and writes
> separately. Combines the two flows.
>
> Patch 3: Patch 4 will create a separate c file for the netlink
> interface. Add a separate header file now. No functional changes. This
> mostly just makes it easier to see the changes in Patch 4.
>
> Patch 4: Adds attestation support to the driver and provides a netlink
> interface to perform the service.
>
> Other changes
>
> Patch 5: Adds support to read the in-band BIOS lock. If set, On Demand
> controls are not available in the driver.
>
> Patch 6: Adds a new attribute to allow reading the most current metering
> state.
>
> Patch 7: Fixes for the intel_sdsi tool
>
> Patch 8: Adds support to the intel_sdsi tool to read the current meter
> state.
>
> David E. Box (7):
> platform/x86/intel/sdsi: Set message size during writes
> platform/x86/intel/sdsi: Combine read and write mailbox flows
> platform/x86/intel/sdsi: Add header file
> platform/x86/intel/sdsi: Add netlink SPDM transport
> platform/x86/intel/sdsi: Add attribute to read the current meter state
> tools: Fix errors in meter_certificate display
> tools: intel_sdsi: Add current meter support
>
> Kuppuswamy Sathyanarayanan (1):
> platform/x86/intel/sdsi: Add in-band BIOS lock support
>
> Documentation/netlink/specs/intel_sdsi.yaml | 97 ++++++
> MAINTAINERS | 3 +
> drivers/platform/x86/intel/Makefile | 2 +-
> drivers/platform/x86/intel/sdsi.c | 317 ++++++++++++++++----
> drivers/platform/x86/intel/sdsi.h | 47 +++
> drivers/platform/x86/intel/sdsi_genl.c | 249 +++++++++++++++
> include/uapi/linux/intel-sdsi.h | 40 +++
> tools/arch/x86/intel_sdsi/intel_sdsi.c | 99 +++---
> 8 files changed, 754 insertions(+), 100 deletions(-)
> create mode 100644 Documentation/netlink/specs/intel_sdsi.yaml
> create mode 100644 drivers/platform/x86/intel/sdsi.h
> create mode 100644 drivers/platform/x86/intel/sdsi_genl.c
> create mode 100644 include/uapi/linux/intel-sdsi.h
>
>
> base-commit: 6613476e225e090cc9aad49be7fa504e290dd33d

--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer


Subject: Re: [PATCH 2/8] platform/x86/intel/sdsi: Combine read and write mailbox flows


On 1/31/24 5:07 PM, David E. Box wrote:
> The current mailbox commands are either read-only or write-only and the
> flow is different for each. New commands will need to send and receive
> data. In preparation for these commands, create a common polling function
> to handle sending data and receiving in the same transaction.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> drivers/platform/x86/intel/sdsi.c | 79 +++++++++++++++++--------------
> 1 file changed, 44 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
> index a70c071de6e2..05a35f2f85b6 100644
> --- a/drivers/platform/x86/intel/sdsi.c
> +++ b/drivers/platform/x86/intel/sdsi.c
> @@ -15,6 +15,7 @@
> #include <linux/iopoll.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> +#include <linux/overflow.h>
> #include <linux/pci.h>
> #include <linux/slab.h>
> #include <linux/sysfs.h>
> @@ -156,8 +157,8 @@ static int sdsi_status_to_errno(u32 status)
> }
> }
>
> -static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
> - size_t *data_size)
> +static int sdsi_mbox_poll(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
> + size_t *data_size)
> {
> struct device *dev = priv->dev;
> u32 total, loop, eom, status, message_size;
> @@ -166,18 +167,10 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
>
> lockdep_assert_held(&priv->mb_lock);
>
> - /* Format and send the read command */
> - control = FIELD_PREP(CTRL_EOM, 1) |
> - FIELD_PREP(CTRL_SOM, 1) |
> - FIELD_PREP(CTRL_RUN_BUSY, 1) |
> - FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> - writeq(control, priv->control_addr);
> -
> /* For reads, data sizes that are larger than the mailbox size are read in packets. */
> total = 0;
> loop = 0;
> do {
> - void *buf = info->buffer + (SDSI_SIZE_MAILBOX * loop);
> u32 packet_size;
>
> /* Poll on ready bit */
> @@ -195,6 +188,11 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
> if (ret)
> break;
>
> + if (!packet_size) {
> + sdsi_complete_transaction(priv);
> + break;
> + }
> +

It seems to be a generic check. Is this related to converting to a read/write function or
a common fix you added together in this patch.

> /* Only the last packet can be less than the mailbox size. */
> if (!eom && packet_size != SDSI_SIZE_MAILBOX) {
> dev_err(dev, "Invalid packet size\n");
> @@ -208,9 +206,13 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
> break;
> }
>
> - sdsi_memcpy64_fromio(buf, priv->mbox_addr, round_up(packet_size, SDSI_SIZE_CMD));
> + if (packet_size && info->buffer) {
> + void *buf = info->buffer + array_size(SDSI_SIZE_MAILBOX, loop);
>
> - total += packet_size;
> + sdsi_memcpy64_fromio(buf, priv->mbox_addr,
> + round_up(packet_size, SDSI_SIZE_CMD));
> + total += packet_size;
> + }
>
> sdsi_complete_transaction(priv);
> } while (!eom && ++loop < MBOX_MAX_PACKETS);
> @@ -230,16 +232,33 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
> dev_warn(dev, "Read count %u differs from expected count %u\n",
> total, message_size);
>
> - *data_size = total;
> + if (data_size)
> + *data_size = total;
>
> return 0;
> }
>
> -static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
> +static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
> + size_t *data_size)
> +{
> + u64 control;
> +
> + lockdep_assert_held(&priv->mb_lock);
> +
> + /* Format and send the read command */
> + control = FIELD_PREP(CTRL_EOM, 1) |
> + FIELD_PREP(CTRL_SOM, 1) |
> + FIELD_PREP(CTRL_RUN_BUSY, 1) |
> + FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> + writeq(control, priv->control_addr);
> +
> + return sdsi_mbox_poll(priv, info, data_size);
> +}
> +
> +static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
> + size_t *data_size)
> {
> u64 control;
> - u32 status;
> - int ret;
>
> lockdep_assert_held(&priv->mb_lock);
>
> @@ -256,20 +275,7 @@ static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *in
> FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> writeq(control, priv->control_addr);
>
> - /* Poll on ready bit */
> - ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY,
> - MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
> -
> - if (ret)
> - goto release_mbox;
> -
> - status = FIELD_GET(CTRL_STATUS, control);
> - ret = sdsi_status_to_errno(status);
> -
> -release_mbox:
> - sdsi_complete_transaction(priv);
> -
> - return ret;
> + return sdsi_mbox_poll(priv, info, data_size);
> }
>
> static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
> @@ -313,7 +319,8 @@ static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info
> return ret;
> }
>
> -static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
> +static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
> + size_t *data_size)
> {
> int ret;
>
> @@ -323,7 +330,7 @@ static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
> if (ret)
> return ret;
>
> - return sdsi_mbox_cmd_write(priv, info);
> + return sdsi_mbox_cmd_write(priv, info, data_size);
> }
>
> static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, size_t *data_size)
> @@ -342,7 +349,7 @@ static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, s
> static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
> enum sdsi_command command)
> {
> - struct sdsi_mbox_info info;
> + struct sdsi_mbox_info info = {};

This change also looks like an independent fix. Is this related to common function usage
you mentioned in the commit log.

> int ret;
>
> if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
> @@ -364,7 +371,9 @@ static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
> ret = mutex_lock_interruptible(&priv->mb_lock);
> if (ret)
> goto free_payload;
> - ret = sdsi_mbox_write(priv, &info);
> +
> + ret = sdsi_mbox_write(priv, &info, NULL);
> +
> mutex_unlock(&priv->mb_lock);
>
> free_payload:
> @@ -408,7 +417,7 @@ static ssize_t
> certificate_read(u64 command, struct sdsi_priv *priv, char *buf, loff_t off,
> size_t count)
> {
> - struct sdsi_mbox_info info;
> + struct sdsi_mbox_info info = {};
> size_t size;
> int ret;
>

--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer


2024-02-02 00:11:16

by David E. Box

[permalink] [raw]
Subject: Re: [PATCH 2/8] platform/x86/intel/sdsi: Combine read and write mailbox flows

Hi Sathya,

On Thu, 2024-02-01 at 09:31 -0800, Kuppuswamy Sathyanarayanan wrote:
>
> On 1/31/24 5:07 PM, David E. Box wrote:
> > The current mailbox commands are either read-only or write-only and the
> > flow is different for each. New commands will need to send and receive
> > data. In preparation for these commands, create a common polling function
> > to handle sending data and receiving in the same transaction.
> >
> > Signed-off-by: David E. Box <[email protected]>
> > ---
> >  drivers/platform/x86/intel/sdsi.c | 79 +++++++++++++++++--------------
> >  1 file changed, 44 insertions(+), 35 deletions(-)
> >
> > diff --git a/drivers/platform/x86/intel/sdsi.c
> > b/drivers/platform/x86/intel/sdsi.c
> > index a70c071de6e2..05a35f2f85b6 100644
> > --- a/drivers/platform/x86/intel/sdsi.c
> > +++ b/drivers/platform/x86/intel/sdsi.c
> > @@ -15,6 +15,7 @@
> >  #include <linux/iopoll.h>
> >  #include <linux/kernel.h>
> >  #include <linux/module.h>
> > +#include <linux/overflow.h>
> >  #include <linux/pci.h>
> >  #include <linux/slab.h>
> >  #include <linux/sysfs.h>
> > @@ -156,8 +157,8 @@ static int sdsi_status_to_errno(u32 status)
> >         }
> >  }
> >  
> > -static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info
> > *info,
> > -                             size_t *data_size)
> > +static int sdsi_mbox_poll(struct sdsi_priv *priv, struct sdsi_mbox_info
> > *info,
> > +                         size_t *data_size)
> >  {
> >         struct device *dev = priv->dev;
> >         u32 total, loop, eom, status, message_size;
> > @@ -166,18 +167,10 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv,
> > struct sdsi_mbox_info *inf
> >  
> >         lockdep_assert_held(&priv->mb_lock);
> >  
> > -       /* Format and send the read command */
> > -       control = FIELD_PREP(CTRL_EOM, 1) |
> > -                 FIELD_PREP(CTRL_SOM, 1) |
> > -                 FIELD_PREP(CTRL_RUN_BUSY, 1) |
> > -                 FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> > -       writeq(control, priv->control_addr);
> > -
> >         /* For reads, data sizes that are larger than the mailbox size are
> > read in packets. */
> >         total = 0;
> >         loop = 0;
> >         do {
> > -               void *buf = info->buffer + (SDSI_SIZE_MAILBOX * loop);
> >                 u32 packet_size;
> >  
> >                 /* Poll on ready bit */
> > @@ -195,6 +188,11 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv,
> > struct sdsi_mbox_info *inf
> >                 if (ret)
> >                         break;
> >  
> > +               if (!packet_size) {
> > +                       sdsi_complete_transaction(priv);
> > +                       break;
> > +               }
> > +
>
> It seems to be a generic check. Is this related to converting to a read/write
> function or
> a common fix you added together in this patch.

Yes, it's related. The code that follows this only applies to reads. This check
would be true only for writes which only need to poll once to confirm the write
was successful. I'll add a comment to make it clear.

2024-02-02 01:43:04

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH 0/8] Intel On Demand: Add netlink interface for SPDM attestation

On Thu, 1 Feb 2024 08:53:37 -0800 Kuppuswamy Sathyanarayanan wrote:
> On 1/31/24 5:07 PM, David E. Box wrote:
> > This patch series primarily adds support for a new netlink ABI in the
> > Intel On Demand driver for performing attestation of the hardware state.
>
> Try to add some info about why you need new netlink ABI?

Since netdev is copied it'd also be useful to give us a high level
intro into what pieces are involved. Assume we have heard about
SPDM/attestation in context of NIC FW but have little understanding of
x86 platform stuff.

grep -i sdsi Documentation doesn't say much, the first Google result
for Intel On Demand reads like marketing fluff :(

2024-02-08 13:38:26

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH 2/8] platform/x86/intel/sdsi: Combine read and write mailbox flows

On Wed, 31 Jan 2024, David E. Box wrote:

> The current mailbox commands are either read-only or write-only and the
> flow is different for each. New commands will need to send and receive
> data. In preparation for these commands, create a common polling function
> to handle sending data and receiving in the same transaction.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> drivers/platform/x86/intel/sdsi.c | 79 +++++++++++++++++--------------
> 1 file changed, 44 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
> index a70c071de6e2..05a35f2f85b6 100644
> --- a/drivers/platform/x86/intel/sdsi.c
> +++ b/drivers/platform/x86/intel/sdsi.c
> @@ -15,6 +15,7 @@
> #include <linux/iopoll.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> +#include <linux/overflow.h>
> #include <linux/pci.h>
> #include <linux/slab.h>
> #include <linux/sysfs.h>
> @@ -156,8 +157,8 @@ static int sdsi_status_to_errno(u32 status)
> }
> }
>
> -static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
> - size_t *data_size)
> +static int sdsi_mbox_poll(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
> + size_t *data_size)
> {
> struct device *dev = priv->dev;
> u32 total, loop, eom, status, message_size;
> @@ -166,18 +167,10 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
>
> lockdep_assert_held(&priv->mb_lock);
>
> - /* Format and send the read command */
> - control = FIELD_PREP(CTRL_EOM, 1) |
> - FIELD_PREP(CTRL_SOM, 1) |
> - FIELD_PREP(CTRL_RUN_BUSY, 1) |
> - FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> - writeq(control, priv->control_addr);
> -
> /* For reads, data sizes that are larger than the mailbox size are read in packets. */
> total = 0;
> loop = 0;
> do {
> - void *buf = info->buffer + (SDSI_SIZE_MAILBOX * loop);
> u32 packet_size;
>
> /* Poll on ready bit */
> @@ -195,6 +188,11 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
> if (ret)
> break;
>
> + if (!packet_size) {
> + sdsi_complete_transaction(priv);
> + break;
> + }
> +
> /* Only the last packet can be less than the mailbox size. */
> if (!eom && packet_size != SDSI_SIZE_MAILBOX) {
> dev_err(dev, "Invalid packet size\n");
> @@ -208,9 +206,13 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
> break;
> }
>
> - sdsi_memcpy64_fromio(buf, priv->mbox_addr, round_up(packet_size, SDSI_SIZE_CMD));
> + if (packet_size && info->buffer) {

Why you check for packet_size here if you break earlier for !packet_size?

> + void *buf = info->buffer + array_size(SDSI_SIZE_MAILBOX, loop);
>
> - total += packet_size;
> + sdsi_memcpy64_fromio(buf, priv->mbox_addr,
> + round_up(packet_size, SDSI_SIZE_CMD));
> + total += packet_size;
> + }
>
> sdsi_complete_transaction(priv);
> } while (!eom && ++loop < MBOX_MAX_PACKETS);
> @@ -230,16 +232,33 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
> dev_warn(dev, "Read count %u differs from expected count %u\n",
> total, message_size);
>
> - *data_size = total;
> + if (data_size)
> + *data_size = total;
>
> return 0;
> }


--
i.


2024-02-08 13:56:32

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH 5/8] platform/x86/intel/sdsi: Add in-band BIOS lock support

On Wed, 31 Jan 2024, David E. Box wrote:

> From: Kuppuswamy Sathyanarayanan <[email protected]>
>
> As per SDSi in-band interface specification, sec titled "BIOS lock for
> in-band provisioning", when IB_LOCK bit is set in control qword, the
> SDSI agent is only allowed to perform the read flow, but not allowed to
> provision license blob or license key. So add check for it in
> sdsi_provision().
>
> Signed-off-by: Kuppuswamy Sathyanarayanan <[email protected]>
> Signed-off-by: David E. Box <[email protected]>
> ---
> drivers/platform/x86/intel/sdsi.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
> index 14821fee249c..287780fe65bb 100644
> --- a/drivers/platform/x86/intel/sdsi.c
> +++ b/drivers/platform/x86/intel/sdsi.c
> @@ -61,6 +61,7 @@
> #define CTRL_OWNER GENMASK(5, 4)
> #define CTRL_COMPLETE BIT(6)
> #define CTRL_READY BIT(7)
> +#define CTRL_INBAND_LOCK BIT(32)
> #define CTRL_STATUS GENMASK(15, 8)
> #define CTRL_PACKET_SIZE GENMASK(31, 16)
> #define CTRL_MSG_SIZE GENMASK(63, 48)
> @@ -331,12 +332,21 @@ static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, s
> return sdsi_mbox_cmd_read(priv, info, data_size);
> }
>
> +static bool sdsi_ib_locked(struct sdsi_priv *priv)
> +{
> + return !!FIELD_GET(CTRL_INBAND_LOCK, readq(priv->control_addr));
> +}
> +
> static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
> enum sdsi_command command)
> {
> struct sdsi_mbox_info info = {};
> int ret;
>
> + /* Make sure In-band lock is not set */
> + if (sdsi_ib_locked(priv))
> + return -EPERM;
> +
> if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
> return -EOVERFLOW;

Any reason why this order was chosen? I'd prefer these checks be other way
around (a stupid caller providing too long count gets notified of its
stupidity regardless of the locked state).

--
i.


2024-02-08 14:44:06

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH 6/8] platform/x86/intel/sdsi: Add attribute to read the current meter state

On Wed, 31 Jan 2024, David E. Box wrote:

> The meter_certificate file provides access to metering information that may
> be attested but is only updated every 8 hours. Add new attribute,
> meter_current, to allow reading an untested snapshot of the current values.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> drivers/platform/x86/intel/sdsi.c | 42 ++++++++++++++++++++++++++++---
> drivers/platform/x86/intel/sdsi.h | 2 ++
> 2 files changed, 41 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
> index 287780fe65bb..171899b4a671 100644
> --- a/drivers/platform/x86/intel/sdsi.c
> +++ b/drivers/platform/x86/intel/sdsi.c
> @@ -62,6 +62,7 @@
> #define CTRL_COMPLETE BIT(6)
> #define CTRL_READY BIT(7)
> #define CTRL_INBAND_LOCK BIT(32)
> +#define CTRL_METER_ENABLE_DRAM BIT(33)
> #define CTRL_STATUS GENMASK(15, 8)
> #define CTRL_PACKET_SIZE GENMASK(31, 16)
> #define CTRL_MSG_SIZE GENMASK(63, 48)
> @@ -235,8 +236,10 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf
> control = FIELD_PREP(CTRL_EOM, 1) |
> FIELD_PREP(CTRL_SOM, 1) |
> FIELD_PREP(CTRL_RUN_BUSY, 1) |
> - FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> + FIELD_PREP(CTRL_PACKET_SIZE, info->size) |
> + priv->control_flags;
> writeq(control, priv->control_addr);
> + priv->control_flags = 0;

I'm slightly worried about this. The function is named with a generic
name but I suppose meter_lock that has less generic name is supposed to
protect this also?

Also, resetting it after every use smells like it should be a parameter
instead of struct member.

> return sdsi_mbox_poll(priv, info, data_size);
> }
> @@ -468,11 +471,42 @@ meter_certificate_read(struct file *filp, struct kobject *kobj,
> {
> struct device *dev = kobj_to_dev(kobj);
> struct sdsi_priv *priv = dev_get_drvdata(dev);
> + int ret;
>
> - return certificate_read(SDSI_CMD_READ_METER, priv, buf, off, count);
> + ret = mutex_lock_interruptible(&priv->meter_lock);
> + if (ret)
> + return ret;
> +
> + ret = certificate_read(SDSI_CMD_READ_METER, priv, buf, off, count);
> +
> + mutex_unlock(&priv->meter_lock);
> +
> + return ret;
> }
> static BIN_ATTR_ADMIN_RO(meter_certificate, SDSI_SIZE_READ_MSG);
>
> +static ssize_t
> +meter_current_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *attr, char *buf, loff_t off,
> + size_t count)
> +{
> + struct device *dev = kobj_to_dev(kobj);
> + struct sdsi_priv *priv = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = mutex_lock_interruptible(&priv->meter_lock);
> + if (ret)
> + return ret;
> +
> + priv->control_flags = CTRL_METER_ENABLE_DRAM;
> + ret = certificate_read(SDSI_CMD_READ_METER, priv, buf, off, count);
> +
> + mutex_unlock(&priv->meter_lock);
> +
> + return ret;
> +}
> +static BIN_ATTR_ADMIN_RO(meter_current, SDSI_SIZE_READ_MSG);
> +
> static ssize_t registers_read(struct file *filp, struct kobject *kobj,
> struct bin_attribute *attr, char *buf, loff_t off,
> size_t count)
> @@ -503,6 +537,7 @@ static struct bin_attribute *sdsi_bin_attrs[] = {
> &bin_attr_registers,
> &bin_attr_state_certificate,
> &bin_attr_meter_certificate,
> + &bin_attr_meter_current,
> &bin_attr_provision_akc,
> &bin_attr_provision_cap,
> NULL
> @@ -522,7 +557,7 @@ sdsi_battr_is_visible(struct kobject *kobj, struct bin_attribute *attr, int n)
> if (!(priv->features & SDSI_FEATURE_SDSI))
> return 0;
>
> - if (attr == &bin_attr_meter_certificate)
> + if (attr == &bin_attr_meter_certificate || attr == &bin_attr_meter_current)
> return (priv->features & SDSI_FEATURE_METERING) ?
> attr->attr.mode : 0;
>
> @@ -725,6 +760,7 @@ static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_de
> priv->dev = &auxdev->dev;
> priv->id = auxdev->id;
> mutex_init(&priv->mb_lock);
> + mutex_init(&priv->meter_lock);
> auxiliary_set_drvdata(auxdev, priv);
>
> /* Get the SDSi discovery table */
> diff --git a/drivers/platform/x86/intel/sdsi.h b/drivers/platform/x86/intel/sdsi.h
> index 256618eb3136..e20cf279212e 100644
> --- a/drivers/platform/x86/intel/sdsi.h
> +++ b/drivers/platform/x86/intel/sdsi.h
> @@ -18,12 +18,14 @@ struct device;
>
> struct sdsi_priv {
> struct mutex mb_lock; /* Mailbox access lock */
> + struct mutex meter_lock;

Please add information what this protects.


--
i.


2024-02-08 14:45:13

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH 3/8] platform/x86/intel/sdsi: Add header file

On Wed, 31 Jan 2024, David E. Box wrote:

> In preparation for new source files, move common structures to a new
> header flie.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> MAINTAINERS | 1 +
> drivers/platform/x86/intel/sdsi.c | 23 +----------------------
> drivers/platform/x86/intel/sdsi.h | 31 +++++++++++++++++++++++++++++++
> 3 files changed, 33 insertions(+), 22 deletions(-)
> create mode 100644 drivers/platform/x86/intel/sdsi.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8d1052fa6a69..09ef8497e48a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11042,6 +11042,7 @@ INTEL SDSI DRIVER
> M: David E. Box <[email protected]>
> S: Supported
> F: drivers/platform/x86/intel/sdsi.c
> +F: drivers/platform/x86/intel/sdsi.h

Use this instead:

drivers/platform/x86/intel/sdsi*

Reviewed-by: Ilpo J?rvinen <[email protected]>

--
i.

2024-02-08 14:46:25

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH 7/8] tools: Fix errors in meter_certificate display

On Wed, 31 Jan 2024, David E. Box wrote:

> The maximum number of bundles in the meter certificate was hardcoded to
> 8 which caused extra bundles not to display. Instead, since the bundles
> appear at the end of the file, set it to the remaining size from where
> the bundles start.
>
> Add missing 'version' field to struct meter_certificate.
>
> Fix errors in the calculation of the start position of the counters and
> in the display loop.

Why are all these bundled into a single commit? They sound like
independent changes.

--
i.

> Fixes: aad129780bae ("platform/x86/intel/sdsi: Add support for reading the current meter state")
> Signed-off-by: David E. Box <[email protected]>
> ---
> tools/arch/x86/intel_sdsi/intel_sdsi.c | 51 +++++++++++++++-----------
> 1 file changed, 30 insertions(+), 21 deletions(-)
>
> diff --git a/tools/arch/x86/intel_sdsi/intel_sdsi.c b/tools/arch/x86/intel_sdsi/intel_sdsi.c
> index 2cd92761f171..a8fb6d17405f 100644
> --- a/tools/arch/x86/intel_sdsi/intel_sdsi.c
> +++ b/tools/arch/x86/intel_sdsi/intel_sdsi.c
> @@ -43,7 +43,6 @@
> #define METER_CERT_MAX_SIZE 4096
> #define STATE_MAX_NUM_LICENSES 16
> #define STATE_MAX_NUM_IN_BUNDLE (uint32_t)8
> -#define METER_MAX_NUM_BUNDLES 8
>
> #define __round_mask(x, y) ((__typeof__(x))((y) - 1))
> #define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
> @@ -154,11 +153,12 @@ struct bundle_encoding {
> };
>
> struct meter_certificate {
> - uint32_t block_signature;
> + uint32_t signature;
> + uint32_t version;
> + uint64_t ppin;
> uint32_t counter_unit;
> - uint64_t ppin;
> uint32_t bundle_length;
> - uint32_t reserved;
> + uint64_t reserved;
> uint32_t mmrc_encoding;
> uint32_t mmrc_counter;
> };
> @@ -167,6 +167,9 @@ struct bundle_encoding_counter {
> uint32_t encoding;
> uint32_t counter;
> };
> +#define METER_MAX_NUM_BUNDLES \
> + (METER_CERT_MAX_SIZE - sizeof(struct meter_certificate) / \
> + sizeof(struct bundle_encoding_counter))
>
> struct sdsi_dev {
> struct sdsi_regs regs;
> @@ -334,6 +337,7 @@ static int sdsi_meter_cert_show(struct sdsi_dev *s)
> uint32_t count = 0;
> FILE *cert_ptr;
> int ret, size;
> + char name[4];
>
> ret = sdsi_update_registers(s);
> if (ret)
> @@ -375,32 +379,39 @@ static int sdsi_meter_cert_show(struct sdsi_dev *s)
> printf("\n");
> printf("Meter certificate for device %s\n", s->dev_name);
> printf("\n");
> - printf("Block Signature: 0x%x\n", mc->block_signature);
> - printf("Count Unit: %dms\n", mc->counter_unit);
> - printf("PPIN: 0x%lx\n", mc->ppin);
> - printf("Feature Bundle Length: %d\n", mc->bundle_length);
> - printf("MMRC encoding: %d\n", mc->mmrc_encoding);
> - printf("MMRC counter: %d\n", mc->mmrc_counter);
> +
> + get_feature(mc->signature, name);
> + printf("Signature: %.4s\n", name);
> +
> + printf("Version: %d\n", mc->version);
> + printf("Count Unit: %dms\n", mc->counter_unit);
> + printf("PPIN: 0x%lx\n", mc->ppin);
> + printf("Feature Bundle Length: %d\n", mc->bundle_length);
> +
> + get_feature(mc->mmrc_encoding, name);
> + printf("MMRC encoding: %.4s\n", name);
> +
> + printf("MMRC counter: %d\n", mc->mmrc_counter);
> if (mc->bundle_length % 8) {
> fprintf(stderr, "Invalid bundle length\n");
> return -1;
> }
>
> if (mc->bundle_length > METER_MAX_NUM_BUNDLES * 8) {
> - fprintf(stderr, "More than %d bundles: %d\n",
> + fprintf(stderr, "More than %ld bundles: actual %d\n",
> METER_MAX_NUM_BUNDLES, mc->bundle_length / 8);
> return -1;
> }
>
> - bec = (void *)(mc) + sizeof(mc);
> + bec = (void *)(mc) + sizeof(*mc);
>
> - printf("Number of Feature Counters: %d\n", mc->bundle_length / 8);
> - while (count++ < mc->bundle_length / 8) {
> - char feature[5];
> + printf("Number of Feature Counters: %d\n", mc->bundle_length / 8);
> + while (count < mc->bundle_length / 8) {
> + char feature[4];
>
> - feature[4] = '\0';
> get_feature(bec[count].encoding, feature);
> - printf(" %s: %d\n", feature, bec[count].counter);
> + printf(" %.4s: %d\n", feature, bec[count].counter);
> + ++count;
> }
>
> return 0;
> @@ -480,7 +491,7 @@ static int sdsi_state_cert_show(struct sdsi_dev *s)
> sizeof(*lki) + // size of the license key info
> offset; // offset to this blob content
> struct bundle_encoding *bundle = (void *)(lbc) + sizeof(*lbc);
> - char feature[5];
> + char feature[4];
> uint32_t i;
>
> printf(" Blob %d:\n", count - 1);
> @@ -493,11 +504,9 @@ static int sdsi_state_cert_show(struct sdsi_dev *s)
> printf(" Blob revision ID: %u\n", lbc->rev_id);
> printf(" Number of Features: %u\n", lbc->num_bundles);
>
> - feature[4] = '\0';
> -
> for (i = 0; i < min(lbc->num_bundles, STATE_MAX_NUM_IN_BUNDLE); i++) {
> get_feature(bundle[i].encoding, feature);
> - printf(" Feature %d: %s\n", i, feature);
> + printf(" Feature %d: %.4s\n", i, feature);
> }
>
> if (lbc->num_bundles > STATE_MAX_NUM_IN_BUNDLE)
>

2024-02-08 17:50:47

by Ilpo Järvinen

[permalink] [raw]
Subject: Re: [PATCH 1/8] platform/x86/intel/sdsi: Set message size during writes

On Wed, 31 Jan 2024, David E. Box wrote:

> New mailbox commands will support sending multi packet writes and updated
> firmware now requires that the message size be written for all commands
> along with the packet size. Since the driver doesn't perform writes larger
> than the packet size, set the message size to the same value.
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> drivers/platform/x86/intel/sdsi.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
> index 556e7c6dbb05..a70c071de6e2 100644
> --- a/drivers/platform/x86/intel/sdsi.c
> +++ b/drivers/platform/x86/intel/sdsi.c
> @@ -252,6 +252,7 @@ static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *in
> FIELD_PREP(CTRL_SOM, 1) |
> FIELD_PREP(CTRL_RUN_BUSY, 1) |
> FIELD_PREP(CTRL_READ_WRITE, 1) |
> + FIELD_PREP(CTRL_MSG_SIZE, info->size) |
> FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> writeq(control, priv->control_addr);

Reviewed-by: Ilpo J?rvinen <[email protected]>

--
i.

Subject: Re: [PATCH 3/8] platform/x86/intel/sdsi: Add header file


On 1/31/24 5:07 PM, David E. Box wrote:
> In preparation for new source files, move common structures to a new
> header flie.

Add some detail about why you adding new source files.

Reviewed-by: Kuppuswamy Sathyanarayanan <[email protected]>
>
> Signed-off-by: David E. Box <[email protected]>
> ---
> MAINTAINERS | 1 +
> drivers/platform/x86/intel/sdsi.c | 23 +----------------------
> drivers/platform/x86/intel/sdsi.h | 31 +++++++++++++++++++++++++++++++
> 3 files changed, 33 insertions(+), 22 deletions(-)
> create mode 100644 drivers/platform/x86/intel/sdsi.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8d1052fa6a69..09ef8497e48a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11042,6 +11042,7 @@ INTEL SDSI DRIVER
> M: David E. Box <[email protected]>
> S: Supported
> F: drivers/platform/x86/intel/sdsi.c
> +F: drivers/platform/x86/intel/sdsi.h
> F: tools/arch/x86/intel_sdsi/
> F: tools/testing/selftests/drivers/sdsi/
>
> diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
> index 05a35f2f85b6..d48bb648f0b2 100644
> --- a/drivers/platform/x86/intel/sdsi.c
> +++ b/drivers/platform/x86/intel/sdsi.c
> @@ -22,24 +22,16 @@
> #include <linux/types.h>
> #include <linux/uaccess.h>
>
> +#include "sdsi.h"
> #include "vsec.h"
>
> #define ACCESS_TYPE_BARID 2
> #define ACCESS_TYPE_LOCAL 3
>
> #define SDSI_MIN_SIZE_DWORDS 276
> -#define SDSI_SIZE_MAILBOX 1024
> #define SDSI_SIZE_REGS 80
> #define SDSI_SIZE_CMD sizeof(u64)
>
> -/*
> - * Write messages are currently up to the size of the mailbox
> - * while read messages are up to 4 times the size of the
> - * mailbox, sent in packets
> - */
> -#define SDSI_SIZE_WRITE_MSG SDSI_SIZE_MAILBOX
> -#define SDSI_SIZE_READ_MSG (SDSI_SIZE_MAILBOX * 4)
> -
> #define SDSI_ENABLED_FEATURES_OFFSET 16
> #define SDSI_FEATURE_SDSI BIT(3)
> #define SDSI_FEATURE_METERING BIT(26)
> @@ -103,19 +95,6 @@ struct disc_table {
> u32 offset;
> };
>
> -struct sdsi_priv {
> - struct mutex mb_lock; /* Mailbox access lock */
> - struct device *dev;
> - void __iomem *control_addr;
> - void __iomem *mbox_addr;
> - void __iomem *regs_addr;
> - int control_size;
> - int maibox_size;
> - int registers_size;
> - u32 guid;
> - u32 features;
> -};
> -
> /* SDSi mailbox operations must be performed using 64bit mov instructions */
> static __always_inline void
> sdsi_memcpy64_toio(u64 __iomem *to, const u64 *from, size_t count_bytes)
> diff --git a/drivers/platform/x86/intel/sdsi.h b/drivers/platform/x86/intel/sdsi.h
> new file mode 100644
> index 000000000000..d0d7450c7b2b
> --- /dev/null
> +++ b/drivers/platform/x86/intel/sdsi.h
> @@ -0,0 +1,31 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __PDx86_SDSI_H_
> +#define __PDx86_SDSI_H_
> +#include <linux/mutex.h>
> +#include <linux/types.h>
> +
> +#define SDSI_SIZE_MAILBOX 1024
> +
> +/*
> + * Write messages are currently up to the size of the mailbox
> + * while read messages are up to 4 times the size of the
> + * mailbox, sent in packets
> + */
> +#define SDSI_SIZE_WRITE_MSG SDSI_SIZE_MAILBOX
> +#define SDSI_SIZE_READ_MSG (SDSI_SIZE_MAILBOX * 4)
> +
> +struct device;
> +
> +struct sdsi_priv {
> + struct mutex mb_lock; /* Mailbox access lock */
> + struct device *dev;
> + void __iomem *control_addr;
> + void __iomem *mbox_addr;
> + void __iomem *regs_addr;
> + int control_size;
> + int maibox_size;
> + int registers_size;
> + u32 guid;
> + u32 features;
> +};
> +#endif

--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer


Subject: Re: [PATCH 1/8] platform/x86/intel/sdsi: Set message size during writes


On 1/31/24 5:07 PM, David E. Box wrote:
> New mailbox commands will support sending multi packet writes and updated
> firmware now requires that the message size be written for all commands
> along with the packet size. Since the driver doesn't perform writes larger
> than the packet size, set the message size to the same value.
>
> Signed-off-by: David E. Box <[email protected]>
> ---

Reviewed-by: Kuppuswamy Sathyanarayanan <[email protected]>

> drivers/platform/x86/intel/sdsi.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
> index 556e7c6dbb05..a70c071de6e2 100644
> --- a/drivers/platform/x86/intel/sdsi.c
> +++ b/drivers/platform/x86/intel/sdsi.c
> @@ -252,6 +252,7 @@ static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *in
> FIELD_PREP(CTRL_SOM, 1) |
> FIELD_PREP(CTRL_RUN_BUSY, 1) |
> FIELD_PREP(CTRL_READ_WRITE, 1) |
> + FIELD_PREP(CTRL_MSG_SIZE, info->size) |
> FIELD_PREP(CTRL_PACKET_SIZE, info->size);
> writeq(control, priv->control_addr);
>

--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer