linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ben Widawsky <ben.widawsky@intel.com>
To: linux-cxl@vger.kernel.org
Cc: Ben Widawsky <ben.widawsky@intel.com>,
	linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-nvdimm@lists.01.org, linux-pci@vger.kernel.org,
	Bjorn Helgaas <helgaas@kernel.org>,
	Chris Browy <cbrowy@avery-design.com>,
	Christoph Hellwig <hch@infradead.org>,
	Dan Williams <dan.j.williams@intel.com>,
	Ira Weiny <ira.weiny@intel.com>, Jon Masters <jcm@jonmasters.org>,
	Jonathan Cameron <Jonathan.Cameron@Huawei.com>,
	Rafael Wysocki <rafael.j.wysocki@intel.com>,
	Randy Dunlap <rdunlap@infradead.org>,
	Vishal Verma <vishal.l.verma@intel.com>,
	daniel.lll@alibaba-inc.com,
	"John Groves (jgroves)" <jgroves@micron.com>,
	"Kelley, Sean V" <sean.v.kelley@intel.com>
Subject: [PATCH 09/14] cxl/mem: Add a "RAW" send command
Date: Fri, 29 Jan 2021 16:24:33 -0800	[thread overview]
Message-ID: <20210130002438.1872527-10-ben.widawsky@intel.com> (raw)
In-Reply-To: <20210130002438.1872527-1-ben.widawsky@intel.com>

The CXL memory device send interface will have a number of supported
commands. The raw command is not such a command. Raw commands allow
userspace to send a specified opcode to the underlying hardware and
bypass all driver checks on the command. This is useful for a couple of
usecases, mainly:
1. Undocumented vendor specific hardware commands
2. Prototyping new hardware commands not yet supported by the driver

While this all sounds very powerful it comes with a couple of caveats:
1. Bug reports using raw commands will not get the same level of
   attention as bug reports using supported commands (via taint).
2. Supported commands will be rejected by the RAW command.

With this comes new debugfs knob to allow full access to your toes with
your weapon of choice.

Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
---
 Documentation/ABI/testing/debugfs-cxl |  10 ++
 drivers/cxl/mem.c                     | 130 ++++++++++++++++++++++++--
 include/uapi/linux/cxl_mem.h          |  12 ++-
 3 files changed, 142 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/ABI/testing/debugfs-cxl

diff --git a/Documentation/ABI/testing/debugfs-cxl b/Documentation/ABI/testing/debugfs-cxl
new file mode 100644
index 000000000000..37e89aaac296
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-cxl
@@ -0,0 +1,10 @@
+What:		/sys/kernel/debug/cxl/mbox/raw_allow_all
+Date:		January 2021
+KernelVersion:	5.12
+Description:
+		Permits "RAW" mailbox commands to be passed through to hardware
+		without driver intervention. Many such commands require
+		coordination and therefore should only be used for debugging or
+		testing.
+
+		Valid values are boolean.
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index c646f0a1cf66..2942730dc967 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright(c) 2020 Intel Corporation. All rights reserved. */
 #include <uapi/linux/cxl_mem.h>
+#include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/cdev.h>
@@ -40,7 +41,14 @@
 
 enum opcode {
 	CXL_MBOX_OP_INVALID		= 0x0000,
+#define CXL_MBOX_OP_RAW		CXL_MBOX_OP_INVALID
+	CXL_MBOX_OP_ACTIVATE_FW		= 0x0202,
 	CXL_MBOX_OP_IDENTIFY		= 0x4000,
+	CXL_MBOX_OP_SET_PARTITION_INFO	= 0x4101,
+	CXL_MBOX_OP_SET_LSA		= 0x4103,
+	CXL_MBOX_OP_SET_SHUTDOWN_STATE	= 0x4204,
+	CXL_MBOX_OP_SCAN_MEDIA		= 0x4304,
+	CXL_MBOX_OP_GET_SCAN_MEDIA	= 0x4305,
 	CXL_MBOX_OP_MAX			= 0x10000
 };
 
@@ -90,6 +98,8 @@ struct cxl_memdev {
 
 static int cxl_mem_major;
 static DEFINE_IDA(cxl_memdev_ida);
+static struct dentry *cxl_debugfs;
+static bool raw_allow_all;
 
 /**
  * struct cxl_mem_command - Driver representation of a memory device command
@@ -139,6 +149,47 @@ struct cxl_mem_command {
 static struct cxl_mem_command mem_commands[] = {
 	CXL_CMD(INVALID, KERNEL, 0, 0, HIDDEN),
 	CXL_CMD(IDENTIFY, NONE, 0, 0x43, MANDATORY),
+	CXL_CMD(RAW, NONE, ~0, ~0, MANDATORY),
+};
+
+/*
+ * Commands that RAW doesn't permit. The rationale for each:
+ *
+ * CXL_MBOX_OP_ACTIVATE_FW: Firmware activation requires adjustment /
+ * coordination of transaction timeout values at the root bridge level.
+ *
+ * CXL_MBOX_OP_SET_PARTITION_INFO: The device memory map may change live
+ * and needs to be coordinated with HDM updates.
+ *
+ * CXL_MBOX_OP_SET_LSA: The label storage area may be cached by the
+ * driver and any writes from userspace invalidates those contents.
+ *
+ * CXL_MBOX_OP_SET_SHUTDOWN_STATE: Set shutdown state assumes no writes
+ * to the device after it is marked clean, userspace can not make that
+ * assertion.
+ *
+ * CXL_MBOX_OP_[GET_]SCAN_MEDIA: The kernel provides a native error list that
+ * is kept up to date with patrol notifications and error management.
+ */
+static u16 disabled_raw_commands[] = {
+	CXL_MBOX_OP_ACTIVATE_FW,
+	CXL_MBOX_OP_SET_PARTITION_INFO,
+	CXL_MBOX_OP_SET_LSA,
+	CXL_MBOX_OP_SET_SHUTDOWN_STATE,
+	CXL_MBOX_OP_SCAN_MEDIA,
+	CXL_MBOX_OP_GET_SCAN_MEDIA,
+};
+
+/*
+ * Command sets that RAW doesn't permit. All opcodes in this set are
+ * disabled because they pass plain text security payloads over the
+ * user/kernel boundary. This functionality is intended to be wrapped
+ * behind the keys ABI which allows for encrypted payloads in the UAPI
+ */
+static u8 security_command_sets[] = {
+	0x44, /* Sanitize */
+	0x45, /* Persistent Memory Data-at-rest Security */
+	0x46, /* Security Passthrough */
 };
 
 #define cxl_for_each_cmd(cmd)                                                  \
@@ -180,22 +231,30 @@ static int cxl_mem_wait_for_doorbell(struct cxl_mem *cxlm)
 	return 0;
 }
 
+static bool is_security_command(u16 opcode)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(security_command_sets); i++)
+		if (security_command_sets[i] == (opcode >> 8))
+			return true;
+	return false;
+}
+
 static void cxl_mem_mbox_timeout(struct cxl_mem *cxlm,
 				 struct mbox_cmd *mbox_cmd)
 {
-	dev_warn(&cxlm->pdev->dev, "Mailbox command timed out\n");
-	dev_info(&cxlm->pdev->dev,
-		 "\topcode: 0x%04x\n"
-		 "\tpayload size: %zub\n",
-		 mbox_cmd->opcode, mbox_cmd->size_in);
+	struct device *dev = &cxlm->pdev->dev;
+
+	dev_dbg(dev, "Mailbox command (opcode: %#x size: %zub) timed out\n",
+		mbox_cmd->opcode, mbox_cmd->size_in);
 
-	if (IS_ENABLED(CONFIG_CXL_MEM_INSECURE_DEBUG)) {
+	if (!is_security_command(mbox_cmd->opcode) ||
+	    IS_ENABLED(CONFIG_CXL_MEM_INSECURE_DEBUG)) {
 		print_hex_dump_debug("Payload ", DUMP_PREFIX_OFFSET, 16, 1,
 				     mbox_cmd->payload_in, mbox_cmd->size_in,
 				     true);
 	}
-
-	/* Here's a good place to figure out if a device reset is needed */
 }
 
 /**
@@ -458,6 +517,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev *cxlmd,
 					struct cxl_send_command __user *u)
 {
 	struct cxl_mem *cxlm = cxlmd->cxlm;
+	struct device *dev = &cxlmd->dev;
 	struct mbox_cmd mbox_cmd = {
 		.opcode = cmd->opcode,
 		.payload_in = NULL, /* Populated with copy_from_user() */
@@ -495,13 +555,17 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev *cxlmd,
 	if (rc)
 		goto out;
 
-	dev_dbg(&cxlmd->dev,
+	dev_dbg(dev,
 		"Submitting %s command for user\n"
 		"\topcode: %x\n"
 		"\tsize: %ub\n",
 		cxl_command_names[cmd->info.id].name, mbox_cmd.opcode,
 		cmd->info.size_in);
 
+	WARN_TAINT_ONCE(cmd->info.id == CXL_MEM_COMMAND_ID_RAW,
+			TAINT_RAW_PASSTHROUGH, "%s %s: raw command path used\n",
+			dev_driver_string(dev), dev_name(dev));
+
 	rc = cxl_mem_mbox_send_cmd(cxlm, &mbox_cmd);
 	cxl_mem_mbox_put(cxlm);
 	if (rc)
@@ -532,6 +596,23 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev *cxlmd,
 	return rc;
 }
 
+static bool cxl_mem_raw_command_allowed(u16 opcode)
+{
+	int i;
+
+	if (raw_allow_all)
+		return true;
+
+	if (is_security_command(opcode))
+		return false;
+
+	for (i = 0; i < ARRAY_SIZE(disabled_raw_commands); i++)
+		if (disabled_raw_commands[i] == opcode)
+			return false;
+
+	return true;
+}
+
 /**
  * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND.
  * @cxlm: &struct cxl_mem device whose mailbox will be used.
@@ -568,6 +649,30 @@ static int cxl_validate_cmd_from_user(struct cxl_mem *cxlm,
 	if (send_cmd->size_in > cxlm->mbox.payload_size)
 		return -EINVAL;
 
+	/* Checks are bypassed for raw commands but along comes the taint! */
+	if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) {
+		const struct cxl_mem_command temp = {
+			.info = {
+				.id = CXL_MEM_COMMAND_ID_RAW,
+				.flags = CXL_MEM_COMMAND_FLAG_NONE,
+				.size_in = send_cmd->size_in,
+				.size_out = send_cmd->size_out,
+			},
+			.flags = 0,
+			.opcode = send_cmd->raw.opcode
+		};
+
+		if (send_cmd->raw.rsvd)
+			return -EINVAL;
+
+		if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode))
+			return -EPERM;
+
+		memcpy(out_cmd, &temp, sizeof(temp));
+
+		return 0;
+	}
+
 	if (send_cmd->flags & ~CXL_MEM_COMMAND_FLAG_MASK)
 		return -EINVAL;
 
@@ -1200,6 +1305,7 @@ static __init int cxl_mem_init(void)
 {
 	int rc;
 	dev_t devt;
+	struct dentry *mbox_debugfs;
 
 	rc = alloc_chrdev_region(&devt, 0, CXL_MEM_MAX_DEVS, "cxl");
 	if (rc)
@@ -1214,11 +1320,17 @@ static __init int cxl_mem_init(void)
 		return rc;
 	}
 
+	cxl_debugfs = debugfs_create_dir("cxl", NULL);
+	mbox_debugfs = debugfs_create_dir("mbox", cxl_debugfs);
+	debugfs_create_bool("raw_allow_all", 0600, mbox_debugfs,
+			    &raw_allow_all);
+
 	return 0;
 }
 
 static __exit void cxl_mem_exit(void)
 {
+	debugfs_remove_recursive(cxl_debugfs);
 	pci_unregister_driver(&cxl_mem_driver);
 	unregister_chrdev_region(MKDEV(cxl_mem_major, 0), CXL_MEM_MAX_DEVS);
 }
diff --git a/include/uapi/linux/cxl_mem.h b/include/uapi/linux/cxl_mem.h
index 9d865794a420..25bfcb071c1f 100644
--- a/include/uapi/linux/cxl_mem.h
+++ b/include/uapi/linux/cxl_mem.h
@@ -33,6 +33,7 @@ extern "C" {
 #define CXL_CMDS                                                          \
 	___C(INVALID, "Invalid Command"),                                 \
 	___C(IDENTIFY, "Identify Command"),                               \
+	___C(RAW, "Raw device command"),                                  \
 	___C(MAX, "Last command")
 
 #define ___C(a, b) CXL_MEM_COMMAND_ID_##a
@@ -124,6 +125,9 @@ struct cxl_mem_query_commands {
  * @id: The command to send to the memory device. This must be one of the
  *	commands returned by the query command.
  * @flags: Flags for the command (input).
+ * @raw: Special fields for raw commands
+ * @raw.opcode: Opcode passed to hardware when using the RAW command.
+ * @raw.rsvd: Must be zero.
  * @rsvd: Must be zero.
  * @retval: Return value from the memory device (output).
  * @size_in: Size of the payload to provide to the device (input).
@@ -143,7 +147,13 @@ struct cxl_mem_query_commands {
 struct cxl_send_command {
 	__u32 id;
 	__u32 flags;
-	__u32 rsvd;
+	union {
+		struct {
+			__u16 opcode;
+			__u16 rsvd;
+		} raw;
+		__u32 rsvd;
+	};
 	__u32 retval;
 
 	struct {
-- 
2.30.0


  parent reply	other threads:[~2021-01-30 10:21 UTC|newest]

Thread overview: 96+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-30  0:24 [PATCH 00/14] CXL 2.0 Support Ben Widawsky
2021-01-30  0:24 ` [PATCH 01/14] cxl/mem: Introduce a driver for CXL-2.0-Type-3 endpoints Ben Widawsky
2021-01-30 23:51   ` David Rientjes
2021-02-01 17:21   ` Jonathan Cameron
2021-02-01 17:34   ` Konrad Rzeszutek Wilk
2021-02-02 17:58     ` Christoph Hellwig
2021-02-02 18:00   ` Christoph Hellwig
2021-01-30  0:24 ` [PATCH 02/14] cxl/mem: Map memory device registers Ben Widawsky
2021-01-30 23:51   ` David Rientjes
2021-02-01 16:46     ` Ben Widawsky
2021-02-01 18:19       ` Jonathan Cameron
2021-02-01 17:36   ` Konrad Rzeszutek Wilk
2021-02-02 18:04   ` Christoph Hellwig
2021-02-02 18:31     ` Ben Widawsky
2021-02-03 17:12       ` Christoph Hellwig
2021-01-30  0:24 ` [PATCH 03/14] cxl/mem: Find device capabilities Ben Widawsky
2021-01-30 23:51   ` David Rientjes
2021-02-01 16:53     ` Ben Widawsky
2021-02-01 21:51       ` David Rientjes
2021-02-01 21:58         ` Ben Widawsky
2021-02-01 22:23           ` David Rientjes
2021-02-01 22:28             ` Ben Widawsky
2021-02-01 22:33               ` Ben Widawsky
2021-02-01 22:45                 ` David Rientjes
2021-02-01 22:50                   ` Ben Widawsky
2021-02-01 23:09                     ` David Rientjes
2021-02-01 23:17                       ` Ben Widawsky
2021-02-01 23:58                         ` David Rientjes
2021-02-02  0:11                           ` Ben Widawsky
2021-02-02  0:14                             ` Dan Williams
2021-02-02  1:09                               ` David Rientjes
2021-02-01 22:02         ` Dan Williams
2021-02-01 17:41   ` Konrad Rzeszutek Wilk
2021-02-01 17:50     ` Ben Widawsky
2021-02-01 18:08       ` Konrad Rzeszutek Wilk
2021-02-02 18:10   ` Christoph Hellwig
2021-02-02 18:24     ` Ben Widawsky
2021-02-03 17:15       ` Christoph Hellwig
2021-02-03 17:23         ` Ben Widawsky
2021-02-03 21:23           ` Dan Williams
2021-02-04  7:16             ` Christoph Hellwig
2021-02-04 15:29               ` Ben Widawsky
2021-01-30  0:24 ` [PATCH 04/14] cxl/mem: Implement polled mode mailbox Ben Widawsky
2021-01-30 23:51   ` David Rientjes
2021-02-01 20:00     ` Dan Williams
2021-02-02 22:57       ` Ben Widawsky
2021-02-02 23:54         ` Dan Williams
2021-02-03  0:54           ` Ben Widawsky
2021-02-02 22:50     ` Ben Widawsky
2021-02-01 17:54   ` Konrad Rzeszutek Wilk
2021-02-01 19:13     ` Ben Widawsky
2021-02-01 19:28       ` Dan Williams
     [not found]         ` <SN6PR08MB46052FE9BC20A747CACD8F50D1B39@SN6PR08MB4605.namprd08.prod.outlook.com>
2021-02-04 22:24           ` [EXT] " Ben Widawsky
2021-01-30  0:24 ` [PATCH 05/14] cxl/mem: Register CXL memX devices Ben Widawsky
2021-01-30  0:31   ` Dan Williams
2021-01-30 23:52   ` David Rientjes
2021-02-01 17:10     ` Ben Widawsky
2021-02-01 21:53       ` David Rientjes
2021-02-01 21:55         ` Dan Williams
2021-02-02 18:13   ` Christoph Hellwig
2021-01-30  0:24 ` [PATCH 06/14] cxl/mem: Add basic IOCTL interface Ben Widawsky
2021-02-02 18:15   ` Christoph Hellwig
2021-02-02 18:33     ` Ben Widawsky
2021-01-30  0:24 ` [PATCH 07/14] cxl/mem: Add send command Ben Widawsky
2021-02-01 18:15   ` Konrad Rzeszutek Wilk
2021-02-02 23:08     ` Ben Widawsky
2021-01-30  0:24 ` [PATCH 08/14] taint: add taint for direct hardware access Ben Widawsky
2021-02-01 18:18   ` Konrad Rzeszutek Wilk
2021-02-01 18:34     ` Ben Widawsky
2021-02-01 19:01       ` Dan Williams
2021-02-02  2:49         ` Konrad Rzeszutek Wilk
2021-02-02 17:46           ` Dan Williams
2021-02-08 22:00   ` Dan Williams
2021-02-08 22:09     ` Kees Cook
2021-02-08 23:05       ` Ben Widawsky
2021-02-08 23:36       ` Dan Williams
2021-02-09  1:03         ` Dan Williams
2021-02-09  3:36           ` Ben Widawsky
2021-01-30  0:24 ` Ben Widawsky [this message]
2021-02-01 18:24   ` [PATCH 09/14] cxl/mem: Add a "RAW" send command Konrad Rzeszutek Wilk
2021-02-01 19:27     ` Ben Widawsky
2021-02-01 19:34       ` Konrad Rzeszutek Wilk
2021-02-01 21:20         ` Dan Williams
2021-01-30  0:24 ` [PATCH 10/14] cxl/mem: Create concept of enabled commands Ben Widawsky
2021-01-30  0:24 ` [PATCH 11/14] cxl/mem: Use CEL for enabling commands Ben Widawsky
2021-01-30  0:24 ` [PATCH 12/14] cxl/mem: Add set of informational commands Ben Widawsky
2021-01-30  0:24 ` [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h) Ben Widawsky
2021-02-01 18:28   ` Konrad Rzeszutek Wilk
2021-02-02 23:51     ` Ben Widawsky
2021-02-02 23:57       ` Dan Williams
2021-02-03 17:16         ` Ben Widawsky
2021-02-03 18:14           ` Konrad Rzeszutek Wilk
2021-02-03 20:31             ` Dan Williams
2021-02-04 18:55               ` Ben Widawsky
2021-02-04 21:01                 ` Dan Williams
2021-01-30  0:24 ` [PATCH 14/14] MAINTAINERS: Add maintainers of the CXL driver Ben Widawsky

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=20210130002438.1872527-10-ben.widawsky@intel.com \
    --to=ben.widawsky@intel.com \
    --cc=Jonathan.Cameron@Huawei.com \
    --cc=cbrowy@avery-design.com \
    --cc=dan.j.williams@intel.com \
    --cc=daniel.lll@alibaba-inc.com \
    --cc=hch@infradead.org \
    --cc=helgaas@kernel.org \
    --cc=ira.weiny@intel.com \
    --cc=jcm@jonmasters.org \
    --cc=jgroves@micron.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nvdimm@lists.01.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=rafael.j.wysocki@intel.com \
    --cc=rdunlap@infradead.org \
    --cc=sean.v.kelley@intel.com \
    --cc=vishal.l.verma@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).