Module Name: src Committed By: maxv Date: Fri Dec 16 19:52:22 UTC 2016
Modified Files: src/sys/arch/amd64/amd64: locore.S src/sys/arch/i386/i386: locore.S machdep.c src/sys/arch/x86/x86: pmap.c src/sys/arch/xen/x86: x86_xpmap.c Log Message: The way the xen dummy page is taken care of makes absolutely no sense at all, with magic offsets here and there in different layers of the system. It is just blind luck that everything has always worked as expected so far. Due to this wrong design we have a problem now: we allocate one physical page for lapic, and it happens to overlap with the dummy page, which causes the system to crash. Fix this by keeping the dummy va directly in a variable instead of magic offsets. The asm locore now increments the first pa to hide the dummy page to machdep and pmap. To generate a diff of this commit: cvs rdiff -u -r1.116 -r1.117 src/sys/arch/amd64/amd64/locore.S cvs rdiff -u -r1.142 -r1.143 src/sys/arch/i386/i386/locore.S cvs rdiff -u -r1.767 -r1.768 src/sys/arch/i386/i386/machdep.c cvs rdiff -u -r1.231 -r1.232 src/sys/arch/x86/x86/pmap.c cvs rdiff -u -r1.67 -r1.68 src/sys/arch/xen/x86/x86_xpmap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/amd64/locore.S diff -u src/sys/arch/amd64/amd64/locore.S:1.116 src/sys/arch/amd64/amd64/locore.S:1.117 --- src/sys/arch/amd64/amd64/locore.S:1.116 Fri Dec 9 17:57:24 2016 +++ src/sys/arch/amd64/amd64/locore.S Fri Dec 16 19:52:22 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.116 2016/12/09 17:57:24 maxv Exp $ */ +/* $NetBSD: locore.S,v 1.117 2016/12/16 19:52:22 maxv Exp $ */ /* * Copyright-o-rama! @@ -948,9 +948,9 @@ longmode_hi: movw %ax,%gs movw %ax,%fs - /* Set first_avail after the UAREA. */ + /* Set first_avail after the DUMMY PAGE (see xen_locore). */ movq %rsi,%rdi - addq $USPACE,%rdi + addq $(USPACE+PAGE_SIZE),%rdi subq $KERNBASE,%rdi /* init_x86_64 wants a physical address */ #endif /* XEN */ Index: src/sys/arch/i386/i386/locore.S diff -u src/sys/arch/i386/i386/locore.S:1.142 src/sys/arch/i386/i386/locore.S:1.143 --- src/sys/arch/i386/i386/locore.S:1.142 Tue Dec 6 15:05:07 2016 +++ src/sys/arch/i386/i386/locore.S Fri Dec 16 19:52:22 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.142 2016/12/06 15:05:07 maxv Exp $ */ +/* $NetBSD: locore.S,v 1.143 2016/12/16 19:52:22 maxv Exp $ */ /* * Copyright-o-rama! @@ -128,7 +128,7 @@ */ #include <machine/asm.h> -__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.142 2016/12/06 15:05:07 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.143 2016/12/16 19:52:22 maxv Exp $"); #include "opt_compat_oldboot.h" #include "opt_copy_symtab.h" @@ -918,8 +918,8 @@ begin: leal (USPACE-FRAMESIZE)(%eax),%esp xorl %ebp,%ebp /* mark end of frames */ - /* Set first_avail after the UAREA. */ - addl $USPACE,%esi + /* Set first_avail after the DUMMY PAGE (see xen_locore). */ + addl $(USPACE+PAGE_SIZE),%esi subl $KERNBASE,%esi /* init386 wants a physical address */ #ifdef PAE Index: src/sys/arch/i386/i386/machdep.c diff -u src/sys/arch/i386/i386/machdep.c:1.767 src/sys/arch/i386/i386/machdep.c:1.768 --- src/sys/arch/i386/i386/machdep.c:1.767 Thu Dec 15 12:04:18 2016 +++ src/sys/arch/i386/i386/machdep.c Fri Dec 16 19:52:22 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.767 2016/12/15 12:04:18 kamil Exp $ */ +/* $NetBSD: machdep.c,v 1.768 2016/12/16 19:52:22 maxv Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009 @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.767 2016/12/15 12:04:18 kamil Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.768 2016/12/16 19:52:22 maxv Exp $"); #include "opt_beep.h" #include "opt_compat_ibcs2.h" @@ -1214,9 +1214,9 @@ init386(paddr_t first_avail) /* Parse Xen command line (replace bootinfo) */ xen_parse_cmdline(XEN_PARSE_BOOTFLAGS, NULL); - /* Steal one page for gdt */ - gdt = (void *)((u_long)first_avail + KERNBASE); - first_avail += PAGE_SIZE; + /* Use the dummy page as a gdt */ + extern vaddr_t xen_dummy_page; + gdt = (void *)xen_dummy_page; /* Determine physical address space */ first_avail = round_page(first_avail); Index: src/sys/arch/x86/x86/pmap.c diff -u src/sys/arch/x86/x86/pmap.c:1.231 src/sys/arch/x86/x86/pmap.c:1.232 --- src/sys/arch/x86/x86/pmap.c:1.231 Tue Dec 13 10:54:27 2016 +++ src/sys/arch/x86/x86/pmap.c Fri Dec 16 19:52:22 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.231 2016/12/13 10:54:27 kamil Exp $ */ +/* $NetBSD: pmap.c,v 1.232 2016/12/16 19:52:22 maxv Exp $ */ /*- * Copyright (c) 2008, 2010, 2016 The NetBSD Foundation, Inc. @@ -171,7 +171,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.231 2016/12/13 10:54:27 kamil Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.232 2016/12/16 19:52:22 maxv Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -1399,15 +1399,16 @@ pmap_bootstrap(vaddr_t kva_start) #endif #if defined(XEN) && defined(__x86_64__) + extern vaddr_t xen_dummy_page; /* * We want a dummy page directory for Xen: when deactivating a pmap, Xen * will still consider it active. So we set user PGD to this one to lift * all protection on the now inactive page tables set. */ - xen_dummy_user_pgd = pmap_bootstrap_palloc(1); + xen_dummy_user_pgd = xen_dummy_page - KERNBASE; /* Zero fill it, the less checks in Xen it requires the better */ - memset((void *) (xen_dummy_user_pgd + KERNBASE), 0, PAGE_SIZE); + memset((void *)(xen_dummy_user_pgd + KERNBASE), 0, PAGE_SIZE); /* Mark read-only */ HYPERVISOR_update_va_mapping(xen_dummy_user_pgd + KERNBASE, pmap_pa2pte(xen_dummy_user_pgd) | PG_u | PG_V, UVMF_INVLPG); Index: src/sys/arch/xen/x86/x86_xpmap.c diff -u src/sys/arch/xen/x86/x86_xpmap.c:1.67 src/sys/arch/xen/x86/x86_xpmap.c:1.68 --- src/sys/arch/xen/x86/x86_xpmap.c:1.67 Tue Nov 15 17:01:12 2016 +++ src/sys/arch/xen/x86/x86_xpmap.c Fri Dec 16 19:52:22 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: x86_xpmap.c,v 1.67 2016/11/15 17:01:12 maxv Exp $ */ +/* $NetBSD: x86_xpmap.c,v 1.68 2016/12/16 19:52:22 maxv Exp $ */ /* * Copyright (c) 2006 Mathieu Ropert <m...@adviseo.fr> @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.67 2016/11/15 17:01:12 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.68 2016/12/16 19:52:22 maxv Exp $"); #include "opt_xen.h" #include "opt_ddb.h" @@ -103,6 +103,7 @@ volatile shared_info_t *HYPERVISOR_share union start_info_union start_info_union __aligned(PAGE_SIZE); unsigned long *xpmap_phys_to_machine_mapping; kmutex_t pte_lock; +vaddr_t xen_dummy_page; void xen_failsafe_handler(void); @@ -588,6 +589,20 @@ static const int l2_4_count = PTP_LEVELS /* * Xen locore: get rid of the Xen bootstrap tables. Build and switch to new page * tables. + * + * Virtual address space of the kernel when leaving this function: + * +--------------+------------------+-------------+------------+--------------- + * | KERNEL IMAGE | BOOTSTRAP TABLES | PROC0 UAREA | DUMMY PAGE | HYPER. SHARED + * +--------------+------------------+-------------+------------+--------------- + * + * ------+-----------------+-------------+ + * INFO | EARLY ZERO PAGE | ISA I/O MEM | + * ------+-----------------+-------------+ + * + * DUMMY PAGE is either a PDG for amd64 or a GDT for i386. + * + * (HYPER. SHARED INFO + EARLY ZERO PAGE + ISA I/O MEM) have no physical + * addresses preallocated. */ vaddr_t xen_locore(void) @@ -694,7 +709,7 @@ bootstrap_again: xen_bootstrap_tables(bootstrap_tables, init_tables, oldcount + l2_4_count, count, true); - /* Zero out free space after tables */ + /* Zero out PROC0 UAREA and DUMMY PAGE. */ memset((void *)(init_tables + ((count + l2_4_count) * PAGE_SIZE)), 0, (UPAGES + 1) * PAGE_SIZE); @@ -746,7 +761,9 @@ xen_bootstrap_tables(vaddr_t old_pgd, va */ map_end = new_pgd + ((new_count + l2_4_count) * PAGE_SIZE); if (final) { - map_end += (UPAGES + 1) * PAGE_SIZE; + map_end += UPAGES * PAGE_SIZE; + xen_dummy_page = (vaddr_t)map_end; + map_end += PAGE_SIZE; HYPERVISOR_shared_info = (shared_info_t *)map_end; map_end += PAGE_SIZE; early_zerop = (char *)map_end;