Date: Tue, 12 Nov 2019 10:31:29 +0000 (UTC) From: =?UTF-8?Q?Roger_Pau_Monn=c3=a9?= <royger@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r354637 - head/sys/x86/xen Message-ID: <201911121031.xACAVTsw018481@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: royger Date: Tue Nov 12 10:31:28 2019 New Revision: 354637 URL: https://svnweb.freebsd.org/changeset/base/354637 Log: xen: fix dispatching of NMIs Currently NMIs are sent over event channels, but that defeats the purpose of NMIs since event channels can be masked. Fix this by issuing NMIs using a hypercall, which injects a NMI (vector #2) to the desired vCPU. Note that NMIs could also be triggered using the emulated local APIC, but using a hypercall is better from a performance point of view since it doesn't involve instruction decoding when not using x2APIC mode. Reported and Tested by: avg Sponsored by: Citrix Systems R&D Modified: head/sys/x86/xen/xen_apic.c Modified: head/sys/x86/xen/xen_apic.c ============================================================================== --- head/sys/x86/xen/xen_apic.c Tue Nov 12 10:22:48 2019 (r354636) +++ head/sys/x86/xen/xen_apic.c Tue Nov 12 10:31:28 2019 (r354637) @@ -72,7 +72,6 @@ static driver_filter_t xen_invlcache; static driver_filter_t xen_ipi_bitmap_handler; static driver_filter_t xen_cpustop_handler; static driver_filter_t xen_cpususpend_handler; -static driver_filter_t xen_cpustophard_handler; #endif /*---------------------------------- Macros ----------------------------------*/ @@ -96,7 +95,6 @@ static struct xen_ipi_handler xen_ipis[] = [IPI_TO_IDX(IPI_BITMAP_VECTOR)] = { xen_ipi_bitmap_handler, "b" }, [IPI_TO_IDX(IPI_STOP)] = { xen_cpustop_handler, "st" }, [IPI_TO_IDX(IPI_SUSPEND)] = { xen_cpususpend_handler, "sp" }, - [IPI_TO_IDX(IPI_STOP_HARD)] = { xen_cpustophard_handler, "sth" }, }; #endif @@ -259,12 +257,52 @@ xen_pv_lapic_ipi_raw(register_t icrlo, u_int dest) XEN_APIC_UNSUPPORTED; } +#define PCPU_ID_GET(id, field) (pcpu_find(id)->pc_##field) static void +send_nmi(int dest) +{ + unsigned int cpu; + + /* + * NMIs are not routed over event channels, and instead delivered as on + * native using the exception vector (#2). Triggering them can be done + * using the local APIC, or an hypercall as a shortcut like it's done + * below. + */ + switch(dest) { + case APIC_IPI_DEST_SELF: + HYPERVISOR_vcpu_op(VCPUOP_send_nmi, PCPU_GET(vcpu_id), NULL); + break; + case APIC_IPI_DEST_ALL: + CPU_FOREACH(cpu) + HYPERVISOR_vcpu_op(VCPUOP_send_nmi, + PCPU_ID_GET(cpu, vcpu_id), NULL); + break; + case APIC_IPI_DEST_OTHERS: + CPU_FOREACH(cpu) + if (cpu != PCPU_GET(cpuid)) + HYPERVISOR_vcpu_op(VCPUOP_send_nmi, + PCPU_ID_GET(cpu, vcpu_id), NULL); + break; + default: + HYPERVISOR_vcpu_op(VCPUOP_send_nmi, + PCPU_ID_GET(apic_cpuid(dest), vcpu_id), NULL); + break; + } +} +#undef PCPU_ID_GET + +static void xen_pv_lapic_ipi_vectored(u_int vector, int dest) { xen_intr_handle_t *ipi_handle; int ipi_idx, to_cpu, self; + if (vector >= IPI_NMI_FIRST) { + send_nmi(dest); + return; + } + ipi_idx = IPI_TO_IDX(vector); if (ipi_idx >= nitems(xen_ipis)) panic("IPI out of range"); @@ -519,14 +557,6 @@ xen_cpususpend_handler(void *arg) { cpususpend_handler(); - return (FILTER_HANDLED); -} - -static int -xen_cpustophard_handler(void *arg) -{ - - ipi_nmi_handler(); return (FILTER_HANDLED); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911121031.xACAVTsw018481>