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 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 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 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 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 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 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 */ 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 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 */ 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 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 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 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 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 */ 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 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 */ 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 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 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 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 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 */ 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 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 */ 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 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 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 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 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 */ 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 */ 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 */ 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 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 */ 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 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 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 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 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 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 */ 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 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 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 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 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