qemu/target/s390x/interrupt.c
<<
>>
Prefs
   1/*
   2 * QEMU S/390 Interrupt support
   3 *
   4 * Copyright IBM Corp. 2012, 2014
   5 *
   6 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
   7 * option) any later version.  See the COPYING file in the top-level directory.
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "cpu.h"
  12#include "sysemu/kvm.h"
  13#include "hw/s390x/ioinst.h"
  14
  15#if !defined(CONFIG_USER_ONLY)
  16void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
  17                    uint64_t param64)
  18{
  19    CPUS390XState *env = &cpu->env;
  20
  21    if (env->ext_index == MAX_EXT_QUEUE - 1) {
  22        /* ugh - can't queue anymore. Let's drop. */
  23        return;
  24    }
  25
  26    env->ext_index++;
  27    assert(env->ext_index < MAX_EXT_QUEUE);
  28
  29    env->ext_queue[env->ext_index].code = code;
  30    env->ext_queue[env->ext_index].param = param;
  31    env->ext_queue[env->ext_index].param64 = param64;
  32
  33    env->pending_int |= INTERRUPT_EXT;
  34    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
  35}
  36
  37static void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
  38                          uint16_t subchannel_number,
  39                          uint32_t io_int_parm, uint32_t io_int_word)
  40{
  41    CPUS390XState *env = &cpu->env;
  42    int isc = IO_INT_WORD_ISC(io_int_word);
  43
  44    if (env->io_index[isc] == MAX_IO_QUEUE - 1) {
  45        /* ugh - can't queue anymore. Let's drop. */
  46        return;
  47    }
  48
  49    env->io_index[isc]++;
  50    assert(env->io_index[isc] < MAX_IO_QUEUE);
  51
  52    env->io_queue[env->io_index[isc]][isc].id = subchannel_id;
  53    env->io_queue[env->io_index[isc]][isc].nr = subchannel_number;
  54    env->io_queue[env->io_index[isc]][isc].parm = io_int_parm;
  55    env->io_queue[env->io_index[isc]][isc].word = io_int_word;
  56
  57    env->pending_int |= INTERRUPT_IO;
  58    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
  59}
  60
  61static void cpu_inject_crw_mchk(S390CPU *cpu)
  62{
  63    CPUS390XState *env = &cpu->env;
  64
  65    if (env->mchk_index == MAX_MCHK_QUEUE - 1) {
  66        /* ugh - can't queue anymore. Let's drop. */
  67        return;
  68    }
  69
  70    env->mchk_index++;
  71    assert(env->mchk_index < MAX_MCHK_QUEUE);
  72
  73    env->mchk_queue[env->mchk_index].type = 1;
  74
  75    env->pending_int |= INTERRUPT_MCHK;
  76    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
  77}
  78
  79/*
  80 * All of the following interrupts are floating, i.e. not per-vcpu.
  81 * We just need a dummy cpustate in order to be able to inject in the
  82 * non-kvm case.
  83 */
  84void s390_sclp_extint(uint32_t parm)
  85{
  86    if (kvm_enabled()) {
  87        kvm_s390_service_interrupt(parm);
  88    } else {
  89        S390CPU *dummy_cpu = s390_cpu_addr2state(0);
  90
  91        cpu_inject_ext(dummy_cpu, EXT_SERVICE, parm, 0);
  92    }
  93}
  94
  95void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
  96                       uint32_t io_int_parm, uint32_t io_int_word)
  97{
  98    if (kvm_enabled()) {
  99        kvm_s390_io_interrupt(subchannel_id, subchannel_nr, io_int_parm,
 100                              io_int_word);
 101    } else {
 102        S390CPU *dummy_cpu = s390_cpu_addr2state(0);
 103
 104        cpu_inject_io(dummy_cpu, subchannel_id, subchannel_nr, io_int_parm,
 105                      io_int_word);
 106    }
 107}
 108
 109void s390_crw_mchk(void)
 110{
 111    if (kvm_enabled()) {
 112        kvm_s390_crw_mchk();
 113    } else {
 114        S390CPU *dummy_cpu = s390_cpu_addr2state(0);
 115
 116        cpu_inject_crw_mchk(dummy_cpu);
 117    }
 118}
 119
 120#endif
 121