Module Name: src
Committed By: yamaguchi
Date: Tue Jul 14 00:45:53 UTC 2020
Modified Files:
src/sys/arch/amd64/amd64: db_interface.c machdep.c
src/sys/arch/amd64/conf: ALL
src/sys/arch/amd64/include: segments.h
src/sys/arch/i386/conf: ALL
src/sys/arch/i386/i386: db_interface.c machdep.c trap.c
src/sys/arch/i386/include: segments.h
src/sys/arch/x86/conf: files.x86
src/sys/arch/x86/include: cpu.h cpuvar.h pmap.h
src/sys/arch/x86/x86: cpu.c hyperv.c idt.c intr.c lapic.c pmap.c svs.c
src/sys/arch/xen/x86: cpu.c
src/sys/arch/xen/xen: hypervisor.c
src/sys/dev/hyperv: vmbusvar.h
src/sys/dev/nvmm/x86: nvmm_x86_vmx.c
Log Message:
Introduce per-cpu IDTs
This is realized by following modifications:
- Add IDT pages and its allocation maps for each cpu in "struct cpu_info"
- Load per-cpu IDTs at cpu_init_idt(struct cpu_info*)
- Copy the IDT entries for cpu0 to other CPUs at attach
- These are, for example, exceptions, db, system calls, etc.
And, added a kernel option named PCPU_IDT to enable the feature.
To generate a diff of this commit:
cvs rdiff -u -r1.37 -r1.38 src/sys/arch/amd64/amd64/db_interface.c
cvs rdiff -u -r1.355 -r1.356 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.155 -r1.156 src/sys/arch/amd64/conf/ALL
cvs rdiff -u -r1.36 -r1.37 src/sys/arch/amd64/include/segments.h
cvs rdiff -u -r1.493 -r1.494 src/sys/arch/i386/conf/ALL
cvs rdiff -u -r1.84 -r1.85 src/sys/arch/i386/i386/db_interface.c
cvs rdiff -u -r1.830 -r1.831 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.303 -r1.304 src/sys/arch/i386/i386/trap.c
cvs rdiff -u -r1.68 -r1.69 src/sys/arch/i386/include/segments.h
cvs rdiff -u -r1.116 -r1.117 src/sys/arch/x86/conf/files.x86
cvs rdiff -u -r1.126 -r1.127 src/sys/arch/x86/include/cpu.h
cvs rdiff -u -r1.52 -r1.53 src/sys/arch/x86/include/cpuvar.h
cvs rdiff -u -r1.123 -r1.124 src/sys/arch/x86/include/pmap.h
cvs rdiff -u -r1.194 -r1.195 src/sys/arch/x86/x86/cpu.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/x86/x86/hyperv.c
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/x86/x86/idt.c
cvs rdiff -u -r1.151 -r1.152 src/sys/arch/x86/x86/intr.c
cvs rdiff -u -r1.83 -r1.84 src/sys/arch/x86/x86/lapic.c
cvs rdiff -u -r1.399 -r1.400 src/sys/arch/x86/x86/pmap.c
cvs rdiff -u -r1.37 -r1.38 src/sys/arch/x86/x86/svs.c
cvs rdiff -u -r1.138 -r1.139 src/sys/arch/xen/x86/cpu.c
cvs rdiff -u -r1.86 -r1.87 src/sys/arch/xen/xen/hypervisor.c
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/hyperv/vmbusvar.h
cvs rdiff -u -r1.61 -r1.62 src/sys/dev/nvmm/x86/nvmm_x86_vmx.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/db_interface.c
diff -u src/sys/arch/amd64/amd64/db_interface.c:1.37 src/sys/arch/amd64/amd64/db_interface.c:1.38
--- src/sys/arch/amd64/amd64/db_interface.c:1.37 Sat Feb 29 15:00:28 2020
+++ src/sys/arch/amd64/amd64/db_interface.c Tue Jul 14 00:45:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.37 2020/02/29 15:00:28 christos Exp $ */
+/* $NetBSD: db_interface.c,v 1.38 2020/07/14 00:45:52 yamaguchi Exp $ */
/*
* Mach Operating System
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.37 2020/02/29 15:00:28 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.38 2020/07/14 00:45:52 yamaguchi Exp $");
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
@@ -111,12 +111,14 @@ db_machine_init(void)
#ifdef MULTIPROCESSOR
#ifndef XENPV
+ struct idt_vec *iv = &(cpu_info_primary.ci_idtvec);
vector *handler = &Xintr_ddbipi;
+ idt_descriptor_t *idt = iv->iv_idt;
#if NLAPIC > 0
if (lapic_is_x2apic())
handler = &Xintr_x2apic_ddbipi;
#endif
- ddb_vec = idt_vec_alloc(0xf0, 0xff);
+ ddb_vec = idt_vec_alloc(iv, 0xf0, 0xff);
set_idtgate(&idt[ddb_vec], handler, 1, SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
#else
Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.355 src/sys/arch/amd64/amd64/machdep.c:1.356
--- src/sys/arch/amd64/amd64/machdep.c:1.355 Sun May 10 06:30:57 2020
+++ src/sys/arch/amd64/amd64/machdep.c Tue Jul 14 00:45:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.355 2020/05/10 06:30:57 maxv Exp $ */
+/* $NetBSD: machdep.c,v 1.356 2020/07/14 00:45:52 yamaguchi Exp $ */
/*
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -110,7 +110,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.355 2020/05/10 06:30:57 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.356 2020/07/14 00:45:52 yamaguchi Exp $");
#include "opt_modular.h"
#include "opt_user_ldt.h"
@@ -1392,11 +1392,15 @@ char *ldtstore;
char *gdtstore;
void
-setgate(struct gate_descriptor *gd, void *func, int ist, int type, int dpl, int sel)
+setgate(struct gate_descriptor *gd, void *func,
+ int ist, int type, int dpl, int sel)
{
+ vaddr_t vaddr;
+
+ vaddr = ((vaddr_t)gd) & ~PAGE_MASK;
kpreempt_disable();
- pmap_changeprot_local(idt_vaddr, VM_PROT_READ|VM_PROT_WRITE);
+ pmap_changeprot_local(vaddr, VM_PROT_READ|VM_PROT_WRITE);
gd->gd_looffset = (uint64_t)func & 0xffff;
gd->gd_selector = sel;
@@ -1410,20 +1414,23 @@ setgate(struct gate_descriptor *gd, void
gd->gd_xx2 = 0;
gd->gd_xx3 = 0;
- pmap_changeprot_local(idt_vaddr, VM_PROT_READ);
+ pmap_changeprot_local(vaddr, VM_PROT_READ);
kpreempt_enable();
}
void
unsetgate(struct gate_descriptor *gd)
{
+ vaddr_t vaddr;
+
+ vaddr = ((vaddr_t)gd) & ~PAGE_MASK;
kpreempt_disable();
- pmap_changeprot_local(idt_vaddr, VM_PROT_READ|VM_PROT_WRITE);
+ pmap_changeprot_local(vaddr, VM_PROT_READ|VM_PROT_WRITE);
memset(gd, 0, sizeof (*gd));
- pmap_changeprot_local(idt_vaddr, VM_PROT_READ);
+ pmap_changeprot_local(vaddr, VM_PROT_READ);
kpreempt_enable();
}
@@ -1470,10 +1477,12 @@ set_sys_segment(struct sys_segment_descr
}
void
-cpu_init_idt(void)
+cpu_init_idt(struct cpu_info *ci)
{
struct region_descriptor region;
+ idt_descriptor_t *idt;
+ idt = ci->ci_idtvec.iv_idt;
setregion(®ion, idt, NIDT * sizeof(idt[0]) - 1);
lidt(®ion);
}
@@ -1677,6 +1686,8 @@ init_x86_64(paddr_t first_avail)
extern void consinit(void);
struct region_descriptor region;
struct mem_segment_descriptor *ldt_segp;
+ struct idt_vec *iv;
+ idt_descriptor_t *idt;
int x;
struct pcb *pcb;
extern vaddr_t lwp0uarea;
@@ -1807,7 +1818,9 @@ init_x86_64(paddr_t first_avail)
pmap_update(pmap_kernel());
- idt = (idt_descriptor_t *)idt_vaddr;
+ iv = &(cpu_info_primary.ci_idtvec);
+ idt_vec_init_cpu_md(iv, cpu_index(&cpu_info_primary));
+ idt = iv->iv_idt;
gdtstore = (char *)gdt_vaddr;
ldtstore = (char *)ldt_vaddr;
@@ -1872,7 +1885,7 @@ init_x86_64(paddr_t first_avail)
sel = SEL_KPL;
ist = 0;
- idt_vec_reserve(x);
+ idt_vec_reserve(iv, x);
switch (x) {
case 1: /* DB */
@@ -1902,7 +1915,7 @@ init_x86_64(paddr_t first_avail)
}
/* new-style interrupt gate for syscalls */
- idt_vec_reserve(128);
+ idt_vec_reserve(iv, 128);
set_idtgate(&idt[128], &IDTVEC(osyscall), 0, SDT_SYS386IGT, SEL_UPL,
GSEL(GCODE_SEL, SEL_KPL));
@@ -1920,7 +1933,7 @@ init_x86_64(paddr_t first_avail)
panic("HYPERVISOR_set_callbacks() failed");
#endif /* XENPV */
- cpu_init_idt();
+ cpu_init_idt(&cpu_info_primary);
#ifdef XENPV
xen_init_ksyms();
@@ -1961,6 +1974,14 @@ init_x86_64(paddr_t first_avail)
void
cpu_reset(void)
{
+#ifndef XENPV
+ idt_descriptor_t *idt;
+ vaddr_t vaddr;
+
+ idt = cpu_info_primary.ci_idtvec.iv_idt;
+ vaddr = (vaddr_t)idt;
+#endif
+
x86_disable_intr();
#ifdef XENPV
@@ -1974,7 +1995,7 @@ cpu_reset(void)
* invalid and causing a fault.
*/
kpreempt_disable();
- pmap_changeprot_local(idt_vaddr, VM_PROT_READ|VM_PROT_WRITE);
+ pmap_changeprot_local(vaddr, VM_PROT_READ|VM_PROT_WRITE);
memset((void *)idt, 0, NIDT * sizeof(idt[0]));
kpreempt_enable();
breakpoint();
@@ -2321,3 +2342,56 @@ mm_md_direct_mapped_phys(paddr_t paddr,
return false;
#endif
}
+
+static void
+idt_vec_copy(struct idt_vec *dst, struct idt_vec *src)
+{
+ idt_descriptor_t *idt_dst;
+
+ idt_dst = dst->iv_idt;
+
+ kpreempt_disable();
+ pmap_changeprot_local((vaddr_t)idt_dst, VM_PROT_READ|VM_PROT_WRITE);
+
+ memcpy(idt_dst, src->iv_idt, PAGE_SIZE);
+ memcpy(dst->iv_allocmap, src->iv_allocmap, sizeof(dst->iv_allocmap));
+
+ pmap_changeprot_local((vaddr_t)idt_dst, VM_PROT_READ);
+ kpreempt_enable();
+}
+
+void
+idt_vec_init_cpu_md(struct idt_vec *iv, cpuid_t cid)
+{
+ vaddr_t va;
+
+ if (cid != cpu_index(&cpu_info_primary) &&
+ idt_vec_is_pcpu()) {
+#ifdef __HAVE_PCPU_AREA
+ va = (vaddr_t)&pcpuarea->ent[cid].idt;
+#else
+ struct vm_page *pg;
+
+ va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
+ UVM_KMF_VAONLY);
+ pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
+ if (pg == NULL) {
+ panic("failed to allocate a page for IDT");
+ }
+ pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ|VM_PROT_WRITE, 0);
+ pmap_update(pmap_kernel());
+#endif
+
+ memset((void *)va, 0, PAGE_SIZE);
+#ifndef XENPV
+ pmap_changeprot_local(va, VM_PROT_READ);
+#endif
+ pmap_update(pmap_kernel());
+
+ iv->iv_idt = (void *)va;
+ idt_vec_copy(iv, &(cpu_info_primary.ci_idtvec));
+ } else {
+ iv->iv_idt = (void *)idt_vaddr;
+ }
+}
Index: src/sys/arch/amd64/conf/ALL
diff -u src/sys/arch/amd64/conf/ALL:1.155 src/sys/arch/amd64/conf/ALL:1.156
--- src/sys/arch/amd64/conf/ALL:1.155 Mon Jun 29 23:58:44 2020
+++ src/sys/arch/amd64/conf/ALL Tue Jul 14 00:45:52 2020
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.155 2020/06/29 23:58:44 riastradh Exp $
+# $NetBSD: ALL,v 1.156 2020/07/14 00:45:52 yamaguchi Exp $
# From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
#
# ALL machine description file
@@ -17,7 +17,7 @@ include "arch/amd64/conf/std.amd64"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "ALL-$Revision: 1.155 $"
+#ident "ALL-$Revision: 1.156 $"
maxusers 64 # estimated number of users
@@ -29,6 +29,7 @@ options X86EMU # 386 Real Mode emulato
#options PAE # PAE mode (36 bits physical addressing)
makeoptions SPECTRE_V2_GCC_MITIGATION=1 # GCC Spectre variant 2
# migitation
+options PCPU_IDT # Per CPU IDT
# CPU features
acpicpu* at cpu? # ACPI CPU (including frequency scaling)
Index: src/sys/arch/amd64/include/segments.h
diff -u src/sys/arch/amd64/include/segments.h:1.36 src/sys/arch/amd64/include/segments.h:1.37
--- src/sys/arch/amd64/include/segments.h:1.36 Mon Feb 11 14:59:32 2019
+++ src/sys/arch/amd64/include/segments.h Tue Jul 14 00:45:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: segments.h,v 1.36 2019/02/11 14:59:32 cherry Exp $ */
+/* $NetBSD: segments.h,v 1.37 2020/07/14 00:45:52 yamaguchi Exp $ */
/*
* Copyright (c) 1990 The Regents of the University of California.
@@ -238,7 +238,6 @@ typedef struct trap_info idt_descriptor_
#else
typedef struct gate_descriptor idt_descriptor_t;
#endif /* XENPV */
-extern idt_descriptor_t *idt;
extern char *gdtstore;
extern char *ldtstore;
@@ -251,14 +250,16 @@ void set_sys_segment(struct sys_segment_
int, int, int);
void set_mem_segment(struct mem_segment_descriptor *, void *, size_t,
int, int, int, int, int);
-void cpu_init_idt(void);
void update_descriptor(void *, void *);
-
-void idt_vec_reserve(int);
-int idt_vec_alloc(int, int);
-void idt_vec_set(int, void (*)(void));
-void idt_vec_free(int);
+struct idt_vec;
+void idt_vec_reserve(struct idt_vec *, int);
+int idt_vec_alloc(struct idt_vec *, int, int);
+void idt_vec_set(struct idt_vec *, int, void (*)(void));
+void idt_vec_free(struct idt_vec *, int);
+void idt_vec_init_cpu_md(struct idt_vec *, cpuid_t);
+bool idt_vec_is_pcpu(void);
+struct idt_vec * idt_vec_ref(struct idt_vec *);
struct lwp;
Index: src/sys/arch/i386/conf/ALL
diff -u src/sys/arch/i386/conf/ALL:1.493 src/sys/arch/i386/conf/ALL:1.494
--- src/sys/arch/i386/conf/ALL:1.493 Mon May 25 07:20:15 2020
+++ src/sys/arch/i386/conf/ALL Tue Jul 14 00:45:52 2020
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.493 2020/05/25 07:20:15 yamaguchi Exp $
+# $NetBSD: ALL,v 1.494 2020/07/14 00:45:52 yamaguchi Exp $
# From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
#
# ALL machine description file
@@ -17,7 +17,7 @@ include "arch/i386/conf/std.i386"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "ALL-$Revision: 1.493 $"
+#ident "ALL-$Revision: 1.494 $"
maxusers 64 # estimated number of users
@@ -29,6 +29,7 @@ options X86EMU # 386 Real Mode emulato
options PAE # PAE mode (36 bits physical addressing)
makeoptions SPECTRE_V2_GCC_MITIGATION=1 # GCC Spectre variant 2
# migitation
+options PCPU_IDT # Per CPU IDT
# CPU features
acpicpu* at cpu? # ACPI CPU (including frequency scaling)
Index: src/sys/arch/i386/i386/db_interface.c
diff -u src/sys/arch/i386/i386/db_interface.c:1.84 src/sys/arch/i386/i386/db_interface.c:1.85
--- src/sys/arch/i386/i386/db_interface.c:1.84 Thu Feb 14 07:12:40 2019
+++ src/sys/arch/i386/i386/db_interface.c Tue Jul 14 00:45:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.84 2019/02/14 07:12:40 cherry Exp $ */
+/* $NetBSD: db_interface.c,v 1.85 2020/07/14 00:45:52 yamaguchi Exp $ */
/*
* Mach Operating System
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.84 2019/02/14 07:12:40 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.85 2020/07/14 00:45:52 yamaguchi Exp $");
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
@@ -114,12 +114,15 @@ db_machine_init(void)
#ifdef MULTIPROCESSOR
#ifndef XENPV
vector *handler = &Xintr_ddbipi;
+ struct idt_vec *iv;
+
+ iv = &(cpu_info_primary.ci_idtvec);
#if NLAPIC > 0
if (lapic_is_x2apic())
handler = &Xintr_x2apic_ddbipi;
#endif
- ddb_vec = idt_vec_alloc(0xf0, 0xff);
- idt_vec_set(ddb_vec, handler);
+ ddb_vec = idt_vec_alloc(iv, 0xf0, 0xff);
+ idt_vec_set(iv, ddb_vec, handler);
#else
/* Initialised as part of xen_ipi_init() */
#endif /* XENPV */
Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.830 src/sys/arch/i386/i386/machdep.c:1.831
--- src/sys/arch/i386/i386/machdep.c:1.830 Fri May 8 00:52:29 2020
+++ src/sys/arch/i386/i386/machdep.c Tue Jul 14 00:45:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.830 2020/05/08 00:52:29 riastradh Exp $ */
+/* $NetBSD: machdep.c,v 1.831 2020/07/14 00:45:52 yamaguchi Exp $ */
/*
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009, 2017
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.830 2020/05/08 00:52:29 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.831 2020/07/14 00:45:52 yamaguchi Exp $");
#include "opt_beep.h"
#include "opt_compat_freebsd.h"
@@ -554,6 +554,7 @@ cpu_set_tss_gates(struct cpu_info *ci)
{
struct segment_descriptor sd;
void *doubleflt_stack;
+ idt_descriptor_t *idt;
doubleflt_stack = (void *)uvm_km_alloc(kernel_map, USPACE, 0,
UVM_KMF_WIRED);
@@ -563,6 +564,7 @@ cpu_set_tss_gates(struct cpu_info *ci)
SDT_SYS386TSS, SEL_KPL, 0, 0);
ci->ci_gdt[GTRAPTSS_SEL].sd = sd;
+ idt = cpu_info_primary.ci_idtvec.iv_idt;
set_idtgate(&idt[8], NULL, 0, SDT_SYSTASKGT, SEL_KPL,
GSEL(GTRAPTSS_SEL, SEL_KPL));
@@ -906,6 +908,7 @@ setgate(struct gate_descriptor *gd, void
void
unsetgate(struct gate_descriptor *gd)
{
+
gd->gd_p = 0;
gd->gd_hioffset = 0;
gd->gd_looffset = 0;
@@ -949,10 +952,15 @@ extern union descriptor tmpgdt[];
#endif
void
-cpu_init_idt(void)
+cpu_init_idt(struct cpu_info *ci)
{
struct region_descriptor region;
- setregion(®ion, pentium_idt, NIDT * sizeof(idt[0]) - 1);
+ struct idt_vec *iv;
+ idt_descriptor_t *idt;
+
+ iv = &ci->ci_idtvec;
+ idt = iv->iv_idt_pentium;
+ setregion(®ion, idt, NIDT * sizeof(idt[0]) - 1);
lidt(®ion);
}
@@ -1134,6 +1142,8 @@ init386(paddr_t first_avail)
#endif
#endif /* !XENPV */
struct pcb *pcb;
+ struct idt_vec *iv;
+ idt_descriptor_t *idt;
KASSERT(first_avail % PAGE_SIZE == 0);
@@ -1305,8 +1315,9 @@ init386(paddr_t first_avail)
pmap_kenter_pa(pentium_idt_vaddr, idt_paddr, VM_PROT_READ, 0);
pmap_update(pmap_kernel());
- pentium_idt = (union descriptor *)pentium_idt_vaddr;
- idt = (idt_descriptor_t *)idt_vaddr;
+ iv = &(cpu_info_primary.ci_idtvec);
+ idt_vec_init_cpu_md(iv, cpu_index(&cpu_info_primary));
+ idt = (idt_descriptor_t *)iv->iv_idt;
#ifndef XENPV
tgdt = gdtstore;
@@ -1340,7 +1351,7 @@ init386(paddr_t first_avail)
sel = SEL_KPL;
#endif /* XENPV */
- idt_vec_reserve(x);
+ idt_vec_reserve(iv, x);
switch (x) {
#ifdef XENPV
@@ -1361,7 +1372,7 @@ init386(paddr_t first_avail)
}
/* new-style interrupt gate for syscalls */
- idt_vec_reserve(128);
+ idt_vec_reserve(iv, 128);
set_idtgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386IGT, SEL_UPL,
GSEL(GCODE_SEL, SEL_KPL));
@@ -1371,7 +1382,7 @@ init386(paddr_t first_avail)
#endif
lldt(GSEL(GLDT_SEL, SEL_KPL));
- cpu_init_idt();
+ cpu_init_idt(&cpu_info_primary);
#ifdef XENPV
xen_init_ksyms();
@@ -1441,7 +1452,9 @@ cpu_reset(void)
for (;;);
#else /* XENPV */
struct region_descriptor region;
+ idt_descriptor_t *idt;
+ idt = (idt_descriptor_t *)cpu_info_primary.ci_idtvec.iv_idt;
x86_disable_intr();
/*
@@ -1698,3 +1711,50 @@ cpu_alloc_l3_page(struct cpu_info *ci)
pmap_update(pmap_kernel());
}
#endif /* PAE */
+
+static void
+idt_vec_copy(struct idt_vec *dst, struct idt_vec *src)
+{
+ idt_descriptor_t *idt_dst;
+
+ idt_dst = dst->iv_idt;
+ memcpy(idt_dst, src->iv_idt, PAGE_SIZE);
+ memcpy(dst->iv_allocmap, src->iv_allocmap, sizeof(dst->iv_allocmap));
+}
+
+void
+idt_vec_init_cpu_md(struct idt_vec *iv, cpuid_t cid)
+{
+ vaddr_t va_idt, va_pentium_idt;
+ struct vm_page *pg;
+
+ if (idt_vec_is_pcpu() &&
+ cid != cpu_index(&cpu_info_primary)) {
+ va_idt = uvm_km_alloc(kernel_map, PAGE_SIZE,
+ 0, UVM_KMF_VAONLY);
+ pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
+ if (pg == NULL) {
+ panic("failed to allocate pcpu idt PA");
+ }
+ pmap_kenter_pa(va_idt, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ|VM_PROT_WRITE, 0);
+ pmap_update(pmap_kernel());
+
+ memset((void *)va_idt, 0, PAGE_SIZE);
+
+ /* pentium f00f bug stuff */
+ va_pentium_idt = uvm_km_alloc(kernel_map, PAGE_SIZE,
+ 0, UVM_KMF_VAONLY);
+ pmap_kenter_pa(va_pentium_idt, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ, 0);
+ pmap_update(pmap_kernel());
+
+ iv->iv_idt = (void *)va_idt;
+ iv->iv_idt_pentium = (void *)va_pentium_idt;
+
+ idt_vec_copy(iv, &(cpu_info_primary.ci_idtvec));
+ } else {
+ iv->iv_idt = (void *)idt_vaddr;
+ iv->iv_idt_pentium = (void *)pentium_idt_vaddr;
+ }
+}
Index: src/sys/arch/i386/i386/trap.c
diff -u src/sys/arch/i386/i386/trap.c:1.303 src/sys/arch/i386/i386/trap.c:1.304
--- src/sys/arch/i386/i386/trap.c:1.303 Thu Nov 21 19:24:00 2019
+++ src/sys/arch/i386/i386/trap.c Tue Jul 14 00:45:52 2020
@@ -1,5 +1,5 @@
-/* $NetBSD: trap.c,v 1.303 2019/11/21 19:24:00 ad Exp $ */
+/* $NetBSD: trap.c,v 1.304 2020/07/14 00:45:52 yamaguchi Exp $ */
/*-
* Copyright (c) 1998, 2000, 2005, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.303 2019/11/21 19:24:00 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.304 2020/07/14 00:45:52 yamaguchi Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -245,10 +245,16 @@ int
ss_shadow(struct trapframe *tf)
{
struct gate_descriptor *gd;
+ struct cpu_info *ci;
+ struct idt_vec *iv;
+ idt_descriptor_t *idt;
uintptr_t eip, func;
size_t i;
eip = tf->tf_eip;
+ ci = curcpu();
+ iv = idt_vec_ref(&ci->ci_idtvec);
+ idt = iv->iv_idt;
for (i = 0; i < 256; i++) {
gd = &idt[i];
Index: src/sys/arch/i386/include/segments.h
diff -u src/sys/arch/i386/include/segments.h:1.68 src/sys/arch/i386/include/segments.h:1.69
--- src/sys/arch/i386/include/segments.h:1.68 Mon Feb 11 14:59:32 2019
+++ src/sys/arch/i386/include/segments.h Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: segments.h,v 1.68 2019/02/11 14:59:32 cherry Exp $ */
+/* $NetBSD: segments.h,v 1.69 2020/07/14 00:45:53 yamaguchi Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -196,7 +196,6 @@ typedef struct trap_info idt_descriptor_
#else
typedef struct gate_descriptor idt_descriptor_t;
#endif /* XENPV */
-extern idt_descriptor_t *idt;
extern union descriptor *gdtstore, *ldtstore;
void setgate(struct gate_descriptor *, void *, int, int, int, int);
@@ -206,15 +205,16 @@ void setregion(struct region_descriptor
void setsegment(struct segment_descriptor *, const void *, size_t, int, int,
int, int);
void unsetgate(struct gate_descriptor *);
-
-void cpu_init_idt(void);
void update_descriptor(union descriptor *, union descriptor *);
-
-void idt_vec_reserve(int);
-int idt_vec_alloc(int, int);
-void idt_vec_set(int, void (*)(void));
-void idt_vec_free(int);
+struct idt_vec;
+void idt_vec_reserve(struct idt_vec *, int);
+int idt_vec_alloc(struct idt_vec *, int, int);
+void idt_vec_set(struct idt_vec *, int, void (*)(void));
+void idt_vec_free(struct idt_vec *, int);
+void idt_vec_init_cpu_md(struct idt_vec *, cpuid_t);
+bool idt_vec_is_pcpu(void);
+struct idt_vec* idt_vec_ref(struct idt_vec *);
#endif /* _KERNEL */
Index: src/sys/arch/x86/conf/files.x86
diff -u src/sys/arch/x86/conf/files.x86:1.116 src/sys/arch/x86/conf/files.x86:1.117
--- src/sys/arch/x86/conf/files.x86:1.116 Mon Jun 29 23:51:35 2020
+++ src/sys/arch/x86/conf/files.x86 Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-# $NetBSD: files.x86,v 1.116 2020/06/29 23:51:35 riastradh Exp $
+# $NetBSD: files.x86,v 1.117 2020/07/14 00:45:53 yamaguchi Exp $
# options for MP configuration through the MP spec
defflag opt_mpbios.h MPBIOS MPDEBUG MPBIOS_SCANPCI
@@ -22,6 +22,8 @@ defflag opt_kaslr.h NO_X86_ASLR
defflag SVS
+defflag PCPU_IDT
+
define cpubus { [apid = -1] }
define cpufeaturebus {}
define ioapicbus { [apid = -1] }
Index: src/sys/arch/x86/include/cpu.h
diff -u src/sys/arch/x86/include/cpu.h:1.126 src/sys/arch/x86/include/cpu.h:1.127
--- src/sys/arch/x86/include/cpu.h:1.126 Fri Jun 19 16:20:22 2020
+++ src/sys/arch/x86/include/cpu.h Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.126 2020/06/19 16:20:22 maxv Exp $ */
+/* $NetBSD: cpu.h,v 1.127 2020/07/14 00:45:53 yamaguchi Exp $ */
/*
* Copyright (c) 1990 The Regents of the University of California.
@@ -103,6 +103,12 @@ struct clockframe {
struct intrframe cf_if;
};
+struct idt_vec {
+ void *iv_idt;
+ void *iv_idt_pentium;
+ char iv_allocmap[NIDT];
+};
+
/*
* a bunch of this belongs in cpuvar.h; move it later..
*/
@@ -126,6 +132,7 @@ struct cpu_info {
uint64_t ci_scratch;
uintptr_t ci_pmap_data[128 / sizeof(uintptr_t)];
struct kcpuset *ci_tlb_cpuset;
+ struct idt_vec ci_idtvec;
int ci_kfpu_spl;
Index: src/sys/arch/x86/include/cpuvar.h
diff -u src/sys/arch/x86/include/cpuvar.h:1.52 src/sys/arch/x86/include/cpuvar.h:1.53
--- src/sys/arch/x86/include/cpuvar.h:1.52 Sat Apr 25 15:26:18 2020
+++ src/sys/arch/x86/include/cpuvar.h Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpuvar.h,v 1.52 2020/04/25 15:26:18 bouyer Exp $ */
+/* $NetBSD: cpuvar.h,v 1.53 2020/07/14 00:45:53 yamaguchi Exp $ */
/*-
* Copyright (c) 2000, 2007 The NetBSD Foundation, Inc.
@@ -112,6 +112,7 @@ void identifycpu_cpuids(struct cpu_info
void cpu_init(struct cpu_info *);
void cpu_init_tss(struct cpu_info *);
void cpu_init_first(void);
+void cpu_init_idt(struct cpu_info *);
void x86_cpu_idle_init(void);
void x86_cpu_idle_halt(void);
Index: src/sys/arch/x86/include/pmap.h
diff -u src/sys/arch/x86/include/pmap.h:1.123 src/sys/arch/x86/include/pmap.h:1.124
--- src/sys/arch/x86/include/pmap.h:1.123 Wed Jun 24 18:09:37 2020
+++ src/sys/arch/x86/include/pmap.h Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.123 2020/06/24 18:09:37 maxv Exp $ */
+/* $NetBSD: pmap.h,v 1.124 2020/07/14 00:45:53 yamaguchi Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -198,6 +198,7 @@ extern struct slotspace slotspace;
struct pcpu_entry {
uint8_t gdt[MAXGDTSIZ];
uint8_t ldt[MAX_USERLDT_SIZE];
+ uint8_t idt[PAGE_SIZE];
uint8_t tss[PAGE_SIZE];
uint8_t ist0[PAGE_SIZE];
uint8_t ist1[PAGE_SIZE];
@@ -210,7 +211,6 @@ struct pcpu_area {
#ifdef SVS
uint8_t utls[PAGE_SIZE];
#endif
- uint8_t idt[PAGE_SIZE];
uint8_t ldt[PAGE_SIZE];
struct pcpu_entry ent[MAXCPUS];
} __packed;
Index: src/sys/arch/x86/x86/cpu.c
diff -u src/sys/arch/x86/x86/cpu.c:1.194 src/sys/arch/x86/x86/cpu.c:1.195
--- src/sys/arch/x86/x86/cpu.c:1.194 Mon Jun 15 09:09:24 2020
+++ src/sys/arch/x86/x86/cpu.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.194 2020/06/15 09:09:24 msaitoh Exp $ */
+/* $NetBSD: cpu.c,v 1.195 2020/07/14 00:45:53 yamaguchi Exp $ */
/*
* Copyright (c) 2000-2020 NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.194 2020/06/15 09:09:24 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.195 2020/07/14 00:45:53 yamaguchi Exp $");
#include "opt_ddb.h"
#include "opt_mpbios.h" /* for MPDEBUG */
@@ -493,6 +493,7 @@ cpu_attach(device_t parent, device_t sel
* report on an AP
*/
cpu_intr_init(ci);
+ idt_vec_init_cpu_md(&ci->ci_idtvec, cpu_index(ci));
gdt_alloc_cpu(ci);
#ifdef i386
cpu_set_tss_gates(ci);
@@ -978,7 +979,7 @@ cpu_hatch(void *v)
pcb = lwp_getpcb(ci->ci_data.cpu_idlelwp);
lcr0(pcb->pcb_cr0);
- cpu_init_idt();
+ cpu_init_idt(ci);
gdt_init_cpu(ci);
#if NLAPIC > 0
lapic_enable();
Index: src/sys/arch/x86/x86/hyperv.c
diff -u src/sys/arch/x86/x86/hyperv.c:1.10 src/sys/arch/x86/x86/hyperv.c:1.11
--- src/sys/arch/x86/x86/hyperv.c:1.10 Mon Jun 15 09:09:24 2020
+++ src/sys/arch/x86/x86/hyperv.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: hyperv.c,v 1.10 2020/06/15 09:09:24 msaitoh Exp $ */
+/* $NetBSD: hyperv.c,v 1.11 2020/07/14 00:45:53 yamaguchi Exp $ */
/*-
* Copyright (c) 2009-2012,2016-2017 Microsoft Corp.
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
#ifdef __KERNEL_RCSID
-__KERNEL_RCSID(0, "$NetBSD: hyperv.c,v 1.10 2020/06/15 09:09:24 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hyperv.c,v 1.11 2020/07/14 00:45:53 yamaguchi Exp $");
#endif
#ifdef __FBSDID
__FBSDID("$FreeBSD: head/sys/dev/hyperv/vmbus/hyperv.c 331757 2018-03-30 02:25:12Z emaste $");
@@ -95,6 +95,10 @@ struct hyperv_hypercall_ctx {
paddr_t hc_paddr;
};
+struct hyperv_percpu_data {
+ int pd_idtvec;
+};
+
static struct hyperv_hypercall_ctx hyperv_hypercall_ctx;
static char hyperv_hypercall_page[PAGE_SIZE]
@@ -115,8 +119,6 @@ static char hyperv_features_str[256];
static char hyperv_pm_features_str[256];
static char hyperv_features3_str[256];
-static int hyperv_idtvec;
-
uint32_t hyperv_vcpuid[MAXCPUS];
static struct timecounter hyperv_timecounter = {
@@ -756,37 +758,91 @@ void
vmbus_init_interrupts_md(struct vmbus_softc *sc)
{
extern void Xintr_hyperv_hypercall(void);
+ struct vmbus_percpu_data *pd;
+ struct hyperv_percpu_data *hv_pd;
+ struct idt_vec *iv = &(cpu_info_primary.ci_idtvec);
+ cpuid_t cid;
+ if (idt_vec_is_pcpu())
+ return;
/*
* All Hyper-V ISR required resources are setup, now let's find a
* free IDT vector for Hyper-V ISR and set it up.
*/
+ iv = &(cpu_info_primary.ci_idtvec);
+ cid = cpu_index(&cpu_info_primary);
+ pd = &sc->sc_percpu[cid];
+
+ hv_pd = kmem_zalloc(sizeof(*hv_pd), KM_SLEEP);
mutex_enter(&cpu_lock);
- hyperv_idtvec = idt_vec_alloc(APIC_LEVEL(NIPL), IDT_INTR_HIGH);
+ hv_pd->pd_idtvec = idt_vec_alloc(iv,
+ APIC_LEVEL(NIPL), IDT_INTR_HIGH);
mutex_exit(&cpu_lock);
- KASSERT(hyperv_idtvec > 0);
- idt_vec_set(hyperv_idtvec, Xintr_hyperv_hypercall);
+ KASSERT(hv_pd->pd_idtvec > 0);
+ idt_vec_set(iv, hv_pd->pd_idtvec, Xintr_hyperv_hypercall);
+ pd->md_cookie = (void *)hv_pd;
}
void
vmbus_deinit_interrupts_md(struct vmbus_softc *sc)
{
+ struct vmbus_percpu_data *pd;
+ struct hyperv_percpu_data *hv_pd;
+ struct idt_vec *iv;
+ cpuid_t cid;
- if (hyperv_idtvec > 0) {
- idt_vec_free(hyperv_idtvec);
- hyperv_idtvec = 0;
- }
+ if (idt_vec_is_pcpu())
+ return;
+
+ iv = &(cpu_info_primary.ci_idtvec);
+ cid = cpu_index(&cpu_info_primary);
+ pd = &sc->sc_percpu[cid];
+ hv_pd = pd->md_cookie;
+
+ if (hv_pd->pd_idtvec > 0)
+ idt_vec_free(iv, hv_pd->pd_idtvec);
+
+ pd->md_cookie = NULL;
+ kmem_free(hv_pd, sizeof(*hv_pd));
}
void
vmbus_init_synic_md(struct vmbus_softc *sc, cpuid_t cpu)
{
- struct vmbus_percpu_data *pd;
+ extern void Xintr_hyperv_hypercall(void);
+ struct vmbus_percpu_data *pd, *pd0;
+ struct hyperv_percpu_data *hv_pd;
+ struct cpu_info *ci;
+ struct idt_vec *iv;
uint64_t val, orig;
uint32_t sint;
+ int hyperv_idtvec;
pd = &sc->sc_percpu[cpu];
+ hv_pd = kmem_alloc(sizeof(*hv_pd), KM_SLEEP);
+ pd->md_cookie = (void *)hv_pd;
+
+ /* Allocate IDT vector for ISR and set it up. */
+ if (idt_vec_is_pcpu()) {
+ ci = curcpu();
+ iv = &ci->ci_idtvec;
+
+ mutex_enter(&cpu_lock);
+ hyperv_idtvec = idt_vec_alloc(iv, APIC_LEVEL(NIPL), IDT_INTR_HIGH);
+ mutex_exit(&cpu_lock);
+ KASSERT(hyperv_idtvec > 0);
+ idt_vec_set(iv, hyperv_idtvec, Xintr_hyperv_hypercall);
+
+ hv_pd = kmem_alloc(sizeof(*hv_pd), KM_SLEEP);
+ hv_pd->pd_idtvec = hyperv_idtvec;
+ pd->md_cookie = hv_pd;
+ } else {
+ pd0 = &sc->sc_percpu[cpu_index(&cpu_info_primary)];
+ hv_pd = pd0->md_cookie;
+ hyperv_idtvec = hv_pd->pd_idtvec;
+ }
+
/*
* Setup the SynIC message.
*/
@@ -832,6 +888,10 @@ vmbus_init_synic_md(struct vmbus_softc *
void
vmbus_deinit_synic_md(struct vmbus_softc *sc, cpuid_t cpu)
{
+ struct vmbus_percpu_data *pd;
+ struct hyperv_percpu_data *hv_pd;
+ struct cpu_info *ci;
+ struct idt_vec *iv;
uint64_t orig;
uint32_t sint;
@@ -866,6 +926,22 @@ vmbus_deinit_synic_md(struct vmbus_softc
*/
orig = rdmsr(MSR_HV_SIEFP);
wrmsr(MSR_HV_SIEFP, (orig & MSR_HV_SIEFP_RSVD_MASK));
+
+ /*
+ * Free IDT vector
+ */
+ if (idt_vec_is_pcpu()) {
+ ci = curcpu();
+ iv = &ci->ci_idtvec;
+ pd = &sc->sc_percpu[cpu_index(ci)];
+ hv_pd = pd->md_cookie;
+
+ if (hv_pd->pd_idtvec > 0)
+ idt_vec_free(iv, hv_pd->pd_idtvec);
+
+ pd->md_cookie = NULL;
+ kmem_free(hv_pd, sizeof(*hv_pd));
+ }
}
static int
Index: src/sys/arch/x86/x86/idt.c
diff -u src/sys/arch/x86/x86/idt.c:1.12 src/sys/arch/x86/x86/idt.c:1.13
--- src/sys/arch/x86/x86/idt.c:1.12 Sat Jul 4 09:03:54 2020
+++ src/sys/arch/x86/x86/idt.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: idt.c,v 1.12 2020/07/04 09:03:54 bouyer Exp $ */
+/* $NetBSD: idt.c,v 1.13 2020/07/14 00:45:53 yamaguchi Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2000, 2009 The NetBSD Foundation, Inc.
@@ -65,7 +65,9 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: idt.c,v 1.12 2020/07/04 09:03:54 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: idt.c,v 1.13 2020/07/14 00:45:53 yamaguchi Exp $");
+
+#include "opt_pcpu_idt.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -81,9 +83,6 @@ __KERNEL_RCSID(0, "$NetBSD: idt.c,v 1.12
* XEN PV and native have a different idea of what idt entries should
* look like.
*/
-idt_descriptor_t *idt;
-
-static char idt_allocmap[NIDT];
/* Normalise across XEN PV and native */
#if defined(XENPV)
@@ -164,9 +163,10 @@ unset_idtgate(struct gate_descriptor *id
* cpu_lock will be held unless single threaded during early boot.
*/
int
-idt_vec_alloc(int low, int high)
+idt_vec_alloc(struct idt_vec *iv, int low, int high)
{
int vec;
+ char *idt_allocmap = iv->iv_allocmap;
KASSERT(mutex_owned(&cpu_lock) || !mp_online);
@@ -182,23 +182,26 @@ idt_vec_alloc(int low, int high)
}
void
-idt_vec_reserve(int vec)
+idt_vec_reserve(struct idt_vec *iv, int vec)
{
int result;
KASSERT(mutex_owned(&cpu_lock) || !mp_online);
- result = idt_vec_alloc(vec, vec);
+ result = idt_vec_alloc(iv, vec, vec);
if (result != vec) {
panic("%s: failed to reserve vec %d", __func__, vec);
}
}
void
-idt_vec_set(int vec, void (*function)(void))
+idt_vec_set(struct idt_vec *iv, int vec, void (*function)(void))
{
+ idt_descriptor_t *idt;
+ char *idt_allocmap = iv->iv_allocmap;
KASSERT(idt_allocmap[vec] == 1);
+ idt = iv->iv_idt;
set_idtgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
}
@@ -207,10 +210,32 @@ idt_vec_set(int vec, void (*function)(vo
* Free IDT vector. No locking required as release is atomic.
*/
void
-idt_vec_free(int vec)
+idt_vec_free(struct idt_vec *iv, int vec)
{
+ idt_descriptor_t *idt;
+ char *idt_allocmap = iv->iv_allocmap;
+ idt = iv->iv_idt;
unset_idtgate(&idt[vec]);
idt_allocmap[vec] = 0;
}
+bool
+idt_vec_is_pcpu(void)
+{
+
+#ifdef PCPU_IDT
+ return true;
+#else
+ return false;
+#endif
+}
+
+struct idt_vec *
+idt_vec_ref(struct idt_vec *iv)
+{
+ if (idt_vec_is_pcpu())
+ return iv;
+
+ return &(cpu_info_primary.ci_idtvec);
+}
Index: src/sys/arch/x86/x86/intr.c
diff -u src/sys/arch/x86/x86/intr.c:1.151 src/sys/arch/x86/x86/intr.c:1.152
--- src/sys/arch/x86/x86/intr.c:1.151 Sat Apr 25 15:26:18 2020
+++ src/sys/arch/x86/x86/intr.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.c,v 1.151 2020/04/25 15:26:18 bouyer Exp $ */
+/* $NetBSD: intr.c,v 1.152 2020/07/14 00:45:53 yamaguchi Exp $ */
/*
* Copyright (c) 2007, 2008, 2009, 2019 The NetBSD Foundation, Inc.
@@ -133,7 +133,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.151 2020/04/25 15:26:18 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.152 2020/07/14 00:45:53 yamaguchi Exp $");
#include "opt_intrdebug.h"
#include "opt_multiprocessor.h"
@@ -252,12 +252,13 @@ static int intr_set_affinity(struct intr
void
intr_default_setup(void)
{
+ struct idt_vec *iv = &(cpu_info_primary.ci_idtvec);
int i;
/* icu vectors */
for (i = 0; i < NUM_LEGACY_IRQS; i++) {
- idt_vec_reserve(ICU_OFFSET + i);
- idt_vec_set(ICU_OFFSET + i, legacy_stubs[i].ist_entry);
+ idt_vec_reserve(iv, ICU_OFFSET + i);
+ idt_vec_set(iv, ICU_OFFSET + i, legacy_stubs[i].ist_entry);
}
/*
@@ -503,6 +504,7 @@ intr_allocate_slot(struct pic *pic, int
struct cpu_info *ci, *lci;
struct intrsource *isp;
int slot = 0, idtvec, error;
+ struct idt_vec *iv;
KASSERT(mutex_owned(&cpu_lock));
@@ -600,7 +602,8 @@ intr_allocate_slot(struct pic *pic, int
* are used by a device using MSI multiple vectors must be
* continuous.
*/
- idtvec = idt_vec_alloc(APIC_LEVEL(level), IDT_INTR_HIGH);
+ iv = idt_vec_ref(&ci->ci_idtvec);
+ idtvec = idt_vec_alloc(iv, APIC_LEVEL(level), IDT_INTR_HIGH);
}
if (idtvec == 0) {
evcnt_detach(&ci->ci_isources[slot]->is_evcnt);
@@ -619,14 +622,16 @@ static void
intr_source_free(struct cpu_info *ci, int slot, struct pic *pic, int idtvec)
{
struct intrsource *isp;
+ struct idt_vec *iv;
isp = ci->ci_isources[slot];
+ iv = idt_vec_ref(&ci->ci_idtvec);
if (isp->is_handlers != NULL)
return;
ci->ci_isources[slot] = NULL;
if (pic != &i8259_pic)
- idt_vec_free(idtvec);
+ idt_vec_free(iv, idtvec);
}
#ifdef MULTIPROCESSOR
@@ -703,6 +708,7 @@ intr_hwunmask_xcall(void *arg1, void *ar
static void
intr_establish_xcall(void *arg1, void *arg2)
{
+ struct idt_vec *iv;
struct intrsource *source;
struct intrstub *stubp;
struct intrhand *ih;
@@ -717,6 +723,7 @@ intr_establish_xcall(void *arg1, void *a
ci = ih->ih_cpu;
source = ci->ci_isources[ih->ih_slot];
idt_vec = (int)(intptr_t)arg2;
+ iv = idt_vec_ref(&ci->ci_idtvec);
/* Disable interrupts locally. */
psl = x86_read_psl();
@@ -729,7 +736,7 @@ intr_establish_xcall(void *arg1, void *a
/* Hook in new IDT vector and SPL state. */
if (source->is_resume == NULL || source->is_idtvec != idt_vec) {
if (source->is_idtvec != 0 && source->is_idtvec != idt_vec)
- idt_vec_free(source->is_idtvec);
+ idt_vec_free(iv, source->is_idtvec);
source->is_idtvec = idt_vec;
if (source->is_type == IST_LEVEL) {
stubp = &source->is_pic->pic_level_stubs[ih->ih_slot];
@@ -738,7 +745,7 @@ intr_establish_xcall(void *arg1, void *a
}
source->is_resume = stubp->ist_resume;
source->is_recurse = stubp->ist_recurse;
- idt_vec_set(idt_vec, stubp->ist_entry);
+ idt_vec_set(iv, idt_vec, stubp->ist_entry);
}
/* Re-enable interrupts locally. */
@@ -1713,6 +1720,7 @@ intr_activate_xcall(void *arg1, void *ar
struct intrsource *source;
struct intrstub *stubp;
struct intrhand *ih;
+ struct idt_vec *iv;
u_long psl;
int idt_vec;
int slot;
@@ -1727,6 +1735,7 @@ intr_activate_xcall(void *arg1, void *ar
slot = ih->ih_slot;
source = ci->ci_isources[slot];
idt_vec = source->is_idtvec;
+ iv = idt_vec_ref(&ci->ci_idtvec);
psl = x86_read_psl();
x86_disable_intr();
@@ -1738,9 +1747,10 @@ intr_activate_xcall(void *arg1, void *ar
} else {
stubp = &source->is_pic->pic_edge_stubs[slot];
}
+
source->is_resume = stubp->ist_resume;
source->is_recurse = stubp->ist_recurse;
- idt_vec_set(idt_vec, stubp->ist_entry);
+ idt_vec_set(iv, idt_vec, stubp->ist_entry);
x86_write_psl(psl);
@@ -1755,7 +1765,9 @@ intr_deactivate_xcall(void *arg1, void *
{
struct cpu_info *ci;
struct intrhand *ih, *lih;
+ struct intrsource *isp;
u_long psl;
+ int idt_vec;
int slot;
ih = arg1;
@@ -1766,6 +1778,8 @@ intr_deactivate_xcall(void *arg1, void *
ci = ih->ih_cpu;
slot = ih->ih_slot;
+ isp = ci->ci_isources[slot];
+ idt_vec = isp->is_idtvec;
psl = x86_read_psl();
x86_disable_intr();
@@ -1778,10 +1792,14 @@ intr_deactivate_xcall(void *arg1, void *
x86_intr_calculatemasks(ci);
- /*
- * Skip unsetgate(), because the same itd[] entry is overwritten in
- * intr_activate_xcall().
- */
+ if (idt_vec > 0 && idt_vec_is_pcpu()) {
+ idt_vec_free(&ci->ci_idtvec, idt_vec);
+ } else {
+ /*
+ * Skip unsetgate(), because the same idt[] entry is
+ * overwritten in intr_activate_xcall().
+ */
+ }
x86_write_psl(psl);
@@ -1820,7 +1838,7 @@ intr_set_affinity(struct intrsource *isp
struct intrhand *ih, *lih;
struct pic *pic;
u_int cpu_idx;
- int idt_vec;
+ int old_idtvec, new_idtvec;
int oldslot, newslot;
int err;
int pin;
@@ -1863,7 +1881,6 @@ intr_set_affinity(struct intrsource *isp
return 0;
oldslot = ih->ih_slot;
- idt_vec = isp->is_idtvec;
err = intr_find_unused_slot(newci, &newslot);
if (err) {
@@ -1872,6 +1889,19 @@ intr_set_affinity(struct intrsource *isp
return err;
}
+ old_idtvec = isp->is_idtvec;
+
+ if (isp->is_idtvec > 0 && idt_vec_is_pcpu()) {
+ new_idtvec = idt_vec_alloc(&newci->ci_idtvec,
+ APIC_LEVEL(ih->ih_level), IDT_INTR_HIGH);
+ if (new_idtvec == 0)
+ return EBUSY;
+ DPRINTF(("interrupt from cpu%d vec %d to cpu%d vec %d\n",
+ cpu_index(oldci), old_idtvec, cpu_index(newci), new_idtvec));
+ } else {
+ new_idtvec = isp->is_idtvec;
+ }
+
/* Prevent intr_unmask() from reenabling the source at the hw. */
isp->is_distribute_pending = true;
@@ -1893,9 +1923,10 @@ intr_set_affinity(struct intrsource *isp
xc_wait(where);
}
intr_save_evcnt(isp, oldci->ci_cpuid);
- (*pic->pic_delroute)(pic, oldci, pin, idt_vec, isp->is_type);
+ (*pic->pic_delroute)(pic, oldci, pin, old_idtvec, isp->is_type);
/* activate new interrupt setting */
+ isp->is_idtvec = new_idtvec;
newci->ci_isources[newslot] = isp;
for (lih = ih; lih != NULL; lih = lih->ih_next) {
newci->ci_nintrhand++;
@@ -1912,7 +1943,7 @@ intr_set_affinity(struct intrsource *isp
}
intr_restore_evcnt(isp, newci->ci_cpuid);
isp->is_active_cpu = newci->ci_cpuid;
- (*pic->pic_addroute)(pic, newci, pin, idt_vec, isp->is_type);
+ (*pic->pic_addroute)(pic, newci, pin, new_idtvec, isp->is_type);
isp->is_distribute_pending = false;
if (newci == curcpu() || !mp_online) {
Index: src/sys/arch/x86/x86/lapic.c
diff -u src/sys/arch/x86/x86/lapic.c:1.83 src/sys/arch/x86/x86/lapic.c:1.84
--- src/sys/arch/x86/x86/lapic.c:1.83 Fri May 29 12:30:41 2020
+++ src/sys/arch/x86/x86/lapic.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: lapic.c,v 1.83 2020/05/29 12:30:41 rin Exp $ */
+/* $NetBSD: lapic.c,v 1.84 2020/07/14 00:45:53 yamaguchi Exp $ */
/*-
* Copyright (c) 2000, 2008, 2020 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.83 2020/05/29 12:30:41 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.84 2020/07/14 00:45:53 yamaguchi Exp $");
#include "acpica.h"
#include "ioapic.h"
@@ -338,6 +338,8 @@ lapic_setup_bsp(paddr_t lapic_base)
#endif
#if defined(DDB) && defined(MULTIPROCESSOR)
#ifdef __x86_64__
+ struct idt_vec *iv = &(cpu_info_primary.ci_idtvec);
+ idt_descriptor_t *idt = iv->iv_idt;
set_idtgate(&idt[ddb_vec], &Xintr_x2apic_ddbipi, 1,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#else
@@ -475,23 +477,24 @@ lapic_set_lvt(void)
void
lapic_boot_init(paddr_t lapic_base)
{
+ struct idt_vec *iv = &(cpu_info_primary.ci_idtvec);
lapic_setup_bsp(lapic_base);
#ifdef MULTIPROCESSOR
- idt_vec_reserve(LAPIC_IPI_VECTOR);
- idt_vec_set(LAPIC_IPI_VECTOR,
+ idt_vec_reserve(iv, LAPIC_IPI_VECTOR);
+ idt_vec_set(iv, LAPIC_IPI_VECTOR,
x2apic_mode ? Xintr_x2apic_ipi : Xintr_lapic_ipi);
- idt_vec_reserve(LAPIC_TLB_VECTOR);
- idt_vec_set(LAPIC_TLB_VECTOR,
+ idt_vec_reserve(iv, LAPIC_TLB_VECTOR);
+ idt_vec_set(iv, LAPIC_TLB_VECTOR,
x2apic_mode ? Xintr_x2apic_tlb : Xintr_lapic_tlb);
#endif
- idt_vec_reserve(LAPIC_SPURIOUS_VECTOR);
- idt_vec_set(LAPIC_SPURIOUS_VECTOR, Xintrspurious);
+ idt_vec_reserve(iv, LAPIC_SPURIOUS_VECTOR);
+ idt_vec_set(iv, LAPIC_SPURIOUS_VECTOR, Xintrspurious);
- idt_vec_reserve(LAPIC_TIMER_VECTOR);
- idt_vec_set(LAPIC_TIMER_VECTOR,
+ idt_vec_reserve(iv, LAPIC_TIMER_VECTOR);
+ idt_vec_set(iv, LAPIC_TIMER_VECTOR,
x2apic_mode ? Xintr_x2apic_ltimer : Xintr_lapic_ltimer);
}
Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.399 src/sys/arch/x86/x86/pmap.c:1.400
--- src/sys/arch/x86/x86/pmap.c:1.399 Sun Jun 14 21:41:42 2020
+++ src/sys/arch/x86/x86/pmap.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.399 2020/06/14 21:41:42 ad Exp $ */
+/* $NetBSD: pmap.c,v 1.400 2020/07/14 00:45:53 yamaguchi Exp $ */
/*
* Copyright (c) 2008, 2010, 2016, 2017, 2019, 2020 The NetBSD Foundation, Inc.
@@ -130,7 +130,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.399 2020/06/14 21:41:42 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.400 2020/07/14 00:45:53 yamaguchi Exp $");
#include "opt_user_ldt.h"
#include "opt_lockdebug.h"
@@ -1309,11 +1309,7 @@ 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);
Index: src/sys/arch/x86/x86/svs.c
diff -u src/sys/arch/x86/x86/svs.c:1.37 src/sys/arch/x86/x86/svs.c:1.38
--- src/sys/arch/x86/x86/svs.c:1.37 Wed May 27 19:40:29 2020
+++ src/sys/arch/x86/x86/svs.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: svs.c,v 1.37 2020/05/27 19:40:29 ad Exp $ */
+/* $NetBSD: svs.c,v 1.38 2020/07/14 00:45:53 yamaguchi Exp $ */
/*
* Copyright (c) 2018-2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.37 2020/05/27 19:40:29 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svs.c,v 1.38 2020/07/14 00:45:53 yamaguchi Exp $");
#include "opt_svs.h"
#include "opt_user_ldt.h"
@@ -519,6 +519,7 @@ cpu_svs_init(struct cpu_info *ci)
{
extern char __text_user_start;
extern char __text_user_end;
+ extern vaddr_t idt_vaddr;
const cpuid_t cid = cpu_index(ci);
struct vm_page *pg;
@@ -543,7 +544,8 @@ cpu_svs_init(struct cpu_info *ci)
mutex_init(&ci->ci_svs_mtx, MUTEX_DEFAULT, IPL_VM);
- svs_page_add(ci, (vaddr_t)&pcpuarea->idt, true);
+ if (cid == cpu_index(&cpu_info_primary) || !idt_vec_is_pcpu())
+ svs_page_add(ci, idt_vaddr, true);
svs_page_add(ci, (vaddr_t)&pcpuarea->ldt, true);
svs_range_add(ci, (vaddr_t)&pcpuarea->ent[cid],
offsetof(struct pcpu_entry, rsp0), true);
Index: src/sys/arch/xen/x86/cpu.c
diff -u src/sys/arch/xen/x86/cpu.c:1.138 src/sys/arch/xen/x86/cpu.c:1.139
--- src/sys/arch/xen/x86/cpu.c:1.138 Wed Jul 8 11:11:00 2020
+++ src/sys/arch/xen/x86/cpu.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.138 2020/07/08 11:11:00 jdolecek Exp $ */
+/* $NetBSD: cpu.c,v 1.139 2020/07/14 00:45:53 yamaguchi Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.138 2020/07/08 11:11:00 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.139 2020/07/14 00:45:53 yamaguchi Exp $");
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
@@ -477,6 +477,9 @@ cpu_attach_common(device_t parent, devic
/* interrupt handler stack */
cpu_intr_init(ci);
+ /* Setup per-cpu memory for idt */
+ idt_vec_init_cpu_md(&ci->ci_idtvec, cpu_index(ci));
+
/* Setup per-cpu memory for gdt */
gdt_alloc_cpu(ci);
@@ -700,7 +703,7 @@ cpu_hatch(void *v)
/* Setup TLS and kernel GS/FS */
cpu_init_msrs(ci, true);
- cpu_init_idt();
+ cpu_init_idt(ci);
gdt_init_cpu(ci);
cpu_probe(ci);
Index: src/sys/arch/xen/xen/hypervisor.c
diff -u src/sys/arch/xen/xen/hypervisor.c:1.86 src/sys/arch/xen/xen/hypervisor.c:1.87
--- src/sys/arch/xen/xen/hypervisor.c:1.86 Tue May 26 10:37:25 2020
+++ src/sys/arch/xen/xen/hypervisor.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: hypervisor.c,v 1.86 2020/05/26 10:37:25 bouyer Exp $ */
+/* $NetBSD: hypervisor.c,v 1.87 2020/07/14 00:45:53 yamaguchi Exp $ */
/*
* Copyright (c) 2005 Manuel Bouyer.
@@ -53,7 +53,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hypervisor.c,v 1.86 2020/05/26 10:37:25 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hypervisor.c,v 1.87 2020/07/14 00:45:53 yamaguchi Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -295,6 +295,8 @@ xen_check_hypervisordev(void)
static int
xen_hvm_init_late(void)
{
+ struct idt_vec *iv = &(cpu_info_primary.ci_idtvec);
+
if (HYPERVISOR_xen_version(XENVER_version, NULL) < 0) {
aprint_error("Xen HVM: hypercall page not working\n");
return 0;
@@ -350,8 +352,8 @@ xen_hvm_init_late(void)
* prepare vector.
* We don't really care where it is, as long as it's free
*/
- xen_hvm_vec = idt_vec_alloc(129, 255);
- idt_vec_set(xen_hvm_vec, &IDTVEC(hypervisor_pvhvm_callback));
+ xen_hvm_vec = idt_vec_alloc(iv, 129, 255);
+ idt_vec_set(iv, xen_hvm_vec, &IDTVEC(hypervisor_pvhvm_callback));
events_default_setup();
return 1;
Index: src/sys/dev/hyperv/vmbusvar.h
diff -u src/sys/dev/hyperv/vmbusvar.h:1.5 src/sys/dev/hyperv/vmbusvar.h:1.6
--- src/sys/dev/hyperv/vmbusvar.h:1.5 Tue May 26 16:08:55 2020
+++ src/sys/dev/hyperv/vmbusvar.h Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: vmbusvar.h,v 1.5 2020/05/26 16:08:55 nonaka Exp $ */
+/* $NetBSD: vmbusvar.h,v 1.6 2020/07/14 00:45:53 yamaguchi Exp $ */
/* $OpenBSD: hypervvar.h,v 1.13 2017/06/23 19:05:42 mikeb Exp $ */
/*
@@ -159,6 +159,8 @@ struct vmbus_percpu_data {
/* Rarely used fields */
struct hyperv_dma simp_dma;
struct hyperv_dma siep_dma;
+
+ void *md_cookie;
} __aligned(CACHE_LINE_SIZE);
struct vmbus_softc {
Index: src/sys/dev/nvmm/x86/nvmm_x86_vmx.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.61 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.62
--- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.61 Fri Jul 3 16:09:54 2020
+++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Tue Jul 14 00:45:53 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_x86_vmx.c,v 1.61 2020/07/03 16:09:54 maxv Exp $ */
+/* $NetBSD: nvmm_x86_vmx.c,v 1.62 2020/07/14 00:45:53 yamaguchi Exp $ */
/*
* Copyright (c) 2018-2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.61 2020/07/03 16:09:54 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.62 2020/07/14 00:45:53 yamaguchi Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -2698,7 +2698,8 @@ vmx_vcpu_init(struct nvmm_machine *mach,
struct vmcs *vmcs = cpudata->vmcs;
struct msr_entry *gmsr = cpudata->gmsr;
extern uint8_t vmx_resume_rip;
- uint64_t rev, eptp;
+ uint64_t rev, eptp, idt;
+ struct cpu_info *ci;
rev = vmx_get_revision();
@@ -2765,6 +2766,9 @@ vmx_vcpu_init(struct nvmm_machine *mach,
vmx_vmwrite(VMCS_CR4_MASK, CR4_VMXE);
/* Set the Host state for resuming. */
+ ci = curcpu();
+ idt = (uint64_t)ci->ci_idtvec.iv_idt;
+
vmx_vmwrite(VMCS_HOST_RIP, (uint64_t)&vmx_resume_rip);
vmx_vmwrite(VMCS_HOST_CS_SELECTOR, GSEL(GCODE_SEL, SEL_KPL));
vmx_vmwrite(VMCS_HOST_SS_SELECTOR, GSEL(GDATA_SEL, SEL_KPL));
@@ -2775,7 +2779,7 @@ vmx_vcpu_init(struct nvmm_machine *mach,
vmx_vmwrite(VMCS_HOST_IA32_SYSENTER_CS, 0);
vmx_vmwrite(VMCS_HOST_IA32_SYSENTER_ESP, 0);
vmx_vmwrite(VMCS_HOST_IA32_SYSENTER_EIP, 0);
- vmx_vmwrite(VMCS_HOST_IDTR_BASE, (uint64_t)idt);
+ vmx_vmwrite(VMCS_HOST_IDTR_BASE, idt);
vmx_vmwrite(VMCS_HOST_IA32_PAT, rdmsr(MSR_CR_PAT));
vmx_vmwrite(VMCS_HOST_IA32_EFER, rdmsr(MSR_EFER));
vmx_vmwrite(VMCS_HOST_CR0, rcr0() & ~CR0_TS);