[PATCH] x86/ebda: If the EBDA is in lowmem, reserve only 4k for the EBDA

From: Andy Lutomirski
Date: Wed Jul 20 2016 - 21:33:17 EST

Under some conditions, my Dell XPS 13 9350 puts the EBDA at 0x2c000
but reports the lowmem cutoff as 0. The old code reserves
everything above 0x2c000 and I can't boot [1].

Due to an old quirk, we assume that lowmem ends at 0x9f000. Nonetheless,
the old code would reserve everything from 0x2c000 to 0xfffff.

Be a little less conservative: when the EBDA is in lowmem, reserve
4k the EBDA and reserve highmem separately. On my laptop, this ends
up being more or less a no-op: the EBDA shows up as a single-page of
runtime data in the EFI memmap. Go Dell for getting this right.

[1] This only breaks boot in practice when some other firmware or
GRUB oddity that I don't fully understand kicks in causing the
memory below 0x2c000 to be unusable.

Signed-off-by: Andy Lutomirski <luto@xxxxxxxxxx>

This is intentionally not tagged for -stable. I think it's -stable
material *eventually*, but the problem that's fixed is not widespread
(it's apparently just me for now) and there's plenty of potential to
regress something that was worked around by the old code.

arch/x86/kernel/ebda.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/ebda.c b/arch/x86/kernel/ebda.c
index afe65dffee80..2183a7eac646 100644
--- a/arch/x86/kernel/ebda.c
+++ b/arch/x86/kernel/ebda.c
@@ -62,10 +62,12 @@ void __init reserve_ebda_region(void)
if (lowmem < INSANE_CUTOFF)
lowmem = LOWMEM_CAP;

- /* Use the lower of the lowmem and EBDA markers as the cutoff */
- lowmem = min(lowmem, ebda_addr);
lowmem = min(lowmem, LOWMEM_CAP); /* Absolute cap */

/* reserve all memory between lowmem and the 1MB mark */
memblock_reserve(lowmem, 0x100000 - lowmem);
+ /* if the EBDA is in lowmem, reserve it separately. */
+ if (ebda_addr < lowmem)
+ memblock_reserve(ebda_addr, 4096);