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