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-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
	linux-acpi@vger.kernel.org, Ira Weiny <ira.weiny@intel.com>,
	Dan Williams <dan.j.williams@intel.com>,
	Vishal Verma <vishal.l.verma@intel.com>,
	"Kelley, Sean V" <sean.v.kelley@intel.com>,
	Rafael Wysocki <rafael.j.wysocki@intel.com>,
	Bjorn Helgaas <helgaas@kernel.org>,
	Jonathan Cameron <Jonathan.Cameron@Huawei.com>,
	Jon Masters <jcm@jonmasters.org>,
	Chris Browy <cbrowy@avery-design.com>,
	Randy Dunlap <rdunlap@infradead.org>,
	Christoph Hellwig <hch@infradead.org>
Subject: [RFC PATCH 10/14] cxl/mem: Add send command
Date: Tue,  8 Dec 2020 16:24:14 -0800	[thread overview]
Message-ID: <20201209002418.1976362-11-ben.widawsky@intel.com> (raw)
In-Reply-To: <20201209002418.1976362-1-ben.widawsky@intel.com>

The send command allows userspace to issue mailbox commands directly to
the hardware. The driver will verify basic properties of the command but
otherwise pass any input payload untouched to the hardware, and return
the output payload to userspace.

The caller of this IOCTL is required to allocate enough space for
max(size_in, size_out) of the payload. The payload input data will be
wiped out if any output payload exists.

Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
---
 drivers/cxl/mem.c            | 127 +++++++++++++++++++++++++++++++++++
 include/uapi/linux/cxl_mem.h |  35 ++++++++++
 2 files changed, 162 insertions(+)

diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 2c4aadcea0e4..0bf03afc0c80 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -324,6 +324,120 @@ static int cxl_mem_count_commands(void)
 	}
 
 	return n;
+};
+
+/**
+ * handle_mailbox_cmd_from_user() - Dispatch a mailbox command.
+ * @cxlmd: The CXL memory device to communicate with.
+ * @cmd: The validated command
+ * @u: The command submitted by userspace. Only useful for RAW commands.
+ *
+ * Return: 0 on success.
+ *
+ * This function packages up a &struct mbox_cmd on behalf of userspace,
+ * dispatches the command, and returns the results.
+ */
+static int handle_mailbox_cmd_from_user(struct cxl_memdev *cxlmd,
+					const struct cxl_mem_command *cmd,
+					struct cxl_send_command __user *u)
+{
+	struct mbox_cmd mbox_cmd;
+	ssize_t payload_size;
+	void *payload;
+	u32 size_out;
+	int rc;
+
+	if (get_user(size_out, &u->size_out))
+		return -EFAULT;
+
+	payload_size = max_t(ssize_t, cmd->info.size_in, size_out);
+	if (payload_size) {
+		payload =
+			memdup_user(u64_to_user_ptr(u->payload), payload_size);
+		if (IS_ERR(payload))
+			return PTR_ERR(payload);
+	}
+
+	rc = cxl_mem_mbox_get(cxlmd->cxlm);
+	if (rc)
+		return rc;
+
+	mbox_cmd = (struct mbox_cmd){
+		.opcode = cmd->opcode,
+		.payload = payload,
+		.size_in = cmd->info.size_in,
+		.size_out = size_out,
+	};
+	rc = cxl_mem_mbox_send_cmd(cxlmd->cxlm, &mbox_cmd);
+	cxl_mem_mbox_put(cxlmd->cxlm);
+	if (rc)
+		goto out;
+
+	rc = put_user(mbox_cmd.return_code, &u->retval);
+	if (rc)
+		goto out;
+
+	rc = put_user(mbox_cmd.size_out, &u->size_out);
+	if (rc)
+		goto out;
+
+	if (mbox_cmd.size_out)
+		if (copy_to_user(u64_to_user_ptr(u->payload), payload,
+				 mbox_cmd.size_out))
+			rc = -EFAULT;
+
+out:
+	if (payload_size)
+		kfree(payload);
+	return rc;
+}
+
+/**
+ * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND.
+ * @user_cmd: &struct cxl_send_command from userspace.
+ * @out_cmd: Sanitized and populared &struct cxl_mem_command.
+ *
+ * Return:
+ *  * %0	- Command dispatched successfully.
+ *  * %-EFAULT	- Something happened with copy_to/from_user.
+ *  * %-EINVAL	- Rerserved fields were used.
+ *  * %-EPERM	- Protected command used by the RAW interface.
+ *  * %-ENOMEM	- Input or output buffer wasn't large enough.
+ *
+ */
+static int cxl_validate_cmd_from_user(struct cxl_send_command __user *user_cmd,
+				      struct cxl_mem_command *out_cmd)
+{
+	const struct cxl_command_info *info;
+	struct cxl_send_command cmd;
+	struct cxl_mem_command *c;
+
+	if (copy_from_user(&cmd, user_cmd, sizeof(cmd)))
+		return -EFAULT;
+
+	if (cmd.id == 0 || cmd.id >= CXL_MEM_COMMAND_ID_MAX)
+		return -EINVAL;
+
+	c = &mem_commands[cmd.id];
+	info = &c->info;
+
+	if (cmd.flags & CXL_MEM_COMMAND_FLAG_MASK)
+		return -EINVAL;
+
+	if (cmd.rsvd)
+		return -EINVAL;
+
+	/* Check the input buffer is the expected size */
+	if (info->size_in >= 0 && info->size_in != cmd.size_in)
+		return -ENOMEM;
+
+	/* Check the output buffer is at least large enough */
+	if (info->size_out >= 0 && cmd.size_out < info->size_out)
+		return -ENOMEM;
+
+	memcpy(out_cmd, c, sizeof(*c));
+
+	return 0;
 }
 
 static long cxl_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -357,6 +471,19 @@ static long cxl_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg
 
 			j++;
 		}
+
+		return 0;
+	} else if (cmd == CXL_MEM_SEND_COMMAND) {
+		struct cxl_send_command __user *u = (void __user *)arg;
+		struct cxl_memdev *cxlmd = file->private_data;
+		struct cxl_mem_command c;
+		int rc;
+
+		rc = cxl_validate_cmd_from_user(u, &c);
+		if (rc)
+			return rc;
+
+		return handle_mailbox_cmd_from_user(cxlmd, &c, u);
 	}
 
 	return -ENOTTY;
diff --git a/include/uapi/linux/cxl_mem.h b/include/uapi/linux/cxl_mem.h
index 1d1e143f98ec..189d86a13637 100644
--- a/include/uapi/linux/cxl_mem.h
+++ b/include/uapi/linux/cxl_mem.h
@@ -19,6 +19,7 @@ extern "C" {
  */
 
 #define CXL_MEM_QUERY_COMMANDS _IOR('C', 1, struct cxl_mem_query_commands)
+#define CXL_MEM_SEND_COMMAND _IOWR('C', 2, struct cxl_send_command)
 
 #define CXL_MEM_COMMAND_NAME_LENGTH 32
 
@@ -48,10 +49,12 @@ extern "C" {
 struct cxl_command_info {
 	__u32 id;
 #define CXL_MEM_COMMAND_ID_INVALID 0
+#define CXL_MEM_COMMAND_ID_MAX (CXL_MEM_COMMAND_ID_INVALID + 1)
 
 	__u32 flags;
 #define CXL_MEM_COMMAND_FLAG_NONE 0
 #define CXL_MEM_COMMAND_FLAG_TAINT BIT(0)
+#define CXL_MEM_COMMAND_FLAG_MASK ~BIT(0)
 
 	__s32 size_in;
 	__s32 size_out;
@@ -95,6 +98,38 @@ struct cxl_mem_query_commands {
 	struct cxl_command_info __user commands[]; /* out: supported commands */
 };
 
+/**
+ * struct cxl_send_command - Send a command to a memory device.
+ * @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
+ * @rsvd: Reserved for future use.
+ * @retval: Return value from the memory device (output).
+ * @size_in: Size of the payload to provide to the device (input).
+ * @size_out: Size of the payload received from the device (input/output). This
+ *	      field is filled in my userspace to let the driver know how much
+ *	      space was allocated for output. It is populated by the driver to
+ *	      let userspace know how large the output payload actually was.
+ * @payload: Pointer to memory available for payload input/output.
+ *
+ * Mechanism for userspace to send a command to the hardware for processing. The
+ * driver will do basic validation on the command sizes, but the payload input
+ * and output are not introspected. Userspace is required to allocate large
+ * enough buffers for max(size_in, size_out).
+ */
+struct cxl_send_command {
+	__u32 id;
+	__u32 flags;
+	__u32 rsvd;
+	__u32 retval;
+
+	struct {
+		__s32 size_in;
+		__s32 size_out;
+		__u64 payload;
+	};
+};
+
 #if defined(__cplusplus)
 }
 #endif
-- 
2.29.2


  parent reply	other threads:[~2020-12-09  0:28 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-09  0:24 [RFC PATCH v2 00/14] CXL 2.0 Support Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH v2 01/14] docs: cxl: Add basic documentation Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH v2 02/14] cxl/acpi: Add an acpi_cxl module for the CXL interconnect Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH v2 03/14] cxl/acpi: add OSC support Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH v2 04/14] cxl/mem: Introduce a driver for CXL-2.0-Type-3 endpoints Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH v2 05/14] cxl/mem: Map memory device registers Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH v2 06/14] cxl/mem: Find device capabilities Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH v2 07/14] cxl/mem: Implement polled mode mailbox Ben Widawsky
2021-01-07 19:05   ` Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH v2 08/14] cxl/mem: Register CXL memX devices Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH 09/14] cxl/mem: Add basic IOCTL interface Ben Widawsky
2020-12-09  1:37   ` Dan Williams
2020-12-09  2:12     ` Ben Widawsky
2020-12-09  3:33       ` Dan Williams
2020-12-09 16:23         ` Ben Widawsky
2020-12-10  3:32   ` Randy Dunlap
2020-12-14 17:29     ` Ben Widawsky
2020-12-09  0:24 ` Ben Widawsky [this message]
2020-12-09 22:06   ` [RFC PATCH 10/14] cxl/mem: Add send command Dan Williams
2020-12-15 21:43     ` Ben Widawsky
2020-12-15 22:03       ` Dan Williams
2020-12-15 22:17         ` Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH 11/14] cxl/mem: Add a "RAW" " Ben Widawsky
2020-12-09 22:38   ` Dan Williams
2020-12-16 20:42     ` Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH 12/14] cxl: Add basic debugging Ben Widawsky
2020-12-09  1:17   ` Dan Williams
2020-12-09  2:04     ` Ben Widawsky
2020-12-09  3:06       ` Dan Williams
2020-12-16 21:02         ` Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH 13/14] MAINTAINERS: Add maintainers of the CXL driver Ben Widawsky
2020-12-09  0:24 ` [RFC PATCH 14/14] WIP/cxl/mem: Add get firmware for testing Ben Widawsky
2020-12-10  0:42   ` Dan Williams
2020-12-09  0:33 ` [RFC PATCH v2 00/14] CXL 2.0 Support Verma, Vishal L
2020-12-09  0:47 ` 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=20201209002418.1976362-11-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=hch@infradead.org \
    --cc=helgaas@kernel.org \
    --cc=ira.weiny@intel.com \
    --cc=jcm@jonmasters.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.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).