cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

pic_cpu.c (4807B)


      1/*
      2 * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
      3 * All rights reserved.
      4 *
      5 * Redistribution and use in source and binary forms, with or without
      6 * modification, are permitted provided that the following conditions are met:
      7 *     * Redistributions of source code must retain the above copyright
      8 *       notice, this list of conditions and the following disclaimer.
      9 *     * Redistributions in binary form must reproduce the above copyright
     10 *       notice, this list of conditions and the following disclaimer in the
     11 *       documentation and/or other materials provided with the distribution.
     12 *     * Neither the name of the Open Source and Linux Lab nor the
     13 *       names of its contributors may be used to endorse or promote products
     14 *       derived from this software without specific prior written permission.
     15 *
     16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 */
     27
     28#include "qemu/osdep.h"
     29#include "cpu.h"
     30#include "hw/irq.h"
     31#include "qemu/log.h"
     32#include "qemu/timer.h"
     33
     34void check_interrupts(CPUXtensaState *env)
     35{
     36    CPUState *cs = env_cpu(env);
     37    int minlevel = xtensa_get_cintlevel(env);
     38    uint32_t int_set_enabled = env->sregs[INTSET] &
     39        (env->sregs[INTENABLE] | env->config->inttype_mask[INTTYPE_NMI]);
     40    int level;
     41
     42    if (minlevel >= env->config->nmi_level) {
     43        minlevel = env->config->nmi_level - 1;
     44    }
     45    for (level = env->config->nlevel; level > minlevel; --level) {
     46        if (env->config->level_mask[level] & int_set_enabled) {
     47            env->pending_irq_level = level;
     48            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     49            qemu_log_mask(CPU_LOG_INT,
     50                    "%s level = %d, cintlevel = %d, "
     51                    "pc = %08x, a0 = %08x, ps = %08x, "
     52                    "intset = %08x, intenable = %08x, "
     53                    "ccount = %08x\n",
     54                    __func__, level, xtensa_get_cintlevel(env),
     55                    env->pc, env->regs[0], env->sregs[PS],
     56                    env->sregs[INTSET], env->sregs[INTENABLE],
     57                    env->sregs[CCOUNT]);
     58            return;
     59        }
     60    }
     61    env->pending_irq_level = 0;
     62    cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     63}
     64
     65static void xtensa_set_irq(void *opaque, int irq, int active)
     66{
     67    CPUXtensaState *env = opaque;
     68
     69    if (irq >= env->config->ninterrupt) {
     70        qemu_log("%s: bad IRQ %d\n", __func__, irq);
     71    } else {
     72        uint32_t irq_bit = 1 << irq;
     73
     74        if (active) {
     75            qatomic_or(&env->sregs[INTSET], irq_bit);
     76        } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) {
     77            qatomic_and(&env->sregs[INTSET], ~irq_bit);
     78        }
     79
     80        check_interrupts(env);
     81    }
     82}
     83
     84static void xtensa_ccompare_cb(void *opaque)
     85{
     86    XtensaCcompareTimer *ccompare = opaque;
     87    CPUXtensaState *env = ccompare->env;
     88    unsigned i = ccompare - env->ccompare;
     89
     90    qemu_set_irq(env->irq_inputs[env->config->timerint[i]], 1);
     91}
     92
     93static void xtensa_set_runstall(void *opaque, int irq, int active)
     94{
     95    CPUXtensaState *env = opaque;
     96    xtensa_runstall(env, active);
     97}
     98
     99void xtensa_irq_init(CPUXtensaState *env)
    100{
    101    unsigned i;
    102
    103    env->irq_inputs = qemu_allocate_irqs(xtensa_set_irq, env,
    104                                         env->config->ninterrupt);
    105    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
    106        env->time_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    107        env->ccount_base = env->sregs[CCOUNT];
    108        for (i = 0; i < env->config->nccompare; ++i) {
    109            env->ccompare[i].env = env;
    110            env->ccompare[i].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
    111                    xtensa_ccompare_cb, env->ccompare + i);
    112        }
    113    }
    114    for (i = 0; i < env->config->nextint; ++i) {
    115        unsigned irq = env->config->extint[i];
    116
    117        env->ext_irq_inputs[i] = env->irq_inputs[irq];
    118    }
    119    env->runstall_irq = qemu_allocate_irq(xtensa_set_runstall, env, 0);
    120}
    121
    122qemu_irq *xtensa_get_extints(CPUXtensaState *env)
    123{
    124    return env->ext_irq_inputs;
    125}
    126
    127qemu_irq xtensa_get_runstall(CPUXtensaState *env)
    128{
    129    return env->runstall_irq;
    130}