Skip to content

Commit 505569d

Browse files
committed
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar: "Misc fixes: two vdso fixes, two kbuild fixes and a boot failure fix with certain odd memory mappings" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, vdso: Use asm volatile in __getcpu x86/build: Clean auto-generated processor feature files x86: Fix mkcapflags.sh bash-ism x86: Fix step size adjustment during initial memory mapping x86_64, vdso: Fix the vdso address randomization algorithm
2 parents 5ab551d + 2aba73a commit 505569d

File tree

6 files changed

+53
-39
lines changed

6 files changed

+53
-39
lines changed

arch/x86/boot/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ targets += cpustr.h
5151
$(obj)/cpustr.h: $(obj)/mkcpustr FORCE
5252
$(call if_changed,cpustr)
5353
endif
54+
clean-files += cpustr.h
5455

5556
# ---------------------------------------------------------------------------
5657

arch/x86/include/asm/vgtod.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,11 @@ static inline unsigned int __getcpu(void)
8080

8181
/*
8282
* Load per CPU data from GDT. LSL is faster than RDTSCP and
83-
* works on all CPUs.
83+
* works on all CPUs. This is volatile so that it orders
84+
* correctly wrt barrier() and to keep gcc from cleverly
85+
* hoisting it out of the calling function.
8486
*/
85-
asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
87+
asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
8688

8789
return p;
8890
}

arch/x86/kernel/cpu/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,4 @@ targets += capflags.c
6666
$(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE
6767
$(call if_changed,mkcapflags)
6868
endif
69+
clean-files += capflags.c

arch/x86/kernel/cpu/mkcapflags.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function dump_array()
2828
# If the /* comment */ starts with a quote string, grab that.
2929
VALUE="$(echo "$i" | sed -n 's@.*/\* *\("[^"]*"\).*\*/@\1@p')"
3030
[ -z "$VALUE" ] && VALUE="\"$NAME\""
31-
[ "$VALUE" == '""' ] && continue
31+
[ "$VALUE" = '""' ] && continue
3232

3333
# Name is uppercase, VALUE is all lowercase
3434
VALUE="$(echo "$VALUE" | tr A-Z a-z)"

arch/x86/mm/init.c

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -438,20 +438,20 @@ static unsigned long __init init_range_memory_mapping(
438438
static unsigned long __init get_new_step_size(unsigned long step_size)
439439
{
440440
/*
441-
* Explain why we shift by 5 and why we don't have to worry about
442-
* 'step_size << 5' overflowing:
443-
*
444-
* initial mapped size is PMD_SIZE (2M).
441+
* Initial mapped size is PMD_SIZE (2M).
445442
* We can not set step_size to be PUD_SIZE (1G) yet.
446443
* In worse case, when we cross the 1G boundary, and
447444
* PG_LEVEL_2M is not set, we will need 1+1+512 pages (2M + 8k)
448-
* to map 1G range with PTE. Use 5 as shift for now.
445+
* to map 1G range with PTE. Hence we use one less than the
446+
* difference of page table level shifts.
449447
*
450-
* Don't need to worry about overflow, on 32bit, when step_size
451-
* is 0, round_down() returns 0 for start, and that turns it
452-
* into 0x100000000ULL.
448+
* Don't need to worry about overflow in the top-down case, on 32bit,
449+
* when step_size is 0, round_down() returns 0 for start, and that
450+
* turns it into 0x100000000ULL.
451+
* In the bottom-up case, round_up(x, 0) returns 0 though too, which
452+
* needs to be taken into consideration by the code below.
453453
*/
454-
return step_size << 5;
454+
return step_size << (PMD_SHIFT - PAGE_SHIFT - 1);
455455
}
456456

457457
/**
@@ -471,7 +471,6 @@ static void __init memory_map_top_down(unsigned long map_start,
471471
unsigned long step_size;
472472
unsigned long addr;
473473
unsigned long mapped_ram_size = 0;
474-
unsigned long new_mapped_ram_size;
475474

476475
/* xen has big range in reserved near end of ram, skip it at first.*/
477476
addr = memblock_find_in_range(map_start, map_end, PMD_SIZE, PMD_SIZE);
@@ -496,14 +495,12 @@ static void __init memory_map_top_down(unsigned long map_start,
496495
start = map_start;
497496
} else
498497
start = map_start;
499-
new_mapped_ram_size = init_range_memory_mapping(start,
498+
mapped_ram_size += init_range_memory_mapping(start,
500499
last_start);
501500
last_start = start;
502501
min_pfn_mapped = last_start >> PAGE_SHIFT;
503-
/* only increase step_size after big range get mapped */
504-
if (new_mapped_ram_size > mapped_ram_size)
502+
if (mapped_ram_size >= step_size)
505503
step_size = get_new_step_size(step_size);
506-
mapped_ram_size += new_mapped_ram_size;
507504
}
508505

509506
if (real_end < map_end)
@@ -524,7 +521,7 @@ static void __init memory_map_top_down(unsigned long map_start,
524521
static void __init memory_map_bottom_up(unsigned long map_start,
525522
unsigned long map_end)
526523
{
527-
unsigned long next, new_mapped_ram_size, start;
524+
unsigned long next, start;
528525
unsigned long mapped_ram_size = 0;
529526
/* step_size need to be small so pgt_buf from BRK could cover it */
530527
unsigned long step_size = PMD_SIZE;
@@ -539,19 +536,19 @@ static void __init memory_map_bottom_up(unsigned long map_start,
539536
* for page table.
540537
*/
541538
while (start < map_end) {
542-
if (map_end - start > step_size) {
539+
if (step_size && map_end - start > step_size) {
543540
next = round_up(start + 1, step_size);
544541
if (next > map_end)
545542
next = map_end;
546-
} else
543+
} else {
547544
next = map_end;
545+
}
548546

549-
new_mapped_ram_size = init_range_memory_mapping(start, next);
547+
mapped_ram_size += init_range_memory_mapping(start, next);
550548
start = next;
551549

552-
if (new_mapped_ram_size > mapped_ram_size)
550+
if (mapped_ram_size >= step_size)
553551
step_size = get_new_step_size(step_size);
554-
mapped_ram_size += new_mapped_ram_size;
555552
}
556553
}
557554

arch/x86/vdso/vma.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,35 +41,48 @@ void __init init_vdso_image(const struct vdso_image *image)
4141

4242
struct linux_binprm;
4343

44-
/* Put the vdso above the (randomized) stack with another randomized offset.
45-
This way there is no hole in the middle of address space.
46-
To save memory make sure it is still in the same PTE as the stack top.
47-
This doesn't give that many random bits.
48-
49-
Only used for the 64-bit and x32 vdsos. */
44+
/*
45+
* Put the vdso above the (randomized) stack with another randomized
46+
* offset. This way there is no hole in the middle of address space.
47+
* To save memory make sure it is still in the same PTE as the stack
48+
* top. This doesn't give that many random bits.
49+
*
50+
* Note that this algorithm is imperfect: the distribution of the vdso
51+
* start address within a PMD is biased toward the end.
52+
*
53+
* Only used for the 64-bit and x32 vdsos.
54+
*/
5055
static unsigned long vdso_addr(unsigned long start, unsigned len)
5156
{
5257
#ifdef CONFIG_X86_32
5358
return 0;
5459
#else
5560
unsigned long addr, end;
5661
unsigned offset;
57-
end = (start + PMD_SIZE - 1) & PMD_MASK;
62+
63+
/*
64+
* Round up the start address. It can start out unaligned as a result
65+
* of stack start randomization.
66+
*/
67+
start = PAGE_ALIGN(start);
68+
69+
/* Round the lowest possible end address up to a PMD boundary. */
70+
end = (start + len + PMD_SIZE - 1) & PMD_MASK;
5871
if (end >= TASK_SIZE_MAX)
5972
end = TASK_SIZE_MAX;
6073
end -= len;
61-
/* This loses some more bits than a modulo, but is cheaper */
62-
offset = get_random_int() & (PTRS_PER_PTE - 1);
63-
addr = start + (offset << PAGE_SHIFT);
64-
if (addr >= end)
65-
addr = end;
74+
75+
if (end > start) {
76+
offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
77+
addr = start + (offset << PAGE_SHIFT);
78+
} else {
79+
addr = start;
80+
}
6681

6782
/*
68-
* page-align it here so that get_unmapped_area doesn't
69-
* align it wrongfully again to the next page. addr can come in 4K
70-
* unaligned here as a result of stack start randomization.
83+
* Forcibly align the final address in case we have a hardware
84+
* issue that requires alignment for performance reasons.
7185
*/
72-
addr = PAGE_ALIGN(addr);
7386
addr = align_vdso_addr(addr);
7487

7588
return addr;

0 commit comments

Comments
 (0)