qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20170714' into staging

s390x/kvm/migration/cpumodel: fixes, enhancements and cleanups

- add a network boot rom for s390 (Thomas Huth)
- migration of storage attributes like the CMMA used/unused state
- PCI related enhancements - full support for aen, ais and zpci
- migration support for css with vmstates (Halil Pasic)
- cpu model enhancements for cpu features
- guarded storage support

# gpg: Signature made Fri 14 Jul 2017 11:33:04 BST
# gpg: using RSA key 0x117BBC80B5A61C7C
# gpg: Good signature from "Christian Borntraeger (IBM) <borntraeger@de.ibm.com>"
# Primary key fingerprint: F922 9381 A334 08F9 DBAB FBCA 117B BC80 B5A6 1C7C

* remotes/borntraeger/tags/s390x-20170714: (40 commits)
s390x/gdb: add gs registers
s390x/arch_dump: also dump guarded storage control block
s390x/kvm: enable guarded storage
s390x/kvm: Enable KSS facility for nested virtualization
s390x/cpumodel: add esop/esop2 to z12 model
s390x/cpumodel: we are always in zarchitecture mode
s390x/cpumodel: wire up new hardware features
s390x/flic: migrate ais states
s390x/cpumodel: add zpci, aen and ais facilities
s390x: initialize cpu firstly
pc-bios/s390: rebuild s390-ccw.img
pc-bios/s390: add s390-netboot.img
pc-bios/s390-ccw: Link libnet into the netboot image and do the TFTP load
pc-bios/s390-ccw: Add virtio-net driver code
pc-bios/s390-ccw: Add core files for the network bootloading program
roms/SLOF: Update submodule to latest status
pc-bios/s390-ccw: Add code for virtio feature negotiation
pc-bios/s390-ccw: Remove unused structs from virtio.h
pc-bios/s390-ccw: Move byteswap functions to a separate header
pc-bios/s390-ccw: Add a write() function for stdio
...

Conflicts:
target/s390x/kvm.c

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+2832 -509
+1 -1
Makefile
··· 553 553 qemu-icon.bmp qemu_logo_no_text.svg \ 554 554 bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ 555 555 multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin \ 556 - s390-ccw.img \ 556 + s390-ccw.img s390-netboot.img \ 557 557 spapr-rtas.bin slof.bin skiboot.lid \ 558 558 palcode-clipper \ 559 559 u-boot.e500 \
+1 -1
configure
··· 6231 6231 echo "TARGET_ABI32=y" >> $config_target_mak 6232 6232 ;; 6233 6233 s390x) 6234 - gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml s390-virt.xml" 6234 + gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml s390-virt.xml s390-gs.xml" 6235 6235 ;; 6236 6236 tilegx) 6237 6237 ;;
+14
gdb-xml/s390-gs.xml
··· 1 + <?xml version="1.0"?> 2 + <!-- Copyright 2017 IBM Corp. 3 + 4 + This work is licensed under the terms of the GNU GPL, version 2 or 5 + (at your option) any later version. See the COPYING file in the 6 + top-level directory. --> 7 + 8 + <!DOCTYPE feature SYSTEM "gdb-target.dtd"> 9 + <feature name="org.gnu.gdb.s390.gs"> 10 + <reg name="gs_reserved" bitsize="64" type="uint64" group="system"/> 11 + <reg name="gsd" bitsize="64" type="uint64" group="system"/> 12 + <reg name="gssm" bitsize="64" type="uint64" group="system"/> 13 + <reg name="gsepla" bitsize="64" type="data_ptr" group="system"/> 14 + </feature>
+16
hmp-commands-info.hx
··· 777 777 Display the value of a storage key (s390 only) 778 778 ETEXI 779 779 780 + #if defined(TARGET_S390X) 781 + { 782 + .name = "cmma", 783 + .args_type = "addr:l,count:l?", 784 + .params = "address [count]", 785 + .help = "Display the values of the CMMA storage attributes for a range of pages", 786 + .cmd = hmp_info_cmma, 787 + }, 788 + #endif 789 + 790 + STEXI 791 + @item info cmma @var{address} 792 + @findex cmma 793 + Display the values of the CMMA storage attributes for a range of pages (s390 only) 794 + ETEXI 795 + 780 796 { 781 797 .name = "dump", 782 798 .args_type = "",
+16
hmp-commands.hx
··· 1153 1153 Save guest storage keys to a file. 1154 1154 ETEXI 1155 1155 1156 + #if defined(TARGET_S390X) 1157 + { 1158 + .name = "migration_mode", 1159 + .args_type = "mode:i", 1160 + .params = "mode", 1161 + .help = "Enables or disables migration mode\n", 1162 + .cmd = hmp_migrationmode, 1163 + }, 1164 + #endif 1165 + 1166 + STEXI 1167 + @item migration_mode @var{mode} 1168 + @findex migration_mode 1169 + Enables or disables migration mode. 1170 + ETEXI 1171 + 1156 1172 { 1157 1173 .name = "snapshot_blkdev", 1158 1174 .args_type = "reuse:-n,device:B,snapshot-file:s?,format:s?",
+105 -2
hw/intc/s390_flic.c
··· 13 13 #include "qemu/osdep.h" 14 14 #include "qemu/error-report.h" 15 15 #include "hw/sysbus.h" 16 + #include "hw/s390x/ioinst.h" 16 17 #include "hw/s390x/s390_flic.h" 18 + #include "hw/s390x/css.h" 17 19 #include "trace.h" 20 + #include "cpu.h" 18 21 #include "hw/qdev.h" 19 22 #include "qapi/error.h" 20 23 #include "hw/s390x/s390-virtio-ccw.h" ··· 48 51 49 52 static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id, 50 53 uint8_t isc, bool swap, 51 - bool is_maskable) 54 + bool is_maskable, uint8_t flags) 52 55 { 53 56 /* nothing to do */ 54 57 return 0; ··· 79 82 return -ENOSYS; 80 83 } 81 84 85 + static int qemu_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc, 86 + uint16_t mode) 87 + { 88 + QEMUS390FLICState *flic = QEMU_S390_FLIC(fs); 89 + 90 + switch (mode) { 91 + case SIC_IRQ_MODE_ALL: 92 + flic->simm &= ~AIS_MODE_MASK(isc); 93 + flic->nimm &= ~AIS_MODE_MASK(isc); 94 + break; 95 + case SIC_IRQ_MODE_SINGLE: 96 + flic->simm |= AIS_MODE_MASK(isc); 97 + flic->nimm &= ~AIS_MODE_MASK(isc); 98 + break; 99 + default: 100 + return -EINVAL; 101 + } 102 + 103 + return 0; 104 + } 105 + 106 + static int qemu_s390_inject_airq(S390FLICState *fs, uint8_t type, 107 + uint8_t isc, uint8_t flags) 108 + { 109 + QEMUS390FLICState *flic = QEMU_S390_FLIC(fs); 110 + bool flag = flags & S390_ADAPTER_SUPPRESSIBLE; 111 + uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI; 112 + 113 + if (flag && (flic->nimm & AIS_MODE_MASK(isc))) { 114 + trace_qemu_s390_airq_suppressed(type, isc); 115 + return 0; 116 + } 117 + 118 + s390_io_interrupt(0, 0, 0, io_int_word); 119 + 120 + if (flag && (flic->simm & AIS_MODE_MASK(isc))) { 121 + flic->nimm |= AIS_MODE_MASK(isc); 122 + trace_qemu_s390_suppress_airq(isc, "Single-Interruption Mode", 123 + "NO-Interruptions Mode"); 124 + } 125 + 126 + return 0; 127 + } 128 + 129 + static void qemu_s390_flic_reset(DeviceState *dev) 130 + { 131 + QEMUS390FLICState *flic = QEMU_S390_FLIC(dev); 132 + 133 + flic->simm = 0; 134 + flic->nimm = 0; 135 + } 136 + 137 + bool ais_needed(void *opaque) 138 + { 139 + S390FLICState *s = opaque; 140 + 141 + return s->ais_supported; 142 + } 143 + 144 + static const VMStateDescription qemu_s390_flic_vmstate = { 145 + .name = "qemu-s390-flic", 146 + .version_id = 1, 147 + .minimum_version_id = 1, 148 + .needed = ais_needed, 149 + .fields = (VMStateField[]) { 150 + VMSTATE_UINT8(simm, QEMUS390FLICState), 151 + VMSTATE_UINT8(nimm, QEMUS390FLICState), 152 + VMSTATE_END_OF_LIST() 153 + } 154 + }; 155 + 82 156 static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) 83 157 { 158 + DeviceClass *dc = DEVICE_CLASS(oc); 84 159 S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); 85 160 161 + dc->reset = qemu_s390_flic_reset; 162 + dc->vmsd = &qemu_s390_flic_vmstate; 86 163 fsc->register_io_adapter = qemu_s390_register_io_adapter; 87 164 fsc->io_adapter_map = qemu_s390_io_adapter_map; 88 165 fsc->add_adapter_routes = qemu_s390_add_adapter_routes; 89 166 fsc->release_adapter_routes = qemu_s390_release_adapter_routes; 90 167 fsc->clear_io_irq = qemu_s390_clear_io_flic; 168 + fsc->modify_ais_mode = qemu_s390_modify_ais_mode; 169 + fsc->inject_airq = qemu_s390_inject_airq; 91 170 } 92 171 93 172 static Property s390_flic_common_properties[] = { ··· 98 177 99 178 static void s390_flic_common_realize(DeviceState *dev, Error **errp) 100 179 { 101 - uint32_t max_batch = S390_FLIC_COMMON(dev)->adapter_routes_max_batch; 180 + S390FLICState *fs = S390_FLIC_COMMON(dev); 181 + uint32_t max_batch = fs->adapter_routes_max_batch; 102 182 103 183 if (max_batch > ADAPTER_ROUTES_MAX_GSI) { 104 184 error_setg(errp, "flic property adapter_routes_max_batch too big" 105 185 " (%d > %d)", max_batch, ADAPTER_ROUTES_MAX_GSI); 186 + return; 106 187 } 188 + 189 + fs->ais_supported = s390_has_feat(S390_FEAT_ADAPTER_INT_SUPPRESSION); 107 190 } 108 191 109 192 static void s390_flic_class_init(ObjectClass *oc, void *data) ··· 138 221 139 222 type_init(qemu_s390_flic_register_types) 140 223 224 + static bool adapter_info_so_needed(void *opaque) 225 + { 226 + return css_migration_enabled(); 227 + } 228 + 229 + const VMStateDescription vmstate_adapter_info_so = { 230 + .name = "s390_adapter_info/summary_offset", 231 + .version_id = 1, 232 + .minimum_version_id = 1, 233 + .needed = adapter_info_so_needed, 234 + .fields = (VMStateField[]) { 235 + VMSTATE_UINT32(summary_offset, AdapterInfo), 236 + VMSTATE_END_OF_LIST() 237 + } 238 + }; 239 + 141 240 const VMStateDescription vmstate_adapter_info = { 142 241 .name = "s390_adapter_info", 143 242 .version_id = 1, ··· 151 250 */ 152 251 VMSTATE_END_OF_LIST() 153 252 }, 253 + .subsections = (const VMStateDescription * []) { 254 + &vmstate_adapter_info_so, 255 + NULL 256 + } 154 257 }; 155 258 156 259 const VMStateDescription vmstate_adapter_routes = {
+135 -2
hw/intc/s390_flic_kvm.c
··· 20 20 #include "sysemu/kvm.h" 21 21 #include "hw/s390x/s390_flic.h" 22 22 #include "hw/s390x/adapter.h" 23 + #include "hw/s390x/css.h" 23 24 #include "trace.h" 24 25 25 26 #define FLIC_SAVE_INITIAL_SIZE getpagesize() ··· 149 150 return rc ? -errno : 0; 150 151 } 151 152 153 + static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc, 154 + uint16_t mode) 155 + { 156 + KVMS390FLICState *flic = KVM_S390_FLIC(fs); 157 + struct kvm_s390_ais_req req = { 158 + .isc = isc, 159 + .mode = mode, 160 + }; 161 + struct kvm_device_attr attr = { 162 + .group = KVM_DEV_FLIC_AISM, 163 + .addr = (uint64_t)&req, 164 + }; 165 + 166 + if (!fs->ais_supported) { 167 + return -ENOSYS; 168 + } 169 + 170 + return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0; 171 + } 172 + 173 + static int kvm_s390_inject_airq(S390FLICState *fs, uint8_t type, 174 + uint8_t isc, uint8_t flags) 175 + { 176 + KVMS390FLICState *flic = KVM_S390_FLIC(fs); 177 + uint32_t id = css_get_adapter_id(type, isc); 178 + struct kvm_device_attr attr = { 179 + .group = KVM_DEV_FLIC_AIRQ_INJECT, 180 + .attr = id, 181 + }; 182 + 183 + if (!fs->ais_supported) { 184 + return -ENOSYS; 185 + } 186 + 187 + return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0; 188 + } 189 + 152 190 /** 153 191 * __get_all_irqs - store all pending irqs in buffer 154 192 * @flic: pointer to flic device state ··· 186 224 187 225 static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id, 188 226 uint8_t isc, bool swap, 189 - bool is_maskable) 227 + bool is_maskable, uint8_t flags) 190 228 { 191 229 struct kvm_s390_io_adapter adapter = { 192 230 .id = id, 193 231 .isc = isc, 194 232 .maskable = is_maskable, 195 233 .swap = swap, 234 + .flags = flags, 196 235 }; 197 236 KVMS390FLICState *flic = KVM_S390_FLIC(fs); 198 237 int r; ··· 374 413 return r; 375 414 } 376 415 416 + typedef struct KVMS390FLICStateMigTmp { 417 + KVMS390FLICState *parent; 418 + uint8_t simm; 419 + uint8_t nimm; 420 + } KVMS390FLICStateMigTmp; 421 + 422 + static void kvm_flic_ais_pre_save(void *opaque) 423 + { 424 + KVMS390FLICStateMigTmp *tmp = opaque; 425 + KVMS390FLICState *flic = tmp->parent; 426 + struct kvm_s390_ais_all ais; 427 + struct kvm_device_attr attr = { 428 + .group = KVM_DEV_FLIC_AISM_ALL, 429 + .addr = (uint64_t)&ais, 430 + .attr = sizeof(ais), 431 + }; 432 + 433 + if (ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr)) { 434 + error_report("Failed to retrieve kvm flic ais states"); 435 + return; 436 + } 437 + 438 + tmp->simm = ais.simm; 439 + tmp->nimm = ais.nimm; 440 + } 441 + 442 + static int kvm_flic_ais_post_load(void *opaque, int version_id) 443 + { 444 + KVMS390FLICStateMigTmp *tmp = opaque; 445 + KVMS390FLICState *flic = tmp->parent; 446 + struct kvm_s390_ais_all ais = { 447 + .simm = tmp->simm, 448 + .nimm = tmp->nimm, 449 + }; 450 + struct kvm_device_attr attr = { 451 + .group = KVM_DEV_FLIC_AISM_ALL, 452 + .addr = (uint64_t)&ais, 453 + }; 454 + 455 + /* This can happen when the user mis-configures its guests in an 456 + * incompatible fashion or without a CPU model. For example using 457 + * qemu with -cpu host (which is not migration safe) and do a 458 + * migration from a host that has AIS to a host that has no AIS. 459 + * In that case the target system will reject the migration here. 460 + */ 461 + if (!ais_needed(flic)) { 462 + return -ENOSYS; 463 + } 464 + 465 + return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0; 466 + } 467 + 468 + static const VMStateDescription kvm_s390_flic_ais_tmp = { 469 + .name = "s390-flic-ais-tmp", 470 + .pre_save = kvm_flic_ais_pre_save, 471 + .post_load = kvm_flic_ais_post_load, 472 + .fields = (VMStateField[]) { 473 + VMSTATE_UINT8(simm, KVMS390FLICStateMigTmp), 474 + VMSTATE_UINT8(nimm, KVMS390FLICStateMigTmp), 475 + VMSTATE_END_OF_LIST() 476 + } 477 + }; 478 + 479 + static const VMStateDescription kvm_s390_flic_vmstate_ais = { 480 + .name = "s390-flic/ais", 481 + .version_id = 1, 482 + .minimum_version_id = 1, 483 + .needed = ais_needed, 484 + .fields = (VMStateField[]) { 485 + VMSTATE_WITH_TMP(KVMS390FLICState, KVMS390FLICStateMigTmp, 486 + kvm_s390_flic_ais_tmp), 487 + VMSTATE_END_OF_LIST() 488 + } 489 + }; 490 + 377 491 static const VMStateDescription kvm_s390_flic_vmstate = { 492 + /* should have been like kvm-s390-flic, 493 + * can't change without breaking compat */ 378 494 .name = "s390-flic", 379 495 .version_id = FLIC_SAVEVM_VERSION, 380 496 .minimum_version_id = FLIC_SAVEVM_VERSION, ··· 389 505 .flags = VMS_SINGLE, 390 506 }, 391 507 VMSTATE_END_OF_LIST() 508 + }, 509 + .subsections = (const VMStateDescription * []) { 510 + &kvm_s390_flic_vmstate_ais, 511 + NULL 392 512 } 393 513 }; 394 514 ··· 436 556 test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ; 437 557 flic_state->clear_io_supported = !ioctl(flic_state->fd, 438 558 KVM_HAS_DEVICE_ATTR, test_attr); 439 - 440 559 return; 441 560 fail: 442 561 error_propagate(errp, errp_local); ··· 445 564 static void kvm_s390_flic_reset(DeviceState *dev) 446 565 { 447 566 KVMS390FLICState *flic = KVM_S390_FLIC(dev); 567 + S390FLICState *fs = S390_FLIC_COMMON(dev); 448 568 struct kvm_device_attr attr = { 449 569 .group = KVM_DEV_FLIC_CLEAR_IRQS, 450 570 }; 451 571 int rc = 0; 572 + uint8_t isc; 452 573 453 574 if (flic->fd == -1) { 454 575 return; ··· 456 577 457 578 flic_disable_wait_pfault(flic); 458 579 580 + if (fs->ais_supported) { 581 + for (isc = 0; isc <= MAX_ISC; isc++) { 582 + rc = kvm_s390_modify_ais_mode(fs, isc, SIC_IRQ_MODE_ALL); 583 + if (rc) { 584 + error_report("Failed to reset ais mode for isc %d: %s", 585 + isc, strerror(-rc)); 586 + } 587 + } 588 + } 589 + 459 590 rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); 460 591 if (rc) { 461 592 trace_flic_reset_failed(errno); ··· 478 609 fsc->add_adapter_routes = kvm_s390_add_adapter_routes; 479 610 fsc->release_adapter_routes = kvm_s390_release_adapter_routes; 480 611 fsc->clear_io_irq = kvm_s390_clear_io_flic; 612 + fsc->modify_ais_mode = kvm_s390_modify_ais_mode; 613 + fsc->inject_airq = kvm_s390_inject_airq; 481 614 } 482 615 483 616 static const TypeInfo kvm_s390_flic_info = {
+4
hw/intc/trace-events
··· 73 73 flic_no_device_api(int err) "flic: no Device Contral API support %d" 74 74 flic_reset_failed(int err) "flic: reset failed %d" 75 75 76 + # hw/intc/s390_flic.c 77 + qemu_s390_airq_suppressed(uint8_t type, uint8_t isc) "flic: adapter I/O interrupt suppressed (type %x isc %x)" 78 + qemu_s390_suppress_airq(uint8_t isc, const char *from, const char *to) "flic: for isc %x, suppress airq by modifying ais mode from %s to %s" 79 + 76 80 # hw/intc/aspeed_vic.c 77 81 aspeed_vic_set_irq(int irq, int level) "Enabling IRQ %d: %d" 78 82 aspeed_vic_update_fiq(int flags) "Raising FIQ: %d"
+2
hw/s390x/Makefile.objs
··· 13 13 obj-y += ccw-device.o 14 14 obj-y += s390-pci-bus.o s390-pci-inst.o 15 15 obj-y += s390-skeys.o 16 + obj-y += s390-stattrib.o 16 17 obj-$(CONFIG_KVM) += s390-skeys-kvm.o 18 + obj-$(CONFIG_KVM) += s390-stattrib-kvm.o 17 19 obj-y += s390-ccw.o
+1 -1
hw/s390x/css-bridge.c
··· 110 110 qbus_set_hotplug_handler(bus, dev, &error_abort); 111 111 112 112 css_register_io_adapters(CSS_IO_ADAPTER_VIRTIO, true, false, 113 - &error_abort); 113 + 0, &error_abort); 114 114 115 115 return cbus; 116 116 }
+177 -19
hw/s390x/css.c
··· 29 29 QTAILQ_ENTRY(CrwContainer) sibling; 30 30 } CrwContainer; 31 31 32 + static const VMStateDescription vmstate_crw = { 33 + .name = "s390_crw", 34 + .version_id = 1, 35 + .minimum_version_id = 1, 36 + .fields = (VMStateField[]) { 37 + VMSTATE_UINT16(flags, CRW), 38 + VMSTATE_UINT16(rsid, CRW), 39 + VMSTATE_END_OF_LIST() 40 + }, 41 + }; 42 + 43 + static const VMStateDescription vmstate_crw_container = { 44 + .name = "s390_crw_container", 45 + .version_id = 1, 46 + .minimum_version_id = 1, 47 + .fields = (VMStateField[]) { 48 + VMSTATE_STRUCT(crw, CrwContainer, 0, vmstate_crw, CRW), 49 + VMSTATE_END_OF_LIST() 50 + }, 51 + }; 52 + 32 53 typedef struct ChpInfo { 33 54 uint8_t in_use; 34 55 uint8_t type; 35 56 uint8_t is_virtual; 36 57 } ChpInfo; 58 + 59 + static const VMStateDescription vmstate_chp_info = { 60 + .name = "s390_chp_info", 61 + .version_id = 1, 62 + .minimum_version_id = 1, 63 + .fields = (VMStateField[]) { 64 + VMSTATE_UINT8(in_use, ChpInfo), 65 + VMSTATE_UINT8(type, ChpInfo), 66 + VMSTATE_UINT8(is_virtual, ChpInfo), 67 + VMSTATE_END_OF_LIST() 68 + } 69 + }; 37 70 38 71 typedef struct SubchSet { 39 72 SubchDev *sch[MAX_SCHID + 1]; ··· 132 165 } 133 166 }; 134 167 168 + static const VMStateDescription vmstate_orb = { 169 + .name = "s390_orb", 170 + .version_id = 1, 171 + .minimum_version_id = 1, 172 + .fields = (VMStateField[]) { 173 + VMSTATE_UINT32(intparm, ORB), 174 + VMSTATE_UINT16(ctrl0, ORB), 175 + VMSTATE_UINT8(lpm, ORB), 176 + VMSTATE_UINT8(ctrl1, ORB), 177 + VMSTATE_UINT32(cpa, ORB), 178 + VMSTATE_END_OF_LIST() 179 + } 180 + }; 181 + 182 + static bool vmstate_schdev_orb_needed(void *opaque) 183 + { 184 + return css_migration_enabled(); 185 + } 186 + 187 + static const VMStateDescription vmstate_schdev_orb = { 188 + .name = "s390_subch_dev/orb", 189 + .version_id = 1, 190 + .minimum_version_id = 1, 191 + .needed = vmstate_schdev_orb_needed, 192 + .fields = (VMStateField[]) { 193 + VMSTATE_STRUCT(orb, SubchDev, 1, vmstate_orb, ORB), 194 + VMSTATE_END_OF_LIST() 195 + } 196 + }; 197 + 135 198 static int subch_dev_post_load(void *opaque, int version_id); 136 199 static void subch_dev_pre_save(void *opaque); 137 200 ··· 160 223 VMSTATE_BOOL(ccw_fmt_1, SubchDev), 161 224 VMSTATE_UINT8(ccw_no_data_cnt, SubchDev), 162 225 VMSTATE_END_OF_LIST() 226 + }, 227 + .subsections = (const VMStateDescription * []) { 228 + &vmstate_schdev_orb, 229 + NULL 163 230 } 164 231 }; 165 232 ··· 221 288 ChpInfo chpids[MAX_CHPID + 1]; 222 289 } CssImage; 223 290 291 + static const VMStateDescription vmstate_css_img = { 292 + .name = "s390_css_img", 293 + .version_id = 1, 294 + .minimum_version_id = 1, 295 + .fields = (VMStateField[]) { 296 + /* Subchannel sets have no relevant state. */ 297 + VMSTATE_STRUCT_ARRAY(chpids, CssImage, MAX_CHPID + 1, 0, 298 + vmstate_chp_info, ChpInfo), 299 + VMSTATE_END_OF_LIST() 300 + } 301 + 302 + }; 303 + 224 304 typedef struct IoAdapter { 225 305 uint32_t id; 226 306 uint8_t type; 227 307 uint8_t isc; 308 + uint8_t flags; 228 309 } IoAdapter; 229 310 230 311 typedef struct ChannelSubSys { ··· 238 319 uint64_t chnmon_area; 239 320 CssImage *css[MAX_CSSID + 1]; 240 321 uint8_t default_cssid; 322 + /* don't migrate, see css_register_io_adapters */ 241 323 IoAdapter *io_adapters[CSS_IO_ADAPTER_TYPE_NUMS][MAX_ISC + 1]; 324 + /* don't migrate, see get_indicator and IndAddrPtrTmp */ 242 325 QTAILQ_HEAD(, IndAddr) indicator_addresses; 243 326 } ChannelSubSys; 244 327 328 + static const VMStateDescription vmstate_css = { 329 + .name = "s390_css", 330 + .version_id = 1, 331 + .minimum_version_id = 1, 332 + .fields = (VMStateField[]) { 333 + VMSTATE_QTAILQ_V(pending_crws, ChannelSubSys, 1, vmstate_crw_container, 334 + CrwContainer, sibling), 335 + VMSTATE_BOOL(sei_pending, ChannelSubSys), 336 + VMSTATE_BOOL(do_crw_mchk, ChannelSubSys), 337 + VMSTATE_BOOL(crws_lost, ChannelSubSys), 338 + /* These were kind of migrated by virtio */ 339 + VMSTATE_UINT8(max_cssid, ChannelSubSys), 340 + VMSTATE_UINT8(max_ssid, ChannelSubSys), 341 + VMSTATE_BOOL(chnmon_active, ChannelSubSys), 342 + VMSTATE_UINT64(chnmon_area, ChannelSubSys), 343 + VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(css, ChannelSubSys, MAX_CSSID + 1, 344 + 0, vmstate_css_img, CssImage), 345 + VMSTATE_UINT8(default_cssid, ChannelSubSys), 346 + VMSTATE_END_OF_LIST() 347 + } 348 + }; 349 + 245 350 static ChannelSubSys channel_subsys = { 246 351 .pending_crws = QTAILQ_HEAD_INITIALIZER(channel_subsys.pending_crws), 247 352 .do_crw_mchk = true, ··· 281 386 css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s); 282 387 } 283 388 389 + if (css_migration_enabled()) { 390 + /* No compat voodoo to do ;) */ 391 + return 0; 392 + } 284 393 /* 285 394 * Hack alert. If we don't migrate the channel subsystem status 286 395 * we still need to find out if the guest enabled mss/mcss-e. ··· 299 408 return 0; 300 409 } 301 410 411 + void css_register_vmstate(void) 412 + { 413 + vmstate_register(NULL, 0, &vmstate_css, &channel_subsys); 414 + } 415 + 302 416 IndAddr *get_indicator(hwaddr ind_addr, int len) 303 417 { 304 418 IndAddr *indicator; ··· 392 506 * 393 507 * @swap: an indication if byte swap is needed. 394 508 * @maskable: an indication if the adapter is subject to the mask operation. 509 + * @flags: further characteristics of the adapter. 510 + * e.g. suppressible, an indication if the adapter is subject to AIS. 395 511 * @errp: location to store error information. 396 512 */ 397 513 void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, 398 - Error **errp) 514 + uint8_t flags, Error **errp) 399 515 { 400 516 uint32_t id; 401 517 int ret, isc; ··· 413 529 414 530 for (isc = 0; isc <= MAX_ISC; isc++) { 415 531 id = (type << 3) | isc; 416 - ret = fsc->register_io_adapter(fs, id, isc, swap, maskable); 532 + ret = fsc->register_io_adapter(fs, id, isc, swap, maskable, flags); 417 533 if (ret == 0) { 418 534 adapter = g_new0(IoAdapter, 1); 419 535 adapter->id = id; 420 536 adapter->isc = isc; 421 537 adapter->type = type; 538 + adapter->flags = flags; 422 539 channel_subsys.io_adapters[type][isc] = adapter; 423 540 } else { 424 541 error_setg_errno(errp, -ret, "Unexpected error %d when " ··· 517 634 } 518 635 } 519 636 520 - void css_adapter_interrupt(uint8_t isc) 637 + int css_do_sic(CPUS390XState *env, uint8_t isc, uint16_t mode) 521 638 { 639 + S390FLICState *fs = s390_get_flic(); 640 + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); 641 + int r; 642 + 643 + if (env->psw.mask & PSW_MASK_PSTATE) { 644 + r = -PGM_PRIVILEGED; 645 + goto out; 646 + } 647 + 648 + trace_css_do_sic(mode, isc); 649 + switch (mode) { 650 + case SIC_IRQ_MODE_ALL: 651 + case SIC_IRQ_MODE_SINGLE: 652 + break; 653 + default: 654 + r = -PGM_OPERAND; 655 + goto out; 656 + } 657 + 658 + r = fsc->modify_ais_mode(fs, isc, mode) ? -PGM_OPERATION : 0; 659 + out: 660 + return r; 661 + } 662 + 663 + void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc) 664 + { 665 + S390FLICState *fs = s390_get_flic(); 666 + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); 522 667 uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI; 668 + IoAdapter *adapter = channel_subsys.io_adapters[type][isc]; 669 + 670 + if (!adapter) { 671 + return; 672 + } 523 673 524 674 trace_css_adapter_interrupt(isc); 525 - s390_io_interrupt(0, 0, 0, io_int_word); 675 + if (fs->ais_supported) { 676 + if (fsc->inject_airq(fs, type, isc, adapter->flags)) { 677 + error_report("Failed to inject airq with AIS supported"); 678 + exit(1); 679 + } 680 + } else { 681 + s390_io_interrupt(0, 0, 0, io_int_word); 682 + } 526 683 } 527 684 528 685 static void sch_handle_clear_func(SubchDev *sch) ··· 752 909 return ret; 753 910 } 754 911 755 - static void sch_handle_start_func_virtual(SubchDev *sch, ORB *orb) 912 + static void sch_handle_start_func_virtual(SubchDev *sch) 756 913 { 757 914 758 915 PMCW *p = &sch->curr_status.pmcw; ··· 766 923 767 924 if (!(s->ctrl & SCSW_ACTL_SUSP)) { 768 925 /* Start Function triggered via ssch, i.e. we have an ORB */ 926 + ORB *orb = &sch->orb; 769 927 s->cstat = 0; 770 928 s->dstat = 0; 771 929 /* Look at the orb and try to execute the channel program. */ 772 - assert(orb != NULL); /* resume does not pass an orb */ 773 930 p->intparm = orb->intparm; 774 931 if (!(orb->lpm & path)) { 775 932 /* Generate a deferred cc 3 condition. */ ··· 783 940 sch->ccw_no_data_cnt = 0; 784 941 suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND); 785 942 } else { 786 - /* Start Function resumed via rsch, i.e. we don't have an 787 - * ORB */ 943 + /* Start Function resumed via rsch */ 788 944 s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND); 789 945 /* The channel program had been suspended before. */ 790 946 suspend_allowed = true; ··· 854 1010 855 1011 } 856 1012 857 - static int sch_handle_start_func_passthrough(SubchDev *sch, ORB *orb) 1013 + static int sch_handle_start_func_passthrough(SubchDev *sch) 858 1014 { 859 1015 860 1016 PMCW *p = &sch->curr_status.pmcw; 861 1017 SCSW *s = &sch->curr_status.scsw; 862 1018 int ret; 863 1019 1020 + ORB *orb = &sch->orb; 864 1021 if (!(s->ctrl & SCSW_ACTL_SUSP)) { 865 1022 assert(orb != NULL); 866 1023 p->intparm = orb->intparm; ··· 905 1062 * read/writes) asynchronous later on if we start supporting more than 906 1063 * our current very simple devices. 907 1064 */ 908 - int do_subchannel_work_virtual(SubchDev *sch, ORB *orb) 1065 + int do_subchannel_work_virtual(SubchDev *sch) 909 1066 { 910 1067 911 1068 SCSW *s = &sch->curr_status.scsw; ··· 916 1073 sch_handle_halt_func(sch); 917 1074 } else if (s->ctrl & SCSW_FCTL_START_FUNC) { 918 1075 /* Triggered by both ssch and rsch. */ 919 - sch_handle_start_func_virtual(sch, orb); 1076 + sch_handle_start_func_virtual(sch); 920 1077 } else { 921 1078 /* Cannot happen. */ 922 1079 return 0; ··· 925 1082 return 0; 926 1083 } 927 1084 928 - int do_subchannel_work_passthrough(SubchDev *sch, ORB *orb) 1085 + int do_subchannel_work_passthrough(SubchDev *sch) 929 1086 { 930 1087 int ret; 931 1088 SCSW *s = &sch->curr_status.scsw; ··· 939 1096 sch_handle_halt_func(sch); 940 1097 ret = 0; 941 1098 } else if (s->ctrl & SCSW_FCTL_START_FUNC) { 942 - ret = sch_handle_start_func_passthrough(sch, orb); 1099 + ret = sch_handle_start_func_passthrough(sch); 943 1100 } else { 944 1101 /* Cannot happen. */ 945 1102 return -ENODEV; ··· 948 1105 return ret; 949 1106 } 950 1107 951 - static int do_subchannel_work(SubchDev *sch, ORB *orb) 1108 + static int do_subchannel_work(SubchDev *sch) 952 1109 { 953 1110 if (sch->do_subchannel_work) { 954 - return sch->do_subchannel_work(sch, orb); 1111 + return sch->do_subchannel_work(sch); 955 1112 } else { 956 1113 return -EINVAL; 957 1114 } ··· 1158 1315 s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL); 1159 1316 s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND; 1160 1317 1161 - do_subchannel_work(sch, NULL); 1318 + do_subchannel_work(sch); 1162 1319 ret = 0; 1163 1320 1164 1321 out: ··· 1199 1356 } 1200 1357 s->ctrl |= SCSW_ACTL_HALT_PEND; 1201 1358 1202 - do_subchannel_work(sch, NULL); 1359 + do_subchannel_work(sch); 1203 1360 ret = 0; 1204 1361 1205 1362 out: ··· 1268 1425 if (channel_subsys.chnmon_active) { 1269 1426 css_update_chnmon(sch); 1270 1427 } 1428 + sch->orb = *orb; 1271 1429 sch->channel_prog = orb->cpa; 1272 1430 /* Trigger the start function. */ 1273 1431 s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND); 1274 1432 s->flags &= ~SCSW_FLAGS_MASK_PNO; 1275 1433 1276 - ret = do_subchannel_work(sch, orb); 1434 + ret = do_subchannel_work(sch); 1277 1435 1278 1436 out: 1279 1437 return ret; ··· 1552 1710 } 1553 1711 1554 1712 s->ctrl |= SCSW_ACTL_RESUME_PEND; 1555 - do_subchannel_work(sch, NULL); 1713 + do_subchannel_work(sch); 1556 1714 ret = 0; 1557 1715 1558 1716 out:
+3 -2
hw/s390x/s390-pci-bus.c
··· 500 500 0x80 >> ((ind_bit + vec) % 8)); 501 501 if (!set_ind_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8, 502 502 0x80 >> (sum_bit % 8))) { 503 - css_adapter_interrupt(pbdev->isc); 503 + css_adapter_interrupt(CSS_IO_ADAPTER_PCI, pbdev->isc); 504 504 } 505 505 } 506 506 ··· 579 579 QTAILQ_INIT(&s->pending_sei); 580 580 QTAILQ_INIT(&s->zpci_devs); 581 581 582 - css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, &error_abort); 582 + css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, 583 + S390_ADAPTER_SUPPRESSIBLE, &error_abort); 583 584 584 585 return 0; 585 586 }
+190
hw/s390x/s390-stattrib-kvm.c
··· 1 + /* 2 + * s390 storage attributes device -- KVM object 3 + * 4 + * Copyright 2016 IBM Corp. 5 + * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.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 "hw/boards.h" 14 + #include "migration/qemu-file.h" 15 + #include "hw/s390x/storage-attributes.h" 16 + #include "qemu/error-report.h" 17 + #include "sysemu/kvm.h" 18 + #include "exec/ram_addr.h" 19 + #include "cpu.h" 20 + 21 + Object *kvm_s390_stattrib_create(void) 22 + { 23 + if (kvm_enabled() && 24 + kvm_check_extension(kvm_state, KVM_CAP_S390_CMMA_MIGRATION)) { 25 + return object_new(TYPE_KVM_S390_STATTRIB); 26 + } 27 + return NULL; 28 + } 29 + 30 + static void kvm_s390_stattrib_instance_init(Object *obj) 31 + { 32 + KVMS390StAttribState *sas = KVM_S390_STATTRIB(obj); 33 + 34 + sas->still_dirty = 0; 35 + } 36 + 37 + static int kvm_s390_stattrib_read_helper(S390StAttribState *sa, 38 + uint64_t *start_gfn, 39 + uint32_t count, 40 + uint8_t *values, 41 + uint32_t flags) 42 + { 43 + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); 44 + int r; 45 + struct kvm_s390_cmma_log clog = { 46 + .values = (uint64_t)values, 47 + .start_gfn = *start_gfn, 48 + .count = count, 49 + .flags = flags, 50 + }; 51 + 52 + r = kvm_vm_ioctl(kvm_state, KVM_S390_GET_CMMA_BITS, &clog); 53 + if (r < 0) { 54 + error_report("KVM_S390_GET_CMMA_BITS failed: %s", strerror(-r)); 55 + return r; 56 + } 57 + 58 + *start_gfn = clog.start_gfn; 59 + sas->still_dirty = clog.remaining; 60 + return clog.count; 61 + } 62 + 63 + static int kvm_s390_stattrib_get_stattr(S390StAttribState *sa, 64 + uint64_t *start_gfn, 65 + uint32_t count, 66 + uint8_t *values) 67 + { 68 + return kvm_s390_stattrib_read_helper(sa, start_gfn, count, values, 0); 69 + } 70 + 71 + static int kvm_s390_stattrib_peek_stattr(S390StAttribState *sa, 72 + uint64_t start_gfn, 73 + uint32_t count, 74 + uint8_t *values) 75 + { 76 + return kvm_s390_stattrib_read_helper(sa, &start_gfn, count, values, 77 + KVM_S390_CMMA_PEEK); 78 + } 79 + 80 + static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa, 81 + uint64_t start_gfn, 82 + uint32_t count, 83 + uint8_t *values) 84 + { 85 + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); 86 + MachineState *machine = MACHINE(qdev_get_machine()); 87 + unsigned long max = machine->maxram_size / TARGET_PAGE_SIZE; 88 + 89 + if (start_gfn + count > max) { 90 + error_report("Out of memory bounds when setting storage attributes"); 91 + return -1; 92 + } 93 + if (!sas->incoming_buffer) { 94 + sas->incoming_buffer = g_malloc0(max); 95 + } 96 + 97 + memcpy(sas->incoming_buffer + start_gfn, values, count); 98 + 99 + return 0; 100 + } 101 + 102 + static void kvm_s390_stattrib_synchronize(S390StAttribState *sa) 103 + { 104 + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); 105 + MachineState *machine = MACHINE(qdev_get_machine()); 106 + unsigned long max = machine->maxram_size / TARGET_PAGE_SIZE; 107 + unsigned long cx, len = 1 << 19; 108 + int r; 109 + struct kvm_s390_cmma_log clog = { 110 + .flags = 0, 111 + .mask = ~0ULL, 112 + }; 113 + 114 + if (sas->incoming_buffer) { 115 + for (cx = 0; cx + len <= max; cx += len) { 116 + clog.start_gfn = cx; 117 + clog.count = len; 118 + clog.values = (uint64_t)(sas->incoming_buffer + cx * len); 119 + r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog); 120 + if (r) { 121 + error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r)); 122 + return; 123 + } 124 + } 125 + if (cx < max) { 126 + clog.start_gfn = cx; 127 + clog.count = max - cx; 128 + clog.values = (uint64_t)(sas->incoming_buffer + cx * len); 129 + r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog); 130 + if (r) { 131 + error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r)); 132 + } 133 + } 134 + g_free(sas->incoming_buffer); 135 + sas->incoming_buffer = NULL; 136 + } 137 + } 138 + 139 + static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val) 140 + { 141 + struct kvm_device_attr attr = { 142 + .group = KVM_S390_VM_MIGRATION, 143 + .attr = val, 144 + .addr = 0, 145 + }; 146 + return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); 147 + } 148 + 149 + static long long kvm_s390_stattrib_get_dirtycount(S390StAttribState *sa) 150 + { 151 + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); 152 + uint8_t val[8]; 153 + 154 + kvm_s390_stattrib_peek_stattr(sa, 0, 1, val); 155 + return sas->still_dirty; 156 + } 157 + 158 + static int kvm_s390_stattrib_get_active(S390StAttribState *sa) 159 + { 160 + return kvm_s390_cmma_active() && sa->migration_enabled; 161 + } 162 + 163 + static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data) 164 + { 165 + S390StAttribClass *sac = S390_STATTRIB_CLASS(oc); 166 + 167 + sac->get_stattr = kvm_s390_stattrib_get_stattr; 168 + sac->peek_stattr = kvm_s390_stattrib_peek_stattr; 169 + sac->set_stattr = kvm_s390_stattrib_set_stattr; 170 + sac->set_migrationmode = kvm_s390_stattrib_set_migrationmode; 171 + sac->get_dirtycount = kvm_s390_stattrib_get_dirtycount; 172 + sac->synchronize = kvm_s390_stattrib_synchronize; 173 + sac->get_active = kvm_s390_stattrib_get_active; 174 + } 175 + 176 + static const TypeInfo kvm_s390_stattrib_info = { 177 + .name = TYPE_KVM_S390_STATTRIB, 178 + .parent = TYPE_S390_STATTRIB, 179 + .instance_init = kvm_s390_stattrib_instance_init, 180 + .instance_size = sizeof(KVMS390StAttribState), 181 + .class_init = kvm_s390_stattrib_class_init, 182 + .class_size = sizeof(S390StAttribClass), 183 + }; 184 + 185 + static void kvm_s390_stattrib_register_types(void) 186 + { 187 + type_register_static(&kvm_s390_stattrib_info); 188 + } 189 + 190 + type_init(kvm_s390_stattrib_register_types)
+404
hw/s390x/s390-stattrib.c
··· 1 + /* 2 + * s390 storage attributes device 3 + * 4 + * Copyright 2016 IBM Corp. 5 + * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.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 "hw/boards.h" 14 + #include "qmp-commands.h" 15 + #include "migration/qemu-file.h" 16 + #include "migration/register.h" 17 + #include "hw/s390x/storage-attributes.h" 18 + #include "qemu/error-report.h" 19 + #include "sysemu/kvm.h" 20 + #include "exec/ram_addr.h" 21 + #include "qapi/error.h" 22 + 23 + #define CMMA_BLOCK_SIZE (1 << 10) 24 + 25 + #define STATTR_FLAG_EOS 0x01ULL 26 + #define STATTR_FLAG_MORE 0x02ULL 27 + #define STATTR_FLAG_ERROR 0x04ULL 28 + #define STATTR_FLAG_DONE 0x08ULL 29 + 30 + static S390StAttribState *s390_get_stattrib_device(void) 31 + { 32 + S390StAttribState *sas; 33 + 34 + sas = S390_STATTRIB(object_resolve_path_type("", TYPE_S390_STATTRIB, NULL)); 35 + assert(sas); 36 + return sas; 37 + } 38 + 39 + void s390_stattrib_init(void) 40 + { 41 + Object *obj; 42 + 43 + obj = kvm_s390_stattrib_create(); 44 + if (!obj) { 45 + obj = object_new(TYPE_QEMU_S390_STATTRIB); 46 + } 47 + 48 + object_property_add_child(qdev_get_machine(), TYPE_S390_STATTRIB, 49 + obj, NULL); 50 + object_unref(obj); 51 + 52 + qdev_init_nofail(DEVICE(obj)); 53 + } 54 + 55 + /* Console commands: */ 56 + 57 + void hmp_migrationmode(Monitor *mon, const QDict *qdict) 58 + { 59 + S390StAttribState *sas = s390_get_stattrib_device(); 60 + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); 61 + uint64_t what = qdict_get_int(qdict, "mode"); 62 + int r; 63 + 64 + r = sac->set_migrationmode(sas, what); 65 + if (r < 0) { 66 + monitor_printf(mon, "Error: %s", strerror(-r)); 67 + } 68 + } 69 + 70 + void hmp_info_cmma(Monitor *mon, const QDict *qdict) 71 + { 72 + S390StAttribState *sas = s390_get_stattrib_device(); 73 + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); 74 + uint64_t addr = qdict_get_int(qdict, "addr"); 75 + uint64_t buflen = qdict_get_try_int(qdict, "count", 8); 76 + uint8_t *vals; 77 + int cx, len; 78 + 79 + vals = g_try_malloc(buflen); 80 + if (!vals) { 81 + monitor_printf(mon, "Error: %s\n", strerror(errno)); 82 + return; 83 + } 84 + 85 + len = sac->peek_stattr(sas, addr / TARGET_PAGE_SIZE, buflen, vals); 86 + if (len < 0) { 87 + monitor_printf(mon, "Error: %s", strerror(-len)); 88 + goto out; 89 + } 90 + 91 + monitor_printf(mon, " CMMA attributes, " 92 + "pages %" PRIu64 "+%d (0x%" PRIx64 "):\n", 93 + addr / TARGET_PAGE_SIZE, len, addr & ~TARGET_PAGE_MASK); 94 + for (cx = 0; cx < len; cx++) { 95 + if (cx % 8 == 7) { 96 + monitor_printf(mon, "%02x\n", vals[cx]); 97 + } else { 98 + monitor_printf(mon, "%02x", vals[cx]); 99 + } 100 + } 101 + monitor_printf(mon, "\n"); 102 + 103 + out: 104 + g_free(vals); 105 + } 106 + 107 + /* Migration support: */ 108 + 109 + static int cmma_load(QEMUFile *f, void *opaque, int version_id) 110 + { 111 + S390StAttribState *sas = S390_STATTRIB(opaque); 112 + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); 113 + uint64_t count, cur_gfn; 114 + int flags, ret = 0; 115 + ram_addr_t addr; 116 + uint8_t *buf; 117 + 118 + while (!ret) { 119 + addr = qemu_get_be64(f); 120 + flags = addr & ~TARGET_PAGE_MASK; 121 + addr &= TARGET_PAGE_MASK; 122 + 123 + switch (flags) { 124 + case STATTR_FLAG_MORE: { 125 + cur_gfn = addr / TARGET_PAGE_SIZE; 126 + count = qemu_get_be64(f); 127 + buf = g_try_malloc(count); 128 + if (!buf) { 129 + error_report("cmma_load could not allocate memory"); 130 + ret = -ENOMEM; 131 + break; 132 + } 133 + 134 + qemu_get_buffer(f, buf, count); 135 + ret = sac->set_stattr(sas, cur_gfn, count, buf); 136 + if (ret < 0) { 137 + error_report("Error %d while setting storage attributes", ret); 138 + } 139 + g_free(buf); 140 + break; 141 + } 142 + case STATTR_FLAG_ERROR: { 143 + error_report("Storage attributes data is incomplete"); 144 + ret = -EINVAL; 145 + break; 146 + } 147 + case STATTR_FLAG_DONE: 148 + /* This is after the last pre-copied value has been sent, nothing 149 + * more will be sent after this. Pre-copy has finished, and we 150 + * are done flushing all the remaining values. Now the target 151 + * system is about to take over. We synchronize the buffer to 152 + * apply the actual correct values where needed. 153 + */ 154 + sac->synchronize(sas); 155 + break; 156 + case STATTR_FLAG_EOS: 157 + /* Normal exit */ 158 + return 0; 159 + default: 160 + error_report("Unexpected storage attribute flag data: %#x", flags); 161 + ret = -EINVAL; 162 + } 163 + } 164 + 165 + return ret; 166 + } 167 + 168 + static int cmma_save_setup(QEMUFile *f, void *opaque) 169 + { 170 + S390StAttribState *sas = S390_STATTRIB(opaque); 171 + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); 172 + int res; 173 + /* 174 + * Signal that we want to start a migration, thus needing PGSTE dirty 175 + * tracking. 176 + */ 177 + res = sac->set_migrationmode(sas, 1); 178 + if (res) { 179 + return res; 180 + } 181 + qemu_put_be64(f, STATTR_FLAG_EOS); 182 + return 0; 183 + } 184 + 185 + static void cmma_save_pending(QEMUFile *f, void *opaque, uint64_t max_size, 186 + uint64_t *non_postcopiable_pending, 187 + uint64_t *postcopiable_pending) 188 + { 189 + S390StAttribState *sas = S390_STATTRIB(opaque); 190 + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); 191 + long long res = sac->get_dirtycount(sas); 192 + 193 + if (res >= 0) { 194 + *non_postcopiable_pending += res; 195 + } 196 + } 197 + 198 + static int cmma_save(QEMUFile *f, void *opaque, int final) 199 + { 200 + S390StAttribState *sas = S390_STATTRIB(opaque); 201 + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); 202 + uint8_t *buf; 203 + int r, cx, reallen = 0, ret = 0; 204 + uint32_t buflen = 1 << 19; /* 512kB cover 2GB of guest memory */ 205 + uint64_t start_gfn = sas->migration_cur_gfn; 206 + 207 + buf = g_try_malloc(buflen); 208 + if (!buf) { 209 + error_report("Could not allocate memory to save storage attributes"); 210 + return -ENOMEM; 211 + } 212 + 213 + while (final ? 1 : qemu_file_rate_limit(f) == 0) { 214 + reallen = sac->get_stattr(sas, &start_gfn, buflen, buf); 215 + if (reallen < 0) { 216 + g_free(buf); 217 + return reallen; 218 + } 219 + 220 + ret = 1; 221 + if (!reallen) { 222 + break; 223 + } 224 + qemu_put_be64(f, (start_gfn << TARGET_PAGE_BITS) | STATTR_FLAG_MORE); 225 + qemu_put_be64(f, reallen); 226 + for (cx = 0; cx < reallen; cx++) { 227 + qemu_put_byte(f, buf[cx]); 228 + } 229 + if (!sac->get_dirtycount(sas)) { 230 + break; 231 + } 232 + } 233 + 234 + sas->migration_cur_gfn = start_gfn + reallen; 235 + g_free(buf); 236 + if (final) { 237 + qemu_put_be64(f, STATTR_FLAG_DONE); 238 + } 239 + qemu_put_be64(f, STATTR_FLAG_EOS); 240 + 241 + r = qemu_file_get_error(f); 242 + if (r < 0) { 243 + return r; 244 + } 245 + 246 + return ret; 247 + } 248 + 249 + static int cmma_save_iterate(QEMUFile *f, void *opaque) 250 + { 251 + return cmma_save(f, opaque, 0); 252 + } 253 + 254 + static int cmma_save_complete(QEMUFile *f, void *opaque) 255 + { 256 + return cmma_save(f, opaque, 1); 257 + } 258 + 259 + static void cmma_save_cleanup(void *opaque) 260 + { 261 + S390StAttribState *sas = S390_STATTRIB(opaque); 262 + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); 263 + sac->set_migrationmode(sas, 0); 264 + } 265 + 266 + static bool cmma_active(void *opaque) 267 + { 268 + S390StAttribState *sas = S390_STATTRIB(opaque); 269 + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); 270 + return sac->get_active(sas); 271 + } 272 + 273 + /* QEMU object: */ 274 + 275 + static void qemu_s390_stattrib_instance_init(Object *obj) 276 + { 277 + } 278 + 279 + static int qemu_s390_peek_stattr_stub(S390StAttribState *sa, uint64_t start_gfn, 280 + uint32_t count, uint8_t *values) 281 + { 282 + return 0; 283 + } 284 + static void qemu_s390_synchronize_stub(S390StAttribState *sa) 285 + { 286 + } 287 + static int qemu_s390_get_stattr_stub(S390StAttribState *sa, uint64_t *start_gfn, 288 + uint32_t count, uint8_t *values) 289 + { 290 + return 0; 291 + } 292 + static long long qemu_s390_get_dirtycount_stub(S390StAttribState *sa) 293 + { 294 + return 0; 295 + } 296 + static int qemu_s390_set_migrationmode_stub(S390StAttribState *sa, bool value) 297 + { 298 + return 0; 299 + } 300 + 301 + static int qemu_s390_get_active(S390StAttribState *sa) 302 + { 303 + return sa->migration_enabled; 304 + } 305 + 306 + static void qemu_s390_stattrib_class_init(ObjectClass *oc, void *data) 307 + { 308 + S390StAttribClass *sa_cl = S390_STATTRIB_CLASS(oc); 309 + 310 + sa_cl->synchronize = qemu_s390_synchronize_stub; 311 + sa_cl->get_stattr = qemu_s390_get_stattr_stub; 312 + sa_cl->set_stattr = qemu_s390_peek_stattr_stub; 313 + sa_cl->peek_stattr = qemu_s390_peek_stattr_stub; 314 + sa_cl->set_migrationmode = qemu_s390_set_migrationmode_stub; 315 + sa_cl->get_dirtycount = qemu_s390_get_dirtycount_stub; 316 + sa_cl->get_active = qemu_s390_get_active; 317 + } 318 + 319 + static const TypeInfo qemu_s390_stattrib_info = { 320 + .name = TYPE_QEMU_S390_STATTRIB, 321 + .parent = TYPE_S390_STATTRIB, 322 + .instance_init = qemu_s390_stattrib_instance_init, 323 + .instance_size = sizeof(QEMUS390StAttribState), 324 + .class_init = qemu_s390_stattrib_class_init, 325 + .class_size = sizeof(S390StAttribClass), 326 + }; 327 + 328 + /* Generic abstract object: */ 329 + 330 + static void s390_stattrib_realize(DeviceState *dev, Error **errp) 331 + { 332 + bool ambiguous = false; 333 + 334 + object_resolve_path_type("", TYPE_S390_STATTRIB, &ambiguous); 335 + if (ambiguous) { 336 + error_setg(errp, "storage_attributes device already exists"); 337 + } 338 + } 339 + 340 + static void s390_stattrib_class_init(ObjectClass *oc, void *data) 341 + { 342 + DeviceClass *dc = DEVICE_CLASS(oc); 343 + 344 + dc->hotpluggable = false; 345 + set_bit(DEVICE_CATEGORY_MISC, dc->categories); 346 + dc->realize = s390_stattrib_realize; 347 + } 348 + 349 + static inline bool s390_stattrib_get_migration_enabled(Object *obj, Error **e) 350 + { 351 + S390StAttribState *s = S390_STATTRIB(obj); 352 + 353 + return s->migration_enabled; 354 + } 355 + 356 + static inline void s390_stattrib_set_migration_enabled(Object *obj, bool value, 357 + Error **errp) 358 + { 359 + S390StAttribState *s = S390_STATTRIB(obj); 360 + 361 + s->migration_enabled = value; 362 + } 363 + 364 + static void s390_stattrib_instance_init(Object *obj) 365 + { 366 + S390StAttribState *sas = S390_STATTRIB(obj); 367 + SaveVMHandlers *ops; 368 + 369 + /* ops will always be freed by qemu when unregistering */ 370 + ops = g_new0(SaveVMHandlers, 1); 371 + 372 + ops->save_setup = cmma_save_setup; 373 + ops->save_live_iterate = cmma_save_iterate; 374 + ops->save_live_complete_precopy = cmma_save_complete; 375 + ops->save_live_pending = cmma_save_pending; 376 + ops->save_cleanup = cmma_save_cleanup; 377 + ops->load_state = cmma_load; 378 + ops->is_active = cmma_active; 379 + register_savevm_live(NULL, TYPE_S390_STATTRIB, 0, 0, ops, sas); 380 + 381 + object_property_add_bool(obj, "migration-enabled", 382 + s390_stattrib_get_migration_enabled, 383 + s390_stattrib_set_migration_enabled, NULL); 384 + object_property_set_bool(obj, true, "migration-enabled", NULL); 385 + sas->migration_cur_gfn = 0; 386 + } 387 + 388 + static const TypeInfo s390_stattrib_info = { 389 + .name = TYPE_S390_STATTRIB, 390 + .parent = TYPE_DEVICE, 391 + .instance_init = s390_stattrib_instance_init, 392 + .instance_size = sizeof(S390StAttribState), 393 + .class_init = s390_stattrib_class_init, 394 + .class_size = sizeof(S390StAttribClass), 395 + .abstract = true, 396 + }; 397 + 398 + static void s390_stattrib_register_types(void) 399 + { 400 + type_register_static(&s390_stattrib_info); 401 + type_register_static(&qemu_s390_stattrib_info); 402 + } 403 + 404 + type_init(s390_stattrib_register_types)
+67 -23
hw/s390x/s390-virtio-ccw.c
··· 24 24 #include "qemu/config-file.h" 25 25 #include "s390-pci-bus.h" 26 26 #include "hw/s390x/storage-keys.h" 27 + #include "hw/s390x/storage-attributes.h" 27 28 #include "hw/compat.h" 28 29 #include "ipl.h" 29 30 #include "hw/s390x/s390-virtio-ccw.h" 30 31 #include "hw/s390x/css-bridge.h" 31 32 #include "migration/register.h" 33 + #include "cpu_models.h" 32 34 33 35 static const char *const reset_dev_types[] = { 34 36 TYPE_VIRTUAL_CSS_BRIDGE, ··· 103 105 104 106 /* Initialize storage key device */ 105 107 s390_skeys_init(); 108 + /* Initialize storage attributes device */ 109 + s390_stattrib_init(); 106 110 } 107 111 108 112 static SaveVMHandlers savevm_gtod = { ··· 119 123 s390_sclp_init(); 120 124 s390_memory_init(machine->ram_size); 121 125 126 + /* init CPUs */ 127 + s390_init_cpus(machine); 128 + 122 129 s390_flic_init(); 123 130 124 131 /* get a BUS */ ··· 134 141 135 142 /* register hypercalls */ 136 143 virtio_ccw_register_hcalls(); 137 - 138 - /* init CPUs */ 139 - s390_init_cpus(machine); 140 144 141 145 if (kvm_enabled()) { 142 146 kvm_s390_enable_css_support(s390_cpu_addr2state(0)); ··· 206 210 207 211 s390mc->ri_allowed = true; 208 212 s390mc->cpu_model_allowed = true; 213 + s390mc->css_migration_enabled = true; 214 + s390mc->gs_allowed = true; 209 215 mc->init = ccw_init; 210 216 mc->reset = s390_machine_reset; 211 217 mc->hot_add_cpu = s390_hot_add_cpu; ··· 252 258 ms->dea_key_wrap = value; 253 259 } 254 260 261 + static S390CcwMachineClass *current_mc; 262 + 263 + static S390CcwMachineClass *get_machine_class(void) 264 + { 265 + if (unlikely(!current_mc)) { 266 + /* 267 + * No s390 ccw machine was instantiated, we are likely to 268 + * be called for the 'none' machine. The properties will 269 + * have their after-initialization values. 270 + */ 271 + current_mc = S390_MACHINE_CLASS( 272 + object_class_by_name(TYPE_S390_CCW_MACHINE)); 273 + } 274 + return current_mc; 275 + } 276 + 255 277 bool ri_allowed(void) 256 278 { 279 + if (!kvm_enabled()) { 280 + return false; 281 + } 282 + /* for "none" machine this results in true */ 283 + return get_machine_class()->ri_allowed; 284 + } 285 + 286 + bool cpu_model_allowed(void) 287 + { 288 + /* for "none" machine this results in true */ 289 + return get_machine_class()->cpu_model_allowed; 290 + } 291 + 292 + bool gs_allowed(void) 293 + { 257 294 if (kvm_enabled()) { 258 295 MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 259 296 if (object_class_dynamic_cast(OBJECT_CLASS(mc), 260 297 TYPE_S390_CCW_MACHINE)) { 261 298 S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); 262 299 263 - return s390mc->ri_allowed; 300 + return s390mc->gs_allowed; 264 301 } 265 - /* 266 - * Make sure the "none" machine can have ri, otherwise it won't * be 267 - * unlocked in KVM and therefore the host CPU model might be wrong. 268 - */ 302 + /* Make sure the "none" machine can have gs */ 269 303 return true; 270 304 } 271 - return 0; 272 - } 273 - 274 - bool cpu_model_allowed(void) 275 - { 276 - MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 277 - if (object_class_dynamic_cast(OBJECT_CLASS(mc), 278 - TYPE_S390_CCW_MACHINE)) { 279 - S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); 280 - 281 - return s390mc->cpu_model_allowed; 282 - } 283 - /* allow CPU model qmp queries with the "none" machine */ 284 - return true; 305 + return false; 285 306 } 286 307 287 308 static char *machine_get_loadparm(Object *obj, Error **errp) ··· 376 397 }, 377 398 }; 378 399 400 + bool css_migration_enabled(void) 401 + { 402 + return get_machine_class()->css_migration_enabled; 403 + } 404 + 379 405 #define DEFINE_CCW_MACHINE(suffix, verstr, latest) \ 380 406 static void ccw_machine_##suffix##_class_init(ObjectClass *oc, \ 381 407 void *data) \ ··· 391 417 static void ccw_machine_##suffix##_instance_init(Object *obj) \ 392 418 { \ 393 419 MachineState *machine = MACHINE(obj); \ 420 + current_mc = S390_MACHINE_CLASS(MACHINE_GET_CLASS(machine)); \ 394 421 ccw_machine_##suffix##_instance_options(machine); \ 395 422 } \ 396 423 static const TypeInfo ccw_machine_##suffix##_info = { \ ··· 406 433 type_init(ccw_machine_register_##suffix) 407 434 408 435 #define CCW_COMPAT_2_9 \ 409 - HW_COMPAT_2_9 436 + HW_COMPAT_2_9 \ 437 + {\ 438 + .driver = TYPE_S390_STATTRIB,\ 439 + .property = "migration-enabled",\ 440 + .value = "off",\ 441 + }, 410 442 411 443 #define CCW_COMPAT_2_8 \ 412 444 HW_COMPAT_2_8 \ ··· 476 508 477 509 static void ccw_machine_2_10_instance_options(MachineState *machine) 478 510 { 511 + if (css_migration_enabled()) { 512 + css_register_vmstate(); 513 + } 479 514 } 480 515 481 516 static void ccw_machine_2_10_class_options(MachineClass *mc) ··· 486 521 static void ccw_machine_2_9_instance_options(MachineState *machine) 487 522 { 488 523 ccw_machine_2_10_instance_options(machine); 524 + s390_cpudef_featoff_greater(12, 1, S390_FEAT_ESOP); 525 + s390_cpudef_featoff_greater(12, 1, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2); 526 + s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI); 527 + s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION); 528 + s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_EVENT_NOTIFICATION); 489 529 } 490 530 491 531 static void ccw_machine_2_9_class_options(MachineClass *mc) 492 532 { 533 + S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); 534 + 535 + s390mc->gs_allowed = false; 493 536 ccw_machine_2_10_class_options(mc); 494 537 SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_9); 538 + s390mc->css_migration_enabled = false; 495 539 } 496 540 DEFINE_CCW_MACHINE(2_9, "2.9", false); 497 541
+1
hw/s390x/trace-events
··· 8 8 css_assign_subch(const char *do_assign, uint8_t cssid, uint8_t ssid, uint16_t schid, uint16_t devno) "CSS: %s %x.%x.%04x (devno %04x)" 9 9 css_io_interrupt(int cssid, int ssid, int schid, uint32_t intparm, uint8_t isc, const char *conditional) "CSS: I/O interrupt on sch %x.%x.%04x (intparm %08x, isc %x) %s" 10 10 css_adapter_interrupt(uint8_t isc) "CSS: adapter I/O interrupt (isc %x)" 11 + css_do_sic(uint16_t mode, uint8_t isc) "CSS: set interruption mode %x on isc %x" 11 12 12 13 # hw/s390x/virtio-ccw.c 13 14 virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command %x"
+1 -1
hw/s390x/virtio-ccw.c
··· 1070 1070 0x80 >> ((ind_bit + vector) % 8)); 1071 1071 if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr, 1072 1072 0x01)) { 1073 - css_adapter_interrupt(dev->thinint_isc); 1073 + css_adapter_interrupt(CSS_IO_ADAPTER_VIRTIO, dev->thinint_isc); 1074 1074 } 1075 1075 } else { 1076 1076 indicators = address_space_ldq(&address_space_memory,
+1
include/elf.h
··· 1476 1476 #define NT_TASKSTRUCT 4 1477 1477 #define NT_AUXV 6 1478 1478 #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ 1479 + #define NT_S390_GS_CB 0x30b /* s390 guarded storage registers */ 1479 1480 #define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31 */ 1480 1481 #define NT_S390_VXRS_LOW 0x309 /* s390 vector registers 0-15 (lower half) */ 1481 1482 #define NT_S390_PREFIX 0x305 /* s390 prefix register */
+18 -5
include/hw/s390x/css.h
··· 12 12 #ifndef CSS_H 13 13 #define CSS_H 14 14 15 + #include "cpu.h" 15 16 #include "hw/s390x/adapter.h" 16 17 #include "hw/s390x/s390_flic.h" 17 18 #include "hw/s390x/ioinst.h" ··· 89 90 bool thinint_active; 90 91 uint8_t ccw_no_data_cnt; 91 92 uint16_t migrated_schid; /* used for missmatch detection */ 93 + ORB orb; 92 94 /* transport-provided data: */ 93 95 int (*ccw_cb) (SubchDev *, CCW1); 94 96 void (*disable_cb)(SubchDev *); 95 - int (*do_subchannel_work) (SubchDev *, ORB *); 97 + int (*do_subchannel_work) (SubchDev *); 96 98 SenseId id; 97 99 void *driver_data; 98 100 }; ··· 154 156 void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); 155 157 void css_generate_css_crws(uint8_t cssid); 156 158 void css_clear_sei_pending(void); 157 - void css_adapter_interrupt(uint8_t isc); 158 159 int s390_ccw_cmd_request(ORB *orb, SCSW *scsw, void *data); 159 - int do_subchannel_work_virtual(SubchDev *sub, ORB *orb); 160 - int do_subchannel_work_passthrough(SubchDev *sub, ORB *orb); 160 + int do_subchannel_work_virtual(SubchDev *sub); 161 + int do_subchannel_work_passthrough(SubchDev *sub); 161 162 162 163 typedef enum { 163 164 CSS_IO_ADAPTER_VIRTIO = 0, ··· 165 166 CSS_IO_ADAPTER_TYPE_NUMS, 166 167 } CssIoAdapterType; 167 168 169 + void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc); 170 + int css_do_sic(CPUS390XState *env, uint8_t isc, uint16_t mode); 168 171 uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc); 169 172 void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, 170 - Error **errp); 173 + uint8_t flags, Error **errp); 174 + 175 + #ifndef CONFIG_KVM 176 + #define S390_ADAPTER_SUPPRESSIBLE 0x01 177 + #else 178 + #define S390_ADAPTER_SUPPRESSIBLE KVM_S390_ADAPTER_SUPPRESSIBLE 179 + #endif 171 180 172 181 #ifndef CONFIG_USER_ONLY 173 182 SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, ··· 225 234 */ 226 235 SubchDev *css_create_sch(CssDevId bus_id, bool is_virtual, bool squash_mcss, 227 236 Error **errp); 237 + 238 + /** Turn on css migration */ 239 + void css_register_vmstate(void); 240 + 228 241 #endif
+10
include/hw/s390x/s390-virtio-ccw.h
··· 39 39 /*< public >*/ 40 40 bool ri_allowed; 41 41 bool cpu_model_allowed; 42 + bool css_migration_enabled; 43 + bool gs_allowed; 42 44 } S390CcwMachineClass; 43 45 44 46 /* runtime-instrumentation allowed by the machine */ 45 47 bool ri_allowed(void); 46 48 /* cpu model allowed by the machine */ 47 49 bool cpu_model_allowed(void); 50 + /* guarded-storage allowed by the machine */ 51 + bool gs_allowed(void); 52 + 53 + /** 54 + * Returns true if (vmstate based) migration of the channel subsystem 55 + * is enabled, false if it is disabled. 56 + */ 57 + bool css_migration_enabled(void); 48 58 49 59 #endif
+12 -2
include/hw/s390x/s390_flic.h
··· 44 44 SysBusDevice parent_obj; 45 45 /* to limit AdapterRoutes.num_routes for compat */ 46 46 uint32_t adapter_routes_max_batch; 47 - 47 + bool ais_supported; 48 48 } S390FLICState; 49 49 50 50 #define S390_FLIC_COMMON_CLASS(klass) \ ··· 56 56 DeviceClass parent_class; 57 57 58 58 int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc, 59 - bool swap, bool maskable); 59 + bool swap, bool maskable, uint8_t flags); 60 60 int (*io_adapter_map)(S390FLICState *fs, uint32_t id, uint64_t map_addr, 61 61 bool do_map); 62 62 int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); 63 63 void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); 64 64 int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id, 65 65 uint16_t subchannel_nr); 66 + int (*modify_ais_mode)(S390FLICState *fs, uint8_t isc, uint16_t mode); 67 + int (*inject_airq)(S390FLICState *fs, uint8_t type, uint8_t isc, 68 + uint8_t flags); 66 69 } S390FLICStateClass; 67 70 68 71 #define TYPE_KVM_S390_FLIC "s390-flic-kvm" ··· 73 76 #define QEMU_S390_FLIC(obj) \ 74 77 OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC) 75 78 79 + #define SIC_IRQ_MODE_ALL 0 80 + #define SIC_IRQ_MODE_SINGLE 1 81 + #define AIS_MODE_MASK(isc) (0x80 >> isc) 82 + 76 83 typedef struct QEMUS390FLICState { 77 84 S390FLICState parent_obj; 85 + uint8_t simm; 86 + uint8_t nimm; 78 87 } QEMUS390FLICState; 79 88 80 89 void s390_flic_init(void); 81 90 82 91 S390FLICState *s390_get_flic(void); 92 + bool ais_needed(void *opaque); 83 93 84 94 #ifdef CONFIG_KVM 85 95 DeviceState *s390_flic_kvm_create(void);
+1 -2
include/hw/s390x/sclp.h
··· 123 123 uint64_t facilities; /* 48-55 */ 124 124 uint8_t _reserved0[76 - 56]; /* 56-75 */ 125 125 uint32_t ibc_val; 126 - uint8_t conf_char[96 - 80]; /* 80-95 */ 127 - uint8_t _reserved4[99 - 96]; /* 96-98 */ 126 + uint8_t conf_char[99 - 80]; /* 80-98 */ 128 127 uint8_t mha_pow; 129 128 uint32_t rnsize2; 130 129 uint64_t rnmax2;
+81
include/hw/s390x/storage-attributes.h
··· 1 + /* 2 + * s390 storage attributes device 3 + * 4 + * Copyright 2016 IBM Corp. 5 + * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.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 + #ifndef S390_STORAGE_ATTRIBUTES_H 13 + #define S390_STORAGE_ATTRIBUTES_H 14 + 15 + #include <hw/qdev.h> 16 + #include "monitor/monitor.h" 17 + 18 + #define TYPE_S390_STATTRIB "s390-storage_attributes" 19 + #define TYPE_QEMU_S390_STATTRIB "s390-storage_attributes-qemu" 20 + #define TYPE_KVM_S390_STATTRIB "s390-storage_attributes-kvm" 21 + 22 + #define S390_STATTRIB(obj) \ 23 + OBJECT_CHECK(S390StAttribState, (obj), TYPE_S390_STATTRIB) 24 + 25 + typedef struct S390StAttribState { 26 + DeviceState parent_obj; 27 + uint64_t migration_cur_gfn; 28 + bool migration_enabled; 29 + } S390StAttribState; 30 + 31 + #define S390_STATTRIB_CLASS(klass) \ 32 + OBJECT_CLASS_CHECK(S390StAttribClass, (klass), TYPE_S390_STATTRIB) 33 + #define S390_STATTRIB_GET_CLASS(obj) \ 34 + OBJECT_GET_CLASS(S390StAttribClass, (obj), TYPE_S390_STATTRIB) 35 + 36 + typedef struct S390StAttribClass { 37 + DeviceClass parent_class; 38 + /* Return value: < 0 on error, or new count */ 39 + int (*get_stattr)(S390StAttribState *sa, uint64_t *start_gfn, 40 + uint32_t count, uint8_t *values); 41 + int (*peek_stattr)(S390StAttribState *sa, uint64_t start_gfn, 42 + uint32_t count, uint8_t *values); 43 + int (*set_stattr)(S390StAttribState *sa, uint64_t start_gfn, 44 + uint32_t count, uint8_t *values); 45 + void (*synchronize)(S390StAttribState *sa); 46 + int (*set_migrationmode)(S390StAttribState *sa, bool value); 47 + int (*get_active)(S390StAttribState *sa); 48 + long long (*get_dirtycount)(S390StAttribState *sa); 49 + } S390StAttribClass; 50 + 51 + #define QEMU_S390_STATTRIB(obj) \ 52 + OBJECT_CHECK(QEMUS390StAttribState, (obj), TYPE_QEMU_S390_STATTRIB) 53 + 54 + typedef struct QEMUS390StAttribState { 55 + S390StAttribState parent_obj; 56 + } QEMUS390StAttribState; 57 + 58 + #define KVM_S390_STATTRIB(obj) \ 59 + OBJECT_CHECK(KVMS390StAttribState, (obj), TYPE_KVM_S390_STATTRIB) 60 + 61 + typedef struct KVMS390StAttribState { 62 + S390StAttribState parent_obj; 63 + uint64_t still_dirty; 64 + uint8_t *incoming_buffer; 65 + } KVMS390StAttribState; 66 + 67 + void s390_stattrib_init(void); 68 + 69 + #ifdef CONFIG_KVM 70 + Object *kvm_s390_stattrib_create(void); 71 + #else 72 + static inline Object *kvm_s390_stattrib_create(void) 73 + { 74 + return NULL; 75 + } 76 + #endif 77 + 78 + void hmp_info_cmma(Monitor *mon, const QDict *qdict); 79 + void hmp_migrationmode(Monitor *mon, const QDict *qdict); 80 + 81 + #endif /* S390_STORAGE_ATTRIBUTES_H */
+12 -9
include/standard-headers/asm-x86/hyperv.h
··· 34 34 #define HV_X64_MSR_REFERENCE_TSC 0x40000021 35 35 36 36 /* 37 - * There is a single feature flag that signifies the presence of the MSR 38 - * that can be used to retrieve both the local APIC Timer frequency as 39 - * well as the TSC frequency. 37 + * There is a single feature flag that signifies if the partition has access 38 + * to MSRs with local APIC and TSC frequencies. 40 39 */ 41 - 42 - /* Local APIC timer frequency MSR (HV_X64_MSR_APIC_FREQUENCY) is available */ 43 - #define HV_X64_MSR_APIC_FREQUENCY_AVAILABLE (1 << 11) 44 - 45 - /* TSC frequency MSR (HV_X64_MSR_TSC_FREQUENCY) is available */ 46 - #define HV_X64_MSR_TSC_FREQUENCY_AVAILABLE (1 << 11) 40 + #define HV_X64_ACCESS_FREQUENCY_MSRS (1 << 11) 47 41 48 42 /* 49 43 * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM ··· 72 66 * HV_X64_MSR_STATS_VP_INTERNAL_PAGE) available 73 67 */ 74 68 #define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8) 69 + 70 + /* Frequency MSRs available */ 71 + #define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE (1 << 8) 75 72 76 73 /* Crash MSR available */ 77 74 #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10) ··· 151 148 * Virtual APIC support 152 149 */ 153 150 #define HV_X64_DEPRECATING_AEOI_RECOMMENDED (1 << 9) 151 + 152 + /* 153 + * HV_VP_SET available 154 + */ 155 + #define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11) 156 + 154 157 155 158 /* 156 159 * Crash notification flag.
+1
include/standard-headers/linux/input-event-codes.h
··· 600 600 #define KEY_APPSELECT 0x244 /* AL Select Task/Application */ 601 601 #define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ 602 602 #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ 603 + #define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ 603 604 604 605 #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ 605 606 #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
+1
include/standard-headers/linux/pci_regs.h
··· 517 517 #define PCI_EXP_LNKCAP_SLS 0x0000000f /* Supported Link Speeds */ 518 518 #define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */ 519 519 #define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */ 520 + #define PCI_EXP_LNKCAP_SLS_8_0GB 0x00000003 /* LNKCAP2 SLS Vector bit 2 */ 520 521 #define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */ 521 522 #define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */ 522 523 #define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */
+8
linux-headers/asm-arm/kvm.h
··· 203 203 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff 204 204 #define VGIC_LEVEL_INFO_LINE_LEVEL 0 205 205 206 + /* Device Control API on vcpu fd */ 207 + #define KVM_ARM_VCPU_PMU_V3_CTRL 0 208 + #define KVM_ARM_VCPU_PMU_V3_IRQ 0 209 + #define KVM_ARM_VCPU_PMU_V3_INIT 1 210 + #define KVM_ARM_VCPU_TIMER_CTRL 1 211 + #define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0 212 + #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 213 + 206 214 #define KVM_DEV_ARM_VGIC_CTRL_INIT 0 207 215 #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 208 216 #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
+3
linux-headers/asm-arm64/kvm.h
··· 232 232 #define KVM_ARM_VCPU_PMU_V3_CTRL 0 233 233 #define KVM_ARM_VCPU_PMU_V3_IRQ 0 234 234 #define KVM_ARM_VCPU_PMU_V3_INIT 1 235 + #define KVM_ARM_VCPU_TIMER_CTRL 1 236 + #define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0 237 + #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 235 238 236 239 /* KVM_IRQ_LINE irq field index values */ 237 240 #define KVM_ARM_IRQ_TYPE_SHIFT 24
+6
linux-headers/asm-powerpc/kvm.h
··· 60 60 61 61 #define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */ 62 62 63 + /* flags for kvm_run.flags */ 64 + #define KVM_RUN_PPC_NMI_DISP_MASK (3 << 0) 65 + #define KVM_RUN_PPC_NMI_DISP_FULLY_RECOV (1 << 0) 66 + #define KVM_RUN_PPC_NMI_DISP_LIMITED_RECOV (2 << 0) 67 + #define KVM_RUN_PPC_NMI_DISP_NOT_RECOV (3 << 0) 68 + 63 69 /* 64 70 * Feature bits indicate which sections of the sregs struct are valid, 65 71 * both in KVM_GET_SREGS and KVM_SET_SREGS. On KVM_SET_SREGS, registers
+12
linux-headers/asm-s390/kvm.h
··· 28 28 #define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 29 29 #define KVM_DEV_FLIC_AISM 9 30 30 #define KVM_DEV_FLIC_AIRQ_INJECT 10 31 + #define KVM_DEV_FLIC_AISM_ALL 11 31 32 /* 32 33 * We can have up to 4*64k pending subchannels + 8 adapter interrupts, 33 34 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. ··· 53 54 __u16 mode; 54 55 }; 55 56 57 + struct kvm_s390_ais_all { 58 + __u8 simm; 59 + __u8 nimm; 60 + }; 61 + 56 62 #define KVM_S390_IO_ADAPTER_MASK 1 57 63 #define KVM_S390_IO_ADAPTER_MAP 2 58 64 #define KVM_S390_IO_ADAPTER_UNMAP 3 ··· 70 76 #define KVM_S390_VM_TOD 1 71 77 #define KVM_S390_VM_CRYPTO 2 72 78 #define KVM_S390_VM_CPU_MODEL 3 79 + #define KVM_S390_VM_MIGRATION 4 73 80 74 81 /* kvm attributes for mem_ctrl */ 75 82 #define KVM_S390_VM_MEM_ENABLE_CMMA 0 ··· 150 157 #define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1 151 158 #define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2 152 159 #define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3 160 + 161 + /* kvm attributes for migration mode */ 162 + #define KVM_S390_VM_MIGRATION_STOP 0 163 + #define KVM_S390_VM_MIGRATION_START 1 164 + #define KVM_S390_VM_MIGRATION_STATUS 2 153 165 154 166 /* for KVM_GET_REGS and KVM_SET_REGS */ 155 167 struct kvm_regs {
+35
linux-headers/linux/kvm.h
··· 155 155 __u32 reserved[9]; 156 156 }; 157 157 158 + #define KVM_S390_CMMA_PEEK (1 << 0) 159 + 160 + /** 161 + * kvm_s390_cmma_log - Used for CMMA migration. 162 + * 163 + * Used both for input and output. 164 + * 165 + * @start_gfn: Guest page number to start from. 166 + * @count: Size of the result buffer. 167 + * @flags: Control operation mode via KVM_S390_CMMA_* flags 168 + * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty 169 + * pages are still remaining. 170 + * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set 171 + * in the PGSTE. 172 + * @values: Pointer to the values buffer. 173 + * 174 + * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls. 175 + */ 176 + struct kvm_s390_cmma_log { 177 + __u64 start_gfn; 178 + __u32 count; 179 + __u32 flags; 180 + union { 181 + __u64 remaining; 182 + __u64 mask; 183 + }; 184 + __u64 values; 185 + }; 186 + 158 187 struct kvm_hyperv_exit { 159 188 #define KVM_EXIT_HYPERV_SYNIC 1 160 189 #define KVM_EXIT_HYPERV_HCALL 2 ··· 895 924 #define KVM_CAP_SPAPR_TCE_VFIO 142 896 925 #define KVM_CAP_X86_GUEST_MWAIT 143 897 926 #define KVM_CAP_ARM_USER_IRQ 144 927 + #define KVM_CAP_S390_CMMA_MIGRATION 145 928 + #define KVM_CAP_PPC_FWNMI 146 929 + #define KVM_CAP_PPC_SMT_POSSIBLE 147 898 930 899 931 #ifdef KVM_CAP_IRQ_ROUTING 900 932 ··· 1318 1350 #define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state) 1319 1351 /* Available with KVM_CAP_X86_SMM */ 1320 1352 #define KVM_SMI _IO(KVMIO, 0xb7) 1353 + /* Available with KVM_CAP_S390_CMMA_MIGRATION */ 1354 + #define KVM_S390_GET_CMMA_BITS _IOW(KVMIO, 0xb8, struct kvm_s390_cmma_log) 1355 + #define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log) 1321 1356 1322 1357 #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) 1323 1358 #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
+1
monitor.c
··· 81 81 82 82 #if defined(TARGET_S390X) 83 83 #include "hw/s390x/storage-keys.h" 84 + #include "hw/s390x/storage-attributes.h" 84 85 #endif 85 86 86 87 /*
pc-bios/s390-ccw.img

This is a binary file and will not be displayed.

+10 -3
pc-bios/s390-ccw/Makefile
··· 9 9 10 10 .PHONY : all clean build-all 11 11 12 - OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o 12 + OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o 13 13 QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) 14 14 QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float 15 15 QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing 16 16 QEMU_CFLAGS += $(call cc-option, $(QEMU_CFLAGS), -fno-stack-protector) 17 17 LDFLAGS += -Wl,-pie -nostdlib 18 18 19 - build-all: s390-ccw.img 19 + build-all: s390-ccw.img s390-netboot.img 20 20 21 21 s390-ccw.elf: $(OBJECTS) 22 22 $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"BUILD","$(TARGET_DIR)$@") ··· 28 28 29 29 $(OBJECTS): Makefile 30 30 31 + ifneq ($(wildcard $(SRC_PATH)/roms/SLOF/lib/libnet),) 32 + include $(SRC_PATH)/pc-bios/s390-ccw/netboot.mak 33 + else 34 + s390-netboot.img: 35 + @echo "s390-netboot.img not built since roms/SLOF/ is not available." 36 + endif 37 + 31 38 clean: 32 - rm -f *.o *.d *.img *.elf *~ 39 + $(RM) *.o *.d *.img *.elf *~ *.a
+2
pc-bios/s390-ccw/bootmap.c
··· 8 8 * directory. 9 9 */ 10 10 11 + #include "libc.h" 11 12 #include "s390-ccw.h" 12 13 #include "bootmap.h" 13 14 #include "virtio.h" 15 + #include "bswap.h" 14 16 15 17 #ifdef DEBUG 16 18 /* #define DEBUG_FALLBACK */
-26
pc-bios/s390-ccw/bootmap.h
··· 324 324 return 0; 325 325 } 326 326 327 - /* from include/qemu/bswap.h */ 328 - 329 - /* El Torito is always little-endian */ 330 - static inline uint16_t bswap16(uint16_t x) 331 - { 332 - return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8); 333 - } 334 - 335 - static inline uint32_t bswap32(uint32_t x) 336 - { 337 - return ((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | 338 - ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24); 339 - } 340 - 341 - static inline uint64_t bswap64(uint64_t x) 342 - { 343 - return ((x & 0x00000000000000ffULL) << 56) | 344 - ((x & 0x000000000000ff00ULL) << 40) | 345 - ((x & 0x0000000000ff0000ULL) << 24) | 346 - ((x & 0x00000000ff000000ULL) << 8) | 347 - ((x & 0x000000ff00000000ULL) >> 8) | 348 - ((x & 0x0000ff0000000000ULL) >> 24) | 349 - ((x & 0x00ff000000000000ULL) >> 40) | 350 - ((x & 0xff00000000000000ULL) >> 56); 351 - } 352 - 353 327 static inline uint32_t iso_733_to_u32(uint64_t x) 354 328 { 355 329 return (uint32_t)x;
+30
pc-bios/s390-ccw/bswap.h
··· 1 + /* 2 + * Byte swap functions - taken from include/qemu/bswap.h 3 + * 4 + * This work is licensed under the terms of the GNU GPL, version 2 or (at 5 + * your option) any later version. See the COPYING file in the top-level 6 + * directory. 7 + */ 8 + 9 + static inline uint16_t bswap16(uint16_t x) 10 + { 11 + return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8); 12 + } 13 + 14 + static inline uint32_t bswap32(uint32_t x) 15 + { 16 + return ((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | 17 + ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24); 18 + } 19 + 20 + static inline uint64_t bswap64(uint64_t x) 21 + { 22 + return ((x & 0x00000000000000ffULL) << 56) | 23 + ((x & 0x000000000000ff00ULL) << 40) | 24 + ((x & 0x0000000000ff0000ULL) << 24) | 25 + ((x & 0x00000000ff000000ULL) << 8) | 26 + ((x & 0x000000ff00000000ULL) >> 8) | 27 + ((x & 0x0000ff0000000000ULL) >> 24) | 28 + ((x & 0x00ff000000000000ULL) >> 40) | 29 + ((x & 0xff00000000000000ULL) >> 56); 30 + }
+45
pc-bios/s390-ccw/libc.h
··· 1 + /* 2 + * libc-style definitions and functions 3 + * 4 + * This code is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License as published by the 6 + * Free Software Foundation; either version 2 of the License, or (at your 7 + * option) any later version. 8 + */ 9 + 10 + #ifndef S390_CCW_LIBC_H 11 + #define S390_CCW_LIBC_H 12 + 13 + typedef long size_t; 14 + typedef int bool; 15 + typedef unsigned char uint8_t; 16 + typedef unsigned short uint16_t; 17 + typedef unsigned int uint32_t; 18 + typedef unsigned long long uint64_t; 19 + 20 + static inline void *memset(void *s, int c, size_t n) 21 + { 22 + int i; 23 + unsigned char *p = s; 24 + 25 + for (i = 0; i < n; i++) { 26 + p[i] = c; 27 + } 28 + 29 + return s; 30 + } 31 + 32 + static inline void *memcpy(void *s1, const void *s2, size_t n) 33 + { 34 + uint8_t *dest = s1; 35 + const uint8_t *src = s2; 36 + int i; 37 + 38 + for (i = 0; i < n; i++) { 39 + dest[i] = src[i]; 40 + } 41 + 42 + return s1; 43 + } 44 + 45 + #endif
+2 -12
pc-bios/s390-ccw/main.c
··· 8 8 * directory. 9 9 */ 10 10 11 + #include "libc.h" 11 12 #include "s390-ccw.h" 12 13 #include "virtio.h" 13 14 ··· 15 16 static SubChannelId blk_schid = { .one = 1 }; 16 17 IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); 17 18 static char loadparm[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 18 - 19 - const unsigned char ebc2asc[256] = 20 - /* 0123456789abcdef0123456789abcdef */ 21 - "................................" /* 1F */ 22 - "................................" /* 3F */ 23 - " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */ 24 - "-/.........,%_>?.........`:#@'=\""/* 7F */ 25 - ".abcdefghi.......jklmnopqr......" /* 9F */ 26 - "..stuvwxyz......................" /* BF */ 27 - ".ABCDEFGHI.......JKLMNOPQR......" /* DF */ 28 - "..STUVWXYZ......0123456789......";/* FF */ 29 19 30 20 /* 31 21 * Priniciples of Operations (SA22-7832-09) chapter 17 requires that ··· 154 144 sclp_print("Network boot device detected\n"); 155 145 vdev->netboot_start_addr = iplb.ccw.netboot_start_addr; 156 146 } else { 157 - virtio_setup_device(blk_schid); 147 + virtio_blk_setup_device(blk_schid); 158 148 159 149 IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); 160 150 }
+59
pc-bios/s390-ccw/netboot.mak
··· 1 + 2 + SLOF_DIR := $(SRC_PATH)/roms/SLOF 3 + 4 + NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o libnet.a libc.a 5 + 6 + LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include 7 + LIBNET_INC := -I$(SLOF_DIR)/lib/libnet 8 + 9 + NETLDFLAGS := $(LDFLAGS) -Ttext=0x7800000 10 + 11 + $(NETOBJS): QEMU_CFLAGS += $(LIBC_INC) $(LIBNET_INC) 12 + 13 + s390-netboot.elf: $(NETOBJS) 14 + $(call quiet-command,$(CC) $(NETLDFLAGS) -o $@ $(NETOBJS),"BUILD","$(TARGET_DIR)$@") 15 + 16 + s390-netboot.img: s390-netboot.elf 17 + $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@") 18 + 19 + # libc files: 20 + 21 + LIBC_CFLAGS := $(QEMU_CFLAGS) $(LIBC_INC) $(LIBNET_INC) 22 + 23 + CTYPE_OBJS = isdigit.o isxdigit.o toupper.o 24 + %.o : $(SLOF_DIR)/lib/libc/ctype/%.c 25 + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") 26 + 27 + STRING_OBJS = strcat.o strchr.o strcmp.o strcpy.o strlen.o strncmp.o strncpy.o \ 28 + strstr.o memset.o memcpy.o memmove.o memcmp.o 29 + %.o : $(SLOF_DIR)/lib/libc/string/%.c 30 + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") 31 + 32 + STDLIB_OBJS = atoi.o atol.o strtoul.o strtol.o rand.o malloc.o free.o 33 + %.o : $(SLOF_DIR)/lib/libc/stdlib/%.c 34 + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") 35 + 36 + STDIO_OBJS = sprintf.o vfprintf.o vsnprintf.o vsprintf.o fprintf.o \ 37 + printf.o putc.o puts.o putchar.o stdchnls.o fileno.o 38 + %.o : $(SLOF_DIR)/lib/libc/stdio/%.c 39 + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") 40 + 41 + sbrk.o: $(SLOF_DIR)/slof/sbrk.c 42 + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") 43 + 44 + LIBCOBJS := $(STRING_OBJS) $(CTYPE_OBJS) $(STDLIB_OBJS) $(STDIO_OBJS) sbrk.o 45 + 46 + libc.a: $(LIBCOBJS) 47 + $(call quiet-command,$(AR) -rc $@ $^,"AR","$(TARGET_DIR)$@") 48 + 49 + # libnet files: 50 + 51 + LIBNETOBJS := args.o dhcp.o dns.o icmpv6.o ipv6.o tcp.o udp.o bootp.o \ 52 + dhcpv6.o ethernet.o ipv4.o ndp.o tftp.o 53 + LIBNETCFLAGS := $(QEMU_CFLAGS) $(LIBC_INC) $(LIBNET_INC) 54 + 55 + %.o : $(SLOF_DIR)/lib/libnet/%.c 56 + $(call quiet-command,$(CC) $(LIBNETCFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") 57 + 58 + libnet.a: $(LIBNETOBJS) 59 + $(call quiet-command,$(AR) -rc $@ $^,"AR","$(TARGET_DIR)$@")
+361
pc-bios/s390-ccw/netmain.c
··· 1 + /* 2 + * S390 virtio-ccw network boot loading program 3 + * 4 + * Copyright 2017 Thomas Huth, Red Hat Inc. 5 + * 6 + * Based on the S390 virtio-ccw loading program (main.c) 7 + * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 8 + * 9 + * And based on the network loading code from SLOF (netload.c) 10 + * Copyright (c) 2004, 2008 IBM Corporation 11 + * 12 + * This code is free software; you can redistribute it and/or modify it 13 + * under the terms of the GNU General Public License as published by the 14 + * Free Software Foundation; either version 2 of the License, or (at your 15 + * option) any later version. 16 + */ 17 + 18 + #include <stdint.h> 19 + #include <stdbool.h> 20 + #include <stdio.h> 21 + #include <stdlib.h> 22 + #include <string.h> 23 + #include <unistd.h> 24 + 25 + #include <tftp.h> 26 + #include <ethernet.h> 27 + #include <dhcp.h> 28 + #include <dhcpv6.h> 29 + #include <ipv4.h> 30 + #include <ipv6.h> 31 + #include <dns.h> 32 + #include <time.h> 33 + 34 + #include "s390-ccw.h" 35 + #include "virtio.h" 36 + 37 + #define DEFAULT_BOOT_RETRIES 10 38 + #define DEFAULT_TFTP_RETRIES 20 39 + 40 + extern char _start[]; 41 + 42 + char stack[PAGE_SIZE * 8] __attribute__((aligned(PAGE_SIZE))); 43 + IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE))); 44 + 45 + static SubChannelId net_schid = { .one = 1 }; 46 + static int ip_version = 4; 47 + static uint64_t dest_timer; 48 + 49 + static uint64_t get_timer_ms(void) 50 + { 51 + uint64_t clk; 52 + 53 + asm volatile(" stck %0 " : : "Q"(clk) : "memory"); 54 + 55 + /* Bit 51 is incremented each microsecond */ 56 + return (clk >> (63 - 51)) / 1000; 57 + } 58 + 59 + void set_timer(int val) 60 + { 61 + dest_timer = get_timer_ms() + val; 62 + } 63 + 64 + int get_timer(void) 65 + { 66 + return dest_timer - get_timer_ms(); 67 + } 68 + 69 + int get_sec_ticks(void) 70 + { 71 + return 1000; /* number of ticks in 1 second */ 72 + } 73 + 74 + /** 75 + * Obtain IP and configuration info from DHCP server (either IPv4 or IPv6). 76 + * @param fn_ip contains the following configuration information: 77 + * client MAC, client IP, TFTP-server MAC, TFTP-server IP, 78 + * boot file name 79 + * @param retries Number of DHCP attempts 80 + * @return 0 : IP and configuration info obtained; 81 + * non-0 : error condition occurred. 82 + */ 83 + static int dhcp(struct filename_ip *fn_ip, int retries) 84 + { 85 + int i = retries + 1; 86 + int rc = -1; 87 + 88 + printf(" Requesting information via DHCP: "); 89 + 90 + dhcpv4_generate_transaction_id(); 91 + dhcpv6_generate_transaction_id(); 92 + 93 + do { 94 + printf("\b\b\b%03d", i - 1); 95 + if (!--i) { 96 + printf("\nGiving up after %d DHCP requests\n", retries); 97 + return -1; 98 + } 99 + ip_version = 4; 100 + rc = dhcpv4(NULL, fn_ip); 101 + if (rc == -1) { 102 + ip_version = 6; 103 + set_ipv6_address(fn_ip->fd, 0); 104 + rc = dhcpv6(NULL, fn_ip); 105 + if (rc == 0) { 106 + memcpy(&fn_ip->own_ip6, get_ipv6_address(), 16); 107 + break; 108 + } 109 + } 110 + if (rc != -1) { /* either success or non-dhcp failure */ 111 + break; 112 + } 113 + } while (1); 114 + printf("\b\b\b\bdone\n"); 115 + 116 + return rc; 117 + } 118 + 119 + /** 120 + * Seed the random number generator with our mac and current timestamp 121 + */ 122 + static void seed_rng(uint8_t mac[]) 123 + { 124 + uint64_t seed; 125 + 126 + asm volatile(" stck %0 " : : "Q"(seed) : "memory"); 127 + seed ^= (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5]; 128 + srand(seed); 129 + } 130 + 131 + static int tftp_load(filename_ip_t *fnip, void *buffer, int len, 132 + unsigned int retries, int ip_vers) 133 + { 134 + tftp_err_t tftp_err; 135 + int rc; 136 + 137 + rc = tftp(fnip, buffer, len, retries, &tftp_err, 1, 1428, ip_vers); 138 + 139 + if (rc > 0) { 140 + printf(" TFTP: Received %s (%d KBytes)\n", fnip->filename, 141 + rc / 1024); 142 + } else if (rc == -1) { 143 + puts("unknown TFTP error"); 144 + } else if (rc == -2) { 145 + printf("TFTP buffer of %d bytes is too small for %s\n", 146 + len, fnip->filename); 147 + } else if (rc == -3) { 148 + printf("file not found: %s\n", fnip->filename); 149 + } else if (rc == -4) { 150 + puts("TFTP access violation"); 151 + } else if (rc == -5) { 152 + puts("illegal TFTP operation"); 153 + } else if (rc == -6) { 154 + puts("unknown TFTP transfer ID"); 155 + } else if (rc == -7) { 156 + puts("no such TFTP user"); 157 + } else if (rc == -8) { 158 + puts("TFTP blocksize negotiation failed"); 159 + } else if (rc == -9) { 160 + puts("file exceeds maximum TFTP transfer size"); 161 + } else if (rc <= -10 && rc >= -15) { 162 + const char *icmp_err_str; 163 + switch (rc) { 164 + case -ICMP_NET_UNREACHABLE - 10: 165 + icmp_err_str = "net unreachable"; 166 + break; 167 + case -ICMP_HOST_UNREACHABLE - 10: 168 + icmp_err_str = "host unreachable"; 169 + break; 170 + case -ICMP_PROTOCOL_UNREACHABLE - 10: 171 + icmp_err_str = "protocol unreachable"; 172 + break; 173 + case -ICMP_PORT_UNREACHABLE - 10: 174 + icmp_err_str = "port unreachable"; 175 + break; 176 + case -ICMP_FRAGMENTATION_NEEDED - 10: 177 + icmp_err_str = "fragmentation needed and DF set"; 178 + break; 179 + case -ICMP_SOURCE_ROUTE_FAILED - 10: 180 + icmp_err_str = "source route failed"; 181 + break; 182 + default: 183 + icmp_err_str = " UNKNOWN"; 184 + break; 185 + } 186 + printf("ICMP ERROR \"%s\"\n", icmp_err_str); 187 + } else if (rc == -40) { 188 + printf("TFTP error occurred after %d bad packets received", 189 + tftp_err.bad_tftp_packets); 190 + } else if (rc == -41) { 191 + printf("TFTP error occurred after missing %d responses", 192 + tftp_err.no_packets); 193 + } else if (rc == -42) { 194 + printf("TFTP error missing block %d, expected block was %d", 195 + tftp_err.blocks_missed, 196 + tftp_err.blocks_received); 197 + } 198 + 199 + return rc; 200 + } 201 + 202 + static int net_load(char *buffer, int len) 203 + { 204 + filename_ip_t fn_ip; 205 + uint8_t mac[6]; 206 + int rc; 207 + 208 + memset(&fn_ip, 0, sizeof(filename_ip_t)); 209 + 210 + rc = virtio_net_init(mac); 211 + if (rc < 0) { 212 + puts("Could not initialize network device"); 213 + return -101; 214 + } 215 + fn_ip.fd = rc; 216 + 217 + printf(" Using MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", 218 + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 219 + 220 + set_mac_address(mac); /* init ethernet layer */ 221 + seed_rng(mac); 222 + 223 + rc = dhcp(&fn_ip, DEFAULT_BOOT_RETRIES); 224 + if (rc >= 0) { 225 + if (ip_version == 4) { 226 + set_ipv4_address(fn_ip.own_ip); 227 + } 228 + } else { 229 + puts("Could not get IP address"); 230 + return -101; 231 + } 232 + 233 + if (ip_version == 4) { 234 + printf(" Using IPv4 address: %d.%d.%d.%d\n", 235 + (fn_ip.own_ip >> 24) & 0xFF, (fn_ip.own_ip >> 16) & 0xFF, 236 + (fn_ip.own_ip >> 8) & 0xFF, fn_ip.own_ip & 0xFF); 237 + } else if (ip_version == 6) { 238 + char ip6_str[40]; 239 + ipv6_to_str(fn_ip.own_ip6.addr, ip6_str); 240 + printf(" Using IPv6 address: %s\n", ip6_str); 241 + } 242 + 243 + if (rc == -2) { 244 + printf("ARP request to TFTP server (%d.%d.%d.%d) failed\n", 245 + (fn_ip.server_ip >> 24) & 0xFF, (fn_ip.server_ip >> 16) & 0xFF, 246 + (fn_ip.server_ip >> 8) & 0xFF, fn_ip.server_ip & 0xFF); 247 + return -102; 248 + } 249 + if (rc == -4 || rc == -3) { 250 + puts("Can't obtain TFTP server IP address"); 251 + return -107; 252 + } 253 + 254 + if (ip_version == 4) { 255 + printf(" Requesting file \"%s\" via TFTP from %d.%d.%d.%d\n", 256 + fn_ip.filename, 257 + (fn_ip.server_ip >> 24) & 0xFF, (fn_ip.server_ip >> 16) & 0xFF, 258 + (fn_ip.server_ip >> 8) & 0xFF, fn_ip.server_ip & 0xFF); 259 + } else if (ip_version == 6) { 260 + char ip6_str[40]; 261 + printf(" Requesting file \"%s\" via TFTP from ", fn_ip.filename); 262 + ipv6_to_str(fn_ip.server_ip6.addr, ip6_str); 263 + printf("%s\n", ip6_str); 264 + } 265 + 266 + /* Do the TFTP load and print error message if necessary */ 267 + rc = tftp_load(&fn_ip, buffer, len, DEFAULT_TFTP_RETRIES, ip_version); 268 + 269 + if (ip_version == 4) { 270 + dhcp_send_release(fn_ip.fd); 271 + } 272 + 273 + return rc; 274 + } 275 + 276 + void panic(const char *string) 277 + { 278 + sclp_print(string); 279 + for (;;) { 280 + disabled_wait(); 281 + } 282 + } 283 + 284 + static bool find_net_dev(Schib *schib, int dev_no) 285 + { 286 + int i, r; 287 + 288 + for (i = 0; i < 0x10000; i++) { 289 + net_schid.sch_no = i; 290 + r = stsch_err(net_schid, schib); 291 + if (r == 3 || r == -EIO) { 292 + break; 293 + } 294 + if (!schib->pmcw.dnv) { 295 + continue; 296 + } 297 + if (!virtio_is_supported(net_schid)) { 298 + continue; 299 + } 300 + if (virtio_get_device_type() != VIRTIO_ID_NET) { 301 + continue; 302 + } 303 + if (dev_no < 0 || schib->pmcw.dev == dev_no) { 304 + return true; 305 + } 306 + } 307 + 308 + return false; 309 + } 310 + 311 + static void virtio_setup(void) 312 + { 313 + Schib schib; 314 + int ssid; 315 + bool found = false; 316 + uint16_t dev_no; 317 + 318 + /* 319 + * We unconditionally enable mss support. In every sane configuration, 320 + * this will succeed; and even if it doesn't, stsch_err() can deal 321 + * with the consequences. 322 + */ 323 + enable_mss_facility(); 324 + 325 + if (store_iplb(&iplb)) { 326 + IPL_assert(iplb.pbt == S390_IPL_TYPE_CCW, "IPL_TYPE_CCW expected"); 327 + dev_no = iplb.ccw.devno; 328 + debug_print_int("device no. ", dev_no); 329 + net_schid.ssid = iplb.ccw.ssid & 0x3; 330 + debug_print_int("ssid ", net_schid.ssid); 331 + found = find_net_dev(&schib, dev_no); 332 + } else { 333 + for (ssid = 0; ssid < 0x3; ssid++) { 334 + net_schid.ssid = ssid; 335 + found = find_net_dev(&schib, -1); 336 + if (found) { 337 + break; 338 + } 339 + } 340 + } 341 + 342 + IPL_assert(found, "No virtio net device found"); 343 + } 344 + 345 + void main(void) 346 + { 347 + int rc; 348 + 349 + sclp_setup(); 350 + sclp_print("Network boot starting...\n"); 351 + 352 + virtio_setup(); 353 + 354 + rc = net_load(NULL, (long)_start); 355 + if (rc > 0) { 356 + sclp_print("Network loading done, starting kernel...\n"); 357 + asm volatile (" lpsw 0(%0) " : : "r"(0) : "memory"); 358 + } 359 + 360 + panic("Failed to load OS from network\n"); 361 + }
+3 -30
pc-bios/s390-ccw/s390-ccw.h
··· 18 18 typedef unsigned int u32; 19 19 typedef unsigned long long u64; 20 20 typedef unsigned long ulong; 21 - typedef long size_t; 22 - typedef int bool; 23 - typedef unsigned char uint8_t; 24 - typedef unsigned short uint16_t; 25 - typedef unsigned int uint32_t; 26 - typedef unsigned long long uint64_t; 27 21 typedef unsigned char __u8; 28 22 typedef unsigned short __u16; 29 23 typedef unsigned int __u32; ··· 49 43 #define MIN_NON_ZERO(a, b) ((a) == 0 ? (b) : \ 50 44 ((b) == 0 ? (a) : (MIN(a, b)))) 51 45 #endif 46 + 47 + #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 52 48 53 49 #include "cio.h" 54 50 #include "iplb.h" ··· 80 76 unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, 81 77 ulong subchan_id, void *load_addr); 82 78 bool virtio_is_supported(SubChannelId schid); 83 - void virtio_setup_device(SubChannelId schid); 79 + void virtio_blk_setup_device(SubChannelId schid); 84 80 int virtio_read(ulong sector, void *load_addr); 85 81 int enable_mss_facility(void); 86 82 ulong get_second(void); ··· 88 84 /* bootmap.c */ 89 85 void zipl_load(void); 90 86 91 - static inline void *memset(void *s, int c, size_t n) 92 - { 93 - int i; 94 - unsigned char *p = s; 95 - 96 - for (i = 0; i < n; i++) { 97 - p[i] = c; 98 - } 99 - 100 - return s; 101 - } 102 - 103 87 static inline void fill_hex(char *out, unsigned char val) 104 88 { 105 89 const char hex[] = "0123456789abcdef"; ··· 167 151 while (get_second() < target) { 168 152 yield(); 169 153 } 170 - } 171 - 172 - static inline void *memcpy(void *s1, const void *s2, size_t n) 173 - { 174 - uint8_t *p1 = s1; 175 - const uint8_t *p2 = s2; 176 - 177 - while (n--) { 178 - p1[n] = p2[n]; 179 - } 180 - return s1; 181 154 } 182 155 183 156 static inline void IPL_assert(bool term, const char *message)
+27 -10
pc-bios/s390-ccw/sclp.c
··· 8 8 * directory. 9 9 */ 10 10 11 + #include "libc.h" 11 12 #include "s390-ccw.h" 12 13 #include "sclp.h" 13 14 15 + long write(int fd, const void *str, size_t len); 16 + 14 17 static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); 18 + 19 + const unsigned char ebc2asc[256] = 20 + /* 0123456789abcdef0123456789abcdef */ 21 + "................................" /* 1F */ 22 + "................................" /* 3F */ 23 + " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */ 24 + "-/.........,%_>?.........`:#@'=\""/* 7F */ 25 + ".abcdefghi.......jklmnopqr......" /* 9F */ 26 + "..stuvwxyz......................" /* BF */ 27 + ".ABCDEFGHI.......JKLMNOPQR......" /* DF */ 28 + "..STUVWXYZ......0123456789......";/* FF */ 15 29 16 30 /* Perform service call. Return 0 on success, non-zero otherwise. */ 17 31 static int sclp_service_call(unsigned int command, void *sccb) ··· 59 73 return i; 60 74 } 61 75 62 - static void _memcpy(char *dest, const char *src, int len) 76 + long write(int fd, const void *str, size_t len) 63 77 { 64 - int i; 65 - for (i = 0; i < len; i++) 66 - dest[i] = src[i]; 67 - } 78 + WriteEventData *sccb = (void *)_sccb; 68 79 69 - void sclp_print(const char *str) 70 - { 71 - int len = _strlen(str); 72 - WriteEventData *sccb = (void *)_sccb; 80 + if (fd != 1 && fd != 2) { 81 + return -EIO; 82 + } 73 83 74 84 sccb->h.length = sizeof(WriteEventData) + len; 75 85 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 76 86 sccb->ebh.length = sizeof(EventBufferHeader) + len; 77 87 sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; 78 88 sccb->ebh.flags = 0; 79 - _memcpy(sccb->data, str, len); 89 + memcpy(sccb->data, str, len); 80 90 81 91 sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 92 + 93 + return len; 94 + } 95 + 96 + void sclp_print(const char *str) 97 + { 98 + write(1, str, _strlen(str)); 82 99 } 83 100 84 101 void sclp_get_loadparm_ascii(char *loadparm)
+296
pc-bios/s390-ccw/virtio-blkdev.c
··· 1 + /* 2 + * Virtio driver bits 3 + * 4 + * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 5 + * 6 + * This work is licensed under the terms of the GNU GPL, version 2 or (at 7 + * your option) any later version. See the COPYING file in the top-level 8 + * directory. 9 + */ 10 + 11 + #include "libc.h" 12 + #include "s390-ccw.h" 13 + #include "virtio.h" 14 + #include "virtio-scsi.h" 15 + 16 + static int virtio_blk_read_many(VDev *vdev, ulong sector, void *load_addr, 17 + int sec_num) 18 + { 19 + VirtioBlkOuthdr out_hdr; 20 + u8 status; 21 + VRing *vr = &vdev->vrings[vdev->cmd_vr_idx]; 22 + 23 + /* Tell the host we want to read */ 24 + out_hdr.type = VIRTIO_BLK_T_IN; 25 + out_hdr.ioprio = 99; 26 + out_hdr.sector = virtio_sector_adjust(sector); 27 + 28 + vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT); 29 + 30 + /* This is where we want to receive data */ 31 + vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num, 32 + VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN | 33 + VRING_DESC_F_NEXT); 34 + 35 + /* status field */ 36 + vring_send_buf(vr, &status, sizeof(u8), 37 + VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN); 38 + 39 + /* Now we can tell the host to read */ 40 + vring_wait_reply(); 41 + 42 + if (drain_irqs(vr->schid)) { 43 + /* Well, whatever status is supposed to contain... */ 44 + status = 1; 45 + } 46 + return status; 47 + } 48 + 49 + int virtio_read_many(ulong sector, void *load_addr, int sec_num) 50 + { 51 + VDev *vdev = virtio_get_device(); 52 + 53 + switch (vdev->senseid.cu_model) { 54 + case VIRTIO_ID_BLOCK: 55 + return virtio_blk_read_many(vdev, sector, load_addr, sec_num); 56 + case VIRTIO_ID_SCSI: 57 + return virtio_scsi_read_many(vdev, sector, load_addr, sec_num); 58 + } 59 + panic("\n! No readable IPL device !\n"); 60 + return -1; 61 + } 62 + 63 + unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, 64 + ulong subchan_id, void *load_addr) 65 + { 66 + u8 status; 67 + int sec = rec_list1; 68 + int sec_num = ((rec_list2 >> 32) & 0xffff) + 1; 69 + int sec_len = rec_list2 >> 48; 70 + ulong addr = (ulong)load_addr; 71 + 72 + if (sec_len != virtio_get_block_size()) { 73 + return -1; 74 + } 75 + 76 + sclp_print("."); 77 + status = virtio_read_many(sec, (void *)addr, sec_num); 78 + if (status) { 79 + panic("I/O Error"); 80 + } 81 + addr += sec_num * virtio_get_block_size(); 82 + 83 + return addr; 84 + } 85 + 86 + int virtio_read(ulong sector, void *load_addr) 87 + { 88 + return virtio_read_many(sector, load_addr, 1); 89 + } 90 + 91 + /* 92 + * Other supported value pairs, if any, would need to be added here. 93 + * Note: head count is always 15. 94 + */ 95 + static inline u8 virtio_eckd_sectors_for_block_size(int size) 96 + { 97 + switch (size) { 98 + case 512: 99 + return 49; 100 + case 1024: 101 + return 33; 102 + case 2048: 103 + return 21; 104 + case 4096: 105 + return 12; 106 + } 107 + return 0; 108 + } 109 + 110 + VirtioGDN virtio_guessed_disk_nature(void) 111 + { 112 + return virtio_get_device()->guessed_disk_nature; 113 + } 114 + 115 + void virtio_assume_scsi(void) 116 + { 117 + VDev *vdev = virtio_get_device(); 118 + 119 + switch (vdev->senseid.cu_model) { 120 + case VIRTIO_ID_BLOCK: 121 + vdev->guessed_disk_nature = VIRTIO_GDN_SCSI; 122 + vdev->config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE; 123 + vdev->config.blk.physical_block_exp = 0; 124 + vdev->blk_factor = 1; 125 + break; 126 + case VIRTIO_ID_SCSI: 127 + vdev->scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE; 128 + break; 129 + } 130 + } 131 + 132 + void virtio_assume_iso9660(void) 133 + { 134 + VDev *vdev = virtio_get_device(); 135 + 136 + switch (vdev->senseid.cu_model) { 137 + case VIRTIO_ID_BLOCK: 138 + vdev->guessed_disk_nature = VIRTIO_GDN_SCSI; 139 + vdev->config.blk.blk_size = VIRTIO_ISO_BLOCK_SIZE; 140 + vdev->config.blk.physical_block_exp = 0; 141 + vdev->blk_factor = VIRTIO_ISO_BLOCK_SIZE / VIRTIO_SECTOR_SIZE; 142 + break; 143 + case VIRTIO_ID_SCSI: 144 + vdev->scsi_block_size = VIRTIO_ISO_BLOCK_SIZE; 145 + break; 146 + } 147 + } 148 + 149 + void virtio_assume_eckd(void) 150 + { 151 + VDev *vdev = virtio_get_device(); 152 + 153 + vdev->guessed_disk_nature = VIRTIO_GDN_DASD; 154 + vdev->blk_factor = 1; 155 + vdev->config.blk.physical_block_exp = 0; 156 + switch (vdev->senseid.cu_model) { 157 + case VIRTIO_ID_BLOCK: 158 + vdev->config.blk.blk_size = 4096; 159 + break; 160 + case VIRTIO_ID_SCSI: 161 + vdev->config.blk.blk_size = vdev->scsi_block_size; 162 + break; 163 + } 164 + vdev->config.blk.geometry.heads = 15; 165 + vdev->config.blk.geometry.sectors = 166 + virtio_eckd_sectors_for_block_size(vdev->config.blk.blk_size); 167 + } 168 + 169 + bool virtio_disk_is_scsi(void) 170 + { 171 + VDev *vdev = virtio_get_device(); 172 + 173 + if (vdev->guessed_disk_nature == VIRTIO_GDN_SCSI) { 174 + return true; 175 + } 176 + switch (vdev->senseid.cu_model) { 177 + case VIRTIO_ID_BLOCK: 178 + return (vdev->config.blk.geometry.heads == 255) 179 + && (vdev->config.blk.geometry.sectors == 63) 180 + && (virtio_get_block_size() == VIRTIO_SCSI_BLOCK_SIZE); 181 + case VIRTIO_ID_SCSI: 182 + return true; 183 + } 184 + return false; 185 + } 186 + 187 + bool virtio_disk_is_eckd(void) 188 + { 189 + VDev *vdev = virtio_get_device(); 190 + const int block_size = virtio_get_block_size(); 191 + 192 + if (vdev->guessed_disk_nature == VIRTIO_GDN_DASD) { 193 + return true; 194 + } 195 + switch (vdev->senseid.cu_model) { 196 + case VIRTIO_ID_BLOCK: 197 + return (vdev->config.blk.geometry.heads == 15) 198 + && (vdev->config.blk.geometry.sectors == 199 + virtio_eckd_sectors_for_block_size(block_size)); 200 + case VIRTIO_ID_SCSI: 201 + return false; 202 + } 203 + return false; 204 + } 205 + 206 + bool virtio_ipl_disk_is_valid(void) 207 + { 208 + return virtio_disk_is_scsi() || virtio_disk_is_eckd(); 209 + } 210 + 211 + int virtio_get_block_size(void) 212 + { 213 + VDev *vdev = virtio_get_device(); 214 + 215 + switch (vdev->senseid.cu_model) { 216 + case VIRTIO_ID_BLOCK: 217 + return vdev->config.blk.blk_size << vdev->config.blk.physical_block_exp; 218 + case VIRTIO_ID_SCSI: 219 + return vdev->scsi_block_size; 220 + } 221 + return 0; 222 + } 223 + 224 + uint8_t virtio_get_heads(void) 225 + { 226 + VDev *vdev = virtio_get_device(); 227 + 228 + switch (vdev->senseid.cu_model) { 229 + case VIRTIO_ID_BLOCK: 230 + return vdev->config.blk.geometry.heads; 231 + case VIRTIO_ID_SCSI: 232 + return vdev->guessed_disk_nature == VIRTIO_GDN_DASD 233 + ? vdev->config.blk.geometry.heads : 255; 234 + } 235 + return 0; 236 + } 237 + 238 + uint8_t virtio_get_sectors(void) 239 + { 240 + VDev *vdev = virtio_get_device(); 241 + 242 + switch (vdev->senseid.cu_model) { 243 + case VIRTIO_ID_BLOCK: 244 + return vdev->config.blk.geometry.sectors; 245 + case VIRTIO_ID_SCSI: 246 + return vdev->guessed_disk_nature == VIRTIO_GDN_DASD 247 + ? vdev->config.blk.geometry.sectors : 63; 248 + } 249 + return 0; 250 + } 251 + 252 + uint64_t virtio_get_blocks(void) 253 + { 254 + VDev *vdev = virtio_get_device(); 255 + const uint64_t factor = virtio_get_block_size() / VIRTIO_SECTOR_SIZE; 256 + 257 + switch (vdev->senseid.cu_model) { 258 + case VIRTIO_ID_BLOCK: 259 + return vdev->config.blk.capacity / factor; 260 + case VIRTIO_ID_SCSI: 261 + return vdev->scsi_last_block / factor; 262 + } 263 + return 0; 264 + } 265 + 266 + void virtio_blk_setup_device(SubChannelId schid) 267 + { 268 + VDev *vdev = virtio_get_device(); 269 + 270 + vdev->schid = schid; 271 + virtio_setup_ccw(vdev); 272 + 273 + switch (vdev->senseid.cu_model) { 274 + case VIRTIO_ID_BLOCK: 275 + sclp_print("Using virtio-blk.\n"); 276 + if (!virtio_ipl_disk_is_valid()) { 277 + /* make sure all getters but blocksize return 0 for 278 + * invalid IPL disk 279 + */ 280 + memset(&vdev->config.blk, 0, sizeof(vdev->config.blk)); 281 + virtio_assume_scsi(); 282 + } 283 + break; 284 + case VIRTIO_ID_SCSI: 285 + IPL_assert(vdev->config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE, 286 + "Config: sense size mismatch"); 287 + IPL_assert(vdev->config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE, 288 + "Config: CDB size mismatch"); 289 + 290 + sclp_print("Using virtio-scsi.\n"); 291 + virtio_scsi_setup(vdev); 292 + break; 293 + default: 294 + panic("\n! No IPL device available !\n"); 295 + } 296 + }
+135
pc-bios/s390-ccw/virtio-net.c
··· 1 + /* 2 + * Virtio-net driver for the s390-ccw firmware 3 + * 4 + * Copyright 2017 Thomas Huth, Red Hat Inc. 5 + * 6 + * This code is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License as published by the 8 + * Free Software Foundation; either version 2 of the License, or (at your 9 + * option) any later version. 10 + */ 11 + 12 + #include <stdint.h> 13 + #include <stdbool.h> 14 + #include <stdio.h> 15 + #include <stdlib.h> 16 + #include <string.h> 17 + #include <unistd.h> 18 + #include <sys/socket.h> 19 + #include <ethernet.h> 20 + #include "s390-ccw.h" 21 + #include "virtio.h" 22 + 23 + #ifndef DEBUG_VIRTIO_NET 24 + #define DEBUG_VIRTIO_NET 0 25 + #endif 26 + 27 + #define VIRTIO_NET_F_MAC_BIT (1 << 5) 28 + 29 + #define VQ_RX 0 /* Receive queue */ 30 + #define VQ_TX 1 /* Transmit queue */ 31 + 32 + struct VirtioNetHdr { 33 + uint8_t flags; 34 + uint8_t gso_type; 35 + uint16_t hdr_len; 36 + uint16_t gso_size; 37 + uint16_t csum_start; 38 + uint16_t csum_offset; 39 + /*uint16_t num_buffers;*/ /* Only with VIRTIO_NET_F_MRG_RXBUF or VIRTIO1 */ 40 + }; 41 + typedef struct VirtioNetHdr VirtioNetHdr; 42 + 43 + static uint16_t rx_last_idx; /* Last index in receive queue "used" ring */ 44 + 45 + int virtio_net_init(void *mac_addr) 46 + { 47 + VDev *vdev = virtio_get_device(); 48 + VRing *rxvq = &vdev->vrings[VQ_RX]; 49 + void *buf; 50 + int i; 51 + 52 + vdev->guest_features[0] = VIRTIO_NET_F_MAC_BIT; 53 + virtio_setup_ccw(vdev); 54 + 55 + IPL_assert(vdev->guest_features[0] & VIRTIO_NET_F_MAC_BIT, 56 + "virtio-net device does not support the MAC address feature"); 57 + memcpy(mac_addr, vdev->config.net.mac, ETH_ALEN); 58 + 59 + for (i = 0; i < 64; i++) { 60 + buf = malloc(ETH_MTU_SIZE + sizeof(VirtioNetHdr)); 61 + IPL_assert(buf != NULL, "Can not allocate memory for receive buffers"); 62 + vring_send_buf(rxvq, buf, ETH_MTU_SIZE + sizeof(VirtioNetHdr), 63 + VRING_DESC_F_WRITE); 64 + } 65 + vring_notify(rxvq); 66 + 67 + return 0; 68 + } 69 + 70 + int send(int fd, const void *buf, int len, int flags) 71 + { 72 + VirtioNetHdr tx_hdr; 73 + VDev *vdev = virtio_get_device(); 74 + VRing *txvq = &vdev->vrings[VQ_TX]; 75 + 76 + /* Set up header - we do not use anything special, so simply clear it */ 77 + memset(&tx_hdr, 0, sizeof(tx_hdr)); 78 + 79 + vring_send_buf(txvq, &tx_hdr, sizeof(tx_hdr), VRING_DESC_F_NEXT); 80 + vring_send_buf(txvq, (void *)buf, len, VRING_HIDDEN_IS_CHAIN); 81 + while (!vr_poll(txvq)) { 82 + yield(); 83 + } 84 + if (drain_irqs(txvq->schid)) { 85 + puts("send: drain irqs failed"); 86 + return -1; 87 + } 88 + 89 + return len; 90 + } 91 + 92 + int recv(int fd, void *buf, int maxlen, int flags) 93 + { 94 + VDev *vdev = virtio_get_device(); 95 + VRing *rxvq = &vdev->vrings[VQ_RX]; 96 + int len, id; 97 + uint8_t *pkt; 98 + 99 + if (rx_last_idx == rxvq->used->idx) { 100 + return 0; 101 + } 102 + 103 + len = rxvq->used->ring[rx_last_idx % rxvq->num].len - sizeof(VirtioNetHdr); 104 + if (len > maxlen) { 105 + puts("virtio-net: Receive buffer too small"); 106 + len = maxlen; 107 + } 108 + id = rxvq->used->ring[rx_last_idx % rxvq->num].id % rxvq->num; 109 + pkt = (uint8_t *)(rxvq->desc[id].addr + sizeof(VirtioNetHdr)); 110 + 111 + #if DEBUG_VIRTIO_NET /* Dump packet */ 112 + int i; 113 + printf("\nbuf %p: len=%i\n", (void *)rxvq->desc[id].addr, len); 114 + for (i = 0; i < 64; i++) { 115 + printf(" %02x", pkt[i]); 116 + if ((i % 16) == 15) { 117 + printf("\n"); 118 + } 119 + } 120 + printf("\n"); 121 + #endif 122 + 123 + /* Copy data to destination buffer */ 124 + memcpy(buf, pkt, len); 125 + 126 + /* Mark buffer as available to the host again */ 127 + rxvq->avail->ring[rxvq->avail->idx % rxvq->num] = id; 128 + rxvq->avail->idx = rxvq->avail->idx + 1; 129 + vring_notify(rxvq); 130 + 131 + /* Move index to next entry */ 132 + rx_last_idx = rx_last_idx + 1; 133 + 134 + return len; 135 + }
+1
pc-bios/s390-ccw/virtio-scsi.c
··· 9 9 * directory. 10 10 */ 11 11 12 + #include "libc.h" 12 13 #include "s390-ccw.h" 13 14 #include "virtio.h" 14 15 #include "scsi.h"
+29 -277
pc-bios/s390-ccw/virtio.c
··· 8 8 * directory. 9 9 */ 10 10 11 + #include "libc.h" 11 12 #include "s390-ccw.h" 12 13 #include "virtio.h" 13 14 #include "virtio-scsi.h" 15 + #include "bswap.h" 14 16 15 17 #define VRING_WAIT_REPLY_TIMEOUT 3 16 18 ··· 69 71 * Virtio functions * 70 72 ***********************************************/ 71 73 72 - static int drain_irqs(SubChannelId schid) 74 + int drain_irqs(SubChannelId schid) 73 75 { 74 76 Irb irb = {}; 75 77 int r = 0; ··· 148 150 debug_print_addr("init vr", vr); 149 151 } 150 152 151 - static bool vring_notify(VRing *vr) 153 + bool vring_notify(VRing *vr) 152 154 { 153 155 vr->cookie = virtio_notify(vr->schid, vr->id, vr->cookie); 154 156 return vr->cookie >= 0; 155 157 } 156 158 157 - static void vring_send_buf(VRing *vr, void *p, int len, int flags) 159 + void vring_send_buf(VRing *vr, void *p, int len, int flags) 158 160 { 159 161 /* For follow-up chains we need to keep the first entry point */ 160 162 if (!(flags & VRING_HIDDEN_IS_CHAIN)) { ··· 187 189 return (get_clock() >> 12) / 1000000; 188 190 } 189 191 190 - static int vr_poll(VRing *vr) 192 + int vr_poll(VRing *vr) 191 193 { 192 194 if (vr->used->idx == vr->used_idx) { 193 195 vring_notify(vr); ··· 209 211 * 210 212 * Returns 0 on success, 1 on timeout. 211 213 */ 212 - static int vring_wait_reply(void) 214 + int vring_wait_reply(void) 213 215 { 214 216 ulong target_second = get_second() + vdev.wait_reply_timeout; 215 217 ··· 246 248 return 0; 247 249 } 248 250 249 - /*********************************************** 250 - * Virtio block * 251 - ***********************************************/ 252 - 253 - static int virtio_blk_read_many(VDev *vdev, 254 - ulong sector, void *load_addr, int sec_num) 255 - { 256 - VirtioBlkOuthdr out_hdr; 257 - u8 status; 258 - VRing *vr = &vdev->vrings[vdev->cmd_vr_idx]; 259 - 260 - /* Tell the host we want to read */ 261 - out_hdr.type = VIRTIO_BLK_T_IN; 262 - out_hdr.ioprio = 99; 263 - out_hdr.sector = virtio_sector_adjust(sector); 264 - 265 - vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT); 266 - 267 - /* This is where we want to receive data */ 268 - vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num, 269 - VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN | 270 - VRING_DESC_F_NEXT); 271 - 272 - /* status field */ 273 - vring_send_buf(vr, &status, sizeof(u8), 274 - VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN); 275 - 276 - /* Now we can tell the host to read */ 277 - vring_wait_reply(); 278 - 279 - if (drain_irqs(vr->schid)) { 280 - /* Well, whatever status is supposed to contain... */ 281 - status = 1; 282 - } 283 - return status; 284 - } 285 - 286 - int virtio_read_many(ulong sector, void *load_addr, int sec_num) 287 - { 288 - switch (vdev.senseid.cu_model) { 289 - case VIRTIO_ID_BLOCK: 290 - return virtio_blk_read_many(&vdev, sector, load_addr, sec_num); 291 - case VIRTIO_ID_SCSI: 292 - return virtio_scsi_read_many(&vdev, sector, load_addr, sec_num); 293 - } 294 - panic("\n! No readable IPL device !\n"); 295 - return -1; 296 - } 297 - 298 - unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, 299 - ulong subchan_id, void *load_addr) 300 - { 301 - u8 status; 302 - int sec = rec_list1; 303 - int sec_num = ((rec_list2 >> 32) & 0xffff) + 1; 304 - int sec_len = rec_list2 >> 48; 305 - ulong addr = (ulong)load_addr; 306 - 307 - if (sec_len != virtio_get_block_size()) { 308 - return -1; 309 - } 310 - 311 - sclp_print("."); 312 - status = virtio_read_many(sec, (void *)addr, sec_num); 313 - if (status) { 314 - panic("I/O Error"); 315 - } 316 - addr += sec_num * virtio_get_block_size(); 317 - 318 - return addr; 319 - } 320 - 321 - int virtio_read(ulong sector, void *load_addr) 322 - { 323 - return virtio_read_many(sector, load_addr, 1); 324 - } 325 - 326 - /* 327 - * Other supported value pairs, if any, would need to be added here. 328 - * Note: head count is always 15. 329 - */ 330 - static inline u8 virtio_eckd_sectors_for_block_size(int size) 331 - { 332 - switch (size) { 333 - case 512: 334 - return 49; 335 - case 1024: 336 - return 33; 337 - case 2048: 338 - return 21; 339 - case 4096: 340 - return 12; 341 - } 342 - return 0; 343 - } 344 - 345 - VirtioGDN virtio_guessed_disk_nature(void) 346 - { 347 - return vdev.guessed_disk_nature; 348 - } 349 - 350 - void virtio_assume_scsi(void) 351 - { 352 - switch (vdev.senseid.cu_model) { 353 - case VIRTIO_ID_BLOCK: 354 - vdev.guessed_disk_nature = VIRTIO_GDN_SCSI; 355 - vdev.config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE; 356 - vdev.config.blk.physical_block_exp = 0; 357 - vdev.blk_factor = 1; 358 - break; 359 - case VIRTIO_ID_SCSI: 360 - vdev.scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE; 361 - break; 362 - } 363 - } 364 - 365 - void virtio_assume_iso9660(void) 366 - { 367 - switch (vdev.senseid.cu_model) { 368 - case VIRTIO_ID_BLOCK: 369 - vdev.guessed_disk_nature = VIRTIO_GDN_SCSI; 370 - vdev.config.blk.blk_size = VIRTIO_ISO_BLOCK_SIZE; 371 - vdev.config.blk.physical_block_exp = 0; 372 - vdev.blk_factor = VIRTIO_ISO_BLOCK_SIZE / VIRTIO_SECTOR_SIZE; 373 - break; 374 - case VIRTIO_ID_SCSI: 375 - vdev.scsi_block_size = VIRTIO_ISO_BLOCK_SIZE; 376 - break; 377 - } 378 - } 379 - 380 - void virtio_assume_eckd(void) 381 - { 382 - vdev.guessed_disk_nature = VIRTIO_GDN_DASD; 383 - vdev.blk_factor = 1; 384 - vdev.config.blk.physical_block_exp = 0; 385 - switch (vdev.senseid.cu_model) { 386 - case VIRTIO_ID_BLOCK: 387 - vdev.config.blk.blk_size = 4096; 388 - break; 389 - case VIRTIO_ID_SCSI: 390 - vdev.config.blk.blk_size = vdev.scsi_block_size; 391 - break; 392 - } 393 - vdev.config.blk.geometry.heads = 15; 394 - vdev.config.blk.geometry.sectors = 395 - virtio_eckd_sectors_for_block_size(vdev.config.blk.blk_size); 396 - } 397 - 398 - bool virtio_disk_is_scsi(void) 251 + void virtio_setup_ccw(VDev *vdev) 399 252 { 400 - if (vdev.guessed_disk_nature == VIRTIO_GDN_SCSI) { 401 - return true; 402 - } 403 - switch (vdev.senseid.cu_model) { 404 - case VIRTIO_ID_BLOCK: 405 - return (vdev.config.blk.geometry.heads == 255) 406 - && (vdev.config.blk.geometry.sectors == 63) 407 - && (virtio_get_block_size() == VIRTIO_SCSI_BLOCK_SIZE); 408 - case VIRTIO_ID_SCSI: 409 - return true; 410 - } 411 - return false; 412 - } 413 - 414 - bool virtio_disk_is_eckd(void) 415 - { 416 - const int block_size = virtio_get_block_size(); 417 - 418 - if (vdev.guessed_disk_nature == VIRTIO_GDN_DASD) { 419 - return true; 420 - } 421 - switch (vdev.senseid.cu_model) { 422 - case VIRTIO_ID_BLOCK: 423 - return (vdev.config.blk.geometry.heads == 15) 424 - && (vdev.config.blk.geometry.sectors == 425 - virtio_eckd_sectors_for_block_size(block_size)); 426 - case VIRTIO_ID_SCSI: 427 - return false; 428 - } 429 - return false; 430 - } 431 - 432 - bool virtio_ipl_disk_is_valid(void) 433 - { 434 - return virtio_disk_is_scsi() || virtio_disk_is_eckd(); 435 - } 436 - 437 - int virtio_get_block_size(void) 438 - { 439 - switch (vdev.senseid.cu_model) { 440 - case VIRTIO_ID_BLOCK: 441 - return vdev.config.blk.blk_size << vdev.config.blk.physical_block_exp; 442 - case VIRTIO_ID_SCSI: 443 - return vdev.scsi_block_size; 444 - } 445 - return 0; 446 - } 447 - 448 - uint8_t virtio_get_heads(void) 449 - { 450 - switch (vdev.senseid.cu_model) { 451 - case VIRTIO_ID_BLOCK: 452 - return vdev.config.blk.geometry.heads; 453 - case VIRTIO_ID_SCSI: 454 - return vdev.guessed_disk_nature == VIRTIO_GDN_DASD 455 - ? vdev.config.blk.geometry.heads : 255; 456 - } 457 - return 0; 458 - } 459 - 460 - uint8_t virtio_get_sectors(void) 461 - { 462 - switch (vdev.senseid.cu_model) { 463 - case VIRTIO_ID_BLOCK: 464 - return vdev.config.blk.geometry.sectors; 465 - case VIRTIO_ID_SCSI: 466 - return vdev.guessed_disk_nature == VIRTIO_GDN_DASD 467 - ? vdev.config.blk.geometry.sectors : 63; 468 - } 469 - return 0; 470 - } 471 - 472 - uint64_t virtio_get_blocks(void) 473 - { 474 - const uint64_t factor = virtio_get_block_size() / VIRTIO_SECTOR_SIZE; 475 - switch (vdev.senseid.cu_model) { 476 - case VIRTIO_ID_BLOCK: 477 - return vdev.config.blk.capacity / factor; 478 - case VIRTIO_ID_SCSI: 479 - return vdev.scsi_last_block / factor; 480 - } 481 - return 0; 482 - } 483 - 484 - static void virtio_setup_ccw(VDev *vdev) 485 - { 486 - int i, cfg_size = 0; 253 + int i, rc, cfg_size = 0; 487 254 unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK; 255 + struct VirtioFeatureDesc { 256 + uint32_t features; 257 + uint8_t index; 258 + } __attribute__((packed)) feats; 488 259 489 260 IPL_assert(virtio_is_supported(vdev->schid), "PE"); 490 261 /* device ID has been established now */ ··· 495 266 run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0); 496 267 497 268 switch (vdev->senseid.cu_model) { 269 + case VIRTIO_ID_NET: 270 + vdev->nr_vqs = 2; 271 + vdev->cmd_vr_idx = 0; 272 + cfg_size = sizeof(vdev->config.net); 273 + break; 498 274 case VIRTIO_ID_BLOCK: 499 275 vdev->nr_vqs = 1; 500 276 vdev->cmd_vr_idx = 0; ··· 511 287 IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0, 512 288 "Could not get block device configuration"); 513 289 514 - /* 515 - * Skipping CCW_CMD_READ_FEAT. We're not doing anything fancy, and 516 - * we'll just stop dead anyway if anything does not work like we 517 - * expect it. 518 - */ 290 + /* Feature negotiation */ 291 + for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) { 292 + feats.features = 0; 293 + feats.index = i; 294 + rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats)); 295 + IPL_assert(rc == 0, "Could not get features bits"); 296 + vdev->guest_features[i] &= bswap32(feats.features); 297 + feats.features = bswap32(vdev->guest_features[i]); 298 + rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats)); 299 + IPL_assert(rc == 0, "Could not set features bits"); 300 + } 519 301 520 302 for (i = 0; i < vdev->nr_vqs; i++) { 521 303 VqInfo info = { ··· 541 323 IPL_assert( 542 324 run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status)) == 0, 543 325 "Could not write status to host"); 544 - } 545 - 546 - void virtio_setup_device(SubChannelId schid) 547 - { 548 - vdev.schid = schid; 549 - virtio_setup_ccw(&vdev); 550 - 551 - switch (vdev.senseid.cu_model) { 552 - case VIRTIO_ID_BLOCK: 553 - sclp_print("Using virtio-blk.\n"); 554 - if (!virtio_ipl_disk_is_valid()) { 555 - /* make sure all getters but blocksize return 0 for 556 - * invalid IPL disk 557 - */ 558 - memset(&vdev.config.blk, 0, sizeof(vdev.config.blk)); 559 - virtio_assume_scsi(); 560 - } 561 - break; 562 - case VIRTIO_ID_SCSI: 563 - IPL_assert(vdev.config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE, 564 - "Config: sense size mismatch"); 565 - IPL_assert(vdev.config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE, 566 - "Config: CDB size mismatch"); 567 - 568 - sclp_print("Using virtio-scsi.\n"); 569 - virtio_scsi_setup(&vdev); 570 - break; 571 - default: 572 - panic("\n! No IPL device available !\n"); 573 - } 574 326 } 575 327 576 328 bool virtio_is_supported(SubChannelId schid)
+17 -29
pc-bios/s390-ccw/virtio.h
··· 11 11 #ifndef VIRTIO_H 12 12 #define VIRTIO_H 13 13 14 - #include "s390-ccw.h" 15 - 16 14 /* Status byte for guest to report progress, and synchronize features. */ 17 15 /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ 18 16 #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 ··· 32 30 }; 33 31 typedef enum VirtioDevType VirtioDevType; 34 32 35 - struct VirtioDevHeader { 36 - VirtioDevType type:8; 37 - uint8_t num_vq; 38 - uint8_t feature_len; 39 - uint8_t config_len; 40 - uint8_t status; 41 - uint8_t vqconfig[]; 42 - } __attribute__((packed)); 43 - typedef struct VirtioDevHeader VirtioDevHeader; 44 - 45 - struct VirtioVqConfig { 46 - uint64_t token; 47 - uint64_t address; 48 - uint16_t num; 49 - uint8_t pad[6]; 50 - } __attribute__((packed)); 51 - typedef struct VirtioVqConfig VirtioVqConfig; 52 - 53 33 struct VqInfo { 54 34 uint64_t queue; 55 35 uint32_t align; ··· 63 43 uint16_t num; 64 44 } __attribute__((packed)); 65 45 typedef struct VqConfig VqConfig; 66 - 67 - struct VirtioDev { 68 - VirtioDevHeader *header; 69 - VirtioVqConfig *vqconfig; 70 - char *host_features; 71 - char *guest_features; 72 - char *config; 73 - }; 74 - typedef struct VirtioDev VirtioDev; 75 46 76 47 #define VIRTIO_RING_SIZE (PAGE_SIZE * 8) 77 48 #define VIRTIO_MAX_VQS 3 ··· 254 225 }; 255 226 typedef struct ScsiDevice ScsiDevice; 256 227 228 + struct VirtioNetConfig { 229 + uint8_t mac[6]; 230 + /* uint16_t status; */ /* Only with VIRTIO_NET_F_STATUS */ 231 + /* uint16_t max_virtqueue_pairs; */ /* Only with VIRTIO_NET_F_MQ */ 232 + }; 233 + typedef struct VirtioNetConfig VirtioNetConfig; 234 + 257 235 struct VDev { 258 236 int nr_vqs; 259 237 VRing *vrings; ··· 266 244 union { 267 245 VirtioBlkConfig blk; 268 246 VirtioScsiConfig scsi; 247 + VirtioNetConfig net; 269 248 } config; 270 249 ScsiDevice *scsi_device; 271 250 bool is_cdrom; ··· 278 257 ScsiDevice selected_scsi_device; 279 258 uint64_t netboot_start_addr; 280 259 uint32_t max_transfer; 260 + uint32_t guest_features[2]; 281 261 }; 282 262 typedef struct VDev VDev; 283 263 ··· 291 271 }; 292 272 typedef struct VirtioCmd VirtioCmd; 293 273 274 + bool vring_notify(VRing *vr); 275 + int drain_irqs(SubChannelId schid); 276 + void vring_send_buf(VRing *vr, void *p, int len, int flags); 277 + int vr_poll(VRing *vr); 278 + int vring_wait_reply(void); 294 279 int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd); 280 + void virtio_setup_ccw(VDev *vdev); 281 + 282 + int virtio_net_init(void *mac_addr); 295 283 296 284 #endif /* VIRTIO_H */
pc-bios/s390-netboot.img

This is a binary file and will not be displayed.

+18
target/s390x/arch_dump.c
··· 57 57 58 58 typedef struct S390xElfVregsHiStruct S390xElfVregsHi; 59 59 60 + struct S390xElfGSCBStruct { 61 + uint64_t gsregs[4]; 62 + } QEMU_PACKED; 63 + 64 + typedef struct S390xElfGSCBStruct S390xElfGSCB; 65 + 60 66 typedef struct noteStruct { 61 67 Elf64_Nhdr hdr; 62 68 char name[8]; ··· 65 71 S390xElfFpregset fpregset; 66 72 S390xElfVregsLo vregslo; 67 73 S390xElfVregsHi vregshi; 74 + S390xElfGSCB gscb; 68 75 uint32_t prefix; 69 76 uint64_t timer; 70 77 uint64_t todcmp; ··· 126 133 } 127 134 } 128 135 136 + static void s390x_write_elf64_gscb(Note *note, S390CPU *cpu, int id) 137 + { 138 + int i; 139 + 140 + note->hdr.n_type = cpu_to_be32(NT_S390_GS_CB); 141 + for (i = 0; i < 4; i++) { 142 + note->contents.gscb.gsregs[i] = cpu_to_be64(cpu->env.gscb[i]); 143 + } 144 + } 145 + 129 146 static void s390x_write_elf64_timer(Note *note, S390CPU *cpu, int id) 130 147 { 131 148 note->hdr.n_type = cpu_to_be32(NT_S390_TIMER); ··· 181 198 {sizeof(((Note *)0)->contents.todpreg), s390x_write_elf64_todpreg}, 182 199 {sizeof(((Note *)0)->contents.vregslo), s390x_write_elf64_vregslo}, 183 200 {sizeof(((Note *)0)->contents.vregshi), s390x_write_elf64_vregshi}, 201 + {sizeof(((Note *)0)->contents.gscb), s390x_write_elf64_gscb}, 184 202 { 0, NULL} 185 203 }; 186 204
+8
target/s390x/cpu.h
··· 89 89 CPU_DoubleU vregs[32][2]; /* vector registers */ 90 90 uint32_t aregs[16]; /* access registers */ 91 91 uint8_t riccb[64]; /* runtime instrumentation control */ 92 + uint64_t gscb[4]; /* guarded storage control */ 92 93 93 94 /* Fields up to this point are not cleared by initial CPU reset */ 94 95 struct {} start_initial_reset_fields; ··· 1158 1159 int vq, bool assign); 1159 1160 int kvm_s390_cpu_restart(S390CPU *cpu); 1160 1161 int kvm_s390_get_memslot_count(KVMState *s); 1162 + int kvm_s390_cmma_active(void); 1161 1163 void kvm_s390_cmma_reset(void); 1162 1164 int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); 1163 1165 void kvm_s390_reset_vcpu(S390CPU *cpu); ··· 1165 1167 void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); 1166 1168 int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); 1167 1169 int kvm_s390_get_ri(void); 1170 + int kvm_s390_get_gs(void); 1168 1171 void kvm_s390_crypto_reset(void); 1169 1172 #else 1170 1173 static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, ··· 1216 1219 return 0; 1217 1220 } 1218 1221 static inline int kvm_s390_get_ri(void) 1222 + { 1223 + return 0; 1224 + } 1225 + static inline int kvm_s390_get_gs(void) 1219 1226 { 1220 1227 return 0; 1221 1228 } ··· 1327 1334 #define MCIC_VB_CR 0x0000000400000000ULL 1328 1335 #define MCIC_VB_ST 0x0000000100000000ULL 1329 1336 #define MCIC_VB_AR 0x0000000040000000ULL 1337 + #define MCIC_VB_GS 0x0000000008000000ULL 1330 1338 #define MCIC_VB_PR 0x0000000000200000ULL 1331 1339 #define MCIC_VB_FC 0x0000000000100000ULL 1332 1340 #define MCIC_VB_CT 0x0000000000020000ULL
+50 -2
target/s390x/cpu_features.c
··· 59 59 FEAT_INIT("exrl", S390_FEAT_TYPE_STFL, 35, "Execute-extensions facility"), 60 60 FEAT_INIT("emon", S390_FEAT_TYPE_STFL, 36, "Enhanced-monitor facility"), 61 61 FEAT_INIT("fpe", S390_FEAT_TYPE_STFL, 37, "Floating-point extension facility"), 62 + FEAT_INIT("opc", S390_FEAT_TYPE_STFL, 38, "Order Preserving Compression facility"), 62 63 FEAT_INIT("sprogp", S390_FEAT_TYPE_STFL, 40, "Set-program-parameters facility"), 63 64 FEAT_INIT("fpseh", S390_FEAT_TYPE_STFL, 41, "Floating-point-support-enhancement facilities"), 64 65 FEAT_INIT("dfp", S390_FEAT_TYPE_STFL, 42, "DFP (decimal-floating-point) facility"), ··· 72 73 FEAT_INIT("ltlbc", S390_FEAT_TYPE_STFL, 51, "Local-TLB-clearing facility"), 73 74 FEAT_INIT("iacc2", S390_FEAT_TYPE_STFL, 52, "Interlocked-access facility 2"), 74 75 FEAT_INIT("stfle53", S390_FEAT_TYPE_STFL, 53, "Various facilities introduced with z13"), 76 + FEAT_INIT("eec", S390_FEAT_TYPE_STFL, 54, "Entropy encoding compression facility"), 75 77 FEAT_INIT("msa5-base", S390_FEAT_TYPE_STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)"), 78 + FEAT_INIT("minste2", S390_FEAT_TYPE_STFL, 58, "Miscellaneous-instruction-extensions facility 2"), 79 + FEAT_INIT("sema", S390_FEAT_TYPE_STFL, 59, "Semaphore-assist facility"), 80 + FEAT_INIT("tsi", S390_FEAT_TYPE_STFL, 60, "Time-slice Instrumentation facility"), 76 81 FEAT_INIT("ri", S390_FEAT_TYPE_STFL, 64, "CPU runtime-instrumentation facility"), 82 + FEAT_INIT("zpci", S390_FEAT_TYPE_STFL, 69, "z/PCI facility"), 83 + FEAT_INIT("aen", S390_FEAT_TYPE_STFL, 71, "General-purpose-adapter-event-notification facility"), 84 + FEAT_INIT("ais", S390_FEAT_TYPE_STFL, 72, "General-purpose-adapter-interruption-suppression facility"), 77 85 FEAT_INIT("te", S390_FEAT_TYPE_STFL, 73, "Transactional-execution facility"), 78 86 FEAT_INIT("sthyi", S390_FEAT_TYPE_STFL, 74, "Store-hypervisor-information facility"), 79 87 FEAT_INIT("aefsi", S390_FEAT_TYPE_STFL, 75, "Access-exception-fetch/store-indication facility"), ··· 82 90 FEAT_INIT("edat2", S390_FEAT_TYPE_STFL, 78, "Enhanced-DAT facility 2"), 83 91 FEAT_INIT("dfppc", S390_FEAT_TYPE_STFL, 80, "Decimal-floating-point packed-conversion facility"), 84 92 FEAT_INIT("vx", S390_FEAT_TYPE_STFL, 129, "Vector facility"), 93 + FEAT_INIT("iep", S390_FEAT_TYPE_STFL, 130, "Instruction-execution-protection facility"), 94 + FEAT_INIT("sea_esop2", S390_FEAT_TYPE_STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2"), 95 + FEAT_INIT("gs", S390_FEAT_TYPE_STFL, 133, "Guarded-storage facility"), 96 + FEAT_INIT("vxpd", S390_FEAT_TYPE_STFL, 134, "Vector packed decimal facility"), 97 + FEAT_INIT("vxeh", S390_FEAT_TYPE_STFL, 135, "Vector enhancements facility"), 98 + FEAT_INIT("mepoch", S390_FEAT_TYPE_STFL, 139, "Multiple-epoch facility"), 99 + FEAT_INIT("tpei", S390_FEAT_TYPE_STFL, 144, "Test-pending-external-interruption facility"), 100 + FEAT_INIT("irbm", S390_FEAT_TYPE_STFL, 145, "Insert-reference-bits-multiple facility"), 101 + FEAT_INIT("msa8-base", S390_FEAT_TYPE_STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)"), 102 + FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), 85 103 104 + /* SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ 86 105 FEAT_INIT("gsls", S390_FEAT_TYPE_SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility"), 87 106 FEAT_INIT("esop", S390_FEAT_TYPE_SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility"), 107 + FEAT_INIT("hpma2", S390_FEAT_TYPE_SCLP_CONF_CHAR, 90, "Host page management assist 2 Facility"), /* 91-2 */ 108 + FEAT_INIT("kss", S390_FEAT_TYPE_SCLP_CONF_CHAR, 151, "SIE: Keyless-subset facility"), /* 98-7 */ 88 109 110 + /* SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ 89 111 FEAT_INIT("64bscao", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility"), 90 112 FEAT_INIT("cmma", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-management assist"), 91 113 FEAT_INIT("pfmfi", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility"), ··· 182 204 FEAT_INIT("kimd-sha-1", S390_FEAT_TYPE_KIMD, 1, "KIMD SHA-1"), 183 205 FEAT_INIT("kimd-sha-256", S390_FEAT_TYPE_KIMD, 2, "KIMD SHA-256"), 184 206 FEAT_INIT("kimd-sha-512", S390_FEAT_TYPE_KIMD, 3, "KIMD SHA-512"), 207 + FEAT_INIT("kimd-sha3-224", S390_FEAT_TYPE_KIMD, 32, "KIMD SHA3-224"), 208 + FEAT_INIT("kimd-sha3-256", S390_FEAT_TYPE_KIMD, 33, "KIMD SHA3-256"), 209 + FEAT_INIT("kimd-sha3-384", S390_FEAT_TYPE_KIMD, 34, "KIMD SHA3-384"), 210 + FEAT_INIT("kimd-sha3-512", S390_FEAT_TYPE_KIMD, 35, "KIMD SHA3-512"), 211 + FEAT_INIT("kimd-shake-128", S390_FEAT_TYPE_KIMD, 36, "KIMD SHAKE-128"), 212 + FEAT_INIT("kimd-shake-256", S390_FEAT_TYPE_KIMD, 37, "KIMD SHAKE-256"), 185 213 FEAT_INIT("kimd-ghash", S390_FEAT_TYPE_KIMD, 65, "KIMD GHASH"), 214 + 186 215 FEAT_INIT("klmd-sha-1", S390_FEAT_TYPE_KLMD, 1, "KLMD SHA-1"), 187 216 FEAT_INIT("klmd-sha-256", S390_FEAT_TYPE_KLMD, 2, "KLMD SHA-256"), 188 217 FEAT_INIT("klmd-sha-512", S390_FEAT_TYPE_KLMD, 3, "KLMD SHA-512"), 218 + FEAT_INIT("klmd-sha3-224", S390_FEAT_TYPE_KLMD, 32, "KLMD SHA3-224"), 219 + FEAT_INIT("klmd-sha3-256", S390_FEAT_TYPE_KLMD, 33, "KLMD SHA3-256"), 220 + FEAT_INIT("klmd-sha3-384", S390_FEAT_TYPE_KLMD, 34, "KLMD SHA3-384"), 221 + FEAT_INIT("klmd-sha3-512", S390_FEAT_TYPE_KLMD, 35, "KLMD SHA3-512"), 222 + FEAT_INIT("klmd-shake-128", S390_FEAT_TYPE_KLMD, 36, "KLMD SHAKE-128"), 223 + FEAT_INIT("klmd-shake-256", S390_FEAT_TYPE_KLMD, 37, "KLMD SHAKE-256"), 189 224 190 225 FEAT_INIT("pckmo-edea", S390_FEAT_TYPE_PCKMO, 1, "PCKMO Encrypted-DEA-Key"), 191 226 FEAT_INIT("pckmo-etdea-128", S390_FEAT_TYPE_PCKMO, 2, "PCKMO Encrypted-TDEA-128-Key"), ··· 251 286 FEAT_INIT("pcc-xts-eaes-256", S390_FEAT_TYPE_PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256"), 252 287 253 288 FEAT_INIT("ppno-sha-512-drng", S390_FEAT_TYPE_PPNO, 3, "PPNO SHA-512-DRNG"), 289 + FEAT_INIT("prno-trng-qrtcr", S390_FEAT_TYPE_PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio"), 290 + FEAT_INIT("prno-trng", S390_FEAT_TYPE_PPNO, 114, "PRNO TRNG"), 291 + 292 + FEAT_INIT("kma-gcm-aes-128", S390_FEAT_TYPE_KMA, 18, "KMA GCM-AES-128"), 293 + FEAT_INIT("kma-gcm-aes-192", S390_FEAT_TYPE_KMA, 19, "KMA GCM-AES-192"), 294 + FEAT_INIT("kma-gcm-aes-256", S390_FEAT_TYPE_KMA, 20, "KMA GCM-AES-256"), 295 + FEAT_INIT("kma-gcm-eaes-128", S390_FEAT_TYPE_KMA, 26, "KMA GCM-Encrypted-AES-128"), 296 + FEAT_INIT("kma-gcm-eaes-192", S390_FEAT_TYPE_KMA, 27, "KMA GCM-Encrypted-AES-192"), 297 + FEAT_INIT("kma-gcm-eaes-256", S390_FEAT_TYPE_KMA, 28, "KMA GCM-Encrypted-AES-256"), 254 298 }; 255 299 256 300 const S390FeatDef *s390_feat_def(S390Feat feat) ··· 293 337 int bit_nr; 294 338 295 339 if (type == S390_FEAT_TYPE_STFL && test_bit(S390_FEAT_ZARCH, features)) { 296 - /* z/Architecture is always active if around */ 297 - data[0] |= 0x20; 340 + /* Features that are always active */ 341 + data[0] |= 0x20; /* z/Architecture */ 342 + data[17] |= 0x20; /* Configuration-z-architectural-mode */ 298 343 } 299 344 300 345 feat = find_first_bit(features, S390_FEAT_MAX); ··· 383 428 FEAT_GROUP_INIT("msa3", MSA_EXT_3, "Message-security-assist-extension 3 facility"), 384 429 FEAT_GROUP_INIT("msa4", MSA_EXT_4, "Message-security-assist-extension 4 facility"), 385 430 FEAT_GROUP_INIT("msa5", MSA_EXT_5, "Message-security-assist-extension 5 facility"), 431 + FEAT_GROUP_INIT("msa6", MSA_EXT_6, "Message-security-assist-extension 6 facility"), 432 + FEAT_GROUP_INIT("msa7", MSA_EXT_7, "Message-security-assist-extension 7 facility"), 433 + FEAT_GROUP_INIT("msa8", MSA_EXT_8, "Message-security-assist-extension 8 facility"), 386 434 }; 387 435 388 436 const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group)
+4
target/s390x/cpu_features.h
··· 37 37 S390_FEAT_TYPE_KMO, 38 38 S390_FEAT_TYPE_PCC, 39 39 S390_FEAT_TYPE_PPNO, 40 + S390_FEAT_TYPE_KMA, 40 41 } S390FeatType; 41 42 42 43 /* Definition of a CPU feature */ ··· 74 75 S390_FEAT_GROUP_MSA_EXT_3, 75 76 S390_FEAT_GROUP_MSA_EXT_4, 76 77 S390_FEAT_GROUP_MSA_EXT_5, 78 + S390_FEAT_GROUP_MSA_EXT_6, 79 + S390_FEAT_GROUP_MSA_EXT_7, 80 + S390_FEAT_GROUP_MSA_EXT_8, 77 81 S390_FEAT_GROUP_MAX, 78 82 } S390FeatGroup; 79 83
+77
target/s390x/cpu_features_def.h
··· 15 15 #define TARGET_S390X_CPU_FEATURES_DEF_H 16 16 17 17 typedef enum { 18 + /* Stfle */ 18 19 S390_FEAT_ESAN3 = 0, 19 20 S390_FEAT_ZARCH, 20 21 S390_FEAT_DAT_ENH, ··· 49 50 S390_FEAT_EXECUTE_EXT, 50 51 S390_FEAT_ENHANCED_MONITOR, 51 52 S390_FEAT_FLOATING_POINT_EXT, 53 + S390_FEAT_ORDER_PRESERVING_COMPRESSION, 52 54 S390_FEAT_SET_PROGRAM_PARAMETERS, 53 55 S390_FEAT_FLOATING_POINT_SUPPPORT_ENH, 54 56 S390_FEAT_DFP, ··· 62 64 S390_FEAT_LOCAL_TLB_CLEARING, 63 65 S390_FEAT_INTERLOCKED_ACCESS_2, 64 66 S390_FEAT_STFLE_53, 67 + S390_FEAT_ENTROPY_ENC_COMP, 65 68 S390_FEAT_MSA_EXT_5, 69 + S390_FEAT_MISC_INSTRUCTION_EXT, 70 + S390_FEAT_SEMAPHORE_ASSIST, 71 + S390_FEAT_TIME_SLICE_INSTRUMENTATION, 66 72 S390_FEAT_RUNTIME_INSTRUMENTATION, 73 + S390_FEAT_ZPCI, 74 + S390_FEAT_ADAPTER_EVENT_NOTIFICATION, 75 + S390_FEAT_ADAPTER_INT_SUPPRESSION, 67 76 S390_FEAT_TRANSACTIONAL_EXE, 68 77 S390_FEAT_STORE_HYPERVISOR_INFO, 69 78 S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, ··· 72 81 S390_FEAT_EDAT_2, 73 82 S390_FEAT_DFP_PACKED_CONVERSION, 74 83 S390_FEAT_VECTOR, 84 + S390_FEAT_INSTRUCTION_EXEC_PROT, 85 + S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, 86 + S390_FEAT_GUARDED_STORAGE, 87 + S390_FEAT_VECTOR_PACKED_DECIMAL, 88 + S390_FEAT_VECTOR_ENH, 89 + S390_FEAT_MULTIPLE_EPOCH, 90 + S390_FEAT_TEST_PENDING_EXT_INTERRUPTION, 91 + S390_FEAT_INSERT_REFERENCE_BITS_MULT, 92 + S390_FEAT_MSA_EXT_8, 93 + S390_FEAT_CMM_NT, 94 + 95 + /* Sclp Conf Char */ 75 96 S390_FEAT_SIE_GSLS, 76 97 S390_FEAT_ESOP, 98 + S390_FEAT_HPMA2, 99 + S390_FEAT_SIE_KSS, 100 + 101 + /* Sclp Conf Char Ext */ 77 102 S390_FEAT_SIE_64BSCAO, 78 103 S390_FEAT_SIE_CMMA, 79 104 S390_FEAT_SIE_PFMFI, 80 105 S390_FEAT_SIE_IBS, 106 + 107 + /* Sclp Cpu */ 81 108 S390_FEAT_SIE_F2, 82 109 S390_FEAT_SIE_SKEY, 83 110 S390_FEAT_SIE_GPERE, ··· 85 112 S390_FEAT_SIE_SIGPIF, 86 113 S390_FEAT_SIE_IB, 87 114 S390_FEAT_SIE_CEI, 115 + 116 + /* Misc */ 88 117 S390_FEAT_DAT_ENH_2, 89 118 S390_FEAT_CMM, 119 + 120 + /* PLO */ 90 121 S390_FEAT_PLO_CL, 91 122 S390_FEAT_PLO_CLG, 92 123 S390_FEAT_PLO_CLGR, ··· 111 142 S390_FEAT_PLO_CSTSTG, 112 143 S390_FEAT_PLO_CSTSTGR, 113 144 S390_FEAT_PLO_CSTSTX, 145 + 146 + /* PTFF */ 114 147 S390_FEAT_PTFF_QTO, 115 148 S390_FEAT_PTFF_QSI, 116 149 S390_FEAT_PTFF_QPT, ··· 118 151 S390_FEAT_PTFF_QTOU, 119 152 S390_FEAT_PTFF_STO, 120 153 S390_FEAT_PTFF_STOU, 154 + 155 + /* KMAC */ 121 156 S390_FEAT_KMAC_DEA, 122 157 S390_FEAT_KMAC_TDEA_128, 123 158 S390_FEAT_KMAC_TDEA_192, ··· 130 165 S390_FEAT_KMAC_EAES_128, 131 166 S390_FEAT_KMAC_EAES_192, 132 167 S390_FEAT_KMAC_EAES_256, 168 + 169 + /* KMC */ 133 170 S390_FEAT_KMC_DEA, 134 171 S390_FEAT_KMC_TDEA_128, 135 172 S390_FEAT_KMC_TDEA_192, ··· 143 180 S390_FEAT_KMC_EAES_192, 144 181 S390_FEAT_KMC_EAES_256, 145 182 S390_FEAT_KMC_PRNG, 183 + 184 + /* KM */ 146 185 S390_FEAT_KM_DEA, 147 186 S390_FEAT_KM_TDEA_128, 148 187 S390_FEAT_KM_TDEA_192, ··· 159 198 S390_FEAT_KM_XTS_AES_256, 160 199 S390_FEAT_KM_XTS_EAES_128, 161 200 S390_FEAT_KM_XTS_EAES_256, 201 + 202 + /* KIMD */ 162 203 S390_FEAT_KIMD_SHA_1, 163 204 S390_FEAT_KIMD_SHA_256, 164 205 S390_FEAT_KIMD_SHA_512, 206 + S390_FEAT_KIMD_SHA3_224, 207 + S390_FEAT_KIMD_SHA3_256, 208 + S390_FEAT_KIMD_SHA3_384, 209 + S390_FEAT_KIMD_SHA3_512, 210 + S390_FEAT_KIMD_SHAKE_128, 211 + S390_FEAT_KIMD_SHAKE_256, 165 212 S390_FEAT_KIMD_GHASH, 213 + 214 + /* KLMD */ 166 215 S390_FEAT_KLMD_SHA_1, 167 216 S390_FEAT_KLMD_SHA_256, 168 217 S390_FEAT_KLMD_SHA_512, 218 + S390_FEAT_KLMD_SHA3_224, 219 + S390_FEAT_KLMD_SHA3_256, 220 + S390_FEAT_KLMD_SHA3_384, 221 + S390_FEAT_KLMD_SHA3_512, 222 + S390_FEAT_KLMD_SHAKE_128, 223 + S390_FEAT_KLMD_SHAKE_256, 224 + 225 + /* PCKMO */ 169 226 S390_FEAT_PCKMO_EDEA, 170 227 S390_FEAT_PCKMO_ETDEA_128, 171 228 S390_FEAT_PCKMO_ETDEA_256, 172 229 S390_FEAT_PCKMO_AES_128, 173 230 S390_FEAT_PCKMO_AES_192, 174 231 S390_FEAT_PCKMO_AES_256, 232 + 233 + /* KMCTR */ 175 234 S390_FEAT_KMCTR_DEA, 176 235 S390_FEAT_KMCTR_TDEA_128, 177 236 S390_FEAT_KMCTR_TDEA_192, ··· 184 243 S390_FEAT_KMCTR_EAES_128, 185 244 S390_FEAT_KMCTR_EAES_192, 186 245 S390_FEAT_KMCTR_EAES_256, 246 + 247 + /* KMF */ 187 248 S390_FEAT_KMF_DEA, 188 249 S390_FEAT_KMF_TDEA_128, 189 250 S390_FEAT_KMF_TDEA_192, ··· 196 257 S390_FEAT_KMF_EAES_128, 197 258 S390_FEAT_KMF_EAES_192, 198 259 S390_FEAT_KMF_EAES_256, 260 + 261 + /* KMO */ 199 262 S390_FEAT_KMO_DEA, 200 263 S390_FEAT_KMO_TDEA_128, 201 264 S390_FEAT_KMO_TDEA_192, ··· 208 271 S390_FEAT_KMO_EAES_128, 209 272 S390_FEAT_KMO_EAES_192, 210 273 S390_FEAT_KMO_EAES_256, 274 + 275 + /* PCC */ 211 276 S390_FEAT_PCC_CMAC_DEA, 212 277 S390_FEAT_PCC_CMAC_TDEA_128, 213 278 S390_FEAT_PCC_CMAC_TDEA_192, ··· 224 289 S390_FEAT_PCC_XTS_AES_256, 225 290 S390_FEAT_PCC_XTS_EAES_128, 226 291 S390_FEAT_PCC_XTS_EAES_256, 292 + 293 + /* PPNO/PRNO */ 227 294 S390_FEAT_PPNO_SHA_512_DRNG, 295 + S390_FEAT_PRNO_TRNG_QRTCR, 296 + S390_FEAT_PRNO_TRNG, 297 + 298 + /* KMA */ 299 + S390_FEAT_KMA_GCM_AES_128, 300 + S390_FEAT_KMA_GCM_AES_192, 301 + S390_FEAT_KMA_GCM_AES_256 , 302 + S390_FEAT_KMA_GCM_EAES_128, 303 + S390_FEAT_KMA_GCM_EAES_192, 304 + S390_FEAT_KMA_GCM_EAES_256, 228 305 S390_FEAT_MAX, 229 306 } S390Feat; 230 307
+51
target/s390x/cpu_models.c
··· 77 77 CPUDEF_INIT(0x2965, 13, 2, 47, 0x08000000U, "z13s", "IBM z13s GA1"), 78 78 }; 79 79 80 + void s390_cpudef_featoff(uint8_t gen, uint8_t ec_ga, S390Feat feat) 81 + { 82 + const S390CPUDef *def; 83 + 84 + def = s390_find_cpu_def(0, gen, ec_ga, NULL); 85 + clear_bit(feat, (unsigned long *)&def->default_feat); 86 + } 87 + 88 + void s390_cpudef_featoff_greater(uint8_t gen, uint8_t ec_ga, S390Feat feat) 89 + { 90 + int i; 91 + 92 + for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) { 93 + const S390CPUDef *def = &s390_cpu_defs[i]; 94 + 95 + if (def->gen < gen) { 96 + continue; 97 + } 98 + if (def->gen == gen && def->ec_ga < ec_ga) { 99 + continue; 100 + } 101 + 102 + clear_bit(feat, (unsigned long *)&def->default_feat); 103 + } 104 + } 105 + 80 106 uint32_t s390_get_hmfai(void) 81 107 { 82 108 static S390CPU *cpu; ··· 671 697 { S390_FEAT_SIE_CMMA, S390_FEAT_CMM }, 672 698 { S390_FEAT_SIE_CMMA, S390_FEAT_SIE_GSLS }, 673 699 { S390_FEAT_SIE_PFMFI, S390_FEAT_EDAT }, 700 + { S390_FEAT_MSA_EXT_8, S390_FEAT_MSA_EXT_3 }, 701 + { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING }, 702 + { S390_FEAT_VECTOR_PACKED_DECIMAL, S390_FEAT_VECTOR }, 703 + { S390_FEAT_VECTOR_ENH, S390_FEAT_VECTOR }, 704 + { S390_FEAT_INSTRUCTION_EXEC_PROT, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2 }, 705 + { S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, S390_FEAT_ESOP }, 706 + { S390_FEAT_CMM_NT, S390_FEAT_CMM }, 707 + { S390_FEAT_GUARDED_STORAGE, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2 }, 708 + { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_STORE_CLOCK_FAST }, 709 + { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING }, 710 + { S390_FEAT_SEMAPHORE_ASSIST, S390_FEAT_STFLE_49 }, 711 + { S390_FEAT_KIMD_SHA3_224, S390_FEAT_MSA }, 712 + { S390_FEAT_KIMD_SHA3_256, S390_FEAT_MSA }, 713 + { S390_FEAT_KIMD_SHA3_384, S390_FEAT_MSA }, 714 + { S390_FEAT_KIMD_SHA3_512, S390_FEAT_MSA }, 715 + { S390_FEAT_KIMD_SHAKE_128, S390_FEAT_MSA }, 716 + { S390_FEAT_KIMD_SHAKE_256, S390_FEAT_MSA }, 717 + { S390_FEAT_KLMD_SHA3_224, S390_FEAT_MSA }, 718 + { S390_FEAT_KLMD_SHA3_256, S390_FEAT_MSA }, 719 + { S390_FEAT_KLMD_SHA3_384, S390_FEAT_MSA }, 720 + { S390_FEAT_KLMD_SHA3_512, S390_FEAT_MSA }, 721 + { S390_FEAT_KLMD_SHAKE_128, S390_FEAT_MSA }, 722 + { S390_FEAT_KLMD_SHAKE_256, S390_FEAT_MSA }, 723 + { S390_FEAT_PRNO_TRNG_QRTCR, S390_FEAT_MSA_EXT_5 }, 724 + { S390_FEAT_PRNO_TRNG, S390_FEAT_MSA_EXT_5 }, 674 725 }; 675 726 int i; 676 727
+2
target/s390x/cpu_models.h
··· 72 72 #define ibc_gen(x) (x == 0 ? 0 : ((x >> 4) + S390_GEN_Z10)) 73 73 #define ibc_ec_ga(x) (x & 0xf) 74 74 75 + void s390_cpudef_featoff(uint8_t gen, uint8_t ec_ga, S390Feat feat); 76 + void s390_cpudef_featoff_greater(uint8_t gen, uint8_t ec_ga, S390Feat feat); 75 77 uint32_t s390_get_hmfai(void); 76 78 uint8_t s390_get_mha_pow(void); 77 79 uint32_t s390_get_ibc_val(void);
+24
target/s390x/gdbstub.c
··· 286 286 } 287 287 #endif 288 288 289 + /* the values represent the positions in s390-gs.xml */ 290 + #define S390_GS_RESERVED_REGNUM 0 291 + #define S390_GS_GSD_REGNUM 1 292 + #define S390_GS_GSSM_REGNUM 2 293 + #define S390_GS_GSEPLA_REGNUM 3 294 + /* total number of registers in s390-gs.xml */ 295 + #define S390_NUM_GS_REGS 4 296 + 297 + static int cpu_read_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 298 + { 299 + return gdb_get_regl(mem_buf, env->gscb[n]); 300 + } 301 + 302 + static int cpu_write_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 303 + { 304 + env->gscb[n] = ldtul_p(mem_buf); 305 + cpu_synchronize_post_init(ENV_GET_CPU(env)); 306 + return 8; 307 + } 308 + 289 309 void s390_cpu_gdb_init(CPUState *cs) 290 310 { 291 311 gdb_register_coprocessor(cs, cpu_read_ac_reg, ··· 299 319 gdb_register_coprocessor(cs, cpu_read_vreg, 300 320 cpu_write_vreg, 301 321 S390_NUM_VREGS, "s390-vx.xml", 0); 322 + 323 + gdb_register_coprocessor(cs, cpu_read_gs_reg, 324 + cpu_write_gs_reg, 325 + S390_NUM_GS_REGS, "s390-gs.xml", 0); 302 326 303 327 #ifndef CONFIG_USER_ONLY 304 328 gdb_register_coprocessor(cs, cpu_read_c_reg,
+102 -3
target/s390x/gen-features.c
··· 182 182 S390_FEAT_MSA_EXT_5, \ 183 183 S390_FEAT_PPNO_SHA_512_DRNG 184 184 185 + #define S390_FEAT_GROUP_MSA_EXT_6 \ 186 + S390_FEAT_KIMD_SHA3_224, \ 187 + S390_FEAT_KIMD_SHA3_256, \ 188 + S390_FEAT_KIMD_SHA3_384, \ 189 + S390_FEAT_KIMD_SHA3_512, \ 190 + S390_FEAT_KIMD_SHAKE_128, \ 191 + S390_FEAT_KIMD_SHAKE_256, \ 192 + S390_FEAT_KLMD_SHA3_224, \ 193 + S390_FEAT_KLMD_SHA3_256, \ 194 + S390_FEAT_KLMD_SHA3_384, \ 195 + S390_FEAT_KLMD_SHA3_512, \ 196 + S390_FEAT_KLMD_SHAKE_128, \ 197 + S390_FEAT_KLMD_SHAKE_256 198 + 199 + #define S390_FEAT_GROUP_MSA_EXT_7 \ 200 + S390_FEAT_PRNO_TRNG_QRTCR, \ 201 + S390_FEAT_PRNO_TRNG 202 + 203 + #define S390_FEAT_GROUP_MSA_EXT_8 \ 204 + S390_FEAT_MSA_EXT_8, \ 205 + S390_FEAT_KMA_GCM_AES_128, \ 206 + S390_FEAT_KMA_GCM_AES_192, \ 207 + S390_FEAT_KMA_GCM_AES_256 , \ 208 + S390_FEAT_KMA_GCM_EAES_128, \ 209 + S390_FEAT_KMA_GCM_EAES_192, \ 210 + S390_FEAT_KMA_GCM_EAES_256 211 + 185 212 /* cpu feature groups */ 186 213 static uint16_t group_PLO[] = { 187 214 S390_FEAT_GROUP_PLO, ··· 210 237 static uint16_t group_MSA_EXT_5[] = { 211 238 S390_FEAT_GROUP_MSA_EXT_5, 212 239 }; 240 + static uint16_t group_MSA_EXT_6[] = { 241 + S390_FEAT_GROUP_MSA_EXT_6, 242 + }; 243 + static uint16_t group_MSA_EXT_7[] = { 244 + S390_FEAT_GROUP_MSA_EXT_7, 245 + }; 246 + static uint16_t group_MSA_EXT_8[] = { 247 + S390_FEAT_GROUP_MSA_EXT_8, 248 + }; 213 249 214 - /* base features in order of release */ 250 + /* Base features (in order of release) 251 + * Only non-hypervisor managed features belong here. 252 + * Base feature sets are static meaning they do not change in future QEMU 253 + * releases. 254 + */ 215 255 static uint16_t base_GEN7_GA1[] = { 216 256 S390_FEAT_GROUP_PLO, 217 257 S390_FEAT_ESAN3, 218 258 S390_FEAT_ZARCH, 219 259 }; 260 + 220 261 #define base_GEN7_GA2 EmptyFeat 221 262 #define base_GEN7_GA3 EmptyFeat 263 + 222 264 static uint16_t base_GEN8_GA1[] = { 223 265 S390_FEAT_DAT_ENH, 224 266 S390_FEAT_EXTENDED_TRANSLATION_2, ··· 227 269 S390_FEAT_LONG_DISPLACEMENT_FAST, 228 270 S390_FEAT_HFP_MADDSUB, 229 271 }; 272 + 230 273 #define base_GEN8_GA2 EmptyFeat 231 274 #define base_GEN8_GA3 EmptyFeat 232 275 #define base_GEN8_GA4 EmptyFeat 233 276 #define base_GEN8_GA5 EmptyFeat 277 + 234 278 static uint16_t base_GEN9_GA1[] = { 235 279 S390_FEAT_IDTE_SEGMENT, 236 280 S390_FEAT_ASN_LX_REUSE, ··· 245 289 S390_FEAT_ETF3_ENH, 246 290 S390_FEAT_DAT_ENH_2, 247 291 }; 292 + 248 293 #define base_GEN9_GA2 EmptyFeat 249 294 #define base_GEN9_GA3 EmptyFeat 295 + 250 296 static uint16_t base_GEN10_GA1[] = { 251 297 S390_FEAT_CONDITIONAL_SSKE, 252 298 S390_FEAT_PARSING_ENH, ··· 263 309 }; 264 310 #define base_GEN10_GA2 EmptyFeat 265 311 #define base_GEN10_GA3 EmptyFeat 312 + 266 313 static uint16_t base_GEN11_GA1[] = { 267 314 S390_FEAT_NONQ_KEY_SETTING, 268 315 S390_FEAT_ENHANCED_MONITOR, ··· 272 319 S390_FEAT_CMPSC_ENH, 273 320 S390_FEAT_INTERLOCKED_ACCESS_2, 274 321 }; 322 + 275 323 #define base_GEN11_GA2 EmptyFeat 324 + 276 325 static uint16_t base_GEN12_GA1[] = { 277 326 S390_FEAT_DFP_ZONED_CONVERSION, 278 327 S390_FEAT_STFLE_49, 279 328 S390_FEAT_LOCAL_TLB_CLEARING, 280 329 }; 330 + 281 331 #define base_GEN12_GA2 EmptyFeat 332 + 282 333 static uint16_t base_GEN13_GA1[] = { 283 334 S390_FEAT_STFLE_53, 284 335 S390_FEAT_DFP_PACKED_CONVERSION, 285 336 S390_FEAT_GROUP_GEN13_PTFF, 286 337 }; 338 + 287 339 #define base_GEN13_GA2 EmptyFeat 288 340 289 - /* full features differing to the base in order of release */ 341 + /* Full features (in order of release) 342 + * Automatically includes corresponding base features. 343 + * Full features are all features this hardware supports even if kvm/QEMU do not 344 + * support these features yet. 345 + */ 290 346 static uint16_t full_GEN7_GA1[] = { 291 347 S390_FEAT_SIE_F2, 292 348 S390_FEAT_SIE_SKEY, ··· 294 350 S390_FEAT_SIE_IB, 295 351 S390_FEAT_SIE_CEI, 296 352 }; 353 + 297 354 static uint16_t full_GEN7_GA2[] = { 298 355 S390_FEAT_EXTENDED_TRANSLATION_2, 299 356 }; 357 + 300 358 static uint16_t full_GEN7_GA3[] = { 301 359 S390_FEAT_LONG_DISPLACEMENT, 302 360 S390_FEAT_SIE_SIIF, 303 361 }; 362 + 304 363 static uint16_t full_GEN8_GA1[] = { 305 364 S390_FEAT_SIE_GSLS, 306 365 S390_FEAT_SIE_64BSCAO, 307 366 }; 367 + 308 368 #define full_GEN8_GA2 EmptyFeat 369 + 309 370 static uint16_t full_GEN8_GA3[] = { 310 371 S390_FEAT_ASN_LX_REUSE, 311 372 S390_FEAT_EXTENDED_TRANSLATION_3, 312 373 }; 374 + 313 375 #define full_GEN8_GA4 EmptyFeat 314 376 #define full_GEN8_GA5 EmptyFeat 377 + 315 378 static uint16_t full_GEN9_GA1[] = { 316 379 S390_FEAT_STORE_HYPERVISOR_INFO, 317 380 S390_FEAT_GROUP_MSA_EXT_1, 318 381 S390_FEAT_CMM, 319 382 S390_FEAT_SIE_CMMA, 320 383 }; 384 + 321 385 static uint16_t full_GEN9_GA2[] = { 322 386 S390_FEAT_MOVE_WITH_OPTIONAL_SPEC, 323 387 S390_FEAT_EXTRACT_CPU_TIME, ··· 325 389 S390_FEAT_FLOATING_POINT_SUPPPORT_ENH, 326 390 S390_FEAT_DFP, 327 391 }; 392 + 328 393 static uint16_t full_GEN9_GA3[] = { 329 394 S390_FEAT_CONDITIONAL_SSKE, 330 395 S390_FEAT_PFPO, 331 396 }; 397 + 332 398 static uint16_t full_GEN10_GA1[] = { 333 399 S390_FEAT_EDAT, 334 400 S390_FEAT_CONFIGURATION_TOPOLOGY, ··· 337 403 S390_FEAT_SIE_PFMFI, 338 404 S390_FEAT_SIE_SIGPIF, 339 405 }; 406 + 340 407 static uint16_t full_GEN10_GA2[] = { 341 408 S390_FEAT_SET_PROGRAM_PARAMETERS, 342 409 S390_FEAT_SIE_IBS, 343 410 }; 411 + 344 412 static uint16_t full_GEN10_GA3[] = { 345 413 S390_FEAT_GROUP_MSA_EXT_3, 346 414 }; 415 + 347 416 static uint16_t full_GEN11_GA1[] = { 348 417 S390_FEAT_IPTE_RANGE, 349 418 S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, 350 419 S390_FEAT_GROUP_MSA_EXT_4, 351 420 }; 421 + 352 422 #define full_GEN11_GA2 EmptyFeat 423 + 353 424 static uint16_t full_GEN12_GA1[] = { 354 425 S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, 355 426 S390_FEAT_TRANSACTIONAL_EXE, 356 427 S390_FEAT_RUNTIME_INSTRUMENTATION, 428 + S390_FEAT_ZPCI, 429 + S390_FEAT_ADAPTER_EVENT_NOTIFICATION, 430 + S390_FEAT_ADAPTER_INT_SUPPRESSION, 357 431 S390_FEAT_EDAT_2, 432 + S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, 358 433 }; 434 + 359 435 static uint16_t full_GEN12_GA2[] = { 360 436 S390_FEAT_GROUP_MSA_EXT_5, 361 437 }; 438 + 362 439 static uint16_t full_GEN13_GA1[] = { 363 440 S390_FEAT_VECTOR, 364 441 }; 442 + 365 443 #define full_GEN13_GA2 EmptyFeat 366 444 367 - /* default features differing to the base in order of release */ 445 + /* Default features (in order of release) 446 + * Automatically includes corresponding base features. 447 + * Default features are all features this version of QEMU supports for this 448 + * hardware model. Default feature sets can grow with new QEMU releases. 449 + */ 368 450 #define default_GEN7_GA1 EmptyFeat 369 451 #define default_GEN7_GA2 EmptyFeat 370 452 #define default_GEN7_GA3 EmptyFeat ··· 373 455 #define default_GEN8_GA3 EmptyFeat 374 456 #define default_GEN8_GA4 EmptyFeat 375 457 #define default_GEN8_GA5 EmptyFeat 458 + 376 459 static uint16_t default_GEN9_GA1[] = { 377 460 S390_FEAT_STORE_HYPERVISOR_INFO, 378 461 S390_FEAT_GROUP_MSA_EXT_1, 379 462 S390_FEAT_CMM, 380 463 }; 464 + 381 465 #define default_GEN9_GA2 EmptyFeat 382 466 #define default_GEN9_GA3 EmptyFeat 467 + 383 468 static uint16_t default_GEN10_GA1[] = { 384 469 S390_FEAT_EDAT, 385 470 S390_FEAT_GROUP_MSA_EXT_2, 386 471 }; 472 + 387 473 #define default_GEN10_GA2 EmptyFeat 388 474 #define default_GEN10_GA3 EmptyFeat 475 + 389 476 static uint16_t default_GEN11_GA1[] = { 390 477 S390_FEAT_GROUP_MSA_EXT_3, 391 478 S390_FEAT_IPTE_RANGE, 392 479 S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, 393 480 S390_FEAT_GROUP_MSA_EXT_4, 394 481 }; 482 + 395 483 #define default_GEN11_GA2 EmptyFeat 484 + 396 485 static uint16_t default_GEN12_GA1[] = { 397 486 S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, 398 487 S390_FEAT_TRANSACTIONAL_EXE, 399 488 S390_FEAT_RUNTIME_INSTRUMENTATION, 489 + S390_FEAT_ZPCI, 490 + S390_FEAT_ADAPTER_EVENT_NOTIFICATION, 400 491 S390_FEAT_EDAT_2, 492 + S390_FEAT_ESOP, 493 + S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, 401 494 }; 495 + 402 496 #define default_GEN12_GA2 EmptyFeat 497 + 403 498 static uint16_t default_GEN13_GA1[] = { 404 499 S390_FEAT_GROUP_MSA_EXT_5, 405 500 S390_FEAT_VECTOR, 406 501 }; 502 + 407 503 #define default_GEN13_GA2 EmptyFeat 408 504 409 505 /****** END FEATURE DEFS ******/ ··· 491 587 FEAT_GROUP_INITIALIZER(MSA_EXT_3), 492 588 FEAT_GROUP_INITIALIZER(MSA_EXT_4), 493 589 FEAT_GROUP_INITIALIZER(MSA_EXT_5), 590 + FEAT_GROUP_INITIALIZER(MSA_EXT_6), 591 + FEAT_GROUP_INITIALIZER(MSA_EXT_7), 592 + FEAT_GROUP_INITIALIZER(MSA_EXT_8), 494 593 }; 495 594 496 595 static void set_bits(uint64_t list[], BitSpec bits)
+122 -47
target/s390x/kvm.c
··· 139 139 static int cap_mem_op; 140 140 static int cap_s390_irq; 141 141 static int cap_ri; 142 + static int cap_gs; 143 + 144 + static int active_cmma; 142 145 143 146 static void *legacy_s390_alloc(size_t size, uint64_t *align); 144 147 ··· 177 180 return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr); 178 181 } 179 182 183 + int kvm_s390_cmma_active(void) 184 + { 185 + return active_cmma; 186 + } 187 + 180 188 static bool kvm_s390_cmma_available(void) 181 189 { 182 190 static bool initialized, value; ··· 197 205 .attr = KVM_S390_VM_MEM_CLR_CMMA, 198 206 }; 199 207 200 - if (mem_path || !kvm_s390_cmma_available()) { 208 + if (!kvm_s390_cmma_active()) { 201 209 return; 202 210 } 203 211 ··· 213 221 .attr = KVM_S390_VM_MEM_ENABLE_CMMA, 214 222 }; 215 223 224 + if (mem_path) { 225 + error_report("Warning: CMM will not be enabled because it is not " 226 + "compatible to hugetlbfs."); 227 + return; 228 + } 216 229 rc = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); 230 + active_cmma = !rc; 217 231 trace_kvm_enable_cmma(rc); 218 232 } 219 233 ··· 288 302 cap_ri = 1; 289 303 } 290 304 } 305 + if (gs_allowed()) { 306 + if (kvm_vm_enable_cap(s, KVM_CAP_S390_GS, 0) == 0) { 307 + cap_gs = 1; 308 + } 309 + } 310 + 311 + /* Try to enable AIS facility */ 312 + kvm_vm_enable_cap(s, KVM_CAP_S390_AIS, 0); 291 313 292 314 qemu_mutex_init(&qemu_sigp_mutex); 293 315 ··· 456 478 } 457 479 } 458 480 481 + if (can_sync_regs(cs, KVM_SYNC_GSCB)) { 482 + memcpy(cs->kvm_run->s.regs.gscb, env->gscb, 32); 483 + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_GSCB; 484 + } 485 + 459 486 /* Finally the prefix */ 460 487 if (can_sync_regs(cs, KVM_SYNC_PREFIX)) { 461 488 cs->kvm_run->s.regs.prefix = env->psa; ··· 560 587 561 588 if (can_sync_regs(cs, KVM_SYNC_RICCB)) { 562 589 memcpy(env->riccb, cs->kvm_run->s.regs.riccb, 64); 590 + } 591 + 592 + if (can_sync_regs(cs, KVM_SYNC_GSCB)) { 593 + memcpy(env->gscb, cs->kvm_run->s.regs.gscb, 32); 563 594 } 564 595 565 596 /* pfault parameters */ ··· 1193 1224 1194 1225 static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run) 1195 1226 { 1196 - /* NOOP */ 1227 + CPUS390XState *env = &cpu->env; 1228 + uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4; 1229 + uint8_t r3 = run->s390_sieic.ipa & 0x000f; 1230 + uint8_t isc; 1231 + uint16_t mode; 1232 + int r; 1233 + 1234 + cpu_synchronize_state(CPU(cpu)); 1235 + mode = env->regs[r1] & 0xffff; 1236 + isc = (env->regs[r3] >> 27) & 0x7; 1237 + r = css_do_sic(env, isc, mode); 1238 + if (r) { 1239 + enter_pgmcheck(cpu, -r); 1240 + } 1241 + 1197 1242 return 0; 1198 1243 } 1199 1244 ··· 1444 1489 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 1445 1490 } 1446 1491 1447 - #define ADTL_SAVE_AREA_SIZE 1024 1448 - static int kvm_s390_store_adtl_status(S390CPU *cpu, hwaddr addr) 1492 + #define ADTL_GS_OFFSET 1024 /* offset of GS data in adtl save area */ 1493 + #define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */ 1494 + static int do_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len) 1449 1495 { 1496 + hwaddr save = len; 1450 1497 void *mem; 1451 - hwaddr len = ADTL_SAVE_AREA_SIZE; 1452 1498 1453 - mem = cpu_physical_memory_map(addr, &len, 1); 1499 + mem = cpu_physical_memory_map(addr, &save, 1); 1454 1500 if (!mem) { 1455 1501 return -EFAULT; 1456 1502 } 1457 - if (len != ADTL_SAVE_AREA_SIZE) { 1503 + if (save != len) { 1458 1504 cpu_physical_memory_unmap(mem, len, 1, 0); 1459 1505 return -EFAULT; 1460 1506 } 1461 1507 1462 - memcpy(mem, &cpu->env.vregs, 512); 1508 + if (s390_has_feat(S390_FEAT_VECTOR)) { 1509 + memcpy(mem, &cpu->env.vregs, 512); 1510 + } 1511 + if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) { 1512 + memcpy(mem + ADTL_GS_OFFSET, &cpu->env.gscb, 32); 1513 + } 1463 1514 1464 1515 cpu_physical_memory_unmap(mem, len, 1, len); 1465 1516 ··· 1555 1606 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 1556 1607 } 1557 1608 1609 + #define ADTL_SAVE_LC_MASK 0xfUL 1558 1610 static void sigp_store_adtl_status(CPUState *cs, run_on_cpu_data arg) 1559 1611 { 1560 1612 S390CPU *cpu = S390_CPU(cs); 1561 1613 SigpInfo *si = arg.host_ptr; 1614 + uint8_t lc = si->param & ADTL_SAVE_LC_MASK; 1615 + hwaddr addr = si->param & ~ADTL_SAVE_LC_MASK; 1616 + hwaddr len = 1UL << (lc ? lc : 10); 1562 1617 1563 - if (!s390_has_feat(S390_FEAT_VECTOR)) { 1618 + if (!s390_has_feat(S390_FEAT_VECTOR) && 1619 + !s390_has_feat(S390_FEAT_GUARDED_STORAGE)) { 1564 1620 set_sigp_status(si, SIGP_STAT_INVALID_ORDER); 1565 1621 return; 1566 1622 } ··· 1571 1627 return; 1572 1628 } 1573 1629 1574 - /* parameter must be aligned to 1024-byte boundary */ 1575 - if (si->param & 0x3ff) { 1630 + /* address must be aligned to length */ 1631 + if (addr & (len - 1)) { 1632 + set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); 1633 + return; 1634 + } 1635 + 1636 + /* no GS: only lc == 0 is valid */ 1637 + if (!s390_has_feat(S390_FEAT_GUARDED_STORAGE) && 1638 + lc != 0) { 1639 + set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); 1640 + return; 1641 + } 1642 + 1643 + /* GS: 0, 10, 11, 12 are valid */ 1644 + if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && 1645 + lc != 0 && 1646 + lc != 10 && 1647 + lc != 11 && 1648 + lc != 12) { 1576 1649 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); 1577 1650 return; 1578 1651 } 1579 1652 1580 1653 cpu_synchronize_state(cs); 1581 1654 1582 - if (kvm_s390_store_adtl_status(cpu, si->param)) { 1655 + if (do_store_adtl_status(cpu, addr, len)) { 1583 1656 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); 1584 1657 return; 1585 1658 } ··· 1727 1800 { 1728 1801 CPUState *cur_cs; 1729 1802 S390CPU *cur_cpu; 1803 + bool all_stopped = true; 1730 1804 1731 - /* due to the BQL, we are the only active cpu */ 1732 1805 CPU_FOREACH(cur_cs) { 1733 1806 cur_cpu = S390_CPU(cur_cs); 1734 - if (cur_cpu->env.sigp_order != 0) { 1735 - return SIGP_CC_BUSY; 1807 + 1808 + if (cur_cpu == cpu) { 1809 + continue; 1736 1810 } 1737 - cpu_synchronize_state(cur_cs); 1738 - /* all but the current one have to be stopped */ 1739 - if (cur_cpu != cpu && 1740 - s390_cpu_get_state(cur_cpu) != CPU_STATE_STOPPED) { 1741 - *status_reg &= 0xffffffff00000000ULL; 1742 - *status_reg |= SIGP_STAT_INCORRECT_STATE; 1743 - return SIGP_CC_STATUS_STORED; 1811 + if (s390_cpu_get_state(cur_cpu) != CPU_STATE_STOPPED) { 1812 + all_stopped = false; 1744 1813 } 1745 1814 } 1746 1815 1747 - switch (param & 0xff) { 1748 - case SIGP_MODE_ESA_S390: 1749 - /* not supported */ 1750 - return SIGP_CC_NOT_OPERATIONAL; 1751 - case SIGP_MODE_Z_ARCH_TRANS_ALL_PSW: 1752 - case SIGP_MODE_Z_ARCH_TRANS_CUR_PSW: 1753 - CPU_FOREACH(cur_cs) { 1754 - cur_cpu = S390_CPU(cur_cs); 1755 - cur_cpu->env.pfault_token = -1UL; 1756 - } 1757 - break; 1758 - default: 1759 - *status_reg &= 0xffffffff00000000ULL; 1760 - *status_reg |= SIGP_STAT_INVALID_PARAMETER; 1761 - return SIGP_CC_STATUS_STORED; 1762 - } 1816 + *status_reg &= 0xffffffff00000000ULL; 1763 1817 1764 - return SIGP_CC_ORDER_CODE_ACCEPTED; 1818 + /* Reject set arch order, with czam we're always in z/Arch mode. */ 1819 + *status_reg |= (all_stopped ? SIGP_STAT_INVALID_PARAMETER : 1820 + SIGP_STAT_INCORRECT_STATE); 1821 + return SIGP_CC_STATUS_STORED; 1765 1822 } 1766 1823 1767 1824 static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) ··· 2174 2231 if (s390_has_feat(S390_FEAT_VECTOR)) { 2175 2232 mcic |= MCIC_VB_VR; 2176 2233 } 2234 + if (s390_has_feat(S390_FEAT_GUARDED_STORAGE)) { 2235 + mcic |= MCIC_VB_GS; 2236 + } 2177 2237 return mcic; 2178 2238 } 2179 2239 ··· 2237 2297 int kvm_s390_get_ri(void) 2238 2298 { 2239 2299 return cap_ri; 2300 + } 2301 + 2302 + int kvm_s390_get_gs(void) 2303 + { 2304 + return cap_gs; 2240 2305 } 2241 2306 2242 2307 int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) ··· 2417 2482 if (test_bit(S390_FEAT_MSA_EXT_5, features)) { 2418 2483 s390_add_from_feat_block(features, S390_FEAT_TYPE_PPNO, prop.ppno); 2419 2484 } 2485 + if (test_bit(S390_FEAT_MSA_EXT_8, features)) { 2486 + s390_add_from_feat_block(features, S390_FEAT_TYPE_KMA, prop.kma); 2487 + } 2420 2488 return 0; 2421 2489 } 2422 2490 ··· 2470 2538 s390_fill_feat_block(features, S390_FEAT_TYPE_PPNO, prop.ppno); 2471 2539 prop.ppno[0] |= 0x80; /* query is always available */ 2472 2540 } 2541 + if (test_bit(S390_FEAT_MSA_EXT_8, features)) { 2542 + s390_fill_feat_block(features, S390_FEAT_TYPE_KMA, prop.kma); 2543 + prop.kma[0] |= 0x80; /* query is always available */ 2544 + } 2473 2545 return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); 2474 2546 } 2475 2547 ··· 2487 2559 { KVM_S390_VM_CPU_FEAT_CMMA, S390_FEAT_SIE_CMMA }, 2488 2560 { KVM_S390_VM_CPU_FEAT_PFMFI, S390_FEAT_SIE_PFMFI}, 2489 2561 { KVM_S390_VM_CPU_FEAT_SIGPIF, S390_FEAT_SIE_SIGPIF}, 2562 + { KVM_S390_VM_CPU_FEAT_KSS, S390_FEAT_SIE_KSS}, 2490 2563 }; 2491 2564 2492 2565 static int query_cpu_feat(S390FeatBitmap features) ··· 2606 2679 /* with cpu model support, CMM is only indicated if really available */ 2607 2680 if (kvm_s390_cmma_available()) { 2608 2681 set_bit(S390_FEAT_CMM, model->features); 2682 + } else { 2683 + /* no cmm -> no cmm nt */ 2684 + clear_bit(S390_FEAT_CMM_NT, model->features); 2609 2685 } 2686 + 2687 + /* set zpci and aen facilities */ 2688 + set_bit(S390_FEAT_ZPCI, model->features); 2689 + set_bit(S390_FEAT_ADAPTER_EVENT_NOTIFICATION, model->features); 2610 2690 2611 2691 if (s390_known_cpu_type(cpu_type)) { 2612 2692 /* we want the exact model, even if some features are missing */ ··· 2641 2721 2642 2722 if (!model) { 2643 2723 /* compatibility handling if cpu models are disabled */ 2644 - if (kvm_s390_cmma_available() && !mem_path) { 2724 + if (kvm_s390_cmma_available()) { 2645 2725 kvm_s390_enable_cmma(); 2646 2726 } 2647 2727 return; ··· 2672 2752 error_setg(errp, "KVM: Error configuring CPU subfunctions: %d", rc); 2673 2753 return; 2674 2754 } 2675 - /* enable CMM via CMMA - disable on hugetlbfs */ 2755 + /* enable CMM via CMMA */ 2676 2756 if (test_bit(S390_FEAT_CMM, model->features)) { 2677 - if (mem_path) { 2678 - warn_report("CMM will not be enabled because it is not " 2679 - "compatible to hugetlbfs."); 2680 - } else { 2681 - kvm_s390_enable_cmma(); 2682 - } 2757 + kvm_s390_enable_cmma(); 2683 2758 } 2684 2759 }
+17
target/s390x/machine.c
··· 174 174 } 175 175 }; 176 176 177 + static bool gscb_needed(void *opaque) 178 + { 179 + return kvm_s390_get_gs(); 180 + } 181 + 182 + const VMStateDescription vmstate_gscb = { 183 + .name = "cpu/gscb", 184 + .version_id = 1, 185 + .minimum_version_id = 1, 186 + .needed = gscb_needed, 187 + .fields = (VMStateField[]) { 188 + VMSTATE_UINT64_ARRAY(env.gscb, S390CPU, 4), 189 + VMSTATE_END_OF_LIST() 190 + } 191 + }; 192 + 177 193 const VMStateDescription vmstate_s390_cpu = { 178 194 .name = "cpu", 179 195 .post_load = cpu_post_load, ··· 207 223 &vmstate_vregs, 208 224 &vmstate_riccb, 209 225 &vmstate_exval, 226 + &vmstate_gscb, 210 227 NULL 211 228 }, 212 229 };