1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright(c) 2021 Intel Corporation. All rights reserved. 3 4 #include <linux/platform_device.h> 5 #include <linux/mod_devicetable.h> 6 #include <linux/module.h> 7 #include <linux/delay.h> 8 #include <linux/sizes.h> 9 #include <linux/bits.h> 10 #include <cxlmem.h> 11 12 #include "trace.h" 13 14 #define LSA_SIZE SZ_128K 15 #define DEV_SIZE SZ_2G 16 #define EFFECT(x) (1U << x) 17 18 static struct cxl_cel_entry mock_cel[] = { 19 { 20 .opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_LOGS), 21 .effect = cpu_to_le16(0), 22 }, 23 { 24 .opcode = cpu_to_le16(CXL_MBOX_OP_IDENTIFY), 25 .effect = cpu_to_le16(0), 26 }, 27 { 28 .opcode = cpu_to_le16(CXL_MBOX_OP_GET_LSA), 29 .effect = cpu_to_le16(0), 30 }, 31 { 32 .opcode = cpu_to_le16(CXL_MBOX_OP_GET_PARTITION_INFO), 33 .effect = cpu_to_le16(0), 34 }, 35 { 36 .opcode = cpu_to_le16(CXL_MBOX_OP_SET_LSA), 37 .effect = cpu_to_le16(EFFECT(1) | EFFECT(2)), 38 }, 39 { 40 .opcode = cpu_to_le16(CXL_MBOX_OP_GET_HEALTH_INFO), 41 .effect = cpu_to_le16(0), 42 }, 43 }; 44 45 /* See CXL 2.0 Table 181 Get Health Info Output Payload */ 46 struct cxl_mbox_health_info { 47 u8 health_status; 48 u8 media_status; 49 u8 ext_status; 50 u8 life_used; 51 __le16 temperature; 52 __le32 dirty_shutdowns; 53 __le32 volatile_errors; 54 __le32 pmem_errors; 55 } __packed; 56 57 static struct { 58 struct cxl_mbox_get_supported_logs gsl; 59 struct cxl_gsl_entry entry; 60 } mock_gsl_payload = { 61 .gsl = { 62 .entries = cpu_to_le16(1), 63 }, 64 .entry = { 65 .uuid = DEFINE_CXL_CEL_UUID, 66 .size = cpu_to_le32(sizeof(mock_cel)), 67 }, 68 }; 69 70 #define PASS_TRY_LIMIT 3 71 72 #define CXL_TEST_EVENT_CNT_MAX 15 73 74 /* Set a number of events to return at a time for simulation. */ 75 #define CXL_TEST_EVENT_CNT 3 76 77 struct mock_event_log { 78 u16 clear_idx; 79 u16 cur_idx; 80 u16 nr_events; 81 u16 nr_overflow; 82 u16 overflow_reset; 83 struct cxl_event_record_raw *events[CXL_TEST_EVENT_CNT_MAX]; 84 }; 85 86 struct mock_event_store { 87 struct cxl_dev_state *cxlds; 88 struct mock_event_log mock_logs[CXL_EVENT_TYPE_MAX]; 89 u32 ev_status; 90 }; 91 92 struct cxl_mockmem_data { 93 void *lsa; 94 u32 security_state; 95 u8 user_pass[NVDIMM_PASSPHRASE_LEN]; 96 u8 master_pass[NVDIMM_PASSPHRASE_LEN]; 97 int user_limit; 98 int master_limit; 99 struct mock_event_store mes; 100 u8 event_buf[SZ_4K]; 101 }; 102 103 static struct mock_event_log *event_find_log(struct device *dev, int log_type) 104 { 105 struct cxl_mockmem_data *mdata = dev_get_drvdata(dev); 106 107 if (log_type >= CXL_EVENT_TYPE_MAX) 108 return NULL; 109 return &mdata->mes.mock_logs[log_type]; 110 } 111 112 static struct cxl_event_record_raw *event_get_current(struct mock_event_log *log) 113 { 114 return log->events[log->cur_idx]; 115 } 116 117 static void event_reset_log(struct mock_event_log *log) 118 { 119 log->cur_idx = 0; 120 log->clear_idx = 0; 121 log->nr_overflow = log->overflow_reset; 122 } 123 124 /* Handle can never be 0 use 1 based indexing for handle */ 125 static u16 event_get_clear_handle(struct mock_event_log *log) 126 { 127 return log->clear_idx + 1; 128 } 129 130 /* Handle can never be 0 use 1 based indexing for handle */ 131 static __le16 event_get_cur_event_handle(struct mock_event_log *log) 132 { 133 u16 cur_handle = log->cur_idx + 1; 134 135 return cpu_to_le16(cur_handle); 136 } 137 138 static bool event_log_empty(struct mock_event_log *log) 139 { 140 return log->cur_idx == log->nr_events; 141 } 142 143 static void mes_add_event(struct mock_event_store *mes, 144 enum cxl_event_log_type log_type, 145 struct cxl_event_record_raw *event) 146 { 147 struct mock_event_log *log; 148 149 if (WARN_ON(log_type >= CXL_EVENT_TYPE_MAX)) 150 return; 151 152 log = &mes->mock_logs[log_type]; 153 154 if ((log->nr_events + 1) > CXL_TEST_EVENT_CNT_MAX) { 155 log->nr_overflow++; 156 log->overflow_reset = log->nr_overflow; 157 return; 158 } 159 160 log->events[log->nr_events] = event; 161 log->nr_events++; 162 } 163 164 static int mock_get_event(struct cxl_dev_state *cxlds, 165 struct cxl_mbox_cmd *cmd) 166 { 167 struct cxl_get_event_payload *pl; 168 struct mock_event_log *log; 169 u16 nr_overflow; 170 u8 log_type; 171 int i; 172 173 if (cmd->size_in != sizeof(log_type)) 174 return -EINVAL; 175 176 if (cmd->size_out < struct_size(pl, records, CXL_TEST_EVENT_CNT)) 177 return -EINVAL; 178 179 log_type = *((u8 *)cmd->payload_in); 180 if (log_type >= CXL_EVENT_TYPE_MAX) 181 return -EINVAL; 182 183 memset(cmd->payload_out, 0, cmd->size_out); 184 185 log = event_find_log(cxlds->dev, log_type); 186 if (!log || event_log_empty(log)) 187 return 0; 188 189 pl = cmd->payload_out; 190 191 for (i = 0; i < CXL_TEST_EVENT_CNT && !event_log_empty(log); i++) { 192 memcpy(&pl->records[i], event_get_current(log), 193 sizeof(pl->records[i])); 194 pl->records[i].hdr.handle = event_get_cur_event_handle(log); 195 log->cur_idx++; 196 } 197 198 pl->record_count = cpu_to_le16(i); 199 if (!event_log_empty(log)) 200 pl->flags |= CXL_GET_EVENT_FLAG_MORE_RECORDS; 201 202 if (log->nr_overflow) { 203 u64 ns; 204 205 pl->flags |= CXL_GET_EVENT_FLAG_OVERFLOW; 206 pl->overflow_err_count = cpu_to_le16(nr_overflow); 207 ns = ktime_get_real_ns(); 208 ns -= 5000000000; /* 5s ago */ 209 pl->first_overflow_timestamp = cpu_to_le64(ns); 210 ns = ktime_get_real_ns(); 211 ns -= 1000000000; /* 1s ago */ 212 pl->last_overflow_timestamp = cpu_to_le64(ns); 213 } 214 215 return 0; 216 } 217 218 static int mock_clear_event(struct cxl_dev_state *cxlds, 219 struct cxl_mbox_cmd *cmd) 220 { 221 struct cxl_mbox_clear_event_payload *pl = cmd->payload_in; 222 struct mock_event_log *log; 223 u8 log_type = pl->event_log; 224 u16 handle; 225 int nr; 226 227 if (log_type >= CXL_EVENT_TYPE_MAX) 228 return -EINVAL; 229 230 log = event_find_log(cxlds->dev, log_type); 231 if (!log) 232 return 0; /* No mock data in this log */ 233 234 /* 235 * This check is technically not invalid per the specification AFAICS. 236 * (The host could 'guess' handles and clear them in order). 237 * However, this is not good behavior for the host so test it. 238 */ 239 if (log->clear_idx + pl->nr_recs > log->cur_idx) { 240 dev_err(cxlds->dev, 241 "Attempting to clear more events than returned!\n"); 242 return -EINVAL; 243 } 244 245 /* Check handle order prior to clearing events */ 246 for (nr = 0, handle = event_get_clear_handle(log); 247 nr < pl->nr_recs; 248 nr++, handle++) { 249 if (handle != le16_to_cpu(pl->handles[nr])) { 250 dev_err(cxlds->dev, "Clearing events out of order\n"); 251 return -EINVAL; 252 } 253 } 254 255 if (log->nr_overflow) 256 log->nr_overflow = 0; 257 258 /* Clear events */ 259 log->clear_idx += pl->nr_recs; 260 return 0; 261 } 262 263 static void cxl_mock_event_trigger(struct device *dev) 264 { 265 struct cxl_mockmem_data *mdata = dev_get_drvdata(dev); 266 struct mock_event_store *mes = &mdata->mes; 267 int i; 268 269 for (i = CXL_EVENT_TYPE_INFO; i < CXL_EVENT_TYPE_MAX; i++) { 270 struct mock_event_log *log; 271 272 log = event_find_log(dev, i); 273 if (log) 274 event_reset_log(log); 275 } 276 277 cxl_mem_get_event_records(mes->cxlds, mes->ev_status); 278 } 279 280 struct cxl_event_record_raw maint_needed = { 281 .hdr = { 282 .id = UUID_INIT(0xBA5EBA11, 0xABCD, 0xEFEB, 283 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0xa5, 0x5a, 0xa5), 284 .length = sizeof(struct cxl_event_record_raw), 285 .flags[0] = CXL_EVENT_RECORD_FLAG_MAINT_NEEDED, 286 /* .handle = Set dynamically */ 287 .related_handle = cpu_to_le16(0xa5b6), 288 }, 289 .data = { 0xDE, 0xAD, 0xBE, 0xEF }, 290 }; 291 292 struct cxl_event_record_raw hardware_replace = { 293 .hdr = { 294 .id = UUID_INIT(0xABCDEFEB, 0xBA11, 0xBA5E, 295 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0xa5, 0x5a, 0xa5), 296 .length = sizeof(struct cxl_event_record_raw), 297 .flags[0] = CXL_EVENT_RECORD_FLAG_HW_REPLACE, 298 /* .handle = Set dynamically */ 299 .related_handle = cpu_to_le16(0xb6a5), 300 }, 301 .data = { 0xDE, 0xAD, 0xBE, 0xEF }, 302 }; 303 304 struct cxl_event_gen_media gen_media = { 305 .hdr = { 306 .id = UUID_INIT(0xfbcd0a77, 0xc260, 0x417f, 307 0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6), 308 .length = sizeof(struct cxl_event_gen_media), 309 .flags[0] = CXL_EVENT_RECORD_FLAG_PERMANENT, 310 /* .handle = Set dynamically */ 311 .related_handle = cpu_to_le16(0), 312 }, 313 .phys_addr = cpu_to_le64(0x2000), 314 .descriptor = CXL_GMER_EVT_DESC_UNCORECTABLE_EVENT, 315 .type = CXL_GMER_MEM_EVT_TYPE_DATA_PATH_ERROR, 316 .transaction_type = CXL_GMER_TRANS_HOST_WRITE, 317 /* .validity_flags = <set below> */ 318 .channel = 1, 319 .rank = 30 320 }; 321 322 struct cxl_event_dram dram = { 323 .hdr = { 324 .id = UUID_INIT(0x601dcbb3, 0x9c06, 0x4eab, 325 0xb8, 0xaf, 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24), 326 .length = sizeof(struct cxl_event_dram), 327 .flags[0] = CXL_EVENT_RECORD_FLAG_PERF_DEGRADED, 328 /* .handle = Set dynamically */ 329 .related_handle = cpu_to_le16(0), 330 }, 331 .phys_addr = cpu_to_le64(0x8000), 332 .descriptor = CXL_GMER_EVT_DESC_THRESHOLD_EVENT, 333 .type = CXL_GMER_MEM_EVT_TYPE_INV_ADDR, 334 .transaction_type = CXL_GMER_TRANS_INTERNAL_MEDIA_SCRUB, 335 /* .validity_flags = <set below> */ 336 .channel = 1, 337 .bank_group = 5, 338 .bank = 2, 339 .column = {0xDE, 0xAD}, 340 }; 341 342 struct cxl_event_mem_module mem_module = { 343 .hdr = { 344 .id = UUID_INIT(0xfe927475, 0xdd59, 0x4339, 345 0xa5, 0x86, 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74), 346 .length = sizeof(struct cxl_event_mem_module), 347 /* .handle = Set dynamically */ 348 .related_handle = cpu_to_le16(0), 349 }, 350 .event_type = CXL_MMER_TEMP_CHANGE, 351 .info = { 352 .health_status = CXL_DHI_HS_PERFORMANCE_DEGRADED, 353 .media_status = CXL_DHI_MS_ALL_DATA_LOST, 354 .add_status = (CXL_DHI_AS_CRITICAL << 2) | 355 (CXL_DHI_AS_WARNING << 4) | 356 (CXL_DHI_AS_WARNING << 5), 357 .device_temp = { 0xDE, 0xAD}, 358 .dirty_shutdown_cnt = { 0xde, 0xad, 0xbe, 0xef }, 359 .cor_vol_err_cnt = { 0xde, 0xad, 0xbe, 0xef }, 360 .cor_per_err_cnt = { 0xde, 0xad, 0xbe, 0xef }, 361 } 362 }; 363 364 static void cxl_mock_add_event_logs(struct mock_event_store *mes) 365 { 366 put_unaligned_le16(CXL_GMER_VALID_CHANNEL | CXL_GMER_VALID_RANK, 367 &gen_media.validity_flags); 368 369 put_unaligned_le16(CXL_DER_VALID_CHANNEL | CXL_DER_VALID_BANK_GROUP | 370 CXL_DER_VALID_BANK | CXL_DER_VALID_COLUMN, 371 &dram.validity_flags); 372 373 mes_add_event(mes, CXL_EVENT_TYPE_INFO, &maint_needed); 374 mes_add_event(mes, CXL_EVENT_TYPE_INFO, 375 (struct cxl_event_record_raw *)&gen_media); 376 mes_add_event(mes, CXL_EVENT_TYPE_INFO, 377 (struct cxl_event_record_raw *)&mem_module); 378 mes->ev_status |= CXLDEV_EVENT_STATUS_INFO; 379 380 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &maint_needed); 381 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 382 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, 383 (struct cxl_event_record_raw *)&dram); 384 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, 385 (struct cxl_event_record_raw *)&gen_media); 386 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, 387 (struct cxl_event_record_raw *)&mem_module); 388 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 389 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, 390 (struct cxl_event_record_raw *)&dram); 391 /* Overflow this log */ 392 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 393 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 394 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 395 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 396 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 397 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 398 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 399 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 400 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 401 mes_add_event(mes, CXL_EVENT_TYPE_FAIL, &hardware_replace); 402 mes->ev_status |= CXLDEV_EVENT_STATUS_FAIL; 403 404 mes_add_event(mes, CXL_EVENT_TYPE_FATAL, &hardware_replace); 405 mes_add_event(mes, CXL_EVENT_TYPE_FATAL, 406 (struct cxl_event_record_raw *)&dram); 407 mes->ev_status |= CXLDEV_EVENT_STATUS_FATAL; 408 } 409 410 static int mock_gsl(struct cxl_mbox_cmd *cmd) 411 { 412 if (cmd->size_out < sizeof(mock_gsl_payload)) 413 return -EINVAL; 414 415 memcpy(cmd->payload_out, &mock_gsl_payload, sizeof(mock_gsl_payload)); 416 cmd->size_out = sizeof(mock_gsl_payload); 417 418 return 0; 419 } 420 421 static int mock_get_log(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 422 { 423 struct cxl_mbox_get_log *gl = cmd->payload_in; 424 u32 offset = le32_to_cpu(gl->offset); 425 u32 length = le32_to_cpu(gl->length); 426 uuid_t uuid = DEFINE_CXL_CEL_UUID; 427 void *data = &mock_cel; 428 429 if (cmd->size_in < sizeof(*gl)) 430 return -EINVAL; 431 if (length > cxlds->payload_size) 432 return -EINVAL; 433 if (offset + length > sizeof(mock_cel)) 434 return -EINVAL; 435 if (!uuid_equal(&gl->uuid, &uuid)) 436 return -EINVAL; 437 if (length > cmd->size_out) 438 return -EINVAL; 439 440 memcpy(cmd->payload_out, data + offset, length); 441 442 return 0; 443 } 444 445 static int mock_rcd_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 446 { 447 struct cxl_mbox_identify id = { 448 .fw_revision = { "mock fw v1 " }, 449 .total_capacity = 450 cpu_to_le64(DEV_SIZE / CXL_CAPACITY_MULTIPLIER), 451 .volatile_capacity = 452 cpu_to_le64(DEV_SIZE / CXL_CAPACITY_MULTIPLIER), 453 }; 454 455 if (cmd->size_out < sizeof(id)) 456 return -EINVAL; 457 458 memcpy(cmd->payload_out, &id, sizeof(id)); 459 460 return 0; 461 } 462 463 static int mock_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 464 { 465 struct cxl_mbox_identify id = { 466 .fw_revision = { "mock fw v1 " }, 467 .lsa_size = cpu_to_le32(LSA_SIZE), 468 .partition_align = 469 cpu_to_le64(SZ_256M / CXL_CAPACITY_MULTIPLIER), 470 .total_capacity = 471 cpu_to_le64(DEV_SIZE / CXL_CAPACITY_MULTIPLIER), 472 }; 473 474 if (cmd->size_out < sizeof(id)) 475 return -EINVAL; 476 477 memcpy(cmd->payload_out, &id, sizeof(id)); 478 479 return 0; 480 } 481 482 static int mock_partition_info(struct cxl_dev_state *cxlds, 483 struct cxl_mbox_cmd *cmd) 484 { 485 struct cxl_mbox_get_partition_info pi = { 486 .active_volatile_cap = 487 cpu_to_le64(DEV_SIZE / 2 / CXL_CAPACITY_MULTIPLIER), 488 .active_persistent_cap = 489 cpu_to_le64(DEV_SIZE / 2 / CXL_CAPACITY_MULTIPLIER), 490 }; 491 492 if (cmd->size_out < sizeof(pi)) 493 return -EINVAL; 494 495 memcpy(cmd->payload_out, &pi, sizeof(pi)); 496 497 return 0; 498 } 499 500 static int mock_get_security_state(struct cxl_dev_state *cxlds, 501 struct cxl_mbox_cmd *cmd) 502 { 503 struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev); 504 505 if (cmd->size_in) 506 return -EINVAL; 507 508 if (cmd->size_out != sizeof(u32)) 509 return -EINVAL; 510 511 memcpy(cmd->payload_out, &mdata->security_state, sizeof(u32)); 512 513 return 0; 514 } 515 516 static void master_plimit_check(struct cxl_mockmem_data *mdata) 517 { 518 if (mdata->master_limit == PASS_TRY_LIMIT) 519 return; 520 mdata->master_limit++; 521 if (mdata->master_limit == PASS_TRY_LIMIT) 522 mdata->security_state |= CXL_PMEM_SEC_STATE_MASTER_PLIMIT; 523 } 524 525 static void user_plimit_check(struct cxl_mockmem_data *mdata) 526 { 527 if (mdata->user_limit == PASS_TRY_LIMIT) 528 return; 529 mdata->user_limit++; 530 if (mdata->user_limit == PASS_TRY_LIMIT) 531 mdata->security_state |= CXL_PMEM_SEC_STATE_USER_PLIMIT; 532 } 533 534 static int mock_set_passphrase(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 535 { 536 struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev); 537 struct cxl_set_pass *set_pass; 538 539 if (cmd->size_in != sizeof(*set_pass)) 540 return -EINVAL; 541 542 if (cmd->size_out != 0) 543 return -EINVAL; 544 545 if (mdata->security_state & CXL_PMEM_SEC_STATE_FROZEN) { 546 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 547 return -ENXIO; 548 } 549 550 set_pass = cmd->payload_in; 551 switch (set_pass->type) { 552 case CXL_PMEM_SEC_PASS_MASTER: 553 if (mdata->security_state & CXL_PMEM_SEC_STATE_MASTER_PLIMIT) { 554 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 555 return -ENXIO; 556 } 557 /* 558 * CXL spec rev3.0 8.2.9.8.6.2, The master pasphrase shall only be set in 559 * the security disabled state when the user passphrase is not set. 560 */ 561 if (mdata->security_state & CXL_PMEM_SEC_STATE_USER_PASS_SET) { 562 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 563 return -ENXIO; 564 } 565 if (memcmp(mdata->master_pass, set_pass->old_pass, NVDIMM_PASSPHRASE_LEN)) { 566 master_plimit_check(mdata); 567 cmd->return_code = CXL_MBOX_CMD_RC_PASSPHRASE; 568 return -ENXIO; 569 } 570 memcpy(mdata->master_pass, set_pass->new_pass, NVDIMM_PASSPHRASE_LEN); 571 mdata->security_state |= CXL_PMEM_SEC_STATE_MASTER_PASS_SET; 572 return 0; 573 574 case CXL_PMEM_SEC_PASS_USER: 575 if (mdata->security_state & CXL_PMEM_SEC_STATE_USER_PLIMIT) { 576 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 577 return -ENXIO; 578 } 579 if (memcmp(mdata->user_pass, set_pass->old_pass, NVDIMM_PASSPHRASE_LEN)) { 580 user_plimit_check(mdata); 581 cmd->return_code = CXL_MBOX_CMD_RC_PASSPHRASE; 582 return -ENXIO; 583 } 584 memcpy(mdata->user_pass, set_pass->new_pass, NVDIMM_PASSPHRASE_LEN); 585 mdata->security_state |= CXL_PMEM_SEC_STATE_USER_PASS_SET; 586 return 0; 587 588 default: 589 cmd->return_code = CXL_MBOX_CMD_RC_INPUT; 590 } 591 return -EINVAL; 592 } 593 594 static int mock_disable_passphrase(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 595 { 596 struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev); 597 struct cxl_disable_pass *dis_pass; 598 599 if (cmd->size_in != sizeof(*dis_pass)) 600 return -EINVAL; 601 602 if (cmd->size_out != 0) 603 return -EINVAL; 604 605 if (mdata->security_state & CXL_PMEM_SEC_STATE_FROZEN) { 606 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 607 return -ENXIO; 608 } 609 610 dis_pass = cmd->payload_in; 611 switch (dis_pass->type) { 612 case CXL_PMEM_SEC_PASS_MASTER: 613 if (mdata->security_state & CXL_PMEM_SEC_STATE_MASTER_PLIMIT) { 614 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 615 return -ENXIO; 616 } 617 618 if (!(mdata->security_state & CXL_PMEM_SEC_STATE_MASTER_PASS_SET)) { 619 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 620 return -ENXIO; 621 } 622 623 if (memcmp(dis_pass->pass, mdata->master_pass, NVDIMM_PASSPHRASE_LEN)) { 624 master_plimit_check(mdata); 625 cmd->return_code = CXL_MBOX_CMD_RC_PASSPHRASE; 626 return -ENXIO; 627 } 628 629 mdata->master_limit = 0; 630 memset(mdata->master_pass, 0, NVDIMM_PASSPHRASE_LEN); 631 mdata->security_state &= ~CXL_PMEM_SEC_STATE_MASTER_PASS_SET; 632 return 0; 633 634 case CXL_PMEM_SEC_PASS_USER: 635 if (mdata->security_state & CXL_PMEM_SEC_STATE_USER_PLIMIT) { 636 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 637 return -ENXIO; 638 } 639 640 if (!(mdata->security_state & CXL_PMEM_SEC_STATE_USER_PASS_SET)) { 641 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 642 return -ENXIO; 643 } 644 645 if (memcmp(dis_pass->pass, mdata->user_pass, NVDIMM_PASSPHRASE_LEN)) { 646 user_plimit_check(mdata); 647 cmd->return_code = CXL_MBOX_CMD_RC_PASSPHRASE; 648 return -ENXIO; 649 } 650 651 mdata->user_limit = 0; 652 memset(mdata->user_pass, 0, NVDIMM_PASSPHRASE_LEN); 653 mdata->security_state &= ~(CXL_PMEM_SEC_STATE_USER_PASS_SET | 654 CXL_PMEM_SEC_STATE_LOCKED); 655 return 0; 656 657 default: 658 cmd->return_code = CXL_MBOX_CMD_RC_INPUT; 659 return -EINVAL; 660 } 661 662 return 0; 663 } 664 665 static int mock_freeze_security(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 666 { 667 struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev); 668 669 if (cmd->size_in != 0) 670 return -EINVAL; 671 672 if (cmd->size_out != 0) 673 return -EINVAL; 674 675 if (mdata->security_state & CXL_PMEM_SEC_STATE_FROZEN) 676 return 0; 677 678 mdata->security_state |= CXL_PMEM_SEC_STATE_FROZEN; 679 return 0; 680 } 681 682 static int mock_unlock_security(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 683 { 684 struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev); 685 686 if (cmd->size_in != NVDIMM_PASSPHRASE_LEN) 687 return -EINVAL; 688 689 if (cmd->size_out != 0) 690 return -EINVAL; 691 692 if (mdata->security_state & CXL_PMEM_SEC_STATE_FROZEN) { 693 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 694 return -ENXIO; 695 } 696 697 if (!(mdata->security_state & CXL_PMEM_SEC_STATE_USER_PASS_SET)) { 698 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 699 return -ENXIO; 700 } 701 702 if (mdata->security_state & CXL_PMEM_SEC_STATE_USER_PLIMIT) { 703 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 704 return -ENXIO; 705 } 706 707 if (!(mdata->security_state & CXL_PMEM_SEC_STATE_LOCKED)) { 708 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 709 return -ENXIO; 710 } 711 712 if (memcmp(cmd->payload_in, mdata->user_pass, NVDIMM_PASSPHRASE_LEN)) { 713 if (++mdata->user_limit == PASS_TRY_LIMIT) 714 mdata->security_state |= CXL_PMEM_SEC_STATE_USER_PLIMIT; 715 cmd->return_code = CXL_MBOX_CMD_RC_PASSPHRASE; 716 return -ENXIO; 717 } 718 719 mdata->user_limit = 0; 720 mdata->security_state &= ~CXL_PMEM_SEC_STATE_LOCKED; 721 return 0; 722 } 723 724 static int mock_passphrase_secure_erase(struct cxl_dev_state *cxlds, 725 struct cxl_mbox_cmd *cmd) 726 { 727 struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev); 728 struct cxl_pass_erase *erase; 729 730 if (cmd->size_in != sizeof(*erase)) 731 return -EINVAL; 732 733 if (cmd->size_out != 0) 734 return -EINVAL; 735 736 erase = cmd->payload_in; 737 if (mdata->security_state & CXL_PMEM_SEC_STATE_FROZEN) { 738 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 739 return -ENXIO; 740 } 741 742 if (mdata->security_state & CXL_PMEM_SEC_STATE_USER_PLIMIT && 743 erase->type == CXL_PMEM_SEC_PASS_USER) { 744 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 745 return -ENXIO; 746 } 747 748 if (mdata->security_state & CXL_PMEM_SEC_STATE_MASTER_PLIMIT && 749 erase->type == CXL_PMEM_SEC_PASS_MASTER) { 750 cmd->return_code = CXL_MBOX_CMD_RC_SECURITY; 751 return -ENXIO; 752 } 753 754 switch (erase->type) { 755 case CXL_PMEM_SEC_PASS_MASTER: 756 /* 757 * The spec does not clearly define the behavior of the scenario 758 * where a master passphrase is passed in while the master 759 * passphrase is not set and user passphrase is not set. The 760 * code will take the assumption that it will behave the same 761 * as a CXL secure erase command without passphrase (0x4401). 762 */ 763 if (mdata->security_state & CXL_PMEM_SEC_STATE_MASTER_PASS_SET) { 764 if (memcmp(mdata->master_pass, erase->pass, 765 NVDIMM_PASSPHRASE_LEN)) { 766 master_plimit_check(mdata); 767 cmd->return_code = CXL_MBOX_CMD_RC_PASSPHRASE; 768 return -ENXIO; 769 } 770 mdata->master_limit = 0; 771 mdata->user_limit = 0; 772 mdata->security_state &= ~CXL_PMEM_SEC_STATE_USER_PASS_SET; 773 memset(mdata->user_pass, 0, NVDIMM_PASSPHRASE_LEN); 774 mdata->security_state &= ~CXL_PMEM_SEC_STATE_LOCKED; 775 } else { 776 /* 777 * CXL rev3 8.2.9.8.6.3 Disable Passphrase 778 * When master passphrase is disabled, the device shall 779 * return Invalid Input for the Passphrase Secure Erase 780 * command with master passphrase. 781 */ 782 return -EINVAL; 783 } 784 /* Scramble encryption keys so that data is effectively erased */ 785 break; 786 case CXL_PMEM_SEC_PASS_USER: 787 /* 788 * The spec does not clearly define the behavior of the scenario 789 * where a user passphrase is passed in while the user 790 * passphrase is not set. The code will take the assumption that 791 * it will behave the same as a CXL secure erase command without 792 * passphrase (0x4401). 793 */ 794 if (mdata->security_state & CXL_PMEM_SEC_STATE_USER_PASS_SET) { 795 if (memcmp(mdata->user_pass, erase->pass, 796 NVDIMM_PASSPHRASE_LEN)) { 797 user_plimit_check(mdata); 798 cmd->return_code = CXL_MBOX_CMD_RC_PASSPHRASE; 799 return -ENXIO; 800 } 801 mdata->user_limit = 0; 802 mdata->security_state &= ~CXL_PMEM_SEC_STATE_USER_PASS_SET; 803 memset(mdata->user_pass, 0, NVDIMM_PASSPHRASE_LEN); 804 } 805 806 /* 807 * CXL rev3 Table 8-118 808 * If user passphrase is not set or supported by device, current 809 * passphrase value is ignored. Will make the assumption that 810 * the operation will proceed as secure erase w/o passphrase 811 * since spec is not explicit. 812 */ 813 814 /* Scramble encryption keys so that data is effectively erased */ 815 break; 816 default: 817 return -EINVAL; 818 } 819 820 return 0; 821 } 822 823 static int mock_get_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 824 { 825 struct cxl_mbox_get_lsa *get_lsa = cmd->payload_in; 826 struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev); 827 void *lsa = mdata->lsa; 828 u32 offset, length; 829 830 if (sizeof(*get_lsa) > cmd->size_in) 831 return -EINVAL; 832 offset = le32_to_cpu(get_lsa->offset); 833 length = le32_to_cpu(get_lsa->length); 834 if (offset + length > LSA_SIZE) 835 return -EINVAL; 836 if (length > cmd->size_out) 837 return -EINVAL; 838 839 memcpy(cmd->payload_out, lsa + offset, length); 840 return 0; 841 } 842 843 static int mock_set_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 844 { 845 struct cxl_mbox_set_lsa *set_lsa = cmd->payload_in; 846 struct cxl_mockmem_data *mdata = dev_get_drvdata(cxlds->dev); 847 void *lsa = mdata->lsa; 848 u32 offset, length; 849 850 if (sizeof(*set_lsa) > cmd->size_in) 851 return -EINVAL; 852 offset = le32_to_cpu(set_lsa->offset); 853 length = cmd->size_in - sizeof(*set_lsa); 854 if (offset + length > LSA_SIZE) 855 return -EINVAL; 856 857 memcpy(lsa + offset, &set_lsa->data[0], length); 858 return 0; 859 } 860 861 static int mock_health_info(struct cxl_dev_state *cxlds, 862 struct cxl_mbox_cmd *cmd) 863 { 864 struct cxl_mbox_health_info health_info = { 865 /* set flags for maint needed, perf degraded, hw replacement */ 866 .health_status = 0x7, 867 /* set media status to "All Data Lost" */ 868 .media_status = 0x3, 869 /* 870 * set ext_status flags for: 871 * ext_life_used: normal, 872 * ext_temperature: critical, 873 * ext_corrected_volatile: warning, 874 * ext_corrected_persistent: normal, 875 */ 876 .ext_status = 0x18, 877 .life_used = 15, 878 .temperature = cpu_to_le16(25), 879 .dirty_shutdowns = cpu_to_le32(10), 880 .volatile_errors = cpu_to_le32(20), 881 .pmem_errors = cpu_to_le32(30), 882 }; 883 884 if (cmd->size_out < sizeof(health_info)) 885 return -EINVAL; 886 887 memcpy(cmd->payload_out, &health_info, sizeof(health_info)); 888 return 0; 889 } 890 891 static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) 892 { 893 struct device *dev = cxlds->dev; 894 int rc = -EIO; 895 896 switch (cmd->opcode) { 897 case CXL_MBOX_OP_GET_SUPPORTED_LOGS: 898 rc = mock_gsl(cmd); 899 break; 900 case CXL_MBOX_OP_GET_LOG: 901 rc = mock_get_log(cxlds, cmd); 902 break; 903 case CXL_MBOX_OP_IDENTIFY: 904 if (cxlds->rcd) 905 rc = mock_rcd_id(cxlds, cmd); 906 else 907 rc = mock_id(cxlds, cmd); 908 break; 909 case CXL_MBOX_OP_GET_LSA: 910 rc = mock_get_lsa(cxlds, cmd); 911 break; 912 case CXL_MBOX_OP_GET_PARTITION_INFO: 913 rc = mock_partition_info(cxlds, cmd); 914 break; 915 case CXL_MBOX_OP_GET_EVENT_RECORD: 916 rc = mock_get_event(cxlds, cmd); 917 break; 918 case CXL_MBOX_OP_CLEAR_EVENT_RECORD: 919 rc = mock_clear_event(cxlds, cmd); 920 break; 921 case CXL_MBOX_OP_SET_LSA: 922 rc = mock_set_lsa(cxlds, cmd); 923 break; 924 case CXL_MBOX_OP_GET_HEALTH_INFO: 925 rc = mock_health_info(cxlds, cmd); 926 break; 927 case CXL_MBOX_OP_GET_SECURITY_STATE: 928 rc = mock_get_security_state(cxlds, cmd); 929 break; 930 case CXL_MBOX_OP_SET_PASSPHRASE: 931 rc = mock_set_passphrase(cxlds, cmd); 932 break; 933 case CXL_MBOX_OP_DISABLE_PASSPHRASE: 934 rc = mock_disable_passphrase(cxlds, cmd); 935 break; 936 case CXL_MBOX_OP_FREEZE_SECURITY: 937 rc = mock_freeze_security(cxlds, cmd); 938 break; 939 case CXL_MBOX_OP_UNLOCK: 940 rc = mock_unlock_security(cxlds, cmd); 941 break; 942 case CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE: 943 rc = mock_passphrase_secure_erase(cxlds, cmd); 944 break; 945 default: 946 break; 947 } 948 949 dev_dbg(dev, "opcode: %#x sz_in: %zd sz_out: %zd rc: %d\n", cmd->opcode, 950 cmd->size_in, cmd->size_out, rc); 951 952 return rc; 953 } 954 955 static void label_area_release(void *lsa) 956 { 957 vfree(lsa); 958 } 959 960 static bool is_rcd(struct platform_device *pdev) 961 { 962 const struct platform_device_id *id = platform_get_device_id(pdev); 963 964 return !!id->driver_data; 965 } 966 967 static ssize_t event_trigger_store(struct device *dev, 968 struct device_attribute *attr, 969 const char *buf, size_t count) 970 { 971 cxl_mock_event_trigger(dev); 972 return count; 973 } 974 static DEVICE_ATTR_WO(event_trigger); 975 976 static int cxl_mock_mem_probe(struct platform_device *pdev) 977 { 978 struct device *dev = &pdev->dev; 979 struct cxl_memdev *cxlmd; 980 struct cxl_dev_state *cxlds; 981 struct cxl_mockmem_data *mdata; 982 int rc; 983 984 mdata = devm_kzalloc(dev, sizeof(*mdata), GFP_KERNEL); 985 if (!mdata) 986 return -ENOMEM; 987 dev_set_drvdata(dev, mdata); 988 989 mdata->lsa = vmalloc(LSA_SIZE); 990 if (!mdata->lsa) 991 return -ENOMEM; 992 rc = devm_add_action_or_reset(dev, label_area_release, mdata->lsa); 993 if (rc) 994 return rc; 995 996 cxlds = cxl_dev_state_create(dev); 997 if (IS_ERR(cxlds)) 998 return PTR_ERR(cxlds); 999 1000 cxlds->serial = pdev->id; 1001 cxlds->mbox_send = cxl_mock_mbox_send; 1002 cxlds->payload_size = SZ_4K; 1003 cxlds->event.buf = (struct cxl_get_event_payload *) mdata->event_buf; 1004 if (is_rcd(pdev)) { 1005 cxlds->rcd = true; 1006 cxlds->component_reg_phys = CXL_RESOURCE_NONE; 1007 } 1008 1009 rc = cxl_enumerate_cmds(cxlds); 1010 if (rc) 1011 return rc; 1012 1013 rc = cxl_dev_state_identify(cxlds); 1014 if (rc) 1015 return rc; 1016 1017 rc = cxl_mem_create_range_info(cxlds); 1018 if (rc) 1019 return rc; 1020 1021 mdata->mes.cxlds = cxlds; 1022 cxl_mock_add_event_logs(&mdata->mes); 1023 1024 cxlmd = devm_cxl_add_memdev(cxlds); 1025 if (IS_ERR(cxlmd)) 1026 return PTR_ERR(cxlmd); 1027 1028 cxl_mem_get_event_records(cxlds, CXLDEV_EVENT_STATUS_ALL); 1029 1030 return 0; 1031 } 1032 1033 static ssize_t security_lock_show(struct device *dev, 1034 struct device_attribute *attr, char *buf) 1035 { 1036 struct cxl_mockmem_data *mdata = dev_get_drvdata(dev); 1037 1038 return sysfs_emit(buf, "%u\n", 1039 !!(mdata->security_state & CXL_PMEM_SEC_STATE_LOCKED)); 1040 } 1041 1042 static ssize_t security_lock_store(struct device *dev, struct device_attribute *attr, 1043 const char *buf, size_t count) 1044 { 1045 struct cxl_mockmem_data *mdata = dev_get_drvdata(dev); 1046 u32 mask = CXL_PMEM_SEC_STATE_FROZEN | CXL_PMEM_SEC_STATE_USER_PLIMIT | 1047 CXL_PMEM_SEC_STATE_MASTER_PLIMIT; 1048 int val; 1049 1050 if (kstrtoint(buf, 0, &val) < 0) 1051 return -EINVAL; 1052 1053 if (val == 1) { 1054 if (!(mdata->security_state & CXL_PMEM_SEC_STATE_USER_PASS_SET)) 1055 return -ENXIO; 1056 mdata->security_state |= CXL_PMEM_SEC_STATE_LOCKED; 1057 mdata->security_state &= ~mask; 1058 } else { 1059 return -EINVAL; 1060 } 1061 return count; 1062 } 1063 1064 static DEVICE_ATTR_RW(security_lock); 1065 1066 static struct attribute *cxl_mock_mem_attrs[] = { 1067 &dev_attr_security_lock.attr, 1068 &dev_attr_event_trigger.attr, 1069 NULL 1070 }; 1071 ATTRIBUTE_GROUPS(cxl_mock_mem); 1072 1073 static const struct platform_device_id cxl_mock_mem_ids[] = { 1074 { .name = "cxl_mem", 0 }, 1075 { .name = "cxl_rcd", 1 }, 1076 { }, 1077 }; 1078 MODULE_DEVICE_TABLE(platform, cxl_mock_mem_ids); 1079 1080 static struct platform_driver cxl_mock_mem_driver = { 1081 .probe = cxl_mock_mem_probe, 1082 .id_table = cxl_mock_mem_ids, 1083 .driver = { 1084 .name = KBUILD_MODNAME, 1085 .dev_groups = cxl_mock_mem_groups, 1086 }, 1087 }; 1088 1089 module_platform_driver(cxl_mock_mem_driver); 1090 MODULE_LICENSE("GPL v2"); 1091 MODULE_IMPORT_NS(CXL); 1092