[funini.com] -> [kei@sodan] -> Kernel Reading

root/arch/x86/xen/irq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xen_force_evtchn_callback
  2. __xen_init_IRQ
  3. xen_save_fl
  4. xen_restore_fl
  5. xen_irq_disable
  6. xen_irq_enable
  7. xen_safe_halt
  8. xen_halt
  9. xen_init_irq_ops

#include <linux/hardirq.h>

#include <xen/interface/xen.h>
#include <xen/interface/sched.h>
#include <xen/interface/vcpu.h>

#include <asm/xen/hypercall.h>
#include <asm/xen/hypervisor.h>

#include "xen-ops.h"

/*
 * Force a proper event-channel callback from Xen after clearing the
 * callback mask. We do this in a very simple manner, by making a call
 * down into Xen. The pending flag will be checked by Xen on return.
 */
void xen_force_evtchn_callback(void)
{
        (void)HYPERVISOR_xen_version(0, NULL);
}

static void __init __xen_init_IRQ(void)
{
#ifdef CONFIG_X86_64
        int i;

        /* Create identity vector->irq map */
        for(i = 0; i < NR_VECTORS; i++) {
                int cpu;

                for_each_possible_cpu(cpu)
                        per_cpu(vector_irq, cpu)[i] = i;
        }
#endif  /* CONFIG_X86_64 */

        xen_init_IRQ();
}

static unsigned long xen_save_fl(void)
{
        struct vcpu_info *vcpu;
        unsigned long flags;

        vcpu = x86_read_percpu(xen_vcpu);

        /* flag has opposite sense of mask */
        flags = !vcpu->evtchn_upcall_mask;

        /* convert to IF type flag
           -0 -> 0x00000000
           -1 -> 0xffffffff
        */
        return (-flags) & X86_EFLAGS_IF;
}

static void xen_restore_fl(unsigned long flags)
{
        struct vcpu_info *vcpu;

        /* convert from IF type flag */
        flags = !(flags & X86_EFLAGS_IF);

        /* There's a one instruction preempt window here.  We need to
           make sure we're don't switch CPUs between getting the vcpu
           pointer and updating the mask. */
        preempt_disable();
        vcpu = x86_read_percpu(xen_vcpu);
        vcpu->evtchn_upcall_mask = flags;
        preempt_enable_no_resched();

        /* Doesn't matter if we get preempted here, because any
           pending event will get dealt with anyway. */

        if (flags == 0) {
                preempt_check_resched();
                barrier(); /* unmask then check (avoid races) */
                if (unlikely(vcpu->evtchn_upcall_pending))
                        xen_force_evtchn_callback();
        }
}

static void xen_irq_disable(void)
{
        /* There's a one instruction preempt window here.  We need to
           make sure we're don't switch CPUs between getting the vcpu
           pointer and updating the mask. */
        preempt_disable();
        x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1;
        preempt_enable_no_resched();
}

static void xen_irq_enable(void)
{
        struct vcpu_info *vcpu;

        /* We don't need to worry about being preempted here, since
           either a) interrupts are disabled, so no preemption, or b)
           the caller is confused and is trying to re-enable interrupts
           on an indeterminate processor. */

        vcpu = x86_read_percpu(xen_vcpu);
        vcpu->evtchn_upcall_mask = 0;

        /* Doesn't matter if we get preempted here, because any
           pending event will get dealt with anyway. */

        barrier(); /* unmask then check (avoid races) */
        if (unlikely(vcpu->evtchn_upcall_pending))
                xen_force_evtchn_callback();
}

static void xen_safe_halt(void)
{
        /* Blocking includes an implicit local_irq_enable(). */
        if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0)
                BUG();
}

static void xen_halt(void)
{
        if (irqs_disabled())
                HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
        else
                xen_safe_halt();
}

static const struct pv_irq_ops xen_irq_ops __initdata = {
        .init_IRQ = __xen_init_IRQ,
        .save_fl = xen_save_fl,
        .restore_fl = xen_restore_fl,
        .irq_disable = xen_irq_disable,
        .irq_enable = xen_irq_enable,
        .safe_halt = xen_safe_halt,
        .halt = xen_halt,
#ifdef CONFIG_X86_64
        .adjust_exception_frame = xen_adjust_exception_frame,
#endif
};

void __init xen_init_irq_ops()
{
        pv_irq_ops = xen_irq_ops;
}

/* [<][>][^][v][top][bottom][index][help] */

[funini.com] -> [kei@sodan] -> Kernel Reading