mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 17:41:44 +00:00
Merge branch 'x86/cpu' into x86/core
This commit is contained in:
commit
446d27338d
@ -1888,6 +1888,12 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||||||
shapers= [NET]
|
shapers= [NET]
|
||||||
Maximal number of shapers.
|
Maximal number of shapers.
|
||||||
|
|
||||||
|
show_msr= [x86] show boot-time MSR settings
|
||||||
|
Format: { <integer> }
|
||||||
|
Show boot-time (BIOS-initialized) MSR settings.
|
||||||
|
The parameter means the number of CPUs to show,
|
||||||
|
for example 1 means boot CPU only.
|
||||||
|
|
||||||
sim710= [SCSI,HW]
|
sim710= [SCSI,HW]
|
||||||
See header of drivers/scsi/sim710.c.
|
See header of drivers/scsi/sim710.c.
|
||||||
|
|
||||||
|
@ -8,14 +8,14 @@ obj-y += proc.o capflags.o powerflags.o
|
|||||||
obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o
|
obj-$(CONFIG_X86_32) += common.o bugs.o cmpxchg.o
|
||||||
obj-$(CONFIG_X86_64) += common_64.o bugs_64.o
|
obj-$(CONFIG_X86_64) += common_64.o bugs_64.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o
|
||||||
|
obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o
|
||||||
obj-$(CONFIG_CPU_SUP_AMD_32) += amd.o
|
obj-$(CONFIG_CPU_SUP_AMD_32) += amd.o
|
||||||
obj-$(CONFIG_CPU_SUP_AMD_64) += amd_64.o
|
obj-$(CONFIG_CPU_SUP_AMD_64) += amd_64.o
|
||||||
obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o
|
obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o
|
||||||
obj-$(CONFIG_CPU_SUP_CENTAUR_32) += centaur.o
|
obj-$(CONFIG_CPU_SUP_CENTAUR_32) += centaur.o
|
||||||
obj-$(CONFIG_CPU_SUP_CENTAUR_64) += centaur_64.o
|
obj-$(CONFIG_CPU_SUP_CENTAUR_64) += centaur_64.o
|
||||||
obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o
|
obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o
|
||||||
obj-$(CONFIG_CPU_SUP_INTEL_32) += intel.o
|
|
||||||
obj-$(CONFIG_CPU_SUP_INTEL_64) += intel_64.o
|
|
||||||
obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o
|
obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o
|
||||||
|
|
||||||
obj-$(CONFIG_X86_MCE) += mcheck/
|
obj-$(CONFIG_X86_MCE) += mcheck/
|
||||||
|
@ -31,6 +31,11 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
|
|||||||
if (c->x86_power & (1<<8))
|
if (c->x86_power & (1<<8))
|
||||||
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
|
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set MTRR capability flag if appropriate */
|
||||||
|
if (c->x86_model == 13 || c->x86_model == 9 ||
|
||||||
|
(c->x86_model == 8 && c->x86_mask >= 8))
|
||||||
|
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
||||||
@ -166,10 +171,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
|
|||||||
mbytes);
|
mbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set MTRR capability flag if appropriate */
|
|
||||||
if (c->x86_model == 13 || c->x86_model == 9 ||
|
|
||||||
(c->x86_model == 8 && c->x86_mask >= 8))
|
|
||||||
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +298,7 @@ static struct cpu_dev amd_cpu_dev __cpuinitdata = {
|
|||||||
.c_early_init = early_init_amd,
|
.c_early_init = early_init_amd,
|
||||||
.c_init = init_amd,
|
.c_init = init_amd,
|
||||||
.c_size_cache = amd_size_cache,
|
.c_size_cache = amd_size_cache,
|
||||||
|
.c_x86_vendor = X86_VENDOR_AMD,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev);
|
cpu_dev_register(amd_cpu_dev);
|
||||||
|
@ -218,7 +218,7 @@ static struct cpu_dev amd_cpu_dev __cpuinitdata = {
|
|||||||
.c_ident = { "AuthenticAMD" },
|
.c_ident = { "AuthenticAMD" },
|
||||||
.c_early_init = early_init_amd,
|
.c_early_init = early_init_amd,
|
||||||
.c_init = init_amd,
|
.c_init = init_amd,
|
||||||
|
.c_x86_vendor = X86_VENDOR_AMD,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev);
|
cpu_dev_register(amd_cpu_dev);
|
||||||
|
|
||||||
|
@ -314,6 +314,16 @@ enum {
|
|||||||
EAMD3D = 1<<20,
|
EAMD3D = 1<<20,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
switch (c->x86) {
|
||||||
|
case 5:
|
||||||
|
/* Emulate MTRRs using Centaur's MCR. */
|
||||||
|
set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
|
static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -462,8 +472,10 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
|
|||||||
static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
|
static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
|
||||||
.c_vendor = "Centaur",
|
.c_vendor = "Centaur",
|
||||||
.c_ident = { "CentaurHauls" },
|
.c_ident = { "CentaurHauls" },
|
||||||
|
.c_early_init = early_init_centaur,
|
||||||
.c_init = init_centaur,
|
.c_init = init_centaur,
|
||||||
.c_size_cache = centaur_size_cache,
|
.c_size_cache = centaur_size_cache,
|
||||||
|
.c_x86_vendor = X86_VENDOR_CENTAUR,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_CENTAUR, ¢aur_cpu_dev);
|
cpu_dev_register(centaur_cpu_dev);
|
||||||
|
@ -29,7 +29,8 @@ static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
|
|||||||
.c_ident = { "CentaurHauls" },
|
.c_ident = { "CentaurHauls" },
|
||||||
.c_early_init = early_init_centaur,
|
.c_early_init = early_init_centaur,
|
||||||
.c_init = init_centaur,
|
.c_init = init_centaur,
|
||||||
|
.c_x86_vendor = X86_VENDOR_CENTAUR,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_CENTAUR, ¢aur_cpu_dev);
|
cpu_dev_register(centaur_cpu_dev);
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
|
static struct cpu_dev *this_cpu __cpuinitdata;
|
||||||
|
|
||||||
DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
|
DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
|
||||||
[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } },
|
[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } },
|
||||||
[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
|
[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
|
||||||
@ -58,32 +60,9 @@ DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
|
|||||||
} };
|
} };
|
||||||
EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
|
EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
|
||||||
|
|
||||||
__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
|
|
||||||
|
|
||||||
static int cachesize_override __cpuinitdata = -1;
|
static int cachesize_override __cpuinitdata = -1;
|
||||||
static int disable_x86_serial_nr __cpuinitdata = 1;
|
static int disable_x86_serial_nr __cpuinitdata = 1;
|
||||||
|
|
||||||
struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
|
|
||||||
|
|
||||||
static void __cpuinit default_init(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
/* Not much we can do here... */
|
|
||||||
/* Check if at least it has cpuid */
|
|
||||||
if (c->cpuid_level == -1) {
|
|
||||||
/* No cpuid. It must be an ancient CPU */
|
|
||||||
if (c->x86 == 4)
|
|
||||||
strcpy(c->x86_model_id, "486");
|
|
||||||
else if (c->x86 == 3)
|
|
||||||
strcpy(c->x86_model_id, "386");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct cpu_dev __cpuinitdata default_cpu = {
|
|
||||||
.c_init = default_init,
|
|
||||||
.c_vendor = "Unknown",
|
|
||||||
};
|
|
||||||
static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
|
|
||||||
|
|
||||||
static int __init cachesize_setup(char *str)
|
static int __init cachesize_setup(char *str)
|
||||||
{
|
{
|
||||||
get_option(&str, &cachesize_override);
|
get_option(&str, &cachesize_override);
|
||||||
@ -91,72 +70,6 @@ static int __init cachesize_setup(char *str)
|
|||||||
}
|
}
|
||||||
__setup("cachesize=", cachesize_setup);
|
__setup("cachesize=", cachesize_setup);
|
||||||
|
|
||||||
int __cpuinit get_model_name(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
unsigned int *v;
|
|
||||||
char *p, *q;
|
|
||||||
|
|
||||||
if (cpuid_eax(0x80000000) < 0x80000004)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
v = (unsigned int *) c->x86_model_id;
|
|
||||||
cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
|
|
||||||
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
|
|
||||||
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
|
|
||||||
c->x86_model_id[48] = 0;
|
|
||||||
|
|
||||||
/* Intel chips right-justify this string for some dumb reason;
|
|
||||||
undo that brain damage */
|
|
||||||
p = q = &c->x86_model_id[0];
|
|
||||||
while (*p == ' ')
|
|
||||||
p++;
|
|
||||||
if (p != q) {
|
|
||||||
while (*p)
|
|
||||||
*q++ = *p++;
|
|
||||||
while (q <= &c->x86_model_id[48])
|
|
||||||
*q++ = '\0'; /* Zero-pad the rest */
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
unsigned int n, dummy, ecx, edx, l2size;
|
|
||||||
|
|
||||||
n = cpuid_eax(0x80000000);
|
|
||||||
|
|
||||||
if (n >= 0x80000005) {
|
|
||||||
cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
|
|
||||||
printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
|
|
||||||
edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
|
|
||||||
c->x86_cache_size = (ecx>>24)+(edx>>24);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n < 0x80000006) /* Some chips just has a large L1. */
|
|
||||||
return;
|
|
||||||
|
|
||||||
ecx = cpuid_ecx(0x80000006);
|
|
||||||
l2size = ecx >> 16;
|
|
||||||
|
|
||||||
/* do processor-specific cache resizing */
|
|
||||||
if (this_cpu->c_size_cache)
|
|
||||||
l2size = this_cpu->c_size_cache(c, l2size);
|
|
||||||
|
|
||||||
/* Allow user to override all this if necessary. */
|
|
||||||
if (cachesize_override != -1)
|
|
||||||
l2size = cachesize_override;
|
|
||||||
|
|
||||||
if (l2size == 0)
|
|
||||||
return; /* Again, no L2 cache is possible */
|
|
||||||
|
|
||||||
c->x86_cache_size = l2size;
|
|
||||||
|
|
||||||
printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
|
|
||||||
l2size, ecx & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Naming convention should be: <Name> [(<Codename>)]
|
* Naming convention should be: <Name> [(<Codename>)]
|
||||||
* This table only is used unless init_<vendor>() below doesn't set it;
|
* This table only is used unless init_<vendor>() below doesn't set it;
|
||||||
@ -185,35 +98,6 @@ static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
|
|||||||
return NULL; /* Not found */
|
return NULL; /* Not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
|
|
||||||
{
|
|
||||||
char *v = c->x86_vendor_id;
|
|
||||||
int i;
|
|
||||||
static int printed;
|
|
||||||
|
|
||||||
for (i = 0; i < X86_VENDOR_NUM; i++) {
|
|
||||||
if (cpu_devs[i]) {
|
|
||||||
if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
|
|
||||||
(cpu_devs[i]->c_ident[1] &&
|
|
||||||
!strcmp(v, cpu_devs[i]->c_ident[1]))) {
|
|
||||||
c->x86_vendor = i;
|
|
||||||
if (!early)
|
|
||||||
this_cpu = cpu_devs[i];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!printed) {
|
|
||||||
printed++;
|
|
||||||
printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
|
|
||||||
printk(KERN_ERR "CPU: Your system may be unstable.\n");
|
|
||||||
}
|
|
||||||
c->x86_vendor = X86_VENDOR_UNKNOWN;
|
|
||||||
this_cpu = &default_cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int __init x86_fxsr_setup(char *s)
|
static int __init x86_fxsr_setup(char *s)
|
||||||
{
|
{
|
||||||
setup_clear_cpu_cap(X86_FEATURE_FXSR);
|
setup_clear_cpu_cap(X86_FEATURE_FXSR);
|
||||||
@ -222,7 +106,6 @@ static int __init x86_fxsr_setup(char *s)
|
|||||||
}
|
}
|
||||||
__setup("nofxsr", x86_fxsr_setup);
|
__setup("nofxsr", x86_fxsr_setup);
|
||||||
|
|
||||||
|
|
||||||
static int __init x86_sep_setup(char *s)
|
static int __init x86_sep_setup(char *s)
|
||||||
{
|
{
|
||||||
setup_clear_cpu_cap(X86_FEATURE_SEP);
|
setup_clear_cpu_cap(X86_FEATURE_SEP);
|
||||||
@ -230,7 +113,6 @@ static int __init x86_sep_setup(char *s)
|
|||||||
}
|
}
|
||||||
__setup("nosep", x86_sep_setup);
|
__setup("nosep", x86_sep_setup);
|
||||||
|
|
||||||
|
|
||||||
/* Standard macro to see if a specific flag is changeable */
|
/* Standard macro to see if a specific flag is changeable */
|
||||||
static inline int flag_is_changeable_p(u32 flag)
|
static inline int flag_is_changeable_p(u32 flag)
|
||||||
{
|
{
|
||||||
@ -252,14 +134,216 @@ static inline int flag_is_changeable_p(u32 flag)
|
|||||||
return ((f1^f2) & flag) != 0;
|
return ((f1^f2) & flag) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Probe for the CPUID instruction */
|
/* Probe for the CPUID instruction */
|
||||||
static int __cpuinit have_cpuid_p(void)
|
static int __cpuinit have_cpuid_p(void)
|
||||||
{
|
{
|
||||||
return flag_is_changeable_p(X86_EFLAGS_ID);
|
return flag_is_changeable_p(X86_EFLAGS_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init cpu_detect(struct cpuinfo_x86 *c)
|
static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
|
||||||
|
/* Disable processor serial number */
|
||||||
|
unsigned long lo, hi;
|
||||||
|
rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
|
||||||
|
lo |= 0x200000;
|
||||||
|
wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
|
||||||
|
printk(KERN_NOTICE "CPU serial number disabled.\n");
|
||||||
|
clear_cpu_cap(c, X86_FEATURE_PN);
|
||||||
|
|
||||||
|
/* Disabling the serial number may affect the cpuid level */
|
||||||
|
c->cpuid_level = cpuid_eax(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init x86_serial_nr_setup(char *s)
|
||||||
|
{
|
||||||
|
disable_x86_serial_nr = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
__setup("serialnumber", x86_serial_nr_setup);
|
||||||
|
|
||||||
|
__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
|
||||||
|
|
||||||
|
/* Current gdt points %fs at the "master" per-cpu area: after this,
|
||||||
|
* it's on the real one. */
|
||||||
|
void switch_to_new_gdt(void)
|
||||||
|
{
|
||||||
|
struct desc_ptr gdt_descr;
|
||||||
|
|
||||||
|
gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
|
||||||
|
gdt_descr.size = GDT_SIZE - 1;
|
||||||
|
load_gdt(&gdt_descr);
|
||||||
|
asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
|
||||||
|
|
||||||
|
static void __cpuinit default_init(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
/* Not much we can do here... */
|
||||||
|
/* Check if at least it has cpuid */
|
||||||
|
if (c->cpuid_level == -1) {
|
||||||
|
/* No cpuid. It must be an ancient CPU */
|
||||||
|
if (c->x86 == 4)
|
||||||
|
strcpy(c->x86_model_id, "486");
|
||||||
|
else if (c->x86 == 3)
|
||||||
|
strcpy(c->x86_model_id, "386");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cpu_dev __cpuinitdata default_cpu = {
|
||||||
|
.c_init = default_init,
|
||||||
|
.c_vendor = "Unknown",
|
||||||
|
.c_x86_vendor = X86_VENDOR_UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
|
int __cpuinit get_model_name(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
unsigned int *v;
|
||||||
|
char *p, *q;
|
||||||
|
|
||||||
|
if (c->extended_cpuid_level < 0x80000004)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
v = (unsigned int *) c->x86_model_id;
|
||||||
|
cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
|
||||||
|
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
|
||||||
|
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
|
||||||
|
c->x86_model_id[48] = 0;
|
||||||
|
|
||||||
|
/* Intel chips right-justify this string for some dumb reason;
|
||||||
|
undo that brain damage */
|
||||||
|
p = q = &c->x86_model_id[0];
|
||||||
|
while (*p == ' ')
|
||||||
|
p++;
|
||||||
|
if (p != q) {
|
||||||
|
while (*p)
|
||||||
|
*q++ = *p++;
|
||||||
|
while (q <= &c->x86_model_id[48])
|
||||||
|
*q++ = '\0'; /* Zero-pad the rest */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
unsigned int n, dummy, ebx, ecx, edx, l2size;
|
||||||
|
|
||||||
|
n = c->extended_cpuid_level;
|
||||||
|
|
||||||
|
if (n >= 0x80000005) {
|
||||||
|
cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
|
||||||
|
printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
|
||||||
|
edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
|
||||||
|
c->x86_cache_size = (ecx>>24) + (edx>>24);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n < 0x80000006) /* Some chips just has a large L1. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
|
||||||
|
l2size = ecx >> 16;
|
||||||
|
|
||||||
|
/* do processor-specific cache resizing */
|
||||||
|
if (this_cpu->c_size_cache)
|
||||||
|
l2size = this_cpu->c_size_cache(c, l2size);
|
||||||
|
|
||||||
|
/* Allow user to override all this if necessary. */
|
||||||
|
if (cachesize_override != -1)
|
||||||
|
l2size = cachesize_override;
|
||||||
|
|
||||||
|
if (l2size == 0)
|
||||||
|
return; /* Again, no L2 cache is possible */
|
||||||
|
|
||||||
|
c->x86_cache_size = l2size;
|
||||||
|
|
||||||
|
printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
|
||||||
|
l2size, ecx & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_HT
|
||||||
|
void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
u32 eax, ebx, ecx, edx;
|
||||||
|
int index_msb, core_bits;
|
||||||
|
|
||||||
|
if (!cpu_has(c, X86_FEATURE_HT))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
smp_num_siblings = (ebx & 0xff0000) >> 16;
|
||||||
|
|
||||||
|
if (smp_num_siblings == 1) {
|
||||||
|
printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
|
||||||
|
} else if (smp_num_siblings > 1) {
|
||||||
|
|
||||||
|
if (smp_num_siblings > NR_CPUS) {
|
||||||
|
printk(KERN_WARNING "CPU: Unsupported number of siblings %d",
|
||||||
|
smp_num_siblings);
|
||||||
|
smp_num_siblings = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
index_msb = get_count_order(smp_num_siblings);
|
||||||
|
c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
|
||||||
|
|
||||||
|
|
||||||
|
smp_num_siblings = smp_num_siblings / c->x86_max_cores;
|
||||||
|
|
||||||
|
index_msb = get_count_order(smp_num_siblings);
|
||||||
|
|
||||||
|
core_bits = get_count_order(c->x86_max_cores);
|
||||||
|
|
||||||
|
c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
|
||||||
|
((1 << core_bits) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if ((c->x86_max_cores * smp_num_siblings) > 1) {
|
||||||
|
printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
|
||||||
|
c->phys_proc_id);
|
||||||
|
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
|
||||||
|
c->cpu_core_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
char *v = c->x86_vendor_id;
|
||||||
|
int i;
|
||||||
|
static int printed;
|
||||||
|
|
||||||
|
for (i = 0; i < X86_VENDOR_NUM; i++) {
|
||||||
|
if (!cpu_devs[i])
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
|
||||||
|
(cpu_devs[i]->c_ident[1] &&
|
||||||
|
!strcmp(v, cpu_devs[i]->c_ident[1]))) {
|
||||||
|
this_cpu = cpu_devs[i];
|
||||||
|
c->x86_vendor = this_cpu->c_x86_vendor;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!printed) {
|
||||||
|
printed++;
|
||||||
|
printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
|
||||||
|
printk(KERN_ERR "CPU: Your system may be unstable.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
c->x86_vendor = X86_VENDOR_UNKNOWN;
|
||||||
|
this_cpu = &default_cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cpuinit cpu_detect(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
/* Get vendor name */
|
/* Get vendor name */
|
||||||
cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
|
cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
|
||||||
@ -268,50 +352,47 @@ void __init cpu_detect(struct cpuinfo_x86 *c)
|
|||||||
(unsigned int *)&c->x86_vendor_id[4]);
|
(unsigned int *)&c->x86_vendor_id[4]);
|
||||||
|
|
||||||
c->x86 = 4;
|
c->x86 = 4;
|
||||||
|
/* Intel-defined flags: level 0x00000001 */
|
||||||
if (c->cpuid_level >= 0x00000001) {
|
if (c->cpuid_level >= 0x00000001) {
|
||||||
u32 junk, tfms, cap0, misc;
|
u32 junk, tfms, cap0, misc;
|
||||||
cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
|
cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
|
||||||
c->x86 = (tfms >> 8) & 15;
|
c->x86 = (tfms >> 8) & 0xf;
|
||||||
c->x86_model = (tfms >> 4) & 15;
|
c->x86_model = (tfms >> 4) & 0xf;
|
||||||
|
c->x86_mask = tfms & 0xf;
|
||||||
if (c->x86 == 0xf)
|
if (c->x86 == 0xf)
|
||||||
c->x86 += (tfms >> 20) & 0xff;
|
c->x86 += (tfms >> 20) & 0xff;
|
||||||
if (c->x86 >= 0x6)
|
if (c->x86 >= 0x6)
|
||||||
c->x86_model += ((tfms >> 16) & 0xF) << 4;
|
c->x86_model += ((tfms >> 16) & 0xf) << 4;
|
||||||
c->x86_mask = tfms & 15;
|
|
||||||
if (cap0 & (1<<19)) {
|
if (cap0 & (1<<19)) {
|
||||||
c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
|
|
||||||
c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
|
c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
|
||||||
|
c->x86_cache_alignment = c->x86_clflush_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
|
|
||||||
|
static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
u32 tfms, xlvl;
|
u32 tfms, xlvl;
|
||||||
unsigned int ebx;
|
u32 ebx;
|
||||||
|
|
||||||
memset(&c->x86_capability, 0, sizeof c->x86_capability);
|
|
||||||
if (have_cpuid_p()) {
|
|
||||||
/* Intel-defined flags: level 0x00000001 */
|
|
||||||
if (c->cpuid_level >= 0x00000001) {
|
|
||||||
u32 capability, excap;
|
|
||||||
cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
|
|
||||||
c->x86_capability[0] = capability;
|
|
||||||
c->x86_capability[4] = excap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AMD-defined flags: level 0x80000001 */
|
|
||||||
xlvl = cpuid_eax(0x80000000);
|
|
||||||
if ((xlvl & 0xffff0000) == 0x80000000) {
|
|
||||||
if (xlvl >= 0x80000001) {
|
|
||||||
c->x86_capability[1] = cpuid_edx(0x80000001);
|
|
||||||
c->x86_capability[6] = cpuid_ecx(0x80000001);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Intel-defined flags: level 0x00000001 */
|
||||||
|
if (c->cpuid_level >= 0x00000001) {
|
||||||
|
u32 capability, excap;
|
||||||
|
cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
|
||||||
|
c->x86_capability[0] = capability;
|
||||||
|
c->x86_capability[4] = excap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* AMD-defined flags: level 0x80000001 */
|
||||||
|
xlvl = cpuid_eax(0x80000000);
|
||||||
|
c->extended_cpuid_level = xlvl;
|
||||||
|
if ((xlvl & 0xffff0000) == 0x80000000) {
|
||||||
|
if (xlvl >= 0x80000001) {
|
||||||
|
c->x86_capability[1] = cpuid_edx(0x80000001);
|
||||||
|
c->x86_capability[6] = cpuid_ecx(0x80000001);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do minimum CPU detection early.
|
* Do minimum CPU detection early.
|
||||||
* Fields really needed: vendor, cpuid_level, family, model, mask,
|
* Fields really needed: vendor, cpuid_level, family, model, mask,
|
||||||
@ -321,25 +402,54 @@ static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
|
|||||||
* WARNING: this function is only called on the BP. Don't add code here
|
* WARNING: this function is only called on the BP. Don't add code here
|
||||||
* that is supposed to run on all CPUs.
|
* that is supposed to run on all CPUs.
|
||||||
*/
|
*/
|
||||||
static void __init early_cpu_detect(void)
|
static void __init early_identify_cpu(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
|
||||||
|
|
||||||
c->x86_cache_alignment = 32;
|
|
||||||
c->x86_clflush_size = 32;
|
c->x86_clflush_size = 32;
|
||||||
|
c->x86_cache_alignment = c->x86_clflush_size;
|
||||||
|
|
||||||
if (!have_cpuid_p())
|
if (!have_cpuid_p())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
memset(&c->x86_capability, 0, sizeof c->x86_capability);
|
||||||
|
|
||||||
|
c->extended_cpuid_level = 0;
|
||||||
|
|
||||||
cpu_detect(c);
|
cpu_detect(c);
|
||||||
|
|
||||||
get_cpu_vendor(c, 1);
|
get_cpu_vendor(c);
|
||||||
|
|
||||||
if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
|
get_cpu_cap(c);
|
||||||
cpu_devs[c->x86_vendor]->c_early_init)
|
|
||||||
cpu_devs[c->x86_vendor]->c_early_init(c);
|
|
||||||
|
|
||||||
early_get_cap(c);
|
if (this_cpu->c_early_init)
|
||||||
|
this_cpu->c_early_init(c);
|
||||||
|
|
||||||
|
validate_pat_support(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init early_cpu_init(void)
|
||||||
|
{
|
||||||
|
struct cpu_dev **cdev;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
printk("KERNEL supported cpus:\n");
|
||||||
|
for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
|
||||||
|
struct cpu_dev *cpudev = *cdev;
|
||||||
|
unsigned int j;
|
||||||
|
|
||||||
|
if (count >= X86_VENDOR_NUM)
|
||||||
|
break;
|
||||||
|
cpu_devs[count] = cpudev;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
for (j = 0; j < 2; j++) {
|
||||||
|
if (!cpudev->c_ident[j])
|
||||||
|
continue;
|
||||||
|
printk(" %s %s\n", cpudev->c_vendor,
|
||||||
|
cpudev->c_ident[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
early_identify_cpu(&boot_cpu_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -373,87 +483,34 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
|
static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
u32 tfms, xlvl;
|
if (!have_cpuid_p())
|
||||||
unsigned int ebx;
|
return;
|
||||||
|
|
||||||
if (have_cpuid_p()) {
|
c->extended_cpuid_level = 0;
|
||||||
/* Get vendor name */
|
|
||||||
cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
|
|
||||||
(unsigned int *)&c->x86_vendor_id[0],
|
|
||||||
(unsigned int *)&c->x86_vendor_id[8],
|
|
||||||
(unsigned int *)&c->x86_vendor_id[4]);
|
|
||||||
|
|
||||||
get_cpu_vendor(c, 0);
|
cpu_detect(c);
|
||||||
/* Initialize the standard set of capabilities */
|
|
||||||
/* Note that the vendor-specific code below might override */
|
get_cpu_vendor(c);
|
||||||
/* Intel-defined flags: level 0x00000001 */
|
|
||||||
if (c->cpuid_level >= 0x00000001) {
|
get_cpu_cap(c);
|
||||||
u32 capability, excap;
|
|
||||||
cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
|
if (c->cpuid_level >= 0x00000001) {
|
||||||
c->x86_capability[0] = capability;
|
c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
|
||||||
c->x86_capability[4] = excap;
|
|
||||||
c->x86 = (tfms >> 8) & 15;
|
|
||||||
c->x86_model = (tfms >> 4) & 15;
|
|
||||||
if (c->x86 == 0xf)
|
|
||||||
c->x86 += (tfms >> 20) & 0xff;
|
|
||||||
if (c->x86 >= 0x6)
|
|
||||||
c->x86_model += ((tfms >> 16) & 0xF) << 4;
|
|
||||||
c->x86_mask = tfms & 15;
|
|
||||||
c->initial_apicid = (ebx >> 24) & 0xFF;
|
|
||||||
#ifdef CONFIG_X86_HT
|
#ifdef CONFIG_X86_HT
|
||||||
c->apicid = phys_pkg_id(c->initial_apicid, 0);
|
c->apicid = phys_pkg_id(c->initial_apicid, 0);
|
||||||
c->phys_proc_id = c->initial_apicid;
|
c->phys_proc_id = c->initial_apicid;
|
||||||
#else
|
#else
|
||||||
c->apicid = c->initial_apicid;
|
c->apicid = c->initial_apicid;
|
||||||
#endif
|
#endif
|
||||||
if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
|
|
||||||
c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
|
|
||||||
} else {
|
|
||||||
/* Have CPUID level 0 only - unheard of */
|
|
||||||
c->x86 = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AMD-defined flags: level 0x80000001 */
|
|
||||||
xlvl = cpuid_eax(0x80000000);
|
|
||||||
if ((xlvl & 0xffff0000) == 0x80000000) {
|
|
||||||
if (xlvl >= 0x80000001) {
|
|
||||||
c->x86_capability[1] = cpuid_edx(0x80000001);
|
|
||||||
c->x86_capability[6] = cpuid_ecx(0x80000001);
|
|
||||||
}
|
|
||||||
if (xlvl >= 0x80000004)
|
|
||||||
get_model_name(c); /* Default name */
|
|
||||||
}
|
|
||||||
|
|
||||||
init_scattered_cpuid_features(c);
|
|
||||||
detect_nopl(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->extended_cpuid_level >= 0x80000004)
|
||||||
|
get_model_name(c); /* Default name */
|
||||||
|
|
||||||
|
init_scattered_cpuid_features(c);
|
||||||
|
detect_nopl(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
|
|
||||||
/* Disable processor serial number */
|
|
||||||
unsigned long lo, hi;
|
|
||||||
rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
|
|
||||||
lo |= 0x200000;
|
|
||||||
wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
|
|
||||||
printk(KERN_NOTICE "CPU serial number disabled.\n");
|
|
||||||
clear_cpu_cap(c, X86_FEATURE_PN);
|
|
||||||
|
|
||||||
/* Disabling the serial number may affect the cpuid level */
|
|
||||||
c->cpuid_level = cpuid_eax(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init x86_serial_nr_setup(char *s)
|
|
||||||
{
|
|
||||||
disable_x86_serial_nr = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("serialnumber", x86_serial_nr_setup);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This does the hard work of actually picking apart the CPU stuff...
|
* This does the hard work of actually picking apart the CPU stuff...
|
||||||
*/
|
*/
|
||||||
@ -529,7 +586,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
|
|||||||
*/
|
*/
|
||||||
if (c != &boot_cpu_data) {
|
if (c != &boot_cpu_data) {
|
||||||
/* AND the already accumulated flags with these */
|
/* AND the already accumulated flags with these */
|
||||||
for (i = 0 ; i < NCAPINTS ; i++)
|
for (i = 0; i < NCAPINTS; i++)
|
||||||
boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
|
boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,51 +615,48 @@ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
|
|||||||
mtrr_ap_init();
|
mtrr_ap_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_HT
|
struct msr_range {
|
||||||
void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
unsigned min;
|
||||||
|
unsigned max;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct msr_range msr_range_array[] __cpuinitdata = {
|
||||||
|
{ 0x00000000, 0x00000418},
|
||||||
|
{ 0xc0000000, 0xc000040b},
|
||||||
|
{ 0xc0010000, 0xc0010142},
|
||||||
|
{ 0xc0011000, 0xc001103b},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __cpuinit print_cpu_msr(void)
|
||||||
{
|
{
|
||||||
u32 eax, ebx, ecx, edx;
|
unsigned index;
|
||||||
int index_msb, core_bits;
|
u64 val;
|
||||||
|
int i;
|
||||||
|
unsigned index_min, index_max;
|
||||||
|
|
||||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
|
||||||
|
index_min = msr_range_array[i].min;
|
||||||
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
index_max = msr_range_array[i].max;
|
||||||
return;
|
for (index = index_min; index < index_max; index++) {
|
||||||
|
if (rdmsrl_amd_safe(index, &val))
|
||||||
smp_num_siblings = (ebx & 0xff0000) >> 16;
|
continue;
|
||||||
|
printk(KERN_INFO " MSR%08x: %016llx\n", index, val);
|
||||||
if (smp_num_siblings == 1) {
|
|
||||||
printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
|
|
||||||
} else if (smp_num_siblings > 1) {
|
|
||||||
|
|
||||||
if (smp_num_siblings > NR_CPUS) {
|
|
||||||
printk(KERN_WARNING "CPU: Unsupported number of the "
|
|
||||||
"siblings %d", smp_num_siblings);
|
|
||||||
smp_num_siblings = 1;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
index_msb = get_count_order(smp_num_siblings);
|
|
||||||
c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
|
|
||||||
|
|
||||||
printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
|
|
||||||
c->phys_proc_id);
|
|
||||||
|
|
||||||
smp_num_siblings = smp_num_siblings / c->x86_max_cores;
|
|
||||||
|
|
||||||
index_msb = get_count_order(smp_num_siblings) ;
|
|
||||||
|
|
||||||
core_bits = get_count_order(c->x86_max_cores);
|
|
||||||
|
|
||||||
c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
|
|
||||||
((1 << core_bits) - 1);
|
|
||||||
|
|
||||||
if (c->x86_max_cores > 1)
|
|
||||||
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
|
|
||||||
c->cpu_core_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
static int show_msr __cpuinitdata;
|
||||||
|
static __init int setup_show_msr(char *arg)
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
|
||||||
|
get_option(&arg, &num);
|
||||||
|
|
||||||
|
if (num > 0)
|
||||||
|
show_msr = num;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
__setup("show_msr=", setup_show_msr);
|
||||||
|
|
||||||
static __init int setup_noclflush(char *arg)
|
static __init int setup_noclflush(char *arg)
|
||||||
{
|
{
|
||||||
@ -621,17 +675,25 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
|
|||||||
vendor = c->x86_vendor_id;
|
vendor = c->x86_vendor_id;
|
||||||
|
|
||||||
if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
|
if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
|
||||||
printk("%s ", vendor);
|
printk(KERN_CONT "%s ", vendor);
|
||||||
|
|
||||||
if (!c->x86_model_id[0])
|
if (c->x86_model_id[0])
|
||||||
printk("%d86", c->x86);
|
printk(KERN_CONT "%s", c->x86_model_id);
|
||||||
else
|
else
|
||||||
printk("%s", c->x86_model_id);
|
printk(KERN_CONT "%d86", c->x86);
|
||||||
|
|
||||||
if (c->x86_mask || c->cpuid_level >= 0)
|
if (c->x86_mask || c->cpuid_level >= 0)
|
||||||
printk(" stepping %02x\n", c->x86_mask);
|
printk(KERN_CONT " stepping %02x\n", c->x86_mask);
|
||||||
else
|
else
|
||||||
printk("\n");
|
printk(KERN_CONT "\n");
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
if (c->cpu_index < show_msr)
|
||||||
|
print_cpu_msr();
|
||||||
|
#else
|
||||||
|
if (show_msr)
|
||||||
|
print_cpu_msr();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init int setup_disablecpuid(char *arg)
|
static __init int setup_disablecpuid(char *arg)
|
||||||
@ -647,19 +709,6 @@ __setup("clearcpuid=", setup_disablecpuid);
|
|||||||
|
|
||||||
cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
|
cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
|
||||||
|
|
||||||
void __init early_cpu_init(void)
|
|
||||||
{
|
|
||||||
struct cpu_vendor_dev *cvdev;
|
|
||||||
|
|
||||||
for (cvdev = __x86cpuvendor_start ;
|
|
||||||
cvdev < __x86cpuvendor_end ;
|
|
||||||
cvdev++)
|
|
||||||
cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
|
|
||||||
|
|
||||||
early_cpu_detect();
|
|
||||||
validate_pat_support(&boot_cpu_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure %fs is initialized properly in idle threads */
|
/* Make sure %fs is initialized properly in idle threads */
|
||||||
struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
|
struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
@ -668,18 +717,6 @@ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
|
|||||||
return regs;
|
return regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Current gdt points %fs at the "master" per-cpu area: after this,
|
|
||||||
* it's on the real one. */
|
|
||||||
void switch_to_new_gdt(void)
|
|
||||||
{
|
|
||||||
struct desc_ptr gdt_descr;
|
|
||||||
|
|
||||||
gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
|
|
||||||
gdt_descr.size = GDT_SIZE - 1;
|
|
||||||
load_gdt(&gdt_descr);
|
|
||||||
asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cpu_init() initializes state that is per-CPU. Some data is already
|
* cpu_init() initializes state that is per-CPU. Some data is already
|
||||||
* initialized (naturally) in the bootstrap process, such as the GDT
|
* initialized (naturally) in the bootstrap process, such as the GDT
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
|
static struct cpu_dev *this_cpu __cpuinitdata;
|
||||||
|
|
||||||
/* We need valid kernel segments for data and code in long mode too
|
/* We need valid kernel segments for data and code in long mode too
|
||||||
* IRET will check the segment types kkeil 2000/10/28
|
* IRET will check the segment types kkeil 2000/10/28
|
||||||
* Also sysret mandates a special GDT layout
|
* Also sysret mandates a special GDT layout
|
||||||
@ -66,7 +68,7 @@ void switch_to_new_gdt(void)
|
|||||||
load_gdt(&gdt_descr);
|
load_gdt(&gdt_descr);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
|
static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
|
||||||
|
|
||||||
static void __cpuinit default_init(struct cpuinfo_x86 *c)
|
static void __cpuinit default_init(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
@ -76,12 +78,13 @@ static void __cpuinit default_init(struct cpuinfo_x86 *c)
|
|||||||
static struct cpu_dev __cpuinitdata default_cpu = {
|
static struct cpu_dev __cpuinitdata default_cpu = {
|
||||||
.c_init = default_init,
|
.c_init = default_init,
|
||||||
.c_vendor = "Unknown",
|
.c_vendor = "Unknown",
|
||||||
|
.c_x86_vendor = X86_VENDOR_UNKNOWN,
|
||||||
};
|
};
|
||||||
static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
|
|
||||||
|
|
||||||
int __cpuinit get_model_name(struct cpuinfo_x86 *c)
|
int __cpuinit get_model_name(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
unsigned int *v;
|
unsigned int *v;
|
||||||
|
char *p, *q;
|
||||||
|
|
||||||
if (c->extended_cpuid_level < 0x80000004)
|
if (c->extended_cpuid_level < 0x80000004)
|
||||||
return 0;
|
return 0;
|
||||||
@ -91,35 +94,49 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c)
|
|||||||
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
|
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
|
||||||
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;
|
||||||
|
|
||||||
|
/* Intel chips right-justify this string for some dumb reason;
|
||||||
|
undo that brain damage */
|
||||||
|
p = q = &c->x86_model_id[0];
|
||||||
|
while (*p == ' ')
|
||||||
|
p++;
|
||||||
|
if (p != q) {
|
||||||
|
while (*p)
|
||||||
|
*q++ = *p++;
|
||||||
|
while (q <= &c->x86_model_id[48])
|
||||||
|
*q++ = '\0'; /* Zero-pad the rest */
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
|
void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
unsigned int n, dummy, ebx, ecx, edx;
|
unsigned int n, dummy, ebx, ecx, edx, l2size;
|
||||||
|
|
||||||
n = c->extended_cpuid_level;
|
n = c->extended_cpuid_level;
|
||||||
|
|
||||||
if (n >= 0x80000005) {
|
if (n >= 0x80000005) {
|
||||||
cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
|
cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
|
||||||
printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), "
|
printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
|
||||||
"D cache %dK (%d bytes/line)\n",
|
edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
|
||||||
edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
|
|
||||||
c->x86_cache_size = (ecx>>24) + (edx>>24);
|
c->x86_cache_size = (ecx>>24) + (edx>>24);
|
||||||
/* On K8 L1 TLB is inclusive, so don't count it */
|
/* On K8 L1 TLB is inclusive, so don't count it */
|
||||||
c->x86_tlbsize = 0;
|
c->x86_tlbsize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n >= 0x80000006) {
|
if (n < 0x80000006) /* Some chips just has a large L1. */
|
||||||
cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
|
return;
|
||||||
ecx = cpuid_ecx(0x80000006);
|
|
||||||
c->x86_cache_size = ecx >> 16;
|
|
||||||
c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
|
|
||||||
|
|
||||||
printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
|
cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
|
||||||
c->x86_cache_size, ecx & 0xFF);
|
l2size = ecx >> 16;
|
||||||
}
|
c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
|
||||||
|
|
||||||
|
c->x86_cache_size = l2size;
|
||||||
|
|
||||||
|
printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
|
||||||
|
l2size, ecx & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
||||||
@ -128,14 +145,13 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
|||||||
u32 eax, ebx, ecx, edx;
|
u32 eax, ebx, ecx, edx;
|
||||||
int index_msb, core_bits;
|
int index_msb, core_bits;
|
||||||
|
|
||||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
|
||||||
|
|
||||||
|
|
||||||
if (!cpu_has(c, X86_FEATURE_HT))
|
if (!cpu_has(c, X86_FEATURE_HT))
|
||||||
return;
|
return;
|
||||||
if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
smp_num_siblings = (ebx & 0xff0000) >> 16;
|
smp_num_siblings = (ebx & 0xff0000) >> 16;
|
||||||
|
|
||||||
if (smp_num_siblings == 1) {
|
if (smp_num_siblings == 1) {
|
||||||
@ -143,8 +159,8 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
|||||||
} else if (smp_num_siblings > 1) {
|
} else if (smp_num_siblings > 1) {
|
||||||
|
|
||||||
if (smp_num_siblings > NR_CPUS) {
|
if (smp_num_siblings > NR_CPUS) {
|
||||||
printk(KERN_WARNING "CPU: Unsupported number of "
|
printk(KERN_WARNING "CPU: Unsupported number of siblings %d",
|
||||||
"siblings %d", smp_num_siblings);
|
smp_num_siblings);
|
||||||
smp_num_siblings = 1;
|
smp_num_siblings = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -161,6 +177,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
|||||||
c->cpu_core_id = phys_pkg_id(index_msb) &
|
c->cpu_core_id = phys_pkg_id(index_msb) &
|
||||||
((1 << core_bits) - 1);
|
((1 << core_bits) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if ((c->x86_max_cores * smp_num_siblings) > 1) {
|
if ((c->x86_max_cores * smp_num_siblings) > 1) {
|
||||||
printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
|
printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
|
||||||
@ -168,7 +185,6 @@ out:
|
|||||||
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
|
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
|
||||||
c->cpu_core_id);
|
c->cpu_core_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,43 +195,150 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
|
|||||||
static int printed;
|
static int printed;
|
||||||
|
|
||||||
for (i = 0; i < X86_VENDOR_NUM; i++) {
|
for (i = 0; i < X86_VENDOR_NUM; i++) {
|
||||||
if (cpu_devs[i]) {
|
if (!cpu_devs[i])
|
||||||
if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
|
break;
|
||||||
(cpu_devs[i]->c_ident[1] &&
|
|
||||||
!strcmp(v, cpu_devs[i]->c_ident[1]))) {
|
if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
|
||||||
c->x86_vendor = i;
|
(cpu_devs[i]->c_ident[1] &&
|
||||||
this_cpu = cpu_devs[i];
|
!strcmp(v, cpu_devs[i]->c_ident[1]))) {
|
||||||
return;
|
this_cpu = cpu_devs[i];
|
||||||
}
|
c->x86_vendor = this_cpu->c_x86_vendor;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!printed) {
|
if (!printed) {
|
||||||
printed++;
|
printed++;
|
||||||
printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
|
printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
|
||||||
printk(KERN_ERR "CPU: Your system may be unstable.\n");
|
printk(KERN_ERR "CPU: Your system may be unstable.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
c->x86_vendor = X86_VENDOR_UNKNOWN;
|
c->x86_vendor = X86_VENDOR_UNKNOWN;
|
||||||
|
this_cpu = &default_cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init early_cpu_support_print(void)
|
void __cpuinit cpu_detect(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
int i,j;
|
/* Get vendor name */
|
||||||
struct cpu_dev *cpu_devx;
|
cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
|
||||||
|
(unsigned int *)&c->x86_vendor_id[0],
|
||||||
|
(unsigned int *)&c->x86_vendor_id[8],
|
||||||
|
(unsigned int *)&c->x86_vendor_id[4]);
|
||||||
|
|
||||||
printk("KERNEL supported cpus:\n");
|
c->x86 = 4;
|
||||||
for (i = 0; i < X86_VENDOR_NUM; i++) {
|
/* Intel-defined flags: level 0x00000001 */
|
||||||
cpu_devx = cpu_devs[i];
|
if (c->cpuid_level >= 0x00000001) {
|
||||||
if (!cpu_devx)
|
u32 junk, tfms, cap0, misc;
|
||||||
continue;
|
cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
|
||||||
for (j = 0; j < 2; j++) {
|
c->x86 = (tfms >> 8) & 0xf;
|
||||||
if (!cpu_devx->c_ident[j])
|
c->x86_model = (tfms >> 4) & 0xf;
|
||||||
continue;
|
c->x86_mask = tfms & 0xf;
|
||||||
printk(" %s %s\n", cpu_devx->c_vendor,
|
if (c->x86 == 0xf)
|
||||||
cpu_devx->c_ident[j]);
|
c->x86 += (tfms >> 20) & 0xff;
|
||||||
|
if (c->x86 >= 0x6)
|
||||||
|
c->x86_model += ((tfms >> 16) & 0xf) << 4;
|
||||||
|
if (cap0 & (1<<19)) {
|
||||||
|
c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
|
||||||
|
c->x86_cache_alignment = c->x86_clflush_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
u32 tfms, xlvl;
|
||||||
|
u32 ebx;
|
||||||
|
|
||||||
|
/* Intel-defined flags: level 0x00000001 */
|
||||||
|
if (c->cpuid_level >= 0x00000001) {
|
||||||
|
u32 capability, excap;
|
||||||
|
|
||||||
|
cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
|
||||||
|
c->x86_capability[0] = capability;
|
||||||
|
c->x86_capability[4] = excap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AMD-defined flags: level 0x80000001 */
|
||||||
|
xlvl = cpuid_eax(0x80000000);
|
||||||
|
c->extended_cpuid_level = xlvl;
|
||||||
|
if ((xlvl & 0xffff0000) == 0x80000000) {
|
||||||
|
if (xlvl >= 0x80000001) {
|
||||||
|
c->x86_capability[1] = cpuid_edx(0x80000001);
|
||||||
|
c->x86_capability[6] = cpuid_ecx(0x80000001);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transmeta-defined flags: level 0x80860001 */
|
||||||
|
xlvl = cpuid_eax(0x80860000);
|
||||||
|
if ((xlvl & 0xffff0000) == 0x80860000) {
|
||||||
|
/* Don't set x86_cpuid_level here for now to not confuse. */
|
||||||
|
if (xlvl >= 0x80860001)
|
||||||
|
c->x86_capability[2] = cpuid_edx(0x80860001);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->extended_cpuid_level >= 0x80000007)
|
||||||
|
c->x86_power = cpuid_edx(0x80000007);
|
||||||
|
|
||||||
|
if (c->extended_cpuid_level >= 0x80000008) {
|
||||||
|
u32 eax = cpuid_eax(0x80000008);
|
||||||
|
|
||||||
|
c->x86_virt_bits = (eax >> 8) & 0xff;
|
||||||
|
c->x86_phys_bits = eax & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do some early cpuid on the boot CPU to get some parameter that are
|
||||||
|
needed before check_bugs. Everything advanced is in identify_cpu
|
||||||
|
below. */
|
||||||
|
static void __init early_identify_cpu(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
|
||||||
|
c->x86_clflush_size = 64;
|
||||||
|
c->x86_cache_alignment = c->x86_clflush_size;
|
||||||
|
|
||||||
|
memset(&c->x86_capability, 0, sizeof c->x86_capability);
|
||||||
|
|
||||||
|
c->extended_cpuid_level = 0;
|
||||||
|
|
||||||
|
cpu_detect(c);
|
||||||
|
|
||||||
|
get_cpu_vendor(c);
|
||||||
|
|
||||||
|
get_cpu_cap(c);
|
||||||
|
|
||||||
|
if (this_cpu->c_early_init)
|
||||||
|
this_cpu->c_early_init(c);
|
||||||
|
|
||||||
|
validate_pat_support(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init early_cpu_init(void)
|
||||||
|
{
|
||||||
|
struct cpu_dev **cdev;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
printk("KERNEL supported cpus:\n");
|
||||||
|
for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
|
||||||
|
struct cpu_dev *cpudev = *cdev;
|
||||||
|
unsigned int j;
|
||||||
|
|
||||||
|
if (count >= X86_VENDOR_NUM)
|
||||||
|
break;
|
||||||
|
cpu_devs[count] = cpudev;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
for (j = 0; j < 2; j++) {
|
||||||
|
if (!cpudev->c_ident[j])
|
||||||
|
continue;
|
||||||
|
printk(" %s %s\n", cpudev->c_vendor,
|
||||||
|
cpudev->c_ident[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
early_identify_cpu(&boot_cpu_data);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The NOPL instruction is supposed to exist on all CPUs with
|
* The NOPL instruction is supposed to exist on all CPUs with
|
||||||
* family >= 6, unfortunately, that's not true in practice because
|
* family >= 6, unfortunately, that's not true in practice because
|
||||||
@ -249,111 +372,26 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
|
static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
|
||||||
|
|
||||||
void __init early_cpu_init(void)
|
|
||||||
{
|
{
|
||||||
struct cpu_vendor_dev *cvdev;
|
|
||||||
|
|
||||||
for (cvdev = __x86cpuvendor_start ;
|
|
||||||
cvdev < __x86cpuvendor_end ;
|
|
||||||
cvdev++)
|
|
||||||
cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
|
|
||||||
early_cpu_support_print();
|
|
||||||
early_identify_cpu(&boot_cpu_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do some early cpuid on the boot CPU to get some parameter that are
|
|
||||||
needed before check_bugs. Everything advanced is in identify_cpu
|
|
||||||
below. */
|
|
||||||
static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
u32 tfms, xlvl;
|
|
||||||
|
|
||||||
c->loops_per_jiffy = loops_per_jiffy;
|
|
||||||
c->x86_cache_size = -1;
|
|
||||||
c->x86_vendor = X86_VENDOR_UNKNOWN;
|
|
||||||
c->x86_model = c->x86_mask = 0; /* So far unknown... */
|
|
||||||
c->x86_vendor_id[0] = '\0'; /* Unset */
|
|
||||||
c->x86_model_id[0] = '\0'; /* Unset */
|
|
||||||
c->x86_clflush_size = 64;
|
|
||||||
c->x86_cache_alignment = c->x86_clflush_size;
|
|
||||||
c->x86_max_cores = 1;
|
|
||||||
c->x86_coreid_bits = 0;
|
|
||||||
c->extended_cpuid_level = 0;
|
c->extended_cpuid_level = 0;
|
||||||
memset(&c->x86_capability, 0, sizeof c->x86_capability);
|
|
||||||
|
|
||||||
/* Get vendor name */
|
cpu_detect(c);
|
||||||
cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
|
|
||||||
(unsigned int *)&c->x86_vendor_id[0],
|
|
||||||
(unsigned int *)&c->x86_vendor_id[8],
|
|
||||||
(unsigned int *)&c->x86_vendor_id[4]);
|
|
||||||
|
|
||||||
get_cpu_vendor(c);
|
get_cpu_vendor(c);
|
||||||
|
|
||||||
/* Initialize the standard set of capabilities */
|
get_cpu_cap(c);
|
||||||
/* Note that the vendor-specific code below might override */
|
|
||||||
|
|
||||||
/* Intel-defined flags: level 0x00000001 */
|
|
||||||
if (c->cpuid_level >= 0x00000001) {
|
|
||||||
__u32 misc;
|
|
||||||
cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
|
|
||||||
&c->x86_capability[0]);
|
|
||||||
c->x86 = (tfms >> 8) & 0xf;
|
|
||||||
c->x86_model = (tfms >> 4) & 0xf;
|
|
||||||
c->x86_mask = tfms & 0xf;
|
|
||||||
if (c->x86 == 0xf)
|
|
||||||
c->x86 += (tfms >> 20) & 0xff;
|
|
||||||
if (c->x86 >= 0x6)
|
|
||||||
c->x86_model += ((tfms >> 16) & 0xF) << 4;
|
|
||||||
if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
|
|
||||||
c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
|
|
||||||
} else {
|
|
||||||
/* Have CPUID level 0 only - unheard of */
|
|
||||||
c->x86 = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff;
|
c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
c->phys_proc_id = c->initial_apicid;
|
c->phys_proc_id = c->initial_apicid;
|
||||||
#endif
|
#endif
|
||||||
/* AMD-defined flags: level 0x80000001 */
|
|
||||||
xlvl = cpuid_eax(0x80000000);
|
|
||||||
c->extended_cpuid_level = xlvl;
|
|
||||||
if ((xlvl & 0xffff0000) == 0x80000000) {
|
|
||||||
if (xlvl >= 0x80000001) {
|
|
||||||
c->x86_capability[1] = cpuid_edx(0x80000001);
|
|
||||||
c->x86_capability[6] = cpuid_ecx(0x80000001);
|
|
||||||
}
|
|
||||||
if (xlvl >= 0x80000004)
|
|
||||||
get_model_name(c); /* Default name */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Transmeta-defined flags: level 0x80860001 */
|
if (c->extended_cpuid_level >= 0x80000004)
|
||||||
xlvl = cpuid_eax(0x80860000);
|
get_model_name(c); /* Default name */
|
||||||
if ((xlvl & 0xffff0000) == 0x80860000) {
|
|
||||||
/* Don't set x86_cpuid_level here for now to not confuse. */
|
|
||||||
if (xlvl >= 0x80860001)
|
|
||||||
c->x86_capability[2] = cpuid_edx(0x80860001);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->extended_cpuid_level >= 0x80000007)
|
|
||||||
c->x86_power = cpuid_edx(0x80000007);
|
|
||||||
|
|
||||||
if (c->extended_cpuid_level >= 0x80000008) {
|
|
||||||
u32 eax = cpuid_eax(0x80000008);
|
|
||||||
|
|
||||||
c->x86_virt_bits = (eax >> 8) & 0xff;
|
|
||||||
c->x86_phys_bits = eax & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
init_scattered_cpuid_features(c);
|
||||||
detect_nopl(c);
|
detect_nopl(c);
|
||||||
|
|
||||||
if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
|
|
||||||
cpu_devs[c->x86_vendor]->c_early_init)
|
|
||||||
cpu_devs[c->x86_vendor]->c_early_init(c);
|
|
||||||
|
|
||||||
validate_pat_support(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -363,9 +401,19 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
early_identify_cpu(c);
|
c->loops_per_jiffy = loops_per_jiffy;
|
||||||
|
c->x86_cache_size = -1;
|
||||||
|
c->x86_vendor = X86_VENDOR_UNKNOWN;
|
||||||
|
c->x86_model = c->x86_mask = 0; /* So far unknown... */
|
||||||
|
c->x86_vendor_id[0] = '\0'; /* Unset */
|
||||||
|
c->x86_model_id[0] = '\0'; /* Unset */
|
||||||
|
c->x86_max_cores = 1;
|
||||||
|
c->x86_coreid_bits = 0;
|
||||||
|
c->x86_clflush_size = 64;
|
||||||
|
c->x86_cache_alignment = c->x86_clflush_size;
|
||||||
|
memset(&c->x86_capability, 0, sizeof c->x86_capability);
|
||||||
|
|
||||||
init_scattered_cpuid_features(c);
|
generic_identify(c);
|
||||||
|
|
||||||
c->apicid = phys_pkg_id(0);
|
c->apicid = phys_pkg_id(0);
|
||||||
|
|
||||||
@ -411,7 +459,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit identify_boot_cpu(void)
|
void __init identify_boot_cpu(void)
|
||||||
{
|
{
|
||||||
identify_cpu(&boot_cpu_data);
|
identify_cpu(&boot_cpu_data);
|
||||||
}
|
}
|
||||||
@ -423,6 +471,49 @@ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
|
|||||||
mtrr_ap_init();
|
mtrr_ap_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct msr_range {
|
||||||
|
unsigned min;
|
||||||
|
unsigned max;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct msr_range msr_range_array[] __cpuinitdata = {
|
||||||
|
{ 0x00000000, 0x00000418},
|
||||||
|
{ 0xc0000000, 0xc000040b},
|
||||||
|
{ 0xc0010000, 0xc0010142},
|
||||||
|
{ 0xc0011000, 0xc001103b},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __cpuinit print_cpu_msr(void)
|
||||||
|
{
|
||||||
|
unsigned index;
|
||||||
|
u64 val;
|
||||||
|
int i;
|
||||||
|
unsigned index_min, index_max;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
|
||||||
|
index_min = msr_range_array[i].min;
|
||||||
|
index_max = msr_range_array[i].max;
|
||||||
|
for (index = index_min; index < index_max; index++) {
|
||||||
|
if (rdmsrl_amd_safe(index, &val))
|
||||||
|
continue;
|
||||||
|
printk(KERN_INFO " MSR%08x: %016llx\n", index, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int show_msr __cpuinitdata;
|
||||||
|
static __init int setup_show_msr(char *arg)
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
|
||||||
|
get_option(&arg, &num);
|
||||||
|
|
||||||
|
if (num > 0)
|
||||||
|
show_msr = num;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
__setup("show_msr=", setup_show_msr);
|
||||||
|
|
||||||
static __init int setup_noclflush(char *arg)
|
static __init int setup_noclflush(char *arg)
|
||||||
{
|
{
|
||||||
setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
|
setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
|
||||||
@ -439,6 +530,14 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
|
|||||||
printk(KERN_CONT " stepping %02x\n", c->x86_mask);
|
printk(KERN_CONT " stepping %02x\n", c->x86_mask);
|
||||||
else
|
else
|
||||||
printk(KERN_CONT "\n");
|
printk(KERN_CONT "\n");
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
if (c->cpu_index < show_msr)
|
||||||
|
print_cpu_msr();
|
||||||
|
#else
|
||||||
|
if (show_msr)
|
||||||
|
print_cpu_msr();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init int setup_disablecpuid(char *arg)
|
static __init int setup_disablecpuid(char *arg)
|
||||||
|
@ -21,21 +21,15 @@ struct cpu_dev {
|
|||||||
void (*c_init)(struct cpuinfo_x86 * c);
|
void (*c_init)(struct cpuinfo_x86 * c);
|
||||||
void (*c_identify)(struct cpuinfo_x86 * c);
|
void (*c_identify)(struct cpuinfo_x86 * c);
|
||||||
unsigned int (*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size);
|
unsigned int (*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size);
|
||||||
|
int c_x86_vendor;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
|
#define cpu_dev_register(cpu_devX) \
|
||||||
|
static struct cpu_dev *__cpu_dev_##cpu_devX __used \
|
||||||
|
__attribute__((__section__(".x86_cpu_dev.init"))) = \
|
||||||
|
&cpu_devX;
|
||||||
|
|
||||||
struct cpu_vendor_dev {
|
extern struct cpu_dev *__x86_cpu_dev_start[], *__x86_cpu_dev_end[];
|
||||||
int vendor;
|
|
||||||
struct cpu_dev *cpu_dev;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define cpu_vendor_dev_register(cpu_vendor_id, cpu_dev) \
|
|
||||||
static struct cpu_vendor_dev __cpu_vendor_dev_##cpu_vendor_id __used \
|
|
||||||
__attribute__((__section__(".x86cpuvendor.init"))) = \
|
|
||||||
{ cpu_vendor_id, cpu_dev }
|
|
||||||
|
|
||||||
extern struct cpu_vendor_dev __x86cpuvendor_start[], __x86cpuvendor_end[];
|
|
||||||
|
|
||||||
extern int get_model_name(struct cpuinfo_x86 *c);
|
extern int get_model_name(struct cpuinfo_x86 *c);
|
||||||
extern void display_cacheinfo(struct cpuinfo_x86 *c);
|
extern void display_cacheinfo(struct cpuinfo_x86 *c);
|
||||||
|
@ -15,13 +15,11 @@
|
|||||||
/*
|
/*
|
||||||
* Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
|
* Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
|
||||||
*/
|
*/
|
||||||
static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
|
static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
|
||||||
{
|
{
|
||||||
unsigned char ccr2, ccr3;
|
unsigned char ccr2, ccr3;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/* we test for DEVID by checking whether CCR3 is writable */
|
/* we test for DEVID by checking whether CCR3 is writable */
|
||||||
local_irq_save(flags);
|
|
||||||
ccr3 = getCx86(CX86_CCR3);
|
ccr3 = getCx86(CX86_CCR3);
|
||||||
setCx86(CX86_CCR3, ccr3 ^ 0x80);
|
setCx86(CX86_CCR3, ccr3 ^ 0x80);
|
||||||
getCx86(0xc0); /* dummy to change bus */
|
getCx86(0xc0); /* dummy to change bus */
|
||||||
@ -44,9 +42,16 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
|
|||||||
*dir0 = getCx86(CX86_DIR0);
|
*dir0 = getCx86(CX86_DIR0);
|
||||||
*dir1 = getCx86(CX86_DIR1);
|
*dir1 = getCx86(CX86_DIR1);
|
||||||
}
|
}
|
||||||
local_irq_restore(flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
__do_cyrix_devid(dir0, dir1);
|
||||||
|
local_irq_restore(flags);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
|
* Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
|
||||||
* order to identify the Cyrix CPU model after we're out of setup.c
|
* order to identify the Cyrix CPU model after we're out of setup.c
|
||||||
@ -161,6 +166,24 @@ static void __cpuinit geode_configure(void)
|
|||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c)
|
||||||
|
{
|
||||||
|
unsigned char dir0, dir0_msn, dir1 = 0;
|
||||||
|
|
||||||
|
__do_cyrix_devid(&dir0, &dir1);
|
||||||
|
dir0_msn = dir0 >> 4; /* identifies CPU "family" */
|
||||||
|
|
||||||
|
switch (dir0_msn) {
|
||||||
|
case 3: /* 6x86/6x86L */
|
||||||
|
/* Emulate MTRRs using Cyrix's ARRs. */
|
||||||
|
set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
|
||||||
|
break;
|
||||||
|
case 5: /* 6x86MX/M II */
|
||||||
|
/* Emulate MTRRs using Cyrix's ARRs. */
|
||||||
|
set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
|
static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
@ -416,16 +439,19 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c)
|
|||||||
static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
|
static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
|
||||||
.c_vendor = "Cyrix",
|
.c_vendor = "Cyrix",
|
||||||
.c_ident = { "CyrixInstead" },
|
.c_ident = { "CyrixInstead" },
|
||||||
|
.c_early_init = early_init_cyrix,
|
||||||
.c_init = init_cyrix,
|
.c_init = init_cyrix,
|
||||||
.c_identify = cyrix_identify,
|
.c_identify = cyrix_identify,
|
||||||
|
.c_x86_vendor = X86_VENDOR_CYRIX,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_CYRIX, &cyrix_cpu_dev);
|
cpu_dev_register(cyrix_cpu_dev);
|
||||||
|
|
||||||
static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
|
static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
|
||||||
.c_vendor = "NSC",
|
.c_vendor = "NSC",
|
||||||
.c_ident = { "Geode by NSC" },
|
.c_ident = { "Geode by NSC" },
|
||||||
.c_init = init_nsc,
|
.c_init = init_nsc,
|
||||||
|
.c_x86_vendor = X86_VENDOR_NSC,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_NSC, &nsc_cpu_dev);
|
cpu_dev_register(nsc_cpu_dev);
|
||||||
|
@ -303,9 +303,10 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
|
|||||||
.c_early_init = early_init_intel,
|
.c_early_init = early_init_intel,
|
||||||
.c_init = init_intel,
|
.c_init = init_intel,
|
||||||
.c_size_cache = intel_size_cache,
|
.c_size_cache = intel_size_cache,
|
||||||
|
.c_x86_vendor = X86_VENDOR_INTEL,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev);
|
cpu_dev_register(intel_cpu_dev);
|
||||||
|
|
||||||
/* arch_initcall(intel_cpu_init); */
|
/* arch_initcall(intel_cpu_init); */
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
|
|||||||
.c_ident = { "GenuineIntel" },
|
.c_ident = { "GenuineIntel" },
|
||||||
.c_early_init = early_init_intel,
|
.c_early_init = early_init_intel,
|
||||||
.c_init = init_intel,
|
.c_init = init_intel,
|
||||||
|
.c_x86_vendor = X86_VENDOR_INTEL,
|
||||||
};
|
};
|
||||||
cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev);
|
|
||||||
|
|
||||||
|
cpu_dev_register(intel_cpu_dev);
|
||||||
|
@ -102,6 +102,7 @@ static struct cpu_dev transmeta_cpu_dev __cpuinitdata = {
|
|||||||
.c_ident = { "GenuineTMx86", "TransmetaCPU" },
|
.c_ident = { "GenuineTMx86", "TransmetaCPU" },
|
||||||
.c_init = init_transmeta,
|
.c_init = init_transmeta,
|
||||||
.c_identify = transmeta_identify,
|
.c_identify = transmeta_identify,
|
||||||
|
.c_x86_vendor = X86_VENDOR_TRANSMETA,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_TRANSMETA, &transmeta_cpu_dev);
|
cpu_dev_register(transmeta_cpu_dev);
|
||||||
|
@ -19,7 +19,8 @@ static struct cpu_dev umc_cpu_dev __cpuinitdata = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.c_x86_vendor = X86_VENDOR_UMC,
|
||||||
};
|
};
|
||||||
|
|
||||||
cpu_vendor_dev_register(X86_VENDOR_UMC, &umc_cpu_dev);
|
cpu_dev_register(umc_cpu_dev);
|
||||||
|
|
||||||
|
@ -330,6 +330,7 @@ struct pv_cpu_ops pv_cpu_ops = {
|
|||||||
#endif
|
#endif
|
||||||
.wbinvd = native_wbinvd,
|
.wbinvd = native_wbinvd,
|
||||||
.read_msr = native_read_msr_safe,
|
.read_msr = native_read_msr_safe,
|
||||||
|
.read_msr_amd = native_read_msr_amd_safe,
|
||||||
.write_msr = native_write_msr_safe,
|
.write_msr = native_write_msr_safe,
|
||||||
.read_tsc = native_read_tsc,
|
.read_tsc = native_read_tsc,
|
||||||
.read_pmc = native_read_pmc,
|
.read_pmc = native_read_pmc,
|
||||||
|
@ -339,9 +339,8 @@ static void
|
|||||||
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
||||||
unsigned long *stack, unsigned long bp, char *log_lvl)
|
unsigned long *stack, unsigned long bp, char *log_lvl)
|
||||||
{
|
{
|
||||||
printk("\nCall Trace:\n");
|
printk("Call Trace:\n");
|
||||||
dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
|
dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
|
||||||
printk("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_trace(struct task_struct *task, struct pt_regs *regs,
|
void show_trace(struct task_struct *task, struct pt_regs *regs,
|
||||||
@ -386,6 +385,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
|||||||
printk(" %016lx", *stack++);
|
printk(" %016lx", *stack++);
|
||||||
touch_nmi_watchdog();
|
touch_nmi_watchdog();
|
||||||
}
|
}
|
||||||
|
printk("\n");
|
||||||
show_trace_log_lvl(task, regs, sp, bp, log_lvl);
|
show_trace_log_lvl(task, regs, sp, bp, log_lvl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +443,6 @@ void show_registers(struct pt_regs *regs)
|
|||||||
printk("Stack: ");
|
printk("Stack: ");
|
||||||
show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
|
show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
|
||||||
regs->bp, "");
|
regs->bp, "");
|
||||||
printk("\n");
|
|
||||||
|
|
||||||
printk(KERN_EMERG "Code: ");
|
printk(KERN_EMERG "Code: ");
|
||||||
|
|
||||||
|
@ -140,10 +140,10 @@ SECTIONS
|
|||||||
*(.con_initcall.init)
|
*(.con_initcall.init)
|
||||||
__con_initcall_end = .;
|
__con_initcall_end = .;
|
||||||
}
|
}
|
||||||
.x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) {
|
.x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
|
||||||
__x86cpuvendor_start = .;
|
__x86_cpu_dev_start = .;
|
||||||
*(.x86cpuvendor.init)
|
*(.x86_cpu_dev.init)
|
||||||
__x86cpuvendor_end = .;
|
__x86_cpu_dev_end = .;
|
||||||
}
|
}
|
||||||
SECURITY_INIT
|
SECURITY_INIT
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
@ -168,13 +168,12 @@ SECTIONS
|
|||||||
*(.con_initcall.init)
|
*(.con_initcall.init)
|
||||||
}
|
}
|
||||||
__con_initcall_end = .;
|
__con_initcall_end = .;
|
||||||
. = ALIGN(16);
|
__x86_cpu_dev_start = .;
|
||||||
__x86cpuvendor_start = .;
|
.x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
|
||||||
.x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) {
|
*(.x86_cpu_dev.init)
|
||||||
*(.x86cpuvendor.init)
|
|
||||||
}
|
}
|
||||||
__x86cpuvendor_end = .;
|
|
||||||
SECURITY_INIT
|
SECURITY_INIT
|
||||||
|
__x86_cpu_dev_end = .;
|
||||||
|
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
.parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
|
.parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
|
||||||
|
@ -63,6 +63,22 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
|
|||||||
return EAX_EDX_VAL(val, low, high);
|
return EAX_EDX_VAL(val, low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned long long native_read_msr_amd_safe(unsigned int msr,
|
||||||
|
int *err)
|
||||||
|
{
|
||||||
|
DECLARE_ARGS(val, low, high);
|
||||||
|
|
||||||
|
asm volatile("2: rdmsr ; xor %0,%0\n"
|
||||||
|
"1:\n\t"
|
||||||
|
".section .fixup,\"ax\"\n\t"
|
||||||
|
"3: mov %3,%0 ; jmp 1b\n\t"
|
||||||
|
".previous\n\t"
|
||||||
|
_ASM_EXTABLE(2b, 3b)
|
||||||
|
: "=r" (*err), EAX_EDX_RET(val, low, high)
|
||||||
|
: "c" (msr), "D" (0x9c5a203a), "i" (-EFAULT));
|
||||||
|
return EAX_EDX_VAL(val, low, high);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void native_write_msr(unsigned int msr,
|
static inline void native_write_msr(unsigned int msr,
|
||||||
unsigned low, unsigned high)
|
unsigned low, unsigned high)
|
||||||
{
|
{
|
||||||
@ -158,6 +174,13 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
|
|||||||
*p = native_read_msr_safe(msr, &err);
|
*p = native_read_msr_safe(msr, &err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
*p = native_read_msr_amd_safe(msr, &err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
#define rdtscl(low) \
|
#define rdtscl(low) \
|
||||||
((low) = (u32)native_read_tsc())
|
((low) = (u32)native_read_tsc())
|
||||||
|
@ -137,6 +137,7 @@ struct pv_cpu_ops {
|
|||||||
|
|
||||||
/* MSR, PMC and TSR operations.
|
/* MSR, PMC and TSR operations.
|
||||||
err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */
|
err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */
|
||||||
|
u64 (*read_msr_amd)(unsigned int msr, int *err);
|
||||||
u64 (*read_msr)(unsigned int msr, int *err);
|
u64 (*read_msr)(unsigned int msr, int *err);
|
||||||
int (*write_msr)(unsigned int msr, unsigned low, unsigned high);
|
int (*write_msr)(unsigned int msr, unsigned low, unsigned high);
|
||||||
|
|
||||||
@ -720,6 +721,10 @@ static inline u64 paravirt_read_msr(unsigned msr, int *err)
|
|||||||
{
|
{
|
||||||
return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err);
|
return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err);
|
||||||
}
|
}
|
||||||
|
static inline u64 paravirt_read_msr_amd(unsigned msr, int *err)
|
||||||
|
{
|
||||||
|
return PVOP_CALL2(u64, pv_cpu_ops.read_msr_amd, msr, err);
|
||||||
|
}
|
||||||
static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
|
static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
|
||||||
{
|
{
|
||||||
return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high);
|
return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high);
|
||||||
@ -765,6 +770,13 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
|
|||||||
*p = paravirt_read_msr(msr, &err);
|
*p = paravirt_read_msr(msr, &err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
*p = paravirt_read_msr_amd(msr, &err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static inline u64 paravirt_read_tsc(void)
|
static inline u64 paravirt_read_tsc(void)
|
||||||
{
|
{
|
||||||
|
@ -77,9 +77,9 @@ struct cpuinfo_x86 {
|
|||||||
__u8 x86_phys_bits;
|
__u8 x86_phys_bits;
|
||||||
/* CPUID returned core id bits: */
|
/* CPUID returned core id bits: */
|
||||||
__u8 x86_coreid_bits;
|
__u8 x86_coreid_bits;
|
||||||
|
#endif
|
||||||
/* Max extended CPUID function supported: */
|
/* Max extended CPUID function supported: */
|
||||||
__u32 extended_cpuid_level;
|
__u32 extended_cpuid_level;
|
||||||
#endif
|
|
||||||
/* Maximum supported CPUID level, -1=no CPUID: */
|
/* Maximum supported CPUID level, -1=no CPUID: */
|
||||||
int cpuid_level;
|
int cpuid_level;
|
||||||
__u32 x86_capability[NCAPINTS];
|
__u32 x86_capability[NCAPINTS];
|
||||||
|
Loading…
Reference in New Issue
Block a user