xref: /freebsd/sys/x86/xen/xen_apic.c (revision 8114c8e1)
124f7e474SRoger Pau Monné /*
224f7e474SRoger Pau Monné  * Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com>
324f7e474SRoger Pau Monné  * All rights reserved.
424f7e474SRoger Pau Monné  *
524f7e474SRoger Pau Monné  * Redistribution and use in source and binary forms, with or without
624f7e474SRoger Pau Monné  * modification, are permitted provided that the following conditions
724f7e474SRoger Pau Monné  * are met:
824f7e474SRoger Pau Monné  * 1. Redistributions of source code must retain the above copyright
924f7e474SRoger Pau Monné  *    notice, this list of conditions and the following disclaimer.
1024f7e474SRoger Pau Monné  * 2. Redistributions in binary form must reproduce the above copyright
1124f7e474SRoger Pau Monné  *    notice, this list of conditions and the following disclaimer in the
1224f7e474SRoger Pau Monné  *    documentation and/or other materials provided with the distribution.
1324f7e474SRoger Pau Monné  *
1424f7e474SRoger Pau Monné  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
1524f7e474SRoger Pau Monné  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1624f7e474SRoger Pau Monné  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1724f7e474SRoger Pau Monné  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1824f7e474SRoger Pau Monné  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1924f7e474SRoger Pau Monné  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2024f7e474SRoger Pau Monné  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2124f7e474SRoger Pau Monné  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2224f7e474SRoger Pau Monné  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2324f7e474SRoger Pau Monné  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2424f7e474SRoger Pau Monné  * SUCH DAMAGE.
2524f7e474SRoger Pau Monné  */
2624f7e474SRoger Pau Monné 
2724f7e474SRoger Pau Monné #include <sys/cdefs.h>
2824f7e474SRoger Pau Monné __FBSDID("$FreeBSD$");
2924f7e474SRoger Pau Monné 
3024f7e474SRoger Pau Monné #include <sys/param.h>
3124f7e474SRoger Pau Monné #include <sys/bus.h>
3224f7e474SRoger Pau Monné #include <sys/kernel.h>
3324f7e474SRoger Pau Monné #include <sys/malloc.h>
3424f7e474SRoger Pau Monné #include <sys/proc.h>
3524f7e474SRoger Pau Monné #include <sys/smp.h>
3624f7e474SRoger Pau Monné #include <sys/systm.h>
3724f7e474SRoger Pau Monné 
3824f7e474SRoger Pau Monné #include <vm/vm.h>
3924f7e474SRoger Pau Monné #include <vm/pmap.h>
4024f7e474SRoger Pau Monné 
4124f7e474SRoger Pau Monné #include <machine/cpufunc.h>
4224f7e474SRoger Pau Monné #include <machine/cpu.h>
4324f7e474SRoger Pau Monné #include <machine/smp.h>
4424f7e474SRoger Pau Monné 
4524f7e474SRoger Pau Monné #include <x86/apicreg.h>
4624f7e474SRoger Pau Monné 
4724f7e474SRoger Pau Monné #include <xen/xen-os.h>
4824f7e474SRoger Pau Monné #include <xen/features.h>
4924f7e474SRoger Pau Monné #include <xen/gnttab.h>
5024f7e474SRoger Pau Monné #include <xen/hypervisor.h>
5124f7e474SRoger Pau Monné #include <xen/hvm.h>
5224f7e474SRoger Pau Monné #include <xen/xen_intr.h>
5324f7e474SRoger Pau Monné 
5424f7e474SRoger Pau Monné #include <xen/interface/vcpu.h>
5524f7e474SRoger Pau Monné 
5624f7e474SRoger Pau Monné /*--------------------------------- Macros -----------------------------------*/
5724f7e474SRoger Pau Monné 
5824f7e474SRoger Pau Monné #define XEN_APIC_UNSUPPORTED \
5924f7e474SRoger Pau Monné 	panic("%s: not available in Xen PV port.", __func__)
6024f7e474SRoger Pau Monné 
6124f7e474SRoger Pau Monné 
6224f7e474SRoger Pau Monné /*--------------------------- Forward Declarations ---------------------------*/
6324f7e474SRoger Pau Monné #ifdef SMP
6424f7e474SRoger Pau Monné static driver_filter_t xen_smp_rendezvous_action;
6524f7e474SRoger Pau Monné static driver_filter_t xen_invltlb;
6624f7e474SRoger Pau Monné static driver_filter_t xen_invlpg;
6724f7e474SRoger Pau Monné static driver_filter_t xen_invlrng;
6824f7e474SRoger Pau Monné static driver_filter_t xen_invlcache;
6924f7e474SRoger Pau Monné #ifdef __i386__
7024f7e474SRoger Pau Monné static driver_filter_t xen_lazypmap;
7124f7e474SRoger Pau Monné #endif
7224f7e474SRoger Pau Monné static driver_filter_t xen_ipi_bitmap_handler;
7324f7e474SRoger Pau Monné static driver_filter_t xen_cpustop_handler;
7424f7e474SRoger Pau Monné static driver_filter_t xen_cpususpend_handler;
7524f7e474SRoger Pau Monné static driver_filter_t xen_cpustophard_handler;
7624f7e474SRoger Pau Monné #endif
7724f7e474SRoger Pau Monné 
7824f7e474SRoger Pau Monné /*---------------------------- Extern Declarations ---------------------------*/
7924f7e474SRoger Pau Monné /* Variables used by mp_machdep to perform the MMU related IPIs */
8024f7e474SRoger Pau Monné #ifdef __i386__
8124f7e474SRoger Pau Monné extern void pmap_lazyfix_action(void);
8224f7e474SRoger Pau Monné #endif
8324f7e474SRoger Pau Monné #ifdef __amd64__
8424f7e474SRoger Pau Monné extern int pmap_pcid_enabled;
8524f7e474SRoger Pau Monné #endif
8624f7e474SRoger Pau Monné 
8724f7e474SRoger Pau Monné extern int xen_vector_callback_enabled;
8824f7e474SRoger Pau Monné 
8924f7e474SRoger Pau Monné /*---------------------------------- Macros ----------------------------------*/
9024f7e474SRoger Pau Monné #define	IPI_TO_IDX(ipi) ((ipi) - APIC_IPI_INTS)
9124f7e474SRoger Pau Monné 
9224f7e474SRoger Pau Monné /*--------------------------------- Xen IPIs ---------------------------------*/
9324f7e474SRoger Pau Monné #ifdef SMP
9424f7e474SRoger Pau Monné struct xen_ipi_handler
9524f7e474SRoger Pau Monné {
9624f7e474SRoger Pau Monné 	driver_filter_t	*filter;
9724f7e474SRoger Pau Monné 	const char	*description;
9824f7e474SRoger Pau Monné };
9924f7e474SRoger Pau Monné 
10024f7e474SRoger Pau Monné static struct xen_ipi_handler xen_ipis[] =
10124f7e474SRoger Pau Monné {
10224f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_RENDEZVOUS)]	= { xen_smp_rendezvous_action,	"r"   },
10324f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_INVLTLB)]	= { xen_invltlb,		"itlb"},
10424f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_INVLPG)]	= { xen_invlpg,			"ipg" },
10524f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_INVLRNG)]	= { xen_invlrng,		"irg" },
10624f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_INVLCACHE)]	= { xen_invlcache,		"ic"  },
10724f7e474SRoger Pau Monné #ifdef __i386__
10824f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_LAZYPMAP)]	= { xen_lazypmap,		"lp"  },
10924f7e474SRoger Pau Monné #endif
11024f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_BITMAP_VECTOR)] = { xen_ipi_bitmap_handler,	"b"   },
11124f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_STOP)]		= { xen_cpustop_handler,	"st"  },
11224f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_SUSPEND)]	= { xen_cpususpend_handler,	"sp"  },
11324f7e474SRoger Pau Monné 	[IPI_TO_IDX(IPI_STOP_HARD)]	= { xen_cpustophard_handler,	"sth" },
11424f7e474SRoger Pau Monné };
11524f7e474SRoger Pau Monné #endif
11624f7e474SRoger Pau Monné 
11724f7e474SRoger Pau Monné /*------------------------------- Per-CPU Data -------------------------------*/
11824f7e474SRoger Pau Monné #ifdef SMP
11924f7e474SRoger Pau Monné DPCPU_DEFINE(xen_intr_handle_t, ipi_handle[nitems(xen_ipis)]);
12024f7e474SRoger Pau Monné #endif
12124f7e474SRoger Pau Monné 
12224f7e474SRoger Pau Monné /*------------------------------- Xen PV APIC --------------------------------*/
12324f7e474SRoger Pau Monné 
12424f7e474SRoger Pau Monné static void
12524f7e474SRoger Pau Monné xen_pv_lapic_create(u_int apic_id, int boot_cpu)
12624f7e474SRoger Pau Monné {
12724f7e474SRoger Pau Monné #ifdef SMP
12824f7e474SRoger Pau Monné 	cpu_add(apic_id, boot_cpu);
12924f7e474SRoger Pau Monné #endif
13024f7e474SRoger Pau Monné }
13124f7e474SRoger Pau Monné 
13224f7e474SRoger Pau Monné static void
13324f7e474SRoger Pau Monné xen_pv_lapic_init(vm_paddr_t addr)
13424f7e474SRoger Pau Monné {
13524f7e474SRoger Pau Monné 
13624f7e474SRoger Pau Monné }
13724f7e474SRoger Pau Monné 
13824f7e474SRoger Pau Monné static void
13924f7e474SRoger Pau Monné xen_pv_lapic_setup(int boot)
14024f7e474SRoger Pau Monné {
14124f7e474SRoger Pau Monné 
14224f7e474SRoger Pau Monné }
14324f7e474SRoger Pau Monné 
14424f7e474SRoger Pau Monné static void
14524f7e474SRoger Pau Monné xen_pv_lapic_dump(const char *str)
14624f7e474SRoger Pau Monné {
14724f7e474SRoger Pau Monné 
14824f7e474SRoger Pau Monné 	printf("cpu%d %s XEN PV LAPIC\n", PCPU_GET(cpuid), str);
14924f7e474SRoger Pau Monné }
15024f7e474SRoger Pau Monné 
15124f7e474SRoger Pau Monné static void
15224f7e474SRoger Pau Monné xen_pv_lapic_disable(void)
15324f7e474SRoger Pau Monné {
15424f7e474SRoger Pau Monné 
15524f7e474SRoger Pau Monné }
15624f7e474SRoger Pau Monné 
15724f7e474SRoger Pau Monné static void
15824f7e474SRoger Pau Monné xen_pv_lapic_eoi(void)
15924f7e474SRoger Pau Monné {
16024f7e474SRoger Pau Monné 
16124f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
16224f7e474SRoger Pau Monné }
16324f7e474SRoger Pau Monné 
16424f7e474SRoger Pau Monné static int
16524f7e474SRoger Pau Monné xen_pv_lapic_id(void)
16624f7e474SRoger Pau Monné {
16724f7e474SRoger Pau Monné 
16824f7e474SRoger Pau Monné 	return (PCPU_GET(apic_id));
16924f7e474SRoger Pau Monné }
17024f7e474SRoger Pau Monné 
17124f7e474SRoger Pau Monné static int
17224f7e474SRoger Pau Monné xen_pv_lapic_intr_pending(u_int vector)
17324f7e474SRoger Pau Monné {
17424f7e474SRoger Pau Monné 
17524f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
17624f7e474SRoger Pau Monné 	return (0);
17724f7e474SRoger Pau Monné }
17824f7e474SRoger Pau Monné 
17924f7e474SRoger Pau Monné static u_int
18024f7e474SRoger Pau Monné xen_pv_apic_cpuid(u_int apic_id)
18124f7e474SRoger Pau Monné {
18224f7e474SRoger Pau Monné #ifdef SMP
18324f7e474SRoger Pau Monné 	return (apic_cpuids[apic_id]);
18424f7e474SRoger Pau Monné #else
18524f7e474SRoger Pau Monné 	return (0);
18624f7e474SRoger Pau Monné #endif
18724f7e474SRoger Pau Monné }
18824f7e474SRoger Pau Monné 
18924f7e474SRoger Pau Monné static u_int
19024f7e474SRoger Pau Monné xen_pv_apic_alloc_vector(u_int apic_id, u_int irq)
19124f7e474SRoger Pau Monné {
19224f7e474SRoger Pau Monné 
19324f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
19424f7e474SRoger Pau Monné 	return (0);
19524f7e474SRoger Pau Monné }
19624f7e474SRoger Pau Monné 
19724f7e474SRoger Pau Monné static u_int
19824f7e474SRoger Pau Monné xen_pv_apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
19924f7e474SRoger Pau Monné {
20024f7e474SRoger Pau Monné 
20124f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
20224f7e474SRoger Pau Monné 	return (0);
20324f7e474SRoger Pau Monné }
20424f7e474SRoger Pau Monné 
20524f7e474SRoger Pau Monné static void
20624f7e474SRoger Pau Monné xen_pv_apic_disable_vector(u_int apic_id, u_int vector)
20724f7e474SRoger Pau Monné {
20824f7e474SRoger Pau Monné 
20924f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
21024f7e474SRoger Pau Monné }
21124f7e474SRoger Pau Monné 
21224f7e474SRoger Pau Monné static void
21324f7e474SRoger Pau Monné xen_pv_apic_enable_vector(u_int apic_id, u_int vector)
21424f7e474SRoger Pau Monné {
21524f7e474SRoger Pau Monné 
21624f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
21724f7e474SRoger Pau Monné }
21824f7e474SRoger Pau Monné 
21924f7e474SRoger Pau Monné static void
22024f7e474SRoger Pau Monné xen_pv_apic_free_vector(u_int apic_id, u_int vector, u_int irq)
22124f7e474SRoger Pau Monné {
22224f7e474SRoger Pau Monné 
22324f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
22424f7e474SRoger Pau Monné }
22524f7e474SRoger Pau Monné 
22624f7e474SRoger Pau Monné static void
22724f7e474SRoger Pau Monné xen_pv_lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
22824f7e474SRoger Pau Monné {
22924f7e474SRoger Pau Monné 
23024f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
23124f7e474SRoger Pau Monné }
23224f7e474SRoger Pau Monné 
23324f7e474SRoger Pau Monné static int
23424f7e474SRoger Pau Monné xen_pv_lapic_enable_pmc(void)
23524f7e474SRoger Pau Monné {
23624f7e474SRoger Pau Monné 
23724f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
23824f7e474SRoger Pau Monné 	return (0);
23924f7e474SRoger Pau Monné }
24024f7e474SRoger Pau Monné 
24124f7e474SRoger Pau Monné static void
24224f7e474SRoger Pau Monné xen_pv_lapic_disable_pmc(void)
24324f7e474SRoger Pau Monné {
24424f7e474SRoger Pau Monné 
24524f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
24624f7e474SRoger Pau Monné }
24724f7e474SRoger Pau Monné 
24824f7e474SRoger Pau Monné static void
24924f7e474SRoger Pau Monné xen_pv_lapic_reenable_pmc(void)
25024f7e474SRoger Pau Monné {
25124f7e474SRoger Pau Monné 
25224f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
25324f7e474SRoger Pau Monné }
25424f7e474SRoger Pau Monné 
25524f7e474SRoger Pau Monné static void
25624f7e474SRoger Pau Monné xen_pv_lapic_enable_cmc(void)
25724f7e474SRoger Pau Monné {
25824f7e474SRoger Pau Monné 
25924f7e474SRoger Pau Monné }
26024f7e474SRoger Pau Monné 
26124f7e474SRoger Pau Monné static void
26224f7e474SRoger Pau Monné xen_pv_lapic_ipi_raw(register_t icrlo, u_int dest)
26324f7e474SRoger Pau Monné {
26424f7e474SRoger Pau Monné 
26524f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
26624f7e474SRoger Pau Monné }
26724f7e474SRoger Pau Monné 
26824f7e474SRoger Pau Monné static void
26924f7e474SRoger Pau Monné xen_pv_lapic_ipi_vectored(u_int vector, int dest)
27024f7e474SRoger Pau Monné {
27124f7e474SRoger Pau Monné 	xen_intr_handle_t *ipi_handle;
27224f7e474SRoger Pau Monné 	int ipi_idx, to_cpu, self;
27324f7e474SRoger Pau Monné 
27424f7e474SRoger Pau Monné 	ipi_idx = IPI_TO_IDX(vector);
2758114c8e1SRoger Pau Monné 	if (ipi_idx >= nitems(xen_ipis))
27624f7e474SRoger Pau Monné 		panic("IPI out of range");
27724f7e474SRoger Pau Monné 
27824f7e474SRoger Pau Monné 	switch(dest) {
27924f7e474SRoger Pau Monné 	case APIC_IPI_DEST_SELF:
28024f7e474SRoger Pau Monné 		ipi_handle = DPCPU_GET(ipi_handle);
28124f7e474SRoger Pau Monné 		xen_intr_signal(ipi_handle[ipi_idx]);
28224f7e474SRoger Pau Monné 		break;
28324f7e474SRoger Pau Monné 	case APIC_IPI_DEST_ALL:
28424f7e474SRoger Pau Monné 		CPU_FOREACH(to_cpu) {
28524f7e474SRoger Pau Monné 			ipi_handle = DPCPU_ID_GET(to_cpu, ipi_handle);
28624f7e474SRoger Pau Monné 			xen_intr_signal(ipi_handle[ipi_idx]);
28724f7e474SRoger Pau Monné 		}
28824f7e474SRoger Pau Monné 		break;
28924f7e474SRoger Pau Monné 	case APIC_IPI_DEST_OTHERS:
29024f7e474SRoger Pau Monné 		self = PCPU_GET(cpuid);
29124f7e474SRoger Pau Monné 		CPU_FOREACH(to_cpu) {
29224f7e474SRoger Pau Monné 			if (to_cpu != self) {
29324f7e474SRoger Pau Monné 				ipi_handle = DPCPU_ID_GET(to_cpu, ipi_handle);
29424f7e474SRoger Pau Monné 				xen_intr_signal(ipi_handle[ipi_idx]);
29524f7e474SRoger Pau Monné 			}
29624f7e474SRoger Pau Monné 		}
29724f7e474SRoger Pau Monné 		break;
29824f7e474SRoger Pau Monné 	default:
29924f7e474SRoger Pau Monné 		to_cpu = apic_cpuid(dest);
30024f7e474SRoger Pau Monné 		ipi_handle = DPCPU_ID_GET(to_cpu, ipi_handle);
30124f7e474SRoger Pau Monné 		xen_intr_signal(ipi_handle[ipi_idx]);
30224f7e474SRoger Pau Monné 		break;
30324f7e474SRoger Pau Monné 	}
30424f7e474SRoger Pau Monné }
30524f7e474SRoger Pau Monné 
30624f7e474SRoger Pau Monné static int
30724f7e474SRoger Pau Monné xen_pv_lapic_ipi_wait(int delay)
30824f7e474SRoger Pau Monné {
30924f7e474SRoger Pau Monné 
31024f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
31124f7e474SRoger Pau Monné 	return (0);
31224f7e474SRoger Pau Monné }
31324f7e474SRoger Pau Monné 
31424f7e474SRoger Pau Monné static int
31524f7e474SRoger Pau Monné xen_pv_lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked)
31624f7e474SRoger Pau Monné {
31724f7e474SRoger Pau Monné 
31824f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
31924f7e474SRoger Pau Monné 	return (0);
32024f7e474SRoger Pau Monné }
32124f7e474SRoger Pau Monné 
32224f7e474SRoger Pau Monné static int
32324f7e474SRoger Pau Monné xen_pv_lapic_set_lvt_mode(u_int apic_id, u_int lvt, uint32_t mode)
32424f7e474SRoger Pau Monné {
32524f7e474SRoger Pau Monné 
32624f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
32724f7e474SRoger Pau Monné 	return (0);
32824f7e474SRoger Pau Monné }
32924f7e474SRoger Pau Monné 
33024f7e474SRoger Pau Monné static int
33124f7e474SRoger Pau Monné xen_pv_lapic_set_lvt_polarity(u_int apic_id, u_int lvt, enum intr_polarity pol)
33224f7e474SRoger Pau Monné {
33324f7e474SRoger Pau Monné 
33424f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
33524f7e474SRoger Pau Monné 	return (0);
33624f7e474SRoger Pau Monné }
33724f7e474SRoger Pau Monné 
33824f7e474SRoger Pau Monné static int
33924f7e474SRoger Pau Monné xen_pv_lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
34024f7e474SRoger Pau Monné     enum intr_trigger trigger)
34124f7e474SRoger Pau Monné {
34224f7e474SRoger Pau Monné 
34324f7e474SRoger Pau Monné 	XEN_APIC_UNSUPPORTED;
34424f7e474SRoger Pau Monné 	return (0);
34524f7e474SRoger Pau Monné }
34624f7e474SRoger Pau Monné 
34724f7e474SRoger Pau Monné /* Xen apic_ops implementation */
34824f7e474SRoger Pau Monné struct apic_ops xen_apic_ops = {
34924f7e474SRoger Pau Monné 	.create			= xen_pv_lapic_create,
35024f7e474SRoger Pau Monné 	.init			= xen_pv_lapic_init,
35124f7e474SRoger Pau Monné 	.setup			= xen_pv_lapic_setup,
35224f7e474SRoger Pau Monné 	.dump			= xen_pv_lapic_dump,
35324f7e474SRoger Pau Monné 	.disable		= xen_pv_lapic_disable,
35424f7e474SRoger Pau Monné 	.eoi			= xen_pv_lapic_eoi,
35524f7e474SRoger Pau Monné 	.id			= xen_pv_lapic_id,
35624f7e474SRoger Pau Monné 	.intr_pending		= xen_pv_lapic_intr_pending,
35724f7e474SRoger Pau Monné 	.set_logical_id		= xen_pv_lapic_set_logical_id,
35824f7e474SRoger Pau Monné 	.cpuid			= xen_pv_apic_cpuid,
35924f7e474SRoger Pau Monné 	.alloc_vector		= xen_pv_apic_alloc_vector,
36024f7e474SRoger Pau Monné 	.alloc_vectors		= xen_pv_apic_alloc_vectors,
36124f7e474SRoger Pau Monné 	.enable_vector		= xen_pv_apic_enable_vector,
36224f7e474SRoger Pau Monné 	.disable_vector		= xen_pv_apic_disable_vector,
36324f7e474SRoger Pau Monné 	.free_vector		= xen_pv_apic_free_vector,
36424f7e474SRoger Pau Monné 	.enable_pmc		= xen_pv_lapic_enable_pmc,
36524f7e474SRoger Pau Monné 	.disable_pmc		= xen_pv_lapic_disable_pmc,
36624f7e474SRoger Pau Monné 	.reenable_pmc		= xen_pv_lapic_reenable_pmc,
36724f7e474SRoger Pau Monné 	.enable_cmc		= xen_pv_lapic_enable_cmc,
36824f7e474SRoger Pau Monné 	.ipi_raw		= xen_pv_lapic_ipi_raw,
36924f7e474SRoger Pau Monné 	.ipi_vectored		= xen_pv_lapic_ipi_vectored,
37024f7e474SRoger Pau Monné 	.ipi_wait		= xen_pv_lapic_ipi_wait,
37124f7e474SRoger Pau Monné 	.set_lvt_mask		= xen_pv_lapic_set_lvt_mask,
37224f7e474SRoger Pau Monné 	.set_lvt_mode		= xen_pv_lapic_set_lvt_mode,
37324f7e474SRoger Pau Monné 	.set_lvt_polarity	= xen_pv_lapic_set_lvt_polarity,
37424f7e474SRoger Pau Monné 	.set_lvt_triggermode	= xen_pv_lapic_set_lvt_triggermode,
37524f7e474SRoger Pau Monné };
37624f7e474SRoger Pau Monné 
37724f7e474SRoger Pau Monné #ifdef SMP
37824f7e474SRoger Pau Monné /*---------------------------- XEN PV IPI Handlers ---------------------------*/
37924f7e474SRoger Pau Monné /*
38024f7e474SRoger Pau Monné  * These are C clones of the ASM functions found in apic_vector.
38124f7e474SRoger Pau Monné  */
38224f7e474SRoger Pau Monné static int
38324f7e474SRoger Pau Monné xen_ipi_bitmap_handler(void *arg)
38424f7e474SRoger Pau Monné {
38524f7e474SRoger Pau Monné 	struct trapframe *frame;
38624f7e474SRoger Pau Monné 
38724f7e474SRoger Pau Monné 	frame = arg;
38824f7e474SRoger Pau Monné 	ipi_bitmap_handler(*frame);
38924f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
39024f7e474SRoger Pau Monné }
39124f7e474SRoger Pau Monné 
39224f7e474SRoger Pau Monné static int
39324f7e474SRoger Pau Monné xen_smp_rendezvous_action(void *arg)
39424f7e474SRoger Pau Monné {
39524f7e474SRoger Pau Monné #ifdef COUNT_IPIS
39624f7e474SRoger Pau Monné 	(*ipi_rendezvous_counts[PCPU_GET(cpuid)])++;
39724f7e474SRoger Pau Monné #endif /* COUNT_IPIS */
39824f7e474SRoger Pau Monné 
39924f7e474SRoger Pau Monné 	smp_rendezvous_action();
40024f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
40124f7e474SRoger Pau Monné }
40224f7e474SRoger Pau Monné 
40324f7e474SRoger Pau Monné static int
40424f7e474SRoger Pau Monné xen_invltlb(void *arg)
40524f7e474SRoger Pau Monné {
40624f7e474SRoger Pau Monné 
40724f7e474SRoger Pau Monné 	invltlb_handler();
40824f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
40924f7e474SRoger Pau Monné }
41024f7e474SRoger Pau Monné 
41124f7e474SRoger Pau Monné #ifdef __amd64__
41224f7e474SRoger Pau Monné static int
41324f7e474SRoger Pau Monné xen_invltlb_pcid(void *arg)
41424f7e474SRoger Pau Monné {
41524f7e474SRoger Pau Monné 
41624f7e474SRoger Pau Monné 	invltlb_pcid_handler();
41724f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
41824f7e474SRoger Pau Monné }
41924f7e474SRoger Pau Monné #endif
42024f7e474SRoger Pau Monné 
42124f7e474SRoger Pau Monné static int
42224f7e474SRoger Pau Monné xen_invlpg(void *arg)
42324f7e474SRoger Pau Monné {
42424f7e474SRoger Pau Monné 
42524f7e474SRoger Pau Monné 	invlpg_handler();
42624f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
42724f7e474SRoger Pau Monné }
42824f7e474SRoger Pau Monné 
42924f7e474SRoger Pau Monné #ifdef __amd64__
43024f7e474SRoger Pau Monné static int
43124f7e474SRoger Pau Monné xen_invlpg_pcid(void *arg)
43224f7e474SRoger Pau Monné {
43324f7e474SRoger Pau Monné 
43424f7e474SRoger Pau Monné 	invlpg_pcid_handler();
43524f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
43624f7e474SRoger Pau Monné }
43724f7e474SRoger Pau Monné #endif
43824f7e474SRoger Pau Monné 
43924f7e474SRoger Pau Monné static int
44024f7e474SRoger Pau Monné xen_invlrng(void *arg)
44124f7e474SRoger Pau Monné {
44224f7e474SRoger Pau Monné 
44324f7e474SRoger Pau Monné 	invlrng_handler();
44424f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
44524f7e474SRoger Pau Monné }
44624f7e474SRoger Pau Monné 
44724f7e474SRoger Pau Monné static int
44824f7e474SRoger Pau Monné xen_invlcache(void *arg)
44924f7e474SRoger Pau Monné {
45024f7e474SRoger Pau Monné 
45124f7e474SRoger Pau Monné 	invlcache_handler();
45224f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
45324f7e474SRoger Pau Monné }
45424f7e474SRoger Pau Monné 
45524f7e474SRoger Pau Monné #ifdef __i386__
45624f7e474SRoger Pau Monné static int
45724f7e474SRoger Pau Monné xen_lazypmap(void *arg)
45824f7e474SRoger Pau Monné {
45924f7e474SRoger Pau Monné 
46024f7e474SRoger Pau Monné 	pmap_lazyfix_action();
46124f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
46224f7e474SRoger Pau Monné }
46324f7e474SRoger Pau Monné #endif
46424f7e474SRoger Pau Monné 
46524f7e474SRoger Pau Monné static int
46624f7e474SRoger Pau Monné xen_cpustop_handler(void *arg)
46724f7e474SRoger Pau Monné {
46824f7e474SRoger Pau Monné 
46924f7e474SRoger Pau Monné 	cpustop_handler();
47024f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
47124f7e474SRoger Pau Monné }
47224f7e474SRoger Pau Monné 
47324f7e474SRoger Pau Monné static int
47424f7e474SRoger Pau Monné xen_cpususpend_handler(void *arg)
47524f7e474SRoger Pau Monné {
47624f7e474SRoger Pau Monné 
47724f7e474SRoger Pau Monné 	cpususpend_handler();
47824f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
47924f7e474SRoger Pau Monné }
48024f7e474SRoger Pau Monné 
48124f7e474SRoger Pau Monné static int
48224f7e474SRoger Pau Monné xen_cpustophard_handler(void *arg)
48324f7e474SRoger Pau Monné {
48424f7e474SRoger Pau Monné 
48524f7e474SRoger Pau Monné 	ipi_nmi_handler();
48624f7e474SRoger Pau Monné 	return (FILTER_HANDLED);
48724f7e474SRoger Pau Monné }
48824f7e474SRoger Pau Monné 
48924f7e474SRoger Pau Monné /*----------------------------- XEN PV IPI setup -----------------------------*/
49024f7e474SRoger Pau Monné /*
49124f7e474SRoger Pau Monné  * Those functions are provided outside of the Xen PV APIC implementation
49224f7e474SRoger Pau Monné  * so PVHVM guests can also use PV IPIs without having an actual Xen PV APIC,
49324f7e474SRoger Pau Monné  * because on PVHVM there's an emulated LAPIC provided by Xen.
49424f7e474SRoger Pau Monné  */
49524f7e474SRoger Pau Monné static void
49624f7e474SRoger Pau Monné xen_cpu_ipi_init(int cpu)
49724f7e474SRoger Pau Monné {
49824f7e474SRoger Pau Monné 	xen_intr_handle_t *ipi_handle;
49924f7e474SRoger Pau Monné 	const struct xen_ipi_handler *ipi;
50024f7e474SRoger Pau Monné 	device_t dev;
50124f7e474SRoger Pau Monné 	int idx, rc;
50224f7e474SRoger Pau Monné 
50324f7e474SRoger Pau Monné 	ipi_handle = DPCPU_ID_GET(cpu, ipi_handle);
50424f7e474SRoger Pau Monné 	dev = pcpu_find(cpu)->pc_device;
50524f7e474SRoger Pau Monné 	KASSERT((dev != NULL), ("NULL pcpu device_t"));
50624f7e474SRoger Pau Monné 
50724f7e474SRoger Pau Monné 	for (ipi = xen_ipis, idx = 0; idx < nitems(xen_ipis); ipi++, idx++) {
50824f7e474SRoger Pau Monné 
50924f7e474SRoger Pau Monné 		if (ipi->filter == NULL) {
51024f7e474SRoger Pau Monné 			ipi_handle[idx] = NULL;
51124f7e474SRoger Pau Monné 			continue;
51224f7e474SRoger Pau Monné 		}
51324f7e474SRoger Pau Monné 
51424f7e474SRoger Pau Monné 		rc = xen_intr_alloc_and_bind_ipi(dev, cpu, ipi->filter,
51524f7e474SRoger Pau Monné 		    INTR_TYPE_TTY, &ipi_handle[idx]);
51624f7e474SRoger Pau Monné 		if (rc != 0)
51724f7e474SRoger Pau Monné 			panic("Unable to allocate a XEN IPI port");
51824f7e474SRoger Pau Monné 		xen_intr_describe(ipi_handle[idx], "%s", ipi->description);
51924f7e474SRoger Pau Monné 	}
52024f7e474SRoger Pau Monné }
52124f7e474SRoger Pau Monné 
52224f7e474SRoger Pau Monné static void
52324f7e474SRoger Pau Monné xen_setup_cpus(void)
52424f7e474SRoger Pau Monné {
52524f7e474SRoger Pau Monné 	int i;
52624f7e474SRoger Pau Monné 
52724f7e474SRoger Pau Monné 	if (!xen_vector_callback_enabled)
52824f7e474SRoger Pau Monné 		return;
52924f7e474SRoger Pau Monné 
53024f7e474SRoger Pau Monné #ifdef __amd64__
53124f7e474SRoger Pau Monné 	if (pmap_pcid_enabled) {
53224f7e474SRoger Pau Monné 		xen_ipis[IPI_TO_IDX(IPI_INVLTLB)].filter = xen_invltlb_pcid;
53324f7e474SRoger Pau Monné 		xen_ipis[IPI_TO_IDX(IPI_INVLPG)].filter = xen_invlpg_pcid;
53424f7e474SRoger Pau Monné 	}
53524f7e474SRoger Pau Monné #endif
53624f7e474SRoger Pau Monné 	CPU_FOREACH(i)
53724f7e474SRoger Pau Monné 		xen_cpu_ipi_init(i);
53824f7e474SRoger Pau Monné 
53924f7e474SRoger Pau Monné 	/* Set the xen pv ipi ops to replace the native ones */
54024f7e474SRoger Pau Monné 	if (xen_hvm_domain())
54124f7e474SRoger Pau Monné 		apic_ops.ipi_vectored = xen_pv_lapic_ipi_vectored;
54224f7e474SRoger Pau Monné }
54324f7e474SRoger Pau Monné 
54424f7e474SRoger Pau Monné /* We need to setup IPIs before APs are started */
54524f7e474SRoger Pau Monné SYSINIT(xen_setup_cpus, SI_SUB_SMP-1, SI_ORDER_FIRST, xen_setup_cpus, NULL);
54624f7e474SRoger Pau Monné #endif /* SMP */
547