x86: Fix step size adjustment during initial memory mapping
authorJan Beulich <JBeulich@suse.com>
Fri, 19 Dec 2014 16:10:54 +0000 (16:10 +0000)
committerIngo Molnar <mingo@kernel.org>
Tue, 23 Dec 2014 10:39:34 +0000 (11:39 +0100)
commit132978b94e66f8ad7d20790f8332f0e9c1426029
treee928ea7e3fe2abc0d129e4cb42de9c1b3c90ce89
parentfbe1bf140671619508dfa575d74a185ae53c5dbb
x86: Fix step size adjustment during initial memory mapping

The old scheme can lead to failure in certain cases - the
problem is that after bumping step_size the next (non-final)
iteration is only guaranteed to make available a memory block
the size of what step_size was before. E.g. for a memory block
[0,3004600000) we'd have:

 iter start end step amount
 1 3004400000 30045fffff  2M   2M
 2 3004000000 30043fffff 64M   4M
 3 3000000000 3003ffffff  2G  64M
 4 2000000000 2fffffffff 64G  64G

Yet to map 64G with 4k pages (as happens e.g. under PV Xen) we
need slightly over 128M, but the first three iterations made
only about 70M available.

The condition (new_mapped_ram_size > mapped_ram_size) for
bumping step_size is just not suitable. Instead we want to bump
it when we know we have enough memory available to cover a block
of the new step_size. And rather than making that condition more
complicated than needed, simply adjust step_size by the largest
possible factor we know we can cover at that point - which is
shifting it left by one less than the difference between page
table level shifts. (Interestingly the original STEP_SIZE_SHIFT
definition had a comment hinting at that having been the
intention, just that it should have been PUD_SHIFT-PMD_SHIFT-1
instead of (PUD_SHIFT-PMD_SHIFT)/2, and of course for non-PAE
32-bit we can't really use these two constants as they're equal
there.)

Furthermore the comment in get_new_step_size() didn't get
updated when the bottom-down mapping logic got added. Yet while
an overflow (flushing step_size to zero) of the shift doesn't
matter for the top-down method, it does for bottom-up because
round_up(x, 0) = 0, and an upper range boundary of zero can't
really work well.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/54945C1E020000780005114E@mail.emea.novell.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/mm/init.c