Commit b3ba283d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 CPU features from Ingo Molnar:
 "Various CPU feature support related changes: in particular the
  /proc/cpuinfo model name sanitization change should be monitored, it
  has a chance to break stuff.  (but really shouldn't and there are no
  regression reports)"

* 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/cpu/amd: Give access to the number of nodes in a physical package
  x86/cpu: Trim model ID whitespace
  x86/cpu: Strip any /proc/cpuinfo model name field whitespace
  x86/cpu/amd: Set X86_FEATURE_EXTD_APICID for future processors
  x86/gart: Check for GART support before accessing GART registers
parents d43e4f44 cc2749e4
...@@ -98,11 +98,22 @@ static inline u16 amd_get_node_id(struct pci_dev *pdev) ...@@ -98,11 +98,22 @@ static inline u16 amd_get_node_id(struct pci_dev *pdev)
return 0; return 0;
} }
static inline bool amd_gart_present(void)
{
/* GART present only on Fam15h, upto model 0fh */
if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
(boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model < 0x10))
return true;
return false;
}
#else #else
#define amd_nb_num(x) 0 #define amd_nb_num(x) 0
#define amd_nb_has_feature(x) false #define amd_nb_has_feature(x) false
#define node_to_amd_nb(x) NULL #define node_to_amd_nb(x) NULL
#define amd_gart_present(x) false
#endif #endif
......
...@@ -946,6 +946,7 @@ static inline int mpx_disable_management(struct task_struct *tsk) ...@@ -946,6 +946,7 @@ static inline int mpx_disable_management(struct task_struct *tsk)
#endif /* CONFIG_X86_INTEL_MPX */ #endif /* CONFIG_X86_INTEL_MPX */
extern u16 amd_get_nb_id(int cpu); extern u16 amd_get_nb_id(int cpu);
extern u32 amd_get_nodes_per_socket(void);
static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves) static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
{ {
......
...@@ -89,9 +89,7 @@ int amd_cache_northbridges(void) ...@@ -89,9 +89,7 @@ int amd_cache_northbridges(void)
next_northbridge(link, amd_nb_link_ids); next_northbridge(link, amd_nb_link_ids);
} }
/* GART present only on Fam15h upto model 0fh */ if (amd_gart_present())
if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
(boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model < 0x10))
amd_northbridges.flags |= AMD_NB_GART; amd_northbridges.flags |= AMD_NB_GART;
/* /*
......
...@@ -262,6 +262,9 @@ void __init early_gart_iommu_check(void) ...@@ -262,6 +262,9 @@ void __init early_gart_iommu_check(void)
u64 aper_base = 0, last_aper_base = 0; u64 aper_base = 0, last_aper_base = 0;
int aper_enabled = 0, last_aper_enabled = 0, last_valid = 0; int aper_enabled = 0, last_aper_enabled = 0, last_valid = 0;
if (!amd_gart_present())
return;
if (!early_pci_allowed()) if (!early_pci_allowed())
return; return;
...@@ -355,6 +358,9 @@ int __init gart_iommu_hole_init(void) ...@@ -355,6 +358,9 @@ int __init gart_iommu_hole_init(void)
int fix, slot, valid_agp = 0; int fix, slot, valid_agp = 0;
int i, node; int i, node;
if (!amd_gart_present())
return -ENODEV;
if (gart_iommu_aperture_disabled || !fix_aperture || if (gart_iommu_aperture_disabled || !fix_aperture ||
!early_pci_allowed()) !early_pci_allowed())
return -ENODEV; return -ENODEV;
...@@ -452,7 +458,7 @@ int __init gart_iommu_hole_init(void) ...@@ -452,7 +458,7 @@ int __init gart_iommu_hole_init(void)
force_iommu || force_iommu ||
valid_agp || valid_agp ||
fallback_aper_force) { fallback_aper_force) {
pr_info("Your BIOS doesn't leave a aperture memory hole\n"); pr_info("Your BIOS doesn't leave an aperture memory hole\n");
pr_info("Please enable the IOMMU option in the BIOS setup\n"); pr_info("Please enable the IOMMU option in the BIOS setup\n");
pr_info("This costs you %dMB of RAM\n", pr_info("This costs you %dMB of RAM\n",
32 << fallback_aper_order); 32 << fallback_aper_order);
......
...@@ -19,6 +19,13 @@ ...@@ -19,6 +19,13 @@
#include "cpu.h" #include "cpu.h"
/*
* nodes_per_socket: Stores the number of nodes per socket.
* Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
* Node Identifiers[10:8]
*/
static u32 nodes_per_socket = 1;
static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
{ {
u32 gprs[8] = { 0 }; u32 gprs[8] = { 0 };
...@@ -291,7 +298,7 @@ static int nearby_node(int apicid) ...@@ -291,7 +298,7 @@ static int nearby_node(int apicid)
#ifdef CONFIG_X86_HT #ifdef CONFIG_X86_HT
static void amd_get_topology(struct cpuinfo_x86 *c) static void amd_get_topology(struct cpuinfo_x86 *c)
{ {
u32 nodes, cores_per_cu = 1; u32 cores_per_cu = 1;
u8 node_id; u8 node_id;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
...@@ -300,7 +307,7 @@ static void amd_get_topology(struct cpuinfo_x86 *c) ...@@ -300,7 +307,7 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
u32 eax, ebx, ecx, edx; u32 eax, ebx, ecx, edx;
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
nodes = ((ecx >> 8) & 7) + 1; nodes_per_socket = ((ecx >> 8) & 7) + 1;
node_id = ecx & 7; node_id = ecx & 7;
/* get compute unit information */ /* get compute unit information */
...@@ -311,18 +318,18 @@ static void amd_get_topology(struct cpuinfo_x86 *c) ...@@ -311,18 +318,18 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
u64 value; u64 value;
rdmsrl(MSR_FAM10H_NODE_ID, value); rdmsrl(MSR_FAM10H_NODE_ID, value);
nodes = ((value >> 3) & 7) + 1; nodes_per_socket = ((value >> 3) & 7) + 1;
node_id = value & 7; node_id = value & 7;
} else } else
return; return;
/* fixup multi-node processor information */ /* fixup multi-node processor information */
if (nodes > 1) { if (nodes_per_socket > 1) {
u32 cores_per_node; u32 cores_per_node;
u32 cus_per_node; u32 cus_per_node;
set_cpu_cap(c, X86_FEATURE_AMD_DCM); set_cpu_cap(c, X86_FEATURE_AMD_DCM);
cores_per_node = c->x86_max_cores / nodes; cores_per_node = c->x86_max_cores / nodes_per_socket;
cus_per_node = cores_per_node / cores_per_cu; cus_per_node = cores_per_node / cores_per_cu;
/* store NodeID, use llc_shared_map to store sibling info */ /* store NodeID, use llc_shared_map to store sibling info */
...@@ -366,6 +373,12 @@ u16 amd_get_nb_id(int cpu) ...@@ -366,6 +373,12 @@ u16 amd_get_nb_id(int cpu)
} }
EXPORT_SYMBOL_GPL(amd_get_nb_id); EXPORT_SYMBOL_GPL(amd_get_nb_id);
u32 amd_get_nodes_per_socket(void)
{
return nodes_per_socket;
}
EXPORT_SYMBOL_GPL(amd_get_nodes_per_socket);
static void srat_detect_node(struct cpuinfo_x86 *c) static void srat_detect_node(struct cpuinfo_x86 *c)
{ {
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
...@@ -520,8 +533,16 @@ static void early_init_amd(struct cpuinfo_x86 *c) ...@@ -520,8 +533,16 @@ static void early_init_amd(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_K6_MTRR); set_cpu_cap(c, X86_FEATURE_K6_MTRR);
#endif #endif
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI) #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
/*
* ApicID can always be treated as an 8-bit value for AMD APIC versions
* >= 0x10, but even old K8s came out of reset with version 0x10. So, we
* can safely set X86_FEATURE_EXTD_APICID unconditionally for families
* after 16h.
*/
if (cpu_has_apic && c->x86 > 0x16) {
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
} else if (cpu_has_apic && c->x86 >= 0xf) {
/* check CPU config space for extended APIC ID */ /* check CPU config space for extended APIC ID */
if (cpu_has_apic && c->x86 >= 0xf) {
unsigned int val; unsigned int val;
val = read_pci_config(0, 24, 0, 0x68); val = read_pci_config(0, 24, 0, 0x68);
if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18))) if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18)))
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ctype.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -419,7 +420,7 @@ static const struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; ...@@ -419,7 +420,7 @@ static const struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
static void get_model_name(struct cpuinfo_x86 *c) static void get_model_name(struct cpuinfo_x86 *c)
{ {
unsigned int *v; unsigned int *v;
char *p, *q; char *p, *q, *s;
if (c->extended_cpuid_level < 0x80000004) if (c->extended_cpuid_level < 0x80000004)
return; return;
...@@ -430,19 +431,21 @@ static void get_model_name(struct cpuinfo_x86 *c) ...@@ -430,19 +431,21 @@ static void get_model_name(struct cpuinfo_x86 *c)
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
c->x86_model_id[48] = 0; c->x86_model_id[48] = 0;
/* /* Trim whitespace */
* Intel chips right-justify this string for some dumb reason; p = q = s = &c->x86_model_id[0];
* undo that brain damage:
*/
p = q = &c->x86_model_id[0];
while (*p == ' ') while (*p == ' ')
p++; p++;
if (p != q) {
while (*p) while (*p) {
/* Note the last non-whitespace index */
if (!isspace(*p))
s = q;
*q++ = *p++; *q++ = *p++;
while (q <= &c->x86_model_id[48])
*q++ = '\0'; /* Zero-pad the rest */
} }
*(s + 1) = '\0';
} }
void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) void cpu_detect_cache_sizes(struct cpuinfo_x86 *c)
...@@ -1122,7 +1125,7 @@ void print_cpu_info(struct cpuinfo_x86 *c) ...@@ -1122,7 +1125,7 @@ void print_cpu_info(struct cpuinfo_x86 *c)
printk(KERN_CONT "%s ", vendor); printk(KERN_CONT "%s ", vendor);
if (c->x86_model_id[0]) if (c->x86_model_id[0])
printk(KERN_CONT "%s", strim(c->x86_model_id)); printk(KERN_CONT "%s", c->x86_model_id);
else else
printk(KERN_CONT "%d86", c->x86); printk(KERN_CONT "%d86", c->x86);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment