1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2020 Intel Corporation. All rights reserved. */
3 #include <linux/security.h>
4 #include <linux/debugfs.h>
5 #include <linux/ktime.h>
6 #include <linux/mutex.h>
7 #include <linux/unaligned.h>
8 #include <cxlpci.h>
9 #include <cxlmem.h>
10 #include <cxl.h>
11
12 #include "core.h"
13 #include "trace.h"
14
15 static bool cxl_raw_allow_all;
16
17 /**
18 * DOC: cxl mbox
19 *
20 * Core implementation of the CXL 2.0 Type-3 Memory Device Mailbox. The
21 * implementation is used by the cxl_pci driver to initialize the device
22 * and implement the cxl_mem.h IOCTL UAPI. It also implements the
23 * backend of the cxl_pmem_ctl() transport for LIBNVDIMM.
24 */
25
26 #define cxl_for_each_cmd(cmd) \
27 for ((cmd) = &cxl_mem_commands[0]; \
28 ((cmd) - cxl_mem_commands) < ARRAY_SIZE(cxl_mem_commands); (cmd)++)
29
30 #define CXL_CMD(_id, sin, sout, _flags) \
31 [CXL_MEM_COMMAND_ID_##_id] = { \
32 .info = { \
33 .id = CXL_MEM_COMMAND_ID_##_id, \
34 .size_in = sin, \
35 .size_out = sout, \
36 }, \
37 .opcode = CXL_MBOX_OP_##_id, \
38 .flags = _flags, \
39 }
40
41 #define CXL_VARIABLE_PAYLOAD ~0U
42 /*
43 * This table defines the supported mailbox commands for the driver. This table
44 * is made up of a UAPI structure. Non-negative values as parameters in the
45 * table will be validated against the user's input. For example, if size_in is
46 * 0, and the user passed in 1, it is an error.
47 */
48 static struct cxl_mem_command cxl_mem_commands[CXL_MEM_COMMAND_ID_MAX] = {
49 CXL_CMD(IDENTIFY, 0, 0x43, CXL_CMD_FLAG_FORCE_ENABLE),
50 #ifdef CONFIG_CXL_MEM_RAW_COMMANDS
51 CXL_CMD(RAW, CXL_VARIABLE_PAYLOAD, CXL_VARIABLE_PAYLOAD, 0),
52 #endif
53 CXL_CMD(GET_SUPPORTED_LOGS, 0, CXL_VARIABLE_PAYLOAD, CXL_CMD_FLAG_FORCE_ENABLE),
54 CXL_CMD(GET_FW_INFO, 0, 0x50, 0),
55 CXL_CMD(GET_PARTITION_INFO, 0, 0x20, 0),
56 CXL_CMD(GET_LSA, 0x8, CXL_VARIABLE_PAYLOAD, 0),
57 CXL_CMD(GET_HEALTH_INFO, 0, 0x12, 0),
58 CXL_CMD(GET_LOG, 0x18, CXL_VARIABLE_PAYLOAD, CXL_CMD_FLAG_FORCE_ENABLE),
59 CXL_CMD(GET_LOG_CAPS, 0x10, 0x4, 0),
60 CXL_CMD(CLEAR_LOG, 0x10, 0, 0),
61 CXL_CMD(GET_SUP_LOG_SUBLIST, 0x2, CXL_VARIABLE_PAYLOAD, 0),
62 CXL_CMD(SET_PARTITION_INFO, 0x0a, 0, 0),
63 CXL_CMD(SET_LSA, CXL_VARIABLE_PAYLOAD, 0, 0),
64 CXL_CMD(GET_ALERT_CONFIG, 0, 0x10, 0),
65 CXL_CMD(SET_ALERT_CONFIG, 0xc, 0, 0),
66 CXL_CMD(GET_SHUTDOWN_STATE, 0, 0x1, 0),
67 CXL_CMD(SET_SHUTDOWN_STATE, 0x1, 0, 0),
68 CXL_CMD(GET_SCAN_MEDIA_CAPS, 0x10, 0x4, 0),
69 CXL_CMD(GET_TIMESTAMP, 0, 0x8, 0),
70 };
71
72 /*
73 * Commands that RAW doesn't permit. The rationale for each:
74 *
75 * CXL_MBOX_OP_ACTIVATE_FW: Firmware activation requires adjustment /
76 * coordination of transaction timeout values at the root bridge level.
77 *
78 * CXL_MBOX_OP_SET_PARTITION_INFO: The device memory map may change live
79 * and needs to be coordinated with HDM updates.
80 *
81 * CXL_MBOX_OP_SET_LSA: The label storage area may be cached by the
82 * driver and any writes from userspace invalidates those contents.
83 *
84 * CXL_MBOX_OP_SET_SHUTDOWN_STATE: Set shutdown state assumes no writes
85 * to the device after it is marked clean, userspace can not make that
86 * assertion.
87 *
88 * CXL_MBOX_OP_[GET_]SCAN_MEDIA: The kernel provides a native error list that
89 * is kept up to date with patrol notifications and error management.
90 *
91 * CXL_MBOX_OP_[GET_,INJECT_,CLEAR_]POISON: These commands require kernel
92 * driver orchestration for safety.
93 *
94 * CXL_MBOX_OP_[GET_SUPPORTED_FEATURES,GET_FEATURE,SET_FEATURE]: Features are
95 * accessed through the fwctl ABI, which applies scope-based access control.
96 * The RAW path would bypass those checks, so it is not permitted here.
97 */
98 static u16 cxl_disabled_raw_commands[] = {
99 CXL_MBOX_OP_ACTIVATE_FW,
100 CXL_MBOX_OP_SET_PARTITION_INFO,
101 CXL_MBOX_OP_SET_LSA,
102 CXL_MBOX_OP_SET_SHUTDOWN_STATE,
103 CXL_MBOX_OP_SCAN_MEDIA,
104 CXL_MBOX_OP_GET_SCAN_MEDIA,
105 CXL_MBOX_OP_GET_POISON,
106 CXL_MBOX_OP_INJECT_POISON,
107 CXL_MBOX_OP_CLEAR_POISON,
108 CXL_MBOX_OP_GET_SUPPORTED_FEATURES,
109 CXL_MBOX_OP_GET_FEATURE,
110 CXL_MBOX_OP_SET_FEATURE,
111 };
112
113 /*
114 * Command sets that RAW doesn't permit. All opcodes in this set are
115 * disabled because they pass plain text security payloads over the
116 * user/kernel boundary. This functionality is intended to be wrapped
117 * behind the keys ABI which allows for encrypted payloads in the UAPI
118 */
119 static u8 security_command_sets[] = {
120 0x44, /* Sanitize */
121 0x45, /* Persistent Memory Data-at-rest Security */
122 0x46, /* Security Passthrough */
123 };
124
cxl_is_security_command(u16 opcode)125 static bool cxl_is_security_command(u16 opcode)
126 {
127 int i;
128
129 for (i = 0; i < ARRAY_SIZE(security_command_sets); i++)
130 if (security_command_sets[i] == (opcode >> 8))
131 return true;
132 return false;
133 }
134
cxl_set_security_cmd_enabled(struct cxl_security_state * security,u16 opcode)135 static void cxl_set_security_cmd_enabled(struct cxl_security_state *security,
136 u16 opcode)
137 {
138 switch (opcode) {
139 case CXL_MBOX_OP_SANITIZE:
140 set_bit(CXL_SEC_ENABLED_SANITIZE, security->enabled_cmds);
141 break;
142 case CXL_MBOX_OP_SECURE_ERASE:
143 set_bit(CXL_SEC_ENABLED_SECURE_ERASE,
144 security->enabled_cmds);
145 break;
146 case CXL_MBOX_OP_GET_SECURITY_STATE:
147 set_bit(CXL_SEC_ENABLED_GET_SECURITY_STATE,
148 security->enabled_cmds);
149 break;
150 case CXL_MBOX_OP_SET_PASSPHRASE:
151 set_bit(CXL_SEC_ENABLED_SET_PASSPHRASE,
152 security->enabled_cmds);
153 break;
154 case CXL_MBOX_OP_DISABLE_PASSPHRASE:
155 set_bit(CXL_SEC_ENABLED_DISABLE_PASSPHRASE,
156 security->enabled_cmds);
157 break;
158 case CXL_MBOX_OP_UNLOCK:
159 set_bit(CXL_SEC_ENABLED_UNLOCK, security->enabled_cmds);
160 break;
161 case CXL_MBOX_OP_FREEZE_SECURITY:
162 set_bit(CXL_SEC_ENABLED_FREEZE_SECURITY,
163 security->enabled_cmds);
164 break;
165 case CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE:
166 set_bit(CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE,
167 security->enabled_cmds);
168 break;
169 default:
170 break;
171 }
172 }
173
cxl_is_poison_command(u16 opcode)174 static bool cxl_is_poison_command(u16 opcode)
175 {
176 #define CXL_MBOX_OP_POISON_CMDS 0x43
177
178 if ((opcode >> 8) == CXL_MBOX_OP_POISON_CMDS)
179 return true;
180
181 return false;
182 }
183
cxl_set_poison_cmd_enabled(struct cxl_poison_state * poison,u16 opcode)184 static void cxl_set_poison_cmd_enabled(struct cxl_poison_state *poison,
185 u16 opcode)
186 {
187 switch (opcode) {
188 case CXL_MBOX_OP_GET_POISON:
189 set_bit(CXL_POISON_ENABLED_LIST, poison->enabled_cmds);
190 break;
191 case CXL_MBOX_OP_INJECT_POISON:
192 set_bit(CXL_POISON_ENABLED_INJECT, poison->enabled_cmds);
193 break;
194 case CXL_MBOX_OP_CLEAR_POISON:
195 set_bit(CXL_POISON_ENABLED_CLEAR, poison->enabled_cmds);
196 break;
197 case CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS:
198 set_bit(CXL_POISON_ENABLED_SCAN_CAPS, poison->enabled_cmds);
199 break;
200 case CXL_MBOX_OP_SCAN_MEDIA:
201 set_bit(CXL_POISON_ENABLED_SCAN_MEDIA, poison->enabled_cmds);
202 break;
203 case CXL_MBOX_OP_GET_SCAN_MEDIA:
204 set_bit(CXL_POISON_ENABLED_SCAN_RESULTS, poison->enabled_cmds);
205 break;
206 default:
207 break;
208 }
209 }
210
cxl_mem_find_command(u16 opcode)211 static struct cxl_mem_command *cxl_mem_find_command(u16 opcode)
212 {
213 struct cxl_mem_command *c;
214
215 cxl_for_each_cmd(c)
216 if (c->opcode == opcode)
217 return c;
218
219 return NULL;
220 }
221
cxl_mem_opcode_to_name(u16 opcode)222 static const char *cxl_mem_opcode_to_name(u16 opcode)
223 {
224 struct cxl_mem_command *c;
225
226 c = cxl_mem_find_command(opcode);
227 if (!c)
228 return NULL;
229
230 return cxl_command_names[c->info.id].name;
231 }
232
233 /**
234 * cxl_internal_send_cmd() - Kernel internal interface to send a mailbox command
235 * @cxl_mbox: CXL mailbox context
236 * @mbox_cmd: initialized command to execute
237 *
238 * Context: Any context.
239 * Return:
240 * * %>=0 - Number of bytes returned in @out.
241 * * %-E2BIG - Payload is too large for hardware.
242 * * %-EBUSY - Couldn't acquire exclusive mailbox access.
243 * * %-EFAULT - Hardware error occurred.
244 * * %-ENXIO - Command completed, but device reported an error.
245 * * %-EIO - Unexpected output size.
246 *
247 * Mailbox commands may execute successfully yet the device itself reported an
248 * error. While this distinction can be useful for commands from userspace, the
249 * kernel will only be able to use results when both are successful.
250 */
cxl_internal_send_cmd(struct cxl_mailbox * cxl_mbox,struct cxl_mbox_cmd * mbox_cmd)251 int cxl_internal_send_cmd(struct cxl_mailbox *cxl_mbox,
252 struct cxl_mbox_cmd *mbox_cmd)
253 {
254 size_t out_size, min_out;
255 int rc;
256
257 if (mbox_cmd->size_in > cxl_mbox->payload_size ||
258 mbox_cmd->size_out > cxl_mbox->payload_size)
259 return -E2BIG;
260
261 out_size = mbox_cmd->size_out;
262 min_out = mbox_cmd->min_out;
263 rc = cxl_mbox->mbox_send(cxl_mbox, mbox_cmd);
264 /*
265 * EIO is reserved for a payload size mismatch and mbox_send()
266 * may not return this error.
267 */
268 if (WARN_ONCE(rc == -EIO, "Bad return code: -EIO"))
269 return -ENXIO;
270 if (rc)
271 return rc;
272
273 if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS &&
274 mbox_cmd->return_code != CXL_MBOX_CMD_RC_BACKGROUND)
275 return cxl_mbox_cmd_rc2errno(mbox_cmd);
276
277 if (!out_size)
278 return 0;
279
280 /*
281 * Variable sized output needs to at least satisfy the caller's
282 * minimum if not the fully requested size.
283 */
284 if (min_out == 0)
285 min_out = out_size;
286
287 if (mbox_cmd->size_out < min_out)
288 return -EIO;
289 return 0;
290 }
291 EXPORT_SYMBOL_NS_GPL(cxl_internal_send_cmd, "CXL");
292
cxl_mem_raw_command_allowed(u16 opcode)293 static bool cxl_mem_raw_command_allowed(u16 opcode)
294 {
295 int i;
296
297 if (!IS_ENABLED(CONFIG_CXL_MEM_RAW_COMMANDS))
298 return false;
299
300 if (security_locked_down(LOCKDOWN_PCI_ACCESS))
301 return false;
302
303 if (cxl_raw_allow_all)
304 return true;
305
306 if (cxl_is_security_command(opcode))
307 return false;
308
309 for (i = 0; i < ARRAY_SIZE(cxl_disabled_raw_commands); i++)
310 if (cxl_disabled_raw_commands[i] == opcode)
311 return false;
312
313 return true;
314 }
315
316 /**
317 * cxl_payload_from_user_allowed() - Check contents of in_payload.
318 * @opcode: The mailbox command opcode.
319 * @payload_in: Pointer to the input payload passed in from user space.
320 * @in_size: Size of @payload_in in bytes.
321 *
322 * Return:
323 * * true - payload_in passes check for @opcode.
324 * * false - payload_in contains invalid or unsupported values.
325 *
326 * The driver may inspect payload contents before sending a mailbox
327 * command from user space to the device. The intent is to reject
328 * commands with input payloads that are known to be unsafe. This
329 * check is not intended to replace the users careful selection of
330 * mailbox command parameters and makes no guarantee that the user
331 * command will succeed, nor that it is appropriate.
332 *
333 * The specific checks are determined by the opcode.
334 */
cxl_payload_from_user_allowed(u16 opcode,void * payload_in,size_t in_size)335 static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in,
336 size_t in_size)
337 {
338 switch (opcode) {
339 case CXL_MBOX_OP_SET_PARTITION_INFO: {
340 struct cxl_mbox_set_partition_info *pi = payload_in;
341
342 if (in_size < sizeof(*pi))
343 return false;
344 if (pi->flags & CXL_SET_PARTITION_IMMEDIATE_FLAG)
345 return false;
346 break;
347 }
348 case CXL_MBOX_OP_CLEAR_LOG: {
349 const uuid_t *uuid = (uuid_t *)payload_in;
350
351 if (in_size < sizeof(uuid_t))
352 return false;
353 /*
354 * Restrict the ‘Clear log’ action to only apply to
355 * Vendor debug logs.
356 */
357 return uuid_equal(uuid, &DEFINE_CXL_VENDOR_DEBUG_UUID);
358 }
359 default:
360 break;
361 }
362 return true;
363 }
364
cxl_mbox_cmd_ctor(struct cxl_mbox_cmd * mbox_cmd,struct cxl_mailbox * cxl_mbox,u16 opcode,size_t in_size,size_t out_size,u64 in_payload)365 static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox_cmd,
366 struct cxl_mailbox *cxl_mbox, u16 opcode,
367 size_t in_size, size_t out_size, u64 in_payload)
368 {
369 *mbox_cmd = (struct cxl_mbox_cmd) {
370 .opcode = opcode,
371 .size_in = in_size,
372 };
373
374 if (in_size) {
375 mbox_cmd->payload_in = vmemdup_user(u64_to_user_ptr(in_payload),
376 in_size);
377 if (IS_ERR(mbox_cmd->payload_in))
378 return PTR_ERR(mbox_cmd->payload_in);
379
380 if (!cxl_payload_from_user_allowed(opcode, mbox_cmd->payload_in,
381 in_size)) {
382 dev_dbg(cxl_mbox->host, "%s: input payload not allowed\n",
383 cxl_mem_opcode_to_name(opcode));
384 kvfree(mbox_cmd->payload_in);
385 return -EBUSY;
386 }
387 }
388
389 mbox_cmd->size_out = min_t(size_t, out_size, cxl_mbox->payload_size);
390
391 if (mbox_cmd->size_out) {
392 mbox_cmd->payload_out = kvzalloc(mbox_cmd->size_out, GFP_KERNEL);
393 if (!mbox_cmd->payload_out) {
394 kvfree(mbox_cmd->payload_in);
395 return -ENOMEM;
396 }
397 }
398 return 0;
399 }
400
cxl_mbox_cmd_dtor(struct cxl_mbox_cmd * mbox)401 static void cxl_mbox_cmd_dtor(struct cxl_mbox_cmd *mbox)
402 {
403 kvfree(mbox->payload_in);
404 kvfree(mbox->payload_out);
405 }
406
cxl_to_mem_cmd_raw(struct cxl_mem_command * mem_cmd,const struct cxl_send_command * send_cmd,struct cxl_mailbox * cxl_mbox)407 static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
408 const struct cxl_send_command *send_cmd,
409 struct cxl_mailbox *cxl_mbox)
410 {
411 if (send_cmd->raw.rsvd)
412 return -EINVAL;
413
414 /*
415 * Unlike supported commands, the output size of RAW commands
416 * gets passed along without further checking, so it must be
417 * validated here.
418 */
419 if (send_cmd->out.size > cxl_mbox->payload_size)
420 return -EINVAL;
421
422 if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode))
423 return -EPERM;
424
425 dev_WARN_ONCE(cxl_mbox->host, true, "raw command path used\n");
426
427 *mem_cmd = (struct cxl_mem_command) {
428 .info = {
429 .id = CXL_MEM_COMMAND_ID_RAW,
430 .size_in = send_cmd->in.size,
431 .size_out = send_cmd->out.size,
432 },
433 .opcode = send_cmd->raw.opcode
434 };
435
436 return 0;
437 }
438
cxl_to_mem_cmd(struct cxl_mem_command * mem_cmd,const struct cxl_send_command * send_cmd,struct cxl_mailbox * cxl_mbox)439 static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
440 const struct cxl_send_command *send_cmd,
441 struct cxl_mailbox *cxl_mbox)
442 {
443 struct cxl_mem_command *c = &cxl_mem_commands[send_cmd->id];
444 const struct cxl_command_info *info = &c->info;
445
446 if (send_cmd->flags & ~CXL_MEM_COMMAND_FLAG_MASK)
447 return -EINVAL;
448
449 if (send_cmd->rsvd)
450 return -EINVAL;
451
452 if (send_cmd->in.rsvd || send_cmd->out.rsvd)
453 return -EINVAL;
454
455 /* Check that the command is enabled for hardware */
456 if (!test_bit(info->id, cxl_mbox->enabled_cmds))
457 return -ENOTTY;
458
459 /* Check that the command is not claimed for exclusive kernel use */
460 if (test_bit(info->id, cxl_mbox->exclusive_cmds))
461 return -EBUSY;
462
463 /* Check the input buffer is the expected size */
464 if ((info->size_in != CXL_VARIABLE_PAYLOAD) &&
465 (info->size_in != send_cmd->in.size))
466 return -ENOMEM;
467
468 /* Check the output buffer is at least large enough */
469 if ((info->size_out != CXL_VARIABLE_PAYLOAD) &&
470 (send_cmd->out.size < info->size_out))
471 return -ENOMEM;
472
473 *mem_cmd = (struct cxl_mem_command) {
474 .info = {
475 .id = info->id,
476 .flags = info->flags,
477 .size_in = send_cmd->in.size,
478 .size_out = send_cmd->out.size,
479 },
480 .opcode = c->opcode
481 };
482
483 return 0;
484 }
485
486 /**
487 * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND.
488 * @mbox_cmd: Sanitized and populated &struct cxl_mbox_cmd.
489 * @cxl_mbox: CXL mailbox context
490 * @send_cmd: &struct cxl_send_command copied in from userspace.
491 *
492 * Return:
493 * * %0 - @out_cmd is ready to send.
494 * * %-ENOTTY - Invalid command specified.
495 * * %-EINVAL - Reserved fields or invalid values were used.
496 * * %-ENOMEM - Input or output buffer wasn't sized properly.
497 * * %-EPERM - Attempted to use a protected command.
498 * * %-EBUSY - Kernel has claimed exclusive access to this opcode
499 *
500 * The result of this command is a fully validated command in @mbox_cmd that is
501 * safe to send to the hardware.
502 */
cxl_validate_cmd_from_user(struct cxl_mbox_cmd * mbox_cmd,struct cxl_mailbox * cxl_mbox,const struct cxl_send_command * send_cmd)503 static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
504 struct cxl_mailbox *cxl_mbox,
505 const struct cxl_send_command *send_cmd)
506 {
507 struct cxl_mem_command mem_cmd;
508 int rc;
509
510 if (send_cmd->id == 0 || send_cmd->id >= CXL_MEM_COMMAND_ID_MAX)
511 return -ENOTTY;
512
513 /*
514 * The user can never specify an input payload larger than what hardware
515 * supports, but output can be arbitrarily large (simply write out as
516 * much data as the hardware provides).
517 */
518 if (send_cmd->in.size > cxl_mbox->payload_size)
519 return -EINVAL;
520
521 /* Sanitize and construct a cxl_mem_command */
522 if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW)
523 rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, cxl_mbox);
524 else
525 rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, cxl_mbox);
526
527 if (rc)
528 return rc;
529
530 /* Sanitize and construct a cxl_mbox_cmd */
531 return cxl_mbox_cmd_ctor(mbox_cmd, cxl_mbox, mem_cmd.opcode,
532 mem_cmd.info.size_in, mem_cmd.info.size_out,
533 send_cmd->in.payload);
534 }
535
cxl_query_cmd(struct cxl_mailbox * cxl_mbox,struct cxl_mem_query_commands __user * q)536 int cxl_query_cmd(struct cxl_mailbox *cxl_mbox,
537 struct cxl_mem_query_commands __user *q)
538 {
539 struct device *dev = cxl_mbox->host;
540 struct cxl_mem_command *cmd;
541 u32 n_commands;
542 int j = 0;
543
544 dev_dbg(dev, "Query IOCTL\n");
545
546 if (get_user(n_commands, &q->n_commands))
547 return -EFAULT;
548
549 /* returns the total number if 0 elements are requested. */
550 if (n_commands == 0)
551 return put_user(ARRAY_SIZE(cxl_mem_commands), &q->n_commands);
552
553 /*
554 * otherwise, return min(n_commands, total commands) cxl_command_info
555 * structures.
556 */
557 cxl_for_each_cmd(cmd) {
558 struct cxl_command_info info = cmd->info;
559
560 if (test_bit(info.id, cxl_mbox->enabled_cmds))
561 info.flags |= CXL_MEM_COMMAND_FLAG_ENABLED;
562 if (test_bit(info.id, cxl_mbox->exclusive_cmds))
563 info.flags |= CXL_MEM_COMMAND_FLAG_EXCLUSIVE;
564
565 if (copy_to_user(&q->commands[j++], &info, sizeof(info)))
566 return -EFAULT;
567
568 if (j == n_commands)
569 break;
570 }
571
572 return 0;
573 }
574
575 /**
576 * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace.
577 * @cxl_mbox: The mailbox context for the operation.
578 * @mbox_cmd: The validated mailbox command.
579 * @out_payload: Pointer to userspace's output payload.
580 * @size_out: (Input) Max payload size to copy out.
581 * (Output) Payload size hardware generated.
582 * @retval: Hardware generated return code from the operation.
583 *
584 * Return:
585 * * %0 - Mailbox transaction succeeded. This implies the mailbox
586 * protocol completed successfully not that the operation itself
587 * was successful.
588 * * %-ENOMEM - Couldn't allocate a bounce buffer.
589 * * %-EFAULT - Something happened with copy_to/from_user.
590 * * %-EINTR - Mailbox acquisition interrupted.
591 * * %-EXXX - Transaction level failures.
592 *
593 * Dispatches a mailbox command on behalf of a userspace request.
594 * The output payload is copied to userspace.
595 *
596 * See cxl_send_cmd().
597 */
handle_mailbox_cmd_from_user(struct cxl_mailbox * cxl_mbox,struct cxl_mbox_cmd * mbox_cmd,u64 out_payload,s32 * size_out,u32 * retval)598 static int handle_mailbox_cmd_from_user(struct cxl_mailbox *cxl_mbox,
599 struct cxl_mbox_cmd *mbox_cmd,
600 u64 out_payload, s32 *size_out,
601 u32 *retval)
602 {
603 struct device *dev = cxl_mbox->host;
604 int rc;
605
606 dev_dbg(dev,
607 "Submitting %s command for user\n"
608 "\topcode: %x\n"
609 "\tsize: %zx\n",
610 cxl_mem_opcode_to_name(mbox_cmd->opcode),
611 mbox_cmd->opcode, mbox_cmd->size_in);
612
613 rc = cxl_mbox->mbox_send(cxl_mbox, mbox_cmd);
614 if (rc)
615 goto out;
616
617 /*
618 * @size_out contains the max size that's allowed to be written back out
619 * to userspace. While the payload may have written more output than
620 * this it will have to be ignored.
621 */
622 if (mbox_cmd->size_out) {
623 dev_WARN_ONCE(dev, mbox_cmd->size_out > *size_out,
624 "Invalid return size\n");
625 if (copy_to_user(u64_to_user_ptr(out_payload),
626 mbox_cmd->payload_out, mbox_cmd->size_out)) {
627 rc = -EFAULT;
628 goto out;
629 }
630 }
631
632 *size_out = mbox_cmd->size_out;
633 *retval = mbox_cmd->return_code;
634
635 out:
636 cxl_mbox_cmd_dtor(mbox_cmd);
637 return rc;
638 }
639
cxl_send_cmd(struct cxl_mailbox * cxl_mbox,struct cxl_send_command __user * s)640 int cxl_send_cmd(struct cxl_mailbox *cxl_mbox, struct cxl_send_command __user *s)
641 {
642 struct device *dev = cxl_mbox->host;
643 struct cxl_send_command send;
644 struct cxl_mbox_cmd mbox_cmd;
645 int rc;
646
647 dev_dbg(dev, "Send IOCTL\n");
648
649 if (copy_from_user(&send, s, sizeof(send)))
650 return -EFAULT;
651
652 rc = cxl_validate_cmd_from_user(&mbox_cmd, cxl_mbox, &send);
653 if (rc)
654 return rc;
655
656 rc = handle_mailbox_cmd_from_user(cxl_mbox, &mbox_cmd, send.out.payload,
657 &send.out.size, &send.retval);
658 if (rc)
659 return rc;
660
661 if (copy_to_user(s, &send, sizeof(send)))
662 return -EFAULT;
663
664 return 0;
665 }
666
cxl_xfer_log(struct cxl_memdev_state * mds,uuid_t * uuid,u32 * size,u8 * out)667 static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid,
668 u32 *size, u8 *out)
669 {
670 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
671 u32 remaining = *size;
672 u32 offset = 0;
673
674 while (remaining) {
675 u32 xfer_size = min_t(u32, remaining, cxl_mbox->payload_size);
676 struct cxl_mbox_cmd mbox_cmd;
677 struct cxl_mbox_get_log log;
678 int rc;
679
680 log = (struct cxl_mbox_get_log) {
681 .uuid = *uuid,
682 .offset = cpu_to_le32(offset),
683 .length = cpu_to_le32(xfer_size),
684 };
685
686 mbox_cmd = (struct cxl_mbox_cmd) {
687 .opcode = CXL_MBOX_OP_GET_LOG,
688 .size_in = sizeof(log),
689 .payload_in = &log,
690 .size_out = xfer_size,
691 .payload_out = out,
692 };
693
694 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
695
696 /*
697 * The output payload length that indicates the number
698 * of valid bytes can be smaller than the Log buffer
699 * size.
700 */
701 if (rc == -EIO && mbox_cmd.size_out < xfer_size) {
702 offset += mbox_cmd.size_out;
703 break;
704 }
705
706 if (rc < 0)
707 return rc;
708
709 out += xfer_size;
710 remaining -= xfer_size;
711 offset += xfer_size;
712 }
713
714 *size = offset;
715
716 return 0;
717 }
718
check_features_opcodes(u16 opcode,int * ro_cmds,int * wr_cmds)719 static int check_features_opcodes(u16 opcode, int *ro_cmds, int *wr_cmds)
720 {
721 switch (opcode) {
722 case CXL_MBOX_OP_GET_SUPPORTED_FEATURES:
723 case CXL_MBOX_OP_GET_FEATURE:
724 (*ro_cmds)++;
725 return 1;
726 case CXL_MBOX_OP_SET_FEATURE:
727 (*wr_cmds)++;
728 return 1;
729 default:
730 return 0;
731 }
732 }
733
734 /* 'Get Supported Features' and 'Get Feature' */
735 #define MAX_FEATURES_READ_CMDS 2
set_features_cap(struct cxl_mailbox * cxl_mbox,int ro_cmds,int wr_cmds)736 static void set_features_cap(struct cxl_mailbox *cxl_mbox,
737 int ro_cmds, int wr_cmds)
738 {
739 /* Setting up Features capability while walking the CEL */
740 if (ro_cmds == MAX_FEATURES_READ_CMDS) {
741 if (wr_cmds)
742 cxl_mbox->feat_cap = CXL_FEATURES_RW;
743 else
744 cxl_mbox->feat_cap = CXL_FEATURES_RO;
745 }
746 }
747
748 /**
749 * cxl_walk_cel() - Walk through the Command Effects Log.
750 * @mds: The driver data for the operation
751 * @size: Length of the Command Effects Log.
752 * @cel: CEL
753 *
754 * Iterate over each entry in the CEL and determine if the driver supports the
755 * command. If so, the command is enabled for the device and can be used later.
756 */
cxl_walk_cel(struct cxl_memdev_state * mds,size_t size,u8 * cel)757 static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
758 {
759 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
760 struct cxl_cel_entry *cel_entry;
761 const int cel_entries = size / sizeof(*cel_entry);
762 struct device *dev = mds->cxlds.dev;
763 int i, ro_cmds = 0, wr_cmds = 0;
764
765 cel_entry = (struct cxl_cel_entry *) cel;
766
767 for (i = 0; i < cel_entries; i++) {
768 u16 opcode = le16_to_cpu(cel_entry[i].opcode);
769 struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
770 int enabled = 0;
771
772 if (cmd) {
773 set_bit(cmd->info.id, cxl_mbox->enabled_cmds);
774 enabled++;
775 }
776
777 enabled += check_features_opcodes(opcode, &ro_cmds,
778 &wr_cmds);
779
780 if (cxl_is_poison_command(opcode)) {
781 cxl_set_poison_cmd_enabled(&mds->poison, opcode);
782 enabled++;
783 }
784
785 if (cxl_is_security_command(opcode)) {
786 cxl_set_security_cmd_enabled(&mds->security, opcode);
787 enabled++;
788 }
789
790 dev_dbg(dev, "Opcode 0x%04x %s\n", opcode,
791 enabled ? "enabled" : "unsupported by driver");
792 }
793
794 set_features_cap(cxl_mbox, ro_cmds, wr_cmds);
795 }
796
cxl_get_gsl(struct cxl_memdev_state * mds)797 static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state *mds)
798 {
799 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
800 struct cxl_mbox_get_supported_logs *ret;
801 struct cxl_mbox_cmd mbox_cmd;
802 int rc;
803
804 ret = kvmalloc(cxl_mbox->payload_size, GFP_KERNEL);
805 if (!ret)
806 return ERR_PTR(-ENOMEM);
807
808 mbox_cmd = (struct cxl_mbox_cmd) {
809 .opcode = CXL_MBOX_OP_GET_SUPPORTED_LOGS,
810 .size_out = cxl_mbox->payload_size,
811 .payload_out = ret,
812 /* At least the record number field must be valid */
813 .min_out = 2,
814 };
815 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
816 if (rc < 0) {
817 kvfree(ret);
818 return ERR_PTR(rc);
819 }
820
821
822 return ret;
823 }
824
825 enum {
826 CEL_UUID,
827 VENDOR_DEBUG_UUID,
828 };
829
830 /* See CXL 2.0 Table 170. Get Log Input Payload */
831 static const uuid_t log_uuid[] = {
832 [CEL_UUID] = DEFINE_CXL_CEL_UUID,
833 [VENDOR_DEBUG_UUID] = DEFINE_CXL_VENDOR_DEBUG_UUID,
834 };
835
836 /**
837 * cxl_enumerate_cmds() - Enumerate commands for a device.
838 * @mds: The driver data for the operation
839 *
840 * Returns 0 if enumerate completed successfully.
841 *
842 * CXL devices have optional support for certain commands. This function will
843 * determine the set of supported commands for the hardware and update the
844 * enabled_cmds bitmap in the @mds.
845 */
cxl_enumerate_cmds(struct cxl_memdev_state * mds)846 int cxl_enumerate_cmds(struct cxl_memdev_state *mds)
847 {
848 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
849 struct cxl_mbox_get_supported_logs *gsl;
850 struct device *dev = mds->cxlds.dev;
851 struct cxl_mem_command *cmd;
852 int i, rc;
853
854 gsl = cxl_get_gsl(mds);
855 if (IS_ERR(gsl))
856 return PTR_ERR(gsl);
857
858 rc = -ENOENT;
859 for (i = 0; i < le16_to_cpu(gsl->entries); i++) {
860 u32 size = le32_to_cpu(gsl->entry[i].size);
861 uuid_t uuid = gsl->entry[i].uuid;
862 u8 *log;
863
864 dev_dbg(dev, "Found LOG type %pU of size %d", &uuid, size);
865
866 if (!uuid_equal(&uuid, &log_uuid[CEL_UUID]))
867 continue;
868
869 log = kvmalloc(size, GFP_KERNEL);
870 if (!log) {
871 rc = -ENOMEM;
872 goto out;
873 }
874
875 rc = cxl_xfer_log(mds, &uuid, &size, log);
876 if (rc) {
877 kvfree(log);
878 goto out;
879 }
880
881 cxl_walk_cel(mds, size, log);
882 kvfree(log);
883
884 /* In case CEL was bogus, enable some default commands. */
885 cxl_for_each_cmd(cmd)
886 if (cmd->flags & CXL_CMD_FLAG_FORCE_ENABLE)
887 set_bit(cmd->info.id, cxl_mbox->enabled_cmds);
888
889 /* Found the required CEL */
890 rc = 0;
891 }
892 out:
893 kvfree(gsl);
894 return rc;
895 }
896 EXPORT_SYMBOL_NS_GPL(cxl_enumerate_cmds, "CXL");
897
cxl_event_trace_record(struct cxl_memdev * cxlmd,enum cxl_event_log_type type,enum cxl_event_type event_type,const uuid_t * uuid,union cxl_event * evt)898 void cxl_event_trace_record(struct cxl_memdev *cxlmd,
899 enum cxl_event_log_type type,
900 enum cxl_event_type event_type,
901 const uuid_t *uuid, union cxl_event *evt)
902 {
903 if (event_type == CXL_CPER_EVENT_MEM_MODULE) {
904 trace_cxl_memory_module(cxlmd, type, &evt->mem_module);
905 return;
906 }
907 if (event_type == CXL_CPER_EVENT_GENERIC) {
908 trace_cxl_generic_event(cxlmd, type, uuid, &evt->generic);
909 return;
910 }
911 if (event_type == CXL_CPER_EVENT_MEM_SPARING) {
912 trace_cxl_memory_sparing(cxlmd, type, &evt->mem_sparing);
913 return;
914 }
915
916 if (trace_cxl_general_media_enabled() || trace_cxl_dram_enabled()) {
917 u64 dpa, hpa = ULLONG_MAX, hpa_alias = ULLONG_MAX;
918 struct cxl_region *cxlr;
919
920 /*
921 * These trace points are annotated with HPA and region
922 * translations. Take topology mutation locks and lookup
923 * { HPA, REGION } from { DPA, MEMDEV } in the event record.
924 */
925 guard(device)(&cxlmd->dev);
926 guard(rwsem_read)(&cxl_rwsem.region);
927 guard(rwsem_read)(&cxl_rwsem.dpa);
928
929 dpa = le64_to_cpu(evt->media_hdr.phys_addr) & CXL_DPA_MASK;
930 cxlr = cxl_dpa_to_region(cxlmd, dpa);
931 if (cxlr) {
932 u64 cache_size = cxlr->params.cache_size;
933
934 hpa = cxl_dpa_to_hpa(cxlr, cxlmd, dpa);
935 if (cache_size)
936 hpa_alias = hpa - cache_size;
937 }
938
939 if (event_type == CXL_CPER_EVENT_GEN_MEDIA) {
940 if (cxl_store_rec_gen_media((struct cxl_memdev *)cxlmd, evt))
941 dev_dbg(&cxlmd->dev, "CXL store rec_gen_media failed\n");
942
943 if (evt->gen_media.media_hdr.descriptor &
944 CXL_GMER_EVT_DESC_THRESHOLD_EVENT)
945 WARN_ON_ONCE((evt->gen_media.media_hdr.type &
946 CXL_GMER_MEM_EVT_TYPE_AP_CME_COUNTER_EXPIRE) &&
947 !get_unaligned_le24(evt->gen_media.cme_count));
948 else
949 WARN_ON_ONCE(evt->gen_media.media_hdr.type &
950 CXL_GMER_MEM_EVT_TYPE_AP_CME_COUNTER_EXPIRE);
951
952 trace_cxl_general_media(cxlmd, type, cxlr, hpa,
953 hpa_alias, &evt->gen_media);
954 } else if (event_type == CXL_CPER_EVENT_DRAM) {
955 if (cxl_store_rec_dram((struct cxl_memdev *)cxlmd, evt))
956 dev_dbg(&cxlmd->dev, "CXL store rec_dram failed\n");
957
958 if (evt->dram.media_hdr.descriptor &
959 CXL_GMER_EVT_DESC_THRESHOLD_EVENT)
960 WARN_ON_ONCE((evt->dram.media_hdr.type &
961 CXL_DER_MEM_EVT_TYPE_AP_CME_COUNTER_EXPIRE) &&
962 !get_unaligned_le24(evt->dram.cvme_count));
963 else
964 WARN_ON_ONCE(evt->dram.media_hdr.type &
965 CXL_DER_MEM_EVT_TYPE_AP_CME_COUNTER_EXPIRE);
966
967 trace_cxl_dram(cxlmd, type, cxlr, hpa, hpa_alias,
968 &evt->dram);
969 }
970 }
971 }
972 EXPORT_SYMBOL_NS_GPL(cxl_event_trace_record, "CXL");
973
__cxl_event_trace_record(struct cxl_memdev * cxlmd,enum cxl_event_log_type type,struct cxl_event_record_raw * record)974 static void __cxl_event_trace_record(struct cxl_memdev *cxlmd,
975 enum cxl_event_log_type type,
976 struct cxl_event_record_raw *record)
977 {
978 enum cxl_event_type ev_type = CXL_CPER_EVENT_GENERIC;
979 const uuid_t *uuid = &record->id;
980
981 if (uuid_equal(uuid, &CXL_EVENT_GEN_MEDIA_UUID))
982 ev_type = CXL_CPER_EVENT_GEN_MEDIA;
983 else if (uuid_equal(uuid, &CXL_EVENT_DRAM_UUID))
984 ev_type = CXL_CPER_EVENT_DRAM;
985 else if (uuid_equal(uuid, &CXL_EVENT_MEM_MODULE_UUID))
986 ev_type = CXL_CPER_EVENT_MEM_MODULE;
987 else if (uuid_equal(uuid, &CXL_EVENT_MEM_SPARING_UUID))
988 ev_type = CXL_CPER_EVENT_MEM_SPARING;
989
990 cxl_event_trace_record(cxlmd, type, ev_type, uuid, &record->event);
991 }
992
cxl_clear_event_record(struct cxl_memdev_state * mds,enum cxl_event_log_type log,struct cxl_get_event_payload * get_pl)993 static int cxl_clear_event_record(struct cxl_memdev_state *mds,
994 enum cxl_event_log_type log,
995 struct cxl_get_event_payload *get_pl)
996 {
997 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
998 struct cxl_mbox_clear_event_payload *payload;
999 u16 total = le16_to_cpu(get_pl->record_count);
1000 u8 max_handles = CXL_CLEAR_EVENT_MAX_HANDLES;
1001 size_t pl_size = struct_size(payload, handles, max_handles);
1002 struct cxl_mbox_cmd mbox_cmd;
1003 u16 cnt;
1004 int rc = 0;
1005 int i;
1006
1007 /* Payload size may limit the max handles */
1008 if (pl_size > cxl_mbox->payload_size) {
1009 max_handles = (cxl_mbox->payload_size - sizeof(*payload)) /
1010 sizeof(__le16);
1011 pl_size = struct_size(payload, handles, max_handles);
1012 }
1013
1014 payload = kvzalloc(pl_size, GFP_KERNEL);
1015 if (!payload)
1016 return -ENOMEM;
1017
1018 *payload = (struct cxl_mbox_clear_event_payload) {
1019 .event_log = log,
1020 };
1021
1022 mbox_cmd = (struct cxl_mbox_cmd) {
1023 .opcode = CXL_MBOX_OP_CLEAR_EVENT_RECORD,
1024 .payload_in = payload,
1025 .size_in = pl_size,
1026 };
1027
1028 /*
1029 * Clear Event Records uses u8 for the handle cnt while Get Event
1030 * Record can return up to 0xffff records.
1031 */
1032 i = 0;
1033 for (cnt = 0; cnt < total; cnt++) {
1034 struct cxl_event_record_raw *raw = &get_pl->records[cnt];
1035 struct cxl_event_generic *gen = &raw->event.generic;
1036
1037 payload->handles[i++] = gen->hdr.handle;
1038 dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log,
1039 le16_to_cpu(payload->handles[i - 1]));
1040
1041 if (i == max_handles) {
1042 payload->nr_recs = i;
1043 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1044 if (rc)
1045 goto free_pl;
1046 i = 0;
1047 }
1048 }
1049
1050 /* Clear what is left if any */
1051 if (i) {
1052 payload->nr_recs = i;
1053 mbox_cmd.size_in = struct_size(payload, handles, i);
1054 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1055 if (rc)
1056 goto free_pl;
1057 }
1058
1059 free_pl:
1060 kvfree(payload);
1061 return rc;
1062 }
1063
cxl_mem_get_records_log(struct cxl_memdev_state * mds,enum cxl_event_log_type type)1064 static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
1065 enum cxl_event_log_type type)
1066 {
1067 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1068 struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
1069 struct device *dev = mds->cxlds.dev;
1070 struct cxl_get_event_payload *payload;
1071 u8 log_type = type;
1072 u16 nr_rec;
1073
1074 mutex_lock(&mds->event.log_lock);
1075 payload = mds->event.buf;
1076
1077 do {
1078 int rc, i;
1079 struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd) {
1080 .opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
1081 .payload_in = &log_type,
1082 .size_in = sizeof(log_type),
1083 .payload_out = payload,
1084 .size_out = cxl_mbox->payload_size,
1085 .min_out = struct_size(payload, records, 0),
1086 };
1087
1088 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1089 if (rc) {
1090 dev_err_ratelimited(dev,
1091 "Event log '%d': Failed to query event records : %d",
1092 type, rc);
1093 break;
1094 }
1095
1096 nr_rec = le16_to_cpu(payload->record_count);
1097 if (!nr_rec)
1098 break;
1099
1100 for (i = 0; i < nr_rec; i++)
1101 __cxl_event_trace_record(cxlmd, type,
1102 &payload->records[i]);
1103
1104 if (payload->flags & CXL_GET_EVENT_FLAG_OVERFLOW)
1105 trace_cxl_overflow(cxlmd, type, payload);
1106
1107 rc = cxl_clear_event_record(mds, type, payload);
1108 if (rc) {
1109 dev_err_ratelimited(dev,
1110 "Event log '%d': Failed to clear events : %d",
1111 type, rc);
1112 break;
1113 }
1114 } while (nr_rec);
1115
1116 mutex_unlock(&mds->event.log_lock);
1117 }
1118
1119 /**
1120 * cxl_mem_get_event_records - Get Event Records from the device
1121 * @mds: The driver data for the operation
1122 * @status: Event Status register value identifying which events are available.
1123 *
1124 * Retrieve all event records available on the device, report them as trace
1125 * events, and clear them.
1126 *
1127 * See CXL rev 3.0 @8.2.9.2.2 Get Event Records
1128 * See CXL rev 3.0 @8.2.9.2.3 Clear Event Records
1129 */
cxl_mem_get_event_records(struct cxl_memdev_state * mds,u32 status)1130 void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status)
1131 {
1132 dev_dbg(mds->cxlds.dev, "Reading event logs: %x\n", status);
1133
1134 if (status & CXLDEV_EVENT_STATUS_FATAL)
1135 cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FATAL);
1136 if (status & CXLDEV_EVENT_STATUS_FAIL)
1137 cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_FAIL);
1138 if (status & CXLDEV_EVENT_STATUS_WARN)
1139 cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_WARN);
1140 if (status & CXLDEV_EVENT_STATUS_INFO)
1141 cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_INFO);
1142 }
1143 EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, "CXL");
1144
1145 /**
1146 * cxl_mem_get_partition_info - Get partition info
1147 * @mds: The driver data for the operation
1148 *
1149 * Retrieve the current partition info for the device specified. The active
1150 * values are the current capacity in bytes. If not 0, the 'next' values are
1151 * the pending values, in bytes, which take affect on next cold reset.
1152 *
1153 * Return: 0 if no error: or the result of the mailbox command.
1154 *
1155 * See CXL @8.2.9.5.2.1 Get Partition Info
1156 */
cxl_mem_get_partition_info(struct cxl_memdev_state * mds)1157 int cxl_mem_get_partition_info(struct cxl_memdev_state *mds)
1158 {
1159 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1160 struct cxl_mbox_get_partition_info pi;
1161 struct cxl_mbox_cmd mbox_cmd;
1162 int rc;
1163
1164 mbox_cmd = (struct cxl_mbox_cmd) {
1165 .opcode = CXL_MBOX_OP_GET_PARTITION_INFO,
1166 .size_out = sizeof(pi),
1167 .payload_out = &pi,
1168 };
1169 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1170 if (rc)
1171 return rc;
1172
1173 mds->active_volatile_bytes =
1174 le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
1175 mds->active_persistent_bytes =
1176 le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER;
1177
1178 return 0;
1179 }
1180
1181 /**
1182 * cxl_dev_state_identify() - Send the IDENTIFY command to the device.
1183 * @mds: The driver data for the operation
1184 *
1185 * Return: 0 if identify was executed successfully or media not ready.
1186 *
1187 * This will dispatch the identify command to the device and on success populate
1188 * structures to be exported to sysfs.
1189 */
cxl_dev_state_identify(struct cxl_memdev_state * mds)1190 int cxl_dev_state_identify(struct cxl_memdev_state *mds)
1191 {
1192 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1193 /* See CXL 2.0 Table 175 Identify Memory Device Output Payload */
1194 struct cxl_mbox_identify id;
1195 struct cxl_mbox_cmd mbox_cmd;
1196 u32 val;
1197 int rc;
1198
1199 if (!mds->cxlds.media_ready)
1200 return 0;
1201
1202 mbox_cmd = (struct cxl_mbox_cmd) {
1203 .opcode = CXL_MBOX_OP_IDENTIFY,
1204 .size_out = sizeof(id),
1205 .payload_out = &id,
1206 };
1207 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1208 if (rc < 0)
1209 return rc;
1210
1211 mds->total_bytes =
1212 le64_to_cpu(id.total_capacity) * CXL_CAPACITY_MULTIPLIER;
1213 mds->volatile_only_bytes =
1214 le64_to_cpu(id.volatile_capacity) * CXL_CAPACITY_MULTIPLIER;
1215 mds->persistent_only_bytes =
1216 le64_to_cpu(id.persistent_capacity) * CXL_CAPACITY_MULTIPLIER;
1217 mds->partition_align_bytes =
1218 le64_to_cpu(id.partition_align) * CXL_CAPACITY_MULTIPLIER;
1219
1220 mds->lsa_size = le32_to_cpu(id.lsa_size);
1221 memcpy(mds->firmware_version, id.fw_revision,
1222 sizeof(id.fw_revision));
1223
1224 if (test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds)) {
1225 val = get_unaligned_le24(id.poison_list_max_mer);
1226 mds->poison.max_errors = min_t(u32, val, CXL_POISON_LIST_MAX);
1227 }
1228
1229 return 0;
1230 }
1231 EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, "CXL");
1232
__cxl_mem_sanitize(struct cxl_memdev_state * mds,u16 cmd)1233 static int __cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd)
1234 {
1235 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1236 int rc;
1237 u32 sec_out = 0;
1238 struct cxl_get_security_output {
1239 __le32 flags;
1240 } out;
1241 struct cxl_mbox_cmd sec_cmd = {
1242 .opcode = CXL_MBOX_OP_GET_SECURITY_STATE,
1243 .payload_out = &out,
1244 .size_out = sizeof(out),
1245 };
1246 struct cxl_mbox_cmd mbox_cmd = { .opcode = cmd };
1247
1248 if (cmd != CXL_MBOX_OP_SANITIZE && cmd != CXL_MBOX_OP_SECURE_ERASE)
1249 return -EINVAL;
1250
1251 rc = cxl_internal_send_cmd(cxl_mbox, &sec_cmd);
1252 if (rc < 0) {
1253 dev_err(cxl_mbox->host, "Failed to get security state : %d", rc);
1254 return rc;
1255 }
1256
1257 /*
1258 * Prior to using these commands, any security applied to
1259 * the user data areas of the device shall be DISABLED (or
1260 * UNLOCKED for secure erase case).
1261 */
1262 sec_out = le32_to_cpu(out.flags);
1263 if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET)
1264 return -EINVAL;
1265
1266 if (cmd == CXL_MBOX_OP_SECURE_ERASE &&
1267 sec_out & CXL_PMEM_SEC_STATE_LOCKED)
1268 return -EINVAL;
1269
1270 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1271 if (rc < 0) {
1272 dev_err(cxl_mbox->host, "Failed to sanitize device : %d", rc);
1273 return rc;
1274 }
1275
1276 return 0;
1277 }
1278
1279
1280 /**
1281 * cxl_mem_sanitize() - Send a sanitization command to the device.
1282 * @cxlmd: The device for the operation
1283 * @cmd: The specific sanitization command opcode
1284 *
1285 * Return: 0 if the command was executed successfully, regardless of
1286 * whether or not the actual security operation is done in the background,
1287 * such as for the Sanitize case.
1288 * Error return values can be the result of the mailbox command, -EINVAL
1289 * when security requirements are not met or invalid contexts, or -EBUSY
1290 * if the sanitize operation is already in flight.
1291 *
1292 * See CXL 3.0 @8.2.9.8.5.1 Sanitize and @8.2.9.8.5.2 Secure Erase.
1293 */
cxl_mem_sanitize(struct cxl_memdev * cxlmd,u16 cmd)1294 int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)
1295 {
1296 struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
1297 struct cxl_port *endpoint;
1298
1299 /* synchronize with cxl_mem_probe() and decoder write operations */
1300 guard(device)(&cxlmd->dev);
1301 endpoint = cxlmd->endpoint;
1302 guard(rwsem_read)(&cxl_rwsem.region);
1303 /*
1304 * Require an endpoint to be safe otherwise the driver can not
1305 * be sure that the device is unmapped.
1306 */
1307 if (cxlmd->dev.driver && cxl_num_decoders_committed(endpoint) == 0)
1308 return __cxl_mem_sanitize(mds, cmd);
1309
1310 return -EBUSY;
1311 }
1312
cxl_get_dirty_count(struct cxl_memdev_state * mds,u32 * count)1313 int cxl_get_dirty_count(struct cxl_memdev_state *mds, u32 *count)
1314 {
1315 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1316 struct cxl_mbox_get_health_info_out hi;
1317 struct cxl_mbox_cmd mbox_cmd;
1318 int rc;
1319
1320 mbox_cmd = (struct cxl_mbox_cmd) {
1321 .opcode = CXL_MBOX_OP_GET_HEALTH_INFO,
1322 .size_out = sizeof(hi),
1323 .payload_out = &hi,
1324 };
1325
1326 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1327 if (!rc)
1328 *count = le32_to_cpu(hi.dirty_shutdown_cnt);
1329
1330 return rc;
1331 }
1332 EXPORT_SYMBOL_NS_GPL(cxl_get_dirty_count, "CXL");
1333
cxl_arm_dirty_shutdown(struct cxl_memdev_state * mds)1334 int cxl_arm_dirty_shutdown(struct cxl_memdev_state *mds)
1335 {
1336 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1337 struct cxl_mbox_cmd mbox_cmd;
1338 struct cxl_mbox_set_shutdown_state_in in = {
1339 .state = 1
1340 };
1341
1342 mbox_cmd = (struct cxl_mbox_cmd) {
1343 .opcode = CXL_MBOX_OP_SET_SHUTDOWN_STATE,
1344 .size_in = sizeof(in),
1345 .payload_in = &in,
1346 };
1347
1348 return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1349 }
1350 EXPORT_SYMBOL_NS_GPL(cxl_arm_dirty_shutdown, "CXL");
1351
cxl_set_timestamp(struct cxl_memdev_state * mds)1352 int cxl_set_timestamp(struct cxl_memdev_state *mds)
1353 {
1354 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1355 struct cxl_mbox_cmd mbox_cmd;
1356 struct cxl_mbox_set_timestamp_in pi;
1357 int rc;
1358
1359 pi.timestamp = cpu_to_le64(ktime_get_real_ns());
1360 mbox_cmd = (struct cxl_mbox_cmd) {
1361 .opcode = CXL_MBOX_OP_SET_TIMESTAMP,
1362 .size_in = sizeof(pi),
1363 .payload_in = &pi,
1364 };
1365
1366 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1367 /*
1368 * Command is optional. Devices may have another way of providing
1369 * a timestamp, or may return all 0s in timestamp fields.
1370 * Don't report an error if this command isn't supported
1371 */
1372 if (rc && (mbox_cmd.return_code != CXL_MBOX_CMD_RC_UNSUPPORTED))
1373 return rc;
1374
1375 return 0;
1376 }
1377 EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, "CXL");
1378
cxl_mem_get_poison(struct cxl_memdev * cxlmd,u64 offset,u64 len,struct cxl_region * cxlr)1379 int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
1380 struct cxl_region *cxlr)
1381 {
1382 struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
1383 struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
1384 struct cxl_mbox_poison_out *po;
1385 struct cxl_mbox_poison_in pi;
1386 int nr_records = 0;
1387 int rc;
1388
1389 ACQUIRE(mutex_intr, lock)(&mds->poison.mutex);
1390 if ((rc = ACQUIRE_ERR(mutex_intr, &lock)))
1391 return rc;
1392
1393 po = mds->poison.list_out;
1394 pi.offset = cpu_to_le64(offset);
1395 pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT);
1396
1397 do {
1398 struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd){
1399 .opcode = CXL_MBOX_OP_GET_POISON,
1400 .size_in = sizeof(pi),
1401 .payload_in = &pi,
1402 .size_out = cxl_mbox->payload_size,
1403 .payload_out = po,
1404 .min_out = struct_size(po, record, 0),
1405 };
1406
1407 rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
1408 if (rc)
1409 break;
1410
1411 if (!le16_to_cpu(po->count)) {
1412 dev_dbg(&cxlmd->dev, "Poison empty payload!\n");
1413 break;
1414 }
1415
1416 for (int i = 0; i < le16_to_cpu(po->count); i++)
1417 trace_cxl_poison(cxlmd, cxlr, &po->record[i],
1418 po->flags, po->overflow_ts,
1419 CXL_POISON_TRACE_LIST);
1420
1421 /* Protect against an uncleared _FLAG_MORE */
1422 nr_records = nr_records + le16_to_cpu(po->count);
1423 if (nr_records >= mds->poison.max_errors) {
1424 dev_dbg(&cxlmd->dev, "Max Error Records reached: %d\n",
1425 nr_records);
1426 break;
1427 }
1428 } while (po->flags & CXL_POISON_FLAG_MORE);
1429
1430 return rc;
1431 }
1432 EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, "CXL");
1433
free_poison_buf(void * buf)1434 static void free_poison_buf(void *buf)
1435 {
1436 kvfree(buf);
1437 }
1438
1439 /* Get Poison List output buffer is protected by mds->poison.lock */
cxl_poison_alloc_buf(struct cxl_memdev_state * mds)1440 static int cxl_poison_alloc_buf(struct cxl_memdev_state *mds)
1441 {
1442 struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1443
1444 mds->poison.list_out = kvmalloc(cxl_mbox->payload_size, GFP_KERNEL);
1445 if (!mds->poison.list_out)
1446 return -ENOMEM;
1447
1448 return devm_add_action_or_reset(mds->cxlds.dev, free_poison_buf,
1449 mds->poison.list_out);
1450 }
1451
cxl_poison_state_init(struct cxl_memdev_state * mds)1452 int cxl_poison_state_init(struct cxl_memdev_state *mds)
1453 {
1454 int rc;
1455
1456 if (!test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds))
1457 return 0;
1458
1459 rc = cxl_poison_alloc_buf(mds);
1460 if (rc) {
1461 clear_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds);
1462 return rc;
1463 }
1464
1465 mutex_init(&mds->poison.mutex);
1466 return 0;
1467 }
1468 EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, "CXL");
1469
cxl_mailbox_init(struct cxl_mailbox * cxl_mbox,struct device * host)1470 int cxl_mailbox_init(struct cxl_mailbox *cxl_mbox, struct device *host)
1471 {
1472 if (!cxl_mbox || !host)
1473 return -EINVAL;
1474
1475 cxl_mbox->host = host;
1476 mutex_init(&cxl_mbox->mbox_mutex);
1477 mutex_init(&cxl_mbox->feat_mutex);
1478 rcuwait_init(&cxl_mbox->mbox_wait);
1479
1480 return 0;
1481 }
1482 EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, "CXL");
1483
cxl_memdev_state_create(struct device * dev,u64 serial,u16 dvsec)1484 struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev, u64 serial,
1485 u16 dvsec)
1486 {
1487 struct cxl_memdev_state *mds;
1488
1489 mds = devm_cxl_dev_state_create(dev, CXL_DEVTYPE_CLASSMEM, serial,
1490 dvsec, struct cxl_memdev_state, cxlds,
1491 true);
1492 if (!mds) {
1493 dev_err(dev, "No memory available\n");
1494 return ERR_PTR(-ENOMEM);
1495 }
1496
1497 mutex_init(&mds->event.log_lock);
1498
1499 return mds;
1500 }
1501 EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, "CXL");
1502
cxl_mbox_init(void)1503 void __init cxl_mbox_init(void)
1504 {
1505 struct dentry *mbox_debugfs;
1506
1507 mbox_debugfs = cxl_debugfs_create_dir("mbox");
1508 debugfs_create_bool("raw_allow_all", 0600, mbox_debugfs,
1509 &cxl_raw_allow_all);
1510 }
1511