1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intel Platform Monitory Technology Discovery driver 4 * 5 * Copyright (c) 2025, Intel Corporation. 6 * All Rights Reserved. 7 */ 8 9 #include <linux/auxiliary_bus.h> 10 #include <linux/bitfield.h> 11 #include <linux/bits.h> 12 #include <linux/bug.h> 13 #include <linux/cleanup.h> 14 #include <linux/container_of.h> 15 #include <linux/device.h> 16 #include <linux/err.h> 17 #include <linux/io.h> 18 #include <linux/ioport.h> 19 #include <linux/kdev_t.h> 20 #include <linux/kobject.h> 21 #include <linux/list.h> 22 #include <linux/module.h> 23 #include <linux/mutex.h> 24 #include <linux/overflow.h> 25 #include <linux/pci.h> 26 #include <linux/slab.h> 27 #include <linux/string_choices.h> 28 #include <linux/sysfs.h> 29 #include <linux/types.h> 30 #include <linux/uaccess.h> 31 32 #include <linux/intel_pmt_features.h> 33 #include <linux/intel_vsec.h> 34 35 #include "class.h" 36 37 #define MAX_FEATURE_VERSION 0 38 #define DT_TBIR GENMASK(2, 0) 39 #define FEAT_ATTR_SIZE(x) ((x) * sizeof(u32)) 40 #define PMT_GUID_SIZE(x) ((x) * sizeof(u32)) 41 #define PMT_ACCESS_TYPE_RSVD 0xF 42 #define SKIP_FEATURE 1 43 44 struct feature_discovery_table { 45 u32 access_type:4; 46 u32 version:8; 47 u32 size:16; 48 u32 reserved:4; 49 u32 id; 50 u32 offset; 51 u32 reserved2; 52 }; 53 54 /* Common feature table header */ 55 struct feature_header { 56 u32 attr_size:8; 57 u32 num_guids:8; 58 u32 reserved:16; 59 }; 60 61 /* Feature attribute fields */ 62 struct caps { 63 u32 caps; 64 }; 65 66 struct command { 67 u32 max_stream_size:16; 68 u32 max_command_size:16; 69 }; 70 71 struct watcher { 72 u32 reserved:21; 73 u32 period:11; 74 struct command command; 75 }; 76 77 struct rmid { 78 u32 num_rmids:16; /* Number of Resource Monitoring IDs */ 79 u32 reserved:16; 80 struct watcher watcher; 81 }; 82 83 struct feature_table { 84 struct feature_header header; 85 struct caps caps; 86 union { 87 struct command command; 88 struct watcher watcher; 89 struct rmid rmid; 90 }; 91 u32 *guids; 92 }; 93 94 /* For backreference in struct feature */ 95 struct pmt_features_priv; 96 97 struct feature { 98 struct feature_table table; 99 struct kobject kobj; 100 struct pmt_features_priv *priv; 101 struct list_head list; 102 const struct attribute_group *attr_group; 103 enum pmt_feature_id id; 104 }; 105 106 struct pmt_features_priv { 107 struct device *parent; 108 struct device *dev; 109 int count; 110 u32 mask; 111 struct feature feature[]; 112 }; 113 114 static LIST_HEAD(pmt_feature_list); 115 static DEFINE_MUTEX(feature_list_lock); 116 117 #define to_pmt_feature(x) container_of(x, struct feature, kobj) 118 static void pmt_feature_release(struct kobject *kobj) 119 { 120 } 121 122 static ssize_t caps_show(struct kobject *kobj, struct kobj_attribute *attr, 123 char *buf) 124 { 125 struct feature *feature = to_pmt_feature(kobj); 126 struct pmt_cap **pmt_caps; 127 u32 caps = feature->table.caps.caps; 128 ssize_t ret = 0; 129 130 switch (feature->id) { 131 case FEATURE_PER_CORE_PERF_TELEM: 132 pmt_caps = pmt_caps_pcpt; 133 break; 134 case FEATURE_PER_CORE_ENV_TELEM: 135 pmt_caps = pmt_caps_pcet; 136 break; 137 case FEATURE_PER_RMID_PERF_TELEM: 138 pmt_caps = pmt_caps_rmid_perf; 139 break; 140 case FEATURE_ACCEL_TELEM: 141 pmt_caps = pmt_caps_accel; 142 break; 143 case FEATURE_UNCORE_TELEM: 144 pmt_caps = pmt_caps_uncore; 145 break; 146 case FEATURE_CRASH_LOG: 147 pmt_caps = pmt_caps_crashlog; 148 break; 149 case FEATURE_PETE_LOG: 150 pmt_caps = pmt_caps_pete; 151 break; 152 case FEATURE_TPMI_CTRL: 153 pmt_caps = pmt_caps_tpmi; 154 break; 155 case FEATURE_TRACING: 156 pmt_caps = pmt_caps_tracing; 157 break; 158 case FEATURE_PER_RMID_ENERGY_TELEM: 159 pmt_caps = pmt_caps_rmid_energy; 160 break; 161 default: 162 return -EINVAL; 163 } 164 165 while (*pmt_caps) { 166 struct pmt_cap *pmt_cap = *pmt_caps; 167 168 while (pmt_cap->name) { 169 ret += sysfs_emit_at(buf, ret, "%-40s Available: %s\n", pmt_cap->name, 170 str_yes_no(pmt_cap->mask & caps)); 171 pmt_cap++; 172 } 173 pmt_caps++; 174 } 175 176 return ret; 177 } 178 static struct kobj_attribute caps_attribute = __ATTR_RO(caps); 179 180 static struct watcher *get_watcher(struct feature *feature) 181 { 182 switch (feature_layout[feature->id]) { 183 case LAYOUT_RMID: 184 return &feature->table.rmid.watcher; 185 case LAYOUT_WATCHER: 186 return &feature->table.watcher; 187 default: 188 return ERR_PTR(-EINVAL); 189 } 190 } 191 192 static struct command *get_command(struct feature *feature) 193 { 194 switch (feature_layout[feature->id]) { 195 case LAYOUT_RMID: 196 return &feature->table.rmid.watcher.command; 197 case LAYOUT_WATCHER: 198 return &feature->table.watcher.command; 199 case LAYOUT_COMMAND: 200 return &feature->table.command; 201 default: 202 return ERR_PTR(-EINVAL); 203 } 204 } 205 206 static ssize_t num_rmids_show(struct kobject *kobj, 207 struct kobj_attribute *attr, char *buf) 208 { 209 struct feature *feature = to_pmt_feature(kobj); 210 211 return sysfs_emit(buf, "%u\n", feature->table.rmid.num_rmids); 212 } 213 static struct kobj_attribute num_rmids_attribute = __ATTR_RO(num_rmids); 214 215 static ssize_t min_watcher_period_ms_show(struct kobject *kobj, 216 struct kobj_attribute *attr, char *buf) 217 { 218 struct feature *feature = to_pmt_feature(kobj); 219 struct watcher *watcher = get_watcher(feature); 220 221 if (IS_ERR(watcher)) 222 return PTR_ERR(watcher); 223 224 return sysfs_emit(buf, "%u\n", watcher->period); 225 } 226 static struct kobj_attribute min_watcher_period_ms_attribute = 227 __ATTR_RO(min_watcher_period_ms); 228 229 static ssize_t max_stream_size_show(struct kobject *kobj, 230 struct kobj_attribute *attr, char *buf) 231 { 232 struct feature *feature = to_pmt_feature(kobj); 233 struct command *command = get_command(feature); 234 235 if (IS_ERR(command)) 236 return PTR_ERR(command); 237 238 return sysfs_emit(buf, "%u\n", command->max_stream_size); 239 } 240 static struct kobj_attribute max_stream_size_attribute = 241 __ATTR_RO(max_stream_size); 242 243 static ssize_t max_command_size_show(struct kobject *kobj, 244 struct kobj_attribute *attr, char *buf) 245 { 246 struct feature *feature = to_pmt_feature(kobj); 247 struct command *command = get_command(feature); 248 249 if (IS_ERR(command)) 250 return PTR_ERR(command); 251 252 return sysfs_emit(buf, "%u\n", command->max_command_size); 253 } 254 static struct kobj_attribute max_command_size_attribute = 255 __ATTR_RO(max_command_size); 256 257 static ssize_t guids_show(struct kobject *kobj, struct kobj_attribute *attr, 258 char *buf) 259 { 260 struct feature *feature = to_pmt_feature(kobj); 261 int i, count = 0; 262 263 for (i = 0; i < feature->table.header.num_guids; i++) 264 count += sysfs_emit_at(buf, count, "0x%x\n", 265 feature->table.guids[i]); 266 267 return count; 268 } 269 static struct kobj_attribute guids_attribute = __ATTR_RO(guids); 270 271 static struct attribute *pmt_feature_rmid_attrs[] = { 272 &caps_attribute.attr, 273 &num_rmids_attribute.attr, 274 &min_watcher_period_ms_attribute.attr, 275 &max_stream_size_attribute.attr, 276 &max_command_size_attribute.attr, 277 &guids_attribute.attr, 278 NULL 279 }; 280 ATTRIBUTE_GROUPS(pmt_feature_rmid); 281 282 static const struct kobj_type pmt_feature_rmid_ktype = { 283 .sysfs_ops = &kobj_sysfs_ops, 284 .release = pmt_feature_release, 285 .default_groups = pmt_feature_rmid_groups, 286 }; 287 288 static struct attribute *pmt_feature_watcher_attrs[] = { 289 &caps_attribute.attr, 290 &min_watcher_period_ms_attribute.attr, 291 &max_stream_size_attribute.attr, 292 &max_command_size_attribute.attr, 293 &guids_attribute.attr, 294 NULL 295 }; 296 ATTRIBUTE_GROUPS(pmt_feature_watcher); 297 298 static const struct kobj_type pmt_feature_watcher_ktype = { 299 .sysfs_ops = &kobj_sysfs_ops, 300 .release = pmt_feature_release, 301 .default_groups = pmt_feature_watcher_groups, 302 }; 303 304 static struct attribute *pmt_feature_command_attrs[] = { 305 &caps_attribute.attr, 306 &max_stream_size_attribute.attr, 307 &max_command_size_attribute.attr, 308 &guids_attribute.attr, 309 NULL 310 }; 311 ATTRIBUTE_GROUPS(pmt_feature_command); 312 313 static const struct kobj_type pmt_feature_command_ktype = { 314 .sysfs_ops = &kobj_sysfs_ops, 315 .release = pmt_feature_release, 316 .default_groups = pmt_feature_command_groups, 317 }; 318 319 static struct attribute *pmt_feature_guids_attrs[] = { 320 &caps_attribute.attr, 321 &guids_attribute.attr, 322 NULL 323 }; 324 ATTRIBUTE_GROUPS(pmt_feature_guids); 325 326 static const struct kobj_type pmt_feature_guids_ktype = { 327 .sysfs_ops = &kobj_sysfs_ops, 328 .release = pmt_feature_release, 329 .default_groups = pmt_feature_guids_groups, 330 }; 331 332 static int 333 pmt_feature_get_disc_table(struct pmt_features_priv *priv, 334 struct resource *disc_res, 335 struct feature_discovery_table *disc_tbl) 336 { 337 void __iomem *disc_base; 338 339 disc_base = devm_ioremap_resource(priv->dev, disc_res); 340 if (IS_ERR(disc_base)) 341 return PTR_ERR(disc_base); 342 343 memcpy_fromio(disc_tbl, disc_base, sizeof(*disc_tbl)); 344 345 devm_iounmap(priv->dev, disc_base); 346 347 if (priv->mask & BIT(disc_tbl->id)) 348 return dev_err_probe(priv->dev, -EINVAL, "Duplicate feature: %s\n", 349 pmt_feature_names[disc_tbl->id]); 350 351 /* 352 * Some devices may expose non-functioning entries that are 353 * reserved for future use. They have zero size. Do not fail 354 * probe for these. Just ignore them. 355 */ 356 if (disc_tbl->size == 0 || disc_tbl->access_type == PMT_ACCESS_TYPE_RSVD) 357 return SKIP_FEATURE; 358 359 if (disc_tbl->version > MAX_FEATURE_VERSION) 360 return SKIP_FEATURE; 361 362 if (!pmt_feature_id_is_valid(disc_tbl->id)) 363 return SKIP_FEATURE; 364 365 priv->mask |= BIT(disc_tbl->id); 366 367 return 0; 368 } 369 370 static int 371 pmt_feature_get_feature_table(struct pmt_features_priv *priv, 372 struct feature *feature, 373 struct feature_discovery_table *disc_tbl, 374 struct resource *disc_res) 375 { 376 struct feature_table *feat_tbl = &feature->table; 377 struct feature_header *header; 378 struct resource res = {}; 379 resource_size_t res_size; 380 void __iomem *feat_base, *feat_offset; 381 void *tbl_offset; 382 size_t size; 383 u32 *guids; 384 u8 tbir; 385 386 tbir = FIELD_GET(DT_TBIR, disc_tbl->offset); 387 388 switch (disc_tbl->access_type) { 389 case ACCESS_LOCAL: 390 if (tbir) 391 return dev_err_probe(priv->dev, -EINVAL, 392 "Unsupported BAR index %u for access type %u\n", 393 tbir, disc_tbl->access_type); 394 395 396 /* 397 * For access_type LOCAL, the base address is as follows: 398 * base address = end of discovery region + base offset + 1 399 */ 400 res = DEFINE_RES_MEM(disc_res->end + disc_tbl->offset + 1, 401 disc_tbl->size * sizeof(u32)); 402 break; 403 404 default: 405 return dev_err_probe(priv->dev, -EINVAL, "Unrecognized access_type %u\n", 406 disc_tbl->access_type); 407 } 408 409 feature->id = disc_tbl->id; 410 411 /* Get the feature table */ 412 feat_base = devm_ioremap_resource(priv->dev, &res); 413 if (IS_ERR(feat_base)) 414 return PTR_ERR(feat_base); 415 416 feat_offset = feat_base; 417 tbl_offset = feat_tbl; 418 419 /* Get the header */ 420 header = &feat_tbl->header; 421 memcpy_fromio(header, feat_offset, sizeof(*header)); 422 423 /* Validate fields fit within mapped resource */ 424 size = sizeof(*header) + FEAT_ATTR_SIZE(header->attr_size) + 425 PMT_GUID_SIZE(header->num_guids); 426 res_size = resource_size(&res); 427 if (WARN(size > res_size, "Bad table size %zu > %pa", size, &res_size)) 428 return -EINVAL; 429 430 /* Get the feature attributes, including capability fields */ 431 tbl_offset += sizeof(*header); 432 feat_offset += sizeof(*header); 433 434 memcpy_fromio(tbl_offset, feat_offset, FEAT_ATTR_SIZE(header->attr_size)); 435 436 /* Finally, get the guids */ 437 guids = devm_kmalloc(priv->dev, PMT_GUID_SIZE(header->num_guids), GFP_KERNEL); 438 if (!guids) 439 return -ENOMEM; 440 441 feat_offset += FEAT_ATTR_SIZE(header->attr_size); 442 443 memcpy_fromio(guids, feat_offset, PMT_GUID_SIZE(header->num_guids)); 444 445 feat_tbl->guids = guids; 446 447 devm_iounmap(priv->dev, feat_base); 448 449 return 0; 450 } 451 452 static void pmt_features_add_feat(struct feature *feature) 453 { 454 guard(mutex)(&feature_list_lock); 455 list_add(&feature->list, &pmt_feature_list); 456 } 457 458 static void pmt_features_remove_feat(struct feature *feature) 459 { 460 guard(mutex)(&feature_list_lock); 461 list_del(&feature->list); 462 } 463 464 /* Get the discovery table and use it to get the feature table */ 465 static int pmt_features_discovery(struct pmt_features_priv *priv, 466 struct feature *feature, 467 struct intel_vsec_device *ivdev, 468 int idx) 469 { 470 struct feature_discovery_table disc_tbl = {}; /* Avoid false warning */ 471 struct resource *disc_res = &ivdev->resource[idx]; 472 const struct kobj_type *ktype; 473 int ret; 474 475 ret = pmt_feature_get_disc_table(priv, disc_res, &disc_tbl); 476 if (ret) 477 return ret; 478 479 ret = pmt_feature_get_feature_table(priv, feature, &disc_tbl, disc_res); 480 if (ret) 481 return ret; 482 483 switch (feature_layout[feature->id]) { 484 case LAYOUT_RMID: 485 ktype = &pmt_feature_rmid_ktype; 486 feature->attr_group = &pmt_feature_rmid_group; 487 break; 488 case LAYOUT_WATCHER: 489 ktype = &pmt_feature_watcher_ktype; 490 feature->attr_group = &pmt_feature_watcher_group; 491 break; 492 case LAYOUT_COMMAND: 493 ktype = &pmt_feature_command_ktype; 494 feature->attr_group = &pmt_feature_command_group; 495 break; 496 case LAYOUT_CAPS_ONLY: 497 ktype = &pmt_feature_guids_ktype; 498 feature->attr_group = &pmt_feature_guids_group; 499 break; 500 default: 501 return -EINVAL; 502 } 503 504 ret = kobject_init_and_add(&feature->kobj, ktype, &priv->dev->kobj, 505 "%s", pmt_feature_names[feature->id]); 506 if (ret) 507 return ret; 508 509 kobject_uevent(&feature->kobj, KOBJ_ADD); 510 pmt_features_add_feat(feature); 511 512 return 0; 513 } 514 515 static void pmt_features_remove(struct auxiliary_device *auxdev) 516 { 517 struct pmt_features_priv *priv = auxiliary_get_drvdata(auxdev); 518 int i; 519 520 for (i = 0; i < priv->count; i++) { 521 struct feature *feature = &priv->feature[i]; 522 523 pmt_features_remove_feat(feature); 524 sysfs_remove_group(&feature->kobj, feature->attr_group); 525 kobject_put(&feature->kobj); 526 } 527 528 device_unregister(priv->dev); 529 } 530 531 static int pmt_features_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id) 532 { 533 struct intel_vsec_device *ivdev = auxdev_to_ivdev(auxdev); 534 struct pmt_features_priv *priv; 535 size_t size; 536 int ret, i; 537 538 size = struct_size(priv, feature, ivdev->num_resources); 539 priv = devm_kzalloc(&auxdev->dev, size, GFP_KERNEL); 540 if (!priv) 541 return -ENOMEM; 542 543 priv->parent = &ivdev->pcidev->dev; 544 auxiliary_set_drvdata(auxdev, priv); 545 546 priv->dev = device_create(&intel_pmt_class, &auxdev->dev, MKDEV(0, 0), priv, 547 "%s-%s", "features", dev_name(priv->parent)); 548 if (IS_ERR(priv->dev)) 549 return dev_err_probe(priv->dev, PTR_ERR(priv->dev), 550 "Could not create %s-%s device node\n", 551 "features", dev_name(priv->dev)); 552 553 /* Initialize each feature */ 554 for (i = 0; i < ivdev->num_resources; i++) { 555 struct feature *feature = &priv->feature[priv->count]; 556 557 ret = pmt_features_discovery(priv, feature, ivdev, i); 558 if (ret == SKIP_FEATURE) 559 continue; 560 if (ret != 0) 561 goto abort_probe; 562 563 feature->priv = priv; 564 priv->count++; 565 } 566 567 return 0; 568 569 abort_probe: 570 /* 571 * Only fully initialized features are tracked in priv->count, which is 572 * incremented only after a feature is completely set up (i.e., after 573 * discovery and sysfs registration). If feature initialization fails, 574 * the failing feature's state is local and does not require rollback. 575 * 576 * Therefore, on error, we can safely call the driver's remove() routine 577 * pmt_features_remove() to clean up only those features that were 578 * fully initialized and counted. All other resources are device-managed 579 * and will be cleaned up automatically during device_unregister(). 580 */ 581 pmt_features_remove(auxdev); 582 583 return ret; 584 } 585 586 static void pmt_get_features(struct intel_pmt_entry *entry, struct feature *f) 587 { 588 int num_guids = f->table.header.num_guids; 589 int i; 590 591 for (i = 0; i < num_guids; i++) { 592 if (f->table.guids[i] != entry->guid) 593 continue; 594 595 entry->feature_flags |= BIT(f->id); 596 597 if (feature_layout[f->id] == LAYOUT_RMID) 598 entry->num_rmids = f->table.rmid.num_rmids; 599 else 600 entry->num_rmids = 0; /* entry is kzalloc but set anyway */ 601 } 602 } 603 604 void intel_pmt_get_features(struct intel_pmt_entry *entry) 605 { 606 struct feature *feature; 607 608 mutex_lock(&feature_list_lock); 609 list_for_each_entry(feature, &pmt_feature_list, list) { 610 if (feature->priv->parent != &entry->ep->pcidev->dev) 611 continue; 612 613 pmt_get_features(entry, feature); 614 } 615 mutex_unlock(&feature_list_lock); 616 } 617 EXPORT_SYMBOL_NS_GPL(intel_pmt_get_features, "INTEL_PMT"); 618 619 static const struct auxiliary_device_id pmt_features_id_table[] = { 620 { .name = "intel_vsec.discovery" }, 621 {} 622 }; 623 MODULE_DEVICE_TABLE(auxiliary, pmt_features_id_table); 624 625 static struct auxiliary_driver pmt_features_aux_driver = { 626 .id_table = pmt_features_id_table, 627 .remove = pmt_features_remove, 628 .probe = pmt_features_probe, 629 }; 630 module_auxiliary_driver(pmt_features_aux_driver); 631 632 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>"); 633 MODULE_DESCRIPTION("Intel PMT Discovery driver"); 634 MODULE_LICENSE("GPL"); 635 MODULE_IMPORT_NS("INTEL_PMT"); 636