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(&region, idt, NIDT * sizeof(idt[0]) - 1);
 	lidt(&region);
 }
@@ -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(&region, 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(&region, idt, NIDT * sizeof(idt[0]) - 1);
 	lidt(&region);
 }
 
@@ -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);

Reply via email to