aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-28 08:03:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-28 08:03:12 -0400
commite34eb39c1c791fe79da6aae0d9057f0c74c2f0ed (patch)
treecfc27d987b2c888f189f35326702220b694596cc /arch
parent396e6e49c58bb23d1814d3c240c736c9f01523c5 (diff)
parent910b2c5122ab787179a790ca1dec616fc80f0173 (diff)
Merge branch 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, amd: Include linux/elf.h since we use stuff from asm/elf.h x86: cache_info: Update calculation of AMD L3 cache indices x86: cache_info: Kill the atomic allocation in amd_init_l3_cache() x86: cache_info: Kill the moronic shadow struct x86: cache_info: Remove bogus free of amd_l3_cache data x86, amd: Include elf.h explicitly, prepare the code for the module.h split x86-32, amd: Move va_align definition to unbreak 32-bit build x86, amd: Move BSP code to cpu_dev helper x86: Add a BSP cpu_dev helper x86, amd: Avoid cache aliasing penalties on AMD family 15h
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/amd_nb.h6
-rw-r--r--arch/x86/include/asm/elf.h31
-rw-r--r--arch/x86/kernel/cpu/amd.c47
-rw-r--r--arch/x86/kernel/cpu/common.c3
-rw-r--r--arch/x86/kernel/cpu/cpu.h1
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c127
-rw-r--r--arch/x86/kernel/sys_x86_64.c78
-rw-r--r--arch/x86/mm/mmap.c20
-rw-r--r--arch/x86/vdso/vma.c9
9 files changed, 206 insertions, 116 deletions
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index 67f87f257611..8e41071704a5 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -19,9 +19,15 @@ extern int amd_numa_init(void);
19extern int amd_get_subcaches(int); 19extern int amd_get_subcaches(int);
20extern int amd_set_subcaches(int, int); 20extern int amd_set_subcaches(int, int);
21 21
22struct amd_l3_cache {
23 unsigned indices;
24 u8 subcaches[4];
25};
26
22struct amd_northbridge { 27struct amd_northbridge {
23 struct pci_dev *misc; 28 struct pci_dev *misc;
24 struct pci_dev *link; 29 struct pci_dev *link;
30 struct amd_l3_cache l3_cache;
25}; 31};
26 32
27struct amd_northbridge_info { 33struct amd_northbridge_info {
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index f2ad2163109d..5f962df30d0f 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -4,6 +4,7 @@
4/* 4/*
5 * ELF register definitions.. 5 * ELF register definitions..
6 */ 6 */
7#include <linux/thread_info.h>
7 8
8#include <asm/ptrace.h> 9#include <asm/ptrace.h>
9#include <asm/user.h> 10#include <asm/user.h>
@@ -320,4 +321,34 @@ extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
320extern unsigned long arch_randomize_brk(struct mm_struct *mm); 321extern unsigned long arch_randomize_brk(struct mm_struct *mm);
321#define arch_randomize_brk arch_randomize_brk 322#define arch_randomize_brk arch_randomize_brk
322 323
324/*
325 * True on X86_32 or when emulating IA32 on X86_64
326 */
327static inline int mmap_is_ia32(void)
328{
329#ifdef CONFIG_X86_32
330 return 1;
331#endif
332#ifdef CONFIG_IA32_EMULATION
333 if (test_thread_flag(TIF_IA32))
334 return 1;
335#endif
336 return 0;
337}
338
339/* The first two values are special, do not change. See align_addr() */
340enum align_flags {
341 ALIGN_VA_32 = BIT(0),
342 ALIGN_VA_64 = BIT(1),
343 ALIGN_VDSO = BIT(2),
344 ALIGN_TOPDOWN = BIT(3),
345};
346
347struct va_alignment {
348 int flags;
349 unsigned long mask;
350} ____cacheline_aligned;
351
352extern struct va_alignment va_align;
353extern unsigned long align_addr(unsigned long, struct file *, enum align_flags);
323#endif /* _ASM_X86_ELF_H */ 354#endif /* _ASM_X86_ELF_H */
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index b13ed393dfce..13c6ec812545 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1,5 +1,6 @@
1#include <linux/init.h> 1#include <linux/init.h>
2#include <linux/bitops.h> 2#include <linux/bitops.h>
3#include <linux/elf.h>
3#include <linux/mm.h> 4#include <linux/mm.h>
4 5
5#include <linux/io.h> 6#include <linux/io.h>
@@ -410,6 +411,34 @@ static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
410#endif 411#endif
411} 412}
412 413
414static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c)
415{
416 if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
417
418 if (c->x86 > 0x10 ||
419 (c->x86 == 0x10 && c->x86_model >= 0x2)) {
420 u64 val;
421
422 rdmsrl(MSR_K7_HWCR, val);
423 if (!(val & BIT(24)))
424 printk(KERN_WARNING FW_BUG "TSC doesn't count "
425 "with P0 frequency!\n");
426 }
427 }
428
429 if (c->x86 == 0x15) {
430 unsigned long upperbit;
431 u32 cpuid, assoc;
432
433 cpuid = cpuid_edx(0x80000005);
434 assoc = cpuid >> 16 & 0xff;
435 upperbit = ((cpuid >> 24) << 10) / assoc;
436
437 va_align.mask = (upperbit - 1) & PAGE_MASK;
438 va_align.flags = ALIGN_VA_32 | ALIGN_VA_64;
439 }
440}
441
413static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) 442static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
414{ 443{
415 early_init_amd_mc(c); 444 early_init_amd_mc(c);
@@ -441,23 +470,6 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
441 set_cpu_cap(c, X86_FEATURE_EXTD_APICID); 470 set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
442 } 471 }
443#endif 472#endif
444
445 /* We need to do the following only once */
446 if (c != &boot_cpu_data)
447 return;
448
449 if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
450
451 if (c->x86 > 0x10 ||
452 (c->x86 == 0x10 && c->x86_model >= 0x2)) {
453 u64 val;
454
455 rdmsrl(MSR_K7_HWCR, val);
456 if (!(val & BIT(24)))
457 printk(KERN_WARNING FW_BUG "TSC doesn't count "
458 "with P0 frequency!\n");
459 }
460 }
461} 473}
462 474
463static void __cpuinit init_amd(struct cpuinfo_x86 *c) 475static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -679,6 +691,7 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = {
679 .c_size_cache = amd_size_cache, 691 .c_size_cache = amd_size_cache,
680#endif 692#endif
681 .c_early_init = early_init_amd, 693 .c_early_init = early_init_amd,
694 .c_bsp_init = bsp_init_amd,
682 .c_init = init_amd, 695 .c_init = init_amd,
683 .c_x86_vendor = X86_VENDOR_AMD, 696 .c_x86_vendor = X86_VENDOR_AMD,
684}; 697};
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 62184390a601..ec63df54d138 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -681,6 +681,9 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
681 filter_cpuid_features(c, false); 681 filter_cpuid_features(c, false);
682 682
683 setup_smep(c); 683 setup_smep(c);
684
685 if (this_cpu->c_bsp_init)
686 this_cpu->c_bsp_init(c);
684} 687}
685 688
686void __init early_cpu_init(void) 689void __init early_cpu_init(void)
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index e765633f210e..1b22dcc51af4 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -18,6 +18,7 @@ struct cpu_dev {
18 struct cpu_model_info c_models[4]; 18 struct cpu_model_info c_models[4];
19 19
20 void (*c_early_init)(struct cpuinfo_x86 *); 20 void (*c_early_init)(struct cpuinfo_x86 *);
21 void (*c_bsp_init)(struct cpuinfo_x86 *);
21 void (*c_init)(struct cpuinfo_x86 *); 22 void (*c_init)(struct cpuinfo_x86 *);
22 void (*c_identify)(struct cpuinfo_x86 *); 23 void (*c_identify)(struct cpuinfo_x86 *);
23 unsigned int (*c_size_cache)(struct cpuinfo_x86 *, unsigned int); 24 unsigned int (*c_size_cache)(struct cpuinfo_x86 *, unsigned int);
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index c105c533ed94..a3b0811693c9 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -151,28 +151,17 @@ union _cpuid4_leaf_ecx {
151 u32 full; 151 u32 full;
152}; 152};
153 153
154struct amd_l3_cache { 154struct _cpuid4_info_regs {
155 struct amd_northbridge *nb;
156 unsigned indices;
157 u8 subcaches[4];
158};
159
160struct _cpuid4_info {
161 union _cpuid4_leaf_eax eax; 155 union _cpuid4_leaf_eax eax;
162 union _cpuid4_leaf_ebx ebx; 156 union _cpuid4_leaf_ebx ebx;
163 union _cpuid4_leaf_ecx ecx; 157 union _cpuid4_leaf_ecx ecx;
164 unsigned long size; 158 unsigned long size;
165 struct amd_l3_cache *l3; 159 struct amd_northbridge *nb;
166 DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
167}; 160};
168 161
169/* subset of above _cpuid4_info w/o shared_cpu_map */ 162struct _cpuid4_info {
170struct _cpuid4_info_regs { 163 struct _cpuid4_info_regs base;
171 union _cpuid4_leaf_eax eax; 164 DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
172 union _cpuid4_leaf_ebx ebx;
173 union _cpuid4_leaf_ecx ecx;
174 unsigned long size;
175 struct amd_l3_cache *l3;
176}; 165};
177 166
178unsigned short num_cache_leaves; 167unsigned short num_cache_leaves;
@@ -314,16 +303,23 @@ struct _cache_attr {
314/* 303/*
315 * L3 cache descriptors 304 * L3 cache descriptors
316 */ 305 */
317static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) 306static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb)
318{ 307{
308 struct amd_l3_cache *l3 = &nb->l3_cache;
319 unsigned int sc0, sc1, sc2, sc3; 309 unsigned int sc0, sc1, sc2, sc3;
320 u32 val = 0; 310 u32 val = 0;
321 311
322 pci_read_config_dword(l3->nb->misc, 0x1C4, &val); 312 pci_read_config_dword(nb->misc, 0x1C4, &val);
323 313
324 /* calculate subcache sizes */ 314 /* calculate subcache sizes */
325 l3->subcaches[0] = sc0 = !(val & BIT(0)); 315 l3->subcaches[0] = sc0 = !(val & BIT(0));
326 l3->subcaches[1] = sc1 = !(val & BIT(4)); 316 l3->subcaches[1] = sc1 = !(val & BIT(4));
317
318 if (boot_cpu_data.x86 == 0x15) {
319 l3->subcaches[0] = sc0 += !(val & BIT(1));
320 l3->subcaches[1] = sc1 += !(val & BIT(5));
321 }
322
327 l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9)); 323 l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9));
328 l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13)); 324 l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
329 325
@@ -333,33 +329,16 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
333static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, 329static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
334 int index) 330 int index)
335{ 331{
336 static struct amd_l3_cache *__cpuinitdata l3_caches;
337 int node; 332 int node;
338 333
339 /* only for L3, and not in virtualized environments */ 334 /* only for L3, and not in virtualized environments */
340 if (index < 3 || amd_nb_num() == 0) 335 if (index < 3)
341 return; 336 return;
342 337
343 /*
344 * Strictly speaking, the amount in @size below is leaked since it is
345 * never freed but this is done only on shutdown so it doesn't matter.
346 */
347 if (!l3_caches) {
348 int size = amd_nb_num() * sizeof(struct amd_l3_cache);
349
350 l3_caches = kzalloc(size, GFP_ATOMIC);
351 if (!l3_caches)
352 return;
353 }
354
355 node = amd_get_nb_id(smp_processor_id()); 338 node = amd_get_nb_id(smp_processor_id());
356 339 this_leaf->nb = node_to_amd_nb(node);
357 if (!l3_caches[node].nb) { 340 if (this_leaf->nb && !this_leaf->nb->l3_cache.indices)
358 l3_caches[node].nb = node_to_amd_nb(node); 341 amd_calc_l3_indices(this_leaf->nb);
359 amd_calc_l3_indices(&l3_caches[node]);
360 }
361
362 this_leaf->l3 = &l3_caches[node];
363} 342}
364 343
365/* 344/*
@@ -369,11 +348,11 @@ static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
369 * 348 *
370 * @returns: the disabled index if used or negative value if slot free. 349 * @returns: the disabled index if used or negative value if slot free.
371 */ 350 */
372int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot) 351int amd_get_l3_disable_slot(struct amd_northbridge *nb, unsigned slot)
373{ 352{
374 unsigned int reg = 0; 353 unsigned int reg = 0;
375 354
376 pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, &reg); 355 pci_read_config_dword(nb->misc, 0x1BC + slot * 4, &reg);
377 356
378 /* check whether this slot is activated already */ 357 /* check whether this slot is activated already */
379 if (reg & (3UL << 30)) 358 if (reg & (3UL << 30))
@@ -387,11 +366,10 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
387{ 366{
388 int index; 367 int index;
389 368
390 if (!this_leaf->l3 || 369 if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
391 !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
392 return -EINVAL; 370 return -EINVAL;
393 371
394 index = amd_get_l3_disable_slot(this_leaf->l3, slot); 372 index = amd_get_l3_disable_slot(this_leaf->base.nb, slot);
395 if (index >= 0) 373 if (index >= 0)
396 return sprintf(buf, "%d\n", index); 374 return sprintf(buf, "%d\n", index);
397 375
@@ -408,7 +386,7 @@ show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf, \
408SHOW_CACHE_DISABLE(0) 386SHOW_CACHE_DISABLE(0)
409SHOW_CACHE_DISABLE(1) 387SHOW_CACHE_DISABLE(1)
410 388
411static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, 389static void amd_l3_disable_index(struct amd_northbridge *nb, int cpu,
412 unsigned slot, unsigned long idx) 390 unsigned slot, unsigned long idx)
413{ 391{
414 int i; 392 int i;
@@ -421,10 +399,10 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
421 for (i = 0; i < 4; i++) { 399 for (i = 0; i < 4; i++) {
422 u32 reg = idx | (i << 20); 400 u32 reg = idx | (i << 20);
423 401
424 if (!l3->subcaches[i]) 402 if (!nb->l3_cache.subcaches[i])
425 continue; 403 continue;
426 404
427 pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); 405 pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
428 406
429 /* 407 /*
430 * We need to WBINVD on a core on the node containing the L3 408 * We need to WBINVD on a core on the node containing the L3
@@ -434,7 +412,7 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
434 wbinvd_on_cpu(cpu); 412 wbinvd_on_cpu(cpu);
435 413
436 reg |= BIT(31); 414 reg |= BIT(31);
437 pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); 415 pci_write_config_dword(nb->misc, 0x1BC + slot * 4, reg);
438 } 416 }
439} 417}
440 418
@@ -448,24 +426,24 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
448 * 426 *
449 * @return: 0 on success, error status on failure 427 * @return: 0 on success, error status on failure
450 */ 428 */
451int amd_set_l3_disable_slot(struct amd_l3_cache *l3, int cpu, unsigned slot, 429int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot,
452 unsigned long index) 430 unsigned long index)
453{ 431{
454 int ret = 0; 432 int ret = 0;
455 433
456 /* check if @slot is already used or the index is already disabled */ 434 /* check if @slot is already used or the index is already disabled */
457 ret = amd_get_l3_disable_slot(l3, slot); 435 ret = amd_get_l3_disable_slot(nb, slot);
458 if (ret >= 0) 436 if (ret >= 0)
459 return -EINVAL; 437 return -EINVAL;
460 438
461 if (index > l3->indices) 439 if (index > nb->l3_cache.indices)
462 return -EINVAL; 440 return -EINVAL;
463 441
464 /* check whether the other slot has disabled the same index already */ 442 /* check whether the other slot has disabled the same index already */
465 if (index == amd_get_l3_disable_slot(l3, !slot)) 443 if (index == amd_get_l3_disable_slot(nb, !slot))
466 return -EINVAL; 444 return -EINVAL;
467 445
468 amd_l3_disable_index(l3, cpu, slot, index); 446 amd_l3_disable_index(nb, cpu, slot, index);
469 447
470 return 0; 448 return 0;
471} 449}
@@ -480,8 +458,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
480 if (!capable(CAP_SYS_ADMIN)) 458 if (!capable(CAP_SYS_ADMIN))
481 return -EPERM; 459 return -EPERM;
482 460
483 if (!this_leaf->l3 || 461 if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
484 !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
485 return -EINVAL; 462 return -EINVAL;
486 463
487 cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); 464 cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
@@ -489,7 +466,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
489 if (strict_strtoul(buf, 10, &val) < 0) 466 if (strict_strtoul(buf, 10, &val) < 0)
490 return -EINVAL; 467 return -EINVAL;
491 468
492 err = amd_set_l3_disable_slot(this_leaf->l3, cpu, slot, val); 469 err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
493 if (err) { 470 if (err) {
494 if (err == -EEXIST) 471 if (err == -EEXIST)
495 printk(KERN_WARNING "L3 disable slot %d in use!\n", 472 printk(KERN_WARNING "L3 disable slot %d in use!\n",
@@ -518,7 +495,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
518static ssize_t 495static ssize_t
519show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu) 496show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu)
520{ 497{
521 if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) 498 if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
522 return -EINVAL; 499 return -EINVAL;
523 500
524 return sprintf(buf, "%x\n", amd_get_subcaches(cpu)); 501 return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
@@ -533,7 +510,7 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
533 if (!capable(CAP_SYS_ADMIN)) 510 if (!capable(CAP_SYS_ADMIN))
534 return -EPERM; 511 return -EPERM;
535 512
536 if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) 513 if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
537 return -EINVAL; 514 return -EINVAL;
538 515
539 if (strict_strtoul(buf, 16, &val) < 0) 516 if (strict_strtoul(buf, 16, &val) < 0)
@@ -769,7 +746,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
769 return; 746 return;
770 } 747 }
771 this_leaf = CPUID4_INFO_IDX(cpu, index); 748 this_leaf = CPUID4_INFO_IDX(cpu, index);
772 num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; 749 num_threads_sharing = 1 + this_leaf->base.eax.split.num_threads_sharing;
773 750
774 if (num_threads_sharing == 1) 751 if (num_threads_sharing == 1)
775 cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map)); 752 cpumask_set_cpu(cpu, to_cpumask(this_leaf->shared_cpu_map));
@@ -820,29 +797,19 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
820 for (i = 0; i < num_cache_leaves; i++) 797 for (i = 0; i < num_cache_leaves; i++)
821 cache_remove_shared_cpu_map(cpu, i); 798 cache_remove_shared_cpu_map(cpu, i);
822 799
823 kfree(per_cpu(ici_cpuid4_info, cpu)->l3);
824 kfree(per_cpu(ici_cpuid4_info, cpu)); 800 kfree(per_cpu(ici_cpuid4_info, cpu));
825 per_cpu(ici_cpuid4_info, cpu) = NULL; 801 per_cpu(ici_cpuid4_info, cpu) = NULL;
826} 802}
827 803
828static int
829__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
830{
831 struct _cpuid4_info_regs *leaf_regs =
832 (struct _cpuid4_info_regs *)this_leaf;
833
834 return cpuid4_cache_lookup_regs(index, leaf_regs);
835}
836
837static void __cpuinit get_cpu_leaves(void *_retval) 804static void __cpuinit get_cpu_leaves(void *_retval)
838{ 805{
839 int j, *retval = _retval, cpu = smp_processor_id(); 806 int j, *retval = _retval, cpu = smp_processor_id();
840 807
841 /* Do cpuid and store the results */ 808 /* Do cpuid and store the results */
842 for (j = 0; j < num_cache_leaves; j++) { 809 for (j = 0; j < num_cache_leaves; j++) {
843 struct _cpuid4_info *this_leaf; 810 struct _cpuid4_info *this_leaf = CPUID4_INFO_IDX(cpu, j);
844 this_leaf = CPUID4_INFO_IDX(cpu, j); 811
845 *retval = cpuid4_cache_lookup(j, this_leaf); 812 *retval = cpuid4_cache_lookup_regs(j, &this_leaf->base);
846 if (unlikely(*retval < 0)) { 813 if (unlikely(*retval < 0)) {
847 int i; 814 int i;
848 815
@@ -900,16 +867,16 @@ static ssize_t show_##file_name(struct _cpuid4_info *this_leaf, char *buf, \
900 return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \ 867 return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
901} 868}
902 869
903show_one_plus(level, eax.split.level, 0); 870show_one_plus(level, base.eax.split.level, 0);
904show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1); 871show_one_plus(coherency_line_size, base.ebx.split.coherency_line_size, 1);
905show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1); 872show_one_plus(physical_line_partition, base.ebx.split.physical_line_partition, 1);
906show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1); 873show_one_plus(ways_of_associativity, base.ebx.split.ways_of_associativity, 1);
907show_one_plus(number_of_sets, ecx.split.number_of_sets, 1); 874show_one_plus(number_of_sets, base.ecx.split.number_of_sets, 1);
908 875
909static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf, 876static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf,
910 unsigned int cpu) 877 unsigned int cpu)
911{ 878{
912 return sprintf(buf, "%luK\n", this_leaf->size / 1024); 879 return sprintf(buf, "%luK\n", this_leaf->base.size / 1024);
913} 880}
914 881
915static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf, 882static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
@@ -946,7 +913,7 @@ static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf,
946static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf, 913static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf,
947 unsigned int cpu) 914 unsigned int cpu)
948{ 915{
949 switch (this_leaf->eax.split.type) { 916 switch (this_leaf->base.eax.split.type) {
950 case CACHE_TYPE_DATA: 917 case CACHE_TYPE_DATA:
951 return sprintf(buf, "Data\n"); 918 return sprintf(buf, "Data\n");
952 case CACHE_TYPE_INST: 919 case CACHE_TYPE_INST:
@@ -1135,7 +1102,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
1135 1102
1136 ktype_cache.default_attrs = default_attrs; 1103 ktype_cache.default_attrs = default_attrs;
1137#ifdef CONFIG_AMD_NB 1104#ifdef CONFIG_AMD_NB
1138 if (this_leaf->l3) 1105 if (this_leaf->base.nb)
1139 ktype_cache.default_attrs = amd_l3_attrs(); 1106 ktype_cache.default_attrs = amd_l3_attrs();
1140#endif 1107#endif
1141 retval = kobject_init_and_add(&(this_object->kobj), 1108 retval = kobject_init_and_add(&(this_object->kobj),
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index ff14a5044ce6..051489082d59 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -14,10 +14,73 @@
14#include <linux/personality.h> 14#include <linux/personality.h>
15#include <linux/random.h> 15#include <linux/random.h>
16#include <linux/uaccess.h> 16#include <linux/uaccess.h>
17#include <linux/elf.h>
17 18
18#include <asm/ia32.h> 19#include <asm/ia32.h>
19#include <asm/syscalls.h> 20#include <asm/syscalls.h>
20 21
22/*
23 * Align a virtual address to avoid aliasing in the I$ on AMD F15h.
24 *
25 * @flags denotes the allocation direction - bottomup or topdown -
26 * or vDSO; see call sites below.
27 */
28unsigned long align_addr(unsigned long addr, struct file *filp,
29 enum align_flags flags)
30{
31 unsigned long tmp_addr;
32
33 /* handle 32- and 64-bit case with a single conditional */
34 if (va_align.flags < 0 || !(va_align.flags & (2 - mmap_is_ia32())))
35 return addr;
36
37 if (!(current->flags & PF_RANDOMIZE))
38 return addr;
39
40 if (!((flags & ALIGN_VDSO) || filp))
41 return addr;
42
43 tmp_addr = addr;
44
45 /*
46 * We need an address which is <= than the original
47 * one only when in topdown direction.
48 */
49 if (!(flags & ALIGN_TOPDOWN))
50 tmp_addr += va_align.mask;
51
52 tmp_addr &= ~va_align.mask;
53
54 return tmp_addr;
55}
56
57static int __init control_va_addr_alignment(char *str)
58{
59 /* guard against enabling this on other CPU families */
60 if (va_align.flags < 0)
61 return 1;
62
63 if (*str == 0)
64 return 1;
65
66 if (*str == '=')
67 str++;
68
69 if (!strcmp(str, "32"))
70 va_align.flags = ALIGN_VA_32;
71 else if (!strcmp(str, "64"))
72 va_align.flags = ALIGN_VA_64;
73 else if (!strcmp(str, "off"))
74 va_align.flags = 0;
75 else if (!strcmp(str, "on"))
76 va_align.flags = ALIGN_VA_32 | ALIGN_VA_64;
77 else
78 return 0;
79
80 return 1;
81}
82__setup("align_va_addr", control_va_addr_alignment);
83
21SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, 84SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
22 unsigned long, prot, unsigned long, flags, 85 unsigned long, prot, unsigned long, flags,
23 unsigned long, fd, unsigned long, off) 86 unsigned long, fd, unsigned long, off)
@@ -92,6 +155,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
92 start_addr = addr; 155 start_addr = addr;
93 156
94full_search: 157full_search:
158
159 addr = align_addr(addr, filp, 0);
160
95 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { 161 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
96 /* At this point: (!vma || addr < vma->vm_end). */ 162 /* At this point: (!vma || addr < vma->vm_end). */
97 if (end - len < addr) { 163 if (end - len < addr) {
@@ -117,6 +183,7 @@ full_search:
117 mm->cached_hole_size = vma->vm_start - addr; 183 mm->cached_hole_size = vma->vm_start - addr;
118 184
119 addr = vma->vm_end; 185 addr = vma->vm_end;
186 addr = align_addr(addr, filp, 0);
120 } 187 }
121} 188}
122 189
@@ -161,10 +228,13 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
161 228
162 /* make sure it can fit in the remaining address space */ 229 /* make sure it can fit in the remaining address space */
163 if (addr > len) { 230 if (addr > len) {
164 vma = find_vma(mm, addr-len); 231 unsigned long tmp_addr = align_addr(addr - len, filp,
165 if (!vma || addr <= vma->vm_start) 232 ALIGN_TOPDOWN);
233
234 vma = find_vma(mm, tmp_addr);
235 if (!vma || tmp_addr + len <= vma->vm_start)
166 /* remember the address as a hint for next time */ 236 /* remember the address as a hint for next time */
167 return mm->free_area_cache = addr-len; 237 return mm->free_area_cache = tmp_addr;
168 } 238 }
169 239
170 if (mm->mmap_base < len) 240 if (mm->mmap_base < len)
@@ -173,6 +243,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
173 addr = mm->mmap_base-len; 243 addr = mm->mmap_base-len;
174 244
175 do { 245 do {
246 addr = align_addr(addr, filp, ALIGN_TOPDOWN);
247
176 /* 248 /*
177 * Lookup failure means no vma is above this address, 249 * Lookup failure means no vma is above this address,
178 * else if new region fits below vma->vm_start, 250 * else if new region fits below vma->vm_start,
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 1dab5194fd9d..4b5ba85eb5c9 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -31,6 +31,10 @@
31#include <linux/sched.h> 31#include <linux/sched.h>
32#include <asm/elf.h> 32#include <asm/elf.h>
33 33
34struct __read_mostly va_alignment va_align = {
35 .flags = -1,
36};
37
34static unsigned int stack_maxrandom_size(void) 38static unsigned int stack_maxrandom_size(void)
35{ 39{
36 unsigned int max = 0; 40 unsigned int max = 0;
@@ -42,7 +46,6 @@ static unsigned int stack_maxrandom_size(void)
42 return max; 46 return max;
43} 47}
44 48
45
46/* 49/*
47 * Top of mmap area (just below the process stack). 50 * Top of mmap area (just below the process stack).
48 * 51 *
@@ -51,21 +54,6 @@ static unsigned int stack_maxrandom_size(void)
51#define MIN_GAP (128*1024*1024UL + stack_maxrandom_size()) 54#define MIN_GAP (128*1024*1024UL + stack_maxrandom_size())
52#define MAX_GAP (TASK_SIZE/6*5) 55#define MAX_GAP (TASK_SIZE/6*5)
53 56
54/*
55 * True on X86_32 or when emulating IA32 on X86_64
56 */
57static int mmap_is_ia32(void)
58{
59#ifdef CONFIG_X86_32
60 return 1;
61#endif
62#ifdef CONFIG_IA32_EMULATION
63 if (test_thread_flag(TIF_IA32))
64 return 1;
65#endif
66 return 0;
67}
68
69static int mmap_is_legacy(void) 57static int mmap_is_legacy(void)
70{ 58{
71 if (current->personality & ADDR_COMPAT_LAYOUT) 59 if (current->personality & ADDR_COMPAT_LAYOUT)
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 316fbca3490e..153407c35b75 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -89,6 +89,15 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
89 addr = start + (offset << PAGE_SHIFT); 89 addr = start + (offset << PAGE_SHIFT);
90 if (addr >= end) 90 if (addr >= end)
91 addr = end; 91 addr = end;
92
93 /*
94 * page-align it here so that get_unmapped_area doesn't
95 * align it wrongfully again to the next page. addr can come in 4K
96 * unaligned here as a result of stack start randomization.
97 */
98 addr = PAGE_ALIGN(addr);
99 addr = align_addr(addr, NULL, ALIGN_VDSO);
100
92 return addr; 101 return addr;
93} 102}
94 103