On 20/12/17 01:22, Thomas Gleixner wrote:
> On Tue, 19 Dec 2017, Thomas Gleixner wrote:
>> On Tue, 19 Dec 2017, Ingo Molnar wrote:
>> We don't run out of space, but the 0-day robot triggered a nasty issue.
>>
>> The fixmap bottom address, which contains the early_ioremap fixmap area, is:
>>
>>     vaddr_bt = FIXADDR_TOP - FIX_BTMAP_BEGIN * PAGE_SIZE
>>
>> If that address is lower than:
>>
>>     vaddr_end = __START_KERNEL_map + KERNEL_IMAGE_SIZE;
>>
>> then cleanup_highmap() will happily 0 out the PMD entry for the PTE page of
>> FIX_BTMAP. That entry was set up earlier in early_ioremap_init().
>>
>> As a consequence the first call to __early_set_fixmap() which tries to
>> install a PTE for early_ioremap() will crash and burn.
>>
>> Below is a nasty hack which fixes the problem. Ideally we get all of this
>> cpu_entry_stuff out of the fixmap. I'll look into that later, but for now
>> the patch 'fixes' the issue.
> 
> I had a stab on moving the cpu_entry_area to some other place.
> 
> The patch below works, but:
> 
>  - it breaks i386 build because I have not yet found a way to place the
>    CPU_ENTRY_AREA_BASE without creating include recursion hell
> 
>  - it probably does not work on XEN_PV, but I'm too tired now to figure
>    that out.

The attached patch lets the system come up as XEN_PV.


Juergen
diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index e4a6fe8354f0..577fa8adb785 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -37,6 +37,7 @@
 #include <asm/unistd.h>
 #include <asm/fixmap.h>
 #include <asm/traps.h>
+#include <asm/paravirt.h>
 
 #define CREATE_TRACE_POINTS
 #include "vsyscall_trace.h"
@@ -351,15 +352,15 @@ void __init set_vsyscall_pgtable_user_bits(pgd_t *root)
 	pmd_t *pmd;
 
 	pgd = pgd_offset_pgd(root, VSYSCALL_ADDR);
-	pgd->pgd |= _PAGE_USER;
+	set_pgd(pgd, __pgd(pgd_val(*pgd) | _PAGE_USER));
 	p4d = p4d_offset(pgd, VSYSCALL_ADDR);
 #if CONFIG_PGTABLE_LEVELS >= 5
 	p4d->p4d |= _PAGE_USER;
 #endif
 	pud = pud_offset(p4d, VSYSCALL_ADDR);
-	pud->pud |= _PAGE_USER;
+	set_pud(pud, __pud(pud_val(*pud) | _PAGE_USER));
 	pmd = pmd_offset(pud, VSYSCALL_ADDR);
-	pmd->pmd |= _PAGE_USER;
+	set_pmd(pmd, __pmd(pmd_val(*pmd) | _PAGE_USER));
 }
 
 void __init map_vsyscall(void)

Reply via email to