Module Name:    src
Committed By:   martin
Date:           Fri Mar 16 13:17:56 UTC 2018

Modified Files:
        src/sys/arch/amd64/amd64 [netbsd-8]: gdt.c machdep.c
        src/sys/arch/amd64/include [netbsd-8]: param.h types.h
        src/sys/arch/x86/include [netbsd-8]: cpu.h pmap.h
        src/sys/arch/x86/x86 [netbsd-8]: cpu.c intr.c pmap.c

Log Message:
Pull up the following revisions (via patch), requested by maxv in #635:

        sys/arch/amd64/amd64/gdt.c              1.39-1.45 (patch)
        sys/arch/amd64/amd64/amd64/machdep.c    1.284,1.287,1.288 (patch)
        sys/arch/amd64/amd64/include/param.h    1.23 (patch)
        sys/arch/amd64/include/types.h          1.53 (patch)
        sys/arch/x86/include/cpu.h              1.87 (patch)
        sys/arch/x86/include/pmap.h             1.73,1.74 (patch)
        sys/arch/x86/x86/cpu.c                  1.142 (patch)
        sys/arch/x86/x86/intr.c                 1.117 (partial),1.120 (patch)
        sys/arch/x86/x86/pmap.c                 1.276 (patch)

Initialize ist0 in cpu_init_tss.
Backport __HAVE_PCPU_AREA.


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.38.6.1 src/sys/arch/amd64/amd64/gdt.c
cvs rdiff -u -r1.255.6.4 -r1.255.6.5 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.21 -r1.21.6.1 src/sys/arch/amd64/include/param.h
cvs rdiff -u -r1.52 -r1.52.6.1 src/sys/arch/amd64/include/types.h
cvs rdiff -u -r1.71.2.2 -r1.71.2.3 src/sys/arch/x86/include/cpu.h
cvs rdiff -u -r1.64 -r1.64.6.1 src/sys/arch/x86/include/pmap.h
cvs rdiff -u -r1.130.2.3 -r1.130.2.4 src/sys/arch/x86/x86/cpu.c
cvs rdiff -u -r1.101.2.2 -r1.101.2.3 src/sys/arch/x86/x86/intr.c
cvs rdiff -u -r1.245.6.4 -r1.245.6.5 src/sys/arch/x86/x86/pmap.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/gdt.c
diff -u src/sys/arch/amd64/amd64/gdt.c:1.38 src/sys/arch/amd64/amd64/gdt.c:1.38.6.1
--- src/sys/arch/amd64/amd64/gdt.c:1.38	Sat Mar 25 15:05:16 2017
+++ src/sys/arch/amd64/amd64/gdt.c	Fri Mar 16 13:17:56 2018
@@ -1,6 +1,6 @@
-/*	$NetBSD: gdt.c,v 1.38 2017/03/25 15:05:16 maxv Exp $	*/
+/*	$NetBSD: gdt.c,v 1.38.6.1 2018/03/16 13:17:56 martin Exp $	*/
 
-/*-
+/*
  * Copyright (c) 1996, 1997, 2009 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gdt.c,v 1.38 2017/03/25 15:05:16 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gdt.c,v 1.38.6.1 2018/03/16 13:17:56 martin Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_xen.h"
@@ -57,16 +57,24 @@ __KERNEL_RCSID(0, "$NetBSD: gdt.c,v 1.38
 #include <xen/hypervisor.h>
 #endif
 
-#define NDYNSLOTS \
-	((MAXGDTSIZ - DYNSEL_START) / sizeof(struct sys_segment_descriptor))
+#define NSLOTS(sz)	\
+	(((sz) - DYNSEL_START) / sizeof(struct sys_segment_descriptor))
+#define NDYNSLOTS	NSLOTS(MAXGDTSIZ)
 
 typedef struct {
 	bool busy[NDYNSLOTS];
 	size_t nslots;
 } gdt_bitmap_t;
 
-size_t gdt_size;			/* size of GDT in bytes */		
-static gdt_bitmap_t gdt_bitmap;		/* bitmap of busy slots */
+/* size of GDT in bytes */
+#ifdef XEN
+const size_t gdt_size = FIRST_RESERVED_GDT_BYTE;
+#else
+const size_t gdt_size = MAXGDTSIZ;
+#endif
+
+/* bitmap of busy slots */
+static gdt_bitmap_t gdt_bitmap;
 
 #if defined(USER_LDT) || !defined(XEN)
 static void set_sys_gdt(int, void *, size_t, int, int, int);
@@ -124,27 +132,25 @@ void
 gdt_init(void)
 {
 	char *old_gdt;
-	struct vm_page *pg;
-	vaddr_t va;
 	struct cpu_info *ci = &cpu_info_primary;
 
 	/* Initialize the global values */
-	gdt_size = MINGDTSIZ;
 	memset(&gdt_bitmap.busy, 0, sizeof(gdt_bitmap.busy));
-	gdt_bitmap.nslots =
-	    (gdt_size - DYNSEL_START) / sizeof(struct sys_segment_descriptor);
+	gdt_bitmap.nslots = NSLOTS(gdt_size);
 
 	old_gdt = gdtstore;
 
-	/* Allocate MAXGDTSIZ bytes of virtual memory. */
-	gdtstore = (char *)uvm_km_alloc(kernel_map, MAXGDTSIZ, 0,
-	    UVM_KMF_VAONLY);
+#ifdef __HAVE_PCPU_AREA
+	/* The GDT is part of the pcpuarea */
+	gdtstore = (char *)&pcpuarea->ent[cpu_index(ci)].gdt;
+#else
+	struct vm_page *pg;
+	vaddr_t va;
 
-	/*
-	 * Allocate only MINGDTSIZ bytes of physical memory. We will grow this
-	 * area in gdt_grow at run-time if needed.
-	 */
-	for (va = (vaddr_t)gdtstore; va < (vaddr_t)gdtstore + MINGDTSIZ;
+	/* Allocate gdt_size bytes of memory. */
+	gdtstore = (char *)uvm_km_alloc(kernel_map, gdt_size, 0,
+	    UVM_KMF_VAONLY);
+	for (va = (vaddr_t)gdtstore; va < (vaddr_t)gdtstore + gdt_size;
 	    va += PAGE_SIZE) {
 		pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
 		if (pg == NULL) {
@@ -154,6 +160,7 @@ gdt_init(void)
 		    VM_PROT_READ | VM_PROT_WRITE, 0);
 	}
 	pmap_update(pmap_kernel());
+#endif
 
 	/* Copy the initial bootstrap GDT into the new area. */
 	memcpy(gdtstore, old_gdt, DYNSEL_START);
@@ -173,15 +180,15 @@ gdt_init(void)
 void
 gdt_alloc_cpu(struct cpu_info *ci)
 {
-	int max_len = MAXGDTSIZ;
-	int min_len = MINGDTSIZ;
+#ifdef __HAVE_PCPU_AREA
+	ci->ci_gdt = (union descriptor *)&pcpuarea->ent[cpu_index(ci)].gdt;
+#else
 	struct vm_page *pg;
 	vaddr_t va;
 
-	ci->ci_gdt = (union descriptor *)uvm_km_alloc(kernel_map, max_len,
+	ci->ci_gdt = (union descriptor *)uvm_km_alloc(kernel_map, gdt_size,
 	    0, UVM_KMF_VAONLY);
-
-	for (va = (vaddr_t)ci->ci_gdt; va < (vaddr_t)ci->ci_gdt + min_len;
+	for (va = (vaddr_t)ci->ci_gdt; va < (vaddr_t)ci->ci_gdt + gdt_size;
 	    va += PAGE_SIZE) {
 		while ((pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO))
 		    == NULL) {
@@ -191,8 +198,8 @@ gdt_alloc_cpu(struct cpu_info *ci)
 		    VM_PROT_READ | VM_PROT_WRITE, 0);
 	}
 	pmap_update(pmap_kernel());
+#endif
 
-	memset(ci->ci_gdt, 0, min_len);
 	memcpy(ci->ci_gdt, gdtstore, gdt_size);
 }
 
@@ -207,52 +214,11 @@ gdt_init_cpu(struct cpu_info *ci)
 
 	KASSERT(curcpu() == ci);
 
-#ifndef XEN
-	setregion(&region, ci->ci_gdt, (uint16_t)(MAXGDTSIZ - 1));
-#else
 	setregion(&region, ci->ci_gdt, (uint16_t)(gdt_size - 1));
-#endif
 	lgdt(&region);
 }
 
 #if !defined(XEN) || defined(USER_LDT)
-/*
- * Grow the GDT. The GDT is present on each CPU, so we need to iterate over all
- * of them. We already have the virtual memory, we only need to grow the
- * physical memory.
- */
-static void
-gdt_grow(void)
-{
-	size_t old_size;
-	CPU_INFO_ITERATOR cii;
-	struct cpu_info *ci;
-	struct vm_page *pg;
-	vaddr_t va;
-
-	old_size = gdt_size;
-	gdt_size *= 2;
-	if (gdt_size > MAXGDTSIZ)
-		gdt_size = MAXGDTSIZ;
-	gdt_bitmap.nslots =
-	    (gdt_size - DYNSEL_START) / sizeof(struct sys_segment_descriptor);
-
-	for (CPU_INFO_FOREACH(cii, ci)) {
-		for (va = (vaddr_t)(ci->ci_gdt) + old_size;
-		     va < (vaddr_t)(ci->ci_gdt) + gdt_size;
-		     va += PAGE_SIZE) {
-			while ((pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO)) ==
-			    NULL) {
-				uvm_wait("gdt_grow");
-			}
-			pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
-			    VM_PROT_READ | VM_PROT_WRITE, 0);
-		}
-	}
-
-	pmap_update(pmap_kernel());
-}
-
 static int
 gdt_get_slot(void)
 {
@@ -260,17 +226,14 @@ gdt_get_slot(void)
 
 	KASSERT(mutex_owned(&cpu_lock));
 
-	while (1) {
-		for (i = 0; i < gdt_bitmap.nslots; i++) {
-			if (!gdt_bitmap.busy[i]) {
-				gdt_bitmap.busy[i] = true;
-				return (int)i;
-			}
+	for (i = 0; i < gdt_bitmap.nslots; i++) {
+		if (!gdt_bitmap.busy[i]) {
+			gdt_bitmap.busy[i] = true;
+			return (int)i;
 		}
-		if (gdt_size >= MAXGDTSIZ)
-			panic("gdt_get_slot: out of memory");
-		gdt_grow();
 	}
+	panic("gdt_get_slot: out of memory");
+
 	/* NOTREACHED */
 	return 0;
 }
@@ -349,26 +312,25 @@ void
 lgdt(struct region_descriptor *desc)
 {
 	paddr_t frames[16];
-	int i;
+	size_t i;
 	vaddr_t va;
 
 	/*
-	 * XXX: Xen even checks descriptors AFTER limit.
-	 * Zero out last frame after limit if needed.
+	 * Xen even checks descriptors AFTER limit. Zero out last frame after
+	 * limit if needed.
 	 */
 	va = desc->rd_base + desc->rd_limit + 1;
 	memset((void *)va, 0, roundup(va, PAGE_SIZE) - va);
+
+	/*
+	 * The lgdt instruction uses virtual addresses, do some translation for
+	 * Xen. Mark pages R/O too, otherwise Xen will refuse to use them.
+	 */
 	for (i = 0; i < roundup(desc->rd_limit, PAGE_SIZE) >> PAGE_SHIFT; i++) {
-		/*
-		 * The lgdt instruction uses virtual addresses,
-		 * do some translation for Xen.
-		 * Mark pages R/O too, else Xen will refuse to use them.
-		 */
-		frames[i] = ((paddr_t) xpmap_ptetomach(
-		    (pt_entry_t *)(desc->rd_base + (i << PAGE_SHIFT)))) >>
+		va = desc->rd_base + (i << PAGE_SHIFT);
+		frames[i] = ((paddr_t)xpmap_ptetomach((pt_entry_t *)va)) >>
 		    PAGE_SHIFT;
-		pmap_pte_clearbits(kvtopte(desc->rd_base + (i << PAGE_SHIFT)),
-		    PG_RW);
+		pmap_pte_clearbits(kvtopte(va), PG_RW);
 	}
 
 	if (HYPERVISOR_set_gdt(frames, (desc->rd_limit + 1) >> 3))

Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.255.6.4 src/sys/arch/amd64/amd64/machdep.c:1.255.6.5
--- src/sys/arch/amd64/amd64/machdep.c:1.255.6.4	Tue Mar 13 15:47:44 2018
+++ src/sys/arch/amd64/amd64/machdep.c	Fri Mar 16 13:17:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.255.6.4 2018/03/13 15:47:44 martin Exp $	*/
+/*	$NetBSD: machdep.c,v 1.255.6.5 2018/03/16 13:17:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -111,7 +111,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.255.6.4 2018/03/13 15:47:44 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.255.6.5 2018/03/16 13:17:56 martin Exp $");
 
 /* #define XENDEBUG_LOW  */
 
@@ -391,6 +391,9 @@ cpu_startup(void)
 	x86_bus_space_mallocok();
 #endif
 
+#ifdef __HAVE_PCPU_AREA
+	cpu_pcpuarea_init(&cpu_info_primary);
+#endif
 	gdt_init();
 	x86_64_proc0_tss_ldt_init();
 
@@ -500,21 +503,43 @@ x86_64_proc0_tss_ldt_init(void)
 void
 cpu_init_tss(struct cpu_info *ci)
 {
+#ifdef __HAVE_PCPU_AREA
+	const cpuid_t cid = cpu_index(ci);
+#endif
 	struct cpu_tss *cputss;
 	uintptr_t p;
 
+#ifdef __HAVE_PCPU_AREA
+	cputss = (struct cpu_tss *)&pcpuarea->ent[cid].tss;
+#else
 	cputss = (struct cpu_tss *)uvm_km_alloc(kernel_map,
 	    sizeof(struct cpu_tss), 0, UVM_KMF_WIRED|UVM_KMF_ZERO);
+#endif
 
 	cputss->tss.tss_iobase = IOMAP_INVALOFF << 16;
-	/* cputss->tss.tss_ist[0] is filled by cpu_intr_init */
+
+	/* DDB stack */
+#ifdef __HAVE_PCPU_AREA
+	p = (vaddr_t)&pcpuarea->ent[cid].ist0;
+#else
+	p = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED|UVM_KMF_ZERO);
+#endif
+	cputss->tss.tss_ist[0] = p + PAGE_SIZE - 16;
 
 	/* double fault */
-	p = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED);
+#ifdef __HAVE_PCPU_AREA
+	p = (vaddr_t)&pcpuarea->ent[cid].ist1;
+#else
+	p = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED|UVM_KMF_ZERO);
+#endif
 	cputss->tss.tss_ist[1] = p + PAGE_SIZE - 16;
 
 	/* NMI */
-	p = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED);
+#ifdef __HAVE_PCPU_AREA
+	p = (vaddr_t)&pcpuarea->ent[cid].ist2;
+#else
+	p = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED|UVM_KMF_ZERO);
+#endif
 	cputss->tss.tss_ist[2] = p + PAGE_SIZE - 16;
 
 	ci->ci_tss = cputss;

Index: src/sys/arch/amd64/include/param.h
diff -u src/sys/arch/amd64/include/param.h:1.21 src/sys/arch/amd64/include/param.h:1.21.6.1
--- src/sys/arch/amd64/include/param.h:1.21	Thu Feb  2 19:09:08 2017
+++ src/sys/arch/amd64/include/param.h	Fri Mar 16 13:17:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.21 2017/02/02 19:09:08 maxv Exp $	*/
+/*	$NetBSD: param.h,v 1.21.6.1 2018/03/16 13:17:56 martin Exp $	*/
 
 #ifdef __x86_64__
 
@@ -58,7 +58,6 @@
 #define	UPAGES		3		/* pages of u-area */
 #endif
 #define	USPACE		(UPAGES * NBPG)	/* total size of u-area */
-#define	INTRSTACKSIZE	4096
 
 #ifndef MSGBUFSIZE
 #define MSGBUFSIZE	(8*NBPG)	/* default message buffer size */

Index: src/sys/arch/amd64/include/types.h
diff -u src/sys/arch/amd64/include/types.h:1.52 src/sys/arch/amd64/include/types.h:1.52.6.1
--- src/sys/arch/amd64/include/types.h:1.52	Thu Jan 26 15:55:09 2017
+++ src/sys/arch/amd64/include/types.h	Fri Mar 16 13:17:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: types.h,v 1.52 2017/01/26 15:55:09 christos Exp $	*/
+/*	$NetBSD: types.h,v 1.52.6.1 2018/03/16 13:17:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -102,6 +102,7 @@ typedef	unsigned char		__cpu_simple_lock
 
 #include "opt_xen.h"
 #if defined(__x86_64__) && !defined(XEN)
+#define	__HAVE_PCPU_AREA 1
 #define	__HAVE_DIRECT_MAP 1
 #define	__HAVE_MM_MD_DIRECT_MAPPED_IO
 #define	__HAVE_MM_MD_DIRECT_MAPPED_PHYS

Index: src/sys/arch/x86/include/cpu.h
diff -u src/sys/arch/x86/include/cpu.h:1.71.2.2 src/sys/arch/x86/include/cpu.h:1.71.2.3
--- src/sys/arch/x86/include/cpu.h:1.71.2.2	Tue Mar 13 15:47:45 2018
+++ src/sys/arch/x86/include/cpu.h	Fri Mar 16 13:17:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.71.2.2 2018/03/13 15:47:45 martin Exp $	*/
+/*	$NetBSD: cpu.h,v 1.71.2.3 2018/03/16 13:17:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -341,6 +341,8 @@ void cpu_load_pmap(struct pmap *, struct
 void cpu_broadcast_halt(void);
 void cpu_kick(struct cpu_info *);
 
+void cpu_pcpuarea_init(struct cpu_info *);
+
 #define	curcpu()		x86_curcpu()
 #define	curlwp			x86_curlwp()
 #define	curpcb			((struct pcb *)lwp_getpcb(curlwp))

Index: src/sys/arch/x86/include/pmap.h
diff -u src/sys/arch/x86/include/pmap.h:1.64 src/sys/arch/x86/include/pmap.h:1.64.6.1
--- src/sys/arch/x86/include/pmap.h:1.64	Thu Mar 23 18:08:06 2017
+++ src/sys/arch/x86/include/pmap.h	Fri Mar 16 13:17:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.64 2017/03/23 18:08:06 maxv Exp $	*/
+/*	$NetBSD: pmap.h,v 1.64.6.1 2018/03/16 13:17:56 martin Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -112,6 +112,31 @@
 #include <uvm/pmap/pmap_pvt.h>
 
 /*
+ * NetBSD-8: MAXGDTSIZ is 8192 on i386, unlike NetBSD-current. We define
+ * _MAXGDTSIZ as 65536, which is the size of the GDT in bytes, as opposed
+ * to in number of slots.
+ */
+#ifndef _MAXGDTSIZ
+#define _MAXGDTSIZ 65536 /* XXX */
+#endif
+
+struct pcpu_entry {
+	uint8_t gdt[_MAXGDTSIZ];
+	uint8_t tss[PAGE_SIZE];
+	uint8_t ist0[PAGE_SIZE];
+	uint8_t ist1[PAGE_SIZE];
+	uint8_t ist2[PAGE_SIZE];
+} __packed;
+
+struct pcpu_area {
+	uint8_t idt[PAGE_SIZE];
+	uint8_t ldt[PAGE_SIZE];
+	struct pcpu_entry ent[MAXCPUS];
+} __packed;
+
+extern struct pcpu_area *pcpuarea;
+
+/*
  * pmap data structures: see pmap.c for details of locking.
  */
 
@@ -483,6 +508,12 @@ void	pmap_free_ptps(struct vm_page *);
  */
 #define	POOL_VTOPHYS(va)	vtophys((vaddr_t) (va))
 
+#ifdef __HAVE_PCPU_AREA
+extern struct pcpu_area *pcpuarea;
+#define PDIR_SLOT_PCPU		384
+#define PMAP_PCPU_BASE		(VA_SIGN_NEG((PDIR_SLOT_PCPU * NBPD_L4)))
+#endif
+
 #ifdef __HAVE_DIRECT_MAP
 
 #define L4_SLOT_DIRECT		509

Index: src/sys/arch/x86/x86/cpu.c
diff -u src/sys/arch/x86/x86/cpu.c:1.130.2.3 src/sys/arch/x86/x86/cpu.c:1.130.2.4
--- src/sys/arch/x86/x86/cpu.c:1.130.2.3	Thu Mar  8 11:33:15 2018
+++ src/sys/arch/x86/x86/cpu.c	Fri Mar 16 13:17:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.130.2.3 2018/03/08 11:33:15 martin Exp $	*/
+/*	$NetBSD: cpu.c,v 1.130.2.4 2018/03/16 13:17:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 2000-2012 NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.130.2.3 2018/03/08 11:33:15 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.130.2.4 2018/03/16 13:17:56 martin Exp $");
 
 #include "opt_ddb.h"
 #include "opt_mpbios.h"		/* for MPDEBUG */
@@ -232,6 +232,36 @@ cpu_match(device_t parent, cfdata_t matc
 	return 1;
 }
 
+#ifdef __HAVE_PCPU_AREA
+void
+cpu_pcpuarea_init(struct cpu_info *ci)
+{
+	struct vm_page *pg;
+	size_t i, npages;
+	vaddr_t base, va;
+	paddr_t pa;
+
+	CTASSERT(sizeof(struct pcpu_entry) % PAGE_SIZE == 0);
+
+	npages = sizeof(struct pcpu_entry) / PAGE_SIZE;
+	base = (vaddr_t)&pcpuarea->ent[cpu_index(ci)];
+
+	for (i = 0; i < npages; i++) {
+		pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
+		if (pg == NULL) {
+			panic("failed to allocate pcpu PA");
+		}
+
+		va = base + i * PAGE_SIZE;
+		pa = VM_PAGE_TO_PHYS(pg);
+
+		pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE, 0);
+	}
+
+	pmap_update(pmap_kernel());
+}
+#endif
+
 static void
 cpu_vm_init(struct cpu_info *ci)
 {
@@ -372,6 +402,9 @@ cpu_attach(device_t parent, device_t sel
 			    "mi_cpu_attach failed with %d\n", error);
 			return;
 		}
+#ifdef __HAVE_PCPU_AREA
+		cpu_pcpuarea_init(ci);
+#endif
 		cpu_init_tss(ci);
 	} else {
 		KASSERT(ci->ci_data.cpu_idlelwp != NULL);

Index: src/sys/arch/x86/x86/intr.c
diff -u src/sys/arch/x86/x86/intr.c:1.101.2.2 src/sys/arch/x86/x86/intr.c:1.101.2.3
--- src/sys/arch/x86/x86/intr.c:1.101.2.2	Tue Mar 13 15:47:45 2018
+++ src/sys/arch/x86/x86/intr.c	Fri Mar 16 13:17:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.c,v 1.101.2.2 2018/03/13 15:47:45 martin Exp $	*/
+/*	$NetBSD: intr.c,v 1.101.2.3 2018/03/16 13:17:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -133,7 +133,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.101.2.2 2018/03/13 15:47:45 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.101.2.3 2018/03/16 13:17:56 martin Exp $");
 
 #include "opt_intrdebug.h"
 #include "opt_multiprocessor.h"
@@ -233,8 +233,10 @@ static void intr_disestablish_xcall(void
 
 static const char *legacy_intr_string(int, char *, size_t, struct pic *);
 
+#if defined(INTRSTACKSIZE)
 static inline bool redzone_const_or_false(bool);
 static inline int redzone_const_or_zero(int);
+#endif
 
 static void intr_redistribute_xc_t(void *, void *);
 static void intr_redistribute_xc_s1(void *, void *);
@@ -1269,6 +1271,7 @@ struct intrhand fake_preempt_intrhand;
 static const char *x86_ipi_names[X86_NIPI] = X86_IPI_NAMES;
 #endif
 
+#if defined(INTRSTACKSIZE)
 static inline bool
 redzone_const_or_false(bool x)
 {
@@ -1284,6 +1287,7 @@ redzone_const_or_zero(int x)
 {
 	return redzone_const_or_false(true) ? x : 0;
 }
+#endif
 
 /*
  * Initialize all handlers that aren't dynamically allocated, and exist
@@ -1297,9 +1301,6 @@ cpu_intr_init(struct cpu_info *ci)
 	int i;
 	static int first = 1;
 #endif
-#ifdef INTRSTACKSIZE
-	vaddr_t istack;
-#endif
 
 #if NLAPIC > 0
 	isp = kmem_zalloc(sizeof(*isp), KM_SLEEP);
@@ -1340,28 +1341,30 @@ cpu_intr_init(struct cpu_info *ci)
 	intr_calculatemasks(ci);
 
 #if defined(INTRSTACKSIZE)
+	vaddr_t istack;
+
 	/*
 	 * If the red zone is activated, protect both the top and
 	 * the bottom of the stack with an unmapped page.
 	 */
 	istack = uvm_km_alloc(kernel_map,
 	    INTRSTACKSIZE + redzone_const_or_zero(2 * PAGE_SIZE), 0,
-	    UVM_KMF_WIRED);
+	    UVM_KMF_WIRED|UVM_KMF_ZERO);
 	if (redzone_const_or_false(true)) {
 		pmap_kremove(istack, PAGE_SIZE);
 		pmap_kremove(istack + INTRSTACKSIZE + PAGE_SIZE, PAGE_SIZE);
 		pmap_update(pmap_kernel());
 	}
-	/* 33 used to be 1.  Arbitrarily reserve 32 more register_t's
+
+	/*
+	 * 33 used to be 1.  Arbitrarily reserve 32 more register_t's
 	 * of space for ddb(4) to examine some subroutine arguments
 	 * and to hunt for the next stack frame.
 	 */
 	ci->ci_intrstack = (char *)istack + redzone_const_or_zero(PAGE_SIZE) +
 	    INTRSTACKSIZE - 33 * sizeof(register_t);
-#if defined(__x86_64__)
-	ci->ci_tss->tss.tss_ist[0] = (uintptr_t)ci->ci_intrstack & ~0xf;
-#endif /* defined(__x86_64__) */
-#endif /* defined(INTRSTACKSIZE) */
+#endif
+
 	ci->ci_idepth = -1;
 }
 
@@ -1655,7 +1658,7 @@ intr_redistribute(struct cpu_info *oci)
 	where = xc_unicast(0, intr_redistribute_xc_t, isp,
 	    (void *)(intptr_t)nslot, nci);
 	xc_wait(where);
-	
+
 	/*
 	 * We're ready to go on the target CPU.  Run a cross call to
 	 * reroute the interrupt away from the source CPU.

Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.245.6.4 src/sys/arch/x86/x86/pmap.c:1.245.6.5
--- src/sys/arch/x86/x86/pmap.c:1.245.6.4	Tue Mar 13 15:47:45 2018
+++ src/sys/arch/x86/x86/pmap.c	Fri Mar 16 13:17:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.245.6.4 2018/03/13 15:47:45 martin Exp $	*/
+/*	$NetBSD: pmap.c,v 1.245.6.5 2018/03/16 13:17:56 martin Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2010, 2016, 2017 The NetBSD Foundation, Inc.
@@ -171,7 +171,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.245.6.4 2018/03/13 15:47:45 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.245.6.5 2018/03/16 13:17:56 martin Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -323,6 +323,8 @@ long nkptp[] = NKPTP_INITIALIZER;
 struct pmap_head pmaps;
 kmutex_t pmaps_lock;
 
+struct pcpu_area *pcpuarea __read_mostly;
+
 static vaddr_t pmap_maxkvaddr;
 
 /*
@@ -542,6 +544,9 @@ extern vaddr_t pentium_idt_vaddr;
  * Local prototypes
  */
 
+#ifdef __HAVE_PCPU_AREA
+static void pmap_init_pcpu(void);
+#endif
 #ifdef __HAVE_DIRECT_MAP
 static void pmap_init_directmap(struct pmap *);
 #endif
@@ -1316,6 +1321,10 @@ pmap_bootstrap(vaddr_t kva_start)
 	pmap_init_lapic();
 #endif /* !XEN */
 
+#ifdef __HAVE_PCPU_AREA
+	pmap_init_pcpu();
+#endif
+
 #ifdef __HAVE_DIRECT_MAP
 	pmap_init_directmap(kpm);
 #else
@@ -1365,13 +1374,21 @@ pmap_bootstrap(vaddr_t kva_start)
 	/*
 	 * Allocate space for the IDT, GDT and LDT.
 	 */
+#ifdef __HAVE_PCPU_AREA
+	idt_vaddr = (vaddr_t)&pcpuarea->idt;
+#else
 	idt_vaddr = pmap_bootstrap_valloc(1);
+#endif
 	idt_paddr = pmap_bootstrap_palloc(1);
 
 	gdt_vaddr = pmap_bootstrap_valloc(1);
 	gdt_paddr = pmap_bootstrap_palloc(1);
 
+#ifdef __HAVE_PCPU_AREA
+	ldt_vaddr = (vaddr_t)&pcpuarea->ldt;
+#else
 	ldt_vaddr = pmap_bootstrap_valloc(1);
+#endif
 	ldt_paddr = pmap_bootstrap_palloc(1);
 
 #if !defined(__x86_64__) && !defined(XEN)
@@ -1427,6 +1444,103 @@ pmap_init_lapic(void)
 }
 #endif
 
+#ifdef __HAVE_PCPU_AREA
+static size_t
+pmap_pagetree_nentries_range(vaddr_t startva, vaddr_t endva, size_t pgsz)
+{
+	size_t npages;
+	npages = (roundup(endva, pgsz) / pgsz) -
+	    (rounddown(startva, pgsz) / pgsz);
+	return npages;
+}
+
+static void
+pmap_init_pcpu(void)
+{
+	const vaddr_t startva = PMAP_PCPU_BASE;
+	size_t nL4e, nL3e, nL2e, nL1e;
+	size_t L4e_idx, L3e_idx, L2e_idx, L1e_idx __diagused;
+	paddr_t pa;
+	vaddr_t endva;
+	vaddr_t tmpva;
+	pt_entry_t *pte;
+	size_t size;
+	int i;
+
+	const pd_entry_t pteflags = PG_V | PG_KW | pmap_pg_nx;
+
+	size = sizeof(struct pcpu_area);
+
+	endva = startva + size;
+
+	/* We will use this temporary va. */
+	tmpva = (KERNBASE + NKL2_KIMG_ENTRIES * NBPD_L2);
+	pte = PTE_BASE + pl1_i(tmpva);
+
+	/* Build L4 */
+	L4e_idx = pl4_i(startva);
+	nL4e = pmap_pagetree_nentries_range(startva, endva, NBPD_L4);
+	KASSERT(nL4e  == 1);
+	for (i = 0; i < nL4e; i++) {
+		KASSERT(L4_BASE[L4e_idx+i] == 0);
+
+		pa = pmap_bootstrap_palloc(1);
+		*pte = (pa & PG_FRAME) | pteflags;
+		pmap_update_pg(tmpva);
+		memset((void *)tmpva, 0, PAGE_SIZE);
+
+		L4_BASE[L4e_idx+i] = pa | pteflags | PG_U;
+	}
+
+	/* Build L3 */
+	L3e_idx = pl3_i(startva);
+	nL3e = pmap_pagetree_nentries_range(startva, endva, NBPD_L3);
+	for (i = 0; i < nL3e; i++) {
+		KASSERT(L3_BASE[L3e_idx+i] == 0);
+
+		pa = pmap_bootstrap_palloc(1);
+		*pte = (pa & PG_FRAME) | pteflags;
+		pmap_update_pg(tmpva);
+		memset((void *)tmpva, 0, PAGE_SIZE);
+
+		L3_BASE[L3e_idx+i] = pa | pteflags | PG_U;
+	}
+
+	/* Build L2 */
+	L2e_idx = pl2_i(startva);
+	nL2e = pmap_pagetree_nentries_range(startva, endva, NBPD_L2);
+	for (i = 0; i < nL2e; i++) {
+
+		KASSERT(L2_BASE[L2e_idx+i] == 0);
+
+		pa = pmap_bootstrap_palloc(1);
+		*pte = (pa & PG_FRAME) | pteflags;
+		pmap_update_pg(tmpva);
+		memset((void *)tmpva, 0, PAGE_SIZE);
+
+		L2_BASE[L2e_idx+i] = pa | pteflags | PG_U;
+	}
+
+	/* Build L1 */
+	L1e_idx = pl1_i(startva);
+	nL1e = pmap_pagetree_nentries_range(startva, endva, NBPD_L1);
+	for (i = 0; i < nL1e; i++) {
+		/*
+		 * Nothing to do, the PTEs will be entered via
+		 * pmap_kenter_pa.
+		 */
+		KASSERT(L1_BASE[L1e_idx+i] == 0);
+	}
+
+	*pte = 0;
+	pmap_update_pg(tmpva);
+
+	pcpuarea = (struct pcpu_area *)startva;
+
+	tlbflush();
+}
+#endif
+
 #ifdef __HAVE_DIRECT_MAP
 /*
  * Create the amd64 direct map. Called only once at boot time.
@@ -2168,6 +2282,9 @@ pmap_pdp_ctor(void *arg, void *v, int fl
 		pdir[idx] = PDP_BASE[idx];
 	}
 
+#ifdef __HAVE_PCPU_AREA
+	pdir[PDIR_SLOT_PCPU] = PDP_BASE[PDIR_SLOT_PCPU];
+#endif
 #ifdef __HAVE_DIRECT_MAP
 	pdir[PDIR_SLOT_DIRECT] = PDP_BASE[PDIR_SLOT_DIRECT];
 #endif

Reply via email to