diff options
| -rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 108 |
1 files changed, 82 insertions, 26 deletions
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 33eae2062cf5..898c2f4eab88 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
| @@ -347,8 +347,8 @@ static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node) | |||
| 347 | return l3; | 347 | return l3; |
| 348 | } | 348 | } |
| 349 | 349 | ||
| 350 | static void __cpuinit | 350 | static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, |
| 351 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | 351 | int index) |
| 352 | { | 352 | { |
| 353 | int node; | 353 | int node; |
| 354 | 354 | ||
| @@ -396,20 +396,39 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | |||
| 396 | this_leaf->l3 = l3_caches[node]; | 396 | this_leaf->l3 = l3_caches[node]; |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | /* | ||
| 400 | * check whether a slot used for disabling an L3 index is occupied. | ||
| 401 | * @l3: L3 cache descriptor | ||
| 402 | * @slot: slot number (0..1) | ||
| 403 | * | ||
| 404 | * @returns: the disabled index if used or negative value if slot free. | ||
| 405 | */ | ||
| 406 | int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot) | ||
| 407 | { | ||
| 408 | unsigned int reg = 0; | ||
| 409 | |||
| 410 | pci_read_config_dword(l3->dev, 0x1BC + slot * 4, ®); | ||
| 411 | |||
| 412 | /* check whether this slot is activated already */ | ||
| 413 | if (reg & (3UL << 30)) | ||
| 414 | return reg & 0xfff; | ||
| 415 | |||
| 416 | return -1; | ||
| 417 | } | ||
| 418 | |||
| 399 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | 419 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, |
| 400 | unsigned int slot) | 420 | unsigned int slot) |
| 401 | { | 421 | { |
| 402 | struct pci_dev *dev = this_leaf->l3->dev; | 422 | int index; |
| 403 | unsigned int reg = 0; | ||
| 404 | 423 | ||
| 405 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) | 424 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) |
| 406 | return -EINVAL; | 425 | return -EINVAL; |
| 407 | 426 | ||
| 408 | if (!dev) | 427 | index = amd_get_l3_disable_slot(this_leaf->l3, slot); |
| 409 | return -EINVAL; | 428 | if (index >= 0) |
| 429 | return sprintf(buf, "%d\n", index); | ||
| 410 | 430 | ||
| 411 | pci_read_config_dword(dev, 0x1BC + slot * 4, ®); | 431 | return sprintf(buf, "FREE\n"); |
| 412 | return sprintf(buf, "0x%08x\n", reg); | ||
| 413 | } | 432 | } |
| 414 | 433 | ||
| 415 | #define SHOW_CACHE_DISABLE(slot) \ | 434 | #define SHOW_CACHE_DISABLE(slot) \ |
| @@ -451,37 +470,74 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, | |||
| 451 | } | 470 | } |
| 452 | } | 471 | } |
| 453 | 472 | ||
| 454 | 473 | /* | |
| 455 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | 474 | * disable a L3 cache index by using a disable-slot |
| 456 | const char *buf, size_t count, | 475 | * |
| 457 | unsigned int slot) | 476 | * @l3: L3 cache descriptor |
| 477 | * @cpu: A CPU on the node containing the L3 cache | ||
| 478 | * @slot: slot number (0..1) | ||
| 479 | * @index: index to disable | ||
| 480 | * | ||
| 481 | * @return: 0 on success, error status on failure | ||
| 482 | */ | ||
| 483 | int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot, | ||
| 484 | unsigned long index) | ||
| 458 | { | 485 | { |
| 459 | struct pci_dev *dev = this_leaf->l3->dev; | 486 | int ret = 0; |
| 460 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | ||
| 461 | unsigned long val = 0; | ||
| 462 | 487 | ||
| 463 | #define SUBCACHE_MASK (3UL << 20) | 488 | #define SUBCACHE_MASK (3UL << 20) |
| 464 | #define SUBCACHE_INDEX 0xfff | 489 | #define SUBCACHE_INDEX 0xfff |
| 465 | 490 | ||
| 466 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) | 491 | /* |
| 492 | * check whether this slot is already used or | ||
| 493 | * the index is already disabled | ||
| 494 | */ | ||
| 495 | ret = amd_get_l3_disable_slot(l3, slot); | ||
| 496 | if (ret >= 0) | ||
| 467 | return -EINVAL; | 497 | return -EINVAL; |
| 468 | 498 | ||
| 499 | /* | ||
| 500 | * check whether the other slot has disabled the | ||
| 501 | * same index already | ||
| 502 | */ | ||
| 503 | if (index == amd_get_l3_disable_slot(l3, !slot)) | ||
| 504 | return -EINVAL; | ||
| 505 | |||
| 506 | /* do not allow writes outside of allowed bits */ | ||
| 507 | if ((index & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) || | ||
| 508 | ((index & SUBCACHE_INDEX) > l3->indices)) | ||
| 509 | return -EINVAL; | ||
| 510 | |||
| 511 | amd_l3_disable_index(l3, cpu, slot, index); | ||
| 512 | |||
| 513 | return 0; | ||
| 514 | } | ||
| 515 | |||
| 516 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | ||
| 517 | const char *buf, size_t count, | ||
| 518 | unsigned int slot) | ||
| 519 | { | ||
| 520 | unsigned long val = 0; | ||
| 521 | int cpu, err = 0; | ||
| 522 | |||
| 469 | if (!capable(CAP_SYS_ADMIN)) | 523 | if (!capable(CAP_SYS_ADMIN)) |
| 470 | return -EPERM; | 524 | return -EPERM; |
| 471 | 525 | ||
| 472 | if (!dev) | 526 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) |
| 473 | return -EINVAL; | 527 | return -EINVAL; |
| 474 | 528 | ||
| 475 | if (strict_strtoul(buf, 10, &val) < 0) | 529 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); |
| 476 | return -EINVAL; | ||
| 477 | 530 | ||
| 478 | /* do not allow writes outside of allowed bits */ | 531 | if (strict_strtoul(buf, 10, &val) < 0) |
| 479 | if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) || | ||
| 480 | ((val & SUBCACHE_INDEX) > this_leaf->l3->indices)) | ||
| 481 | return -EINVAL; | 532 | return -EINVAL; |
| 482 | 533 | ||
| 483 | amd_l3_disable_index(this_leaf->l3, cpu, slot, val); | 534 | err = amd_set_l3_disable_slot(this_leaf->l3, cpu, slot, val); |
| 484 | 535 | if (err) { | |
| 536 | if (err == -EEXIST) | ||
| 537 | printk(KERN_WARNING "L3 disable slot %d in use!\n", | ||
| 538 | slot); | ||
| 539 | return err; | ||
| 540 | } | ||
| 485 | return count; | 541 | return count; |
| 486 | } | 542 | } |
| 487 | 543 | ||
| @@ -502,7 +558,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | |||
| 502 | 558 | ||
| 503 | #else /* CONFIG_CPU_SUP_AMD */ | 559 | #else /* CONFIG_CPU_SUP_AMD */ |
| 504 | static void __cpuinit | 560 | static void __cpuinit |
| 505 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | 561 | amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index) |
| 506 | { | 562 | { |
| 507 | }; | 563 | }; |
| 508 | #endif /* CONFIG_CPU_SUP_AMD */ | 564 | #endif /* CONFIG_CPU_SUP_AMD */ |
| @@ -518,7 +574,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index, | |||
| 518 | 574 | ||
| 519 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { | 575 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { |
| 520 | amd_cpuid4(index, &eax, &ebx, &ecx); | 576 | amd_cpuid4(index, &eax, &ebx, &ecx); |
| 521 | amd_check_l3_disable(index, this_leaf); | 577 | amd_check_l3_disable(this_leaf, index); |
| 522 | } else { | 578 | } else { |
| 523 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); | 579 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); |
| 524 | } | 580 | } |
