Changeset View
Standalone View
sys/x86/xen/xen_arch_intr.c
- This file was added.
/* | |||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright © 2013 Spectra Logic Corporation | |||||
* Copyright © 2018 The FreeBSD Foundation | |||||
* Copyright © 2021 Elliott Mitchell | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
*/ | |||||
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <sys/param.h> | |||||
#include <sys/bus.h> | |||||
#include <sys/kernel.h> | |||||
#include <sys/pcpu.h> | |||||
#include <sys/proc.h> | |||||
#include <sys/smp.h> | |||||
#include <sys/stddef.h> | |||||
#include <xen/xen-os.h> | |||||
#include <xen/xen_intr.h> | |||||
#include <x86/intr_machdep.h> | |||||
#include <x86/apicvar.h> | |||||
/************************ Xen x86 interrupt interface ************************/ | |||||
/* | |||||
* Pointers to the interrupt counters | |||||
*/ | |||||
DPCPU_DEFINE_STATIC(u_long *, pintrcnt); | |||||
static void | |||||
xen_intrcnt_init(void *dummy __unused) | |||||
{ | |||||
unsigned int i; | |||||
if (!xen_domain()) | |||||
return; | |||||
CPU_FOREACH(i) { | |||||
char buf[MAXCOMLEN + 1]; | |||||
u_long **ppintrcnt; | |||||
ppintrcnt = DPCPU_ID_PTR(i, pintrcnt); | |||||
snprintf(buf, sizeof(buf), "cpu%d:xen", i); | |||||
intrcnt_add(buf, ppintrcnt); | |||||
} | |||||
} | |||||
SYSINIT(xen_intrcnt_init, SI_SUB_INTR, SI_ORDER_MIDDLE, xen_intrcnt_init, NULL); | |||||
/* | |||||
* Transition from assembly language, called from | |||||
* sys/{amd64/amd64|i386/i386}/apic_vector.S | |||||
*/ | |||||
extern void xen_arch_intr_handle_upcall(struct trapframe *); | |||||
void | |||||
xen_arch_intr_handle_upcall(struct trapframe *trap_frame) | |||||
{ | |||||
struct trapframe *old; | |||||
/* | |||||
* Disable preemption in order to always check and fire events | |||||
ehem_freebsd_m5p.com: Approach #2 is **here** set `curthread->td_intr_frame = trap_frame;` (which is passed from… | |||||
Done Inline ActionsYep, agreed that this is where you ought to set it. But as I said, you need to save and restore the previous value of td_intr_frame, not set it to NULL. mhorne: Yep, agreed that this is where you ought to set it. But as I said, you need to save and restore… | |||||
Done Inline ActionsOkay, I can believe that. I cringe at how this means it will be saved both here and in intr_event_handle(), but that could well be correct. I was thinking setting it to NULL might be correct at this point the interrupt is returning and there shouldn't be further trap frames on the stack. ehem_freebsd_m5p.com: Okay, I can believe that. I cringe at how this means it will be saved **both** here and in… | |||||
* on the right vCPU | |||||
*/ | |||||
Done Inline ActionsI'm now guessing this (and the decrement 7 lines below) shouldn't be done. I'm not familiar enough with this to confidently make the call and need advice for whether this is correct. ehem_freebsd_m5p.com: I'm now guessing this (and the decrement 7 lines below) shouldn't be done. I'm not familiar… | |||||
critical_enter(); | |||||
++*DPCPU_GET(pintrcnt); | |||||
old = curthread->td_intr_frame; | |||||
curthread->td_intr_frame = trap_frame; | |||||
xen_intr_handle_upcall(NULL); | |||||
curthread->td_intr_frame = old; | |||||
Done Inline ActionsNote to reviewers (@royger) this is the really significant delta. Previously this would be done if xen_intr_handle_upcall() was invoked for the XenPCI code, but now this will only be invoked for the main Xen interrupt vector. This seems likely correct, but is worthy of reviewer attention. ehem_freebsd_m5p.com: Note to reviewers (@royger) this is the really significant delta. Previously this would be… | |||||
if (xen_evtchn_needs_ack) | |||||
lapic_eoi(); | |||||
critical_exit(); | |||||
} |
Approach #2 is here set curthread->td_intr_frame = trap_frame; (which is passed from assembly language). Then after the call set curthread->td_intr_frame = NULL;. I think this is right, but I would need a review...