From cd20d61634092a9fa19c8c6f0a749526e9958374 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 17 Mar 2015 13:42:03 +0100 Subject: [PATCH 01/10] virtio-ccw: sort into categories Sort the various virtio-ccw devices into the same categories as their virtio-pci counterparts. Reviewed-by: David Hildenbrand Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/s390x/virtio-ccw.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index ed75c638bc..c1d8288b71 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1453,6 +1453,7 @@ static void virtio_ccw_net_class_init(ObjectClass *klass, void *data) k->exit = virtio_ccw_exit; dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_net_properties; + set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); } static const TypeInfo virtio_ccw_net = { @@ -1479,6 +1480,7 @@ static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data) k->exit = virtio_ccw_exit; dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_blk_properties; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo virtio_ccw_blk = { @@ -1505,6 +1507,7 @@ static void virtio_ccw_serial_class_init(ObjectClass *klass, void *data) k->exit = virtio_ccw_exit; dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_serial_properties; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo virtio_ccw_serial = { @@ -1531,6 +1534,7 @@ static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data) k->exit = virtio_ccw_exit; dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_balloon_properties; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo virtio_ccw_balloon = { @@ -1558,6 +1562,7 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data) k->exit = virtio_ccw_exit; dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_scsi_properties; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo virtio_ccw_scsi = { @@ -1583,6 +1588,7 @@ static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data) k->exit = virtio_ccw_exit; dc->reset = virtio_ccw_reset; dc->props = vhost_ccw_scsi_properties; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo vhost_ccw_scsi = { @@ -1620,6 +1626,7 @@ static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data) k->exit = virtio_ccw_exit; dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_rng_properties; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo virtio_ccw_rng = { @@ -1706,9 +1713,11 @@ static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) { SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = virtual_css_bridge_init; hc->unplug = virtio_ccw_busdev_unplug; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); } static const TypeInfo virtual_css_bridge_info = { From 4d1866de9422c4b359f61819ee01efc9b988187b Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 17 Mar 2015 13:43:26 +0100 Subject: [PATCH 02/10] s390-virtio: sort into categories Sort the various s390-virtio devices into the same categories as their virtio-pci counterparts. Reviewed-by: David Hildenbrand Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-bus.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 0f93a644a2..c27f8a531b 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -542,6 +542,7 @@ static void s390_virtio_net_class_init(ObjectClass *klass, void *data) k->realize = s390_virtio_net_realize; dc->props = s390_virtio_net_properties; + set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); } static const TypeInfo s390_virtio_net = { @@ -555,8 +556,10 @@ static const TypeInfo s390_virtio_net = { static void s390_virtio_blk_class_init(ObjectClass *klass, void *data) { VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->realize = s390_virtio_blk_realize; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo s390_virtio_blk = { @@ -578,6 +581,7 @@ static void s390_virtio_serial_class_init(ObjectClass *klass, void *data) k->realize = s390_virtio_serial_realize; dc->props = s390_virtio_serial_properties; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo s390_virtio_serial = { @@ -600,6 +604,7 @@ static void s390_virtio_rng_class_init(ObjectClass *klass, void *data) k->realize = s390_virtio_rng_realize; dc->props = s390_virtio_rng_properties; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo s390_virtio_rng = { @@ -658,6 +663,7 @@ static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data) k->realize = s390_virtio_scsi_realize; dc->props = s390_virtio_scsi_properties; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo s390_virtio_scsi = { @@ -681,6 +687,7 @@ static void s390_vhost_scsi_class_init(ObjectClass *klass, void *data) k->realize = s390_vhost_scsi_realize; dc->props = s390_vhost_scsi_properties; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo s390_vhost_scsi = { @@ -704,8 +711,10 @@ static int s390_virtio_bridge_init(SysBusDevice *dev) static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data) { SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->init = s390_virtio_bridge_init; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); } static const TypeInfo s390_virtio_bridge_info = { From 183f6b8d7e7adf6b892523644e38b534c5954be1 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 17 Mar 2015 13:44:39 +0100 Subject: [PATCH 03/10] sclp: sort into categories Sort the sclp consoles into the input category, just as virtio-serial. Various other sclp devices don't have an obvious category, sort them into misc. Reviewed-by: David Hildenbrand Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/char/sclpconsole-lm.c | 1 + hw/char/sclpconsole.c | 1 + hw/s390x/event-facility.c | 1 + hw/s390x/sclp.c | 9 +++++++++ hw/s390x/sclpcpu.c | 2 ++ hw/s390x/sclpquiesce.c | 1 + 6 files changed, 15 insertions(+) diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index a9f5e62f24..02ac80b650 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -364,6 +364,7 @@ static void console_class_init(ObjectClass *klass, void *data) ec->can_handle_event = can_handle_event; ec->read_event_data = read_event_data; ec->write_event_data = write_event_data; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo sclp_console_info = { diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index 79891dfc58..b014c7f522 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -266,6 +266,7 @@ static void console_class_init(ObjectClass *klass, void *data) ec->can_handle_event = can_handle_event; ec->read_event_data = read_event_data; ec->write_event_data = write_event_data; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo sclp_console_info = { diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 78da718362..1cb116a297 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -362,6 +362,7 @@ static void init_event_facility_class(ObjectClass *klass, void *data) dc->reset = reset_event_facility; dc->vmsd = &vmstate_event_facility; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); k->init = init_event_facility; k->command_handler = command_handler; k->event_pending = event_pending; diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index a969975a78..b3a6c5e5a4 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -457,10 +457,19 @@ sclpMemoryHotplugDev *get_sclp_memory_hotplug_dev(void) TYPE_SCLP_MEMORY_HOTPLUG_DEV, NULL)); } +static void sclp_memory_hotplug_dev_class_init(ObjectClass *klass, + void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + static TypeInfo sclp_memory_hotplug_dev_info = { .name = TYPE_SCLP_MEMORY_HOTPLUG_DEV, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(sclpMemoryHotplugDev), + .class_init = sclp_memory_hotplug_dev_class_init, }; static void register_types(void) diff --git a/hw/s390x/sclpcpu.c b/hw/s390x/sclpcpu.c index 3600fe231d..2fe8b5aa40 100644 --- a/hw/s390x/sclpcpu.c +++ b/hw/s390x/sclpcpu.c @@ -88,12 +88,14 @@ static int irq_cpu_hotplug_init(SCLPEvent *event) static void cpu_class_init(ObjectClass *oc, void *data) { SCLPEventClass *k = SCLP_EVENT_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); k->init = irq_cpu_hotplug_init; k->get_send_mask = send_mask; k->get_receive_mask = receive_mask; k->read_event_data = read_event_data; k->write_event_data = NULL; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo sclp_cpu_info = { diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c index 1a399bd1f0..ffa5553135 100644 --- a/hw/s390x/sclpquiesce.c +++ b/hw/s390x/sclpquiesce.c @@ -116,6 +116,7 @@ static void quiesce_class_init(ObjectClass *klass, void *data) dc->reset = quiesce_reset; dc->vmsd = &vmstate_sclpquiesce; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); k->init = quiesce_init; k->get_send_mask = send_mask; From b4ab4572b319f2c26435b2ed18cfd3fb602c7439 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 20 Mar 2015 10:17:08 +0100 Subject: [PATCH 04/10] s390x/ipl: sort into categories The s390 ipl device has no real home (it's not really a storage device), so let's sort it into the misc category. Reviewed-by: David Hildenbrand Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/s390x/ipl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 2e26d2aa2c..132004ae4f 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -315,6 +315,7 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data) dc->props = s390_ipl_properties; dc->reset = s390_ipl_reset; dc->vmsd = &vmstate_ipl; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo s390_ipl_info = { From 217a4acb211d603f33199cf94ada9fce3ac419b5 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 19 Mar 2015 15:04:50 +0100 Subject: [PATCH 05/10] s390x/mmu: Use access type definitions instead of magic values Since there are now proper definitions for the MMU access type, let's use them in the s390x MMU code, too, instead of the hard-to-understand magic values. Signed-off-by: Thomas Huth Reviewed-by: Jens Freimann Acked-by: Cornelia Huck Signed-off-by: Cornelia Huck --- target-s390x/helper.c | 2 +- target-s390x/mmu_helper.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target-s390x/helper.c b/target-s390x/helper.c index f1060c2bce..041c9c7429 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -162,7 +162,7 @@ hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr) vaddr &= 0x7fffffff; } - mmu_translate(env, vaddr, 2, asc, &raddr, &prot, false); + mmu_translate(env, vaddr, MMU_INST_FETCH, asc, &raddr, &prot, false); return raddr; } diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c index b061c85aff..9b88498b39 100644 --- a/target-s390x/mmu_helper.c +++ b/target-s390x/mmu_helper.c @@ -68,7 +68,7 @@ static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr, { uint64_t tec; - tec = vaddr | (rw == 1 ? FS_WRITE : FS_READ) | 4 | asc >> 46; + tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | 4 | asc >> 46; DPRINTF("%s: trans_exc_code=%016" PRIx64 "\n", __func__, tec); @@ -85,7 +85,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, int ilen = ILEN_LATER; uint64_t tec; - tec = vaddr | (rw == 1 ? FS_WRITE : FS_READ) | asc >> 46; + tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46; DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits); @@ -94,7 +94,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, } /* Code accesses have an undefined ilc. */ - if (rw == 2) { + if (rw == MMU_INST_FETCH) { ilen = 2; } @@ -288,7 +288,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw, exc); - if ((rw == 1) && !(*flags & PAGE_WRITE)) { + if (rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) { trigger_prot_fault(env, vaddr, asc, rw, exc); return -1; } @@ -338,7 +338,7 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc, * Instruction: Primary * Data: Secondary */ - if (rw == 2) { + if (rw == MMU_INST_FETCH) { r = mmu_translate_asce(env, vaddr, PSW_ASC_PRIMARY, env->cregs[1], raddr, flags, rw, exc); *flags &= ~(PAGE_READ | PAGE_WRITE); From 7a52ce8a160739c5d37469b0e344d3239eb86462 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 31 Mar 2015 16:07:08 +0200 Subject: [PATCH 06/10] linux-headers: update This updates linux-headers against master 4.1-rc1 (commit b787f68c36d49bb1d9236f403813641efa74a031). Signed-off-by: Cornelia Huck --- .../standard-headers/linux/virtio_balloon.h | 28 ++- include/standard-headers/linux/virtio_ids.h | 1 + include/standard-headers/linux/virtio_input.h | 76 +++++++++ linux-headers/asm-arm/kvm.h | 9 +- linux-headers/asm-arm64/kvm.h | 9 +- linux-headers/asm-mips/kvm.h | 160 +++++++++++------- linux-headers/asm-s390/kvm.h | 4 + linux-headers/asm-x86/hyperv.h | 2 + linux-headers/linux/kvm.h | 66 +++++++- linux-headers/linux/vfio.h | 2 + 10 files changed, 291 insertions(+), 66 deletions(-) create mode 100644 include/standard-headers/linux/virtio_input.h diff --git a/include/standard-headers/linux/virtio_balloon.h b/include/standard-headers/linux/virtio_balloon.h index 799376d414..88ada1d048 100644 --- a/include/standard-headers/linux/virtio_balloon.h +++ b/include/standard-headers/linux/virtio_balloon.h @@ -25,6 +25,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include "standard-headers/linux/types.h" #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_config.h" @@ -51,9 +52,32 @@ struct virtio_balloon_config { #define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ #define VIRTIO_BALLOON_S_NR 6 +/* + * Memory statistics structure. + * Driver fills an array of these structures and passes to device. + * + * NOTE: fields are laid out in a way that would make compiler add padding + * between and after fields, so we have to use compiler-specific attributes to + * pack it, to disable this padding. This also often causes compiler to + * generate suboptimal code. + * + * We maintain this statistics structure format for backwards compatibility, + * but don't follow this example. + * + * If implementing a similar structure, do something like the below instead: + * struct virtio_balloon_stat { + * __virtio16 tag; + * uint8_t reserved[6]; + * __virtio64 val; + * }; + * + * In other words, add explicit reserved fields to align field and + * structure boundaries at field size, avoiding compiler padding + * without the packed attribute. + */ struct virtio_balloon_stat { - uint16_t tag; - uint64_t val; + __virtio16 tag; + __virtio64 val; } QEMU_PACKED; #endif /* _LINUX_VIRTIO_BALLOON_H */ diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h index 284fc3a05f..5f60aa4be5 100644 --- a/include/standard-headers/linux/virtio_ids.h +++ b/include/standard-headers/linux/virtio_ids.h @@ -39,5 +39,6 @@ #define VIRTIO_ID_9P 9 /* 9p virtio console */ #define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */ #define VIRTIO_ID_CAIF 12 /* Virtio caif */ +#define VIRTIO_ID_INPUT 18 /* virtio input */ #endif /* _LINUX_VIRTIO_IDS_H */ diff --git a/include/standard-headers/linux/virtio_input.h b/include/standard-headers/linux/virtio_input.h new file mode 100644 index 0000000000..a98a7974c2 --- /dev/null +++ b/include/standard-headers/linux/virtio_input.h @@ -0,0 +1,76 @@ +#ifndef _LINUX_VIRTIO_INPUT_H +#define _LINUX_VIRTIO_INPUT_H +/* This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +#include "standard-headers/linux/types.h" + +enum virtio_input_config_select { + VIRTIO_INPUT_CFG_UNSET = 0x00, + VIRTIO_INPUT_CFG_ID_NAME = 0x01, + VIRTIO_INPUT_CFG_ID_SERIAL = 0x02, + VIRTIO_INPUT_CFG_ID_DEVIDS = 0x03, + VIRTIO_INPUT_CFG_PROP_BITS = 0x10, + VIRTIO_INPUT_CFG_EV_BITS = 0x11, + VIRTIO_INPUT_CFG_ABS_INFO = 0x12, +}; + +struct virtio_input_absinfo { + uint32_t min; + uint32_t max; + uint32_t fuzz; + uint32_t flat; + uint32_t res; +}; + +struct virtio_input_devids { + uint16_t bustype; + uint16_t vendor; + uint16_t product; + uint16_t version; +}; + +struct virtio_input_config { + uint8_t select; + uint8_t subsel; + uint8_t size; + uint8_t reserved[5]; + union { + char string[128]; + uint8_t bitmap[128]; + struct virtio_input_absinfo abs; + struct virtio_input_devids ids; + } u; +}; + +struct virtio_input_event { + uint16_t type; + uint16_t code; + uint32_t value; +}; + +#endif /* _LINUX_VIRTIO_INPUT_H */ diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h index 0db25bc328..c98e4dc460 100644 --- a/linux-headers/asm-arm/kvm.h +++ b/linux-headers/asm-arm/kvm.h @@ -195,9 +195,16 @@ struct kvm_arch_memory_slot { #define KVM_ARM_IRQ_CPU_IRQ 0 #define KVM_ARM_IRQ_CPU_FIQ 1 -/* Highest supported SPI, from VGIC_NR_IRQS */ +/* + * This used to hold the highest supported SPI, but it is now obsolete + * and only here to provide source code level compatibility with older + * userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS. + */ #define KVM_ARM_IRQ_GIC_MAX 127 +/* One single KVM irqchip, ie. the VGIC */ +#define KVM_NR_IRQCHIPS 1 + /* PSCI interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index 3ef77a4660..c8abf257c1 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -188,9 +188,16 @@ struct kvm_arch_memory_slot { #define KVM_ARM_IRQ_CPU_IRQ 0 #define KVM_ARM_IRQ_CPU_FIQ 1 -/* Highest supported SPI, from VGIC_NR_IRQS */ +/* + * This used to hold the highest supported SPI, but it is now obsolete + * and only here to provide source code level compatibility with older + * userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS. + */ #define KVM_ARM_IRQ_GIC_MAX 127 +/* One single KVM irqchip, ie. the VGIC */ +#define KVM_NR_IRQCHIPS 1 + /* PSCI interface */ #define KVM_PSCI_FN_BASE 0x95c1ba5e #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) diff --git a/linux-headers/asm-mips/kvm.h b/linux-headers/asm-mips/kvm.h index 2c04b6d9ff..6985eb59b0 100644 --- a/linux-headers/asm-mips/kvm.h +++ b/linux-headers/asm-mips/kvm.h @@ -36,77 +36,85 @@ struct kvm_regs { /* * for KVM_GET_FPU and KVM_SET_FPU - * - * If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs - * are zero filled. */ struct kvm_fpu { - __u64 fpr[32]; - __u32 fir; - __u32 fccr; - __u32 fexr; - __u32 fenr; - __u32 fcsr; - __u32 pad; }; /* - * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0 + * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various * registers. The id field is broken down as follows: * - * bits[2..0] - Register 'sel' index. - * bits[7..3] - Register 'rd' index. - * bits[15..8] - Must be zero. - * bits[31..16] - 1 -> CP0 registers. - * bits[51..32] - Must be zero. * bits[63..52] - As per linux/kvm.h + * bits[51..32] - Must be zero. + * bits[31..16] - Register set. + * + * Register set = 0: GP registers from kvm_regs (see definitions below). + * + * Register set = 1: CP0 registers. + * bits[15..8] - Must be zero. + * bits[7..3] - Register 'rd' index. + * bits[2..0] - Register 'sel' index. + * + * Register set = 2: KVM specific registers (see definitions below). + * + * Register set = 3: FPU / MSA registers (see definitions below). * * Other sets registers may be added in the future. Each set would * have its own identifier in bits[31..16]. - * - * The registers defined in struct kvm_regs are also accessible, the - * id values for these are below. */ -#define KVM_REG_MIPS_R0 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0) -#define KVM_REG_MIPS_R1 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 1) -#define KVM_REG_MIPS_R2 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 2) -#define KVM_REG_MIPS_R3 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 3) -#define KVM_REG_MIPS_R4 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 4) -#define KVM_REG_MIPS_R5 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 5) -#define KVM_REG_MIPS_R6 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 6) -#define KVM_REG_MIPS_R7 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 7) -#define KVM_REG_MIPS_R8 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 8) -#define KVM_REG_MIPS_R9 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 9) -#define KVM_REG_MIPS_R10 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 10) -#define KVM_REG_MIPS_R11 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 11) -#define KVM_REG_MIPS_R12 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 12) -#define KVM_REG_MIPS_R13 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 13) -#define KVM_REG_MIPS_R14 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 14) -#define KVM_REG_MIPS_R15 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 15) -#define KVM_REG_MIPS_R16 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 16) -#define KVM_REG_MIPS_R17 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 17) -#define KVM_REG_MIPS_R18 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 18) -#define KVM_REG_MIPS_R19 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 19) -#define KVM_REG_MIPS_R20 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 20) -#define KVM_REG_MIPS_R21 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 21) -#define KVM_REG_MIPS_R22 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 22) -#define KVM_REG_MIPS_R23 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 23) -#define KVM_REG_MIPS_R24 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 24) -#define KVM_REG_MIPS_R25 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 25) -#define KVM_REG_MIPS_R26 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 26) -#define KVM_REG_MIPS_R27 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 27) -#define KVM_REG_MIPS_R28 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 28) -#define KVM_REG_MIPS_R29 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 29) -#define KVM_REG_MIPS_R30 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 30) -#define KVM_REG_MIPS_R31 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 31) +#define KVM_REG_MIPS_GP (KVM_REG_MIPS | 0x0000000000000000ULL) +#define KVM_REG_MIPS_CP0 (KVM_REG_MIPS | 0x0000000000010000ULL) +#define KVM_REG_MIPS_KVM (KVM_REG_MIPS | 0x0000000000020000ULL) +#define KVM_REG_MIPS_FPU (KVM_REG_MIPS | 0x0000000000030000ULL) -#define KVM_REG_MIPS_HI (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 32) -#define KVM_REG_MIPS_LO (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 33) -#define KVM_REG_MIPS_PC (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 34) -/* KVM specific control registers */ +/* + * KVM_REG_MIPS_GP - General purpose registers from kvm_regs. + */ + +#define KVM_REG_MIPS_R0 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 0) +#define KVM_REG_MIPS_R1 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 1) +#define KVM_REG_MIPS_R2 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 2) +#define KVM_REG_MIPS_R3 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 3) +#define KVM_REG_MIPS_R4 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 4) +#define KVM_REG_MIPS_R5 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 5) +#define KVM_REG_MIPS_R6 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 6) +#define KVM_REG_MIPS_R7 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 7) +#define KVM_REG_MIPS_R8 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 8) +#define KVM_REG_MIPS_R9 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 9) +#define KVM_REG_MIPS_R10 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 10) +#define KVM_REG_MIPS_R11 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 11) +#define KVM_REG_MIPS_R12 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 12) +#define KVM_REG_MIPS_R13 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 13) +#define KVM_REG_MIPS_R14 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 14) +#define KVM_REG_MIPS_R15 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 15) +#define KVM_REG_MIPS_R16 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 16) +#define KVM_REG_MIPS_R17 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 17) +#define KVM_REG_MIPS_R18 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 18) +#define KVM_REG_MIPS_R19 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 19) +#define KVM_REG_MIPS_R20 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 20) +#define KVM_REG_MIPS_R21 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 21) +#define KVM_REG_MIPS_R22 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 22) +#define KVM_REG_MIPS_R23 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 23) +#define KVM_REG_MIPS_R24 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 24) +#define KVM_REG_MIPS_R25 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 25) +#define KVM_REG_MIPS_R26 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 26) +#define KVM_REG_MIPS_R27 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 27) +#define KVM_REG_MIPS_R28 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 28) +#define KVM_REG_MIPS_R29 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 29) +#define KVM_REG_MIPS_R30 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 30) +#define KVM_REG_MIPS_R31 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 31) + +#define KVM_REG_MIPS_HI (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 32) +#define KVM_REG_MIPS_LO (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 33) +#define KVM_REG_MIPS_PC (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 34) + + +/* + * KVM_REG_MIPS_KVM - KVM specific control registers. + */ /* * CP0_Count control @@ -118,8 +126,7 @@ struct kvm_fpu { * safely without losing time or guest timer interrupts. * Other: Reserved, do not change. */ -#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \ - 0x20000 | 0) +#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 0) #define KVM_REG_MIPS_COUNT_CTL_DC 0x00000001 /* @@ -131,15 +138,46 @@ struct kvm_fpu { * emulated. * Modifications to times in the future are rejected. */ -#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \ - 0x20000 | 1) +#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 1) /* * CP0_Count rate in Hz * Specifies the rate of the CP0_Count timer in Hz. Modifications occur without * discontinuities in CP0_Count. */ -#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \ - 0x20000 | 2) +#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 2) + + +/* + * KVM_REG_MIPS_FPU - Floating Point and MIPS SIMD Architecture (MSA) registers. + * + * bits[15..8] - Register subset (see definitions below). + * bits[7..5] - Must be zero. + * bits[4..0] - Register number within register subset. + */ + +#define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL) +#define KVM_REG_MIPS_FCR (KVM_REG_MIPS_FPU | 0x0000000000000100ULL) +#define KVM_REG_MIPS_MSACR (KVM_REG_MIPS_FPU | 0x0000000000000200ULL) + +/* + * KVM_REG_MIPS_FPR - Floating point / Vector registers. + */ +#define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n)) +#define KVM_REG_MIPS_FPR_64(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64 | (n)) +#define KVM_REG_MIPS_VEC_128(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U128 | (n)) + +/* + * KVM_REG_MIPS_FCR - Floating point control registers. + */ +#define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0) +#define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31) + +/* + * KVM_REG_MIPS_MSACR - MIPS SIMD Architecture (MSA) control registers. + */ +#define KVM_REG_MIPS_MSA_IR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 0) +#define KVM_REG_MIPS_MSA_CSR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 1) + /* * KVM MIPS specific structures and definitions diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h index c5a93eb0bc..512d8f1d4f 100644 --- a/linux-headers/asm-s390/kvm.h +++ b/linux-headers/asm-s390/kvm.h @@ -150,6 +150,7 @@ struct kvm_guest_debug_arch { #define KVM_SYNC_CRS (1UL << 3) #define KVM_SYNC_ARCH0 (1UL << 4) #define KVM_SYNC_PFAULT (1UL << 5) +#define KVM_SYNC_VRS (1UL << 6) /* definition of registers in kvm_run */ struct kvm_sync_regs { __u64 prefix; /* prefix register */ @@ -164,6 +165,9 @@ struct kvm_sync_regs { __u64 pft; /* pfault token [PFAULT] */ __u64 pfs; /* pfault select [PFAULT] */ __u64 pfc; /* pfault compare [PFAULT] */ + __u64 vrs[32][2]; /* vector registers */ + __u8 reserved[512]; /* for future vector expansion */ + __u32 fpc; /* only valid with vector registers */ }; #define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1) diff --git a/linux-headers/asm-x86/hyperv.h b/linux-headers/asm-x86/hyperv.h index 90c458e66e..ce6068dbcf 100644 --- a/linux-headers/asm-x86/hyperv.h +++ b/linux-headers/asm-x86/hyperv.h @@ -225,6 +225,8 @@ #define HV_STATUS_INVALID_HYPERCALL_CODE 2 #define HV_STATUS_INVALID_HYPERCALL_INPUT 3 #define HV_STATUS_INVALID_ALIGNMENT 4 +#define HV_STATUS_INSUFFICIENT_MEMORY 11 +#define HV_STATUS_INVALID_CONNECTION_ID 18 #define HV_STATUS_INSUFFICIENT_BUFFERS 19 typedef struct _HV_REFERENCE_TSC_PAGE { diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 60a54c82a3..b96d9787dd 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -147,6 +147,16 @@ struct kvm_pit_config { #define KVM_PIT_SPEAKER_DUMMY 1 +struct kvm_s390_skeys { + __u64 start_gfn; + __u64 count; + __u64 skeydata_addr; + __u32 flags; + __u32 reserved[9]; +}; +#define KVM_S390_GET_SKEYS_NONE 1 +#define KVM_S390_SKEYS_MAX 1048576 + #define KVM_EXIT_UNKNOWN 0 #define KVM_EXIT_EXCEPTION 1 #define KVM_EXIT_IO 2 @@ -172,6 +182,7 @@ struct kvm_pit_config { #define KVM_EXIT_S390_TSCH 22 #define KVM_EXIT_EPR 23 #define KVM_EXIT_SYSTEM_EVENT 24 +#define KVM_EXIT_S390_STSI 25 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -309,6 +320,15 @@ struct kvm_run { __u32 type; __u64 flags; } system_event; + /* KVM_EXIT_S390_STSI */ + struct { + __u64 addr; + __u8 ar; + __u8 reserved; + __u8 fc; + __u8 sel1; + __u16 sel2; + } s390_stsi; /* Fix the size of the union. */ char padding[256]; }; @@ -324,7 +344,7 @@ struct kvm_run { __u64 kvm_dirty_regs; union { struct kvm_sync_regs regs; - char padding[1024]; + char padding[2048]; } s; }; @@ -365,6 +385,24 @@ struct kvm_translation { __u8 pad[5]; }; +/* for KVM_S390_MEM_OP */ +struct kvm_s390_mem_op { + /* in */ + __u64 gaddr; /* the guest address */ + __u64 flags; /* flags */ + __u32 size; /* amount of bytes */ + __u32 op; /* type of operation */ + __u64 buf; /* buffer in userspace */ + __u8 ar; /* the access register number */ + __u8 reserved[31]; /* should be set to 0 */ +}; +/* types for kvm_s390_mem_op->op */ +#define KVM_S390_MEMOP_LOGICAL_READ 0 +#define KVM_S390_MEMOP_LOGICAL_WRITE 1 +/* flags for kvm_s390_mem_op->flags */ +#define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) +#define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) + /* for KVM_INTERRUPT */ struct kvm_interrupt { /* in */ @@ -520,6 +558,13 @@ struct kvm_s390_irq { } u; }; +struct kvm_s390_irq_state { + __u64 buf; + __u32 flags; + __u32 len; + __u32 reserved[4]; +}; + /* for KVM_SET_GUEST_DEBUG */ #define KVM_GUESTDBG_ENABLE 0x00000001 @@ -760,6 +805,15 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_PPC_ENABLE_HCALL 104 #define KVM_CAP_CHECK_EXTENSION_VM 105 #define KVM_CAP_S390_USER_SIGP 106 +#define KVM_CAP_S390_VECTOR_REGISTERS 107 +#define KVM_CAP_S390_MEM_OP 108 +#define KVM_CAP_S390_USER_STSI 109 +#define KVM_CAP_S390_SKEYS 110 +#define KVM_CAP_MIPS_FPU 111 +#define KVM_CAP_MIPS_MSA 112 +#define KVM_CAP_S390_INJECT_IRQ 113 +#define KVM_CAP_S390_IRQ_STATE 114 +#define KVM_CAP_PPC_HWRNG 115 #ifdef KVM_CAP_IRQ_ROUTING @@ -1135,6 +1189,16 @@ struct kvm_s390_ucas_mapping { #define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init) #define KVM_ARM_PREFERRED_TARGET _IOR(KVMIO, 0xaf, struct kvm_vcpu_init) #define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list) +/* Available with KVM_CAP_S390_MEM_OP */ +#define KVM_S390_MEM_OP _IOW(KVMIO, 0xb1, struct kvm_s390_mem_op) +/* Available with KVM_CAP_S390_SKEYS */ +#define KVM_S390_GET_SKEYS _IOW(KVMIO, 0xb2, struct kvm_s390_skeys) +#define KVM_S390_SET_SKEYS _IOW(KVMIO, 0xb3, struct kvm_s390_skeys) +/* Available with KVM_CAP_S390_INJECT_IRQ */ +#define KVM_S390_IRQ _IOW(KVMIO, 0xb4, struct kvm_s390_irq) +/* Available with KVM_CAP_S390_IRQ_STATE */ +#define KVM_S390_SET_IRQ_STATE _IOW(KVMIO, 0xb5, struct kvm_s390_irq_state) +#define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state) #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index 95ba870302..0508d0b5d2 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -160,6 +160,8 @@ struct vfio_device_info { __u32 flags; #define VFIO_DEVICE_FLAGS_RESET (1 << 0) /* Device supports reset */ #define VFIO_DEVICE_FLAGS_PCI (1 << 1) /* vfio-pci device */ +#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2) /* vfio-platform device */ +#define VFIO_DEVICE_FLAGS_AMBA (1 << 3) /* vfio-amba device */ __u32 num_regions; /* Max region index + 1 */ __u32 num_irqs; /* Max IRQ index + 1 */ }; From f07177a5599fb204e42a007db4820ceda1bc85ba Mon Sep 17 00:00:00 2001 From: Ekaterina Tumanova Date: Tue, 3 Mar 2015 18:35:27 +0100 Subject: [PATCH 07/10] s390x/kvm: Put vm name, extended name and UUID into STSI322 SYSIB KVM prefills the SYSIB, returned by STSI 3.2.2. This patch allows userspace to intercept execution, and fill in the values, that are known to qemu: machine name (8 chars), extended machine name (256 chars), extended machine name encoding (equals 2 for UTF-8) and UUID. STSI322 qemu handler also finds a highest virtualization level in level-3 virtualization stack that doesn't support Extended Names (Ext Name delimiter) and propagates zero Ext Name to all levels below, because this level is not capable of managing Extended Names of lower levels. Signed-off-by: Ekaterina Tumanova Reviewed-by: Christian Borntraeger Reviewed-by: Thomas Huth Signed-off-by: Cornelia Huck --- target-s390x/cpu.h | 8 ++++-- target-s390x/kvm.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 8135dda318..79bc80b586 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -865,9 +865,13 @@ struct sysib_322 { uint8_t name[8]; uint32_t caf; uint8_t cpi[16]; - uint8_t res3[24]; + uint8_t res5[3]; + uint8_t ext_name_encoding; + uint32_t res3; + uint8_t uuid[16]; } vm[8]; - uint8_t res4[3552]; + uint8_t res4[1504]; + uint8_t ext_names[8][256]; }; /* MMU defines */ diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index b48c643b36..619684b9ee 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -44,6 +44,7 @@ #include "hw/s390x/s390-pci-inst.h" #include "hw/s390x/s390-pci-bus.h" #include "hw/s390x/ipl.h" +#include "hw/s390x/ebcdic.h" /* #define DEBUG_KVM */ @@ -255,6 +256,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0); + kvm_vm_enable_cap(s, KVM_CAP_S390_USER_STSI, 0); return 0; } @@ -1723,6 +1725,72 @@ static int handle_tsch(S390CPU *cpu) return ret; } +static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr) +{ + struct sysib_322 sysib; + int del; + + if (s390_cpu_virt_mem_read(cpu, addr, &sysib, sizeof(sysib))) { + return; + } + /* Shift the stack of Extended Names to prepare for our own data */ + memmove(&sysib.ext_names[1], &sysib.ext_names[0], + sizeof(sysib.ext_names[0]) * (sysib.count - 1)); + /* First virt level, that doesn't provide Ext Names delimits stack. It is + * assumed it's not capable of managing Extended Names for lower levels. + */ + for (del = 1; del < sysib.count; del++) { + if (!sysib.vm[del].ext_name_encoding || !sysib.ext_names[del][0]) { + break; + } + } + if (del < sysib.count) { + memset(sysib.ext_names[del], 0, + sizeof(sysib.ext_names[0]) * (sysib.count - del)); + } + /* Insert short machine name in EBCDIC, padded with blanks */ + if (qemu_name) { + memset(sysib.vm[0].name, 0x40, sizeof(sysib.vm[0].name)); + ebcdic_put(sysib.vm[0].name, qemu_name, MIN(sizeof(sysib.vm[0].name), + strlen(qemu_name))); + } + sysib.vm[0].ext_name_encoding = 2; /* 2 = UTF-8 */ + memset(sysib.ext_names[0], 0, sizeof(sysib.ext_names[0])); + /* If hypervisor specifies zero Extended Name in STSI322 SYSIB, it's + * considered by s390 as not capable of providing any Extended Name. + * Therefore if no name was specified on qemu invocation, we go with the + * same "KVMguest" default, which KVM has filled into short name field. + */ + if (qemu_name) { + strncpy((char *)sysib.ext_names[0], qemu_name, + sizeof(sysib.ext_names[0])); + } else { + strcpy((char *)sysib.ext_names[0], "KVMguest"); + } + /* Insert UUID */ + memcpy(sysib.vm[0].uuid, qemu_uuid, sizeof(sysib.vm[0].uuid)); + + s390_cpu_virt_mem_write(cpu, addr, &sysib, sizeof(sysib)); +} + +static int handle_stsi(S390CPU *cpu) +{ + CPUState *cs = CPU(cpu); + struct kvm_run *run = cs->kvm_run; + + switch (run->s390_stsi.fc) { + case 3: + if (run->s390_stsi.sel1 != 2 || run->s390_stsi.sel2 != 2) { + return 0; + } + /* Only sysib 3.2.2 needs post-handling for now. */ + insert_stsi_3_2_2(cpu, run->s390_stsi.addr); + return 0; + default: + return 0; + } +} + static int kvm_arch_handle_debug_exit(S390CPU *cpu) { CPUState *cs = CPU(cpu); @@ -1772,6 +1840,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) case KVM_EXIT_S390_TSCH: ret = handle_tsch(cpu); break; + case KVM_EXIT_S390_STSI: + ret = handle_stsi(cpu); + break; case KVM_EXIT_DEBUG: ret = kvm_arch_handle_debug_exit(cpu); break; From a9bcd1b8719dea2e91512238d810e2a0037e174d Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 6 Feb 2015 15:54:58 +0100 Subject: [PATCH 08/10] s390x/mmu: Use ioctl for reading and writing from/to guest memory Add code to make use of the new ioctl for reading from / writing to virtual guest memory. By using the ioctl, the memory accesses are now protected with the so-called ipte-lock in the kernel. [CH: moved error message into kvm_s390_mem_op()] Signed-off-by: Thomas Huth Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- target-s390x/cpu.h | 7 +++++++ target-s390x/kvm.c | 40 +++++++++++++++++++++++++++++++++++++++ target-s390x/mmu_helper.c | 7 +++++++ 3 files changed, 54 insertions(+) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 79bc80b586..9c4274325a 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -401,6 +401,8 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq); void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq); int kvm_s390_inject_flic(struct kvm_s390_irq *irq); void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code); +int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len, + bool is_write); int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock); #else @@ -418,6 +420,11 @@ static inline int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) { return -ENOSYS; } +static inline int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, + int len, bool is_write) +{ + return -ENOSYS; +} static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code) { diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 619684b9ee..1c0e78c64b 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -123,6 +123,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { static int cap_sync_regs; static int cap_async_pf; +static int cap_mem_op; static void *legacy_s390_alloc(size_t size, uint64_t *align); @@ -247,6 +248,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) { cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF); + cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP); kvm_s390_enable_cmma(s); @@ -550,6 +552,44 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); } +/** + * kvm_s390_mem_op: + * @addr: the logical start address in guest memory + * @hostbuf: buffer in host memory. NULL = do only checks w/o copying + * @len: length that should be transfered + * @is_write: true = write, false = read + * Returns: 0 on success, non-zero if an exception or error occured + * + * Use KVM ioctl to read/write from/to guest memory. An access exception + * is injected into the vCPU in case of translation errors. + */ +int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len, + bool is_write) +{ + struct kvm_s390_mem_op mem_op = { + .gaddr = addr, + .flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION, + .size = len, + .op = is_write ? KVM_S390_MEMOP_LOGICAL_WRITE + : KVM_S390_MEMOP_LOGICAL_READ, + .buf = (uint64_t)hostbuf, + }; + int ret; + + if (!cap_mem_op) { + return -ENOSYS; + } + if (!hostbuf) { + mem_op.flags |= KVM_S390_MEMOP_F_CHECK_ONLY; + } + + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_S390_MEM_OP, &mem_op); + if (ret < 0) { + error_printf("KVM_S390_MEM_OP failed: %s\n", strerror(-ret)); + } + return ret; +} + /* * Legacy layout for s390: * Older S390 KVM requires the topmost vma of the RAM to be diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c index 9b88498b39..cd2cb51629 100644 --- a/target-s390x/mmu_helper.c +++ b/target-s390x/mmu_helper.c @@ -450,6 +450,13 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf, target_ulong *pages; int ret; + if (kvm_enabled()) { + ret = kvm_s390_mem_op(cpu, laddr, hostbuf, len, is_write); + if (ret >= 0) { + return ret; + } + } + nr_pages = (((laddr & ~TARGET_PAGE_MASK) + len - 1) >> TARGET_PAGE_BITS) + 1; pages = g_malloc(nr_pages * sizeof(*pages)); From 6cb1e49de58cab8f243b05a971a9a1f80ab3223d Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Thu, 5 Mar 2015 12:36:48 +0300 Subject: [PATCH 09/10] s390x/kvm: Support access register mode for KVM_S390_MEM_OP ioctl Access register mode is one of the modes that control dynamic address translation. In this mode the address space is specified by values of the access registers. The effective address-space-control element is obtained from the result of the access register translation. See the "Access-Register Introduction" section of the chapter 5 "Program Execution" in "Principles of Operations" for more details. When the CPU is in AR mode, the s390_cpu_virt_mem_rw() function must know which access register number to use for address translation. This patch does several things: - add new parameter 'uint8_t ar' to that function - decode ar number from intercepted instructions - pass the ar number to s390_cpu_virt_mem_rw(), which in turn passes it to the KVM_S390_MEM_OP ioctl. Signed-off-by: Alexander Yarygin Reviewed-by: Thomas Huth Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-inst.c | 21 +++++++++--------- hw/s390x/s390-pci-inst.h | 7 +++--- target-s390x/cpu.h | 30 ++++++++++++++----------- target-s390x/ioinst.c | 42 ++++++++++++++++++++--------------- target-s390x/kvm.c | 46 +++++++++++++++++++++++++-------------- target-s390x/mmu_helper.c | 5 +++-- 6 files changed, 90 insertions(+), 61 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 8f7288fadf..f9151a9afb 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -155,7 +155,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) return 0; } - if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer, sizeof(*reqh))) { + if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer, sizeof(*reqh))) { return 0; } reqh = (ClpReqHdr *)buffer; @@ -165,7 +165,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) return 0; } - if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer, + if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer, req_len + sizeof(*resh))) { return 0; } @@ -180,7 +180,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) return 0; } - if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer, + if (s390_cpu_virt_mem_read(cpu, env->regs[r2], r2, buffer, req_len + res_len)) { return 0; } @@ -277,7 +277,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) } out: - if (s390_cpu_virt_mem_write(cpu, env->regs[r2], buffer, + if (s390_cpu_virt_mem_write(cpu, env->regs[r2], r2, buffer, req_len + res_len)) { return 0; } @@ -546,7 +546,8 @@ out: return 0; } -int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr) +int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, + uint8_t ar) { CPUS390XState *env = &cpu->env; S390PCIBusDevice *pbdev; @@ -603,7 +604,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr) return 0; } - if (s390_cpu_virt_mem_read(cpu, gaddr, buffer, len)) { + if (s390_cpu_virt_mem_read(cpu, gaddr, ar, buffer, len)) { return 0; } @@ -698,7 +699,7 @@ static void dereg_ioat(S390PCIBusDevice *pbdev) pbdev->g_iota = 0; } -int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) +int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) { CPUS390XState *env = &cpu->env; uint8_t oc; @@ -727,7 +728,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) return 0; } - if (s390_cpu_virt_mem_read(cpu, fiba, (uint8_t *)&fib, sizeof(fib))) { + if (s390_cpu_virt_mem_read(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) { return 0; } @@ -773,7 +774,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) return 0; } -int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) { CPUS390XState *env = &cpu->env; uint32_t fh; @@ -829,7 +830,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) fib.fc |= 0x10; } - if (s390_cpu_virt_mem_write(cpu, fiba, (uint8_t *)&fib, sizeof(fib))) { + if (s390_cpu_virt_mem_write(cpu, fiba, ar, (uint8_t *)&fib, sizeof(fib))) { return 0; } diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h index 7e6c804737..70fa71395f 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/hw/s390x/s390-pci-inst.h @@ -281,8 +281,9 @@ int clp_service_call(S390CPU *cpu, uint8_t r2); int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); -int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr); -int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba); -int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba); +int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, + uint8_t ar); +int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar); +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar); #endif diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 9c4274325a..ba7d250962 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -356,7 +356,8 @@ int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, #ifndef CONFIG_USER_ONLY void do_restart_interrupt(CPUS390XState *env); -static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb) +static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb, + uint8_t *ar) { hwaddr addr = 0; uint8_t reg; @@ -366,6 +367,9 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb) addr = env->regs[reg]; } addr += (ipb >> 16) & 0xfff; + if (ar) { + *ar = reg; + } return addr; } @@ -401,8 +405,8 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq); void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq); int kvm_s390_inject_flic(struct kvm_s390_irq *irq); void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code); -int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len, - bool is_write); +int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, + int len, bool is_write); int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock); #else @@ -420,8 +424,8 @@ static inline int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) { return -ENOSYS; } -static inline int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, - int len, bool is_write) +static inline int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, + void *hostbuf, int len, bool is_write) { return -ENOSYS; } @@ -963,15 +967,15 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code); uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, uint64_t vr); -int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf, int len, - bool is_write); +int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf, + int len, bool is_write); -#define s390_cpu_virt_mem_read(cpu, laddr, dest, len) \ - s390_cpu_virt_mem_rw(cpu, laddr, dest, len, false) -#define s390_cpu_virt_mem_write(cpu, laddr, dest, len) \ - s390_cpu_virt_mem_rw(cpu, laddr, dest, len, true) -#define s390_cpu_virt_mem_check_write(cpu, laddr, len) \ - s390_cpu_virt_mem_rw(cpu, laddr, NULL, len, true) +#define s390_cpu_virt_mem_read(cpu, laddr, ar, dest, len) \ + s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, false) +#define s390_cpu_virt_mem_write(cpu, laddr, ar, dest, len) \ + s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, true) +#define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \ + s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true) /* The value of the TOD clock for 1.1.1970. */ #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c index b00a00ca2b..e220cea8ab 100644 --- a/target-s390x/ioinst.c +++ b/target-s390x/ioinst.c @@ -149,13 +149,14 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) int ret = -ENODEV; int cc; CPUS390XState *env = &cpu->env; + uint8_t ar; - addr = decode_basedisp_s(env, ipb); + addr = decode_basedisp_s(env, ipb, &ar); if (addr & 3) { program_interrupt(env, PGM_SPECIFICATION, 2); return; } - if (s390_cpu_virt_mem_read(cpu, addr, &schib, sizeof(schib))) { + if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) { return; } if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) || @@ -215,13 +216,14 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) int ret = -ENODEV; int cc; CPUS390XState *env = &cpu->env; + uint8_t ar; - addr = decode_basedisp_s(env, ipb); + addr = decode_basedisp_s(env, ipb, &ar); if (addr & 3) { program_interrupt(env, PGM_SPECIFICATION, 2); return; } - if (s390_cpu_virt_mem_read(cpu, addr, &orig_orb, sizeof(orb))) { + if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) { return; } copy_orb_from_guest(&orb, &orig_orb); @@ -258,8 +260,9 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb) uint64_t addr; int cc; CPUS390XState *env = &cpu->env; + uint8_t ar; - addr = decode_basedisp_s(env, ipb); + addr = decode_basedisp_s(env, ipb, &ar); if (addr & 3) { program_interrupt(env, PGM_SPECIFICATION, 2); return; @@ -268,7 +271,7 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb) cc = css_do_stcrw(&crw); /* 0 - crw stored, 1 - zeroes stored */ - if (s390_cpu_virt_mem_write(cpu, addr, &crw, sizeof(crw)) == 0) { + if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { setcc(cpu, cc); } else if (cc == 0) { /* Write failed: requeue CRW since STCRW is a suppressing instruction */ @@ -284,8 +287,9 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) int cc; SCHIB schib; CPUS390XState *env = &cpu->env; + uint8_t ar; - addr = decode_basedisp_s(env, ipb); + addr = decode_basedisp_s(env, ipb, &ar); if (addr & 3) { program_interrupt(env, PGM_SPECIFICATION, 2); return; @@ -297,7 +301,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) * we check whether the memory area is writeable (injecting the * access execption if it is not) first. */ - if (!s390_cpu_virt_mem_check_write(cpu, addr, sizeof(schib))) { + if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) { program_interrupt(env, PGM_OPERAND, 2); } return; @@ -322,12 +326,13 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) } } if (cc != 3) { - if (s390_cpu_virt_mem_write(cpu, addr, &schib, sizeof(schib)) != 0) { + if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, + sizeof(schib)) != 0) { return; } } else { /* Access exceptions have a higher priority than cc3 */ - if (s390_cpu_virt_mem_check_write(cpu, addr, sizeof(schib)) != 0) { + if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) { return; } } @@ -342,13 +347,14 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) IRB irb; uint64_t addr; int cc, irb_len; + uint8_t ar; if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { program_interrupt(env, PGM_OPERAND, 2); return -EIO; } trace_ioinst_sch_id("tsch", cssid, ssid, schid); - addr = decode_basedisp_s(env, ipb); + addr = decode_basedisp_s(env, ipb, &ar); if (addr & 3) { program_interrupt(env, PGM_SPECIFICATION, 2); return -EIO; @@ -362,14 +368,14 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb) } /* 0 - status pending, 1 - not status pending, 3 - not operational */ if (cc != 3) { - if (s390_cpu_virt_mem_write(cpu, addr, &irb, irb_len) != 0) { + if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) { return -EFAULT; } css_do_tsch_update_subch(sch); } else { irb_len = sizeof(irb) - sizeof(irb.emw); /* Access exceptions have a higher priority than cc3 */ - if (s390_cpu_virt_mem_check_write(cpu, addr, irb_len) != 0) { + if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) { return -EFAULT; } } @@ -645,7 +651,7 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb) * present CHSC sub-handlers ... if we ever need more, we should take * care of req->len here first. */ - if (s390_cpu_virt_mem_read(cpu, addr, buf, sizeof(ChscReq))) { + if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) { return; } req = (ChscReq *)buf; @@ -677,7 +683,8 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb) break; } - if (!s390_cpu_virt_mem_write(cpu, addr + len, res, be16_to_cpu(res->len))) { + if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, + be16_to_cpu(res->len))) { setcc(cpu, 0); /* Command execution complete */ } } @@ -690,9 +697,10 @@ int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb) IOIntCode int_code; hwaddr len; int ret; + uint8_t ar; trace_ioinst("tpi"); - addr = decode_basedisp_s(env, ipb); + addr = decode_basedisp_s(env, ipb, &ar); if (addr & 3) { program_interrupt(env, PGM_SPECIFICATION, 2); return -EIO; @@ -702,7 +710,7 @@ int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb) len = lowcore ? 8 /* two words */ : 12 /* three words */; ret = css_do_tpi(&int_code, lowcore); if (ret == 1) { - s390_cpu_virt_mem_write(cpu, lowcore ? 184 : addr, &int_code, len); + s390_cpu_virt_mem_write(cpu, lowcore ? 184 : addr, ar, &int_code, len); } return ret; } diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 1c0e78c64b..8e65e43f02 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -555,6 +555,7 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) /** * kvm_s390_mem_op: * @addr: the logical start address in guest memory + * @ar: the access register number * @hostbuf: buffer in host memory. NULL = do only checks w/o copying * @len: length that should be transfered * @is_write: true = write, false = read @@ -563,8 +564,8 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) * Use KVM ioctl to read/write from/to guest memory. An access exception * is injected into the vCPU in case of translation errors. */ -int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len, - bool is_write) +int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, + int len, bool is_write) { struct kvm_s390_mem_op mem_op = { .gaddr = addr, @@ -573,6 +574,7 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len, .op = is_write ? KVM_S390_MEMOP_LOGICAL_WRITE : KVM_S390_MEMOP_LOGICAL_READ, .buf = (uint64_t)hostbuf, + .ar = ar, }; int ret; @@ -1017,7 +1019,8 @@ static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) return rc; } -static uint64_t get_base_disp_rxy(S390CPU *cpu, struct kvm_run *run) +static uint64_t get_base_disp_rxy(S390CPU *cpu, struct kvm_run *run, + uint8_t *ar) { CPUS390XState *env = &cpu->env; uint32_t x2 = (run->s390_sieic.ipa & 0x000f); @@ -1028,12 +1031,16 @@ static uint64_t get_base_disp_rxy(S390CPU *cpu, struct kvm_run *run) if (disp2 & 0x80000) { disp2 += 0xfff00000; } + if (ar) { + *ar = base2; + } return (base2 ? env->regs[base2] : 0) + (x2 ? env->regs[x2] : 0) + (long)(int)disp2; } -static uint64_t get_base_disp_rsy(S390CPU *cpu, struct kvm_run *run) +static uint64_t get_base_disp_rsy(S390CPU *cpu, struct kvm_run *run, + uint8_t *ar) { CPUS390XState *env = &cpu->env; uint32_t base2 = run->s390_sieic.ipb >> 28; @@ -1043,6 +1050,9 @@ static uint64_t get_base_disp_rsy(S390CPU *cpu, struct kvm_run *run) if (disp2 & 0x80000) { disp2 += 0xfff00000; } + if (ar) { + *ar = base2; + } return (base2 ? env->regs[base2] : 0) + (long)(int)disp2; } @@ -1074,11 +1084,12 @@ static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run) { uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4; uint64_t fiba; + uint8_t ar; cpu_synchronize_state(CPU(cpu)); - fiba = get_base_disp_rxy(cpu, run); + fiba = get_base_disp_rxy(cpu, run, &ar); - return stpcifc_service_call(cpu, r1, fiba); + return stpcifc_service_call(cpu, r1, fiba, ar); } static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run) @@ -1100,22 +1111,24 @@ static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run) uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4; uint8_t r3 = run->s390_sieic.ipa & 0x000f; uint64_t gaddr; + uint8_t ar; cpu_synchronize_state(CPU(cpu)); - gaddr = get_base_disp_rsy(cpu, run); + gaddr = get_base_disp_rsy(cpu, run, &ar); - return pcistb_service_call(cpu, r1, r3, gaddr); + return pcistb_service_call(cpu, r1, r3, gaddr, ar); } static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run) { uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4; uint64_t fiba; + uint8_t ar; cpu_synchronize_state(CPU(cpu)); - fiba = get_base_disp_rxy(cpu, run); + fiba = get_base_disp_rxy(cpu, run, &ar); - return mpcifc_service_call(cpu, r1, fiba); + return mpcifc_service_call(cpu, r1, fiba, ar); } static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) @@ -1244,7 +1257,7 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb) * For any diagnose call we support, bits 48-63 of the resulting * address specify the function code; the remainder is ignored. */ - func_code = decode_basedisp_rs(&cpu->env, ipb) & DIAG_KVM_CODE_MASK; + func_code = decode_basedisp_rs(&cpu->env, ipb, NULL) & DIAG_KVM_CODE_MASK; switch (func_code) { case DIAG_IPL: kvm_handle_diag_308(cpu, run); @@ -1591,7 +1604,8 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) cpu_synchronize_state(CPU(cpu)); /* get order code */ - order = decode_basedisp_rs(env, run->s390_sieic.ipb) & SIGP_ORDER_MASK; + order = decode_basedisp_rs(env, run->s390_sieic.ipb, NULL) + & SIGP_ORDER_MASK; status_reg = &env->regs[r1]; param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1]; @@ -1765,12 +1779,12 @@ static int handle_tsch(S390CPU *cpu) return ret; } -static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr) +static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar) { struct sysib_322 sysib; int del; - if (s390_cpu_virt_mem_read(cpu, addr, &sysib, sizeof(sysib))) { + if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) { return; } /* Shift the stack of Extended Names to prepare for our own data */ @@ -1810,7 +1824,7 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr) /* Insert UUID */ memcpy(sysib.vm[0].uuid, qemu_uuid, sizeof(sysib.vm[0].uuid)); - s390_cpu_virt_mem_write(cpu, addr, &sysib, sizeof(sysib)); + s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib)); } static int handle_stsi(S390CPU *cpu) @@ -1824,7 +1838,7 @@ static int handle_stsi(S390CPU *cpu) return 0; } /* Only sysib 3.2.2 needs post-handling for now. */ - insert_stsi_3_2_2(cpu, run->s390_stsi.addr); + insert_stsi_3_2_2(cpu, run->s390_stsi.addr, run->s390_stsi.ar); return 0; default: return 0; diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c index cd2cb51629..30a38ecb3c 100644 --- a/target-s390x/mmu_helper.c +++ b/target-s390x/mmu_helper.c @@ -435,6 +435,7 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages, /** * s390_cpu_virt_mem_rw: * @laddr: the logical start address + * @ar: the access register number * @hostbuf: buffer in host memory. NULL = do only checks w/o copying * @len: length that should be transfered * @is_write: true = write, false = read @@ -443,7 +444,7 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages, * Copy from/to guest memory using logical addresses. Note that we inject a * program interrupt in case there is an error while accessing the memory. */ -int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf, +int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf, int len, bool is_write) { int currlen, nr_pages, i; @@ -451,7 +452,7 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf, int ret; if (kvm_enabled()) { - ret = kvm_s390_mem_op(cpu, laddr, hostbuf, len, is_write); + ret = kvm_s390_mem_op(cpu, laddr, ar, hostbuf, len, is_write); if (ret >= 0) { return ret; } From 2c80e996e427ae31982f3405a762859578a6261d Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 23 Apr 2015 17:03:46 +0200 Subject: [PATCH 10/10] kvm: better advice for failed s390x startup If KVM_CREATE failed on s390x, we print a hint to enable the switch_amode kernel parameter. This only applies to old kernels, and only if the error was -EINVAL. Moreover, with new kernels, the most likely reason for -EINVAL is that pgstes were not enabled. Let's update the error message to give a better hint on where things may need fixing. Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- kvm-all.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index 2a717e5b50..3f7061a180 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1544,8 +1544,17 @@ static int kvm_init(MachineState *ms) strerror(-ret)); #ifdef TARGET_S390X - fprintf(stderr, "Please add the 'switch_amode' kernel parameter to " - "your host kernel command line\n"); + if (ret == -EINVAL) { + fprintf(stderr, + "Host kernel setup problem detected. Please verify:\n"); + fprintf(stderr, "- for kernels supporting the switch_amode or" + " user_mode parameters, whether\n"); + fprintf(stderr, + " user space is running in primary address space\n"); + fprintf(stderr, + "- for kernels supporting the vm.allocate_pgste sysctl, " + "whether it is enabled\n"); + } #endif goto err; }