1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intel Platform Monitoring Technology Crashlog driver 4 * 5 * Copyright (c) 2020, Intel Corporation. 6 * All Rights Reserved. 7 * 8 * Author: "Alexander Duyck" <alexander.h.duyck@linux.intel.com> 9 */ 10 11 #include <linux/auxiliary_bus.h> 12 #include <linux/cleanup.h> 13 #include <linux/intel_vsec.h> 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/mutex.h> 17 #include <linux/pci.h> 18 #include <linux/slab.h> 19 #include <linux/uaccess.h> 20 #include <linux/overflow.h> 21 22 #include "class.h" 23 24 /* Crashlog discovery header types */ 25 #define CRASH_TYPE_OOBMSM 1 26 27 /* Crashlog Discovery Header */ 28 #define CONTROL_OFFSET 0x0 29 #define GUID_OFFSET 0x4 30 #define BASE_OFFSET 0x8 31 #define SIZE_OFFSET 0xC 32 #define GET_ACCESS(v) ((v) & GENMASK(3, 0)) 33 #define GET_TYPE(v) (((v) & GENMASK(7, 4)) >> 4) 34 #define GET_VERSION(v) (((v) & GENMASK(19, 16)) >> 16) 35 /* size is in bytes */ 36 #define GET_SIZE(v) ((v) * sizeof(u32)) 37 38 /* 39 * Type 1 Version 0 40 * status and control registers are combined. 41 * 42 * Bits 29 and 30 control the state of bit 31. 43 * Bit 29 will clear bit 31, if set, allowing a new crashlog to be captured. 44 * Bit 30 will immediately trigger a crashlog to be generated, setting bit 31. 45 * Bit 31 is the read-only status with a 1 indicating log is complete. 46 */ 47 #define TYPE1_VER0_STATUS_OFFSET 0x00 48 #define TYPE1_VER0_CONTROL_OFFSET 0x00 49 50 #define TYPE1_VER0_DISABLE BIT(28) 51 #define TYPE1_VER0_CLEAR BIT(29) 52 #define TYPE1_VER0_EXECUTE BIT(30) 53 #define TYPE1_VER0_COMPLETE BIT(31) 54 #define TYPE1_VER0_TRIGGER_MASK GENMASK(31, 28) 55 56 /* 57 * Type 1 Version 2 58 * status and control are different registers 59 */ 60 #define TYPE1_VER2_STATUS_OFFSET 0x00 61 #define TYPE1_VER2_CONTROL_OFFSET 0x14 62 63 /* status register */ 64 #define TYPE1_VER2_CLEAR_SUPPORT BIT(20) 65 #define TYPE1_VER2_REARMED BIT(25) 66 #define TYPE1_VER2_ERROR BIT(26) 67 #define TYPE1_VER2_CONSUMED BIT(27) 68 #define TYPE1_VER2_DISABLED BIT(28) 69 #define TYPE1_VER2_CLEARED BIT(29) 70 #define TYPE1_VER2_IN_PROGRESS BIT(30) 71 #define TYPE1_VER2_COMPLETE BIT(31) 72 73 /* control register */ 74 #define TYPE1_VER2_CONSUME BIT(25) 75 #define TYPE1_VER2_REARM BIT(28) 76 #define TYPE1_VER2_EXECUTE BIT(29) 77 #define TYPE1_VER2_CLEAR BIT(30) 78 #define TYPE1_VER2_DISABLE BIT(31) 79 #define TYPE1_VER2_TRIGGER_MASK \ 80 (TYPE1_VER2_EXECUTE | TYPE1_VER2_CLEAR | TYPE1_VER2_DISABLE) 81 82 /* After offset, order alphabetically, not bit ordered */ 83 struct crashlog_status { 84 u32 offset; 85 u32 clear_supported; 86 u32 cleared; 87 u32 complete; 88 u32 consumed; 89 u32 disabled; 90 u32 error; 91 u32 in_progress; 92 u32 rearmed; 93 }; 94 95 struct crashlog_control { 96 u32 offset; 97 u32 trigger_mask; 98 u32 clear; 99 u32 consume; 100 u32 disable; 101 u32 manual; 102 u32 rearm; 103 }; 104 105 struct crashlog_info { 106 const struct crashlog_status status; 107 const struct crashlog_control control; 108 const struct attribute_group *attr_grp; 109 }; 110 111 struct crashlog_entry { 112 /* entry must be first member of struct */ 113 struct intel_pmt_entry entry; 114 struct mutex control_mutex; 115 const struct crashlog_info *info; 116 }; 117 118 struct pmt_crashlog_priv { 119 int num_entries; 120 struct crashlog_entry entry[]; 121 }; 122 123 /* 124 * I/O 125 */ 126 127 /* Read, modify, write the control register, setting or clearing @bit based on @set */ 128 static void pmt_crashlog_rmw(struct crashlog_entry *crashlog, u32 bit, bool set) 129 { 130 const struct crashlog_control *control = &crashlog->info->control; 131 struct intel_pmt_entry *entry = &crashlog->entry; 132 u32 reg = readl(entry->disc_table + control->offset); 133 134 reg &= ~control->trigger_mask; 135 136 if (set) 137 reg |= bit; 138 else 139 reg &= ~bit; 140 141 writel(reg, entry->disc_table + control->offset); 142 } 143 144 /* Read the status register and see if the specified @bit is set */ 145 static bool pmt_crashlog_rc(struct crashlog_entry *crashlog, u32 bit) 146 { 147 const struct crashlog_status *status = &crashlog->info->status; 148 u32 reg = readl(crashlog->entry.disc_table + status->offset); 149 150 return !!(reg & bit); 151 } 152 153 static bool pmt_crashlog_complete(struct crashlog_entry *crashlog) 154 { 155 /* return current value of the crashlog complete flag */ 156 return pmt_crashlog_rc(crashlog, crashlog->info->status.complete); 157 } 158 159 static bool pmt_crashlog_disabled(struct crashlog_entry *crashlog) 160 { 161 /* return current value of the crashlog disabled flag */ 162 return pmt_crashlog_rc(crashlog, crashlog->info->status.disabled); 163 } 164 165 static bool pmt_crashlog_supported(struct intel_pmt_entry *entry, u32 *crash_type, u32 *version) 166 { 167 u32 discovery_header = readl(entry->disc_table + CONTROL_OFFSET); 168 169 *crash_type = GET_TYPE(discovery_header); 170 *version = GET_VERSION(discovery_header); 171 172 /* 173 * Currently we only recognize OOBMSM (type 1) and version 0 or 2 174 * devices. 175 * 176 * Ignore all other crashlog devices in the system. 177 */ 178 if (*crash_type == CRASH_TYPE_OOBMSM && (*version == 0 || *version == 2)) 179 return true; 180 181 return false; 182 } 183 184 static void pmt_crashlog_set_disable(struct crashlog_entry *crashlog, 185 bool disable) 186 { 187 pmt_crashlog_rmw(crashlog, crashlog->info->control.disable, disable); 188 } 189 190 static void pmt_crashlog_set_clear(struct crashlog_entry *crashlog) 191 { 192 pmt_crashlog_rmw(crashlog, crashlog->info->control.clear, true); 193 } 194 195 static void pmt_crashlog_set_execute(struct crashlog_entry *crashlog) 196 { 197 pmt_crashlog_rmw(crashlog, crashlog->info->control.manual, true); 198 } 199 200 static bool pmt_crashlog_cleared(struct crashlog_entry *crashlog) 201 { 202 return pmt_crashlog_rc(crashlog, crashlog->info->status.cleared); 203 } 204 205 static bool pmt_crashlog_consumed(struct crashlog_entry *crashlog) 206 { 207 return pmt_crashlog_rc(crashlog, crashlog->info->status.consumed); 208 } 209 210 static void pmt_crashlog_set_consumed(struct crashlog_entry *crashlog) 211 { 212 pmt_crashlog_rmw(crashlog, crashlog->info->control.consume, true); 213 } 214 215 static bool pmt_crashlog_error(struct crashlog_entry *crashlog) 216 { 217 return pmt_crashlog_rc(crashlog, crashlog->info->status.error); 218 } 219 220 static bool pmt_crashlog_rearm(struct crashlog_entry *crashlog) 221 { 222 return pmt_crashlog_rc(crashlog, crashlog->info->status.rearmed); 223 } 224 225 static void pmt_crashlog_set_rearm(struct crashlog_entry *crashlog) 226 { 227 pmt_crashlog_rmw(crashlog, crashlog->info->control.rearm, true); 228 } 229 230 /* 231 * sysfs 232 */ 233 static ssize_t 234 clear_show(struct device *dev, struct device_attribute *attr, char *buf) 235 { 236 struct crashlog_entry *crashlog = dev_get_drvdata(dev); 237 bool cleared = pmt_crashlog_cleared(crashlog); 238 239 return sysfs_emit(buf, "%d\n", cleared); 240 } 241 242 static ssize_t 243 clear_store(struct device *dev, struct device_attribute *attr, 244 const char *buf, size_t count) 245 { 246 struct crashlog_entry *crashlog; 247 bool clear; 248 int result; 249 250 crashlog = dev_get_drvdata(dev); 251 252 result = kstrtobool(buf, &clear); 253 if (result) 254 return result; 255 256 /* set bit only */ 257 if (!clear) 258 return -EINVAL; 259 260 guard(mutex)(&crashlog->control_mutex); 261 262 pmt_crashlog_set_clear(crashlog); 263 264 return count; 265 } 266 static DEVICE_ATTR_RW(clear); 267 268 static ssize_t 269 consumed_show(struct device *dev, struct device_attribute *attr, char *buf) 270 { 271 struct crashlog_entry *crashlog = dev_get_drvdata(dev); 272 bool consumed = pmt_crashlog_consumed(crashlog); 273 274 return sysfs_emit(buf, "%d\n", consumed); 275 } 276 277 static ssize_t 278 consumed_store(struct device *dev, struct device_attribute *attr, const char *buf, 279 size_t count) 280 { 281 struct crashlog_entry *crashlog; 282 bool consumed; 283 int result; 284 285 crashlog = dev_get_drvdata(dev); 286 287 result = kstrtobool(buf, &consumed); 288 if (result) 289 return result; 290 291 /* set bit only */ 292 if (!consumed) 293 return -EINVAL; 294 295 guard(mutex)(&crashlog->control_mutex); 296 297 if (pmt_crashlog_disabled(crashlog)) 298 return -EBUSY; 299 300 if (!pmt_crashlog_complete(crashlog)) 301 return -EEXIST; 302 303 pmt_crashlog_set_consumed(crashlog); 304 305 return count; 306 } 307 static DEVICE_ATTR_RW(consumed); 308 309 static ssize_t 310 enable_show(struct device *dev, struct device_attribute *attr, char *buf) 311 { 312 struct crashlog_entry *crashlog = dev_get_drvdata(dev); 313 bool enabled = !pmt_crashlog_disabled(crashlog); 314 315 return sprintf(buf, "%d\n", enabled); 316 } 317 318 static ssize_t 319 enable_store(struct device *dev, struct device_attribute *attr, 320 const char *buf, size_t count) 321 { 322 struct crashlog_entry *crashlog; 323 bool enabled; 324 int result; 325 326 crashlog = dev_get_drvdata(dev); 327 328 result = kstrtobool(buf, &enabled); 329 if (result) 330 return result; 331 332 guard(mutex)(&crashlog->control_mutex); 333 334 pmt_crashlog_set_disable(crashlog, !enabled); 335 336 return count; 337 } 338 static DEVICE_ATTR_RW(enable); 339 340 static ssize_t 341 error_show(struct device *dev, struct device_attribute *attr, char *buf) 342 { 343 struct crashlog_entry *crashlog = dev_get_drvdata(dev); 344 bool error = pmt_crashlog_error(crashlog); 345 346 return sysfs_emit(buf, "%d\n", error); 347 } 348 static DEVICE_ATTR_RO(error); 349 350 static ssize_t 351 rearm_show(struct device *dev, struct device_attribute *attr, char *buf) 352 { 353 struct crashlog_entry *crashlog = dev_get_drvdata(dev); 354 int rearmed = pmt_crashlog_rearm(crashlog); 355 356 return sysfs_emit(buf, "%d\n", rearmed); 357 } 358 359 static ssize_t 360 rearm_store(struct device *dev, struct device_attribute *attr, const char *buf, 361 size_t count) 362 { 363 struct crashlog_entry *crashlog; 364 bool rearm; 365 int result; 366 367 crashlog = dev_get_drvdata(dev); 368 369 result = kstrtobool(buf, &rearm); 370 if (result) 371 return result; 372 373 /* set only */ 374 if (!rearm) 375 return -EINVAL; 376 377 guard(mutex)(&crashlog->control_mutex); 378 379 pmt_crashlog_set_rearm(crashlog); 380 381 return count; 382 } 383 static DEVICE_ATTR_RW(rearm); 384 385 static ssize_t 386 trigger_show(struct device *dev, struct device_attribute *attr, char *buf) 387 { 388 struct crashlog_entry *crashlog; 389 bool trigger; 390 391 crashlog = dev_get_drvdata(dev); 392 trigger = pmt_crashlog_complete(crashlog); 393 394 return sprintf(buf, "%d\n", trigger); 395 } 396 397 static ssize_t 398 trigger_store(struct device *dev, struct device_attribute *attr, 399 const char *buf, size_t count) 400 { 401 struct crashlog_entry *crashlog; 402 bool trigger; 403 int result; 404 405 crashlog = dev_get_drvdata(dev); 406 407 result = kstrtobool(buf, &trigger); 408 if (result) 409 return result; 410 411 guard(mutex)(&crashlog->control_mutex); 412 413 /* if device is currently disabled, return busy */ 414 if (pmt_crashlog_disabled(crashlog)) 415 return -EBUSY; 416 417 if (!trigger) { 418 pmt_crashlog_set_clear(crashlog); 419 return count; 420 } 421 422 /* we cannot trigger a new crash if one is still pending */ 423 if (pmt_crashlog_complete(crashlog)) 424 return -EEXIST; 425 426 pmt_crashlog_set_execute(crashlog); 427 428 return count; 429 } 430 static DEVICE_ATTR_RW(trigger); 431 432 static struct attribute *pmt_crashlog_type1_ver0_attrs[] = { 433 &dev_attr_enable.attr, 434 &dev_attr_trigger.attr, 435 NULL 436 }; 437 438 static struct attribute *pmt_crashlog_type1_ver2_attrs[] = { 439 &dev_attr_clear.attr, 440 &dev_attr_consumed.attr, 441 &dev_attr_enable.attr, 442 &dev_attr_error.attr, 443 &dev_attr_rearm.attr, 444 &dev_attr_trigger.attr, 445 NULL 446 }; 447 448 static const struct attribute_group pmt_crashlog_type1_ver0_group = { 449 .attrs = pmt_crashlog_type1_ver0_attrs, 450 }; 451 452 static const struct attribute_group pmt_crashlog_type1_ver2_group = { 453 .attrs = pmt_crashlog_type1_ver2_attrs, 454 }; 455 456 static const struct crashlog_info crashlog_type1_ver0 = { 457 .status.offset = TYPE1_VER0_STATUS_OFFSET, 458 .status.cleared = TYPE1_VER0_CLEAR, 459 .status.complete = TYPE1_VER0_COMPLETE, 460 .status.disabled = TYPE1_VER0_DISABLE, 461 462 .control.offset = TYPE1_VER0_CONTROL_OFFSET, 463 .control.trigger_mask = TYPE1_VER0_TRIGGER_MASK, 464 .control.clear = TYPE1_VER0_CLEAR, 465 .control.disable = TYPE1_VER0_DISABLE, 466 .control.manual = TYPE1_VER0_EXECUTE, 467 .attr_grp = &pmt_crashlog_type1_ver0_group, 468 }; 469 470 static const struct crashlog_info crashlog_type1_ver2 = { 471 .status.offset = TYPE1_VER2_STATUS_OFFSET, 472 .status.clear_supported = TYPE1_VER2_CLEAR_SUPPORT, 473 .status.cleared = TYPE1_VER2_CLEARED, 474 .status.complete = TYPE1_VER2_COMPLETE, 475 .status.consumed = TYPE1_VER2_CONSUMED, 476 .status.disabled = TYPE1_VER2_DISABLED, 477 .status.error = TYPE1_VER2_ERROR, 478 .status.in_progress = TYPE1_VER2_IN_PROGRESS, 479 .status.rearmed = TYPE1_VER2_REARMED, 480 481 .control.offset = TYPE1_VER2_CONTROL_OFFSET, 482 .control.trigger_mask = TYPE1_VER2_TRIGGER_MASK, 483 .control.clear = TYPE1_VER2_CLEAR, 484 .control.consume = TYPE1_VER2_CONSUME, 485 .control.disable = TYPE1_VER2_DISABLE, 486 .control.manual = TYPE1_VER2_EXECUTE, 487 .control.rearm = TYPE1_VER2_REARM, 488 .attr_grp = &pmt_crashlog_type1_ver2_group, 489 }; 490 491 static const struct crashlog_info *select_crashlog_info(u32 type, u32 version) 492 { 493 if (version == 0) 494 return &crashlog_type1_ver0; 495 496 return &crashlog_type1_ver2; 497 } 498 499 static int pmt_crashlog_header_decode(struct intel_pmt_entry *entry, 500 struct device *dev) 501 { 502 void __iomem *disc_table = entry->disc_table; 503 struct intel_pmt_header *header = &entry->header; 504 struct crashlog_entry *crashlog; 505 u32 version; 506 u32 type; 507 508 if (!pmt_crashlog_supported(entry, &type, &version)) 509 return 1; 510 511 /* initialize the crashlog struct */ 512 crashlog = container_of(entry, struct crashlog_entry, entry); 513 mutex_init(&crashlog->control_mutex); 514 515 crashlog->info = select_crashlog_info(type, version); 516 517 header->access_type = GET_ACCESS(readl(disc_table)); 518 header->guid = readl(disc_table + GUID_OFFSET); 519 header->base_offset = readl(disc_table + BASE_OFFSET); 520 521 /* Size is measured in DWORDS, but accessor returns bytes */ 522 header->size = GET_SIZE(readl(disc_table + SIZE_OFFSET)); 523 524 entry->attr_grp = crashlog->info->attr_grp; 525 526 return 0; 527 } 528 529 static DEFINE_XARRAY_ALLOC(crashlog_array); 530 static struct intel_pmt_namespace pmt_crashlog_ns = { 531 .name = "crashlog", 532 .xa = &crashlog_array, 533 .pmt_header_decode = pmt_crashlog_header_decode, 534 }; 535 536 /* 537 * initialization 538 */ 539 static void pmt_crashlog_remove(struct auxiliary_device *auxdev) 540 { 541 struct pmt_crashlog_priv *priv = auxiliary_get_drvdata(auxdev); 542 int i; 543 544 for (i = 0; i < priv->num_entries; i++) { 545 struct crashlog_entry *crashlog = &priv->entry[i]; 546 547 intel_pmt_dev_destroy(&crashlog->entry, &pmt_crashlog_ns); 548 mutex_destroy(&crashlog->control_mutex); 549 } 550 } 551 552 static int pmt_crashlog_probe(struct auxiliary_device *auxdev, 553 const struct auxiliary_device_id *id) 554 { 555 struct intel_vsec_device *intel_vsec_dev = auxdev_to_ivdev(auxdev); 556 struct pmt_crashlog_priv *priv; 557 size_t size; 558 int i, ret; 559 560 size = struct_size(priv, entry, intel_vsec_dev->num_resources); 561 priv = devm_kzalloc(&auxdev->dev, size, GFP_KERNEL); 562 if (!priv) 563 return -ENOMEM; 564 565 auxiliary_set_drvdata(auxdev, priv); 566 567 for (i = 0; i < intel_vsec_dev->num_resources; i++) { 568 struct intel_pmt_entry *entry = &priv->entry[priv->num_entries].entry; 569 570 ret = intel_pmt_dev_create(entry, &pmt_crashlog_ns, intel_vsec_dev, i); 571 if (ret < 0) 572 goto abort_probe; 573 if (ret) 574 continue; 575 576 priv->num_entries++; 577 } 578 579 return 0; 580 abort_probe: 581 pmt_crashlog_remove(auxdev); 582 return ret; 583 } 584 585 static const struct auxiliary_device_id pmt_crashlog_id_table[] = { 586 { .name = "intel_vsec.crashlog" }, 587 {} 588 }; 589 MODULE_DEVICE_TABLE(auxiliary, pmt_crashlog_id_table); 590 591 static struct auxiliary_driver pmt_crashlog_aux_driver = { 592 .id_table = pmt_crashlog_id_table, 593 .remove = pmt_crashlog_remove, 594 .probe = pmt_crashlog_probe, 595 }; 596 597 static int __init pmt_crashlog_init(void) 598 { 599 return auxiliary_driver_register(&pmt_crashlog_aux_driver); 600 } 601 602 static void __exit pmt_crashlog_exit(void) 603 { 604 auxiliary_driver_unregister(&pmt_crashlog_aux_driver); 605 xa_destroy(&crashlog_array); 606 } 607 608 module_init(pmt_crashlog_init); 609 module_exit(pmt_crashlog_exit); 610 611 MODULE_AUTHOR("Alexander Duyck <alexander.h.duyck@linux.intel.com>"); 612 MODULE_DESCRIPTION("Intel PMT Crashlog driver"); 613 MODULE_LICENSE("GPL v2"); 614 MODULE_IMPORT_NS("INTEL_PMT"); 615