diff options
Diffstat (limited to 'qemu/hw/s390x/s390-virtio-ccw.c')
-rw-r--r-- | qemu/hw/s390x/s390-virtio-ccw.c | 286 |
1 files changed, 180 insertions, 106 deletions
diff --git a/qemu/hw/s390x/s390-virtio-ccw.c b/qemu/hw/s390x/s390-virtio-ccw.c index 4c51d1a5b..e3df9c78b 100644 --- a/qemu/hw/s390x/s390-virtio-ccw.c +++ b/qemu/hw/s390x/s390-virtio-ccw.c @@ -9,6 +9,10 @@ * directory. */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "cpu.h" #include "hw/boards.h" #include "exec/address-spaces.h" #include "s390-virtio.h" @@ -19,41 +23,27 @@ #include "virtio-ccw.h" #include "qemu/config-file.h" #include "s390-pci-bus.h" +#include "hw/s390x/storage-keys.h" +#include "hw/compat.h" +#include "hw/s390x/s390-virtio-ccw.h" + +static const char *const reset_dev_types[] = { + "virtual-css-bridge", + "s390-sclp-event-facility", + "s390-flic", + "diag288", +}; -#define TYPE_S390_CCW_MACHINE "s390-ccw-machine" - -#define S390_CCW_MACHINE(obj) \ - OBJECT_CHECK(S390CcwMachineState, (obj), TYPE_S390_CCW_MACHINE) - -typedef struct S390CcwMachineState { - /*< private >*/ - MachineState parent_obj; - - /*< public >*/ - bool aes_key_wrap; - bool dea_key_wrap; -} S390CcwMachineState; - -void io_subsystem_reset(void) +void subsystem_reset(void) { - DeviceState *css, *sclp, *flic, *diag288; + DeviceState *dev; + int i; - 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); - } - diag288 = DEVICE(object_resolve_path_type("", "diag288", NULL)); - if (diag288) { - qdev_reset_all(diag288); + for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) { + dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL)); + if (dev) { + qdev_reset_all(dev); + } } } @@ -99,58 +89,30 @@ static void virtio_ccw_register_hcalls(void) virtio_ccw_hcall_early_printk); } -static void ccw_init(MachineState *machine) +void s390_memory_init(ram_addr_t mem_size) { - ram_addr_t my_ram_size = machine->ram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); - sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev(); - uint8_t *storage_keys; + + /* allocate RAM for core */ + memory_region_allocate_system_memory(ram, NULL, "s390.ram", mem_size); + memory_region_add_subregion(sysmem, 0, ram); + + /* Initialize storage key device */ + s390_skeys_init(); +} + +static void ccw_init(MachineState *machine) +{ int ret; VirtualCssBus *css_bus; 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; - uint64_t kvm_limit; - - /* 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++; - } - /* 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; - machine->maxram_size = my_ram_size + standby_mem_size; - - ret = s390_set_memory_limit(machine->maxram_size, &kvm_limit); - if (ret == -E2BIG) { - hw_error("qemu: host supports a maximum of %" PRIu64 " GB", - kvm_limit >> 30); - } else if (ret) { - hw_error("qemu: setting the guest size failed"); - } + s390_sclp_init(); + s390_memory_init(machine->ram_size); /* get a BUS */ css_bus = virtual_css_bus_init(); - s390_sclp_init(); s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, machine->initrd_filename, "s390-ccw.img", true); s390_flic_init(); @@ -163,27 +125,8 @@ static void ccw_init(MachineState *machine) /* register hypercalls */ virtio_ccw_register_hcalls(); - /* 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(machine->cpu_model, storage_keys); + s390_init_cpus(machine); if (kvm_enabled()) { kvm_s390_enable_css_support(s390_cpu_addr2state(0)); @@ -203,12 +146,54 @@ static void ccw_init(MachineState *machine) gtod_save, gtod_load, kvm_state); } +static void s390_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + gchar *name; + S390CPU *cpu = S390_CPU(dev); + CPUState *cs = CPU(dev); + + name = g_strdup_printf("cpu[%i]", cpu->env.cpu_num); + object_property_set_link(OBJECT(hotplug_dev), OBJECT(cs), name, + errp); + g_free(name); +} + +static void s390_machine_device_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + s390_cpu_plug(hotplug_dev, dev, errp); + } +} + +static HotplugHandler *s390_get_hotplug_handler(MachineState *machine, + DeviceState *dev) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + return HOTPLUG_HANDLER(machine); + } + return NULL; +} + +static void s390_hot_add_cpu(const int64_t id, Error **errp) +{ + MachineState *machine = MACHINE(qdev_get_machine()); + Error *err = NULL; + + s390x_new_cpu(machine->cpu_model, id, &err); + error_propagate(errp, err); +} + static void ccw_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); NMIClass *nc = NMI_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); mc->init = ccw_init; + mc->reset = s390_machine_reset; + mc->hot_add_cpu = s390_hot_add_cpu; mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; mc->no_floppy = 1; @@ -217,6 +202,8 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) mc->no_sdcard = 1; mc->use_sclp = 1; mc->max_cpus = 255; + mc->get_hotplug_handler = s390_get_hotplug_handler; + hc->plug = s390_machine_device_plug; nc->nmi_monitor_handler = s390_nmi; } @@ -278,30 +265,117 @@ static const TypeInfo ccw_machine_info = { .class_init = ccw_machine_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_NMI }, + { TYPE_HOTPLUG_HANDLER}, { } }, }; -static void ccw_machine_2_4_class_init(ObjectClass *oc, void *data) +#define DEFINE_CCW_MACHINE(suffix, verstr, latest) \ + static void ccw_machine_##suffix##_class_init(ObjectClass *oc, \ + void *data) \ + { \ + MachineClass *mc = MACHINE_CLASS(oc); \ + ccw_machine_##suffix##_class_options(mc); \ + mc->desc = "VirtIO-ccw based S390 machine v" verstr; \ + if (latest) { \ + mc->alias = "s390-ccw-virtio"; \ + mc->is_default = 1; \ + } \ + } \ + static void ccw_machine_##suffix##_instance_init(Object *obj) \ + { \ + MachineState *machine = MACHINE(obj); \ + ccw_machine_##suffix##_instance_options(machine); \ + } \ + static const TypeInfo ccw_machine_##suffix##_info = { \ + .name = MACHINE_TYPE_NAME("s390-ccw-virtio-" verstr), \ + .parent = TYPE_S390_CCW_MACHINE, \ + .class_init = ccw_machine_##suffix##_class_init, \ + .instance_init = ccw_machine_##suffix##_instance_init, \ + }; \ + static void ccw_machine_register_##suffix(void) \ + { \ + type_register_static(&ccw_machine_##suffix##_info); \ + } \ + type_init(ccw_machine_register_##suffix) + +#define CCW_COMPAT_2_5 \ + HW_COMPAT_2_5 + +#define CCW_COMPAT_2_4 \ + CCW_COMPAT_2_5 \ + HW_COMPAT_2_4 \ + {\ + .driver = TYPE_S390_SKEYS,\ + .property = "migration-enabled",\ + .value = "off",\ + },{\ + .driver = "virtio-blk-ccw",\ + .property = "max_revision",\ + .value = "0",\ + },{\ + .driver = "virtio-balloon-ccw",\ + .property = "max_revision",\ + .value = "0",\ + },{\ + .driver = "virtio-serial-ccw",\ + .property = "max_revision",\ + .value = "0",\ + },{\ + .driver = "virtio-9p-ccw",\ + .property = "max_revision",\ + .value = "0",\ + },{\ + .driver = "virtio-rng-ccw",\ + .property = "max_revision",\ + .value = "0",\ + },{\ + .driver = "virtio-net-ccw",\ + .property = "max_revision",\ + .value = "0",\ + },{\ + .driver = "virtio-scsi-ccw",\ + .property = "max_revision",\ + .value = "0",\ + },{\ + .driver = "vhost-scsi-ccw",\ + .property = "max_revision",\ + .value = "0",\ + }, + +static void ccw_machine_2_6_instance_options(MachineState *machine) { - MachineClass *mc = MACHINE_CLASS(oc); +} - mc->name = "s390-ccw-virtio-2.4"; - mc->alias = "s390-ccw-virtio"; - mc->desc = "VirtIO-ccw based S390 machine v2.4"; - mc->is_default = 1; +static void ccw_machine_2_6_class_options(MachineClass *mc) +{ } +DEFINE_CCW_MACHINE(2_6, "2.6", true); -static const TypeInfo ccw_machine_2_4_info = { - .name = TYPE_S390_CCW_MACHINE "2.4", - .parent = TYPE_S390_CCW_MACHINE, - .class_init = ccw_machine_2_4_class_init, -}; +static void ccw_machine_2_5_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_2_5_class_options(MachineClass *mc) +{ + SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_5); +} +DEFINE_CCW_MACHINE(2_5, "2.5", false); + +static void ccw_machine_2_4_instance_options(MachineState *machine) +{ + ccw_machine_2_5_instance_options(machine); +} + +static void ccw_machine_2_4_class_options(MachineClass *mc) +{ + SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_4); +} +DEFINE_CCW_MACHINE(2_4, "2.4", false); static void ccw_machine_register_types(void) { type_register_static(&ccw_machine_info); - type_register_static(&ccw_machine_2_4_info); } type_init(ccw_machine_register_types) |