There are still some leftovers from old virtio interrupts in there.
Most importantly, we don't have to queue service interrupts anymore.
Just like KVM, we can simply multiplex the SCLP service interrupts and
avoid the queue.
Also, now only valid parameters/cpu_addr will be stored on service
interrupts.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <
20170928203708.9376-3-david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
env->gbea = 1;
env->pfault_token = -1UL;
- env->ext_index = -1;
for (i = 0; i < ARRAY_SIZE(env->io_index); i++) {
env->io_index[i] = -1;
}
env->gbea = 1;
env->pfault_token = -1UL;
- env->ext_index = -1;
for (i = 0; i < ARRAY_SIZE(env->io_index); i++) {
env->io_index[i] = -1;
}
#define MMU_USER_IDX 0
-#define MAX_EXT_QUEUE 16
#define MAX_IO_QUEUE 16
#define MAX_MCHK_QUEUE 16
uint64_t addr;
} PSW;
-typedef struct ExtQueue {
- uint32_t code;
- uint32_t param;
- uint32_t param64;
-} ExtQueue;
-
typedef struct IOIntQueue {
uint16_t id;
uint16_t nr;
uint64_t cregs[16]; /* control registers */
- ExtQueue ext_queue[MAX_EXT_QUEUE];
IOIntQueue io_queue[MAX_IO_QUEUE][8];
MchkQueue mchk_queue[MAX_MCHK_QUEUE];
int pending_int;
- int ext_index;
+ uint32_t service_param;
int io_index[8];
int mchk_index;
S390CPU *cpu = s390_env_get_cpu(env);
uint64_t mask, addr;
LowCore *lowcore;
- ExtQueue *q;
if (!(env->psw.mask & PSW_MASK_EXT)) {
cpu_abort(CPU(cpu), "Ext int w/o ext mask\n");
lowcore->cpu_addr = 0;
env->pending_int &= ~INTERRUPT_EXT_CPU_TIMER;
} else if (env->pending_int & INTERRUPT_EXT_SERVICE) {
- g_assert(env->ext_index >= 0);
/*
* FIXME: floating IRQs should be considered by all CPUs and
* shuld not get cleared by CPU reset.
*/
- q = &env->ext_queue[env->ext_index];
- lowcore->ext_int_code = cpu_to_be16(q->code);
- lowcore->ext_params = cpu_to_be32(q->param);
- lowcore->ext_params2 = cpu_to_be64(q->param64);
- lowcore->cpu_addr = cpu_to_be16(env->core_id | VIRTIO_SUBCODE_64);
- env->ext_index--;
- if (env->ext_index == -1) {
- env->pending_int &= ~INTERRUPT_EXT_SERVICE;
- }
+ lowcore->ext_int_code = cpu_to_be16(EXT_SERVICE);
+ lowcore->ext_params = cpu_to_be32(env->service_param);
+ lowcore->cpu_addr = 0;
+ env->service_param = 0;
+ env->pending_int &= ~INTERRUPT_EXT_SERVICE;
} else {
g_assert_not_reached();
}
/* interrupt.c */
void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
-void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
- uint64_t param64);
void cpu_inject_clock_comparator(S390CPU *cpu);
void cpu_inject_cpu_timer(S390CPU *cpu);
}
#if !defined(CONFIG_USER_ONLY)
-void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
- uint64_t param64)
+static void cpu_inject_service(S390CPU *cpu, uint32_t param)
{
CPUS390XState *env = &cpu->env;
- if (env->ext_index == MAX_EXT_QUEUE - 1) {
- /* ugh - can't queue anymore. Let's drop. */
- return;
- }
-
- env->ext_index++;
- assert(env->ext_index < MAX_EXT_QUEUE);
-
- env->ext_queue[env->ext_index].code = code;
- env->ext_queue[env->ext_index].param = param;
- env->ext_queue[env->ext_index].param64 = param64;
+ /* multiplexing is good enough for sclp - kvm does it internally as well*/
+ env->service_param |= param;
env->pending_int |= INTERRUPT_EXT_SERVICE;
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
} else {
S390CPU *dummy_cpu = s390_cpu_addr2state(0);
- cpu_inject_ext(dummy_cpu, EXT_SERVICE, parm, 0);
+ cpu_inject_service(dummy_cpu, parm);
}
}