From db3b2566e0fb45e2901b6f9b842d91db6963915d Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 21 Jul 2015 13:47:32 +0200 Subject: [PATCH] s390x: machine reset function with new ipl cpu handling Current implementation depends on the order of resets getting triggered. If a cpu reset is triggered after the ipl device reset, the CPU is stopped and the VM will not run. In fact, that hinders us from converting the ipl device into a TYPE_DEVICE. Let's change that by manually configuring the ipl cpu during a system reset, so we have full control and can demangle that code. Also remove the superflous cpu parameter from s390_update_iplstate on the way. Acked-by: Christian Borntraeger Reviewed-by: Cornelia Huck Signed-off-by: David Hildenbrand Signed-off-by: Cornelia Huck --- hw/s390x/ipl.c | 27 ++++++++++++++------------- hw/s390x/ipl.h | 3 +++ hw/s390x/s390-virtio-ccw.c | 1 + hw/s390x/s390-virtio.c | 13 +++++++++++++ hw/s390x/s390-virtio.h | 1 + 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index b8c6378ba1..5f7f34900a 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -223,7 +223,7 @@ static Property s390_ipl_properties[] = { * - -1 if no valid boot device was found * - ccw id of the boot device otherwise */ -static uint64_t s390_update_iplstate(CPUS390XState *env, S390IPLState *ipl) +static uint64_t s390_update_iplstate(S390IPLState *ipl) { DeviceState *dev_st; @@ -282,26 +282,27 @@ void s390_reipl_request(void) qemu_system_reset_request(); } +void s390_ipl_prepare_cpu(S390CPU *cpu) +{ + S390IPLState *ipl = get_ipl_device(); + + cpu->env.psw.addr = ipl->start_addr; + cpu->env.psw.mask = IPL_PSW_MASK; + + if (!ipl->kernel || ipl->iplb_valid) { + cpu->env.psw.addr = ipl->bios_start_addr; + cpu->env.regs[7] = s390_update_iplstate(ipl); + } +} + static void s390_ipl_reset(DeviceState *dev) { S390IPLState *ipl = S390_IPL(dev); - S390CPU *cpu = S390_CPU(qemu_get_cpu(0)); - CPUS390XState *env = &cpu->env; - - env->psw.addr = ipl->start_addr; - env->psw.mask = IPL_PSW_MASK; if (!ipl->reipl_requested) { ipl->iplb_valid = false; } ipl->reipl_requested = false; - - if (!ipl->kernel || ipl->iplb_valid) { - env->psw.addr = ipl->bios_start_addr; - env->regs[7] = s390_update_iplstate(env, ipl); - } - - s390_cpu_set_state(CPU_STATE_OPERATING, cpu); } static void s390_ipl_class_init(ObjectClass *klass, void *data) diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 6424e08db8..7f2b4033d4 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -12,6 +12,8 @@ #ifndef HW_S390_IPL_H #define HW_S390_IPL_H +#include "cpu.h" + typedef struct IplParameterBlock { uint8_t reserved1[110]; uint16_t devno; @@ -19,6 +21,7 @@ typedef struct IplParameterBlock { } IplParameterBlock; void s390_ipl_update_diag308(IplParameterBlock *iplb); +void s390_ipl_prepare_cpu(S390CPU *cpu); IplParameterBlock *s390_ipl_get_iplb(void); void s390_reipl_request(void); diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 5e56fbf9df..faba773592 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -161,6 +161,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) NMIClass *nc = NMI_CLASS(oc); mc->init = ccw_init; + mc->reset = s390_machine_reset; mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; mc->no_floppy = 1; diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index bc013eb3d4..7b8f15bb31 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -40,6 +40,7 @@ #include "hw/s390x/s390_flic.h" #include "hw/s390x/s390-virtio.h" #include "hw/s390x/storage-keys.h" +#include "hw/s390x/ipl.h" #include "cpu.h" //#define DEBUG_S390 @@ -314,6 +315,17 @@ void s390_nmi(NMIState *n, int cpu_index, Error **errp) } } +void s390_machine_reset(void) +{ + S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0)); + + qemu_devices_reset(); + + /* all cpus are stopped - configure and start the ipl cpu only */ + s390_ipl_prepare_cpu(ipl_cpu); + s390_cpu_set_state(CPU_STATE_OPERATING, ipl_cpu); +} + static void s390_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -322,6 +334,7 @@ static void s390_machine_class_init(ObjectClass *oc, void *data) mc->alias = "s390"; mc->desc = "VirtIO based S390 machine"; mc->init = s390_init; + mc->reset = s390_machine_reset; mc->block_default_type = IF_VIRTIO; mc->max_cpus = 255; mc->no_serial = 1; diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h index f389aa1a67..eebce8e5e6 100644 --- a/hw/s390x/s390-virtio.h +++ b/hw/s390x/s390-virtio.h @@ -27,5 +27,6 @@ void s390_init_ipl_dev(const char *kernel_filename, bool enforce_bios); void s390_create_virtio_net(BusState *bus, const char *name); void s390_nmi(NMIState *n, int cpu_index, Error **errp); +void s390_machine_reset(void); void s390_memory_init(ram_addr_t mem_size); #endif