xref: /openbmc/linux/arch/x86/xen/irq.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
20d1edf46SJeremy Fitzhardinge #include <linux/hardirq.h>
30d1edf46SJeremy Fitzhardinge 
466bcaf0bSThomas Gleixner #include <asm/x86_init.h>
566bcaf0bSThomas Gleixner 
60d1edf46SJeremy Fitzhardinge #include <xen/interface/xen.h>
70d1edf46SJeremy Fitzhardinge #include <xen/interface/sched.h>
80d1edf46SJeremy Fitzhardinge #include <xen/interface/vcpu.h>
92771374dSMukesh Rathor #include <xen/features.h>
100ec53ecfSStefano Stabellini #include <xen/events.h>
110d1edf46SJeremy Fitzhardinge 
120d1edf46SJeremy Fitzhardinge #include <asm/xen/hypercall.h>
130d1edf46SJeremy Fitzhardinge #include <asm/xen/hypervisor.h>
140d1edf46SJeremy Fitzhardinge 
150d1edf46SJeremy Fitzhardinge #include "xen-ops.h"
160d1edf46SJeremy Fitzhardinge 
170d1edf46SJeremy Fitzhardinge /*
180d1edf46SJeremy Fitzhardinge  * Force a proper event-channel callback from Xen after clearing the
190d1edf46SJeremy Fitzhardinge  * callback mask. We do this in a very simple manner, by making a call
200d1edf46SJeremy Fitzhardinge  * down into Xen. The pending flag will be checked by Xen on return.
210d1edf46SJeremy Fitzhardinge  */
xen_force_evtchn_callback(void)22847d9317SPeter Zijlstra noinstr void xen_force_evtchn_callback(void)
230d1edf46SJeremy Fitzhardinge {
240d1edf46SJeremy Fitzhardinge 	(void)HYPERVISOR_xen_version(0, NULL);
250d1edf46SJeremy Fitzhardinge }
260d1edf46SJeremy Fitzhardinge 
xen_safe_halt(void)27*10a09940SPeter Zijlstra static noinstr void xen_safe_halt(void)
280d1edf46SJeremy Fitzhardinge {
290d1edf46SJeremy Fitzhardinge 	/* Blocking includes an implicit local_irq_enable(). */
300d1edf46SJeremy Fitzhardinge 	if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0)
310d1edf46SJeremy Fitzhardinge 		BUG();
320d1edf46SJeremy Fitzhardinge }
330d1edf46SJeremy Fitzhardinge 
xen_halt(void)340d1edf46SJeremy Fitzhardinge static void xen_halt(void)
350d1edf46SJeremy Fitzhardinge {
360d1edf46SJeremy Fitzhardinge 	if (irqs_disabled())
37ad5475f9SVitaly Kuznetsov 		HYPERVISOR_vcpu_op(VCPUOP_down,
38ad5475f9SVitaly Kuznetsov 				   xen_vcpu_nr(smp_processor_id()), NULL);
390d1edf46SJeremy Fitzhardinge 	else
400d1edf46SJeremy Fitzhardinge 		xen_safe_halt();
410d1edf46SJeremy Fitzhardinge }
420d1edf46SJeremy Fitzhardinge 
431462eb38SPeter Zijlstra static const typeof(pv_ops) xen_irq_ops __initconst = {
441462eb38SPeter Zijlstra 	.irq = {
45e453f872SJuergen Gross 		/* Initial interrupt flag handling only called while interrupts off. */
46e453f872SJuergen Gross 		.save_fl = __PV_IS_CALLEE_SAVE(paravirt_ret0),
47e453f872SJuergen Gross 		.irq_disable = __PV_IS_CALLEE_SAVE(paravirt_nop),
48e453f872SJuergen Gross 		.irq_enable = __PV_IS_CALLEE_SAVE(paravirt_BUG),
49ecb93d1cSJeremy Fitzhardinge 
500d1edf46SJeremy Fitzhardinge 		.safe_halt = xen_safe_halt,
510d1edf46SJeremy Fitzhardinge 		.halt = xen_halt,
521462eb38SPeter Zijlstra 	},
530d1edf46SJeremy Fitzhardinge };
540d1edf46SJeremy Fitzhardinge 
xen_init_irq_ops(void)557d81c3b9SRandy Dunlap void __init xen_init_irq_ops(void)
560d1edf46SJeremy Fitzhardinge {
571462eb38SPeter Zijlstra 	pv_ops.irq = xen_irq_ops.irq;
5866bcaf0bSThomas Gleixner 	x86_init.irqs.intr_init = xen_init_IRQ;
590d1edf46SJeremy Fitzhardinge }
60