mirror of https://gitlab.com/qemu-project/qemu
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.2 KiB
C
86 lines
2.2 KiB
C
/*
|
|
* Support for QEMU/KVM hypercalls on s390
|
|
*
|
|
* Copyright 2012 IBM Corp.
|
|
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
|
* your option) any later version. See the COPYING file in the top-level
|
|
* directory.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "cpu.h"
|
|
#include "hw/s390x/s390-virtio-ccw.h"
|
|
#include "hw/s390x/s390-hypercall.h"
|
|
#include "hw/s390x/ioinst.h"
|
|
#include "hw/s390x/css.h"
|
|
#include "virtio-ccw.h"
|
|
|
|
static int handle_virtio_notify(uint64_t mem)
|
|
{
|
|
MachineState *ms = MACHINE(qdev_get_machine());
|
|
|
|
if (mem < ms->ram_size) {
|
|
/* Early printk */
|
|
return 0;
|
|
}
|
|
return -EINVAL;
|
|
}
|
|
|
|
static int handle_virtio_ccw_notify(uint64_t subch_id, uint64_t data)
|
|
{
|
|
SubchDev *sch;
|
|
VirtIODevice *vdev;
|
|
int cssid, ssid, schid, m;
|
|
uint16_t vq_idx = data;
|
|
|
|
if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
|
|
return -EINVAL;
|
|
}
|
|
sch = css_find_subch(m, cssid, ssid, schid);
|
|
if (!sch || !css_subch_visible(sch)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
vdev = virtio_ccw_get_vdev(sch);
|
|
if (vq_idx >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, vq_idx)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) {
|
|
virtio_queue_set_shadow_avail_idx(virtio_get_queue(vdev, vq_idx),
|
|
(data >> 16) & 0xFFFF);
|
|
}
|
|
|
|
virtio_queue_notify(vdev, vq_idx);
|
|
return 0;
|
|
}
|
|
|
|
static uint64_t handle_storage_limit(void)
|
|
{
|
|
S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
|
|
|
|
return s390_get_memory_limit(s390ms) - 1;
|
|
}
|
|
|
|
void handle_diag_500(S390CPU *cpu, uintptr_t ra)
|
|
{
|
|
CPUS390XState *env = &cpu->env;
|
|
const uint64_t subcode = env->regs[1];
|
|
|
|
switch (subcode) {
|
|
case DIAG500_VIRTIO_NOTIFY:
|
|
env->regs[2] = handle_virtio_notify(env->regs[2]);
|
|
break;
|
|
case DIAG500_VIRTIO_CCW_NOTIFY:
|
|
env->regs[2] = handle_virtio_ccw_notify(env->regs[2], env->regs[3]);
|
|
break;
|
|
case DIAG500_STORAGE_LIMIT:
|
|
env->regs[2] = handle_storage_limit();
|
|
break;
|
|
default:
|
|
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
|
|
}
|
|
}
|