1 /* 2 * virtio ccw machine 3 * 4 * Copyright 2012 IBM Corp. 5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> 6 * 7 * This work is licensed under the terms of the GNU GPL, version 2 or (at 8 * your option) any later version. See the COPYING file in the top-level 9 * directory. 10 */ 11 12 #include "qemu/osdep.h" 13 #include "qapi/error.h" 14 #include "qemu-common.h" 15 #include "cpu.h" 16 #include "hw/boards.h" 17 #include "exec/address-spaces.h" 18 #include "s390-virtio.h" 19 #include "hw/s390x/sclp.h" 20 #include "hw/s390x/s390_flic.h" 21 #include "ioinst.h" 22 #include "css.h" 23 #include "virtio-ccw.h" 24 #include "qemu/config-file.h" 25 #include "s390-pci-bus.h" 26 #include "hw/s390x/storage-keys.h" 27 #include "hw/compat.h" 28 #include "hw/s390x/s390-virtio-ccw.h" 29 30 static const char *const reset_dev_types[] = { 31 "virtual-css-bridge", 32 "s390-sclp-event-facility", 33 "s390-flic", 34 "diag288", 35 }; 36 37 void subsystem_reset(void) 38 { 39 DeviceState *dev; 40 int i; 41 42 for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) { 43 dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL)); 44 if (dev) { 45 qdev_reset_all(dev); 46 } 47 } 48 } 49 50 static int virtio_ccw_hcall_notify(const uint64_t *args) 51 { 52 uint64_t subch_id = args[0]; 53 uint64_t queue = args[1]; 54 SubchDev *sch; 55 int cssid, ssid, schid, m; 56 57 if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) { 58 return -EINVAL; 59 } 60 sch = css_find_subch(m, cssid, ssid, schid); 61 if (!sch || !css_subch_visible(sch)) { 62 return -EINVAL; 63 } 64 if (queue >= VIRTIO_CCW_QUEUE_MAX) { 65 return -EINVAL; 66 } 67 virtio_queue_notify(virtio_ccw_get_vdev(sch), queue); 68 return 0; 69 70 } 71 72 static int virtio_ccw_hcall_early_printk(const uint64_t *args) 73 { 74 uint64_t mem = args[0]; 75 76 if (mem < ram_size) { 77 /* Early printk */ 78 return 0; 79 } 80 return -EINVAL; 81 } 82 83 static void virtio_ccw_register_hcalls(void) 84 { 85 s390_register_virtio_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, 86 virtio_ccw_hcall_notify); 87 /* Tolerate early printk. */ 88 s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY, 89 virtio_ccw_hcall_early_printk); 90 } 91 92 void s390_memory_init(ram_addr_t mem_size) 93 { 94 MemoryRegion *sysmem = get_system_memory(); 95 MemoryRegion *ram = g_new(MemoryRegion, 1); 96 97 /* allocate RAM for core */ 98 memory_region_allocate_system_memory(ram, NULL, "s390.ram", mem_size); 99 memory_region_add_subregion(sysmem, 0, ram); 100 101 /* Initialize storage key device */ 102 s390_skeys_init(); 103 } 104 105 static void ccw_init(MachineState *machine) 106 { 107 int ret; 108 VirtualCssBus *css_bus; 109 DeviceState *dev; 110 111 s390_sclp_init(); 112 s390_memory_init(machine->ram_size); 113 114 /* get a BUS */ 115 css_bus = virtual_css_bus_init(); 116 s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, 117 machine->initrd_filename, "s390-ccw.img", true); 118 s390_flic_init(); 119 120 dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE); 121 object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE, 122 OBJECT(dev), NULL); 123 qdev_init_nofail(dev); 124 125 /* register hypercalls */ 126 virtio_ccw_register_hcalls(); 127 128 /* init CPUs */ 129 s390_init_cpus(machine); 130 131 if (kvm_enabled()) { 132 kvm_s390_enable_css_support(s390_cpu_addr2state(0)); 133 } 134 /* 135 * Create virtual css and set it as default so that non mcss-e 136 * enabled guests only see virtio devices. 137 */ 138 ret = css_create_css_image(VIRTUAL_CSSID, true); 139 assert(ret == 0); 140 141 /* Create VirtIO network adapters */ 142 s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); 143 144 /* Register savevm handler for guest TOD clock */ 145 register_savevm(NULL, "todclock", 0, 1, 146 gtod_save, gtod_load, kvm_state); 147 } 148 149 static void s390_cpu_plug(HotplugHandler *hotplug_dev, 150 DeviceState *dev, Error **errp) 151 { 152 gchar *name; 153 S390CPU *cpu = S390_CPU(dev); 154 CPUState *cs = CPU(dev); 155 156 name = g_strdup_printf("cpu[%i]", cpu->env.cpu_num); 157 object_property_set_link(OBJECT(hotplug_dev), OBJECT(cs), name, 158 errp); 159 g_free(name); 160 } 161 162 static void s390_machine_device_plug(HotplugHandler *hotplug_dev, 163 DeviceState *dev, Error **errp) 164 { 165 if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { 166 s390_cpu_plug(hotplug_dev, dev, errp); 167 } 168 } 169 170 static HotplugHandler *s390_get_hotplug_handler(MachineState *machine, 171 DeviceState *dev) 172 { 173 if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { 174 return HOTPLUG_HANDLER(machine); 175 } 176 return NULL; 177 } 178 179 static void s390_hot_add_cpu(const int64_t id, Error **errp) 180 { 181 MachineState *machine = MACHINE(qdev_get_machine()); 182 Error *err = NULL; 183 184 s390x_new_cpu(machine->cpu_model, id, &err); 185 error_propagate(errp, err); 186 } 187 188 static void ccw_machine_class_init(ObjectClass *oc, void *data) 189 { 190 MachineClass *mc = MACHINE_CLASS(oc); 191 NMIClass *nc = NMI_CLASS(oc); 192 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 193 194 mc->init = ccw_init; 195 mc->reset = s390_machine_reset; 196 mc->hot_add_cpu = s390_hot_add_cpu; 197 mc->block_default_type = IF_VIRTIO; 198 mc->no_cdrom = 1; 199 mc->no_floppy = 1; 200 mc->no_serial = 1; 201 mc->no_parallel = 1; 202 mc->no_sdcard = 1; 203 mc->use_sclp = 1; 204 mc->max_cpus = 255; 205 mc->get_hotplug_handler = s390_get_hotplug_handler; 206 hc->plug = s390_machine_device_plug; 207 nc->nmi_monitor_handler = s390_nmi; 208 } 209 210 static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp) 211 { 212 S390CcwMachineState *ms = S390_CCW_MACHINE(obj); 213 214 return ms->aes_key_wrap; 215 } 216 217 static inline void machine_set_aes_key_wrap(Object *obj, bool value, 218 Error **errp) 219 { 220 S390CcwMachineState *ms = S390_CCW_MACHINE(obj); 221 222 ms->aes_key_wrap = value; 223 } 224 225 static inline bool machine_get_dea_key_wrap(Object *obj, Error **errp) 226 { 227 S390CcwMachineState *ms = S390_CCW_MACHINE(obj); 228 229 return ms->dea_key_wrap; 230 } 231 232 static inline void machine_set_dea_key_wrap(Object *obj, bool value, 233 Error **errp) 234 { 235 S390CcwMachineState *ms = S390_CCW_MACHINE(obj); 236 237 ms->dea_key_wrap = value; 238 } 239 240 static inline void s390_machine_initfn(Object *obj) 241 { 242 object_property_add_bool(obj, "aes-key-wrap", 243 machine_get_aes_key_wrap, 244 machine_set_aes_key_wrap, NULL); 245 object_property_set_description(obj, "aes-key-wrap", 246 "enable/disable AES key wrapping using the CPACF wrapping key", 247 NULL); 248 object_property_set_bool(obj, true, "aes-key-wrap", NULL); 249 250 object_property_add_bool(obj, "dea-key-wrap", 251 machine_get_dea_key_wrap, 252 machine_set_dea_key_wrap, NULL); 253 object_property_set_description(obj, "dea-key-wrap", 254 "enable/disable DEA key wrapping using the CPACF wrapping key", 255 NULL); 256 object_property_set_bool(obj, true, "dea-key-wrap", NULL); 257 } 258 259 static const TypeInfo ccw_machine_info = { 260 .name = TYPE_S390_CCW_MACHINE, 261 .parent = TYPE_MACHINE, 262 .abstract = true, 263 .instance_size = sizeof(S390CcwMachineState), 264 .instance_init = s390_machine_initfn, 265 .class_init = ccw_machine_class_init, 266 .interfaces = (InterfaceInfo[]) { 267 { TYPE_NMI }, 268 { TYPE_HOTPLUG_HANDLER}, 269 { } 270 }, 271 }; 272 273 #define DEFINE_CCW_MACHINE(suffix, verstr, latest) \ 274 static void ccw_machine_##suffix##_class_init(ObjectClass *oc, \ 275 void *data) \ 276 { \ 277 MachineClass *mc = MACHINE_CLASS(oc); \ 278 ccw_machine_##suffix##_class_options(mc); \ 279 mc->desc = "VirtIO-ccw based S390 machine v" verstr; \ 280 if (latest) { \ 281 mc->alias = "s390-ccw-virtio"; \ 282 mc->is_default = 1; \ 283 } \ 284 } \ 285 static void ccw_machine_##suffix##_instance_init(Object *obj) \ 286 { \ 287 MachineState *machine = MACHINE(obj); \ 288 ccw_machine_##suffix##_instance_options(machine); \ 289 } \ 290 static const TypeInfo ccw_machine_##suffix##_info = { \ 291 .name = MACHINE_TYPE_NAME("s390-ccw-virtio-" verstr), \ 292 .parent = TYPE_S390_CCW_MACHINE, \ 293 .class_init = ccw_machine_##suffix##_class_init, \ 294 .instance_init = ccw_machine_##suffix##_instance_init, \ 295 }; \ 296 static void ccw_machine_register_##suffix(void) \ 297 { \ 298 type_register_static(&ccw_machine_##suffix##_info); \ 299 } \ 300 type_init(ccw_machine_register_##suffix) 301 302 #define CCW_COMPAT_2_5 \ 303 HW_COMPAT_2_5 304 305 #define CCW_COMPAT_2_4 \ 306 CCW_COMPAT_2_5 \ 307 HW_COMPAT_2_4 \ 308 {\ 309 .driver = TYPE_S390_SKEYS,\ 310 .property = "migration-enabled",\ 311 .value = "off",\ 312 },{\ 313 .driver = "virtio-blk-ccw",\ 314 .property = "max_revision",\ 315 .value = "0",\ 316 },{\ 317 .driver = "virtio-balloon-ccw",\ 318 .property = "max_revision",\ 319 .value = "0",\ 320 },{\ 321 .driver = "virtio-serial-ccw",\ 322 .property = "max_revision",\ 323 .value = "0",\ 324 },{\ 325 .driver = "virtio-9p-ccw",\ 326 .property = "max_revision",\ 327 .value = "0",\ 328 },{\ 329 .driver = "virtio-rng-ccw",\ 330 .property = "max_revision",\ 331 .value = "0",\ 332 },{\ 333 .driver = "virtio-net-ccw",\ 334 .property = "max_revision",\ 335 .value = "0",\ 336 },{\ 337 .driver = "virtio-scsi-ccw",\ 338 .property = "max_revision",\ 339 .value = "0",\ 340 },{\ 341 .driver = "vhost-scsi-ccw",\ 342 .property = "max_revision",\ 343 .value = "0",\ 344 }, 345 346 static void ccw_machine_2_6_instance_options(MachineState *machine) 347 { 348 } 349 350 static void ccw_machine_2_6_class_options(MachineClass *mc) 351 { 352 } 353 DEFINE_CCW_MACHINE(2_6, "2.6", true); 354 355 static void ccw_machine_2_5_instance_options(MachineState *machine) 356 { 357 } 358 359 static void ccw_machine_2_5_class_options(MachineClass *mc) 360 { 361 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_5); 362 } 363 DEFINE_CCW_MACHINE(2_5, "2.5", false); 364 365 static void ccw_machine_2_4_instance_options(MachineState *machine) 366 { 367 ccw_machine_2_5_instance_options(machine); 368 } 369 370 static void ccw_machine_2_4_class_options(MachineClass *mc) 371 { 372 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_4); 373 } 374 DEFINE_CCW_MACHINE(2_4, "2.4", false); 375 376 static void ccw_machine_register_types(void) 377 { 378 type_register_static(&ccw_machine_info); 379 } 380 381 type_init(ccw_machine_register_types) 382