]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/s390x/s390-virtio.c
s390x/ipl: support diagnose 308 subcodes 5 and 6
[mirror_qemu.git] / hw / s390x / s390-virtio.c
index 30d1118cdc4f12820ee2b6351ad8dd64d327aa40..412e49ba33c3d2ec9772fa52d362487c6d10b644 100644 (file)
@@ -22,7 +22,7 @@
  */
 
 #include "hw/hw.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "net/net.h"
 
 #include "hw/s390x/s390-virtio-bus.h"
 #include "hw/s390x/sclp.h"
+#include "hw/s390x/s390_flic.h"
 #include "hw/s390x/s390-virtio.h"
 
 //#define DEBUG_S390
 
 #ifdef DEBUG_S390
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
 #else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
     do { } while (0)
 #endif
 
 #define MAX_BLK_DEVS                    10
 #define ZIPL_FILENAME                   "s390-zipl.rom"
+#define TYPE_S390_MACHINE               "s390-machine"
 
 static VirtIOS390Bus *s390_bus;
 static S390CPU **ipi_states;
@@ -91,7 +93,7 @@ static int s390_virtio_hcall_reset(const uint64_t *args)
         return -EINVAL;
     }
     virtio_reset(dev->vdev);
-    stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
+    stb_phys(&address_space_memory, dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
     s390_virtio_device_sync(dev);
     s390_virtio_reset_idx(dev);
 
@@ -123,44 +125,11 @@ static void s390_virtio_register_hcalls(void)
                                    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(S390CPU *cpu)
-{
-    CPUState *cs = CPU(cpu);
-    CPUS390XState *env = &cpu->env;
-
-    if (cs->halted) {
-        s390_running_cpus++;
-        cs->halted = 0;
-        env->exception_index = -1;
-    }
-}
-
-unsigned s390_del_running_cpu(S390CPU *cpu)
-{
-    CPUState *cs = CPU(cpu);
-    CPUS390XState *env = &cpu->env;
-
-    if (cs->halted == 0) {
-        assert(s390_running_cpus >= 1);
-        s390_running_cpus--;
-        cs->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,
-                       const char *firmware)
+                       const char *firmware,
+                       bool enforce_bios)
 {
     DeviceState *dev;
 
@@ -173,6 +142,9 @@ void s390_init_ipl_dev(const char *kernel_filename,
     }
     qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
     qdev_prop_set_string(dev, "firmware", firmware);
+    qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
+    object_property_add_child(qdev_get_machine(), "s390-ipl",
+                              OBJECT(dev), NULL);
     qdev_init_nofail(dev);
 }
 
@@ -195,7 +167,7 @@ void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys)
 
         ipi_states[i] = cpu;
         cs->halted = 1;
-        cpu->env.exception_index = EXCP_HLT;
+        cs->exception_index = EXCP_HLT;
         cpu->env.storage_keys = storage_keys;
     }
 }
@@ -225,23 +197,26 @@ void s390_create_virtio_net(BusState *bus, const char *name)
 }
 
 /* PC hardware initialisation */
-static void s390_init(QEMUMachineInitArgs *args)
+static void s390_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;
+    int increment_size = 20;
     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++;
+    /*
+     * 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.
+     */
+    while ((my_ram_size >> increment_size) > MAX_STORAGE_INCREMENTS) {
+        increment_size++;
     }
-    my_ram_size = my_ram_size >> (20 + shift) << (20 + shift);
+    my_ram_size = my_ram_size >> increment_size << increment_size;
 
     /* let's propagate the changed ram size into the global variable. */
     ram_size = my_ram_size;
@@ -249,14 +224,15 @@ static void s390_init(QEMUMachineInitArgs *args)
     /* 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, ZIPL_FILENAME);
+    s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline,
+                      machine->initrd_filename, ZIPL_FILENAME, false);
+    s390_flic_init();
 
     /* register hypercalls */
     s390_virtio_register_hcalls();
 
     /* allocate RAM */
-    memory_region_init_ram(ram, "s390.ram", my_ram_size);
+    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);
 
@@ -273,32 +249,55 @@ static void s390_init(QEMUMachineInitArgs *args)
     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);
 
     /* 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,
+void s390_nmi(NMIState *n, int cpu_index, Error **errp)
+{
+    CPUState *cs = qemu_get_cpu(cpu_index);
+
+    if (s390_cpu_restart(S390_CPU(cs))) {
+        error_set(errp, QERR_UNSUPPORTED);
+    }
+}
+
+static void s390_machine_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    NMIClass *nc = NMI_CLASS(oc);
+
+    mc->name = "s390-virtio";
+    mc->alias = "s390";
+    mc->desc = "VirtIO based S390 machine";
+    mc->init = s390_init;
+    mc->block_default_type = IF_VIRTIO;
+    mc->max_cpus = 255;
+    mc->no_serial = 1;
+    mc->no_parallel = 1;
+    mc->use_virtcon = 1;
+    mc->no_floppy = 1;
+    mc->no_cdrom = 1;
+    mc->no_sdcard = 1;
+    mc->is_default = 1;
+    nc->nmi_monitor_handler = s390_nmi;
+}
+
+static const TypeInfo s390_machine_info = {
+    .name          = TYPE_S390_MACHINE,
+    .parent        = TYPE_MACHINE,
+    .class_init    = s390_machine_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_NMI },
+        { }
+    },
 };
 
-static void s390_machine_init(void)
+static void s390_machine_register_types(void)
 {
-    qemu_register_machine(&s390_machine);
+    type_register_static(&s390_machine_info);
 }
 
-machine_init(s390_machine_init);
+type_init(s390_machine_register_types)