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