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(®ion, ci->ci_gdt, (uint16_t)(MAXGDTSIZ - 1));
-#else
setregion(®ion, ci->ci_gdt, (uint16_t)(gdt_size - 1));
-#endif
lgdt(®ion);
}
#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