Example #1
0
/**
 * DO NOT run any linux calls (e.g. printk) here as they may race with the
 * existing linux threads.
 */
int lkl_trigger_irq(int irq)
{
    if (!irq || irq > NR_IRQS)
        return -EINVAL;

    SET_IRQ_STATUS(irq);

    wakeup_cpu();

    return 0;
}
Example #2
0
File: irq.c Project: teto/linux
/**
 * DO NOT run any linux calls (e.g. printk) here as they may race with the
 * existing linux threads.
 */
int lkl_trigger_irq(int irq, void *data)
{
	int ret = 0;

	if (irq >= NR_IRQS)
		return -EINVAL;

	irqs[irq].triggered = true;
	__sync_synchronize();
	irqs_triggered = true;

	wakeup_cpu();

	return ret;
}
Example #3
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(system_reset) (const int cpu, const int clear, const int target_mode)
{
    int         rc;
    int         n;
    int         regs_mode;
    int         architecture_switch;
    REGS*       regs;
    CPU_BITMAP  mask;

    /* Configure the cpu if it is not online (configure implies initial
     * reset)
     */
    if (!IS_CPU_ONLINE(cpu))
    {
        sysblk.arch_mode = target_mode;
        if ( (rc = configure_cpu(cpu)) )
            return rc;
    }

    HDC1(debug_cpu_state, sysblk.regs[cpu]);

    /* Define the target mode for reset */
    if (target_mode > ARCH_390 &&
        (clear || sysblk.arch_mode != target_mode))
        regs_mode = ARCH_390;
    else
        regs_mode = target_mode;

    architecture_switch = (target_mode != sysblk.arch_mode);

    /* Signal all CPUs in configuration to stop and reset */
    {
        /* Switch lock context to hold both sigplock and intlock */
        RELEASE_INTLOCK(NULL);
        obtain_lock(&sysblk.sigplock);
        OBTAIN_INTLOCK(NULL);

        /* Ensure no external updates pending */
        OFF_IC_SERVSIG;
        OFF_IC_INTKEY;

        /* Loop through CPUs and issue appropriate CPU reset function
         */
        {
            mask = sysblk.config_mask;

            for (n = 0; mask; mask >>= 1, ++n)
            {
                if (mask & 1)
                {
                    regs = sysblk.regs[n];

                    /* Signal CPU reset function; if requesting CPU with
                     * CLEAR or architecture change, signal initial CPU
                     * reset. Otherwise, signal a normal CPU reset.
                     */
                    regs->arch_mode = regs_mode;

                    if (n == cpu &&
                        (clear || architecture_switch))
                        regs->sigpireset = 1;
                    else
                        regs->sigpreset = 1;

                    regs->opinterv = 1;
                    regs->cpustate = CPUSTATE_STOPPING;
                    ON_IC_INTERRUPT(regs);
                    wakeup_cpu(regs);
                }
            }
        }

        /* Return to hold of just intlock */
        RELEASE_INTLOCK(NULL);
        release_lock(&sysblk.sigplock);
        OBTAIN_INTLOCK(NULL);
    }

    /* Wait for CPUs to complete reset */
    {
        int i;
        int wait;

        for (n = 0; ; ++n)
        {
            mask = sysblk.config_mask;

            for (i = wait = 0; mask; mask >>= 1, ++i)
            {
                regs = sysblk.regs[i];

                if (regs->cpustate != CPUSTATE_STOPPED)
                {
                    /* Release intlock, take a nap, and re-acquire */
                    RELEASE_INTLOCK(NULL);
                    wait = 1;
                    usleep(10000);
                    OBTAIN_INTLOCK(NULL);
                }
            }

            if (!wait)
                break;

            if (n < 300)
                continue;

            /* FIXME: Recovery code needed to handle case where CPUs
             *        are misbehaving. Outstanding locks should be
             *        reported, then take-over CPUs and perform an
             *        initial reset of each CPU.
             */
            WRMSG(HHC90000, "E", "Could not perform reset within three seconds");
            break;
        }
    }

    /* Perform subsystem reset */
    subsystem_reset();

    /* Switch modes to requested mode */
    sysblk.arch_mode = regs_mode;

    /* Perform system-reset-clear additional functions */
    if (clear)
    {
        /* Finish reset-clear of all CPUs in the configuration */
        for (n = 0; n < sysblk.maxcpu; ++n)
        {
            if (IS_CPU_ONLINE(n))
            {
                regs = sysblk.regs[n];

                /* Clear all the registers (AR, GPR, FPR, VR) as part
                 * of the CPU CLEAR RESET operation
                 */
                memset (regs->ar, 0, sizeof(regs->ar));
                memset (regs->gr, 0, sizeof(regs->gr));
                memset (regs->fpr, 0, sizeof(regs->fpr));
                #if defined(_FEATURE_VECTOR_FACILITY)
                    memset (regs->vf->vr, 0, sizeof(regs->vf->vr));
                #endif /*defined(_FEATURE_VECTOR_FACILITY)*/
            }
        }

        sysblk.ipled = FALSE;
        sysblk.program_parameter = 0;

        /* Clear storage */
        sysblk.main_clear = sysblk.xpnd_clear = 0;
        storage_clear();
        xstorage_clear();
    }

#if defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)
    /* Clear topology-change-report-pending condition */
    sysblk.topchnge = 0;
#endif /*defined(FEATURE_CONFIGURATION_TOPOLOGY_FACILITY)*/

    /* set default system state to reset */
    sysblk.sys_reset = TRUE;

    return (0);
} /* end function system_reset */
Example #4
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(system_reset)
(
    const int cpu,              /* CPU address                       */
    const int flags,            /* Flags:
                                 * 0x00 0000 0000 System reset normal
                                 * 0x01 .... ...1 System reset clear
                                 * 0x02 .... ..1. System reset normal
                                 *                with initial CPU
                                 *                reset on requesting
                                 *                processor (used by
                                 *                IPL)
                                 */
    const int target_mode       /* Target architecture mode          */
)
{
    int         rc;
    int         n;
    int         regs_mode;
    int         architecture_switch;
    REGS*       regs;
    CPU_BITMAP  mask;

    /* Configure the cpu if it is not online (configure implies initial
     * reset)
     */
    if (!IS_CPU_ONLINE(cpu))
    {
        sysblk.arch_mode = target_mode;
        if ( (rc = configure_cpu(cpu)) )
            return rc;
    }

    HDC1(debug_cpu_state, sysblk.regs[cpu]);

    /* Define the target mode for reset */
    if (flags &&
        target_mode > ARCH_390)
        regs_mode = ARCH_390;
    else
        regs_mode = target_mode;

    architecture_switch = (regs_mode != sysblk.arch_mode);

    /* Signal all CPUs in configuration to stop and reset */
    {
        /* Switch lock context to hold both sigplock and intlock */
        RELEASE_INTLOCK(NULL);
        obtain_lock(&sysblk.sigplock);
        OBTAIN_INTLOCK(NULL);

        /* Ensure no external updates pending */
        OFF_IC_SERVSIG;
        OFF_IC_INTKEY;

        /* Loop through CPUs and issue appropriate CPU reset function
         */
        {
            mask = sysblk.config_mask;

            for (n = 0; mask; mask >>= 1, ++n)
            {
                if (mask & 1)
                {
                    regs = sysblk.regs[n];

                    /* Signal CPU reset function; if requesting CPU with
                     * CLEAR or architecture change, signal initial CPU
                     * reset. Otherwise, signal a normal CPU reset.
                     */
                    if ((n == cpu && (flags & 0x03))    ||
                        architecture_switch)
                        regs->sigpireset = 1;
                    else
                        regs->sigpreset = 1;

                    regs->opinterv = 1;
                    regs->cpustate = CPUSTATE_STOPPING;
                    ON_IC_INTERRUPT(regs);
                    wakeup_cpu(regs);
                }
            }
        }

        /* Return to hold of just intlock */
        RELEASE_INTLOCK(NULL);
        release_lock(&sysblk.sigplock);
        OBTAIN_INTLOCK(NULL);
    }

    /* Wait for CPUs to complete reset */
    {
        int i;
        int wait;

        for (n = 0; ; ++n)
        {
            mask = sysblk.config_mask;

            for (i = wait = 0; mask; mask >>= 1, ++i)
            {
                if (!(mask & 1))
                    continue;

                regs = sysblk.regs[i];

                if (regs->cpustate != CPUSTATE_STOPPED)
                {
                    /* Release intlock, take a nap, and re-acquire */
                    RELEASE_INTLOCK(NULL);
                    wait = 1;
                    usleep(10000);
                    OBTAIN_INTLOCK(NULL);
                }
            }

            if (!wait)
                break;

            if (n < 300)
                continue;

            /* FIXME: Recovery code needed to handle case where CPUs
             *        are misbehaving. Outstanding locks should be
             *        reported, then take-over CPUs and perform an
             *        initial reset of each CPU.
             */
            WRMSG(HHC90000, "E", "Could not perform reset within three seconds");
            break;
        }
    }

    /* If architecture switch, complete reset in requested mode */
    if (architecture_switch)
    {
        sysblk.arch_mode = regs_mode;
        return ARCH_DEP(system_reset)(cpu, flags, target_mode);
    }

    /* Perform subsystem reset
     *
     * GA22-7000-10 IBM System/370 Principles of Operation, Chapter 4.
     *              Control, Subsystem Reset, p. 4-34
     * SA22-7085-00 IBM System/370 Extended Architecture Principles of
     *              Operation, Chapter 4. Control, Subsystem Reset,
     *              p. 4-28
     * SA22-7832-09 z/Architecture Principles of Operation, Chapter 4.
     *              Control, Subsystem Reset, p. 4-57
     */
    subsystem_reset();

    /* Perform system-reset-clear additional functions */
    if (flags & 0x01)
    {
        /* Finish reset-clear of all CPUs in the configuration */
        for (n = 0; n < sysblk.maxcpu; ++n)
        {
            if (IS_CPU_ONLINE(n))
            {
                regs = sysblk.regs[n];

                /* Clear all the registers (AR, GPR, FPR, VR) as part
                 * of the CPU CLEAR RESET operation
                 */
                memset (regs->ar, 0, sizeof(regs->ar));
                memset (regs->gr, 0, sizeof(regs->gr));
                memset (regs->fpr, 0, sizeof(regs->fpr));
                #if defined(_FEATURE_VECTOR_FACILITY)
                    memset (regs->vf->vr, 0, sizeof(regs->vf->vr));
                #endif /*defined(_FEATURE_VECTOR_FACILITY)*/

                /* Clear the instruction counter and CPU time used */
                cpu_reset_instcount_and_cputime(regs);
            }
        }

        /* Clear storage */
        sysblk.main_clear = sysblk.xpnd_clear = 0;
        storage_clear();
        xstorage_clear();

        /* Clear IPL program parameter */
        sysblk.program_parameter = 0;
    }

    /* If IPL call, reset CPU instruction counts and times */
    else if (flags & 0x02)
    {
        CPU_BITMAP  mask = sysblk.config_mask;
        int         i;

        for (i = 0; mask; mask >>= 1, ++i)
        {
            if (mask & 1)
                cpu_reset_instcount_and_cputime(sysblk.regs[i]);
        }
    }