From cc3c7384ac61728e9949d5e64c10664fe4510179 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Sun, 22 Apr 2012 23:52:19 +0000 Subject: [PATCH 1/7] S390: fix kernel_commandline handling The current handling of kernel parameters is broken. The pointer is always valid, even if no -kernel or -append is specified. We must check if the kernel rom address is valid instead, otherwise qemu might segfault. Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- hw/s390-virtio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 1ebe70d0e3..c79784c0c8 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -274,7 +274,7 @@ static void s390_init(ram_addr_t my_ram_size, memcpy(rom_ptr(INITRD_PARM_SIZE), &initrd_size, 8); } - if (kernel_cmdline) { + if (rom_ptr(KERN_PARM_AREA)) { /* we have to overwrite values in the kernel image, which are "rom" */ memcpy(rom_ptr(KERN_PARM_AREA), kernel_cmdline, strlen(kernel_cmdline) + 1); From 118a89774346e6a406cd44f403cb043a417066c9 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Sun, 22 Apr 2012 23:52:20 +0000 Subject: [PATCH 2/7] S390: fix error handling on kernel and initrd failures If the user specifies a non-existing or non-accessable kernel or initrd qemu does not fail, instead it ipls into the system, which then falls into a program check loop due to the zeroed memory with no kernel. Lets add some sanity checks. Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- hw/s390-virtio.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index c79784c0c8..d17602f939 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -230,6 +230,11 @@ static void s390_init(ram_addr_t my_ram_size, if (kernel_size == -1UL) { kernel_size = load_image_targphys(kernel_filename, 0, ram_size); } + if (kernel_size == -1UL) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + kernel_filename); + exit(1); + } /* * we can not rely on the ELF entry point, since up to 3.2 this * value was 0x800 (the SALIPL loader) and it wont work. For @@ -269,6 +274,12 @@ static void s390_init(ram_addr_t my_ram_size, } initrd_size = load_image_targphys(initrd_filename, initrd_offset, ram_size - initrd_offset); + if (initrd_size == -1UL) { + fprintf(stderr, "qemu: could not load initrd '%s'\n", + initrd_filename); + exit(1); + } + /* we have to overwrite values in the kernel image, which are "rom" */ memcpy(rom_ptr(INITRD_PARM_START), &initrd_offset, 8); memcpy(rom_ptr(INITRD_PARM_SIZE), &initrd_size, 8); From eb3caa44b03f5d72a49a18c72443825b58168734 Mon Sep 17 00:00:00 2001 From: Jens Freimann Date: Sun, 22 Apr 2012 23:52:21 +0000 Subject: [PATCH 3/7] S390: reboot: reset device pages on reboot This patch fixes reboot on s390 by resetting the device page on reboot. Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- hw/s390-virtio-bus.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index be1f5f1061..74419b3725 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -57,6 +57,12 @@ static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev); /* length of VirtIO device pages */ const target_phys_addr_t virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE; +static void s390_virtio_bus_reset(void *opaque) +{ + VirtIOS390Bus *bus = opaque; + bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; +} + VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) { VirtIOS390Bus *bus; @@ -82,6 +88,7 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */ *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE; + qemu_register_reset(s390_virtio_bus_reset, bus); return bus; } From add142e0aa41daad86f650b68bac6b6a8e808f8d Mon Sep 17 00:00:00 2001 From: Jens Freimann Date: Sun, 22 Apr 2012 23:52:23 +0000 Subject: [PATCH 4/7] S390: support reboot for kvm on s390 This patch adds reboot support for s390x-softmmu by calling the generic reboot support in kvm. Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- target-s390x/kvm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 2b6723149d..956730d638 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -452,8 +452,7 @@ int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run) ret = handle_intercept(env); break; case KVM_EXIT_S390_RESET: - fprintf(stderr, "RESET not implemented\n"); - exit(1); + qemu_system_reset_request(); break; default: fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason); From ad0bbc560026fb21c5b3d07631457e3be84d0f42 Mon Sep 17 00:00:00 2001 From: Einar Lueck Date: Sun, 22 Apr 2012 23:52:24 +0000 Subject: [PATCH 5/7] S390: remove default cdrom, sd-card and floppy support This patch simply disables CDROM, SD card and floppy support for the s390 virtio machine. Without this patch, a default CDROM drive would get added which has currently no backing on s390. Signed-off-by: Einar Lueck Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- hw/s390-virtio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index d17602f939..d7dc8571d8 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -331,8 +331,11 @@ static QEMUMachine s390_machine = { .alias = "s390", .desc = "VirtIO based S390 machine", .init = s390_init, + .no_cdrom = 1, + .no_floppy = 1, .no_serial = 1, .no_parallel = 1, + .no_sdcard = 1, .use_virtcon = 1, .max_cpus = 255, .is_default = 1, From eca3ed0343ba413937f34ad4f8c4822dc82924e5 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Sun, 22 Apr 2012 23:52:25 +0000 Subject: [PATCH 6/7] S390: dont call system_shutdown on disabled wait A disabled wait usually indicates a guest problem. Dont shutdown the guest to allow guest dumping. Have some special cases, e.g. a quiesce disabled wait. In that case we want to shutdown. Long term solution might be a crashed/panic indication. Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- target-s390x/kvm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 956730d638..90aad61eb0 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -407,6 +407,12 @@ static int handle_instruction(CPUS390XState *env, struct kvm_run *run) return 0; } +static bool is_special_wait_psw(CPUS390XState *env) +{ + /* signal quiesce */ + return env->kvm_run->psw_addr == 0xfffUL; +} + static int handle_intercept(CPUS390XState *env) { struct kvm_run *run = env->kvm_run; @@ -420,6 +426,12 @@ static int handle_intercept(CPUS390XState *env) r = handle_instruction(env, run); break; case ICPT_WAITPSW: + if (s390_del_running_cpu(env) == 0 && + is_special_wait_psw(env)) { + qemu_system_shutdown_request(); + } + r = EXCP_HALTED; + break; case ICPT_CPU_STOP: if (s390_del_running_cpu(env) == 0) { qemu_system_shutdown_request(); From 4170aea1a77d7adf9e35ab4d3c17086c38ca6c09 Mon Sep 17 00:00:00 2001 From: Jens Freimann Date: Thu, 26 Apr 2012 09:03:36 +0000 Subject: [PATCH 7/7] s390: reset avail and used index on reboot reset the guest vring avail/used idx fields, otherwise it's possible that old values remain in memory which would cause a reboot to fail with a "Guest moved used index" message Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- hw/s390-virtio-bus.c | 19 ++++++++++++++++++- hw/s390-virtio-bus.h | 4 ++++ hw/s390-virtio.c | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 74419b3725..63ccd5c35a 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -63,6 +63,23 @@ static void s390_virtio_bus_reset(void *opaque) bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; } +void s390_virtio_reset_idx(VirtIOS390Device *dev) +{ + int i; + target_phys_addr_t idx_addr; + uint8_t num_vq; + + num_vq = s390_virtio_device_num_vq(dev); + for (i = 0; i < num_vq; i++) { + idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) + + VIRTIO_VRING_AVAIL_IDX_OFFS; + stw_phys(idx_addr, 0); + idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + + VIRTIO_VRING_USED_IDX_OFFS; + stw_phys(idx_addr, 0); + } +} + VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) { VirtIOS390Bus *bus; @@ -121,7 +138,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) virtio_bind_device(vdev, &virtio_s390_bindings, dev); dev->host_features = vdev->get_features(vdev, dev->host_features); s390_virtio_device_sync(dev); - + s390_virtio_reset_idx(dev); if (dev->qdev.hotplugged) { CPUS390XState *env = s390_cpu_addr2state(0); s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs); diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h index 0e60bc0fa2..49e6c462df 100644 --- a/hw/s390-virtio-bus.h +++ b/hw/s390-virtio-bus.h @@ -34,6 +34,8 @@ #define VIRTIO_VQCONFIG_LEN 24 #define VIRTIO_RING_LEN (TARGET_PAGE_SIZE * 3) +#define VIRTIO_VRING_AVAIL_IDX_OFFS 2 +#define VIRTIO_VRING_USED_IDX_OFFS 2 #define S390_DEVICE_PAGES 512 #define VIRTIO_PARAM_MASK 0xff @@ -90,3 +92,5 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, ram_addr_t mem, int *vq_num); VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem); void s390_virtio_device_sync(VirtIOS390Device *dev); +void s390_virtio_reset_idx(VirtIOS390Device *dev); + diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index d7dc8571d8..c0e19fd66d 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -99,6 +99,7 @@ int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall) virtio_reset(dev->vdev); stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0); s390_virtio_device_sync(dev); + s390_virtio_reset_idx(dev); break; } case KVM_S390_VIRTIO_SET_STATUS: