X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=hw%2Fs390x%2Fs390-virtio-ccw.c;h=8f0ae59b5f85fefa7fa1875809a37c457f09637f;hb=df75a4e2c607836eee044d7e6b0d94724d6ebf21;hp=d4364143ea72c5f5ae2110060971353250f36863;hpb=fa3889162ff724d09eb6b6bd06ba54769100a77f;p=mirror_qemu.git diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index d4364143ea..8f0ae59b5f 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -13,9 +13,33 @@ #include "exec/address-spaces.h" #include "s390-virtio.h" #include "hw/s390x/sclp.h" +#include "hw/s390x/s390_flic.h" #include "ioinst.h" #include "css.h" #include "virtio-ccw.h" +#include "qemu/config-file.h" +#include "s390-pci-bus.h" + +#define TYPE_S390_CCW_MACHINE "s390-ccw-machine" + +void io_subsystem_reset(void) +{ + DeviceState *css, *sclp, *flic; + + css = DEVICE(object_resolve_path_type("", "virtual-css-bridge", NULL)); + if (css) { + qdev_reset_all(css); + } + sclp = DEVICE(object_resolve_path_type("", + "s390-sclp-event-facility", NULL)); + if (sclp) { + qdev_reset_all(sclp); + } + flic = DEVICE(object_resolve_path_type("", "s390-flic", NULL)); + if (flic) { + qdev_reset_all(flic); + } +} static int virtio_ccw_hcall_notify(const uint64_t *args) { @@ -31,6 +55,9 @@ static int virtio_ccw_hcall_notify(const uint64_t *args) if (!sch || !css_subch_visible(sch)) { return -EINVAL; } + if (queue >= VIRTIO_PCI_QUEUE_MAX) { + return -EINVAL; + } virtio_queue_notify(virtio_ccw_get_vdev(sch), queue); return 0; @@ -56,45 +83,81 @@ static void virtio_ccw_register_hcalls(void) virtio_ccw_hcall_early_printk); } -static void ccw_init(QEMUMachineInitArgs *args) +static void ccw_init(MachineState *machine) { - ram_addr_t my_ram_size = args->ram_size; + ram_addr_t my_ram_size = machine->ram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); - int shift = 0; + sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev(); uint8_t *storage_keys; int ret; VirtualCssBus *css_bus; - - /* 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++; + DeviceState *dev; + QemuOpts *opts = qemu_opts_find(qemu_find_opts("memory"), NULL); + ram_addr_t pad_size = 0; + ram_addr_t maxmem = qemu_opt_get_size(opts, "maxmem", my_ram_size); + ram_addr_t standby_mem_size = maxmem - my_ram_size; + + /* The storage increment size is a multiple of 1M and is a power of 2. + * The number of storage increments must be MAX_STORAGE_INCREMENTS or fewer. + * The variable 'mhd->increment_size' is an exponent of 2 that can be + * used to calculate the size (in bytes) of an increment. */ + mhd->increment_size = 20; + while ((my_ram_size >> mhd->increment_size) > MAX_STORAGE_INCREMENTS) { + mhd->increment_size++; + } + while ((standby_mem_size >> mhd->increment_size) > MAX_STORAGE_INCREMENTS) { + mhd->increment_size++; } - my_ram_size = my_ram_size >> (20 + shift) << (20 + shift); - /* lets propagate the changed ram size into the global variable. */ + /* The core and standby memory areas need to be aligned with + * the increment size. In effect, this can cause the + * user-specified memory size to be rounded down to align + * with the nearest increment boundary. */ + standby_mem_size = standby_mem_size >> mhd->increment_size + << mhd->increment_size; + my_ram_size = my_ram_size >> mhd->increment_size + << mhd->increment_size; + + /* let's propagate the changed ram size into the global variable. */ ram_size = my_ram_size; /* get a BUS */ css_bus = virtual_css_bus_init(); s390_sclp_init(); - s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline, - args->initrd_filename); + s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, + machine->initrd_filename, "s390-ccw.img", true); + s390_flic_init(); + + dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE); + object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE, + OBJECT(dev), NULL); + qdev_init_nofail(dev); /* register hypercalls */ virtio_ccw_register_hcalls(); - /* allocate RAM */ - memory_region_init_ram(ram, "s390.ram", my_ram_size); + /* allocate RAM for core */ + memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size, &error_abort); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); + /* If the size of ram is not on a MEM_SECTION_SIZE boundary, + calculate the pad size necessary to force this boundary. */ + if (standby_mem_size) { + if (my_ram_size % MEM_SECTION_SIZE) { + pad_size = MEM_SECTION_SIZE - my_ram_size % MEM_SECTION_SIZE; + } + my_ram_size += standby_mem_size + pad_size; + mhd->pad_size = pad_size; + mhd->standby_mem_size = standby_mem_size; + } + /* allocate storage keys */ storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE); /* init CPUs */ - s390_init_cpus(args->cpu_model, storage_keys); + s390_init_cpus(machine->cpu_model, storage_keys); if (kvm_enabled()) { kvm_s390_enable_css_support(s390_cpu_addr2state(0)); @@ -110,25 +173,39 @@ static void ccw_init(QEMUMachineInitArgs *args) s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); } -static QEMUMachine ccw_machine = { - .name = "s390-ccw-virtio", - .alias = "s390-ccw", - .desc = "VirtIO-ccw based S390 machine", - .init = ccw_init, - .block_default_type = IF_VIRTIO, - .no_cdrom = 1, - .no_floppy = 1, - .no_serial = 1, - .no_parallel = 1, - .no_sdcard = 1, - .use_sclp = 1, - .max_cpus = 255, - DEFAULT_MACHINE_OPTIONS, +static void ccw_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); + + mc->name = "s390-ccw-virtio"; + mc->alias = "s390-ccw"; + mc->desc = "VirtIO-ccw based S390 machine"; + mc->init = ccw_init; + mc->block_default_type = IF_VIRTIO; + mc->no_cdrom = 1; + mc->no_floppy = 1; + mc->no_serial = 1; + mc->no_parallel = 1; + mc->no_sdcard = 1; + mc->use_sclp = 1; + mc->max_cpus = 255; + nc->nmi_monitor_handler = s390_nmi; +} + +static const TypeInfo ccw_machine_info = { + .name = TYPE_S390_CCW_MACHINE, + .parent = TYPE_MACHINE, + .class_init = ccw_machine_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_NMI }, + { } + }, }; -static void ccw_machine_init(void) +static void ccw_machine_register_types(void) { - qemu_register_machine(&ccw_machine); + type_register_static(&ccw_machine_info); } -machine_init(ccw_machine_init) +type_init(ccw_machine_register_types)