qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

interrupt.c (3867B)


      1 /*
      2  * OpenRISC interrupt.
      3  *
      4  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2.1 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Lesser General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Lesser General Public
     17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 #include "qemu/osdep.h"
     21 #include "qemu/log.h"
     22 #include "cpu.h"
     23 #include "exec/exec-all.h"
     24 #include "exec/gdbstub.h"
     25 #include "qemu/host-utils.h"
     26 #ifndef CONFIG_USER_ONLY
     27 #include "hw/loader.h"
     28 #endif
     29 
     30 void openrisc_cpu_do_interrupt(CPUState *cs)
     31 {
     32     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
     33     CPUOpenRISCState *env = &cpu->env;
     34     int exception = cs->exception_index;
     35 
     36     env->epcr = env->pc;
     37     if (exception == EXCP_SYSCALL) {
     38         env->epcr += 4;
     39     }
     40     /* When we have an illegal instruction the error effective address
     41        shall be set to the illegal instruction address.  */
     42     if (exception == EXCP_ILLEGAL) {
     43         env->eear = env->pc;
     44     }
     45 
     46     /* During exceptions esr is populared with the pre-exception sr.  */
     47     env->esr = cpu_get_sr(env);
     48     /* In parallel sr is updated to disable mmu, interrupts, timers and
     49        set the delay slot exception flag.  */
     50     env->sr &= ~SR_DME;
     51     env->sr &= ~SR_IME;
     52     env->sr |= SR_SM;
     53     env->sr &= ~SR_IEE;
     54     env->sr &= ~SR_TEE;
     55     env->pmr &= ~PMR_DME;
     56     env->pmr &= ~PMR_SME;
     57     env->lock_addr = -1;
     58 
     59     /* Set/clear dsx to indicate if we are in a delay slot exception.  */
     60     if (env->dflag) {
     61         env->dflag = 0;
     62         env->sr |= SR_DSX;
     63         env->epcr -= 4;
     64     } else {
     65         env->sr &= ~SR_DSX;
     66     }
     67 
     68     if (exception > 0 && exception < EXCP_NR) {
     69         static const char * const int_name[EXCP_NR] = {
     70             [EXCP_RESET]    = "RESET",
     71             [EXCP_BUSERR]   = "BUSERR (bus error)",
     72             [EXCP_DPF]      = "DFP (data protection fault)",
     73             [EXCP_IPF]      = "IPF (code protection fault)",
     74             [EXCP_TICK]     = "TICK (timer interrupt)",
     75             [EXCP_ALIGN]    = "ALIGN",
     76             [EXCP_ILLEGAL]  = "ILLEGAL",
     77             [EXCP_INT]      = "INT (device interrupt)",
     78             [EXCP_DTLBMISS] = "DTLBMISS (data tlb miss)",
     79             [EXCP_ITLBMISS] = "ITLBMISS (code tlb miss)",
     80             [EXCP_RANGE]    = "RANGE",
     81             [EXCP_SYSCALL]  = "SYSCALL",
     82             [EXCP_FPE]      = "FPE",
     83             [EXCP_TRAP]     = "TRAP",
     84         };
     85 
     86         qemu_log_mask(CPU_LOG_INT, "CPU: %d INT: %s\n",
     87                       cs->cpu_index,
     88                       int_name[exception]);
     89 
     90         hwaddr vect_pc = exception << 8;
     91         if (env->cpucfgr & CPUCFGR_EVBARP) {
     92             vect_pc |= env->evbar;
     93         }
     94         if (env->sr & SR_EPH) {
     95             vect_pc |= 0xf0000000;
     96         }
     97         env->pc = vect_pc;
     98     } else {
     99         cpu_abort(cs, "Unhandled exception 0x%x\n", exception);
    100     }
    101 
    102     cs->exception_index = -1;
    103 }
    104 
    105 bool openrisc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
    106 {
    107     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
    108     CPUOpenRISCState *env = &cpu->env;
    109     int idx = -1;
    110 
    111     if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->sr & SR_IEE)) {
    112         idx = EXCP_INT;
    113     }
    114     if ((interrupt_request & CPU_INTERRUPT_TIMER) && (env->sr & SR_TEE)) {
    115         idx = EXCP_TICK;
    116     }
    117     if (idx >= 0) {
    118         cs->exception_index = idx;
    119         openrisc_cpu_do_interrupt(cs);
    120         return true;
    121     }
    122     return false;
    123 }