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