From: Alexander Graf Date: Fri, 25 Jan 2013 00:16:39 +0000 (+0100) Subject: s390: Move hw files to hw/s390x X-Git-Tag: v1.4.0-rc0~72^2~6 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=b73d35311098585dbdb375fdf8369b16c8222e12;p=qemu.git s390: Move hw files to hw/s390x This moves all files only used by s390 system emulation to hw/s390x. Signed-off-by: Alexander Graf Acked-by: Christian Borntraeger --- diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c deleted file mode 100644 index 6858db089..000000000 --- a/hw/s390-virtio-bus.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * QEMU S390 virtio target - * - * Copyright (c) 2009 Alexander Graf - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include "hw.h" -#include "block/block.h" -#include "sysemu/sysemu.h" -#include "boards.h" -#include "monitor/monitor.h" -#include "loader.h" -#include "elf.h" -#include "hw/virtio.h" -#include "hw/virtio-rng.h" -#include "hw/virtio-serial.h" -#include "hw/virtio-net.h" -#include "hw/sysbus.h" -#include "sysemu/kvm.h" - -#include "hw/s390-virtio-bus.h" -#include "hw/virtio-bus.h" - -/* #define DEBUG_S390 */ - -#ifdef DEBUG_S390 -#define dprintf(fmt, ...) \ - do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) -#else -#define dprintf(fmt, ...) \ - do { } while (0) -#endif - -#define VIRTIO_EXT_CODE 0x2603 - -static const TypeInfo s390_virtio_bus_info = { - .name = TYPE_S390_VIRTIO_BUS, - .parent = TYPE_BUS, - .instance_size = sizeof(VirtIOS390Bus), -}; - -static const VirtIOBindings virtio_s390_bindings; - -static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev); - -/* length of VirtIO device pages */ -const hwaddr virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE; - -static void s390_virtio_bus_reset(void *opaque) -{ - VirtIOS390Bus *bus = opaque; - bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; -} - -void s390_virtio_reset_idx(VirtIOS390Device *dev) -{ - int i; - hwaddr idx_addr; - uint8_t num_vq; - - num_vq = s390_virtio_device_num_vq(dev); - for (i = 0; i < num_vq; i++) { - idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) + - VIRTIO_VRING_AVAIL_IDX_OFFS; - stw_phys(idx_addr, 0); - idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + - VIRTIO_VRING_USED_IDX_OFFS; - stw_phys(idx_addr, 0); - } -} - -VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) -{ - VirtIOS390Bus *bus; - BusState *_bus; - DeviceState *dev; - - /* Create bridge device */ - dev = qdev_create(NULL, "s390-virtio-bridge"); - qdev_init_nofail(dev); - - /* Create bus on bridge device */ - - _bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio"); - bus = DO_UPCAST(VirtIOS390Bus, bus, _bus); - - bus->dev_page = *ram_size; - bus->dev_offs = bus->dev_page; - bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; - - /* Enable hotplugging */ - _bus->allow_hotplug = 1; - - /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */ - *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE; - - qemu_register_reset(s390_virtio_bus_reset, bus); - return bus; -} - -static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token) -{ - CPUS390XState *env = &cpu->env; - - if (kvm_enabled()) { - kvm_s390_virtio_irq(cpu, config_change, token); - } else { - cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token); - } -} - -static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) -{ - VirtIOS390Bus *bus; - int dev_len; - - bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus); - dev->vdev = vdev; - dev->dev_offs = bus->dev_offs; - dev->feat_len = sizeof(uint32_t); /* always keep 32 bits features */ - - dev_len = VIRTIO_DEV_OFFS_CONFIG; - dev_len += s390_virtio_device_num_vq(dev) * VIRTIO_VQCONFIG_LEN; - dev_len += dev->feat_len * 2; - dev_len += vdev->config_len; - - bus->dev_offs += dev_len; - - virtio_bind_device(vdev, &virtio_s390_bindings, DEVICE(dev)); - dev->host_features = vdev->get_features(vdev, dev->host_features); - s390_virtio_device_sync(dev); - s390_virtio_reset_idx(dev); - if (dev->qdev.hotplugged) { - S390CPU *cpu = s390_cpu_addr2state(0); - s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs); - } - - return 0; -} - -static int s390_virtio_net_init(VirtIOS390Device *dev) -{ - VirtIODevice *vdev; - - vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net); - if (!vdev) { - return -1; - } - - return s390_virtio_device_init(dev, vdev); -} - -static int s390_virtio_blk_init(VirtIOS390Device *dev) -{ - VirtIODevice *vdev; - - vdev = virtio_blk_init((DeviceState *)dev, &dev->blk); - if (!vdev) { - return -1; - } - - return s390_virtio_device_init(dev, vdev); -} - -static int s390_virtio_serial_init(VirtIOS390Device *dev) -{ - VirtIOS390Bus *bus; - VirtIODevice *vdev; - int r; - - bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus); - - vdev = virtio_serial_init((DeviceState *)dev, &dev->serial); - if (!vdev) { - return -1; - } - - r = s390_virtio_device_init(dev, vdev); - if (!r) { - bus->console = dev; - } - - return r; -} - -static int s390_virtio_scsi_init(VirtIOS390Device *dev) -{ - VirtIODevice *vdev; - - vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi); - if (!vdev) { - return -1; - } - - return s390_virtio_device_init(dev, vdev); -} - -static int s390_virtio_rng_init(VirtIOS390Device *dev) -{ - VirtIODevice *vdev; - - vdev = virtio_rng_init((DeviceState *)dev, &dev->rng); - if (!vdev) { - return -1; - } - - return s390_virtio_device_init(dev, vdev); -} - -static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq) -{ - ram_addr_t token_off; - - token_off = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) + - (vq * VIRTIO_VQCONFIG_LEN) + - VIRTIO_VQCONFIG_OFFS_TOKEN; - - return ldq_be_phys(token_off); -} - -static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev) -{ - VirtIODevice *vdev = dev->vdev; - int num_vq; - - for (num_vq = 0; num_vq < VIRTIO_PCI_QUEUE_MAX; num_vq++) { - if (!virtio_queue_get_num(vdev, num_vq)) { - break; - } - } - - return num_vq; -} - -static ram_addr_t s390_virtio_next_ring(VirtIOS390Bus *bus) -{ - ram_addr_t r = bus->next_ring; - - bus->next_ring += VIRTIO_RING_LEN; - return r; -} - -void s390_virtio_device_sync(VirtIOS390Device *dev) -{ - VirtIOS390Bus *bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus); - ram_addr_t cur_offs; - uint8_t num_vq; - int i; - - virtio_reset(dev->vdev); - - /* Sync dev space */ - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id); - - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, s390_virtio_device_num_vq(dev)); - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len); - - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len); - - num_vq = s390_virtio_device_num_vq(dev); - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq); - - /* Sync virtqueues */ - for (i = 0; i < num_vq; i++) { - ram_addr_t vq = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) + - (i * VIRTIO_VQCONFIG_LEN); - ram_addr_t vring; - - vring = s390_virtio_next_ring(bus); - virtio_queue_set_addr(dev->vdev, i, vring); - virtio_queue_set_vector(dev->vdev, i, i); - stq_be_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring); - stw_be_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i)); - } - - cur_offs = dev->dev_offs; - cur_offs += VIRTIO_DEV_OFFS_CONFIG; - cur_offs += num_vq * VIRTIO_VQCONFIG_LEN; - - /* Sync feature bitmap */ - stl_le_phys(cur_offs, dev->host_features); - - dev->feat_offs = cur_offs + dev->feat_len; - cur_offs += dev->feat_len * 2; - - /* Sync config space */ - if (dev->vdev->get_config) { - dev->vdev->get_config(dev->vdev, dev->vdev->config); - } - - cpu_physical_memory_write(cur_offs, - dev->vdev->config, dev->vdev->config_len); - cur_offs += dev->vdev->config_len; -} - -void s390_virtio_device_update_status(VirtIOS390Device *dev) -{ - VirtIODevice *vdev = dev->vdev; - uint32_t features; - - virtio_set_status(vdev, ldub_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS)); - - /* Update guest supported feature bitmap */ - - features = bswap32(ldl_be_phys(dev->feat_offs)); - virtio_set_features(vdev, features); -} - -VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus) -{ - return bus->console; -} - -/* Find a device by vring address */ -VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, - ram_addr_t mem, - int *vq_num) -{ - BusChild *kid; - int i; - - QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { - VirtIOS390Device *dev = (VirtIOS390Device *)kid->child; - - for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) { - if (!virtio_queue_get_addr(dev->vdev, i)) - break; - if (virtio_queue_get_addr(dev->vdev, i) == mem) { - if (vq_num) { - *vq_num = i; - } - return dev; - } - } - } - - return NULL; -} - -/* Find a device by device descriptor location */ -VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem) -{ - BusChild *kid; - - QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { - VirtIOS390Device *dev = (VirtIOS390Device *)kid->child; - if (dev->dev_offs == mem) { - return dev; - } - } - - return NULL; -} - -/* DeviceState to VirtIOS390Device. Note: used on datapath, - * be careful and test performance if you change this. - */ -static inline VirtIOS390Device *to_virtio_s390_device_fast(DeviceState *d) -{ - return container_of(d, VirtIOS390Device, qdev); -} - -/* DeviceState to VirtIOS390Device. TODO: use QOM. */ -static inline VirtIOS390Device *to_virtio_s390_device(DeviceState *d) -{ - return container_of(d, VirtIOS390Device, qdev); -} - -static void virtio_s390_notify(DeviceState *d, uint16_t vector) -{ - VirtIOS390Device *dev = to_virtio_s390_device_fast(d); - uint64_t token = s390_virtio_device_vq_token(dev, vector); - S390CPU *cpu = s390_cpu_addr2state(0); - - s390_virtio_irq(cpu, 0, token); -} - -static unsigned virtio_s390_get_features(DeviceState *d) -{ - VirtIOS390Device *dev = to_virtio_s390_device(d); - return dev->host_features; -} - -/**************** S390 Virtio Bus Device Descriptions *******************/ - -static const VirtIOBindings virtio_s390_bindings = { - .notify = virtio_s390_notify, - .get_features = virtio_s390_get_features, -}; - -static Property s390_virtio_net_properties[] = { - DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic), - DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device, - net.txtimer, TX_TIMER_INTERVAL), - DEFINE_PROP_INT32("x-txburst", VirtIOS390Device, - net.txburst, TX_BURST), - DEFINE_PROP_STRING("tx", VirtIOS390Device, net.tx), - DEFINE_PROP_END_OF_LIST(), -}; - -static void s390_virtio_net_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->init = s390_virtio_net_init; - dc->props = s390_virtio_net_properties; -} - -static const TypeInfo s390_virtio_net = { - .name = "virtio-net-s390", - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOS390Device), - .class_init = s390_virtio_net_class_init, -}; - -static Property s390_virtio_blk_properties[] = { - DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf), - DEFINE_BLOCK_CHS_PROPERTIES(VirtIOS390Device, blk.conf), - DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial), -#ifdef __linux__ - DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true), -#endif - DEFINE_PROP_END_OF_LIST(), -}; - -static void s390_virtio_blk_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->init = s390_virtio_blk_init; - dc->props = s390_virtio_blk_properties; -} - -static const TypeInfo s390_virtio_blk = { - .name = "virtio-blk-s390", - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOS390Device), - .class_init = s390_virtio_blk_class_init, -}; - -static Property s390_virtio_serial_properties[] = { - DEFINE_PROP_UINT32("max_ports", VirtIOS390Device, - serial.max_virtserial_ports, 31), - DEFINE_PROP_END_OF_LIST(), -}; - -static void s390_virtio_serial_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->init = s390_virtio_serial_init; - dc->props = s390_virtio_serial_properties; -} - -static const TypeInfo s390_virtio_serial = { - .name = "virtio-serial-s390", - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOS390Device), - .class_init = s390_virtio_serial_class_init, -}; - -static void s390_virtio_rng_initfn(Object *obj) -{ - VirtIOS390Device *dev = VIRTIO_S390_DEVICE(obj); - - object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, - (Object **)&dev->rng.rng, NULL); -} - -static void s390_virtio_rng_class_init(ObjectClass *klass, void *data) -{ - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->init = s390_virtio_rng_init; -} - -static const TypeInfo s390_virtio_rng = { - .name = "virtio-rng-s390", - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOS390Device), - .instance_init = s390_virtio_rng_initfn, - .class_init = s390_virtio_rng_class_init, -}; - -static int s390_virtio_busdev_init(DeviceState *dev) -{ - VirtIOS390Device *_dev = (VirtIOS390Device *)dev; - VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev); - - virtio_s390_bus_new(&_dev->bus, _dev); - - return _info->init(_dev); -} - -static void s390_virtio_busdev_reset(DeviceState *dev) -{ - VirtIOS390Device *_dev = (VirtIOS390Device *)dev; - - virtio_reset(_dev->vdev); -} - -static void virtio_s390_device_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->init = s390_virtio_busdev_init; - dc->bus_type = TYPE_S390_VIRTIO_BUS; - dc->unplug = qdev_simple_unplug_cb; - dc->reset = s390_virtio_busdev_reset; -} - -static const TypeInfo virtio_s390_device_info = { - .name = TYPE_VIRTIO_S390_DEVICE, - .parent = TYPE_DEVICE, - .instance_size = sizeof(VirtIOS390Device), - .class_init = virtio_s390_device_class_init, - .class_size = sizeof(VirtIOS390DeviceClass), - .abstract = true, -}; - -static Property s390_virtio_scsi_properties[] = { - DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi), - DEFINE_PROP_END_OF_LIST(), -}; - -static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->init = s390_virtio_scsi_init; - dc->props = s390_virtio_scsi_properties; -} - -static const TypeInfo s390_virtio_scsi = { - .name = "virtio-scsi-s390", - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOS390Device), - .class_init = s390_virtio_scsi_class_init, -}; - -/***************** S390 Virtio Bus Bridge Device *******************/ -/* Only required to have the virtio bus as child in the system bus */ - -static int s390_virtio_bridge_init(SysBusDevice *dev) -{ - /* nothing */ - return 0; -} - -static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = s390_virtio_bridge_init; - dc->no_user = 1; -} - -static const TypeInfo s390_virtio_bridge_info = { - .name = "s390-virtio-bridge", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SysBusDevice), - .class_init = s390_virtio_bridge_class_init, -}; - -/* virtio-s390-bus */ - -void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev) -{ - DeviceState *qdev = DEVICE(dev); - BusState *qbus; - qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_S390_BUS, qdev, NULL); - qbus = BUS(bus); - qbus->allow_hotplug = 0; -} - -static void virtio_s390_bus_class_init(ObjectClass *klass, void *data) -{ - VirtioBusClass *k = VIRTIO_BUS_CLASS(klass); - BusClass *bus_class = BUS_CLASS(klass); - bus_class->max_dev = 1; - k->notify = virtio_s390_notify; - k->get_features = virtio_s390_get_features; -} - -static const TypeInfo virtio_s390_bus_info = { - .name = TYPE_VIRTIO_S390_BUS, - .parent = TYPE_VIRTIO_BUS, - .instance_size = sizeof(VirtioS390BusState), - .class_init = virtio_s390_bus_class_init, -}; - -static void s390_virtio_register_types(void) -{ - type_register_static(&virtio_s390_bus_info); - type_register_static(&s390_virtio_bus_info); - type_register_static(&virtio_s390_device_info); - type_register_static(&s390_virtio_serial); - type_register_static(&s390_virtio_blk); - type_register_static(&s390_virtio_net); - type_register_static(&s390_virtio_scsi); - type_register_static(&s390_virtio_rng); - type_register_static(&s390_virtio_bridge_info); -} - -type_init(s390_virtio_register_types) diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h deleted file mode 100644 index 438b37fd8..000000000 --- a/hw/s390-virtio-bus.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * QEMU S390x VirtIO BUS definitions - * - * Copyright (c) 2009 Alexander Graf - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef HW_S390_VIRTIO_BUS_H -#define HW_S390_VIRTIO_BUS_H 1 - -#include "virtio-blk.h" -#include "virtio-net.h" -#include "virtio-rng.h" -#include "virtio-serial.h" -#include "virtio-scsi.h" -#include "virtio-bus.h" - -#define VIRTIO_DEV_OFFS_TYPE 0 /* 8 bits */ -#define VIRTIO_DEV_OFFS_NUM_VQ 1 /* 8 bits */ -#define VIRTIO_DEV_OFFS_FEATURE_LEN 2 /* 8 bits */ -#define VIRTIO_DEV_OFFS_CONFIG_LEN 3 /* 8 bits */ -#define VIRTIO_DEV_OFFS_STATUS 4 /* 8 bits */ -#define VIRTIO_DEV_OFFS_CONFIG 5 /* dynamic */ - -#define VIRTIO_VQCONFIG_OFFS_TOKEN 0 /* 64 bits */ -#define VIRTIO_VQCONFIG_OFFS_ADDRESS 8 /* 64 bits */ -#define VIRTIO_VQCONFIG_OFFS_NUM 16 /* 16 bits */ -#define VIRTIO_VQCONFIG_LEN 24 - -#define VIRTIO_RING_LEN (TARGET_PAGE_SIZE * 3) -#define VIRTIO_VRING_AVAIL_IDX_OFFS 2 -#define VIRTIO_VRING_USED_IDX_OFFS 2 -#define S390_DEVICE_PAGES 512 - -#define VIRTIO_PARAM_MASK 0xff -#define VIRTIO_PARAM_VRING_INTERRUPT 0x0 -#define VIRTIO_PARAM_CONFIG_CHANGED 0x1 -#define VIRTIO_PARAM_DEV_ADD 0x2 - -#define TYPE_VIRTIO_S390_DEVICE "virtio-s390-device" -#define VIRTIO_S390_DEVICE(obj) \ - OBJECT_CHECK(VirtIOS390Device, (obj), TYPE_VIRTIO_S390_DEVICE) -#define VIRTIO_S390_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtIOS390DeviceClass, (klass), TYPE_VIRTIO_S390_DEVICE) -#define VIRTIO_S390_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOS390DeviceClass, (obj), TYPE_VIRTIO_S390_DEVICE) - -#define TYPE_S390_VIRTIO_BUS "s390-virtio-bus" -#define S390_VIRTIO_BUS(obj) \ - OBJECT_CHECK(VirtIOS390Bus, (obj), TYPE_S390_VIRTIO_BUS) - -/* virtio-s390-bus */ - -typedef struct VirtioBusState VirtioS390BusState; -typedef struct VirtioBusClass VirtioS390BusClass; - -#define TYPE_VIRTIO_S390_BUS "virtio-s390-bus" -#define VIRTIO_S390_BUS(obj) \ - OBJECT_CHECK(VirtioS390BusState, (obj), TYPE_VIRTIO_S390_BUS) -#define VIRTIO_S390_BUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtioS390BusClass, obj, TYPE_VIRTIO_S390_BUS) -#define VIRTIO_S390_BUS_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtioS390BusClass, klass, TYPE_VIRTIO_S390_BUS) - - -typedef struct VirtIOS390Device VirtIOS390Device; - -void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev); - -typedef struct VirtIOS390DeviceClass { - DeviceClass qdev; - int (*init)(VirtIOS390Device *dev); -} VirtIOS390DeviceClass; - -struct VirtIOS390Device { - DeviceState qdev; - ram_addr_t dev_offs; - ram_addr_t feat_offs; - uint8_t feat_len; - VirtIODevice *vdev; - VirtIOBlkConf blk; - NICConf nic; - uint32_t host_features; - virtio_serial_conf serial; - virtio_net_conf net; - VirtIOSCSIConf scsi; - VirtIORNGConf rng; - VirtioBusState bus; -}; - -typedef struct VirtIOS390Bus { - BusState bus; - - VirtIOS390Device *console; - ram_addr_t dev_page; - ram_addr_t dev_offs; - ram_addr_t next_ring; -} VirtIOS390Bus; - - -void s390_virtio_device_update_status(VirtIOS390Device *dev); - -VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus); -VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size); - -VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, - ram_addr_t mem, int *vq_num); -VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem); -void s390_virtio_device_sync(VirtIOS390Device *dev); -void s390_virtio_reset_idx(VirtIOS390Device *dev); - - -#endif diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c deleted file mode 100644 index 6e0f53bd8..000000000 --- a/hw/s390-virtio.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * QEMU S390 virtio target - * - * Copyright (c) 2009 Alexander Graf - * Copyright IBM Corp 2012 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * Contributions after 2012-10-29 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - * - * You should have received a copy of the GNU (Lesser) General Public - * License along with this library; if not, see . - */ - -#include "hw.h" -#include "block/block.h" -#include "sysemu/blockdev.h" -#include "sysemu/sysemu.h" -#include "net/net.h" -#include "boards.h" -#include "monitor/monitor.h" -#include "loader.h" -#include "hw/virtio.h" -#include "hw/sysbus.h" -#include "sysemu/kvm.h" -#include "exec/address-spaces.h" - -#include "hw/s390-virtio-bus.h" -#include "hw/s390x/sclp.h" -#include "hw/s390-virtio.h" - -//#define DEBUG_S390 - -#ifdef DEBUG_S390 -#define dprintf(fmt, ...) \ - do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) -#else -#define dprintf(fmt, ...) \ - do { } while (0) -#endif - -#define MAX_BLK_DEVS 10 - -static VirtIOS390Bus *s390_bus; -static S390CPU **ipi_states; - -S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) -{ - if (cpu_addr >= smp_cpus) { - return NULL; - } - - return ipi_states[cpu_addr]; -} - -static int s390_virtio_hcall_notify(const uint64_t *args) -{ - uint64_t mem = args[0]; - int r = 0, i; - - if (mem > ram_size) { - VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus, mem, &i); - if (dev) { - virtio_queue_notify(dev->vdev, i); - } else { - r = -EINVAL; - } - } else { - /* Early printk */ - } - return r; -} - -static int s390_virtio_hcall_reset(const uint64_t *args) -{ - uint64_t mem = args[0]; - VirtIOS390Device *dev; - - dev = s390_virtio_bus_find_mem(s390_bus, mem); - virtio_reset(dev->vdev); - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0); - s390_virtio_device_sync(dev); - s390_virtio_reset_idx(dev); - - return 0; -} - -static int s390_virtio_hcall_set_status(const uint64_t *args) -{ - uint64_t mem = args[0]; - int r = 0; - VirtIOS390Device *dev; - - dev = s390_virtio_bus_find_mem(s390_bus, mem); - if (dev) { - s390_virtio_device_update_status(dev); - } else { - r = -EINVAL; - } - return r; -} - -static void s390_virtio_register_hcalls(void) -{ - s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY, - s390_virtio_hcall_notify); - s390_register_virtio_hypercall(KVM_S390_VIRTIO_RESET, - s390_virtio_hcall_reset); - s390_register_virtio_hypercall(KVM_S390_VIRTIO_SET_STATUS, - s390_virtio_hcall_set_status); -} - -/* - * The number of running CPUs. On s390 a shutdown is the state of all CPUs - * being either stopped or disabled (for interrupts) waiting. We have to - * track this number to call the shutdown sequence accordingly. This - * number is modified either on startup or while holding the big qemu lock. - */ -static unsigned s390_running_cpus; - -void s390_add_running_cpu(CPUS390XState *env) -{ - if (env->halted) { - s390_running_cpus++; - env->halted = 0; - env->exception_index = -1; - } -} - -unsigned s390_del_running_cpu(CPUS390XState *env) -{ - if (env->halted == 0) { - assert(s390_running_cpus >= 1); - s390_running_cpus--; - env->halted = 1; - env->exception_index = EXCP_HLT; - } - return s390_running_cpus; -} - -void s390_init_ipl_dev(const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename) -{ - DeviceState *dev; - - dev = qdev_create(NULL, "s390-ipl"); - if (kernel_filename) { - qdev_prop_set_string(dev, "kernel", kernel_filename); - } - if (initrd_filename) { - qdev_prop_set_string(dev, "initrd", initrd_filename); - } - qdev_prop_set_string(dev, "cmdline", kernel_cmdline); - qdev_init_nofail(dev); -} - -void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys) -{ - int i; - - if (cpu_model == NULL) { - cpu_model = "host"; - } - - ipi_states = g_malloc(sizeof(S390CPU *) * smp_cpus); - - for (i = 0; i < smp_cpus; i++) { - S390CPU *cpu; - - cpu = cpu_s390x_init(cpu_model); - - ipi_states[i] = cpu; - cpu->env.halted = 1; - cpu->env.exception_index = EXCP_HLT; - cpu->env.storage_keys = storage_keys; - } -} - - -void s390_create_virtio_net(BusState *bus, const char *name) -{ - int i; - - for (i = 0; i < nb_nics; i++) { - NICInfo *nd = &nd_table[i]; - DeviceState *dev; - - if (!nd->model) { - nd->model = g_strdup("virtio"); - } - - if (strcmp(nd->model, "virtio")) { - fprintf(stderr, "S390 only supports VirtIO nics\n"); - exit(1); - } - - dev = qdev_create(bus, name); - qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); - } -} - -/* PC hardware initialisation */ -static void s390_init(QEMUMachineInitArgs *args) -{ - ram_addr_t my_ram_size = args->ram_size; - MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); - int shift = 0; - uint8_t *storage_keys; - void *virtio_region; - hwaddr virtio_region_len; - hwaddr virtio_region_start; - - /* s390x ram size detection needs a 16bit multiplier + an increment. So - guests > 64GB can be specified in 2MB steps etc. */ - while ((my_ram_size >> (20 + shift)) > 65535) { - shift++; - } - my_ram_size = my_ram_size >> (20 + shift) << (20 + shift); - - /* lets propagate the changed ram size into the global variable. */ - ram_size = my_ram_size; - - /* get a BUS */ - s390_bus = s390_virtio_bus_init(&my_ram_size); - s390_sclp_init(); - s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline, - args->initrd_filename); - - /* register hypercalls */ - s390_virtio_register_hcalls(); - - /* allocate RAM */ - memory_region_init_ram(ram, "s390.ram", my_ram_size); - vmstate_register_ram_global(ram); - memory_region_add_subregion(sysmem, 0, ram); - - /* clear virtio region */ - virtio_region_len = my_ram_size - ram_size; - virtio_region_start = ram_size; - virtio_region = cpu_physical_memory_map(virtio_region_start, - &virtio_region_len, true); - memset(virtio_region, 0, virtio_region_len); - cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1, - virtio_region_len); - - /* allocate storage keys */ - storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE); - - /* init CPUs */ - s390_init_cpus(args->cpu_model, storage_keys); - - /* Create VirtIO network adapters */ - s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390"); -} - -static QEMUMachine s390_machine = { - .name = "s390-virtio", - .alias = "s390", - .desc = "VirtIO based S390 machine", - .init = s390_init, - .block_default_type = IF_VIRTIO, - .no_cdrom = 1, - .no_floppy = 1, - .no_serial = 1, - .no_parallel = 1, - .no_sdcard = 1, - .use_virtcon = 1, - .max_cpus = 255, - .is_default = 1, - DEFAULT_MACHINE_OPTIONS, -}; - -static void s390_machine_init(void) -{ - qemu_register_machine(&s390_machine); -} - -machine_init(s390_machine_init); diff --git a/hw/s390-virtio.h b/hw/s390-virtio.h deleted file mode 100644 index 67bfd2064..000000000 --- a/hw/s390-virtio.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Virtio interfaces for s390 - * - * Copyright 2012 IBM Corp. - * Author(s): Cornelia Huck - * - * 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. - */ - -#ifndef HW_S390_VIRTIO_H -#define HW_S390_VIRTIO_H 1 - -#define KVM_S390_VIRTIO_NOTIFY 0 -#define KVM_S390_VIRTIO_RESET 1 -#define KVM_S390_VIRTIO_SET_STATUS 2 - -typedef int (*s390_virtio_fn)(const uint64_t *args); -void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn); - -void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys); -void s390_init_ipl_dev(const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename); -void s390_create_virtio_net(BusState *bus, const char *name); -#endif diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index f6b461b6b..e4ee456fd 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -1,6 +1,4 @@ obj-y = s390-virtio-bus.o s390-virtio.o - -obj-y := $(addprefix ../,$(obj-y)) obj-y += s390-virtio-hcall.o obj-y += sclp.o obj-y += event-facility.o diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c new file mode 100644 index 000000000..32f63b07e --- /dev/null +++ b/hw/s390x/s390-virtio-bus.c @@ -0,0 +1,623 @@ +/* + * QEMU S390 virtio target + * + * Copyright (c) 2009 Alexander Graf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "hw/hw.h" +#include "block/block.h" +#include "sysemu/sysemu.h" +#include "hw/boards.h" +#include "monitor/monitor.h" +#include "hw/loader.h" +#include "elf.h" +#include "hw/virtio.h" +#include "hw/virtio-rng.h" +#include "hw/virtio-serial.h" +#include "hw/virtio-net.h" +#include "hw/sysbus.h" +#include "sysemu/kvm.h" + +#include "hw/s390x/s390-virtio-bus.h" +#include "hw/virtio-bus.h" + +/* #define DEBUG_S390 */ + +#ifdef DEBUG_S390 +#define dprintf(fmt, ...) \ + do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) +#else +#define dprintf(fmt, ...) \ + do { } while (0) +#endif + +#define VIRTIO_EXT_CODE 0x2603 + +static const TypeInfo s390_virtio_bus_info = { + .name = TYPE_S390_VIRTIO_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(VirtIOS390Bus), +}; + +static const VirtIOBindings virtio_s390_bindings; + +static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev); + +/* length of VirtIO device pages */ +const hwaddr virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE; + +static void s390_virtio_bus_reset(void *opaque) +{ + VirtIOS390Bus *bus = opaque; + bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; +} + +void s390_virtio_reset_idx(VirtIOS390Device *dev) +{ + int i; + hwaddr idx_addr; + uint8_t num_vq; + + num_vq = s390_virtio_device_num_vq(dev); + for (i = 0; i < num_vq; i++) { + idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) + + VIRTIO_VRING_AVAIL_IDX_OFFS; + stw_phys(idx_addr, 0); + idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + + VIRTIO_VRING_USED_IDX_OFFS; + stw_phys(idx_addr, 0); + } +} + +VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) +{ + VirtIOS390Bus *bus; + BusState *_bus; + DeviceState *dev; + + /* Create bridge device */ + dev = qdev_create(NULL, "s390-virtio-bridge"); + qdev_init_nofail(dev); + + /* Create bus on bridge device */ + + _bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio"); + bus = DO_UPCAST(VirtIOS390Bus, bus, _bus); + + bus->dev_page = *ram_size; + bus->dev_offs = bus->dev_page; + bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; + + /* Enable hotplugging */ + _bus->allow_hotplug = 1; + + /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */ + *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE; + + qemu_register_reset(s390_virtio_bus_reset, bus); + return bus; +} + +static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token) +{ + CPUS390XState *env = &cpu->env; + + if (kvm_enabled()) { + kvm_s390_virtio_irq(cpu, config_change, token); + } else { + cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token); + } +} + +static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) +{ + VirtIOS390Bus *bus; + int dev_len; + + bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus); + dev->vdev = vdev; + dev->dev_offs = bus->dev_offs; + dev->feat_len = sizeof(uint32_t); /* always keep 32 bits features */ + + dev_len = VIRTIO_DEV_OFFS_CONFIG; + dev_len += s390_virtio_device_num_vq(dev) * VIRTIO_VQCONFIG_LEN; + dev_len += dev->feat_len * 2; + dev_len += vdev->config_len; + + bus->dev_offs += dev_len; + + virtio_bind_device(vdev, &virtio_s390_bindings, DEVICE(dev)); + dev->host_features = vdev->get_features(vdev, dev->host_features); + s390_virtio_device_sync(dev); + s390_virtio_reset_idx(dev); + if (dev->qdev.hotplugged) { + S390CPU *cpu = s390_cpu_addr2state(0); + s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs); + } + + return 0; +} + +static int s390_virtio_net_init(VirtIOS390Device *dev) +{ + VirtIODevice *vdev; + + vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net); + if (!vdev) { + return -1; + } + + return s390_virtio_device_init(dev, vdev); +} + +static int s390_virtio_blk_init(VirtIOS390Device *dev) +{ + VirtIODevice *vdev; + + vdev = virtio_blk_init((DeviceState *)dev, &dev->blk); + if (!vdev) { + return -1; + } + + return s390_virtio_device_init(dev, vdev); +} + +static int s390_virtio_serial_init(VirtIOS390Device *dev) +{ + VirtIOS390Bus *bus; + VirtIODevice *vdev; + int r; + + bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus); + + vdev = virtio_serial_init((DeviceState *)dev, &dev->serial); + if (!vdev) { + return -1; + } + + r = s390_virtio_device_init(dev, vdev); + if (!r) { + bus->console = dev; + } + + return r; +} + +static int s390_virtio_scsi_init(VirtIOS390Device *dev) +{ + VirtIODevice *vdev; + + vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi); + if (!vdev) { + return -1; + } + + return s390_virtio_device_init(dev, vdev); +} + +static int s390_virtio_rng_init(VirtIOS390Device *dev) +{ + VirtIODevice *vdev; + + vdev = virtio_rng_init((DeviceState *)dev, &dev->rng); + if (!vdev) { + return -1; + } + + return s390_virtio_device_init(dev, vdev); +} + +static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq) +{ + ram_addr_t token_off; + + token_off = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) + + (vq * VIRTIO_VQCONFIG_LEN) + + VIRTIO_VQCONFIG_OFFS_TOKEN; + + return ldq_be_phys(token_off); +} + +static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev) +{ + VirtIODevice *vdev = dev->vdev; + int num_vq; + + for (num_vq = 0; num_vq < VIRTIO_PCI_QUEUE_MAX; num_vq++) { + if (!virtio_queue_get_num(vdev, num_vq)) { + break; + } + } + + return num_vq; +} + +static ram_addr_t s390_virtio_next_ring(VirtIOS390Bus *bus) +{ + ram_addr_t r = bus->next_ring; + + bus->next_ring += VIRTIO_RING_LEN; + return r; +} + +void s390_virtio_device_sync(VirtIOS390Device *dev) +{ + VirtIOS390Bus *bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus); + ram_addr_t cur_offs; + uint8_t num_vq; + int i; + + virtio_reset(dev->vdev); + + /* Sync dev space */ + stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id); + + stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, s390_virtio_device_num_vq(dev)); + stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len); + + stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len); + + num_vq = s390_virtio_device_num_vq(dev); + stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq); + + /* Sync virtqueues */ + for (i = 0; i < num_vq; i++) { + ram_addr_t vq = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) + + (i * VIRTIO_VQCONFIG_LEN); + ram_addr_t vring; + + vring = s390_virtio_next_ring(bus); + virtio_queue_set_addr(dev->vdev, i, vring); + virtio_queue_set_vector(dev->vdev, i, i); + stq_be_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring); + stw_be_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i)); + } + + cur_offs = dev->dev_offs; + cur_offs += VIRTIO_DEV_OFFS_CONFIG; + cur_offs += num_vq * VIRTIO_VQCONFIG_LEN; + + /* Sync feature bitmap */ + stl_le_phys(cur_offs, dev->host_features); + + dev->feat_offs = cur_offs + dev->feat_len; + cur_offs += dev->feat_len * 2; + + /* Sync config space */ + if (dev->vdev->get_config) { + dev->vdev->get_config(dev->vdev, dev->vdev->config); + } + + cpu_physical_memory_write(cur_offs, + dev->vdev->config, dev->vdev->config_len); + cur_offs += dev->vdev->config_len; +} + +void s390_virtio_device_update_status(VirtIOS390Device *dev) +{ + VirtIODevice *vdev = dev->vdev; + uint32_t features; + + virtio_set_status(vdev, ldub_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS)); + + /* Update guest supported feature bitmap */ + + features = bswap32(ldl_be_phys(dev->feat_offs)); + virtio_set_features(vdev, features); +} + +VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus) +{ + return bus->console; +} + +/* Find a device by vring address */ +VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, + ram_addr_t mem, + int *vq_num) +{ + BusChild *kid; + int i; + + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + VirtIOS390Device *dev = (VirtIOS390Device *)kid->child; + + for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) { + if (!virtio_queue_get_addr(dev->vdev, i)) + break; + if (virtio_queue_get_addr(dev->vdev, i) == mem) { + if (vq_num) { + *vq_num = i; + } + return dev; + } + } + } + + return NULL; +} + +/* Find a device by device descriptor location */ +VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem) +{ + BusChild *kid; + + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + VirtIOS390Device *dev = (VirtIOS390Device *)kid->child; + if (dev->dev_offs == mem) { + return dev; + } + } + + return NULL; +} + +/* DeviceState to VirtIOS390Device. Note: used on datapath, + * be careful and test performance if you change this. + */ +static inline VirtIOS390Device *to_virtio_s390_device_fast(DeviceState *d) +{ + return container_of(d, VirtIOS390Device, qdev); +} + +/* DeviceState to VirtIOS390Device. TODO: use QOM. */ +static inline VirtIOS390Device *to_virtio_s390_device(DeviceState *d) +{ + return container_of(d, VirtIOS390Device, qdev); +} + +static void virtio_s390_notify(DeviceState *d, uint16_t vector) +{ + VirtIOS390Device *dev = to_virtio_s390_device_fast(d); + uint64_t token = s390_virtio_device_vq_token(dev, vector); + S390CPU *cpu = s390_cpu_addr2state(0); + + s390_virtio_irq(cpu, 0, token); +} + +static unsigned virtio_s390_get_features(DeviceState *d) +{ + VirtIOS390Device *dev = to_virtio_s390_device(d); + return dev->host_features; +} + +/**************** S390 Virtio Bus Device Descriptions *******************/ + +static const VirtIOBindings virtio_s390_bindings = { + .notify = virtio_s390_notify, + .get_features = virtio_s390_get_features, +}; + +static Property s390_virtio_net_properties[] = { + DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic), + DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device, + net.txtimer, TX_TIMER_INTERVAL), + DEFINE_PROP_INT32("x-txburst", VirtIOS390Device, + net.txburst, TX_BURST), + DEFINE_PROP_STRING("tx", VirtIOS390Device, net.tx), + DEFINE_PROP_END_OF_LIST(), +}; + +static void s390_virtio_net_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); + + k->init = s390_virtio_net_init; + dc->props = s390_virtio_net_properties; +} + +static const TypeInfo s390_virtio_net = { + .name = "virtio-net-s390", + .parent = TYPE_VIRTIO_S390_DEVICE, + .instance_size = sizeof(VirtIOS390Device), + .class_init = s390_virtio_net_class_init, +}; + +static Property s390_virtio_blk_properties[] = { + DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf), + DEFINE_BLOCK_CHS_PROPERTIES(VirtIOS390Device, blk.conf), + DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial), +#ifdef __linux__ + DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true), +#endif + DEFINE_PROP_END_OF_LIST(), +}; + +static void s390_virtio_blk_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); + + k->init = s390_virtio_blk_init; + dc->props = s390_virtio_blk_properties; +} + +static const TypeInfo s390_virtio_blk = { + .name = "virtio-blk-s390", + .parent = TYPE_VIRTIO_S390_DEVICE, + .instance_size = sizeof(VirtIOS390Device), + .class_init = s390_virtio_blk_class_init, +}; + +static Property s390_virtio_serial_properties[] = { + DEFINE_PROP_UINT32("max_ports", VirtIOS390Device, + serial.max_virtserial_ports, 31), + DEFINE_PROP_END_OF_LIST(), +}; + +static void s390_virtio_serial_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); + + k->init = s390_virtio_serial_init; + dc->props = s390_virtio_serial_properties; +} + +static const TypeInfo s390_virtio_serial = { + .name = "virtio-serial-s390", + .parent = TYPE_VIRTIO_S390_DEVICE, + .instance_size = sizeof(VirtIOS390Device), + .class_init = s390_virtio_serial_class_init, +}; + +static void s390_virtio_rng_initfn(Object *obj) +{ + VirtIOS390Device *dev = VIRTIO_S390_DEVICE(obj); + + object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, + (Object **)&dev->rng.rng, NULL); +} + +static void s390_virtio_rng_class_init(ObjectClass *klass, void *data) +{ + VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); + + k->init = s390_virtio_rng_init; +} + +static const TypeInfo s390_virtio_rng = { + .name = "virtio-rng-s390", + .parent = TYPE_VIRTIO_S390_DEVICE, + .instance_size = sizeof(VirtIOS390Device), + .instance_init = s390_virtio_rng_initfn, + .class_init = s390_virtio_rng_class_init, +}; + +static int s390_virtio_busdev_init(DeviceState *dev) +{ + VirtIOS390Device *_dev = (VirtIOS390Device *)dev; + VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev); + + virtio_s390_bus_new(&_dev->bus, _dev); + + return _info->init(_dev); +} + +static void s390_virtio_busdev_reset(DeviceState *dev) +{ + VirtIOS390Device *_dev = (VirtIOS390Device *)dev; + + virtio_reset(_dev->vdev); +} + +static void virtio_s390_device_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->init = s390_virtio_busdev_init; + dc->bus_type = TYPE_S390_VIRTIO_BUS; + dc->unplug = qdev_simple_unplug_cb; + dc->reset = s390_virtio_busdev_reset; +} + +static const TypeInfo virtio_s390_device_info = { + .name = TYPE_VIRTIO_S390_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(VirtIOS390Device), + .class_init = virtio_s390_device_class_init, + .class_size = sizeof(VirtIOS390DeviceClass), + .abstract = true, +}; + +static Property s390_virtio_scsi_properties[] = { + DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi), + DEFINE_PROP_END_OF_LIST(), +}; + +static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); + + k->init = s390_virtio_scsi_init; + dc->props = s390_virtio_scsi_properties; +} + +static const TypeInfo s390_virtio_scsi = { + .name = "virtio-scsi-s390", + .parent = TYPE_VIRTIO_S390_DEVICE, + .instance_size = sizeof(VirtIOS390Device), + .class_init = s390_virtio_scsi_class_init, +}; + +/***************** S390 Virtio Bus Bridge Device *******************/ +/* Only required to have the virtio bus as child in the system bus */ + +static int s390_virtio_bridge_init(SysBusDevice *dev) +{ + /* nothing */ + return 0; +} + +static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = s390_virtio_bridge_init; + dc->no_user = 1; +} + +static const TypeInfo s390_virtio_bridge_info = { + .name = "s390-virtio-bridge", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SysBusDevice), + .class_init = s390_virtio_bridge_class_init, +}; + +/* virtio-s390-bus */ + +void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev) +{ + DeviceState *qdev = DEVICE(dev); + BusState *qbus; + qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_S390_BUS, qdev, NULL); + qbus = BUS(bus); + qbus->allow_hotplug = 0; +} + +static void virtio_s390_bus_class_init(ObjectClass *klass, void *data) +{ + VirtioBusClass *k = VIRTIO_BUS_CLASS(klass); + BusClass *bus_class = BUS_CLASS(klass); + bus_class->max_dev = 1; + k->notify = virtio_s390_notify; + k->get_features = virtio_s390_get_features; +} + +static const TypeInfo virtio_s390_bus_info = { + .name = TYPE_VIRTIO_S390_BUS, + .parent = TYPE_VIRTIO_BUS, + .instance_size = sizeof(VirtioS390BusState), + .class_init = virtio_s390_bus_class_init, +}; + +static void s390_virtio_register_types(void) +{ + type_register_static(&virtio_s390_bus_info); + type_register_static(&s390_virtio_bus_info); + type_register_static(&virtio_s390_device_info); + type_register_static(&s390_virtio_serial); + type_register_static(&s390_virtio_blk); + type_register_static(&s390_virtio_net); + type_register_static(&s390_virtio_scsi); + type_register_static(&s390_virtio_rng); + type_register_static(&s390_virtio_bridge_info); +} + +type_init(s390_virtio_register_types) diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h new file mode 100644 index 000000000..4aacf8399 --- /dev/null +++ b/hw/s390x/s390-virtio-bus.h @@ -0,0 +1,124 @@ +/* + * QEMU S390x VirtIO BUS definitions + * + * Copyright (c) 2009 Alexander Graf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef HW_S390_VIRTIO_BUS_H +#define HW_S390_VIRTIO_BUS_H 1 + +#include "hw/virtio-blk.h" +#include "hw/virtio-net.h" +#include "hw/virtio-rng.h" +#include "hw/virtio-serial.h" +#include "hw/virtio-scsi.h" +#include "hw/virtio-bus.h" + +#define VIRTIO_DEV_OFFS_TYPE 0 /* 8 bits */ +#define VIRTIO_DEV_OFFS_NUM_VQ 1 /* 8 bits */ +#define VIRTIO_DEV_OFFS_FEATURE_LEN 2 /* 8 bits */ +#define VIRTIO_DEV_OFFS_CONFIG_LEN 3 /* 8 bits */ +#define VIRTIO_DEV_OFFS_STATUS 4 /* 8 bits */ +#define VIRTIO_DEV_OFFS_CONFIG 5 /* dynamic */ + +#define VIRTIO_VQCONFIG_OFFS_TOKEN 0 /* 64 bits */ +#define VIRTIO_VQCONFIG_OFFS_ADDRESS 8 /* 64 bits */ +#define VIRTIO_VQCONFIG_OFFS_NUM 16 /* 16 bits */ +#define VIRTIO_VQCONFIG_LEN 24 + +#define VIRTIO_RING_LEN (TARGET_PAGE_SIZE * 3) +#define VIRTIO_VRING_AVAIL_IDX_OFFS 2 +#define VIRTIO_VRING_USED_IDX_OFFS 2 +#define S390_DEVICE_PAGES 512 + +#define VIRTIO_PARAM_MASK 0xff +#define VIRTIO_PARAM_VRING_INTERRUPT 0x0 +#define VIRTIO_PARAM_CONFIG_CHANGED 0x1 +#define VIRTIO_PARAM_DEV_ADD 0x2 + +#define TYPE_VIRTIO_S390_DEVICE "virtio-s390-device" +#define VIRTIO_S390_DEVICE(obj) \ + OBJECT_CHECK(VirtIOS390Device, (obj), TYPE_VIRTIO_S390_DEVICE) +#define VIRTIO_S390_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtIOS390DeviceClass, (klass), TYPE_VIRTIO_S390_DEVICE) +#define VIRTIO_S390_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtIOS390DeviceClass, (obj), TYPE_VIRTIO_S390_DEVICE) + +#define TYPE_S390_VIRTIO_BUS "s390-virtio-bus" +#define S390_VIRTIO_BUS(obj) \ + OBJECT_CHECK(VirtIOS390Bus, (obj), TYPE_S390_VIRTIO_BUS) + +/* virtio-s390-bus */ + +typedef struct VirtioBusState VirtioS390BusState; +typedef struct VirtioBusClass VirtioS390BusClass; + +#define TYPE_VIRTIO_S390_BUS "virtio-s390-bus" +#define VIRTIO_S390_BUS(obj) \ + OBJECT_CHECK(VirtioS390BusState, (obj), TYPE_VIRTIO_S390_BUS) +#define VIRTIO_S390_BUS_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtioS390BusClass, obj, TYPE_VIRTIO_S390_BUS) +#define VIRTIO_S390_BUS_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtioS390BusClass, klass, TYPE_VIRTIO_S390_BUS) + + +typedef struct VirtIOS390Device VirtIOS390Device; + +void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev); + +typedef struct VirtIOS390DeviceClass { + DeviceClass qdev; + int (*init)(VirtIOS390Device *dev); +} VirtIOS390DeviceClass; + +struct VirtIOS390Device { + DeviceState qdev; + ram_addr_t dev_offs; + ram_addr_t feat_offs; + uint8_t feat_len; + VirtIODevice *vdev; + VirtIOBlkConf blk; + NICConf nic; + uint32_t host_features; + virtio_serial_conf serial; + virtio_net_conf net; + VirtIOSCSIConf scsi; + VirtIORNGConf rng; + VirtioBusState bus; +}; + +typedef struct VirtIOS390Bus { + BusState bus; + + VirtIOS390Device *console; + ram_addr_t dev_page; + ram_addr_t dev_offs; + ram_addr_t next_ring; +} VirtIOS390Bus; + + +void s390_virtio_device_update_status(VirtIOS390Device *dev); + +VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus); +VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size); + +VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, + ram_addr_t mem, int *vq_num); +VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem); +void s390_virtio_device_sync(VirtIOS390Device *dev); +void s390_virtio_reset_idx(VirtIOS390Device *dev); + + +#endif diff --git a/hw/s390x/s390-virtio-hcall.c b/hw/s390x/s390-virtio-hcall.c index d7938c073..ee626493c 100644 --- a/hw/s390x/s390-virtio-hcall.c +++ b/hw/s390x/s390-virtio-hcall.c @@ -10,7 +10,7 @@ */ #include "cpu.h" -#include "hw/s390-virtio.h" +#include "hw/s390x/s390-virtio.h" #define MAX_DIAG_SUBCODES 255 diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c new file mode 100644 index 000000000..a8a489dc3 --- /dev/null +++ b/hw/s390x/s390-virtio.c @@ -0,0 +1,290 @@ +/* + * QEMU S390 virtio target + * + * Copyright (c) 2009 Alexander Graf + * Copyright IBM Corp 2012 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * Contributions after 2012-10-29 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + * + * You should have received a copy of the GNU (Lesser) General Public + * License along with this library; if not, see . + */ + +#include "hw/hw.h" +#include "block/block.h" +#include "sysemu/blockdev.h" +#include "sysemu/sysemu.h" +#include "net/net.h" +#include "hw/boards.h" +#include "monitor/monitor.h" +#include "hw/loader.h" +#include "hw/virtio.h" +#include "hw/sysbus.h" +#include "sysemu/kvm.h" +#include "exec/address-spaces.h" + +#include "hw/s390x/s390-virtio-bus.h" +#include "hw/s390x/sclp.h" +#include "hw/s390x/s390-virtio.h" + +//#define DEBUG_S390 + +#ifdef DEBUG_S390 +#define dprintf(fmt, ...) \ + do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) +#else +#define dprintf(fmt, ...) \ + do { } while (0) +#endif + +#define MAX_BLK_DEVS 10 + +static VirtIOS390Bus *s390_bus; +static S390CPU **ipi_states; + +S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) +{ + if (cpu_addr >= smp_cpus) { + return NULL; + } + + return ipi_states[cpu_addr]; +} + +static int s390_virtio_hcall_notify(const uint64_t *args) +{ + uint64_t mem = args[0]; + int r = 0, i; + + if (mem > ram_size) { + VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus, mem, &i); + if (dev) { + virtio_queue_notify(dev->vdev, i); + } else { + r = -EINVAL; + } + } else { + /* Early printk */ + } + return r; +} + +static int s390_virtio_hcall_reset(const uint64_t *args) +{ + uint64_t mem = args[0]; + VirtIOS390Device *dev; + + dev = s390_virtio_bus_find_mem(s390_bus, mem); + virtio_reset(dev->vdev); + stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0); + s390_virtio_device_sync(dev); + s390_virtio_reset_idx(dev); + + return 0; +} + +static int s390_virtio_hcall_set_status(const uint64_t *args) +{ + uint64_t mem = args[0]; + int r = 0; + VirtIOS390Device *dev; + + dev = s390_virtio_bus_find_mem(s390_bus, mem); + if (dev) { + s390_virtio_device_update_status(dev); + } else { + r = -EINVAL; + } + return r; +} + +static void s390_virtio_register_hcalls(void) +{ + s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY, + s390_virtio_hcall_notify); + s390_register_virtio_hypercall(KVM_S390_VIRTIO_RESET, + s390_virtio_hcall_reset); + s390_register_virtio_hypercall(KVM_S390_VIRTIO_SET_STATUS, + s390_virtio_hcall_set_status); +} + +/* + * The number of running CPUs. On s390 a shutdown is the state of all CPUs + * being either stopped or disabled (for interrupts) waiting. We have to + * track this number to call the shutdown sequence accordingly. This + * number is modified either on startup or while holding the big qemu lock. + */ +static unsigned s390_running_cpus; + +void s390_add_running_cpu(CPUS390XState *env) +{ + if (env->halted) { + s390_running_cpus++; + env->halted = 0; + env->exception_index = -1; + } +} + +unsigned s390_del_running_cpu(CPUS390XState *env) +{ + if (env->halted == 0) { + assert(s390_running_cpus >= 1); + s390_running_cpus--; + env->halted = 1; + env->exception_index = EXCP_HLT; + } + return s390_running_cpus; +} + +void s390_init_ipl_dev(const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename) +{ + DeviceState *dev; + + dev = qdev_create(NULL, "s390-ipl"); + if (kernel_filename) { + qdev_prop_set_string(dev, "kernel", kernel_filename); + } + if (initrd_filename) { + qdev_prop_set_string(dev, "initrd", initrd_filename); + } + qdev_prop_set_string(dev, "cmdline", kernel_cmdline); + qdev_init_nofail(dev); +} + +void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys) +{ + int i; + + if (cpu_model == NULL) { + cpu_model = "host"; + } + + ipi_states = g_malloc(sizeof(S390CPU *) * smp_cpus); + + for (i = 0; i < smp_cpus; i++) { + S390CPU *cpu; + + cpu = cpu_s390x_init(cpu_model); + + ipi_states[i] = cpu; + cpu->env.halted = 1; + cpu->env.exception_index = EXCP_HLT; + cpu->env.storage_keys = storage_keys; + } +} + + +void s390_create_virtio_net(BusState *bus, const char *name) +{ + int i; + + for (i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + DeviceState *dev; + + if (!nd->model) { + nd->model = g_strdup("virtio"); + } + + if (strcmp(nd->model, "virtio")) { + fprintf(stderr, "S390 only supports VirtIO nics\n"); + exit(1); + } + + dev = qdev_create(bus, name); + qdev_set_nic_properties(dev, nd); + qdev_init_nofail(dev); + } +} + +/* PC hardware initialisation */ +static void s390_init(QEMUMachineInitArgs *args) +{ + ram_addr_t my_ram_size = args->ram_size; + MemoryRegion *sysmem = get_system_memory(); + MemoryRegion *ram = g_new(MemoryRegion, 1); + int shift = 0; + uint8_t *storage_keys; + void *virtio_region; + hwaddr virtio_region_len; + hwaddr virtio_region_start; + + /* s390x ram size detection needs a 16bit multiplier + an increment. So + guests > 64GB can be specified in 2MB steps etc. */ + while ((my_ram_size >> (20 + shift)) > 65535) { + shift++; + } + my_ram_size = my_ram_size >> (20 + shift) << (20 + shift); + + /* lets propagate the changed ram size into the global variable. */ + ram_size = my_ram_size; + + /* get a BUS */ + s390_bus = s390_virtio_bus_init(&my_ram_size); + s390_sclp_init(); + s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline, + args->initrd_filename); + + /* register hypercalls */ + s390_virtio_register_hcalls(); + + /* allocate RAM */ + memory_region_init_ram(ram, "s390.ram", my_ram_size); + vmstate_register_ram_global(ram); + memory_region_add_subregion(sysmem, 0, ram); + + /* clear virtio region */ + virtio_region_len = my_ram_size - ram_size; + virtio_region_start = ram_size; + virtio_region = cpu_physical_memory_map(virtio_region_start, + &virtio_region_len, true); + memset(virtio_region, 0, virtio_region_len); + cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1, + virtio_region_len); + + /* allocate storage keys */ + storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE); + + /* init CPUs */ + s390_init_cpus(args->cpu_model, storage_keys); + + /* Create VirtIO network adapters */ + s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390"); +} + +static QEMUMachine s390_machine = { + .name = "s390-virtio", + .alias = "s390", + .desc = "VirtIO based S390 machine", + .init = s390_init, + .block_default_type = IF_VIRTIO, + .no_cdrom = 1, + .no_floppy = 1, + .no_serial = 1, + .no_parallel = 1, + .no_sdcard = 1, + .use_virtcon = 1, + .max_cpus = 255, + .is_default = 1, + DEFAULT_MACHINE_OPTIONS, +}; + +static void s390_machine_init(void) +{ + qemu_register_machine(&s390_machine); +} + +machine_init(s390_machine_init); diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h new file mode 100644 index 000000000..67bfd2064 --- /dev/null +++ b/hw/s390x/s390-virtio.h @@ -0,0 +1,27 @@ +/* + * Virtio interfaces for s390 + * + * Copyright 2012 IBM Corp. + * Author(s): Cornelia Huck + * + * 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. + */ + +#ifndef HW_S390_VIRTIO_H +#define HW_S390_VIRTIO_H 1 + +#define KVM_S390_VIRTIO_NOTIFY 0 +#define KVM_S390_VIRTIO_RESET 1 +#define KVM_S390_VIRTIO_SET_STATUS 2 + +typedef int (*s390_virtio_fn)(const uint64_t *args); +void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn); + +void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys); +void s390_init_ipl_dev(const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename); +void s390_create_virtio_net(BusState *bus, const char *name); +#endif