Module Name:    src
Committed By:   nonaka
Date:           Tue May 23 08:54:39 UTC 2017

Modified Files:
        src/sys/arch/amd64/amd64: db_interface.c mainbus.c vector.S
        src/sys/arch/amd64/include: i82093reg.h
        src/sys/arch/i386/i386: db_interface.c mainbus.c vector.S
        src/sys/arch/i386/include: i82093reg.h
        src/sys/arch/x86/include: cpuvar.h i82489var.h intr.h mpacpi.h
        src/sys/arch/x86/pci: msipic.c
        src/sys/arch/x86/x86: cpu.c lapic.c pmc.c tprof_amdpmi.c tprof_pmi.c
        src/sys/arch/xen/include: intr.h mpacpi.h
        src/sys/arch/xen/x86: intr.c mainbus.c

Log Message:
x86: Add preliminary x2APIC support.

x2APIC is used only when x2APIC is enabled in BIOS/UEFI.
LAPIC ID is not supported above 256.


To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.25 src/sys/arch/amd64/amd64/db_interface.c
cvs rdiff -u -r1.37 -r1.38 src/sys/arch/amd64/amd64/mainbus.c
cvs rdiff -u -r1.48 -r1.49 src/sys/arch/amd64/amd64/vector.S
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/amd64/include/i82093reg.h
cvs rdiff -u -r1.71 -r1.72 src/sys/arch/i386/i386/db_interface.c
cvs rdiff -u -r1.102 -r1.103 src/sys/arch/i386/i386/mainbus.c
cvs rdiff -u -r1.68 -r1.69 src/sys/arch/i386/i386/vector.S
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/i386/include/i82093reg.h
cvs rdiff -u -r1.49 -r1.50 src/sys/arch/x86/include/cpuvar.h \
    src/sys/arch/x86/include/intr.h
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/x86/include/i82489var.h
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/x86/include/mpacpi.h
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/x86/pci/msipic.c
cvs rdiff -u -r1.124 -r1.125 src/sys/arch/x86/x86/cpu.c
cvs rdiff -u -r1.57 -r1.58 src/sys/arch/x86/x86/lapic.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/x86/x86/pmc.c \
    src/sys/arch/x86/x86/tprof_amdpmi.c
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/x86/x86/tprof_pmi.c
cvs rdiff -u -r1.39 -r1.40 src/sys/arch/xen/include/intr.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/xen/include/mpacpi.h
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/xen/x86/intr.c
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/xen/x86/mainbus.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.24 src/sys/arch/amd64/amd64/db_interface.c:1.25
--- src/sys/arch/amd64/amd64/db_interface.c:1.24	Thu Aug 11 19:52:52 2011
+++ src/sys/arch/amd64/amd64/db_interface.c	Tue May 23 08:54:38 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_interface.c,v 1.24 2011/08/11 19:52:52 cherry Exp $	*/
+/*	$NetBSD: db_interface.c,v 1.25 2017/05/23 08:54:38 nonaka Exp $	*/
 
 /*
  * Mach Operating System
@@ -33,11 +33,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.24 2011/08/11 19:52:52 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.25 2017/05/23 08:54:38 nonaka Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
 
+#include "lapic.h"
+
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/reboot.h>
@@ -93,7 +95,7 @@ static bool ddb_mp_online;
 int ddb_cpu = NOCPU;
 
 typedef void (vector)(void);
-extern vector Xintrddb;
+extern vector Xintrddb, Xx2apic_intrddb;
 
 void
 db_machine_init(void)
@@ -101,9 +103,14 @@ db_machine_init(void)
 
 #ifdef MULTIPROCESSOR
 #ifndef XEN
+	vector *handler = &Xintrddb;
+#if NLAPIC > 0
+	if (lapic_is_x2apic())
+		handler = &Xx2apic_intrddb;
+#endif
 	ddb_vec = idt_vec_alloc(0xf0, 0xff);
-	setgate((struct gate_descriptor *)&idt[ddb_vec], &Xintrddb, 1,
-	    SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+	setgate(&idt[ddb_vec], handler, 1, SDT_SYS386IGT, SEL_KPL,
+	    GSEL(GCODE_SEL, SEL_KPL));
 #else
 	/* Initialised as part of xen_ipi_init() */
 #endif /* XEN */

Index: src/sys/arch/amd64/amd64/mainbus.c
diff -u src/sys/arch/amd64/amd64/mainbus.c:1.37 src/sys/arch/amd64/amd64/mainbus.c:1.38
--- src/sys/arch/amd64/amd64/mainbus.c:1.37	Tue Jun 21 11:33:32 2016
+++ src/sys/arch/amd64/amd64/mainbus.c	Tue May 23 08:54:38 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mainbus.c,v 1.37 2016/06/21 11:33:32 nonaka Exp $	*/
+/*	$NetBSD: mainbus.c,v 1.38 2017/05/23 08:54:38 nonaka Exp $	*/
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.37 2016/06/21 11:33:32 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.38 2017/05/23 08:54:38 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -126,6 +126,9 @@ int mp_nintr;
 int mp_isa_bus = -1;
 int mp_eisa_bus = -1;
 
+bool acpi_present;
+bool mpacpi_active;
+
 # ifdef MPVERBOSE
 #  if MPVERBOSE > 0
 int mp_verbose = MPVERBOSE;
@@ -160,13 +163,9 @@ mainbus_attach(device_t parent, device_t
 #if NPCI > 0
 	int mode;
 #endif
-#if NACPICA > 0
-	int acpi_present = 0;
-#endif
 #ifdef MPBIOS
 	int mpbios_present = 0;
 #endif
-	int mpacpi_active = 0;
 	int numcpus = 0;
 #if defined(PCI_BUS_FIXUP)
 	int pci_maxbus = 0;
@@ -202,14 +201,14 @@ mainbus_attach(device_t parent, device_t
 
 #if NACPICA > 0
 	if ((boothowto & RB_MD2) == 0 && acpi_check(self, "acpibus"))
-		acpi_present = acpi_probe();
+		acpi_present = acpi_probe() != 0;
 	/*
 	 * First, see if the MADT contains CPUs, and possibly I/O APICs.
 	 * Building the interrupt routing structures can only
 	 * be done later (via a callback).
 	 */
 	if (acpi_present)
-		mpacpi_active = mpacpi_scan_apics(self, &numcpus);
+		mpacpi_active = mpacpi_scan_apics(self, &numcpus) != 0;
 #endif
 
 	if (!mpacpi_active) {

Index: src/sys/arch/amd64/amd64/vector.S
diff -u src/sys/arch/amd64/amd64/vector.S:1.48 src/sys/arch/amd64/amd64/vector.S:1.49
--- src/sys/arch/amd64/amd64/vector.S:1.48	Fri Nov 25 14:12:55 2016
+++ src/sys/arch/amd64/amd64/vector.S	Tue May 23 08:54:38 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: vector.S,v 1.48 2016/11/25 14:12:55 maxv Exp $	*/
+/*	$NetBSD: vector.S,v 1.49 2017/05/23 08:54:38 nonaka Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -118,7 +118,19 @@ IDTVEC(recurse_lapic_ipi)
 	INTRENTRY
 	jmp	1f
 IDTVEC_END(recurse_lapic_ipi)
-
+IDTVEC(intr_x2apic_ipi)
+	pushq	$0
+	pushq	$T_ASTFLT
+	INTRENTRY
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	movl	CPUVAR(ILEVEL),%ebx
+	cmpl	$IPL_HIGH,%ebx
+	jae	2f
+	jmp	1f
+IDTVEC_END(intr_x2apic_ipi)
 IDTVEC(intr_lapic_ipi)
 	pushq	$0
 	pushq	$T_ASTFLT
@@ -128,6 +140,7 @@ IDTVEC(intr_lapic_ipi)
 	movl	CPUVAR(ILEVEL),%ebx
 	cmpl	$IPL_HIGH,%ebx
 	jae	2f
+IDTVEC_END(intr_lapic_ipi)
 IDTVEC(resume_lapic_ipi)
 1:
 	incl	CPUVAR(IDEPTH)
@@ -140,7 +153,6 @@ IDTVEC(resume_lapic_ipi)
 	orl	$(1 << LIR_IPI),CPUVAR(IPENDING)
 	INTRFASTEXIT
 IDTVEC_END(resume_lapic_ipi)
-IDTVEC_END(intr_lapic_ipi)
 
 #if defined(DDB)
 IDTVEC(intrddb)
@@ -158,6 +170,24 @@ IDTVEC(intrddb)
 	movq	%rax,%cr8
 	INTRFASTEXIT
 IDTVEC_END(intrddb)
+
+IDTVEC(x2apic_intrddb)
+1:
+	pushq	$0
+	pushq	$T_BPTFLT
+	INTRENTRY
+	movl	$0xf,%eax
+	movq	%rax,%cr8
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	sti
+	call	_C_LABEL(ddb_ipi)
+	xorl	%eax,%eax
+	movq	%rax,%cr8
+	INTRFASTEXIT
+IDTVEC_END(x2apic_intrddb)
 #endif /* DDB */
 #endif /* MULTIPROCESSOR */
 
@@ -171,7 +201,19 @@ IDTVEC(recurse_lapic_ltimer)
 	INTRENTRY
 	jmp	1f
 IDTVEC_END(recurse_lapic_ltimer)
-
+IDTVEC(intr_x2apic_ltimer)
+	pushq	$0
+	pushq	$T_ASTFLT
+	INTRENTRY
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	movl	CPUVAR(ILEVEL),%ebx
+	cmpl	$IPL_CLOCK,%ebx
+	jae	2f
+	jmp	1f
+IDTVEC_END(intr_x2apic_ltimer)
 IDTVEC(intr_lapic_ltimer)
 	pushq	$0
 	pushq	$T_ASTFLT
@@ -181,6 +223,7 @@ IDTVEC(intr_lapic_ltimer)
 	movl	CPUVAR(ILEVEL),%ebx
 	cmpl	$IPL_CLOCK,%ebx
 	jae	2f
+IDTVEC_END(intr_lapic_ltimer)
 IDTVEC(resume_lapic_ltimer)
 1:
 	incl	CPUVAR(IDEPTH)
@@ -195,7 +238,6 @@ IDTVEC(resume_lapic_ltimer)
 	orl	$(1 << LIR_TIMER),CPUVAR(IPENDING)
 	INTRFASTEXIT
 IDTVEC_END(resume_lapic_ltimer)
-IDTVEC_END(intr_lapic_ltimer)
 #endif /* NLAPIC > 0 */
 
 #ifndef XEN
@@ -212,6 +254,18 @@ IDTVEC(intr_lapic_tlb)
 	INTRFASTEXIT
 IDTVEC_END(intr_lapic_tlb)
 
+IDTVEC(intr_x2apic_tlb)
+	pushq	$0
+	pushq	$T_ASTFLT
+	INTRENTRY
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	callq	_C_LABEL(pmap_tlb_intr)
+	INTRFASTEXIT
+IDTVEC_END(intr_x2apic_tlb)
+
 #endif /* !XEN */
 
 #define voidop(num)
@@ -397,6 +451,72 @@ INTRSTUB(ioapic_level,29,voidop,ioapic_a
 INTRSTUB(ioapic_level,30,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
 INTRSTUB(ioapic_level,31,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
 
+INTRSTUB(x2apic_edge,0,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,1,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,2,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,3,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,4,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,5,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,6,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,7,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,8,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,9,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,10,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,11,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,12,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,13,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,14,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,15,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,16,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,17,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,18,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,19,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,20,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,21,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,22,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,23,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,24,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,25,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,26,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,27,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,28,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,29,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,30,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,31,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+
+INTRSTUB(x2apic_level,0,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,1,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,2,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,3,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,4,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,5,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,6,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,7,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,8,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,9,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,10,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,11,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,12,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,13,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,14,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,15,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,16,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,17,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,18,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,19,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,20,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,21,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,22,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,23,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,24,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,25,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,26,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,27,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,28,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,29,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,30,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,31,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+
 #endif
 
 	.type _C_LABEL(i8259_stubs), @object
@@ -571,6 +691,142 @@ LABEL(ioapic_level_stubs)
 	.quad _C_LABEL(Xintr_ioapic_level31), _C_LABEL(Xrecurse_ioapic_level31)
 	.quad _C_LABEL(Xresume_ioapic_level31)
 END(ioapic_level_stubs)
+
+	.type _C_LABEL(x2apic_edge_stubs), @object
+LABEL(x2apic_edge_stubs)
+	.quad _C_LABEL(Xintr_x2apic_edge0), _C_LABEL(Xrecurse_x2apic_edge0)
+	.quad _C_LABEL(Xresume_x2apic_edge0)
+	.quad _C_LABEL(Xintr_x2apic_edge1), _C_LABEL(Xrecurse_x2apic_edge1)
+	.quad _C_LABEL(Xresume_x2apic_edge1)
+	.quad _C_LABEL(Xintr_x2apic_edge2), _C_LABEL(Xrecurse_x2apic_edge2)
+	.quad _C_LABEL(Xresume_x2apic_edge2)
+	.quad _C_LABEL(Xintr_x2apic_edge3), _C_LABEL(Xrecurse_x2apic_edge3)
+	.quad _C_LABEL(Xresume_x2apic_edge3)
+	.quad _C_LABEL(Xintr_x2apic_edge4), _C_LABEL(Xrecurse_x2apic_edge4)
+	.quad _C_LABEL(Xresume_x2apic_edge4)
+	.quad _C_LABEL(Xintr_x2apic_edge5), _C_LABEL(Xrecurse_x2apic_edge5)
+	.quad _C_LABEL(Xresume_x2apic_edge5)
+	.quad _C_LABEL(Xintr_x2apic_edge6), _C_LABEL(Xrecurse_x2apic_edge6)
+	.quad _C_LABEL(Xresume_x2apic_edge6)
+	.quad _C_LABEL(Xintr_x2apic_edge7), _C_LABEL(Xrecurse_x2apic_edge7)
+	.quad _C_LABEL(Xresume_x2apic_edge7)
+	.quad _C_LABEL(Xintr_x2apic_edge8), _C_LABEL(Xrecurse_x2apic_edge8)
+	.quad _C_LABEL(Xresume_x2apic_edge8)
+	.quad _C_LABEL(Xintr_x2apic_edge9), _C_LABEL(Xrecurse_x2apic_edge9)
+	.quad _C_LABEL(Xresume_x2apic_edge9)
+	.quad _C_LABEL(Xintr_x2apic_edge10), _C_LABEL(Xrecurse_x2apic_edge10)
+	.quad _C_LABEL(Xresume_x2apic_edge10)
+	.quad _C_LABEL(Xintr_x2apic_edge11), _C_LABEL(Xrecurse_x2apic_edge11)
+	.quad _C_LABEL(Xresume_x2apic_edge11)
+	.quad _C_LABEL(Xintr_x2apic_edge12), _C_LABEL(Xrecurse_x2apic_edge12)
+	.quad _C_LABEL(Xresume_x2apic_edge12)
+	.quad _C_LABEL(Xintr_x2apic_edge13), _C_LABEL(Xrecurse_x2apic_edge13)
+	.quad _C_LABEL(Xresume_x2apic_edge13)
+	.quad _C_LABEL(Xintr_x2apic_edge14), _C_LABEL(Xrecurse_x2apic_edge14)
+	.quad _C_LABEL(Xresume_x2apic_edge14)
+	.quad _C_LABEL(Xintr_x2apic_edge15), _C_LABEL(Xrecurse_x2apic_edge15)
+	.quad _C_LABEL(Xresume_x2apic_edge15)
+	.quad _C_LABEL(Xintr_x2apic_edge16), _C_LABEL(Xrecurse_x2apic_edge16)
+	.quad _C_LABEL(Xresume_x2apic_edge16)
+	.quad _C_LABEL(Xintr_x2apic_edge17), _C_LABEL(Xrecurse_x2apic_edge17)
+	.quad _C_LABEL(Xresume_x2apic_edge17)
+	.quad _C_LABEL(Xintr_x2apic_edge18), _C_LABEL(Xrecurse_x2apic_edge18)
+	.quad _C_LABEL(Xresume_x2apic_edge18)
+	.quad _C_LABEL(Xintr_x2apic_edge19), _C_LABEL(Xrecurse_x2apic_edge19)
+	.quad _C_LABEL(Xresume_x2apic_edge19)
+	.quad _C_LABEL(Xintr_x2apic_edge20), _C_LABEL(Xrecurse_x2apic_edge20)
+	.quad _C_LABEL(Xresume_x2apic_edge20)
+	.quad _C_LABEL(Xintr_x2apic_edge21), _C_LABEL(Xrecurse_x2apic_edge21)
+	.quad _C_LABEL(Xresume_x2apic_edge21)
+	.quad _C_LABEL(Xintr_x2apic_edge22), _C_LABEL(Xrecurse_x2apic_edge22)
+	.quad _C_LABEL(Xresume_x2apic_edge22)
+	.quad _C_LABEL(Xintr_x2apic_edge23), _C_LABEL(Xrecurse_x2apic_edge23)
+	.quad _C_LABEL(Xresume_x2apic_edge23)
+	.quad _C_LABEL(Xintr_x2apic_edge24), _C_LABEL(Xrecurse_x2apic_edge24)
+	.quad _C_LABEL(Xresume_x2apic_edge24)
+	.quad _C_LABEL(Xintr_x2apic_edge25), _C_LABEL(Xrecurse_x2apic_edge25)
+	.quad _C_LABEL(Xresume_x2apic_edge25)
+	.quad _C_LABEL(Xintr_x2apic_edge26), _C_LABEL(Xrecurse_x2apic_edge26)
+	.quad _C_LABEL(Xresume_x2apic_edge26)
+	.quad _C_LABEL(Xintr_x2apic_edge27), _C_LABEL(Xrecurse_x2apic_edge27)
+	.quad _C_LABEL(Xresume_x2apic_edge27)
+	.quad _C_LABEL(Xintr_x2apic_edge28), _C_LABEL(Xrecurse_x2apic_edge28)
+	.quad _C_LABEL(Xresume_x2apic_edge28)
+	.quad _C_LABEL(Xintr_x2apic_edge29), _C_LABEL(Xrecurse_x2apic_edge29)
+	.quad _C_LABEL(Xresume_x2apic_edge29)
+	.quad _C_LABEL(Xintr_x2apic_edge30), _C_LABEL(Xrecurse_x2apic_edge30)
+	.quad _C_LABEL(Xresume_x2apic_edge30)
+	.quad _C_LABEL(Xintr_x2apic_edge31), _C_LABEL(Xrecurse_x2apic_edge31)
+	.quad _C_LABEL(Xresume_x2apic_edge31)
+END(x2apic_edge_stubs)
+
+	.type _C_LABEL(x2apic_level_stubs), @object
+LABEL(x2apic_level_stubs)
+	.quad _C_LABEL(Xintr_x2apic_level0), _C_LABEL(Xrecurse_x2apic_level0)
+	.quad _C_LABEL(Xresume_x2apic_level0)
+	.quad _C_LABEL(Xintr_x2apic_level1), _C_LABEL(Xrecurse_x2apic_level1)
+	.quad _C_LABEL(Xresume_x2apic_level1)
+	.quad _C_LABEL(Xintr_x2apic_level2), _C_LABEL(Xrecurse_x2apic_level2)
+	.quad _C_LABEL(Xresume_x2apic_level2)
+	.quad _C_LABEL(Xintr_x2apic_level3), _C_LABEL(Xrecurse_x2apic_level3)
+	.quad _C_LABEL(Xresume_x2apic_level3)
+	.quad _C_LABEL(Xintr_x2apic_level4), _C_LABEL(Xrecurse_x2apic_level4)
+	.quad _C_LABEL(Xresume_x2apic_level4)
+	.quad _C_LABEL(Xintr_x2apic_level5), _C_LABEL(Xrecurse_x2apic_level5)
+	.quad _C_LABEL(Xresume_x2apic_level5)
+	.quad _C_LABEL(Xintr_x2apic_level6), _C_LABEL(Xrecurse_x2apic_level6)
+	.quad _C_LABEL(Xresume_x2apic_level6)
+	.quad _C_LABEL(Xintr_x2apic_level7), _C_LABEL(Xrecurse_x2apic_level7)
+	.quad _C_LABEL(Xresume_x2apic_level7)
+	.quad _C_LABEL(Xintr_x2apic_level8), _C_LABEL(Xrecurse_x2apic_level8)
+	.quad _C_LABEL(Xresume_x2apic_level8)
+	.quad _C_LABEL(Xintr_x2apic_level9), _C_LABEL(Xrecurse_x2apic_level9)
+	.quad _C_LABEL(Xresume_x2apic_level9)
+	.quad _C_LABEL(Xintr_x2apic_level10), _C_LABEL(Xrecurse_x2apic_level10)
+	.quad _C_LABEL(Xresume_x2apic_level10)
+	.quad _C_LABEL(Xintr_x2apic_level11), _C_LABEL(Xrecurse_x2apic_level11)
+	.quad _C_LABEL(Xresume_x2apic_level11)
+	.quad _C_LABEL(Xintr_x2apic_level12), _C_LABEL(Xrecurse_x2apic_level12)
+	.quad _C_LABEL(Xresume_x2apic_level12)
+	.quad _C_LABEL(Xintr_x2apic_level13), _C_LABEL(Xrecurse_x2apic_level13)
+	.quad _C_LABEL(Xresume_x2apic_level13)
+	.quad _C_LABEL(Xintr_x2apic_level14), _C_LABEL(Xrecurse_x2apic_level14)
+	.quad _C_LABEL(Xresume_x2apic_level14)
+	.quad _C_LABEL(Xintr_x2apic_level15), _C_LABEL(Xrecurse_x2apic_level15)
+	.quad _C_LABEL(Xresume_x2apic_level15)
+	.quad _C_LABEL(Xintr_x2apic_level16), _C_LABEL(Xrecurse_x2apic_level16)
+	.quad _C_LABEL(Xresume_x2apic_level16)
+	.quad _C_LABEL(Xintr_x2apic_level17), _C_LABEL(Xrecurse_x2apic_level17)
+	.quad _C_LABEL(Xresume_x2apic_level17)
+	.quad _C_LABEL(Xintr_x2apic_level18), _C_LABEL(Xrecurse_x2apic_level18)
+	.quad _C_LABEL(Xresume_x2apic_level18)
+	.quad _C_LABEL(Xintr_x2apic_level19), _C_LABEL(Xrecurse_x2apic_level19)
+	.quad _C_LABEL(Xresume_x2apic_level19)
+	.quad _C_LABEL(Xintr_x2apic_level20), _C_LABEL(Xrecurse_x2apic_level20)
+	.quad _C_LABEL(Xresume_x2apic_level20)
+	.quad _C_LABEL(Xintr_x2apic_level21), _C_LABEL(Xrecurse_x2apic_level21)
+	.quad _C_LABEL(Xresume_x2apic_level21)
+	.quad _C_LABEL(Xintr_x2apic_level22), _C_LABEL(Xrecurse_x2apic_level22)
+	.quad _C_LABEL(Xresume_x2apic_level22)
+	.quad _C_LABEL(Xintr_x2apic_level23), _C_LABEL(Xrecurse_x2apic_level23)
+	.quad _C_LABEL(Xresume_x2apic_level23)
+	.quad _C_LABEL(Xintr_x2apic_level24), _C_LABEL(Xrecurse_x2apic_level24)
+	.quad _C_LABEL(Xresume_x2apic_level24)
+	.quad _C_LABEL(Xintr_x2apic_level25), _C_LABEL(Xrecurse_x2apic_level25)
+	.quad _C_LABEL(Xresume_x2apic_level25)
+	.quad _C_LABEL(Xintr_x2apic_level26), _C_LABEL(Xrecurse_x2apic_level26)
+	.quad _C_LABEL(Xresume_x2apic_level26)
+	.quad _C_LABEL(Xintr_x2apic_level27), _C_LABEL(Xrecurse_x2apic_level27)
+	.quad _C_LABEL(Xresume_x2apic_level27)
+	.quad _C_LABEL(Xintr_x2apic_level28), _C_LABEL(Xrecurse_x2apic_level28)
+	.quad _C_LABEL(Xresume_x2apic_level28)
+	.quad _C_LABEL(Xintr_x2apic_level29), _C_LABEL(Xrecurse_x2apic_level29)
+	.quad _C_LABEL(Xresume_x2apic_level29)
+	.quad _C_LABEL(Xintr_x2apic_level30), _C_LABEL(Xrecurse_x2apic_level30)
+	.quad _C_LABEL(Xresume_x2apic_level30)
+	.quad _C_LABEL(Xintr_x2apic_level31), _C_LABEL(Xrecurse_x2apic_level31)
+	.quad _C_LABEL(Xresume_x2apic_level31)
+END(x2apic_level_stubs)
 #endif
 
 #else	/* !XEN */

Index: src/sys/arch/amd64/include/i82093reg.h
diff -u src/sys/arch/amd64/include/i82093reg.h:1.7 src/sys/arch/amd64/include/i82093reg.h:1.8
--- src/sys/arch/amd64/include/i82093reg.h:1.7	Fri Nov 25 14:12:55 2016
+++ src/sys/arch/amd64/include/i82093reg.h	Tue May 23 08:54:38 2017
@@ -1,4 +1,4 @@
-/*	 $NetBSD: i82093reg.h,v 1.7 2016/11/25 14:12:55 maxv Exp $ */
+/*	 $NetBSD: i82093reg.h,v 1.8 2017/05/23 08:54:38 nonaka Exp $ */
 
 #include <x86/i82093reg.h>
 
@@ -12,6 +12,12 @@
 	movq	_C_LABEL(local_apic_va),%rax	; \
 	movl	$0,LAPIC_EOI(%rax)
 
+#define x2apic_asm_ack(num) \
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx ; \
+	xorl	%eax,%eax			; \
+	xorl	%edx,%edx			; \
+	wrmsr
+
 #ifdef MULTIPROCESSOR
 
 #define ioapic_asm_lock(num) 			        \

Index: src/sys/arch/i386/i386/db_interface.c
diff -u src/sys/arch/i386/i386/db_interface.c:1.71 src/sys/arch/i386/i386/db_interface.c:1.72
--- src/sys/arch/i386/i386/db_interface.c:1.71	Fri Feb 28 10:16:51 2014
+++ src/sys/arch/i386/i386/db_interface.c	Tue May 23 08:54:38 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_interface.c,v 1.71 2014/02/28 10:16:51 skrll Exp $	*/
+/*	$NetBSD: db_interface.c,v 1.72 2017/05/23 08:54:38 nonaka Exp $	*/
 
 /*
  * Mach Operating System
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.71 2014/02/28 10:16:51 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.72 2017/05/23 08:54:38 nonaka Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -105,7 +105,7 @@ db_regs_t *ddb_regp = 0;
 int ddb_cpu = NOCPU;
 
 typedef void (vector)(void);
-extern vector Xintrddbipi;
+extern vector Xintrddbipi, Xx2apic_intrddbipi;
 
 void
 db_machine_init(void)
@@ -113,8 +113,13 @@ db_machine_init(void)
 
 #ifdef MULTIPROCESSOR
 #ifndef XEN
+	vector *handler = &Xintrddbipi;
+#if NLAPIC > 0
+	if (lapic_is_x2apic())
+		handler = &Xx2apic_intrddbipi;
+#endif
 	ddb_vec = idt_vec_alloc(0xf0, 0xff);
-	idt_vec_set(ddb_vec, &Xintrddbipi);
+	idt_vec_set(ddb_vec, handler);
 #else
 	/* Initialised as part of xen_ipi_init() */
 #endif /* XEN */

Index: src/sys/arch/i386/i386/mainbus.c
diff -u src/sys/arch/i386/i386/mainbus.c:1.102 src/sys/arch/i386/i386/mainbus.c:1.103
--- src/sys/arch/i386/i386/mainbus.c:1.102	Tue Jun 21 11:33:32 2016
+++ src/sys/arch/i386/i386/mainbus.c	Tue May 23 08:54:38 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mainbus.c,v 1.102 2016/06/21 11:33:32 nonaka Exp $	*/
+/*	$NetBSD: mainbus.c,v 1.103 2017/05/23 08:54:38 nonaka Exp $	*/
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.102 2016/06/21 11:33:32 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.103 2017/05/23 08:54:38 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -102,8 +102,6 @@ struct mainbus_softc {
 	device_t	sc_pci;
 	device_t	sc_mca;
 	device_t	sc_pnpbios;
-	bool		sc_acpi_present;
-	bool		sc_mpacpi_active;
 };
 
 CFATTACH_DECL2_NEW(mainbus, sizeof(struct mainbus_softc),
@@ -161,6 +159,9 @@ int mp_nintr;
 int mp_isa_bus = -1;            /* XXX */
 int mp_eisa_bus = -1;           /* XXX */
 
+bool acpi_present;
+bool mpacpi_active;
+
 # ifdef MPVERBOSE
 #  if MPVERBOSE > 0
 int mp_verbose = MPVERBOSE;
@@ -256,17 +257,17 @@ mainbus_attach(device_t parent, device_t
 
 #if NACPICA > 0
 	if ((boothowto & RB_MD2) == 0 && acpi_check(self, "acpibus"))
-		sc->sc_acpi_present = acpi_probe() != 0;
+		acpi_present = acpi_probe() != 0;
 	/*
 	 * First, see if the MADT contains CPUs, and possibly I/O APICs.
 	 * Building the interrupt routing structures can only
 	 * be done later (via a callback).
 	 */
-	if (sc->sc_acpi_present)
-		sc->sc_mpacpi_active = mpacpi_scan_apics(self, &numcpus) != 0;
+	if (acpi_present)
+		mpacpi_active = mpacpi_scan_apics(self, &numcpus) != 0;
 #endif
 
-	if (!sc->sc_mpacpi_active) {
+	if (!mpacpi_active) {
 #ifdef MPBIOS
 		if (mpbios_present)
 			mpbios_scan(self, &numcpus);
@@ -335,7 +336,7 @@ mainbus_rescan(device_t self, const char
 #endif
 
 	if (ifattr_match(ifattr, "acpibus") && sc->sc_acpi == NULL &&
-	    sc->sc_acpi_present) {
+	    acpi_present) {
 #if NACPICA > 0
 		mba.mba_acpi.aa_iot = x86_bus_space_io;
 		mba.mba_acpi.aa_memt = x86_bus_space_mem;
@@ -415,7 +416,7 @@ mainbus_rescan(device_t self, const char
 		mba.mba_pba.pba_sub = 255;
 		mba.mba_pba.pba_bridgetag = NULL;
 #if NACPICA > 0 && defined(ACPI_SCANPCI)
-		if (npcibus == 0 && sc->sc_mpacpi_active)
+		if (npcibus == 0 && mpacpi_active)
 			npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint);
 #endif
 #if defined(MPBIOS) && defined(MPBIOS_SCANPCI)

Index: src/sys/arch/i386/i386/vector.S
diff -u src/sys/arch/i386/i386/vector.S:1.68 src/sys/arch/i386/i386/vector.S:1.69
--- src/sys/arch/i386/i386/vector.S:1.68	Fri Nov 25 14:12:55 2016
+++ src/sys/arch/i386/i386/vector.S	Tue May 23 08:54:38 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: vector.S,v 1.68 2016/11/25 14:12:55 maxv Exp $	*/
+/*	$NetBSD: vector.S,v 1.69 2017/05/23 08:54:38 nonaka Exp $	*/
 
 /*
  * Copyright 2002 (c) Wasabi Systems, Inc.
@@ -65,7 +65,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: vector.S,v 1.68 2016/11/25 14:12:55 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vector.S,v 1.69 2017/05/23 08:54:38 nonaka Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -158,6 +158,19 @@ IDTVEC(recurse_lapic_ipi)
 	INTRENTRY
 	jmp	1f
 IDTVEC_END(recurse_lapic_ipi)
+IDTVEC(intr_x2apic_ipi)
+	pushl	$0
+	pushl	$T_ASTFLT
+	INTRENTRY
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	movl	CPUVAR(ILEVEL),%ebx
+	cmpl	$IPL_HIGH,%ebx
+	jae	2f
+	jmp	1f
+IDTVEC_END(intr_x2apic_ipi)
 IDTVEC(intr_lapic_ipi)
 	pushl	$0
 	pushl	$T_ASTFLT
@@ -195,6 +208,18 @@ IDTVEC(intr_lapic_tlb)
 	INTRFASTEXIT
 IDTVEC_END(intr_lapic_tlb)
 
+IDTVEC(intr_x2apic_tlb)
+	pushl	$0
+	pushl	$T_ASTFLT
+	INTRENTRY
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	call	_C_LABEL(pmap_tlb_intr)
+	INTRFASTEXIT
+IDTVEC_END(intr_x2apic_tlb)
+
 #if defined(DDB)
 /*
  * No need to use INTRENTRY, since we were brought here through a task-gate
@@ -219,6 +244,32 @@ IDTVEC(intrddbipi)
 	iret
 	jmp	1b
 IDTVEC_END(intrddbipi)
+
+IDTVEC(x2apic_intrddbipi)
+1:
+	str	%ax
+	GET_TSS
+	movzwl	(%eax),%eax
+	GET_TSS
+	pushl	%eax
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_TPRI),%ecx
+	movl	0xff,%eax
+	xorl	%edx,%edx
+	wrmsr
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	sti
+	call	_C_LABEL(ddb_ipi_tss)
+	addl	$4,%esp
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_TPRI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	iret
+	jmp	1b
+IDTVEC_END(x2apic_intrddbipi)
 #endif /* DDB */
 #endif /* MULTIPROCESSOR */
 
@@ -234,6 +285,19 @@ IDTVEC(recurse_lapic_ltimer)
 	INTRENTRY
 	jmp	1f
 IDTVEC_END(recurse_lapic_ltimer)
+IDTVEC(intr_x2apic_ltimer)
+	pushl	$0
+	pushl	$T_ASTFLT
+	INTRENTRY
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	wrmsr
+	movl	CPUVAR(ILEVEL),%ebx
+	cmpl	$IPL_CLOCK,%ebx
+	jae	2f
+	jmp	1f
+IDTVEC_END(intr_x2apic_ltimer)
 IDTVEC(intr_lapic_ltimer)
 	pushl	$0
 	pushl	$T_ASTFLT
@@ -243,6 +307,7 @@ IDTVEC(intr_lapic_ltimer)
 	movl	CPUVAR(ILEVEL),%ebx
 	cmpl	$IPL_CLOCK,%ebx
 	jae	2f
+IDTVEC_END(intr_lapic_ltimer)
 IDTVEC(resume_lapic_ltimer)
 1:
 	pushl	%ebx
@@ -257,7 +322,7 @@ IDTVEC(resume_lapic_ltimer)
 2:
 	orl	$(1 << LIR_TIMER),CPUVAR(IPENDING)
 	INTRFASTEXIT
-IDTVEC_END(intr_lapic_ltimer)
+IDTVEC_END(resume_lapic_ltimer)
 #endif /* NLAPIC > 0 */
 
 
@@ -450,6 +515,72 @@ INTRSTUB(ioapic_level,29,voidop,ioapic_a
 INTRSTUB(ioapic_level,30,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
 INTRSTUB(ioapic_level,31,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
 
+INTRSTUB(x2apic_edge,0,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,1,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,2,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,3,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,4,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,5,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,6,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,7,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,8,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,9,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,10,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,11,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,12,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,13,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,14,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,15,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,16,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,17,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,18,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,19,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,20,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,21,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,22,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,23,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,24,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,25,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,26,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,27,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,28,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,29,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,30,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(x2apic_edge,31,voidop,x2apic_asm_ack,voidop,voidop,voidop)
+
+INTRSTUB(x2apic_level,0,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,1,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,2,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,3,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,4,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,5,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,6,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,7,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,8,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,9,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,10,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,11,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,12,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,13,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,14,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,15,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,16,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,17,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,18,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,19,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,20,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,21,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,22,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,23,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,24,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,25,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,26,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,27,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,28,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,29,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,30,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(x2apic_level,31,voidop,x2apic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+
 #endif
 
 	.type	_C_LABEL(i8259_stubs), @object
@@ -624,6 +755,142 @@ LABEL(ioapic_level_stubs)
 	.long _C_LABEL(Xintr_ioapic_level31), _C_LABEL(Xrecurse_ioapic_level31)
 	.long _C_LABEL(Xresume_ioapic_level31)
 END(ioapic_level_stubs)
+
+	.type	_C_LABEL(x2apic_edge_stubs), @object
+LABEL(x2apic_edge_stubs)
+	.long _C_LABEL(Xintr_x2apic_edge0), _C_LABEL(Xrecurse_x2apic_edge0)
+	.long _C_LABEL(Xresume_x2apic_edge0)
+	.long _C_LABEL(Xintr_x2apic_edge1), _C_LABEL(Xrecurse_x2apic_edge1)
+	.long _C_LABEL(Xresume_x2apic_edge1)
+	.long _C_LABEL(Xintr_x2apic_edge2), _C_LABEL(Xrecurse_x2apic_edge2)
+	.long _C_LABEL(Xresume_x2apic_edge2)
+	.long _C_LABEL(Xintr_x2apic_edge3), _C_LABEL(Xrecurse_x2apic_edge3)
+	.long _C_LABEL(Xresume_x2apic_edge3)
+	.long _C_LABEL(Xintr_x2apic_edge4), _C_LABEL(Xrecurse_x2apic_edge4)
+	.long _C_LABEL(Xresume_x2apic_edge4)
+	.long _C_LABEL(Xintr_x2apic_edge5), _C_LABEL(Xrecurse_x2apic_edge5)
+	.long _C_LABEL(Xresume_x2apic_edge5)
+	.long _C_LABEL(Xintr_x2apic_edge6), _C_LABEL(Xrecurse_x2apic_edge6)
+	.long _C_LABEL(Xresume_x2apic_edge6)
+	.long _C_LABEL(Xintr_x2apic_edge7), _C_LABEL(Xrecurse_x2apic_edge7)
+	.long _C_LABEL(Xresume_x2apic_edge7)
+	.long _C_LABEL(Xintr_x2apic_edge8), _C_LABEL(Xrecurse_x2apic_edge8)
+	.long _C_LABEL(Xresume_x2apic_edge8)
+	.long _C_LABEL(Xintr_x2apic_edge9), _C_LABEL(Xrecurse_x2apic_edge9)
+	.long _C_LABEL(Xresume_x2apic_edge9)
+	.long _C_LABEL(Xintr_x2apic_edge10), _C_LABEL(Xrecurse_x2apic_edge10)
+	.long _C_LABEL(Xresume_x2apic_edge10)
+	.long _C_LABEL(Xintr_x2apic_edge11), _C_LABEL(Xrecurse_x2apic_edge11)
+	.long _C_LABEL(Xresume_x2apic_edge11)
+	.long _C_LABEL(Xintr_x2apic_edge12), _C_LABEL(Xrecurse_x2apic_edge12)
+	.long _C_LABEL(Xresume_x2apic_edge12)
+	.long _C_LABEL(Xintr_x2apic_edge13), _C_LABEL(Xrecurse_x2apic_edge13)
+	.long _C_LABEL(Xresume_x2apic_edge13)
+	.long _C_LABEL(Xintr_x2apic_edge14), _C_LABEL(Xrecurse_x2apic_edge14)
+	.long _C_LABEL(Xresume_x2apic_edge14)
+	.long _C_LABEL(Xintr_x2apic_edge15), _C_LABEL(Xrecurse_x2apic_edge15)
+	.long _C_LABEL(Xresume_x2apic_edge15)
+	.long _C_LABEL(Xintr_x2apic_edge16), _C_LABEL(Xrecurse_x2apic_edge16)
+	.long _C_LABEL(Xresume_x2apic_edge16)
+	.long _C_LABEL(Xintr_x2apic_edge17), _C_LABEL(Xrecurse_x2apic_edge17)
+	.long _C_LABEL(Xresume_x2apic_edge17)
+	.long _C_LABEL(Xintr_x2apic_edge18), _C_LABEL(Xrecurse_x2apic_edge18)
+	.long _C_LABEL(Xresume_x2apic_edge18)
+	.long _C_LABEL(Xintr_x2apic_edge19), _C_LABEL(Xrecurse_x2apic_edge19)
+	.long _C_LABEL(Xresume_x2apic_edge19)
+	.long _C_LABEL(Xintr_x2apic_edge20), _C_LABEL(Xrecurse_x2apic_edge20)
+	.long _C_LABEL(Xresume_x2apic_edge20)
+	.long _C_LABEL(Xintr_x2apic_edge21), _C_LABEL(Xrecurse_x2apic_edge21)
+	.long _C_LABEL(Xresume_x2apic_edge21)
+	.long _C_LABEL(Xintr_x2apic_edge22), _C_LABEL(Xrecurse_x2apic_edge22)
+	.long _C_LABEL(Xresume_x2apic_edge22)
+	.long _C_LABEL(Xintr_x2apic_edge23), _C_LABEL(Xrecurse_x2apic_edge23)
+	.long _C_LABEL(Xresume_x2apic_edge23)
+	.long _C_LABEL(Xintr_x2apic_edge24), _C_LABEL(Xrecurse_x2apic_edge24)
+	.long _C_LABEL(Xresume_x2apic_edge24)
+	.long _C_LABEL(Xintr_x2apic_edge25), _C_LABEL(Xrecurse_x2apic_edge25)
+	.long _C_LABEL(Xresume_x2apic_edge25)
+	.long _C_LABEL(Xintr_x2apic_edge26), _C_LABEL(Xrecurse_x2apic_edge26)
+	.long _C_LABEL(Xresume_x2apic_edge26)
+	.long _C_LABEL(Xintr_x2apic_edge27), _C_LABEL(Xrecurse_x2apic_edge27)
+	.long _C_LABEL(Xresume_x2apic_edge27)
+	.long _C_LABEL(Xintr_x2apic_edge28), _C_LABEL(Xrecurse_x2apic_edge28)
+	.long _C_LABEL(Xresume_x2apic_edge28)
+	.long _C_LABEL(Xintr_x2apic_edge29), _C_LABEL(Xrecurse_x2apic_edge29)
+	.long _C_LABEL(Xresume_x2apic_edge29)
+	.long _C_LABEL(Xintr_x2apic_edge30), _C_LABEL(Xrecurse_x2apic_edge30)
+	.long _C_LABEL(Xresume_x2apic_edge30)
+	.long _C_LABEL(Xintr_x2apic_edge31), _C_LABEL(Xrecurse_x2apic_edge31)
+	.long _C_LABEL(Xresume_x2apic_edge31)
+END(x2apic_edge_stubs)
+
+	.type	_C_LABEL(x2apic_level_stubs), @object
+LABEL(x2apic_level_stubs)
+	.long _C_LABEL(Xintr_x2apic_level0), _C_LABEL(Xrecurse_x2apic_level0)
+	.long _C_LABEL(Xresume_x2apic_level0)
+	.long _C_LABEL(Xintr_x2apic_level1), _C_LABEL(Xrecurse_x2apic_level1)
+	.long _C_LABEL(Xresume_x2apic_level1)
+	.long _C_LABEL(Xintr_x2apic_level2), _C_LABEL(Xrecurse_x2apic_level2)
+	.long _C_LABEL(Xresume_x2apic_level2)
+	.long _C_LABEL(Xintr_x2apic_level3), _C_LABEL(Xrecurse_x2apic_level3)
+	.long _C_LABEL(Xresume_x2apic_level3)
+	.long _C_LABEL(Xintr_x2apic_level4), _C_LABEL(Xrecurse_x2apic_level4)
+	.long _C_LABEL(Xresume_x2apic_level4)
+	.long _C_LABEL(Xintr_x2apic_level5), _C_LABEL(Xrecurse_x2apic_level5)
+	.long _C_LABEL(Xresume_x2apic_level5)
+	.long _C_LABEL(Xintr_x2apic_level6), _C_LABEL(Xrecurse_x2apic_level6)
+	.long _C_LABEL(Xresume_x2apic_level6)
+	.long _C_LABEL(Xintr_x2apic_level7), _C_LABEL(Xrecurse_x2apic_level7)
+	.long _C_LABEL(Xresume_x2apic_level7)
+	.long _C_LABEL(Xintr_x2apic_level8), _C_LABEL(Xrecurse_x2apic_level8)
+	.long _C_LABEL(Xresume_x2apic_level8)
+	.long _C_LABEL(Xintr_x2apic_level9), _C_LABEL(Xrecurse_x2apic_level9)
+	.long _C_LABEL(Xresume_x2apic_level9)
+	.long _C_LABEL(Xintr_x2apic_level10), _C_LABEL(Xrecurse_x2apic_level10)
+	.long _C_LABEL(Xresume_x2apic_level10)
+	.long _C_LABEL(Xintr_x2apic_level11), _C_LABEL(Xrecurse_x2apic_level11)
+	.long _C_LABEL(Xresume_x2apic_level11)
+	.long _C_LABEL(Xintr_x2apic_level12), _C_LABEL(Xrecurse_x2apic_level12)
+	.long _C_LABEL(Xresume_x2apic_level12)
+	.long _C_LABEL(Xintr_x2apic_level13), _C_LABEL(Xrecurse_x2apic_level13)
+	.long _C_LABEL(Xresume_x2apic_level13)
+	.long _C_LABEL(Xintr_x2apic_level14), _C_LABEL(Xrecurse_x2apic_level14)
+	.long _C_LABEL(Xresume_x2apic_level14)
+	.long _C_LABEL(Xintr_x2apic_level15), _C_LABEL(Xrecurse_x2apic_level15)
+	.long _C_LABEL(Xresume_x2apic_level15)
+	.long _C_LABEL(Xintr_x2apic_level16), _C_LABEL(Xrecurse_x2apic_level16)
+	.long _C_LABEL(Xresume_x2apic_level16)
+	.long _C_LABEL(Xintr_x2apic_level17), _C_LABEL(Xrecurse_x2apic_level17)
+	.long _C_LABEL(Xresume_x2apic_level17)
+	.long _C_LABEL(Xintr_x2apic_level18), _C_LABEL(Xrecurse_x2apic_level18)
+	.long _C_LABEL(Xresume_x2apic_level18)
+	.long _C_LABEL(Xintr_x2apic_level19), _C_LABEL(Xrecurse_x2apic_level19)
+	.long _C_LABEL(Xresume_x2apic_level19)
+	.long _C_LABEL(Xintr_x2apic_level20), _C_LABEL(Xrecurse_x2apic_level20)
+	.long _C_LABEL(Xresume_x2apic_level20)
+	.long _C_LABEL(Xintr_x2apic_level21), _C_LABEL(Xrecurse_x2apic_level21)
+	.long _C_LABEL(Xresume_x2apic_level21)
+	.long _C_LABEL(Xintr_x2apic_level22), _C_LABEL(Xrecurse_x2apic_level22)
+	.long _C_LABEL(Xresume_x2apic_level22)
+	.long _C_LABEL(Xintr_x2apic_level23), _C_LABEL(Xrecurse_x2apic_level23)
+	.long _C_LABEL(Xresume_x2apic_level23)
+	.long _C_LABEL(Xintr_x2apic_level24), _C_LABEL(Xrecurse_x2apic_level24)
+	.long _C_LABEL(Xresume_x2apic_level24)
+	.long _C_LABEL(Xintr_x2apic_level25), _C_LABEL(Xrecurse_x2apic_level25)
+	.long _C_LABEL(Xresume_x2apic_level25)
+	.long _C_LABEL(Xintr_x2apic_level26), _C_LABEL(Xrecurse_x2apic_level26)
+	.long _C_LABEL(Xresume_x2apic_level26)
+	.long _C_LABEL(Xintr_x2apic_level27), _C_LABEL(Xrecurse_x2apic_level27)
+	.long _C_LABEL(Xresume_x2apic_level27)
+	.long _C_LABEL(Xintr_x2apic_level28), _C_LABEL(Xrecurse_x2apic_level28)
+	.long _C_LABEL(Xresume_x2apic_level28)
+	.long _C_LABEL(Xintr_x2apic_level29), _C_LABEL(Xrecurse_x2apic_level29)
+	.long _C_LABEL(Xresume_x2apic_level29)
+	.long _C_LABEL(Xintr_x2apic_level30), _C_LABEL(Xrecurse_x2apic_level30)
+	.long _C_LABEL(Xresume_x2apic_level30)
+	.long _C_LABEL(Xintr_x2apic_level31), _C_LABEL(Xrecurse_x2apic_level31)
+	.long _C_LABEL(Xresume_x2apic_level31)
+END(x2apic_level_stubs)
 #endif
 #else /* XEN */
 #define voidop(num)

Index: src/sys/arch/i386/include/i82093reg.h
diff -u src/sys/arch/i386/include/i82093reg.h:1.9 src/sys/arch/i386/include/i82093reg.h:1.10
--- src/sys/arch/i386/include/i82093reg.h:1.9	Fri Nov 25 14:12:55 2016
+++ src/sys/arch/i386/include/i82093reg.h	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	 $NetBSD: i82093reg.h,v 1.9 2016/11/25 14:12:55 maxv Exp $ */
+/*	 $NetBSD: i82093reg.h,v 1.10 2017/05/23 08:54:39 nonaka Exp $ */
 
 #include <x86/i82093reg.h>
 
@@ -12,6 +12,12 @@
 	movl	_C_LABEL(local_apic_va),%eax	; \
 	movl	$0,LAPIC_EOI(%eax)
 
+#define x2apic_asm_ack(num) \
+	movl	$(MSR_X2APIC_BASE + MSR_X2APIC_EOI),%ecx ; \
+	xorl	%eax,%eax			; \
+	xorl	%edx,%edx			; \
+	wrmsr
+
 #ifdef MULTIPROCESSOR
 
 #define ioapic_asm_lock(num) \

Index: src/sys/arch/x86/include/cpuvar.h
diff -u src/sys/arch/x86/include/cpuvar.h:1.49 src/sys/arch/x86/include/cpuvar.h:1.50
--- src/sys/arch/x86/include/cpuvar.h:1.49	Wed Apr 19 06:43:05 2017
+++ src/sys/arch/x86/include/cpuvar.h	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/* 	$NetBSD: cpuvar.h,v 1.49 2017/04/19 06:43:05 nonaka Exp $ */
+/* 	$NetBSD: cpuvar.h,v 1.50 2017/05/23 08:54:39 nonaka Exp $ */
 
 /*-
  * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc.
@@ -101,7 +101,7 @@ struct cpufeature_attach_args {
 #include "opt_multiprocessor.h"
 #endif /* defined(_KERNEL_OPT) */
 
-int x86_ipi(int, int, int);
+extern int (*x86_ipi)(int, int, int);
 int x86_ipi_init(int);
 int x86_ipi_startup(int, int);
 void x86_errata(void);
Index: src/sys/arch/x86/include/intr.h
diff -u src/sys/arch/x86/include/intr.h:1.49 src/sys/arch/x86/include/intr.h:1.50
--- src/sys/arch/x86/include/intr.h:1.49	Thu Jul  7 06:55:39 2016
+++ src/sys/arch/x86/include/intr.h	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.h,v 1.49 2016/07/07 06:55:39 msaitoh Exp $	*/
+/*	$NetBSD: intr.h,v 1.50 2017/05/23 08:54:39 nonaka Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -177,6 +177,8 @@ void Xpreemptresume(void);
 extern struct intrstub i8259_stubs[];
 extern struct intrstub ioapic_edge_stubs[];
 extern struct intrstub ioapic_level_stubs[];
+extern struct intrstub x2apic_edge_stubs[];
+extern struct intrstub x2apic_level_stubs[];
 
 struct cpu_info;
 

Index: src/sys/arch/x86/include/i82489var.h
diff -u src/sys/arch/x86/include/i82489var.h:1.18 src/sys/arch/x86/include/i82489var.h:1.19
--- src/sys/arch/x86/include/i82489var.h:1.18	Sat Apr 22 04:29:31 2017
+++ src/sys/arch/x86/include/i82489var.h	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: i82489var.h,v 1.18 2017/04/22 04:29:31 nonaka Exp $	*/
+/*	$NetBSD: i82489var.h,v 1.19 2017/05/23 08:54:39 nonaka Exp $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -36,27 +36,11 @@
  * Software definitions belonging to Local APIC driver.
  */
 
-static __inline uint32_t i82489_readreg(int);
-static __inline void i82489_writereg(int, uint32_t);
-
 #ifdef _KERNEL
 extern volatile vaddr_t local_apic_va;
+extern bool x2apic_mode;
 #endif
 
-static __inline uint32_t
-i82489_readreg(int reg)
-{
-	return *((volatile uint32_t *)(local_apic_va + reg));
-}
-
-static __inline void
-i82489_writereg(int reg, uint32_t val)
-{
-	*((volatile uint32_t *)(local_apic_va + reg)) = val;
-}
-
-#define lapic_cpu_number() 	(i82489_readreg(LAPIC_ID) >> LAPIC_ID_SHIFT)
-
 /*
  * "spurious interrupt vector"; vector used by interrupt which was
  * aborted because the CPU masked it after it happened but before it
@@ -70,11 +54,13 @@ extern void Xintrspurious(void);
  * Vectors used for inter-processor interrupts.
  */
 extern void Xintr_lapic_ipi(void);
+extern void Xintr_x2apic_ipi(void);
 extern void Xrecurse_lapic_ipi(void);
 extern void Xresume_lapic_ipi(void);
 #define LAPIC_IPI_VECTOR			0xe0
 
 extern void Xintr_lapic_tlb(void);
+extern void Xintr_x2apic_tlb(void);
 #define LAPIC_TLB_VECTOR			0xe1
 
 /*
@@ -82,6 +68,7 @@ extern void Xintr_lapic_tlb(void);
  */
 
 extern void Xintr_lapic_ltimer(void);
+extern void Xintr_x2apic_ltimer(void);
 extern void Xresume_lapic_ltimer(void);
 extern void Xrecurse_lapic_ltimer(void);
 #define LAPIC_TIMER_VECTOR		0xc0
@@ -104,6 +91,11 @@ extern void lapic_enable(void);
 extern void lapic_calibrate_timer(struct cpu_info *ci);
 extern void lapic_initclocks(void);
 
+extern uint32_t lapic_readreg(u_int);
+extern void lapic_writereg(u_int, uint32_t);
 extern void lapic_write_tpri(uint32_t);
+extern void lapic_eoi(void);
+extern uint32_t lapic_cpu_number(void);
+extern bool lapic_is_x2apic(void);
 
 #endif

Index: src/sys/arch/x86/include/mpacpi.h
diff -u src/sys/arch/x86/include/mpacpi.h:1.10 src/sys/arch/x86/include/mpacpi.h:1.11
--- src/sys/arch/x86/include/mpacpi.h:1.10	Sun Mar 31 19:45:06 2013
+++ src/sys/arch/x86/include/mpacpi.h	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mpacpi.h,v 1.10 2013/03/31 19:45:06 chs Exp $	*/
+/*	$NetBSD: mpacpi.h,v 1.11 2017/05/23 08:54:39 nonaka Exp $	*/
 
 #ifndef _X86_MPACPI_H_
 #define _X86_MPACPI_H_
@@ -13,4 +13,7 @@ int mpacpi_pci_attach_hook(device_t, dev
 struct mp_intr_map;
 int mpacpi_findintr_linkdev(struct mp_intr_map *);
 
+extern bool acpi_present;
+extern bool mpacpi_active;
+
 #endif /* _X86_MPACPI_H_ */

Index: src/sys/arch/x86/pci/msipic.c
diff -u src/sys/arch/x86/pci/msipic.c:1.8 src/sys/arch/x86/pci/msipic.c:1.9
--- src/sys/arch/x86/pci/msipic.c:1.8	Tue Nov 17 17:51:42 2015
+++ src/sys/arch/x86/pci/msipic.c	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: msipic.c,v 1.8 2015/11/17 17:51:42 msaitoh Exp $	*/
+/*	$NetBSD: msipic.c,v 1.9 2017/05/23 08:54:39 nonaka Exp $	*/
 
 /*
  * Copyright (c) 2015 Internet Initiative Japan Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msipic.c,v 1.8 2015/11/17 17:51:42 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msipic.c,v 1.9 2017/05/23 08:54:39 nonaka Exp $");
 
 #include "opt_intrdebug.h"
 
@@ -42,6 +42,7 @@ __KERNEL_RCSID(0, "$NetBSD: msipic.c,v 1
 #include <dev/pci/pcivar.h>
 
 #include <machine/i82489reg.h>
+#include <machine/i82489var.h>
 #include <machine/i82093reg.h>
 #include <machine/i82093var.h>
 #include <machine/pic.h>
@@ -257,6 +258,7 @@ msipic_construct_common_msi_pic(const st
 	}
 
 	memcpy(pic, pic_tmpl, sizeof(*pic));
+	pic->pic_edge_stubs = x2apic_mode ? x2apic_edge_stubs : ioapic_edge_stubs,
 	pic->pic_msipic = msipic;
 	msipic->mp_pic = pic;
 	pci_decompose_tag(pa->pa_pc, pa->pa_tag,
@@ -431,8 +433,6 @@ static struct pic msi_pic_tmpl = {
 	.pic_hwunmask = msi_hwunmask,
 	.pic_addroute = msi_addroute,
 	.pic_delroute = msi_delroute,
-	.pic_edge_stubs = ioapic_edge_stubs,
-	.pic_ioapic = NULL,
 };
 
 /*
@@ -603,7 +603,6 @@ static struct pic msix_pic_tmpl = {
 	.pic_hwunmask = msix_hwunmask,
 	.pic_addroute = msix_addroute,
 	.pic_delroute = msix_delroute,
-	.pic_edge_stubs = ioapic_edge_stubs,
 };
 
 struct pic *

Index: src/sys/arch/x86/x86/cpu.c
diff -u src/sys/arch/x86/x86/cpu.c:1.124 src/sys/arch/x86/x86/cpu.c:1.125
--- src/sys/arch/x86/x86/cpu.c:1.124	Sat Apr 22 04:29:31 2017
+++ src/sys/arch/x86/x86/cpu.c	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.124 2017/04/22 04:29:31 nonaka Exp $	*/
+/*	$NetBSD: cpu.c,v 1.125 2017/05/23 08:54:39 nonaka Exp $	*/
 
 /*-
  * Copyright (c) 2000-2012 NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.124 2017/04/22 04:29:31 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.125 2017/05/23 08:54:39 nonaka Exp $");
 
 #include "opt_ddb.h"
 #include "opt_mpbios.h"		/* for MPDEBUG */
@@ -346,8 +346,8 @@ cpu_attach(device_t parent, device_t sel
 			aprint_verbose_dev(self, "running CPU at apic %d"
 			    " instead of at expected %d", lapic_cpu_number(),
 			    cpunum);
-			reg = i82489_readreg(LAPIC_ID);
-			i82489_writereg(LAPIC_ID, (reg & ~LAPIC_ID_MASK) |
+			reg = lapic_readreg(LAPIC_ID);
+			lapic_writereg(LAPIC_ID, (reg & ~LAPIC_ID_MASK) |
 			    (cpunum << LAPIC_ID_SHIFT));
 		}
 		if (cpunum != lapic_cpu_number()) {
@@ -972,7 +972,7 @@ tss_init(struct i386tss *tss, void *stac
 typedef void (vector)(void);
 extern vector IDTVEC(tss_trap08);
 #if defined(DDB) && defined(MULTIPROCESSOR)
-extern vector Xintrddbipi;
+extern vector Xintrddbipi, Xx2apic_intrddbipi;
 extern int ddb_vec;
 #endif
 
@@ -1001,7 +1001,8 @@ cpu_set_tss_gates(struct cpu_info *ci)
 	 */
 	ci->ci_ddbipi_stack = (char *)uvm_km_alloc(kernel_map, USPACE, 0,
 	    UVM_KMF_WIRED);
-	tss_init(&ci->ci_ddbipi_tss, ci->ci_ddbipi_stack, Xintrddbipi);
+	tss_init(&ci->ci_ddbipi_tss, ci->ci_ddbipi_stack,
+	    x2apic_mode ? Xx2apic_intrddbipi : Xintrddbipi);
 
 	setsegment(&sd, &ci->ci_ddbipi_tss, sizeof(struct i386tss) - 1,
 	    SDT_SYS386TSS, SEL_KPL, 0, 0);

Index: src/sys/arch/x86/x86/lapic.c
diff -u src/sys/arch/x86/x86/lapic.c:1.57 src/sys/arch/x86/x86/lapic.c:1.58
--- src/sys/arch/x86/x86/lapic.c:1.57	Tue May 23 03:23:58 2017
+++ src/sys/arch/x86/x86/lapic.c	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: lapic.c,v 1.57 2017/05/23 03:23:58 nonaka Exp $	*/
+/*	$NetBSD: lapic.c,v 1.58 2017/05/23 08:54:39 nonaka Exp $	*/
 
 /*-
  * Copyright (c) 2000, 2008 The NetBSD Foundation, Inc.
@@ -32,8 +32,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.57 2017/05/23 03:23:58 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.58 2017/05/23 08:54:39 nonaka Exp $");
 
+#include "acpica.h"
+#include "ioapic.h"
+#include "opt_acpi.h"
 #include "opt_ddb.h"
 #include "opt_mpbios.h"		/* for MPDEBUG */
 #include "opt_multiprocessor.h"
@@ -55,6 +58,7 @@ __KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.
 #include <machine/cpuvar.h>
 #include <machine/pmap.h>
 #include <machine/vmparam.h>
+#include <machine/mpacpi.h>
 #include <machine/mpbiosvar.h>
 #include <machine/pcb.h>
 #include <machine/specialreg.h>
@@ -66,11 +70,31 @@ __KERNEL_RCSID(0, "$NetBSD: lapic.c,v 1.
 #include <machine/i82489reg.h>
 #include <machine/i82489var.h>
 
+#if NACPICA > 0
+#include <dev/acpi/acpica.h>
+#include <dev/acpi/acpivar.h>
+#endif
+
+#ifdef DDB
+#include <machine/db_machdep.h>
+#ifdef MULTIPROCESSOR
+#ifdef __x86_64__
+typedef void (vector)(void);
+extern vector Xx2apic_intrddb;
+extern int ddb_vec;
+#endif
+#endif
+#endif
+
+#include <x86/x86/vmtreg.h>	/* for vmt_hvcall() */
+#include <x86/x86/vmtvar.h>	/* for vmt_hvcall() */
+
 /* Referenced from vector.S */
 void		lapic_clockintr(void *, struct intrframe *);
 
 static void	lapic_delay(unsigned int);
 static uint32_t lapic_gettick(void);
+static void 	lapic_setup_bsp(paddr_t);
 static void 	lapic_map(paddr_t);
 
 static void lapic_hwmask(struct pic *, int);
@@ -89,18 +113,241 @@ struct pic local_pic = {
 	.pic_delroute = lapic_setup,
 };
 
+static int i82489_ipi(int vec, int target, int dl);
+static int x2apic_ipi(int vec, int target, int dl);
+int (*x86_ipi)(int, int, int) = i82489_ipi;
+
+bool x2apic_mode __read_mostly;
+#ifdef LAPIC_ENABLE_X2APIC
+bool x2apic_enable = true;
+#else
+bool x2apic_enable = false;
+#endif
+
+static uint32_t
+i82489_readreg(u_int reg)
+{
+	return *((volatile uint32_t *)(local_apic_va + reg));
+}
+
+static void
+i82489_writereg(u_int reg, uint32_t val)
+{
+	*((volatile uint32_t *)(local_apic_va + reg)) = val;
+}
+
+static uint32_t
+i82489_cpu_number(void)
+{
+	return i82489_readreg(LAPIC_ID) >> LAPIC_ID_SHIFT;
+}
+
+static uint32_t
+x2apic_readreg(u_int reg)
+{
+	return rdmsr(MSR_X2APIC_BASE + (reg >> 4));
+}
+
+static void
+x2apic_writereg(u_int reg, uint32_t val)
+{
+	x86_mfence();
+	wrmsr(MSR_X2APIC_BASE + (reg >> 4), val);
+}
+
+static void
+x2apic_writereg64(u_int reg, uint64_t val)
+{
+	KDASSERT(reg == LAPIC_ICRLO);
+	x86_mfence();
+	wrmsr(MSR_X2APIC_BASE + (reg >> 4), val);
+}
+
+static void
+x2apic_write_icr(uint32_t hi, uint32_t lo)
+{
+	x2apic_writereg64(LAPIC_ICRLO, ((uint64_t)hi << 32) | lo);
+}
+
+static uint32_t
+x2apic_cpu_number(void)
+{
+	return x2apic_readreg(LAPIC_ID);
+}
+
+uint32_t
+lapic_readreg(u_int reg)
+{
+	if (x2apic_mode)
+		return x2apic_readreg(reg);
+	return i82489_readreg(reg);
+}
+
+void
+lapic_writereg(u_int reg, uint32_t val)
+{
+	if (x2apic_mode)
+		x2apic_writereg(reg, val);
+	else
+		i82489_writereg(reg, val);
+}
+
 void
 lapic_write_tpri(uint32_t val)
 {
 
 	val &= LAPIC_TPRI_MASK;
 #ifdef i386
-	i82489_writereg(LAPIC_TPRI, val);
+	lapic_writereg(LAPIC_TPRI, val);
 #else
 	lcr8(val >> 4);
 #endif
 }
 
+void
+lapic_eoi(void)
+{
+	lapic_writereg(LAPIC_EOI, 0);
+}
+
+uint32_t
+lapic_cpu_number(void)
+{
+	if (x2apic_mode)
+		return x2apic_cpu_number();
+	return i82489_cpu_number();
+}
+
+static void
+lapic_enable_x2apic(void)
+{
+	uint64_t apicbase;
+
+	apicbase = rdmsr(MSR_APICBASE);
+	if (!ISSET(apicbase, APICBASE_EN)) {
+		apicbase |= APICBASE_EN;
+		wrmsr(MSR_APICBASE, apicbase);
+	}
+	apicbase |= APICBASE_EXTD;
+	wrmsr(MSR_APICBASE, apicbase);
+}
+
+bool
+lapic_is_x2apic(void)
+{
+	uint64_t r;
+
+	r = rdmsr(MSR_APICBASE);
+	return (r & (APICBASE_EN | APICBASE_EXTD)) == (APICBASE_EN | APICBASE_EXTD);
+}
+
+/*
+ * Initialize the local APIC on the BSP.
+ */
+static void
+lapic_setup_bsp(paddr_t lapic_base)
+{
+	u_int regs[4];
+	const char *reason = NULL;
+	const char *hw_vendor;
+	bool bios_x2apic;
+
+	if (ISSET(cpu_feature[1], CPUID2_X2APIC)) {
+#if NACPICA > 0
+		if (acpi_present) {
+			ACPI_TABLE_DMAR *dmar;
+			ACPI_STATUS status;
+
+			/*
+			 * Automatically detect several configurations where
+			 * x2APIC mode is known to cause troubles.  User can
+			 * override the setting with hw.x2apic_enable tunable.
+			 */
+			status = AcpiGetTable(ACPI_SIG_DMAR, 1,
+			    (ACPI_TABLE_HEADER **)&dmar);
+			if (ACPI_SUCCESS(status)) {
+				if (ISSET(dmar->Flags, ACPI_DMAR_X2APIC_OPT_OUT)) {
+					reason = "by DMAR table";
+				}
+				AcpiPutTable(&dmar->Header);
+			}
+		}
+#endif	/* NACPICA > 0 */
+		if (vm_guest == VM_GUEST_VMWARE) {
+			vmt_hvcall(VM_CMD_GET_VCPU_INFO, regs);
+			if (ISSET(regs[0], VCPUINFO_VCPU_RESERVED) ||
+			    !ISSET(regs[0], VCPUINFO_LEGACY_X2APIC))
+				reason = "inside VMWare without intr redirection";
+		} else if (vm_guest == VM_GUEST_XEN) {
+			reason = "due to running under XEN";
+		} else if (vm_guest == VM_GUEST_NO &&
+		    CPUID_TO_FAMILY(curcpu()->ci_signature) == 6 &&
+		    CPUID_TO_MODEL(curcpu()->ci_signature) == 0x2a) {
+			hw_vendor = pmf_get_platform("board-vendor");
+			if (hw_vendor != NULL) {
+				/*
+				 * It seems that some Lenovo and ASUS
+				 * SandyBridge-based notebook BIOSes have a bug
+				 * which prevents booting AP in x2APIC mode.
+				 * Since the only way to detect mobile CPU is
+				 * to check northbridge pci id, which cannot be done
+				 * that early, disable x2APIC for all Lenovo and ASUS
+				 * SandyBridge machines.
+				 */
+				if (strcmp(hw_vendor, "LENOVO") == 0 ||
+				    strcmp(hw_vendor, "ASUSTeK Computer Inc.") == 0) {
+					reason =
+					    "for a suspected SandyBridge BIOS bug";
+				}
+			}
+		}
+		bios_x2apic = lapic_is_x2apic();
+		if (reason != NULL && bios_x2apic) {
+			aprint_verbose("x2APIC should be disabled %s but "
+			    "already enabled by BIOS; enabling.\n", reason);
+			reason = NULL;
+		}
+		if (reason == NULL)
+			x2apic_mode = true;
+		else
+			aprint_verbose("x2APIC available but disabled %s\n", reason);
+		if (x2apic_enable != x2apic_mode) {
+			if (bios_x2apic && !x2apic_enable)
+				aprint_verbose("x2APIC disabled by user and "
+				    "enabled by BIOS; ignoring user setting.\n");
+			else
+				x2apic_mode = x2apic_enable;
+		}
+	}
+	if (x2apic_mode) {
+		x86_ipi = x2apic_ipi;
+#if NIOAPIC > 0
+		struct ioapic_softc *ioapic;
+		for (ioapic = ioapics; ioapic != NULL; ioapic = ioapic->sc_next) {
+			ioapic->sc_pic.pic_edge_stubs = x2apic_edge_stubs;
+			ioapic->sc_pic.pic_level_stubs = x2apic_level_stubs;
+		}
+#endif
+#if defined(DDB) && defined(MULTIPROCESSOR)
+#ifdef __x86_64__
+		setgate(&idt[ddb_vec], &Xx2apic_intrddb, 1, SDT_SYS386IGT, SEL_KPL,
+		    GSEL(GCODE_SEL, SEL_KPL));
+#else
+		/* Set DDB IPI handler in cpu_set_tss_gates() when cpu0 is attached. */
+#endif
+#endif
+
+		x86_disable_intr();
+		lapic_enable_x2apic();
+#ifdef MULTIPROCESSOR
+		cpu_init_first();	/* catch up to changed cpu_number() */
+#endif
+		lapic_write_tpri(0);
+		x86_enable_intr();
+	} else
+		lapic_map(lapic_base);
+}
+
 static void
 lapic_map(paddr_t lapic_base)
 {
@@ -152,7 +399,7 @@ lapic_map(paddr_t lapic_base)
 void
 lapic_enable(void)
 {
-	i82489_writereg(LAPIC_SVR, LAPIC_SVR_ENABLE | LAPIC_SPURIOUS_VECTOR);
+	lapic_writereg(LAPIC_SVR, LAPIC_SVR_ENABLE | LAPIC_SPURIOUS_VECTOR);
 }
 
 void
@@ -166,9 +413,9 @@ lapic_set_lvt(void)
 #ifdef MULTIPROCESSOR
 	if (mp_verbose) {
 		apic_format_redir(device_xname(ci->ci_dev), "prelint", 0, 0,
-		    i82489_readreg(LAPIC_LVINT0));
+		    lapic_readreg(LAPIC_LVINT0));
 		apic_format_redir(device_xname(ci->ci_dev), "prelint", 1, 0,
-		    i82489_readreg(LAPIC_LVINT1));
+		    lapic_readreg(LAPIC_LVINT1));
 	}
 #endif
 
@@ -177,18 +424,18 @@ lapic_set_lvt(void)
 	 * the 8259A for interrupt delivery.  Otherwise request the LAPIC to
 	 * get external interrupts via LINT0 for the primary CPU.
 	 */
-	lint0 = LAPIC_DLMODE_EXTINT;
+	lint0 = LAPIC_LVT_DM_EXTINT;
 	if (nioapics > 0 || !CPU_IS_PRIMARY(curcpu()))
 		lint0 |= LAPIC_LVT_MASKED;
-	i82489_writereg(LAPIC_LVINT0, lint0);
+	lapic_writereg(LAPIC_LVINT0, lint0);
 
 	/*
 	 * Non Maskable Interrupts are to be delivered to the primary CPU.
 	 */
-	lint1 = LAPIC_DLMODE_NMI;
+	lint1 = LAPIC_LVT_DM_NMI;
 	if (!CPU_IS_PRIMARY(curcpu()))
 		lint1 |= LAPIC_LVT_MASKED;
-	i82489_writereg(LAPIC_LVINT1, lint1);
+	lapic_writereg(LAPIC_LVINT1, lint1);
 
 	for (i = 0; i < mp_nintr; i++) {
 		mpi = &mp_intrs[i];
@@ -199,9 +446,9 @@ lapic_set_lvt(void)
 				    "%s: WARNING: bad pin value %d\n",
 				    __func__, mpi->ioapic_pin);
 			if (mpi->ioapic_pin == 0)
-				i82489_writereg(LAPIC_LVINT0, mpi->redir);
+				lapic_writereg(LAPIC_LVINT0, mpi->redir);
 			else
-				i82489_writereg(LAPIC_LVINT1, mpi->redir);
+				lapic_writereg(LAPIC_LVINT1, mpi->redir);
 		}
 	}
 
@@ -217,25 +464,27 @@ lapic_set_lvt(void)
 void
 lapic_boot_init(paddr_t lapic_base)
 {
-	lapic_map(lapic_base);
+
+	lapic_setup_bsp(lapic_base);
 
 #ifdef MULTIPROCESSOR
 	idt_vec_reserve(LAPIC_IPI_VECTOR);
-	idt_vec_set(LAPIC_IPI_VECTOR, Xintr_lapic_ipi);
+	idt_vec_set(LAPIC_IPI_VECTOR, x2apic_mode ? Xintr_x2apic_ipi : Xintr_lapic_ipi);
 	idt_vec_reserve(LAPIC_TLB_VECTOR);
-	idt_vec_set(LAPIC_TLB_VECTOR, Xintr_lapic_tlb);
+	idt_vec_set(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(LAPIC_TIMER_VECTOR);
-	idt_vec_set(LAPIC_TIMER_VECTOR, Xintr_lapic_ltimer);
+	idt_vec_set(LAPIC_TIMER_VECTOR, x2apic_mode ? Xintr_x2apic_ltimer :
+	    Xintr_lapic_ltimer);
 }
 
 static uint32_t
 lapic_gettick(void)
 {
-	return i82489_readreg(LAPIC_CCR_TIMER);
+	return lapic_readreg(LAPIC_CCR_TIMER);
 }
 
 #include <sys/kernel.h>		/* for hz */
@@ -279,7 +528,7 @@ lapic_get_timecount(struct timecounter *
 	if (cur_timer >= lapic_tval - 1) {
 		uint16_t reg = LAPIC_IRR + LAPIC_TIMER_VECTOR / 32 * 16;
 
-		if (i82489_readreg(reg) & (1 << (LAPIC_TIMER_VECTOR % 32))) {
+		if (lapic_readreg(reg) & (1 << (LAPIC_TIMER_VECTOR % 32))) {
 			cur_timer -= lapic_tval;
 		}
 	} else if (ci->ci_istate.ipending & (1 << LIR_TIMER))
@@ -327,11 +576,11 @@ lapic_initclocks(void)
 	 * then set divisor,
 	 * then unmask and set the vector.
 	 */
-	i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_LVTT_M);
-	i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
-	i82489_writereg(LAPIC_ICR_TIMER, lapic_tval);
-	i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_TIMER_VECTOR);
-	i82489_writereg(LAPIC_EOI, 0);
+	lapic_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_LVTT_M);
+	lapic_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+	lapic_writereg(LAPIC_ICR_TIMER, lapic_tval);
+	lapic_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_TIMER_VECTOR);
+	lapic_eoi();
 }
 
 extern unsigned int gettick(void);	/* XXX put in header file */
@@ -364,9 +613,9 @@ lapic_calibrate_timer(struct cpu_info *c
 	 * Configure timer to one-shot, interrupt masked,
 	 * large positive number.
 	 */
-	i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_M);
-	i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
-	i82489_writereg(LAPIC_ICR_TIMER, 0x80000000);
+	lapic_writereg(LAPIC_LVTT, LAPIC_LVTT_M);
+	lapic_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+	lapic_writereg(LAPIC_ICR_TIMER, 0x80000000);
 
 	x86_disable_intr();
 
@@ -400,10 +649,10 @@ lapic_calibrate_timer(struct cpu_info *c
 		lapic_tval = (lapic_per_second * 2) / hz;
 		lapic_tval = (lapic_tval / 2) + (lapic_tval & 0x1);
 
-		i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_LVTT_M
+		lapic_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_LVTT_M
 		    | LAPIC_TIMER_VECTOR);
-		i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
-		i82489_writereg(LAPIC_ICR_TIMER, lapic_tval);
+		lapic_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+		lapic_writereg(LAPIC_ICR_TIMER, lapic_tval);
 
 		/*
 		 * Compute fixed-point ratios between cycles and
@@ -496,23 +745,21 @@ i82489_icr_wait(void)
 	}
 }
 
-int
-x86_ipi_init(int target)
+static int
+i82489_ipi_init(int target)
 {
 	uint32_t esr;
 
 	i82489_writereg(LAPIC_ESR, 0);
 	(void)i82489_readreg(LAPIC_ESR);
 
-	if ((target&LAPIC_DEST_MASK)==0)
-		i82489_writereg(LAPIC_ICRHI, target<<LAPIC_ID_SHIFT);
+	i82489_writereg(LAPIC_ICRHI, target << LAPIC_ID_SHIFT);
 
-	i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
-	    LAPIC_DLMODE_INIT | LAPIC_LEVEL_ASSERT );
+	i82489_writereg(LAPIC_ICRLO, LAPIC_DLMODE_INIT | LAPIC_LEVEL_ASSERT);
 	i82489_icr_wait();
 	i8254_delay(10000);
-	i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
-	     LAPIC_DLMODE_INIT | LAPIC_TRIGGER_LEVEL | LAPIC_LEVEL_DEASSERT);
+	i82489_writereg(LAPIC_ICRLO,
+	    LAPIC_DLMODE_INIT | LAPIC_TRIGGER_LEVEL | LAPIC_LEVEL_DEASSERT);
 	i82489_icr_wait();
 
 	if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) != 0)
@@ -520,13 +767,13 @@ x86_ipi_init(int target)
 
 	esr = i82489_readreg(LAPIC_ESR);
 	if (esr != 0)
-		aprint_debug("x86_ipi_init: ESR %08x\n", esr);
+		aprint_debug("%s: ESR %08x\n", __func__, esr);
 
 	return 0;
 }
 
-int
-x86_ipi_startup(int target, int vec)
+static int
+i82489_ipi_startup(int target, int vec)
 {
 	uint32_t esr;
 
@@ -544,13 +791,13 @@ x86_ipi_startup(int target, int vec)
 
 	esr = i82489_readreg(LAPIC_ESR);
 	if (esr != 0)
-		aprint_debug("x86_ipi_startup: ESR %08x\n", esr);
+		aprint_debug("%s: ESR %08x\n", __func__, esr);
 
 	return 0;
 }
 
-int
-x86_ipi(int vec, int target, int dl)
+static int
+i82489_ipi(int vec, int target, int dl)
 {
 	int result, s;
 
@@ -576,6 +823,58 @@ x86_ipi(int vec, int target, int dl)
 	return result;
 }
 
+static int
+x2apic_ipi_init(int target)
+{
+
+	x2apic_write_icr(target, LAPIC_DLMODE_INIT | LAPIC_LEVEL_ASSERT);
+
+	i8254_delay(10000);
+
+	x2apic_write_icr(0,
+	    LAPIC_DLMODE_INIT | LAPIC_TRIGGER_LEVEL | LAPIC_LEVEL_DEASSERT);
+
+	return 0;
+}
+
+static int
+x2apic_ipi_startup(int target, int vec)
+{
+
+	x2apic_write_icr(target, vec | LAPIC_DLMODE_STARTUP | LAPIC_LEVEL_ASSERT);
+
+	return 0;
+}
+
+static int
+x2apic_ipi(int vec, int target, int dl)
+{
+	uint32_t dest_id = 0;
+
+	if ((target & LAPIC_DEST_MASK) == 0)
+		dest_id = target;
+
+	x2apic_write_icr(dest_id,
+	    (target & LAPIC_DEST_MASK) | vec | dl | LAPIC_LEVEL_ASSERT);
+
+	return 0;
+}
+
+int
+x86_ipi_init(int target)
+{
+	if (x2apic_mode)
+		return x2apic_ipi_init(target);
+	return i82489_ipi_init(target);
+}
+
+int
+x86_ipi_startup(int target, int vec)
+{
+	if (x2apic_mode)
+		return x2apic_ipi_startup(target, vec);
+	return i82489_ipi_startup(target, vec);
+}
 
 /*
  * Using 'pin numbers' as:
@@ -594,9 +893,9 @@ lapic_hwmask(struct pic *pic, int pin)
 	uint32_t val;
 
 	reg = LAPIC_LVTT + (pin << 4);
-	val = i82489_readreg(reg);
+	val = lapic_readreg(reg);
 	val |= LAPIC_LVT_MASKED;
-	i82489_writereg(reg, val);
+	lapic_writereg(reg, val);
 }
 
 static void
@@ -606,9 +905,9 @@ lapic_hwunmask(struct pic *pic, int pin)
 	uint32_t val;
 
 	reg = LAPIC_LVTT + (pin << 4);
-	val = i82489_readreg(reg);
+	val = lapic_readreg(reg);
 	val &= ~LAPIC_LVT_MASKED;
-	i82489_writereg(reg, val);
+	lapic_writereg(reg, val);
 }
 
 static void
@@ -623,13 +922,13 @@ lapic_dump(void)
 	struct cpu_info *ci = curcpu();
 
 	apic_format_redir(device_xname(ci->ci_dev), "timer", 0, 0,
-	    i82489_readreg(LAPIC_LVTT));
+	    lapic_readreg(LAPIC_LVTT));
 	apic_format_redir(device_xname(ci->ci_dev), "pcint", 0, 0,
-	    i82489_readreg(LAPIC_PCINT));
+	    lapic_readreg(LAPIC_PCINT));
 	apic_format_redir(device_xname(ci->ci_dev), "lint", 0, 0,
-	    i82489_readreg(LAPIC_LVINT0));
+	    lapic_readreg(LAPIC_LVINT0));
 	apic_format_redir(device_xname(ci->ci_dev), "lint", 1, 0,
-	    i82489_readreg(LAPIC_LVINT1));
+	    lapic_readreg(LAPIC_LVINT1));
 	apic_format_redir(device_xname(ci->ci_dev), "err", 0, 0,
-	    i82489_readreg(LAPIC_LVERR));
+	    lapic_readreg(LAPIC_LVERR));
 }

Index: src/sys/arch/x86/x86/pmc.c
diff -u src/sys/arch/x86/x86/pmc.c:1.6 src/sys/arch/x86/x86/pmc.c:1.7
--- src/sys/arch/x86/x86/pmc.c:1.6	Tue Apr 18 15:14:28 2017
+++ src/sys/arch/x86/x86/pmc.c	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmc.c,v 1.6 2017/04/18 15:14:28 maya Exp $	*/
+/*	$NetBSD: pmc.c,v 1.7 2017/05/23 08:54:39 nonaka Exp $	*/
 
 /*
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.6 2017/04/18 15:14:28 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.7 2017/05/23 08:54:39 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -156,8 +156,8 @@ pmc_apply_cpu(void *arg1, void *arg2)
 	struct cpu_info *ci = curcpu();
 
 	if (start) {
-		pmc_lapic_image[cpu_index(ci)] = i82489_readreg(LAPIC_PCINT);
-		i82489_writereg(LAPIC_PCINT, LAPIC_DLMODE_NMI);
+		pmc_lapic_image[cpu_index(ci)] = lapic_readreg(LAPIC_PCINT);
+		lapic_writereg(LAPIC_PCINT, LAPIC_DLMODE_NMI);
 	}
 
 	wrmsr(pmc->ctrmsr, pmc->ctrinitval);
@@ -173,7 +173,7 @@ pmc_apply_cpu(void *arg1, void *arg2)
 	pmc_val_cpus[cpu_index(ci)].overfl = 0;
 
 	if (!start) {
-		i82489_writereg(LAPIC_PCINT, pmc_lapic_image[cpu_index(ci)]);
+		lapic_writereg(LAPIC_PCINT, pmc_lapic_image[cpu_index(ci)]);
 	}
 }
 
Index: src/sys/arch/x86/x86/tprof_amdpmi.c
diff -u src/sys/arch/x86/x86/tprof_amdpmi.c:1.6 src/sys/arch/x86/x86/tprof_amdpmi.c:1.7
--- src/sys/arch/x86/x86/tprof_amdpmi.c:1.6	Sat Feb 11 13:22:58 2017
+++ src/sys/arch/x86/x86/tprof_amdpmi.c	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: tprof_amdpmi.c,v 1.6 2017/02/11 13:22:58 maxv Exp $	*/
+/*	$NetBSD: tprof_amdpmi.c,v 1.7 2017/05/23 08:54:39 nonaka Exp $	*/
 
 /*-
  * Copyright (c)2008,2009 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tprof_amdpmi.c,v 1.6 2017/02/11 13:22:58 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tprof_amdpmi.c,v 1.7 2017/05/23 08:54:39 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -120,8 +120,8 @@ tprof_amdpmi_start_cpu(void *arg1, void 
 	wrmsr(PERFCTR(ctrno), counter_reset_val);
 	wrmsr(PERFEVTSEL(ctrno), pesr);
 
-	tprof_amdpmi_lapic_saved[cpu_index(ci)] = i82489_readreg(LAPIC_PCINT);
-	i82489_writereg(LAPIC_PCINT, LAPIC_DLMODE_NMI);
+	tprof_amdpmi_lapic_saved[cpu_index(ci)] = lapic_readreg(LAPIC_PCINT);
+	lapic_writereg(LAPIC_PCINT, LAPIC_DLMODE_NMI);
 
 	wrmsr(PERFEVTSEL(ctrno), pesr | PESR_EN);
 }
@@ -133,7 +133,7 @@ tprof_amdpmi_stop_cpu(void *arg1, void *
 
 	wrmsr(PERFEVTSEL(ctrno), 0);
 
-	i82489_writereg(LAPIC_PCINT, tprof_amdpmi_lapic_saved[cpu_index(ci)]);
+	lapic_writereg(LAPIC_PCINT, tprof_amdpmi_lapic_saved[cpu_index(ci)]);
 }
 
 static int

Index: src/sys/arch/x86/x86/tprof_pmi.c
diff -u src/sys/arch/x86/x86/tprof_pmi.c:1.13 src/sys/arch/x86/x86/tprof_pmi.c:1.14
--- src/sys/arch/x86/x86/tprof_pmi.c:1.13	Fri Nov 15 08:47:55 2013
+++ src/sys/arch/x86/x86/tprof_pmi.c	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: tprof_pmi.c,v 1.13 2013/11/15 08:47:55 msaitoh Exp $	*/
+/*	$NetBSD: tprof_pmi.c,v 1.14 2017/05/23 08:54:39 nonaka Exp $	*/
 
 /*-
  * Copyright (c)2008,2009 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tprof_pmi.c,v 1.13 2013/11/15 08:47:55 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tprof_pmi.c,v 1.14 2017/05/23 08:54:39 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -138,8 +138,8 @@ tprof_pmi_start_cpu(void *arg1, void *ar
 	wrmsr(msr->msr_counter, counter_reset_val);
 	wrmsr(msr->msr_escr, escr);
 	wrmsr(msr->msr_cccr, cccr);
-	tprof_pmi_lapic_saved[cpu_index(ci)] = i82489_readreg(LAPIC_PCINT);
-	i82489_writereg(LAPIC_PCINT, LAPIC_DLMODE_NMI);
+	tprof_pmi_lapic_saved[cpu_index(ci)] = lapic_readreg(LAPIC_PCINT);
+	lapic_writereg(LAPIC_PCINT, LAPIC_DLMODE_NMI);
 }
 
 static void
@@ -158,7 +158,7 @@ tprof_pmi_stop_cpu(void *arg1, void *arg
 
 	wrmsr(msr->msr_escr, 0);
 	wrmsr(msr->msr_cccr, 0);
-	i82489_writereg(LAPIC_PCINT, tprof_pmi_lapic_saved[cpu_index(ci)]);
+	lapic_writereg(LAPIC_PCINT, tprof_pmi_lapic_saved[cpu_index(ci)]);
 }
 
 static int
@@ -199,9 +199,9 @@ tprof_pmi_nmi(const struct trapframe *tf
 	wrmsr(msr->msr_cccr, cccr & ~CCCR_OVF);
 
 	/* unmask PMI */
-	pcint = i82489_readreg(LAPIC_PCINT);
+	pcint = lapic_readreg(LAPIC_PCINT);
 	KASSERT((pcint & LAPIC_LVT_MASKED) != 0);
-	i82489_writereg(LAPIC_PCINT, pcint & ~LAPIC_LVT_MASKED);
+	lapic_writereg(LAPIC_PCINT, pcint & ~LAPIC_LVT_MASKED);
 
 	return 1;
 }

Index: src/sys/arch/xen/include/intr.h
diff -u src/sys/arch/xen/include/intr.h:1.39 src/sys/arch/xen/include/intr.h:1.40
--- src/sys/arch/xen/include/intr.h:1.39	Mon Oct 17 18:23:50 2016
+++ src/sys/arch/xen/include/intr.h	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.h,v 1.39 2016/10/17 18:23:50 jdolecek Exp $	*/
+/*	$NetBSD: intr.h,v 1.40 2017/05/23 08:54:39 nonaka Exp $	*/
 /*	NetBSD intr.h,v 1.15 2004/10/31 10:39:34 yamt Exp	*/
 
 /*-
@@ -76,6 +76,8 @@ struct intrstub {
 extern struct intrstub i8259_stubs[];
 extern struct intrstub ioapic_edge_stubs[];
 extern struct intrstub ioapic_level_stubs[];
+extern struct intrstub x2apic_edge_stubs[];
+extern struct intrstub x2apic_level_stubs[];
 
 struct iplsource {
 	struct intrhand *ipl_handlers;   /* handler chain */

Index: src/sys/arch/xen/include/mpacpi.h
diff -u src/sys/arch/xen/include/mpacpi.h:1.1 src/sys/arch/xen/include/mpacpi.h:1.2
--- src/sys/arch/xen/include/mpacpi.h:1.1	Thu Sep 28 18:53:15 2006
+++ src/sys/arch/xen/include/mpacpi.h	Tue May 23 08:54:39 2017
@@ -1,5 +1,3 @@
-/*	$NetBSD: mpacpi.h,v 1.1 2006/09/28 18:53:15 bouyer Exp $	*/
+/*	$NetBSD: mpacpi.h,v 1.2 2017/05/23 08:54:39 nonaka Exp $	*/
 
 #include <x86/mpacpi.h>
-extern int acpi_present;
-extern int mpacpi_active;

Index: src/sys/arch/xen/x86/intr.c
diff -u src/sys/arch/xen/x86/intr.c:1.30 src/sys/arch/xen/x86/intr.c:1.31
--- src/sys/arch/xen/x86/intr.c:1.30	Mon Oct 17 18:23:50 2016
+++ src/sys/arch/xen/x86/intr.c	Tue May 23 08:54:39 2017
@@ -103,7 +103,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.30 2016/10/17 18:23:50 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.31 2017/05/23 08:54:39 nonaka Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_xen.h"
@@ -135,6 +135,8 @@ struct intrstub i8259_stubs[NUM_LEGACY_I
 /* for x86/ioapic.c */
 struct intrstub ioapic_edge_stubs[MAX_INTR_SOURCES] = {{0,0}};
 struct intrstub ioapic_level_stubs[MAX_INTR_SOURCES] = {{0,0}};
+struct intrstub x2apic_edge_stubs[MAX_INTR_SOURCES] = {{0,0}};
+struct intrstub x2apic_level_stubs[MAX_INTR_SOURCES] = {{0,0}};
 
 #include <machine/i82093var.h>
 int irq2vect[256] = {0};

Index: src/sys/arch/xen/x86/mainbus.c
diff -u src/sys/arch/xen/x86/mainbus.c:1.18 src/sys/arch/xen/x86/mainbus.c:1.19
--- src/sys/arch/xen/x86/mainbus.c:1.18	Mon Mar  3 22:09:32 2014
+++ src/sys/arch/xen/x86/mainbus.c	Tue May 23 08:54:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mainbus.c,v 1.18 2014/03/03 22:09:32 dsl Exp $	*/
+/*	$NetBSD: mainbus.c,v 1.19 2017/05/23 08:54:39 nonaka Exp $	*/
 /*	NetBSD: mainbus.c,v 1.53 2003/10/27 14:11:47 junyoung Exp 	*/
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.18 2014/03/03 22:09:32 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.19 2017/05/23 08:54:39 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -87,8 +87,8 @@ int mp_nintr;
 int mp_isa_bus = -1;	    /* XXX */
 int mp_eisa_bus = -1;	   /* XXX */
 
-int acpi_present = 0;
-int mpacpi_active = 0;
+bool acpi_present;
+bool mpacpi_active;
 #ifdef MPVERBOSE
 int mp_verbose = 1;
 #else /* MPVERBOSE */
@@ -168,9 +168,9 @@ mainbus_attach(device_t parent, device_t
 		}
 #endif /* PCI_BUS_FIXUP */
 #if NACPICA > 0
-		acpi_present = acpi_probe();
+		acpi_present = acpi_probe() != 0;
 		if (acpi_present)
-			mpacpi_active = mpacpi_scan_apics(self, &numcpus);
+			mpacpi_active = mpacpi_scan_apics(self, &numcpus) != 0;
 		if (!mpacpi_active)
 #endif
 		{

Reply via email to