Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch The way the xen dummy page is taken care of makes a...



details:   https://anonhg.NetBSD.org/src/rev/8ef62df42260
branches:  trunk
changeset: 349624:8ef62df42260
user:      maxv <maxv%NetBSD.org@localhost>
date:      Fri Dec 16 19:52:22 2016 +0000

description:
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.

diffstat:

 sys/arch/amd64/amd64/locore.S |   6 +++---
 sys/arch/i386/i386/locore.S   |   8 ++++----
 sys/arch/i386/i386/machdep.c  |  10 +++++-----
 sys/arch/x86/x86/pmap.c       |   9 +++++----
 sys/arch/xen/x86/x86_xpmap.c  |  25 +++++++++++++++++++++----
 5 files changed, 38 insertions(+), 20 deletions(-)

diffs (185 lines):

diff -r 3a8d4adc696d -r 8ef62df42260 sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S     Fri Dec 16 17:20:52 2016 +0000
+++ b/sys/arch/amd64/amd64/locore.S     Fri Dec 16 19:52:22 2016 +0000
@@ -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 @@
        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 */
 
diff -r 3a8d4adc696d -r 8ef62df42260 sys/arch/i386/i386/locore.S
--- a/sys/arch/i386/i386/locore.S       Fri Dec 16 17:20:52 2016 +0000
+++ b/sys/arch/i386/i386/locore.S       Fri Dec 16 19:52:22 2016 +0000
@@ -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 @@
        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
diff -r 3a8d4adc696d -r 8ef62df42260 sys/arch/i386/i386/machdep.c
--- a/sys/arch/i386/i386/machdep.c      Fri Dec 16 17:20:52 2016 +0000
+++ b/sys/arch/i386/i386/machdep.c      Fri Dec 16 19:52:22 2016 +0000
@@ -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 @@
        /* 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);
diff -r 3a8d4adc696d -r 8ef62df42260 sys/arch/x86/x86/pmap.c
--- a/sys/arch/x86/x86/pmap.c   Fri Dec 16 17:20:52 2016 +0000
+++ b/sys/arch/x86/x86/pmap.c   Fri Dec 16 19:52:22 2016 +0000
@@ -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 @@
 #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);
diff -r 3a8d4adc696d -r 8ef62df42260 sys/arch/xen/x86/x86_xpmap.c
--- a/sys/arch/xen/x86/x86_xpmap.c      Fri Dec 16 17:20:52 2016 +0000
+++ b/sys/arch/xen/x86/x86_xpmap.c      Fri Dec 16 19:52:22 2016 +0000
@@ -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 <mro%adviseo.fr@localhost>
@@ -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 @@
 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 @@
 /*
  * 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 @@
        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 @@
         */
        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;



Home | Main Index | Thread Index | Old Index