Skip to content

Commit 64f996f

Browse files
committed
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86: cpu_init(): fix memory leak when using CPU hotplug x86: pda_init(): fix memory leak when using CPU hotplug x86, xen: Use native_pte_flags instead of native_pte_val for .pte_flags x86: move mtrr cpu cap setting early in early_init_xxxx x86: delay early cpu initialization until cpuid is done x86: use X86_FEATURE_NOPL in alternatives x86: add NOPL as a synthetic CPU feature bit x86: boot: stub out unimplemented CPU feature words
2 parents f532522 + 23952a9 commit 64f996f

File tree

11 files changed

+167
-61
lines changed

11 files changed

+167
-61
lines changed

arch/x86/boot/cpucheck.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ static const u32 req_flags[NCAPINTS] =
3838
{
3939
REQUIRED_MASK0,
4040
REQUIRED_MASK1,
41-
REQUIRED_MASK2,
42-
REQUIRED_MASK3,
41+
0, /* REQUIRED_MASK2 not implemented in this file */
42+
0, /* REQUIRED_MASK3 not implemented in this file */
4343
REQUIRED_MASK4,
44-
REQUIRED_MASK5,
44+
0, /* REQUIRED_MASK5 not implemented in this file */
4545
REQUIRED_MASK6,
46-
REQUIRED_MASK7,
46+
0, /* REQUIRED_MASK7 not implemented in this file */
4747
};
4848

4949
#define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))

arch/x86/kernel/alternative.c

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -145,35 +145,25 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = {
145145
extern char __vsyscall_0;
146146
const unsigned char *const *find_nop_table(void)
147147
{
148-
return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
149-
boot_cpu_data.x86 < 6 ? k8_nops : p6_nops;
148+
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
149+
boot_cpu_has(X86_FEATURE_NOPL))
150+
return p6_nops;
151+
else
152+
return k8_nops;
150153
}
151154

152155
#else /* CONFIG_X86_64 */
153156

154-
static const struct nop {
155-
int cpuid;
156-
const unsigned char *const *noptable;
157-
} noptypes[] = {
158-
{ X86_FEATURE_K8, k8_nops },
159-
{ X86_FEATURE_K7, k7_nops },
160-
{ X86_FEATURE_P4, p6_nops },
161-
{ X86_FEATURE_P3, p6_nops },
162-
{ -1, NULL }
163-
};
164-
165157
const unsigned char *const *find_nop_table(void)
166158
{
167-
const unsigned char *const *noptable = intel_nops;
168-
int i;
169-
170-
for (i = 0; noptypes[i].cpuid >= 0; i++) {
171-
if (boot_cpu_has(noptypes[i].cpuid)) {
172-
noptable = noptypes[i].noptable;
173-
break;
174-
}
175-
}
176-
return noptable;
159+
if (boot_cpu_has(X86_FEATURE_K8))
160+
return k8_nops;
161+
else if (boot_cpu_has(X86_FEATURE_K7))
162+
return k7_nops;
163+
else if (boot_cpu_has(X86_FEATURE_NOPL))
164+
return p6_nops;
165+
else
166+
return intel_nops;
177167
}
178168

179169
#endif /* CONFIG_X86_64 */

arch/x86/kernel/cpu/amd.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
3131
if (c->x86_power & (1<<8))
3232
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
3333
}
34+
35+
/* Set MTRR capability flag if appropriate */
36+
if (c->x86_model == 13 || c->x86_model == 9 ||
37+
(c->x86_model == 8 && c->x86_mask >= 8))
38+
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
3439
}
3540

3641
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -166,10 +171,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
166171
mbytes);
167172
}
168173

169-
/* Set MTRR capability flag if appropriate */
170-
if (c->x86_model == 13 || c->x86_model == 9 ||
171-
(c->x86_model == 8 && c->x86_mask >= 8))
172-
set_cpu_cap(c, X86_FEATURE_K6_MTRR);
173174
break;
174175
}
175176

arch/x86/kernel/cpu/centaur.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,16 @@ enum {
314314
EAMD3D = 1<<20,
315315
};
316316

317+
static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
318+
{
319+
switch (c->x86) {
320+
case 5:
321+
/* Emulate MTRRs using Centaur's MCR. */
322+
set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
323+
break;
324+
}
325+
}
326+
317327
static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
318328
{
319329

@@ -462,6 +472,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
462472
static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
463473
.c_vendor = "Centaur",
464474
.c_ident = { "CentaurHauls" },
475+
.c_early_init = early_init_centaur,
465476
.c_init = init_centaur,
466477
.c_size_cache = centaur_size_cache,
467478
};

arch/x86/kernel/cpu/common.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <asm/mtrr.h>
1414
#include <asm/mce.h>
1515
#include <asm/pat.h>
16+
#include <asm/asm.h>
1617
#ifdef CONFIG_X86_LOCAL_APIC
1718
#include <asm/mpspec.h>
1819
#include <asm/apic.h>
@@ -334,11 +335,40 @@ static void __init early_cpu_detect(void)
334335

335336
get_cpu_vendor(c, 1);
336337

338+
early_get_cap(c);
339+
337340
if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
338341
cpu_devs[c->x86_vendor]->c_early_init)
339342
cpu_devs[c->x86_vendor]->c_early_init(c);
343+
}
340344

341-
early_get_cap(c);
345+
/*
346+
* The NOPL instruction is supposed to exist on all CPUs with
347+
* family >= 6, unfortunately, that's not true in practice because
348+
* of early VIA chips and (more importantly) broken virtualizers that
349+
* are not easy to detect. Hence, probe for it based on first
350+
* principles.
351+
*/
352+
static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
353+
{
354+
const u32 nopl_signature = 0x888c53b1; /* Random number */
355+
u32 has_nopl = nopl_signature;
356+
357+
clear_cpu_cap(c, X86_FEATURE_NOPL);
358+
if (c->x86 >= 6) {
359+
asm volatile("\n"
360+
"1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
361+
"2:\n"
362+
" .section .fixup,\"ax\"\n"
363+
"3: xor %0,%0\n"
364+
" jmp 2b\n"
365+
" .previous\n"
366+
_ASM_EXTABLE(1b,3b)
367+
: "+a" (has_nopl));
368+
369+
if (has_nopl == nopl_signature)
370+
set_cpu_cap(c, X86_FEATURE_NOPL);
371+
}
342372
}
343373

344374
static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
@@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
395425
}
396426

397427
init_scattered_cpuid_features(c);
428+
detect_nopl(c);
398429
}
399-
400430
}
401431

402432
static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)

arch/x86/kernel/cpu/common_64.c

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <asm/mtrr.h>
1919
#include <asm/mce.h>
2020
#include <asm/pat.h>
21+
#include <asm/asm.h>
2122
#include <asm/numa.h>
2223
#ifdef CONFIG_X86_LOCAL_APIC
2324
#include <asm/mpspec.h>
@@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void)
215216
}
216217
}
217218

219+
/*
220+
* The NOPL instruction is supposed to exist on all CPUs with
221+
* family >= 6, unfortunately, that's not true in practice because
222+
* of early VIA chips and (more importantly) broken virtualizers that
223+
* are not easy to detect. Hence, probe for it based on first
224+
* principles.
225+
*
226+
* Note: no 64-bit chip is known to lack these, but put the code here
227+
* for consistency with 32 bits, and to make it utterly trivial to
228+
* diagnose the problem should it ever surface.
229+
*/
230+
static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
231+
{
232+
const u32 nopl_signature = 0x888c53b1; /* Random number */
233+
u32 has_nopl = nopl_signature;
234+
235+
clear_cpu_cap(c, X86_FEATURE_NOPL);
236+
if (c->x86 >= 6) {
237+
asm volatile("\n"
238+
"1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
239+
"2:\n"
240+
" .section .fixup,\"ax\"\n"
241+
"3: xor %0,%0\n"
242+
" jmp 2b\n"
243+
" .previous\n"
244+
_ASM_EXTABLE(1b,3b)
245+
: "+a" (has_nopl));
246+
247+
if (has_nopl == nopl_signature)
248+
set_cpu_cap(c, X86_FEATURE_NOPL);
249+
}
250+
}
251+
218252
static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
219253

220254
void __init early_cpu_init(void)
@@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
313347
c->x86_phys_bits = eax & 0xff;
314348
}
315349

350+
detect_nopl(c);
351+
316352
if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
317353
cpu_devs[c->x86_vendor]->c_early_init)
318354
cpu_devs[c->x86_vendor]->c_early_init(c);
@@ -493,17 +529,20 @@ void pda_init(int cpu)
493529
/* others are initialized in smpboot.c */
494530
pda->pcurrent = &init_task;
495531
pda->irqstackptr = boot_cpu_stack;
532+
pda->irqstackptr += IRQSTACKSIZE - 64;
496533
} else {
497-
pda->irqstackptr = (char *)
498-
__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
499-
if (!pda->irqstackptr)
500-
panic("cannot allocate irqstack for cpu %d", cpu);
534+
if (!pda->irqstackptr) {
535+
pda->irqstackptr = (char *)
536+
__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
537+
if (!pda->irqstackptr)
538+
panic("cannot allocate irqstack for cpu %d",
539+
cpu);
540+
pda->irqstackptr += IRQSTACKSIZE - 64;
541+
}
501542

502543
if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
503544
pda->nodenumber = cpu_to_node(cpu);
504545
}
505-
506-
pda->irqstackptr += IRQSTACKSIZE-64;
507546
}
508547

509548
char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
@@ -601,19 +640,22 @@ void __cpuinit cpu_init(void)
601640
/*
602641
* set up and load the per-CPU TSS
603642
*/
604-
for (v = 0; v < N_EXCEPTION_STACKS; v++) {
643+
if (!orig_ist->ist[0]) {
605644
static const unsigned int order[N_EXCEPTION_STACKS] = {
606-
[0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
607-
[DEBUG_STACK - 1] = DEBUG_STACK_ORDER
645+
[0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
646+
[DEBUG_STACK - 1] = DEBUG_STACK_ORDER
608647
};
609-
if (cpu) {
610-
estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
611-
if (!estacks)
612-
panic("Cannot allocate exception stack %ld %d\n",
613-
v, cpu);
648+
for (v = 0; v < N_EXCEPTION_STACKS; v++) {
649+
if (cpu) {
650+
estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
651+
if (!estacks)
652+
panic("Cannot allocate exception "
653+
"stack %ld %d\n", v, cpu);
654+
}
655+
estacks += PAGE_SIZE << order[v];
656+
orig_ist->ist[v] = t->x86_tss.ist[v] =
657+
(unsigned long)estacks;
614658
}
615-
estacks += PAGE_SIZE << order[v];
616-
orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks;
617659
}
618660

619661
t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);

arch/x86/kernel/cpu/cyrix.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@
1515
/*
1616
* Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
1717
*/
18-
static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
18+
static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
1919
{
2020
unsigned char ccr2, ccr3;
21-
unsigned long flags;
2221

2322
/* we test for DEVID by checking whether CCR3 is writable */
24-
local_irq_save(flags);
2523
ccr3 = getCx86(CX86_CCR3);
2624
setCx86(CX86_CCR3, ccr3 ^ 0x80);
2725
getCx86(0xc0); /* dummy to change bus */
@@ -44,9 +42,16 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
4442
*dir0 = getCx86(CX86_DIR0);
4543
*dir1 = getCx86(CX86_DIR1);
4644
}
47-
local_irq_restore(flags);
4845
}
4946

47+
static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
48+
{
49+
unsigned long flags;
50+
51+
local_irq_save(flags);
52+
__do_cyrix_devid(dir0, dir1);
53+
local_irq_restore(flags);
54+
}
5055
/*
5156
* Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
5257
* order to identify the Cyrix CPU model after we're out of setup.c
@@ -161,6 +166,24 @@ static void __cpuinit geode_configure(void)
161166
local_irq_restore(flags);
162167
}
163168

169+
static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c)
170+
{
171+
unsigned char dir0, dir0_msn, dir1 = 0;
172+
173+
__do_cyrix_devid(&dir0, &dir1);
174+
dir0_msn = dir0 >> 4; /* identifies CPU "family" */
175+
176+
switch (dir0_msn) {
177+
case 3: /* 6x86/6x86L */
178+
/* Emulate MTRRs using Cyrix's ARRs. */
179+
set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
180+
break;
181+
case 5: /* 6x86MX/M II */
182+
/* Emulate MTRRs using Cyrix's ARRs. */
183+
set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
184+
break;
185+
}
186+
}
164187

165188
static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
166189
{
@@ -416,6 +439,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c)
416439
static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
417440
.c_vendor = "Cyrix",
418441
.c_ident = { "CyrixInstead" },
442+
.c_early_init = early_init_cyrix,
419443
.c_init = init_cyrix,
420444
.c_identify = cyrix_identify,
421445
};

arch/x86/kernel/cpu/feature_names.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ const char * const x86_cap_flags[NCAPINTS*32] = {
3939
NULL, NULL, NULL, NULL,
4040
"constant_tsc", "up", NULL, "arch_perfmon",
4141
"pebs", "bts", NULL, NULL,
42-
"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
42+
"rep_good", NULL, NULL, NULL,
43+
"nopl", NULL, NULL, NULL,
4344
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
4445

4546
/* Intel-defined (#2) */

arch/x86/xen/enlighten.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
13241324
.ptep_modify_prot_commit = __ptep_modify_prot_commit,
13251325

13261326
.pte_val = xen_pte_val,
1327-
.pte_flags = native_pte_val,
1327+
.pte_flags = native_pte_flags,
13281328
.pgd_val = xen_pgd_val,
13291329

13301330
.make_pte = xen_make_pte,

include/asm-x86/cpufeature.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,15 @@
7272
#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */
7373
#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
7474
#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
75-
#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
76-
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
77-
#define X86_FEATURE_SYSCALL32 (3*32+14) /* syscall in ia32 userspace */
78-
#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */
75+
#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
76+
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
77+
#define X86_FEATURE_SYSCALL32 (3*32+14) /* syscall in ia32 userspace */
78+
#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */
7979
#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */
8080
#define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */
8181
#define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */
82-
#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */
82+
#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */
83+
#define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */
8384

8485
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
8586
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */

0 commit comments

Comments
 (0)