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;

Reply via email to