diff --git a/Sync-pv.patch b/Sync-pv.patch new file mode 100644 index 00000000..8704c3d8 --- /dev/null +++ b/Sync-pv.patch @@ -0,0 +1,92 @@ +From: Janosch Frank +Date: Tue, 25 Feb 2020 06:09:23 -0500 +Subject: Sync pv + +References: bsc#1167075 + +Signed-off-by: Janosch Frank +(cherry picked from commit 6807f464961cfee1dd81c95e22ddd91fa352fcc4) +Signed-off-by: Bruce Rogers +--- + linux-headers/linux/kvm.h | 50 +++++++++++++++++++++++++++++++++++++-- + 1 file changed, 48 insertions(+), 2 deletions(-) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 3d9b18f7f871acd0d13a0c42f184..18c636070edaf09dd8cf33ddb400 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -468,12 +468,17 @@ struct kvm_s390_mem_op { + __u32 size; /* amount of bytes */ + __u32 op; /* type of operation */ + __u64 buf; /* buffer in userspace */ +- __u8 ar; /* the access register number */ +- __u8 reserved[31]; /* should be set to 0 */ ++ union { ++ __u8 ar; /* the access register number */ ++ __u32 sida_offset; /* offset into the sida */ ++ __u8 reserved[32]; /* should be set to 0 */ ++ }; + }; + /* types for kvm_s390_mem_op->op */ + #define KVM_S390_MEMOP_LOGICAL_READ 0 + #define KVM_S390_MEMOP_LOGICAL_WRITE 1 ++#define KVM_S390_MEMOP_SIDA_READ 2 ++#define KVM_S390_MEMOP_SIDA_WRITE 3 + /* flags for kvm_s390_mem_op->flags */ + #define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) + #define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) +@@ -1000,6 +1005,8 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_PMU_EVENT_FILTER 173 + #define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 + #define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175 ++#define KVM_CAP_S390_VCPU_RESETS 179 ++#define KVM_CAP_S390_PROTECTED 180 + + #ifdef KVM_CAP_IRQ_ROUTING + +@@ -1461,6 +1468,45 @@ struct kvm_enc_region { + /* Available with KVM_CAP_ARM_SVE */ + #define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) + ++/* Available with KVM_CAP_S390_VCPU_RESETS */ ++#define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) ++#define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) ++ ++struct kvm_s390_pv_sec_parm { ++ __u64 origin; ++ __u64 length; ++}; ++ ++struct kvm_s390_pv_unp { ++ __u64 addr; ++ __u64 size; ++ __u64 tweak; ++}; ++ ++enum pv_cmd_id { ++ KVM_PV_ENABLE, ++ KVM_PV_DISABLE, ++ KVM_PV_VM_SET_SEC_PARMS, ++ KVM_PV_VM_UNPACK, ++ KVM_PV_VM_VERIFY, ++ KVM_PV_VM_PREP_RESET, ++ KVM_PV_VM_UNSHARE_ALL, ++ KVM_PV_VCPU_CREATE, ++ KVM_PV_VCPU_DESTROY, ++}; ++ ++struct kvm_pv_cmd { ++ __u32 cmd; /* Command to be executed */ ++ __u16 rc; /* Ultravisor return code */ ++ __u16 rrc; /* Ultravisor return reason code */ ++ __u64 data; /* Data or address */ ++ __u32 flags; /* flags for future extensions. Must be 0 for now */ ++ __u32 reserved[3]; ++}; ++ ++/* Available with KVM_CAP_S390_PROTECTED */ ++#define KVM_S390_PV_COMMAND _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd) ++ + /* Secure Encrypted Virtualization command */ + enum sev_cmd_id { + /* Guest initialization commands */ diff --git a/block-io-fix-bdrv_co_do_copy_on_readv.patch b/block-io-fix-bdrv_co_do_copy_on_readv.patch new file mode 100644 index 00000000..db99d1c5 --- /dev/null +++ b/block-io-fix-bdrv_co_do_copy_on_readv.patch @@ -0,0 +1,38 @@ +From: Vladimir Sementsov-Ogievskiy +Date: Thu, 12 Mar 2020 11:19:49 +0300 +Subject: block/io: fix bdrv_co_do_copy_on_readv + +Git-commit: 4ab78b19189a81038e744728ed949d09aa477550 + +Prior to 1143ec5ebf4 it was OK to qemu_iovec_from_buf() from aligned-up +buffer to original qiov, as qemu_iovec_from_buf() will stop at qiov end +anyway. + +But after 1143ec5ebf4 we assume that bdrv_co_do_copy_on_readv works on +part of original qiov, defined by qiov_offset and bytes. So we must not +touch qiov behind qiov_offset+bytes bound. Fix it. + +Cc: qemu-stable@nongnu.org # v4.2 +Fixes: 1143ec5ebf4 +Signed-off-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: John Snow +Message-id: 20200312081949.5350-1-vsementsov@virtuozzo.com +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Bruce Rogers +--- + block/io.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/io.c b/block/io.c +index d1f1ee9138c7af82352e9277f22b..c2c3aab9ee3d1d4d494ce98a6d8b 100644 +--- a/block/io.c ++++ b/block/io.c +@@ -1395,7 +1395,7 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child, + if (!(flags & BDRV_REQ_PREFETCH)) { + qemu_iovec_from_buf(qiov, qiov_offset + progress, + bounce_buffer + skip_bytes, +- pnum - skip_bytes); ++ MIN(pnum - skip_bytes, bytes - progress)); + } + } else if (!(flags & BDRV_REQ_PREFETCH)) { + /* Read directly into the destination */ diff --git a/bundles.tar.xz b/bundles.tar.xz index 48e25c94..e0bd16e0 100644 --- a/bundles.tar.xz +++ b/bundles.tar.xz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d6076daf7ce76bafd1fc236b472bb3fbb516e8a2e68440f670a031c2d254250 -size 105540 +oid sha256:8f2312cc7d4811cb10363273c211a6fcf58361e401b7b0c9824c9ed22c4ce898 +size 121876 diff --git a/compat-disable-edid-on-correct-virtio-gp.patch b/compat-disable-edid-on-correct-virtio-gp.patch new file mode 100644 index 00000000..c6384b52 --- /dev/null +++ b/compat-disable-edid-on-correct-virtio-gp.patch @@ -0,0 +1,41 @@ +From: Cornelia Huck +Date: Wed, 18 Mar 2020 10:39:19 +0100 +Subject: compat: disable edid on correct virtio-gpu device +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 02501fc39381c4dabaf6becdd12c2a4754c3847c + +Commit bb15791166c1 ("compat: disable edid on virtio-gpu base +device") tried to disable 'edid' on the virtio-gpu base device. +However, that device is not 'virtio-gpu', but 'virtio-gpu-device'. +Fix it. + +Fixes: bb15791166c1 ("compat: disable edid on virtio-gpu base device") +Reported-by: Lukáš Doktor +Tested-by: Lukáš Doktor +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Cornelia Huck +Message-id: 20200318093919.24942-1-cohuck@redhat.com +Cc: qemu-stable@nongnu.org +Signed-off-by: Cornelia Huck +Signed-off-by: Gerd Hoffmann +Signed-off-by: Bruce Rogers +--- + hw/core/machine.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index a15c5a8673ade765965b4e2c8237..cfab784b02ce6076c827c10c9e9c 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -37,7 +37,7 @@ GlobalProperty hw_compat_4_0[] = { + { "secondary-vga", "edid", "false" }, + { "bochs-display", "edid", "false" }, + { "virtio-vga", "edid", "false" }, +- { "virtio-gpu", "edid", "false" }, ++ { "virtio-gpu-device", "edid", "false" }, + { "virtio-device", "use-started", "false" }, + { "virtio-balloon-device", "qemu-4-0-config-size", "true" }, + { "pl031", "migrate-tick-offset", "false" }, diff --git a/pc-bios-s390x-Save-iplb-location-in-lowc.patch b/pc-bios-s390x-Save-iplb-location-in-lowc.patch index 32a6d226..4f957a25 100644 --- a/pc-bios-s390x-Save-iplb-location-in-lowc.patch +++ b/pc-bios-s390x-Save-iplb-location-in-lowc.patch @@ -2,7 +2,7 @@ From: Janosch Frank Date: Wed, 4 Mar 2020 06:42:31 -0500 Subject: pc-bios: s390x: Save iplb location in lowcore -References: bsc#1163140 +References: bsc#1163140, bsc#1167075 The POP states that for a list directed IPL the IPLB is stored into memory by the machine loader and its address is stored at offset 0x14 @@ -23,7 +23,9 @@ Message-Id: <20200304114231.23493-19-frankja@linux.ibm.com> Reviewed-by: Christian Borntraeger Reviewed-by: David Hildenbrand Signed-off-by: Christian Borntraeger +(cherry picked from commit 9bfc04f9ef6802fff0fc77130ff345a541783363) Signed-off-by: Liang Yan +Signed-off-by: Bruce Rogers --- pc-bios/s390-ccw/jump2ipl.c | 1 + pc-bios/s390-ccw/main.c | 8 +++++++- diff --git a/qemu.changes b/qemu.changes index 98722425..b2c36094 100644 --- a/qemu.changes +++ b/qemu.changes @@ -1,3 +1,41 @@ +------------------------------------------------------------------- +Fri Mar 20 17:27:29 UTC 2020 - Bruce Rogers + +- Include upstream patches targeted for the next stable release + (bug fixes only) + block-io-fix-bdrv_co_do_copy_on_readv.patch + compat-disable-edid-on-correct-virtio-gp.patch + target-ppc-Fix-rlwinm-on-ppc64.patch + vhost-correctly-turn-on-VIRTIO_F_IOMMU_P.patch +- s390x Protected Virtualization support - start and control guest + in secure mode. (note: binary patch from patch series dropped since + for s390x we rebuild the patched binary anyways) (bsc#1167075 + jsc#SLE-7407) + s390-sclp-improve-special-wait-psw-logic.patch + s390x-Add-missing-vcpu-reset-functions.patch + s390x-Add-SIDA-memory-ops.patch + s390x-Add-unpack-facility-feature-to-GA1.patch + s390x-Beautify-diag308-handling.patch + s390x-Don-t-do-a-normal-reset-on-the-ini.patch + s390x-ipl-Consolidate-iplb-validity-chec.patch + s390x-kvm-Make-kvm_sclp_service_call-voi.patch + s390x-Move-clear-reset.patch + s390x-Move-diagnose-308-subcodes-and-rcs.patch + s390x-Move-initial-reset.patch + s390x-Move-reset-normal-to-shared-reset-.patch + s390x-protvirt-Add-migration-blocker.patch + s390x-protvirt-Disable-address-checks-fo.patch + s390x-protvirt-Handle-SIGP-store-status-.patch + s390x-protvirt-Inhibit-balloon-when-swit.patch + s390x-protvirt-KVM-intercept-changes.patch + s390x-protvirt-Move-diag-308-data-over-S.patch + s390x-protvirt-Move-IO-control-structure.patch + s390x-protvirt-Move-STSI-data-over-SIDAD.patch + s390x-protvirt-SCLP-interpretation.patch + s390x-protvirt-Set-guest-IPL-PSW.patch + s390x-protvirt-Support-unpack-facility.patch + Sync-pv.patch + ------------------------------------------------------------------- Fri Mar 20 15:28:35 UTC 2020 - Liang Yan diff --git a/qemu.spec b/qemu.spec index e54f6b45..6e0f0eb5 100644 --- a/qemu.spec +++ b/qemu.spec @@ -202,49 +202,77 @@ Patch00071: iotests-Fix-nonportable-use-of-od-endian.patch Patch00072: block-qcow2-threads-fix-qcow2_decompress.patch Patch00073: job-refactor-progress-to-separate-object.patch Patch00074: block-block-copy-fix-progress-calculatio.patch -Patch00075: XXX-dont-dump-core-on-sigabort.patch -Patch00076: qemu-binfmt-conf-Modify-default-path.patch -Patch00077: qemu-cvs-gettimeofday.patch -Patch00078: qemu-cvs-ioctl_debug.patch -Patch00079: qemu-cvs-ioctl_nodirection.patch -Patch00080: linux-user-add-binfmt-wrapper-for-argv-0.patch -Patch00081: PPC-KVM-Disable-mmu-notifier-check.patch -Patch00082: linux-user-binfmt-support-host-binaries.patch -Patch00083: linux-user-Fake-proc-cpuinfo.patch -Patch00084: linux-user-use-target_ulong.patch -Patch00085: Make-char-muxer-more-robust-wrt-small-FI.patch -Patch00086: linux-user-lseek-explicitly-cast-non-set.patch -Patch00087: AIO-Reduce-number-of-threads-for-32bit-h.patch -Patch00088: xen_disk-Add-suse-specific-flush-disable.patch -Patch00089: qemu-bridge-helper-reduce-security-profi.patch -Patch00090: qemu-binfmt-conf-use-qemu-ARCH-binfmt.patch -Patch00091: linux-user-properly-test-for-infinite-ti.patch -Patch00092: roms-Makefile-pass-a-packaging-timestamp.patch -Patch00093: Raise-soft-address-space-limit-to-hard-l.patch -Patch00094: increase-x86_64-physical-bits-to-42.patch -Patch00095: vga-Raise-VRAM-to-16-MiB-for-pc-0.15-and.patch -Patch00096: i8254-Fix-migration-from-SLE11-SP2.patch -Patch00097: acpi_piix4-Fix-migration-from-SLE11-SP2.patch -Patch00098: Switch-order-of-libraries-for-mpath-supp.patch -Patch00099: Make-installed-scripts-explicitly-python.patch -Patch00100: hw-smbios-handle-both-file-formats-regar.patch -Patch00101: xen-add-block-resize-support-for-xen-dis.patch -Patch00102: tests-qemu-iotests-Triple-timeout-of-i-o.patch -Patch00103: tests-Fix-block-tests-to-be-compatible-w.patch -Patch00104: xen-ignore-live-parameter-from-xen-save-.patch -Patch00105: Conditionalize-ui-bitmap-installation-be.patch -Patch00106: tests-change-error-message-in-test-162.patch -Patch00107: hw-usb-hcd-xhci-Fix-GCC-9-build-warning.patch -Patch00108: hw-usb-dev-mtp-Fix-GCC-9-build-warning.patch -Patch00109: hw-intc-exynos4210_gic-provide-more-room.patch -Patch00110: configure-only-populate-roms-if-softmmu.patch -Patch00111: pc-bios-s390-ccw-net-avoid-warning-about.patch -Patch00112: roms-change-cross-compiler-naming-to-be-.patch -Patch00113: tests-Disable-some-block-tests-for-now.patch -Patch00114: test-add-mapping-from-arch-of-i686-to-qe.patch -Patch00115: roms-Makefile-enable-cross-compile-for-b.patch -Patch00116: hw-i386-disable-smbus-migration-for-xenf.patch -Patch00117: pc-bios-s390x-Save-iplb-location-in-lowc.patch +Patch00075: block-io-fix-bdrv_co_do_copy_on_readv.patch +Patch00076: target-ppc-Fix-rlwinm-on-ppc64.patch +Patch00077: compat-disable-edid-on-correct-virtio-gp.patch +Patch00078: XXX-dont-dump-core-on-sigabort.patch +Patch00079: qemu-binfmt-conf-Modify-default-path.patch +Patch00080: qemu-cvs-gettimeofday.patch +Patch00081: qemu-cvs-ioctl_debug.patch +Patch00082: qemu-cvs-ioctl_nodirection.patch +Patch00083: linux-user-add-binfmt-wrapper-for-argv-0.patch +Patch00084: PPC-KVM-Disable-mmu-notifier-check.patch +Patch00085: linux-user-binfmt-support-host-binaries.patch +Patch00086: linux-user-Fake-proc-cpuinfo.patch +Patch00087: linux-user-use-target_ulong.patch +Patch00088: Make-char-muxer-more-robust-wrt-small-FI.patch +Patch00089: linux-user-lseek-explicitly-cast-non-set.patch +Patch00090: AIO-Reduce-number-of-threads-for-32bit-h.patch +Patch00091: xen_disk-Add-suse-specific-flush-disable.patch +Patch00092: qemu-bridge-helper-reduce-security-profi.patch +Patch00093: qemu-binfmt-conf-use-qemu-ARCH-binfmt.patch +Patch00094: linux-user-properly-test-for-infinite-ti.patch +Patch00095: roms-Makefile-pass-a-packaging-timestamp.patch +Patch00096: Raise-soft-address-space-limit-to-hard-l.patch +Patch00097: increase-x86_64-physical-bits-to-42.patch +Patch00098: vga-Raise-VRAM-to-16-MiB-for-pc-0.15-and.patch +Patch00099: i8254-Fix-migration-from-SLE11-SP2.patch +Patch00100: acpi_piix4-Fix-migration-from-SLE11-SP2.patch +Patch00101: Switch-order-of-libraries-for-mpath-supp.patch +Patch00102: Make-installed-scripts-explicitly-python.patch +Patch00103: hw-smbios-handle-both-file-formats-regar.patch +Patch00104: xen-add-block-resize-support-for-xen-dis.patch +Patch00105: tests-qemu-iotests-Triple-timeout-of-i-o.patch +Patch00106: tests-Fix-block-tests-to-be-compatible-w.patch +Patch00107: xen-ignore-live-parameter-from-xen-save-.patch +Patch00108: Conditionalize-ui-bitmap-installation-be.patch +Patch00109: tests-change-error-message-in-test-162.patch +Patch00110: hw-usb-hcd-xhci-Fix-GCC-9-build-warning.patch +Patch00111: hw-usb-dev-mtp-Fix-GCC-9-build-warning.patch +Patch00112: hw-intc-exynos4210_gic-provide-more-room.patch +Patch00113: configure-only-populate-roms-if-softmmu.patch +Patch00114: pc-bios-s390-ccw-net-avoid-warning-about.patch +Patch00115: roms-change-cross-compiler-naming-to-be-.patch +Patch00116: tests-Disable-some-block-tests-for-now.patch +Patch00117: test-add-mapping-from-arch-of-i686-to-qe.patch +Patch00118: roms-Makefile-enable-cross-compile-for-b.patch +Patch00119: hw-i386-disable-smbus-migration-for-xenf.patch +Patch00120: s390x-Don-t-do-a-normal-reset-on-the-ini.patch +Patch00121: s390x-Move-reset-normal-to-shared-reset-.patch +Patch00122: s390x-Move-initial-reset.patch +Patch00123: s390x-Move-clear-reset.patch +Patch00124: s390x-kvm-Make-kvm_sclp_service_call-voi.patch +Patch00125: s390x-ipl-Consolidate-iplb-validity-chec.patch +Patch00126: s390x-Beautify-diag308-handling.patch +Patch00127: s390x-Add-missing-vcpu-reset-functions.patch +Patch00128: pc-bios-s390x-Save-iplb-location-in-lowc.patch +Patch00129: s390-sclp-improve-special-wait-psw-logic.patch +Patch00130: s390x-Move-diagnose-308-subcodes-and-rcs.patch +Patch00131: vhost-correctly-turn-on-VIRTIO_F_IOMMU_P.patch +Patch00132: Sync-pv.patch +Patch00133: s390x-protvirt-Support-unpack-facility.patch +Patch00134: s390x-protvirt-Add-migration-blocker.patch +Patch00135: s390x-protvirt-Inhibit-balloon-when-swit.patch +Patch00136: s390x-protvirt-KVM-intercept-changes.patch +Patch00137: s390x-Add-SIDA-memory-ops.patch +Patch00138: s390x-protvirt-Move-STSI-data-over-SIDAD.patch +Patch00139: s390x-protvirt-SCLP-interpretation.patch +Patch00140: s390x-protvirt-Set-guest-IPL-PSW.patch +Patch00141: s390x-protvirt-Move-diag-308-data-over-S.patch +Patch00142: s390x-protvirt-Disable-address-checks-fo.patch +Patch00143: s390x-protvirt-Move-IO-control-structure.patch +Patch00144: s390x-protvirt-Handle-SIGP-store-status-.patch +Patch00145: s390x-Add-unpack-facility-feature-to-GA1.patch # Patches applied in roms/seabios/: Patch01000: seabios-use-python2-explicitly-as-needed.patch Patch01001: seabios-switch-to-python3-as-needed.patch @@ -1078,6 +1106,34 @@ This package provides a service file for starting and stopping KSM. %patch00115 -p1 %patch00116 -p1 %patch00117 -p1 +%patch00118 -p1 +%patch00119 -p1 +%patch00120 -p1 +%patch00121 -p1 +%patch00122 -p1 +%patch00123 -p1 +%patch00124 -p1 +%patch00125 -p1 +%patch00126 -p1 +%patch00127 -p1 +%patch00128 -p1 +%patch00129 -p1 +%patch00130 -p1 +%patch00131 -p1 +%patch00132 -p1 +%patch00133 -p1 +%patch00134 -p1 +%patch00135 -p1 +%patch00136 -p1 +%patch00137 -p1 +%patch00138 -p1 +%patch00139 -p1 +%patch00140 -p1 +%patch00141 -p1 +%patch00142 -p1 +%patch00143 -p1 +%patch00144 -p1 +%patch00145 -p1 %patch01000 -p1 %patch01001 -p1 %patch01002 -p1 diff --git a/s390-sclp-improve-special-wait-psw-logic.patch b/s390-sclp-improve-special-wait-psw-logic.patch new file mode 100644 index 00000000..092371fd --- /dev/null +++ b/s390-sclp-improve-special-wait-psw-logic.patch @@ -0,0 +1,35 @@ +From: Christian Borntraeger +Date: Thu, 20 Feb 2020 14:16:22 +0100 +Subject: s390/sclp: improve special wait psw logic + +References: bsc#1167075 + +There is a special quiesce PSW that we check for "shutdown". Otherwise disabled +wait is detected as "crashed". Architecturally we must only check PSW bits +116-127. Fix this. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Christian Borntraeger +Message-Id: <1582204582-22995-1-git-send-email-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Acked-by: Janosch Frank +Signed-off-by: Cornelia Huck +(cherry picked from commit 8b51c0961cc13e55b26bb6665ec3a341abdc7658) +Signed-off-by: Bruce Rogers +--- + target/s390x/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/s390x/helper.c b/target/s390x/helper.c +index a3a49164e471b3f00a40020f987d..6808dfda01f42acbaa1d36ef787b 100644 +--- a/target/s390x/helper.c ++++ b/target/s390x/helper.c +@@ -89,7 +89,7 @@ hwaddr s390_cpu_get_phys_addr_debug(CPUState *cs, vaddr vaddr) + static inline bool is_special_wait_psw(uint64_t psw_addr) + { + /* signal quiesce */ +- return psw_addr == 0xfffUL; ++ return (psw_addr & 0xfffUL) == 0xfffUL; + } + + void s390_handle_wait(S390CPU *cpu) diff --git a/s390x-Add-SIDA-memory-ops.patch b/s390x-Add-SIDA-memory-ops.patch new file mode 100644 index 00000000..a64926bd --- /dev/null +++ b/s390x-Add-SIDA-memory-ops.patch @@ -0,0 +1,135 @@ +From: Janosch Frank +Date: Wed, 5 Feb 2020 06:57:35 -0500 +Subject: s390x: Add SIDA memory ops + +References: bsc#1167075 + +Protected guests save the instruction control blocks in the SIDA +instead of QEMU/KVM directly accessing the guest's memory. + +Let's introduce new functions to access the SIDA. + +The memops for doing so are available with KVM_CAP_S390_PROTECTED, so +let's check for that. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit a9f21cec3bc9c86062c7c24bb2143d22cb3c2950) +Signed-off-by: Bruce Rogers +--- + target/s390x/cpu.h | 7 ++++++- + target/s390x/kvm.c | 26 ++++++++++++++++++++++++++ + target/s390x/kvm_s390x.h | 2 ++ + target/s390x/mmu_helper.c | 14 ++++++++++++++ + 4 files changed, 48 insertions(+), 1 deletion(-) + +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index d2af13b345ccd9094f82385cd528..2ec0f78b48ee15978b62f5fdc1b2 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -821,7 +821,12 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf, + #define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \ + s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true) + void s390_cpu_virt_mem_handle_exc(S390CPU *cpu, uintptr_t ra); +- ++int s390_cpu_pv_mem_rw(S390CPU *cpu, unsigned int offset, void *hostbuf, ++ int len, bool is_write); ++#define s390_cpu_pv_mem_read(cpu, offset, dest, len) \ ++ s390_cpu_pv_mem_rw(cpu, offset, dest, len, false) ++#define s390_cpu_pv_mem_write(cpu, offset, dest, len) \ ++ s390_cpu_pv_mem_rw(cpu, offset, dest, len, true) + + /* sigp.c */ + int s390_cpu_restart(S390CPU *cpu); +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index abeeaaa67452b0b938557b0d0dea..941e4df630ad9b3dc780d3c92e6b 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -154,6 +154,7 @@ static int cap_ri; + static int cap_gs; + static int cap_hpage_1m; + static int cap_vcpu_resets; ++static int cap_protected; + + static int active_cmma; + +@@ -351,6 +352,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP); + cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ); + cap_vcpu_resets = kvm_check_extension(s, KVM_CAP_S390_VCPU_RESETS); ++ cap_protected = kvm_check_extension(s, KVM_CAP_S390_PROTECTED); + + if (!kvm_check_extension(s, KVM_CAP_S390_GMAP) + || !kvm_check_extension(s, KVM_CAP_S390_COW)) { +@@ -848,6 +850,30 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, + return ret; + } + ++int kvm_s390_mem_op_pv(S390CPU *cpu, uint64_t offset, void *hostbuf, ++ int len, bool is_write) ++{ ++ struct kvm_s390_mem_op mem_op = { ++ .sida_offset = offset, ++ .size = len, ++ .op = is_write ? KVM_S390_MEMOP_SIDA_WRITE ++ : KVM_S390_MEMOP_SIDA_READ, ++ .buf = (uint64_t)hostbuf, ++ }; ++ int ret; ++ ++ if (!cap_mem_op || !cap_protected) { ++ return -ENOSYS; ++ } ++ ++ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_S390_MEM_OP, &mem_op); ++ if (ret < 0) { ++ error_report("KVM_S390_MEM_OP failed: %s", strerror(-ret)); ++ abort(); ++ } ++ return ret; ++} ++ + /* + * Legacy layout for s390: + * Older S390 KVM requires the topmost vma of the RAM to be +diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h +index dea813f450153c34e1269424772d..6ab17c81b73a0011e32213552698 100644 +--- a/target/s390x/kvm_s390x.h ++++ b/target/s390x/kvm_s390x.h +@@ -19,6 +19,8 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq); + void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code); + int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, + int len, bool is_write); ++int kvm_s390_mem_op_pv(S390CPU *cpu, vaddr addr, void *hostbuf, int len, ++ bool is_write); + void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); + int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); + void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); +diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c +index c9f3f347501097b894333a36cac3..ec8befbdc87d4c88d83baeeab20e 100644 +--- a/target/s390x/mmu_helper.c ++++ b/target/s390x/mmu_helper.c +@@ -474,6 +474,20 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages, + return 0; + } + ++int s390_cpu_pv_mem_rw(S390CPU *cpu, unsigned int offset, void *hostbuf, ++ int len, bool is_write) ++{ ++ int ret; ++ ++ if (kvm_enabled()) { ++ ret = kvm_s390_mem_op_pv(cpu, offset, hostbuf, len, is_write); ++ } else { ++ /* Protected Virtualization is a KVM/Hardware only feature */ ++ g_assert_not_reached(); ++ } ++ return ret; ++} ++ + /** + * s390_cpu_virt_mem_rw: + * @laddr: the logical start address diff --git a/s390x-Add-missing-vcpu-reset-functions.patch b/s390x-Add-missing-vcpu-reset-functions.patch new file mode 100644 index 00000000..327b0ed9 --- /dev/null +++ b/s390x-Add-missing-vcpu-reset-functions.patch @@ -0,0 +1,159 @@ +From: Janosch Frank +Date: Fri, 14 Feb 2020 10:16:21 -0500 +Subject: s390x: Add missing vcpu reset functions + +References: bsc#1167075 + +Up to now we only had an ioctl to reset vcpu data QEMU couldn't reach +for the initial reset, which was also called for the clear reset. To +be architecture compliant, we also need to clear local interrupts on a +normal reset. + +Because of this and the upcoming protvirt support we need to add +ioctls for the missing clear and normal resets. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Acked-by: David Hildenbrand +Message-Id: <20200214151636.8764-3-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit b91a03946e0f65ddd22927dd80ca1276bf89c5af) +Signed-off-by: Bruce Rogers +--- + target/s390x/cpu.c | 14 ++++++++++++-- + target/s390x/kvm-stub.c | 10 +++++++++- + target/s390x/kvm.c | 42 ++++++++++++++++++++++++++++++++-------- + target/s390x/kvm_s390x.h | 4 +++- + 4 files changed, 58 insertions(+), 12 deletions(-) + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index bd39cb54b7aa3fa8edba5d9975a4..52fefa1586caa3cbd366fe230630 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -131,8 +131,18 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + } + + /* Reset state inside the kernel that we cannot access yet from QEMU. */ +- if (kvm_enabled() && type != S390_CPU_RESET_NORMAL) { +- kvm_s390_reset_vcpu(cpu); ++ if (kvm_enabled()) { ++ switch (type) { ++ case S390_CPU_RESET_CLEAR: ++ kvm_s390_reset_vcpu_clear(cpu); ++ break; ++ case S390_CPU_RESET_INITIAL: ++ kvm_s390_reset_vcpu_initial(cpu); ++ break; ++ case S390_CPU_RESET_NORMAL: ++ kvm_s390_reset_vcpu_normal(cpu); ++ break; ++ } + } + } + +diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c +index 5152e2bdf19b2661330a1da80c5d..c4cd497f850eb9c7a859932b0f1f 100644 +--- a/target/s390x/kvm-stub.c ++++ b/target/s390x/kvm-stub.c +@@ -83,7 +83,15 @@ void kvm_s390_cmma_reset(void) + { + } + +-void kvm_s390_reset_vcpu(S390CPU *cpu) ++void kvm_s390_reset_vcpu_initial(S390CPU *cpu) ++{ ++} ++ ++void kvm_s390_reset_vcpu_clear(S390CPU *cpu) ++{ ++} ++ ++void kvm_s390_reset_vcpu_normal(S390CPU *cpu) + { + } + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index ad6e38c8761be7e0cad57771f49b..f633472980b48757989db245fb1f 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -151,6 +151,7 @@ static int cap_s390_irq; + static int cap_ri; + static int cap_gs; + static int cap_hpage_1m; ++static int cap_vcpu_resets; + + static int active_cmma; + +@@ -342,6 +343,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF); + cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP); + cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ); ++ cap_vcpu_resets = kvm_check_extension(s, KVM_CAP_S390_VCPU_RESETS); + + if (!kvm_check_extension(s, KVM_CAP_S390_GMAP) + || !kvm_check_extension(s, KVM_CAP_S390_COW)) { +@@ -403,17 +405,41 @@ int kvm_arch_destroy_vcpu(CPUState *cs) + return 0; + } + +-void kvm_s390_reset_vcpu(S390CPU *cpu) ++static void kvm_s390_reset_vcpu(S390CPU *cpu, unsigned long type) + { + CPUState *cs = CPU(cpu); + +- /* The initial reset call is needed here to reset in-kernel +- * vcpu data that we can't access directly from QEMU +- * (i.e. with older kernels which don't support sync_regs/ONE_REG). +- * Before this ioctl cpu_synchronize_state() is called in common kvm +- * code (kvm-all) */ +- if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) { +- error_report("Initial CPU reset failed on CPU %i", cs->cpu_index); ++ /* ++ * The reset call is needed here to reset in-kernel vcpu data that ++ * we can't access directly from QEMU (i.e. with older kernels ++ * which don't support sync_regs/ONE_REG). Before this ioctl ++ * cpu_synchronize_state() is called in common kvm code ++ * (kvm-all). ++ */ ++ if (kvm_vcpu_ioctl(cs, type)) { ++ error_report("CPU reset failed on CPU %i type %lx", ++ cs->cpu_index, type); ++ } ++} ++ ++void kvm_s390_reset_vcpu_initial(S390CPU *cpu) ++{ ++ kvm_s390_reset_vcpu(cpu, KVM_S390_INITIAL_RESET); ++} ++ ++void kvm_s390_reset_vcpu_clear(S390CPU *cpu) ++{ ++ if (cap_vcpu_resets) { ++ kvm_s390_reset_vcpu(cpu, KVM_S390_CLEAR_RESET); ++ } else { ++ kvm_s390_reset_vcpu(cpu, KVM_S390_INITIAL_RESET); ++ } ++} ++ ++void kvm_s390_reset_vcpu_normal(S390CPU *cpu) ++{ ++ if (cap_vcpu_resets) { ++ kvm_s390_reset_vcpu(cpu, KVM_S390_NORMAL_RESET); + } + } + +diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h +index caf985955ba5da4e2cda021ed1b5..0b21789796d7c462bdc72160166f 100644 +--- a/target/s390x/kvm_s390x.h ++++ b/target/s390x/kvm_s390x.h +@@ -34,7 +34,9 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, + int vq, bool assign); + int kvm_s390_cmma_active(void); + void kvm_s390_cmma_reset(void); +-void kvm_s390_reset_vcpu(S390CPU *cpu); ++void kvm_s390_reset_vcpu_clear(S390CPU *cpu); ++void kvm_s390_reset_vcpu_normal(S390CPU *cpu); ++void kvm_s390_reset_vcpu_initial(S390CPU *cpu); + int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit); + void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp); + void kvm_s390_crypto_reset(void); diff --git a/s390x-Add-unpack-facility-feature-to-GA1.patch b/s390x-Add-unpack-facility-feature-to-GA1.patch new file mode 100644 index 00000000..dc36603c --- /dev/null +++ b/s390x-Add-unpack-facility-feature-to-GA1.patch @@ -0,0 +1,61 @@ +From: Christian Borntraeger +Date: Tue, 25 Feb 2020 06:28:51 -0500 +Subject: s390x: Add unpack facility feature to GA1 + +References: bsc#1167075 + +The unpack facility is an indication that diagnose 308 subcodes 8-10 +are available to the guest. That means, that the guest can put itself +into protected mode. + +Once it is in protected mode, the hardware stops any attempt of VM +introspection by the hypervisor. + +Some features are currently not supported in protected mode: + * vfio devices + * Migration + * Huge page backings + +Signed-off-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +Signed-off-by: Janosch Frank +(cherry picked from commit 3034eaac3b2970ba85a1d77814ceef1352d05357) +Signed-off-by: Bruce Rogers +--- + target/s390x/gen-features.c | 1 + + target/s390x/kvm.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 6278845b12b8dee84c086413c60a..8ddeebc54419a3e2481e21916389 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -562,6 +562,7 @@ static uint16_t full_GEN15_GA1[] = { + S390_FEAT_GROUP_MSA_EXT_9, + S390_FEAT_GROUP_MSA_EXT_9_PCKMO, + S390_FEAT_ETOKEN, ++ S390_FEAT_UNPACK, + }; + + /* Default features (in order of release) +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index d94b915da419c3ad0a1f9622ca13..8b82e4c93dfa7e89127bce74cde7 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -2407,6 +2407,14 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp) + clear_bit(S390_FEAT_BPB, model->features); + } + ++ /* ++ * If we have support for protected virtualization, indicate ++ * the protected virtualization IPL unpack facility. ++ */ ++ if (cap_protected) { ++ set_bit(S390_FEAT_UNPACK, model->features); ++ } ++ + /* We emulate a zPCI bus and AEN, therefore we don't need HW support */ + set_bit(S390_FEAT_ZPCI, model->features); + set_bit(S390_FEAT_ADAPTER_EVENT_NOTIFICATION, model->features); diff --git a/s390x-Beautify-diag308-handling.patch b/s390x-Beautify-diag308-handling.patch new file mode 100644 index 00000000..87087513 --- /dev/null +++ b/s390x-Beautify-diag308-handling.patch @@ -0,0 +1,113 @@ +From: Janosch Frank +Date: Wed, 27 Nov 2019 12:50:45 -0500 +Subject: s390x: Beautify diag308 handling + +References: bsc#1167075 + +Let's improve readability by: +* Using constants for the subcodes +* Moving parameter checking into a function +* Removing subcode > 6 check as the default case catches that + +Signed-off-by: Janosch Frank +Reviewed-by: Cornelia Huck +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Message-Id: <20191127175046.4911-6-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 0b7fd817e0f383760e37ca9286150d5816cf0594) +Signed-off-by: Bruce Rogers +--- + target/s390x/diag.c | 54 +++++++++++++++++++++++++++------------------ + 1 file changed, 32 insertions(+), 22 deletions(-) + +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 0c81d8e1efbfe37a384199488a72..54e5670b3fd6d960bd3fb4baca8b 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -53,6 +53,29 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + #define DIAG_308_RC_NO_CONF 0x0102 + #define DIAG_308_RC_INVALID 0x0402 + ++#define DIAG308_RESET_MOD_CLR 0 ++#define DIAG308_RESET_LOAD_NORM 1 ++#define DIAG308_LOAD_CLEAR 3 ++#define DIAG308_LOAD_NORMAL_DUMP 4 ++#define DIAG308_SET 5 ++#define DIAG308_STORE 6 ++ ++static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, ++ uintptr_t ra, bool write) ++{ ++ if ((r1 & 1) || (addr & ~TARGET_PAGE_MASK)) { ++ s390_program_interrupt(env, PGM_SPECIFICATION, ra); ++ return -1; ++ } ++ if (!address_space_access_valid(&address_space_memory, addr, ++ sizeof(IplParameterBlock), write, ++ MEMTXATTRS_UNSPECIFIED)) { ++ s390_program_interrupt(env, PGM_ADDRESSING, ra); ++ return -1; ++ } ++ return 0; ++} ++ + void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { + CPUState *cs = env_cpu(env); +@@ -65,30 +88,24 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + return; + } + +- if ((subcode & ~0x0ffffULL) || (subcode > 6)) { ++ if (subcode & ~0x0ffffULL) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } + + switch (subcode) { +- case 0: ++ case DIAG308_RESET_MOD_CLR: + s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); + break; +- case 1: ++ case DIAG308_RESET_LOAD_NORM: + s390_ipl_reset_request(cs, S390_RESET_LOAD_NORMAL); + break; +- case 3: ++ case DIAG308_LOAD_CLEAR: ++ /* Well we still lack the clearing bit... */ + s390_ipl_reset_request(cs, S390_RESET_REIPL); + break; +- case 5: +- if ((r1 & 1) || (addr & 0x0fffULL)) { +- s390_program_interrupt(env, PGM_SPECIFICATION, ra); +- return; +- } +- if (!address_space_access_valid(&address_space_memory, addr, +- sizeof(IplParameterBlock), false, +- MEMTXATTRS_UNSPECIFIED)) { +- s390_program_interrupt(env, PGM_ADDRESSING, ra); ++ case DIAG308_SET: ++ if (diag308_parm_check(env, r1, addr, ra, false)) { + return; + } + iplb = g_new0(IplParameterBlock, 1); +@@ -110,15 +127,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + out: + g_free(iplb); + return; +- case 6: +- if ((r1 & 1) || (addr & 0x0fffULL)) { +- s390_program_interrupt(env, PGM_SPECIFICATION, ra); +- return; +- } +- if (!address_space_access_valid(&address_space_memory, addr, +- sizeof(IplParameterBlock), true, +- MEMTXATTRS_UNSPECIFIED)) { +- s390_program_interrupt(env, PGM_ADDRESSING, ra); ++ case DIAG308_STORE: ++ if (diag308_parm_check(env, r1, addr, ra, true)) { + return; + } + iplb = s390_ipl_get_iplb(); diff --git a/s390x-Don-t-do-a-normal-reset-on-the-ini.patch b/s390x-Don-t-do-a-normal-reset-on-the-ini.patch new file mode 100644 index 00000000..b501ea4a --- /dev/null +++ b/s390x-Don-t-do-a-normal-reset-on-the-ini.patch @@ -0,0 +1,35 @@ +From: Janosch Frank +Date: Wed, 27 Nov 2019 12:50:41 -0500 +Subject: s390x: Don't do a normal reset on the initial cpu + +References: bsc#1167075 + +The initiating cpu needs to be reset with an initial reset. While +doing a normal reset followed by a initial reset is not wrong per se, +the Ultravisor will only allow the correct reset to be performed. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Cornelia Huck +Message-Id: <20191127175046.4911-2-frankja@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit ec9227339fce99412830d44a37eb0bd2fadd5f75) +Signed-off-by: Bruce Rogers +--- + hw/s390x/s390-virtio-ccw.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index d3edeef0ad924af160eb83ea6724..c1d1440272a42eef86eb14724f52 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -348,6 +348,9 @@ static void s390_machine_reset(MachineState *machine) + break; + case S390_RESET_LOAD_NORMAL: + CPU_FOREACH(t) { ++ if (t == cs) { ++ continue; ++ } + run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); + } + subsystem_reset(); diff --git a/s390x-Move-clear-reset.patch b/s390x-Move-clear-reset.patch new file mode 100644 index 00000000..f25acb80 --- /dev/null +++ b/s390x-Move-clear-reset.patch @@ -0,0 +1,129 @@ +From: Janosch Frank +Date: Wed, 27 Nov 2019 12:50:44 -0500 +Subject: s390x: Move clear reset + +References: bsc#1167075 + +Let's also move the clear reset function into the reset handler. + +Signed-off-by: Janosch Frank +Message-Id: <20191127175046.4911-5-frankja@linux.ibm.com> +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit eb8adcc3e9e3b8405c104ede72cf9f3bb2a5e226) +Signed-off-by: Bruce Rogers +--- + target/s390x/cpu-qom.h | 1 + + target/s390x/cpu.c | 58 +++++++++++++----------------------------- + 2 files changed, 18 insertions(+), 41 deletions(-) + +diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h +index 6f0a12042ed4802de7da08d63612..dbe5346ec9019f4f5939598b7a83 100644 +--- a/target/s390x/cpu-qom.h ++++ b/target/s390x/cpu-qom.h +@@ -37,6 +37,7 @@ typedef struct S390CPUDef S390CPUDef; + typedef enum cpu_reset_type { + S390_CPU_RESET_NORMAL, + S390_CPU_RESET_INITIAL, ++ S390_CPU_RESET_CLEAR, + } cpu_reset_type; + + /** +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index ca62fe768569b992bbf41b064734..bd39cb54b7aa3fa8edba5d9975a4 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -94,6 +94,9 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); + + switch (type) { ++ case S390_CPU_RESET_CLEAR: ++ memset(env, 0, offsetof(CPUS390XState, start_initial_reset_fields)); ++ /* fall through */ + case S390_CPU_RESET_INITIAL: + /* initial reset does not clear everything! */ + memset(&env->start_initial_reset_fields, 0, +@@ -107,6 +110,14 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + env->cregs[0] = CR0_RESET; + env->cregs[14] = CR14_RESET; + ++#if defined(CONFIG_USER_ONLY) ++ /* user mode should always be allowed to use the full FPU */ ++ env->cregs[0] |= CR0_AFP; ++ if (s390_has_feat(S390_FEAT_VECTOR)) { ++ env->cregs[0] |= CR0_VECTOR; ++ } ++#endif ++ + /* tininess for underflow is detected before rounding */ + set_float_detect_tininess(float_tininess_before_rounding, + &env->fpu_status); +@@ -125,46 +136,6 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + } + } + +-/* CPUClass:reset() */ +-static void s390_cpu_full_reset(CPUState *s) +-{ +- S390CPU *cpu = S390_CPU(s); +- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); +- CPUS390XState *env = &cpu->env; +- +- scc->parent_reset(s); +- cpu->env.sigp_order = 0; +- s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); +- +- memset(env, 0, offsetof(CPUS390XState, end_reset_fields)); +- +- /* architectured initial values for CR 0 and 14 */ +- env->cregs[0] = CR0_RESET; +- env->cregs[14] = CR14_RESET; +- +-#if defined(CONFIG_USER_ONLY) +- /* user mode should always be allowed to use the full FPU */ +- env->cregs[0] |= CR0_AFP; +- if (s390_has_feat(S390_FEAT_VECTOR)) { +- env->cregs[0] |= CR0_VECTOR; +- } +-#endif +- +- /* architectured initial value for Breaking-Event-Address register */ +- env->gbea = 1; +- +- env->pfault_token = -1UL; +- +- /* tininess for underflow is detected before rounding */ +- set_float_detect_tininess(float_tininess_before_rounding, +- &env->fpu_status); +- +- /* Reset state inside the kernel that we cannot access yet from QEMU. */ +- if (kvm_enabled()) { +- kvm_s390_reset_vcpu(cpu); +- } +-} +- + #if !defined(CONFIG_USER_ONLY) + static void s390_cpu_machine_reset_cb(void *opaque) + { +@@ -456,6 +427,11 @@ static Property s390x_cpu_properties[] = { + DEFINE_PROP_END_OF_LIST() + }; + ++static void s390_cpu_reset_full(CPUState *s) ++{ ++ return s390_cpu_reset(s, S390_CPU_RESET_CLEAR); ++} ++ + static void s390_cpu_class_init(ObjectClass *oc, void *data) + { + S390CPUClass *scc = S390_CPU_CLASS(oc); +@@ -472,7 +448,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) + scc->load_normal = s390_cpu_load_normal; + #endif + scc->reset = s390_cpu_reset; +- cc->reset = s390_cpu_full_reset; ++ cc->reset = s390_cpu_reset_full; + cc->class_by_name = s390_cpu_class_by_name, + cc->has_work = s390_cpu_has_work; + #ifdef CONFIG_TCG diff --git a/s390x-Move-diagnose-308-subcodes-and-rcs.patch b/s390x-Move-diagnose-308-subcodes-and-rcs.patch new file mode 100644 index 00000000..73735253 --- /dev/null +++ b/s390x-Move-diagnose-308-subcodes-and-rcs.patch @@ -0,0 +1,61 @@ +From: Janosch Frank +Date: Fri, 13 Mar 2020 10:35:02 -0400 +Subject: s390x: Move diagnose 308 subcodes and rcs into ipl.h + +References: bsc#1167075 + +They are part of the IPL process, so let's put them into the ipl +header. + +Signed-off-by: Janosch Frank +(cherry picked from commit 284bc3dd6e9a978e6e34b00777ce72007a88d6d9) +Signed-off-by: Bruce Rogers +--- + hw/s390x/ipl.h | 11 +++++++++++ + target/s390x/diag.c | 11 ----------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index 3e44abe1c651d8a01f4708c2801c..a5665e6bfde2e8cfbb1b2e6c7234 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -159,6 +159,17 @@ struct S390IPLState { + typedef struct S390IPLState S390IPLState; + QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + ++#define DIAG_308_RC_OK 0x0001 ++#define DIAG_308_RC_NO_CONF 0x0102 ++#define DIAG_308_RC_INVALID 0x0402 ++ ++#define DIAG308_RESET_MOD_CLR 0 ++#define DIAG308_RESET_LOAD_NORM 1 ++#define DIAG308_LOAD_CLEAR 3 ++#define DIAG308_LOAD_NORMAL_DUMP 4 ++#define DIAG308_SET 5 ++#define DIAG308_STORE 6 ++ + #define S390_IPL_TYPE_FCP 0x00 + #define S390_IPL_TYPE_CCW 0x02 + #define S390_IPL_TYPE_QEMU_SCSI 0xff +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 54e5670b3fd6d960bd3fb4baca8b..8aba6341f94848e1ce8fff420ed8 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -49,17 +49,6 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + return diag288_class->handle_timer(diag288, func, timeout); + } + +-#define DIAG_308_RC_OK 0x0001 +-#define DIAG_308_RC_NO_CONF 0x0102 +-#define DIAG_308_RC_INVALID 0x0402 +- +-#define DIAG308_RESET_MOD_CLR 0 +-#define DIAG308_RESET_LOAD_NORM 1 +-#define DIAG308_LOAD_CLEAR 3 +-#define DIAG308_LOAD_NORMAL_DUMP 4 +-#define DIAG308_SET 5 +-#define DIAG308_STORE 6 +- + static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + uintptr_t ra, bool write) + { diff --git a/s390x-Move-initial-reset.patch b/s390x-Move-initial-reset.patch new file mode 100644 index 00000000..8ab9cbef --- /dev/null +++ b/s390x-Move-initial-reset.patch @@ -0,0 +1,142 @@ +From: Janosch Frank +Date: Thu, 28 Nov 2019 03:37:23 -0500 +Subject: s390x: Move initial reset + +References: bsc#1167075 + +Let's move the intial reset into the reset handler and cleanup +afterwards. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Message-Id: <20191128083723.11937-1-frankja@linux.ibm.com> +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit 81b9222358e5c8f666f0d86057c75e40531d804c) +Signed-off-by: Bruce Rogers +--- + target/s390x/cpu-qom.h | 2 +- + target/s390x/cpu.c | 46 +++++++++++++++++------------------------- + target/s390x/cpu.h | 2 +- + target/s390x/sigp.c | 2 +- + 4 files changed, 21 insertions(+), 31 deletions(-) + +diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h +index f3b71bac67c91c9e307fa250b47a..6f0a12042ed4802de7da08d63612 100644 +--- a/target/s390x/cpu-qom.h ++++ b/target/s390x/cpu-qom.h +@@ -36,6 +36,7 @@ typedef struct S390CPUDef S390CPUDef; + + typedef enum cpu_reset_type { + S390_CPU_RESET_NORMAL, ++ S390_CPU_RESET_INITIAL, + } cpu_reset_type; + + /** +@@ -62,7 +63,6 @@ typedef struct S390CPUClass { + void (*parent_reset)(CPUState *cpu); + void (*load_normal)(CPUState *cpu); + void (*reset)(CPUState *cpu, cpu_reset_type type); +- void (*initial_cpu_reset)(CPUState *cpu); + } S390CPUClass; + + typedef struct S390CPU S390CPU; +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 67d6fbfa4401720aa24f2ace8e3c..ca62fe768569b992bbf41b064734 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -94,6 +94,23 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); + + switch (type) { ++ case S390_CPU_RESET_INITIAL: ++ /* initial reset does not clear everything! */ ++ memset(&env->start_initial_reset_fields, 0, ++ offsetof(CPUS390XState, end_reset_fields) - ++ offsetof(CPUS390XState, start_initial_reset_fields)); ++ ++ /* architectured initial value for Breaking-Event-Address register */ ++ env->gbea = 1; ++ ++ /* architectured initial values for CR 0 and 14 */ ++ env->cregs[0] = CR0_RESET; ++ env->cregs[14] = CR14_RESET; ++ ++ /* tininess for underflow is detected before rounding */ ++ set_float_detect_tininess(float_tininess_before_rounding, ++ &env->fpu_status); ++ /* fall through */ + case S390_CPU_RESET_NORMAL: + env->pfault_token = -1UL; + env->bpbc = false; +@@ -101,35 +118,9 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + default: + g_assert_not_reached(); + } +-} +- +-/* S390CPUClass::initial_reset() */ +-static void s390_cpu_initial_reset(CPUState *s) +-{ +- S390CPU *cpu = S390_CPU(s); +- CPUS390XState *env = &cpu->env; +- +- s390_cpu_reset(s, S390_CPU_RESET_NORMAL); +- /* initial reset does not clear everything! */ +- memset(&env->start_initial_reset_fields, 0, +- offsetof(CPUS390XState, end_reset_fields) - +- offsetof(CPUS390XState, start_initial_reset_fields)); +- +- /* architectured initial values for CR 0 and 14 */ +- env->cregs[0] = CR0_RESET; +- env->cregs[14] = CR14_RESET; +- +- /* architectured initial value for Breaking-Event-Address register */ +- env->gbea = 1; +- +- env->pfault_token = -1UL; +- +- /* tininess for underflow is detected before rounding */ +- set_float_detect_tininess(float_tininess_before_rounding, +- &env->fpu_status); + + /* Reset state inside the kernel that we cannot access yet from QEMU. */ +- if (kvm_enabled()) { ++ if (kvm_enabled() && type != S390_CPU_RESET_NORMAL) { + kvm_s390_reset_vcpu(cpu); + } + } +@@ -481,7 +472,6 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) + scc->load_normal = s390_cpu_load_normal; + #endif + scc->reset = s390_cpu_reset; +- scc->initial_cpu_reset = s390_cpu_initial_reset; + cc->reset = s390_cpu_full_reset; + cc->class_by_name = s390_cpu_class_by_name, + cc->has_work = s390_cpu_has_work; +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 18123dfd5bd13f530fcc3f8c54c4..d2af13b345ccd9094f82385cd528 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -748,7 +748,7 @@ static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg) + { + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + +- scc->initial_cpu_reset(cs); ++ scc->reset(cs, S390_CPU_RESET_INITIAL); + } + + static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg) +diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c +index 850139b9cd544c4bb34497fec554..727875bb4ab9b6c6f606e4ba8afb 100644 +--- a/target/s390x/sigp.c ++++ b/target/s390x/sigp.c +@@ -254,7 +254,7 @@ static void sigp_initial_cpu_reset(CPUState *cs, run_on_cpu_data arg) + SigpInfo *si = arg.host_ptr; + + cpu_synchronize_state(cs); +- scc->initial_cpu_reset(cs); ++ scc->reset(cs, S390_CPU_RESET_INITIAL); + cpu_synchronize_post_reset(cs); + si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; + } diff --git a/s390x-Move-reset-normal-to-shared-reset-.patch b/s390x-Move-reset-normal-to-shared-reset-.patch new file mode 100644 index 00000000..9910bbf6 --- /dev/null +++ b/s390x-Move-reset-normal-to-shared-reset-.patch @@ -0,0 +1,128 @@ +From: Janosch Frank +Date: Wed, 27 Nov 2019 12:50:42 -0500 +Subject: s390x: Move reset normal to shared reset handler + +References: bsc#1167075 + +Let's start moving the cpu reset functions into a single function with +a switch/case, so we can later use fallthroughs and share more code +between resets. + +This patch introduces the reset function by renaming cpu_reset(). + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Message-Id: <20191127175046.4911-3-frankja@linux.ibm.com> +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit eac4f82791f1807c423e85670837db103b9d59b3) +Signed-off-by: Bruce Rogers +--- + target/s390x/cpu-qom.h | 6 +++++- + target/s390x/cpu.c | 19 +++++++++++++------ + target/s390x/cpu.h | 2 +- + target/s390x/sigp.c | 2 +- + 4 files changed, 20 insertions(+), 9 deletions(-) + +diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h +index b809ec8418e016cf8b227489f905..f3b71bac67c91c9e307fa250b47a 100644 +--- a/target/s390x/cpu-qom.h ++++ b/target/s390x/cpu-qom.h +@@ -34,6 +34,10 @@ + typedef struct S390CPUModel S390CPUModel; + typedef struct S390CPUDef S390CPUDef; + ++typedef enum cpu_reset_type { ++ S390_CPU_RESET_NORMAL, ++} cpu_reset_type; ++ + /** + * S390CPUClass: + * @parent_realize: The parent class' realize handler. +@@ -57,7 +61,7 @@ typedef struct S390CPUClass { + DeviceRealize parent_realize; + void (*parent_reset)(CPUState *cpu); + void (*load_normal)(CPUState *cpu); +- void (*cpu_reset)(CPUState *cpu); ++ void (*reset)(CPUState *cpu, cpu_reset_type type); + void (*initial_cpu_reset)(CPUState *cpu); + } S390CPUClass; + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 3abe7e80fd0a067a95545c7c3b9b..67d6fbfa4401720aa24f2ace8e3c 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -82,18 +82,25 @@ static void s390_cpu_load_normal(CPUState *s) + } + #endif + +-/* S390CPUClass::cpu_reset() */ +-static void s390_cpu_reset(CPUState *s) ++/* S390CPUClass::reset() */ ++static void s390_cpu_reset(CPUState *s, cpu_reset_type type) + { + S390CPU *cpu = S390_CPU(s); + S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); + CPUS390XState *env = &cpu->env; + +- env->pfault_token = -1UL; +- env->bpbc = false; + scc->parent_reset(s); + cpu->env.sigp_order = 0; + s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); ++ ++ switch (type) { ++ case S390_CPU_RESET_NORMAL: ++ env->pfault_token = -1UL; ++ env->bpbc = false; ++ break; ++ default: ++ g_assert_not_reached(); ++ } + } + + /* S390CPUClass::initial_reset() */ +@@ -102,7 +109,7 @@ static void s390_cpu_initial_reset(CPUState *s) + S390CPU *cpu = S390_CPU(s); + CPUS390XState *env = &cpu->env; + +- s390_cpu_reset(s); ++ s390_cpu_reset(s, S390_CPU_RESET_NORMAL); + /* initial reset does not clear everything! */ + memset(&env->start_initial_reset_fields, 0, + offsetof(CPUS390XState, end_reset_fields) - +@@ -473,7 +480,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) + #if !defined(CONFIG_USER_ONLY) + scc->load_normal = s390_cpu_load_normal; + #endif +- scc->cpu_reset = s390_cpu_reset; ++ scc->reset = s390_cpu_reset; + scc->initial_cpu_reset = s390_cpu_initial_reset; + cc->reset = s390_cpu_full_reset; + cc->class_by_name = s390_cpu_class_by_name, +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 17460ed7b381070b4d8206e2c4cb..18123dfd5bd13f530fcc3f8c54c4 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -741,7 +741,7 @@ static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg) + { + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + +- scc->cpu_reset(cs); ++ scc->reset(cs, S390_CPU_RESET_NORMAL); + } + + static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg) +diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c +index 2ce22d4dc18bb764948f0abe1084..850139b9cd544c4bb34497fec554 100644 +--- a/target/s390x/sigp.c ++++ b/target/s390x/sigp.c +@@ -266,7 +266,7 @@ static void sigp_cpu_reset(CPUState *cs, run_on_cpu_data arg) + SigpInfo *si = arg.host_ptr; + + cpu_synchronize_state(cs); +- scc->cpu_reset(cs); ++ scc->reset(cs, S390_CPU_RESET_NORMAL); + cpu_synchronize_post_reset(cs); + si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; + } diff --git a/s390x-ipl-Consolidate-iplb-validity-chec.patch b/s390x-ipl-Consolidate-iplb-validity-chec.patch new file mode 100644 index 00000000..3465f21e --- /dev/null +++ b/s390x-ipl-Consolidate-iplb-validity-chec.patch @@ -0,0 +1,64 @@ +From: Janosch Frank +Date: Tue, 10 Mar 2020 05:09:50 -0400 +Subject: s390x: ipl: Consolidate iplb validity check into one function + +References: bsc#1167075 + +It's nicer to just call one function than calling a function for each +possible iplb type. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Message-Id: <20200310090950.61172-1-frankja@linux.ibm.com> +Reviewed-by: Christian Borntraeger +Signed-off-by: Christian Borntraeger +(cherry picked from commit 94c21436e5a89143f8b9cb4d089d1a2f3f4fd377) +Signed-off-by: Bruce Rogers +--- + hw/s390x/ipl.h | 18 +++++++++--------- + target/s390x/diag.c | 2 +- + 2 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index d4813105db33253fd1eba53cd7e3..3e44abe1c651d8a01f4708c2801c 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -173,16 +173,16 @@ static inline bool iplb_valid_len(IplParameterBlock *iplb) + return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock); + } + +-static inline bool iplb_valid_ccw(IplParameterBlock *iplb) ++static inline bool iplb_valid(IplParameterBlock *iplb) + { +- return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN && +- iplb->pbt == S390_IPL_TYPE_CCW; +-} +- +-static inline bool iplb_valid_fcp(IplParameterBlock *iplb) +-{ +- return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN && +- iplb->pbt == S390_IPL_TYPE_FCP; ++ switch (iplb->pbt) { ++ case S390_IPL_TYPE_FCP: ++ return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN; ++ case S390_IPL_TYPE_CCW: ++ return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN; ++ default: ++ return false; ++ } + } + + #endif +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 53c2f81f2a1aad58d417bc3dc79c..0c81d8e1efbfe37a384199488a72 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -100,7 +100,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + + cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); + +- if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb)) { ++ if (!iplb_valid(iplb)) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } diff --git a/s390x-kvm-Make-kvm_sclp_service_call-voi.patch b/s390x-kvm-Make-kvm_sclp_service_call-voi.patch new file mode 100644 index 00000000..feff53ff --- /dev/null +++ b/s390x-kvm-Make-kvm_sclp_service_call-voi.patch @@ -0,0 +1,66 @@ +From: Janosch Frank +Date: Fri, 29 Nov 2019 04:17:13 -0500 +Subject: s390x: kvm: Make kvm_sclp_service_call void + +References: bsc#1167075 + +It defaults to returning 0 anyway and that return value is not +necessary, as 0 is also the default rc that the caller would return. + +While doing that we can simplify the logic a bit and return early if +we inject a PGM exception. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Message-Id: <20191129091713.4582-1-frankja@linux.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit 15b6c0370c3e2774fd9ffda5c10c6e36952e8eb6) +Signed-off-by: Bruce Rogers +--- + target/s390x/kvm.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 0c9d14b4b115de974e21af3f0f47..ad6e38c8761be7e0cad57771f49b 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -1159,13 +1159,13 @@ void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code) + kvm_s390_vcpu_interrupt(cpu, &irq); + } + +-static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, ++static void kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, + uint16_t ipbh0) + { + CPUS390XState *env = &cpu->env; + uint64_t sccb; + uint32_t code; +- int r = 0; ++ int r; + + sccb = env->regs[ipbh0 & 0xf]; + code = env->regs[(ipbh0 & 0xf0) >> 4]; +@@ -1173,11 +1173,9 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, + r = sclp_service_call(env, sccb, code); + if (r < 0) { + kvm_s390_program_interrupt(cpu, -r); +- } else { +- setcc(cpu, r); ++ return; + } +- +- return 0; ++ setcc(cpu, r); + } + + static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) +@@ -1240,7 +1238,7 @@ static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) + setcc(cpu, 3); + break; + case PRIV_B2_SCLP_CALL: +- rc = kvm_sclp_service_call(cpu, run, ipbh0); ++ kvm_sclp_service_call(cpu, run, ipbh0); + break; + default: + rc = -1; diff --git a/s390x-protvirt-Add-migration-blocker.patch b/s390x-protvirt-Add-migration-blocker.patch new file mode 100644 index 00000000..bd0d588b --- /dev/null +++ b/s390x-protvirt-Add-migration-blocker.patch @@ -0,0 +1,64 @@ +From: Janosch Frank +Date: Fri, 6 Mar 2020 06:40:13 -0500 +Subject: s390x: protvirt: Add migration blocker + +References: bsc#1167075 + +Migration is not yet supported. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit e721e55a3dabb2897081614b17dd4565e85249ac) +Signed-off-by: Bruce Rogers +--- + hw/s390x/s390-virtio-ccw.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 5149030d2216040c396a02d977c8..ed910a099627dae96ab5da747fb3 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -44,6 +44,9 @@ + #include "sysemu/sysemu.h" + #include "hw/s390x/pv.h" + #include ++#include "migration/blocker.h" ++ ++static Error *pv_mig_blocker; + + S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) + { +@@ -325,15 +328,30 @@ static void s390_machine_unprotect(S390CcwMachineState *ms) + { + s390_pv_vm_disable(); + ms->pv = false; ++ migrate_del_blocker(pv_mig_blocker); ++ error_free_or_abort(&pv_mig_blocker); + } + + static int s390_machine_protect(S390CcwMachineState *ms) + { ++ Error *local_err = NULL; + int rc; + ++ error_setg(&pv_mig_blocker, ++ "protected VMs are currently not migrateable."); ++ rc = migrate_add_blocker(pv_mig_blocker, &local_err); ++ if (rc) { ++ error_report_err(local_err); ++ error_free_or_abort(&pv_mig_blocker); ++ return rc; ++ } ++ + /* Create SE VM */ + rc = s390_pv_vm_enable(); + if (rc) { ++ error_report_err(local_err); ++ migrate_del_blocker(pv_mig_blocker); ++ error_free_or_abort(&pv_mig_blocker); + return rc; + } + diff --git a/s390x-protvirt-Disable-address-checks-fo.patch b/s390x-protvirt-Disable-address-checks-fo.patch new file mode 100644 index 00000000..e985f70b --- /dev/null +++ b/s390x-protvirt-Disable-address-checks-fo.patch @@ -0,0 +1,119 @@ +From: Janosch Frank +Date: Fri, 29 Nov 2019 04:22:41 -0500 +Subject: s390x: protvirt: Disable address checks for PV guest IO emulation + +References: bsc#1167075 + +IO instruction data is routed through SIDAD for protected guests, so +adresses do not need to be checked, as this is kernel memory which is +always available. + +Also the instruction data always starts at offset 0 of the SIDAD. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit f658bf14295ad49caf8d1b21033982ce69423fb7) +Signed-off-by: Bruce Rogers +--- + target/s390x/ioinst.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index c437a1d8c6afed80199034ab6f6a..bbcccf6be23456393282287bf116 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -16,6 +16,25 @@ + #include "hw/s390x/ioinst.h" + #include "trace.h" + #include "hw/s390x/s390-pci-bus.h" ++#include "hw/s390x/pv.h" ++ ++/* All I/O instructions but chsc use the s format */ ++static uint64_t get_address_from_regs(CPUS390XState *env, uint32_t ipb, ++ uint8_t *ar) ++{ ++ /* ++ * Addresses for protected guests are all offsets into the ++ * satellite block which holds the IO control structures. Those ++ * control structures are always starting at offset 0 and are ++ * always aligned and accessible. So we can return 0 here which ++ * will pass the following address checks. ++ */ ++ if (s390_is_pv()) { ++ *ar = 0; ++ return 0; ++ } ++ return decode_basedisp_s(env, ipb, ar); ++} + + int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid, + int *schid) +@@ -114,7 +133,7 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -171,7 +190,7 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -203,7 +222,7 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -234,7 +253,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + CPUS390XState *env = &cpu->env; + uint8_t ar; + +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; +@@ -303,7 +322,7 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + return -EIO; + } + trace_ioinst_sch_id("tsch", cssid, ssid, schid); +- addr = decode_basedisp_s(env, ipb, &ar); ++ addr = get_address_from_regs(env, ipb, &ar); + if (addr & 3) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return -EIO; +@@ -601,7 +620,7 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + { + ChscReq *req; + ChscResp *res; +- uint64_t addr; ++ uint64_t addr = 0; + int reg; + uint16_t len; + uint16_t command; +@@ -610,7 +629,9 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + + trace_ioinst("chsc"); + reg = (ipb >> 20) & 0x00f; +- addr = env->regs[reg]; ++ if (!s390_is_pv()) { ++ addr = env->regs[reg]; ++ } + /* Page boundary? */ + if (addr & 0xfff) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); diff --git a/s390x-protvirt-Handle-SIGP-store-status-.patch b/s390x-protvirt-Handle-SIGP-store-status-.patch new file mode 100644 index 00000000..fcc698dc --- /dev/null +++ b/s390x-protvirt-Handle-SIGP-store-status-.patch @@ -0,0 +1,44 @@ +From: Janosch Frank +Date: Tue, 6 Aug 2019 15:40:05 +0200 +Subject: s390x: protvirt: Handle SIGP store status correctly + +References: bsc#1167075 + +For protected VMs status storing is not done by QEMU anymore. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit 398fc6874438c320407449d1c9560925aba2280b) +Signed-off-by: Bruce Rogers +--- + target/s390x/helper.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/target/s390x/helper.c b/target/s390x/helper.c +index 6808dfda01f42acbaa1d36ef787b..36b6d3d9d1bca9db90aac1c7bec6 100644 +--- a/target/s390x/helper.c ++++ b/target/s390x/helper.c +@@ -25,6 +25,7 @@ + #include "qemu/timer.h" + #include "qemu/qemu-print.h" + #include "hw/s390x/ioinst.h" ++#include "hw/s390x/pv.h" + #include "sysemu/hw_accel.h" + #include "sysemu/runstate.h" + #ifndef CONFIG_USER_ONLY +@@ -246,6 +247,11 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch) + hwaddr len = sizeof(*sa); + int i; + ++ /* For PVMs storing will occur when this cpu enters SIE again */ ++ if (s390_is_pv()) { ++ return 0; ++ } ++ + sa = cpu_physical_memory_map(addr, &len, 1); + if (!sa) { + return -EFAULT; diff --git a/s390x-protvirt-Inhibit-balloon-when-swit.patch b/s390x-protvirt-Inhibit-balloon-when-swit.patch new file mode 100644 index 00000000..f0a9995e --- /dev/null +++ b/s390x-protvirt-Inhibit-balloon-when-swit.patch @@ -0,0 +1,84 @@ +From: Janosch Frank +Date: Mon, 24 Feb 2020 07:49:06 -0500 +Subject: s390x: protvirt: Inhibit balloon when switching to protected mode + +References: bsc#1167075 + +Ballooning in protected VMs can only be done when the guest shares the +pages it gives to the host. If pages are not shared, the integrity +checks will fail once those pages have been altered and are given back +to the guest. + +As we currently do not yet have a solution for this we will continue +like this: + +1. We block ballooning now in QEMU (with this patch). + +2. Later we will provide a change to virtio that removes the blocker +and adds VIRTIO_F_IOMMU_PLATFORM automatically by QEMU when doing the +protvirt switch. This is OK, as the balloon driver in Linux (the only +supported guest) will refuse to work with the IOMMU_PLATFORM feature +bit set. + +3. Later, we can fix the guest balloon driver to accept the IOMMU +feature bit and correctly exercise sharing and unsharing of balloon +pages. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit 59dc32a3494d6afdd420f3e401f1f324a1179256) +Signed-off-by: Bruce Rogers +--- + hw/s390x/s390-virtio-ccw.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index ed910a099627dae96ab5da747fb3..85250bf046ed72313b03c6ff6c54 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -42,6 +42,7 @@ + #include "hw/qdev-properties.h" + #include "hw/s390x/tod.h" + #include "sysemu/sysemu.h" ++#include "sysemu/balloon.h" + #include "hw/s390x/pv.h" + #include + #include "migration/blocker.h" +@@ -330,6 +331,7 @@ static void s390_machine_unprotect(S390CcwMachineState *ms) + ms->pv = false; + migrate_del_blocker(pv_mig_blocker); + error_free_or_abort(&pv_mig_blocker); ++ qemu_balloon_inhibit(false); + } + + static int s390_machine_protect(S390CcwMachineState *ms) +@@ -337,10 +339,18 @@ static int s390_machine_protect(S390CcwMachineState *ms) + Error *local_err = NULL; + int rc; + ++ /* ++ * Ballooning on protected VMs needs support in the guest for ++ * sharing and unsharing balloon pages. Block ballooning for ++ * now, until we have a solution to make at least Linux guests ++ * either support it or fail gracefully. ++ */ ++ qemu_balloon_inhibit(true); + error_setg(&pv_mig_blocker, + "protected VMs are currently not migrateable."); + rc = migrate_add_blocker(pv_mig_blocker, &local_err); + if (rc) { ++ qemu_balloon_inhibit(false); + error_report_err(local_err); + error_free_or_abort(&pv_mig_blocker); + return rc; +@@ -349,6 +359,7 @@ static int s390_machine_protect(S390CcwMachineState *ms) + /* Create SE VM */ + rc = s390_pv_vm_enable(); + if (rc) { ++ qemu_balloon_inhibit(false); + error_report_err(local_err); + migrate_del_blocker(pv_mig_blocker); + error_free_or_abort(&pv_mig_blocker); diff --git a/s390x-protvirt-KVM-intercept-changes.patch b/s390x-protvirt-KVM-intercept-changes.patch new file mode 100644 index 00000000..571f65d3 --- /dev/null +++ b/s390x-protvirt-KVM-intercept-changes.patch @@ -0,0 +1,60 @@ +From: Janosch Frank +Date: Mon, 13 May 2019 10:35:27 +0200 +Subject: s390x: protvirt: KVM intercept changes + +References: bsc#1167075 + +Protected VMs no longer intercept with code 4 for an instruction +interception. Instead they have codes 104 and 108 for protected +instruction interception and protected instruction notification +respectively. + +The 104 mirrors the 4 interception. + +The 108 is a notification interception to let KVM and QEMU know that +something changed and we need to update tracking information or +perform specific tasks. It's currently taken for the following +instructions: + +* spx (To inform about the changed prefix location) +* sclp (On incorrect SCCB values, so we can inject a IRQ) +* sigp (All but "stop and store status") +* diag308 (Subcodes 0/1) + +Of these exits only sclp errors, state changing sigps and diag308 will +reach QEMU. QEMU will do its parts of the job, while the ultravisor +has done the instruction part of the job. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit fd70eb764f176c200d6723c2ad88362f23536bfa) +Signed-off-by: Bruce Rogers +--- + target/s390x/kvm.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index d8d02ff34f4fc942cb7935deec58..abeeaaa67452b0b938557b0d0dea 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -115,6 +115,8 @@ + #define ICPT_CPU_STOP 0x28 + #define ICPT_OPEREXC 0x2c + #define ICPT_IO 0x40 ++#define ICPT_PV_INSTR 0x68 ++#define ICPT_PV_INSTR_NOTIFICATION 0x6c + + #define NR_LOCAL_IRQS 32 + /* +@@ -1695,6 +1697,8 @@ static int handle_intercept(S390CPU *cpu) + (long)cs->kvm_run->psw_addr); + switch (icpt_code) { + case ICPT_INSTRUCTION: ++ case ICPT_PV_INSTR: ++ case ICPT_PV_INSTR_NOTIFICATION: + r = handle_instruction(cpu, run); + break; + case ICPT_PROGRAM: diff --git a/s390x-protvirt-Move-IO-control-structure.patch b/s390x-protvirt-Move-IO-control-structure.patch new file mode 100644 index 00000000..3b626663 --- /dev/null +++ b/s390x-protvirt-Move-IO-control-structure.patch @@ -0,0 +1,156 @@ +From: Janosch Frank +Date: Wed, 5 Feb 2020 07:02:33 -0500 +Subject: s390x: protvirt: Move IO control structures over SIDA + +References: bsc#1167075 + +For protected guests, we need to put the IO emulation results into the +SIDA, so SIE will write them into the guest at the next entry. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Cornelia Huck +(cherry picked from commit 4989e18cbe5621df39020ef812316f479d8f5246) +Signed-off-by: Bruce Rogers +--- + target/s390x/ioinst.c | 61 +++++++++++++++++++++++++++++++------------ + 1 file changed, 45 insertions(+), 16 deletions(-) + +diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c +index bbcccf6be23456393282287bf116..f40c35c6ff58315622510ae72103 100644 +--- a/target/s390x/ioinst.c ++++ b/target/s390x/ioinst.c +@@ -138,7 +138,9 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, &schib, sizeof(schib)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -195,7 +197,9 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, &orig_orb, sizeof(orb)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -231,14 +235,19 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + cc = css_do_stcrw(&crw); + /* 0 - crw stored, 1 - zeroes stored */ + +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &crw, sizeof(crw)); + setcc(cpu, cc); + } else { +- if (cc == 0) { +- /* Write failed: requeue CRW since STCRW is suppressing */ +- css_undo_stcrw(&crw); ++ if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { ++ setcc(cpu, cc); ++ } else { ++ if (cc == 0) { ++ /* Write failed: requeue CRW since STCRW is suppressing */ ++ css_undo_stcrw(&crw); ++ } ++ s390_cpu_virt_mem_handle_exc(cpu, ra); + } +- s390_cpu_virt_mem_handle_exc(cpu, ra); + } + } + +@@ -260,6 +269,13 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + } + + if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) { ++ /* ++ * The Ultravisor checks schid bit 16 to be one and bits 0-12 ++ * to be 0 and injects a operand exception itself. ++ * ++ * Hence we should never end up here. ++ */ ++ g_assert(!s390_is_pv()); + /* + * As operand exceptions have a lower priority than access exceptions, + * we check whether the memory area is writeable (injecting the +@@ -292,14 +308,17 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, + } + } + if (cc != 3) { +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, +- sizeof(schib)) != 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &schib, sizeof(schib)); ++ } else if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, ++ sizeof(schib)) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } + } else { + /* Access exceptions have a higher priority than cc3 */ +- if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) { ++ if (!s390_is_pv() && ++ s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -336,7 +355,9 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + } + /* 0 - status pending, 1 - not status pending, 3 - not operational */ + if (cc != 3) { +- if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr, &irb, irb_len); ++ } else if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return -EFAULT; + } +@@ -344,7 +365,8 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra) + } else { + irb_len = sizeof(irb) - sizeof(irb.emw); + /* Access exceptions have a higher priority than cc3 */ +- if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) { ++ if (!s390_is_pv() && ++ s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return -EFAULT; + } +@@ -642,7 +664,9 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + * present CHSC sub-handlers ... if we ever need more, we should take + * care of req->len here first. + */ +- if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, addr, buf, sizeof(ChscReq)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) { + s390_cpu_virt_mem_handle_exc(cpu, ra); + return; + } +@@ -675,11 +699,16 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra) + break; + } + +- if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, +- be16_to_cpu(res->len))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, addr + len, res, be16_to_cpu(res->len)); + setcc(cpu, 0); /* Command execution complete */ + } else { +- s390_cpu_virt_mem_handle_exc(cpu, ra); ++ if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, ++ be16_to_cpu(res->len))) { ++ setcc(cpu, 0); /* Command execution complete */ ++ } else { ++ s390_cpu_virt_mem_handle_exc(cpu, ra); ++ } + } + } + diff --git a/s390x-protvirt-Move-STSI-data-over-SIDAD.patch b/s390x-protvirt-Move-STSI-data-over-SIDAD.patch new file mode 100644 index 00000000..7087ed64 --- /dev/null +++ b/s390x-protvirt-Move-STSI-data-over-SIDAD.patch @@ -0,0 +1,55 @@ +From: Janosch Frank +Date: Wed, 5 Feb 2020 07:02:51 -0500 +Subject: s390x: protvirt: Move STSI data over SIDAD + +References: bsc#1167075 + +For protected guests, we need to put the STSI emulation results into +the SIDA, so SIE will write them into the guest at the next entry. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit ccce7a654911ae507c962aff5f41004a7a88fad6) +Signed-off-by: Bruce Rogers +--- + target/s390x/kvm.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 941e4df630ad9b3dc780d3c92e6b..d00e05cc10d274790a215d0f4359 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -50,6 +50,7 @@ + #include "exec/memattrs.h" + #include "hw/s390x/s390-virtio-ccw.h" + #include "hw/s390x/s390-virtio-hcall.h" ++#include "hw/s390x/pv.h" + + #ifndef DEBUG_KVM + #define DEBUG_KVM 0 +@@ -1803,7 +1804,9 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar) + SysIB_322 sysib; + int del; + +- if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) { ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_read(cpu, 0, &sysib, sizeof(sysib)); ++ } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) { + return; + } + /* Shift the stack of Extended Names to prepare for our own data */ +@@ -1843,7 +1846,11 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar) + /* Insert UUID */ + memcpy(sysib.vm[0].uuid, &qemu_uuid, sizeof(sysib.vm[0].uuid)); + +- s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib)); ++ if (s390_is_pv()) { ++ s390_cpu_pv_mem_write(cpu, 0, &sysib, sizeof(sysib)); ++ } else { ++ s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib)); ++ } + } + + static int handle_stsi(S390CPU *cpu) diff --git a/s390x-protvirt-Move-diag-308-data-over-S.patch b/s390x-protvirt-Move-diag-308-data-over-S.patch new file mode 100644 index 00000000..778c757b --- /dev/null +++ b/s390x-protvirt-Move-diag-308-data-over-S.patch @@ -0,0 +1,78 @@ +From: Janosch Frank +Date: Wed, 31 Jul 2019 17:49:08 +0200 +Subject: s390x: protvirt: Move diag 308 data over SIDA + +References: bsc#1167075 + +For protected guests the IPIB is written/read to/from the SIDA, so we +need those accesses to go through s390_cpu_pv_mem_read/write(). + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit 258da1c7736d3aa4604ceea6cce00995c6f30058) +Signed-off-by: Bruce Rogers +--- + target/s390x/diag.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index b2cbefb8cfe4e5a244219e761fb4..1a4842956402e308426c0ed5ce5c 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -75,6 +75,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { + bool valid; + CPUState *cs = env_cpu(env); ++ S390CPU *cpu = S390_CPU(cs); + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; + IplParameterBlock *iplb; +@@ -111,13 +112,22 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + return; + } + iplb = g_new0(IplParameterBlock, 1); +- cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); ++ if (!s390_is_pv()) { ++ cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); ++ } else { ++ s390_cpu_pv_mem_read(cpu, 0, iplb, sizeof(iplb->len)); ++ } ++ + if (!iplb_valid_len(iplb)) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } + +- cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); ++ if (!s390_is_pv()) { ++ cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); ++ } else { ++ s390_cpu_pv_mem_read(cpu, 0, iplb, be32_to_cpu(iplb->len)); ++ } + + valid = subcode == DIAG308_PV_SET ? iplb_valid_pv(iplb) : iplb_valid(iplb); + if (!valid) { +@@ -140,12 +150,17 @@ out: + } else { + iplb = s390_ipl_get_iplb(); + } +- if (iplb) { ++ if (!iplb) { ++ env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; ++ return; ++ } ++ ++ if (!s390_is_pv()) { + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); +- env->regs[r1 + 1] = DIAG_308_RC_OK; + } else { +- env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; ++ s390_cpu_pv_mem_write(cpu, 0, iplb, be32_to_cpu(iplb->len)); + } ++ env->regs[r1 + 1] = DIAG_308_RC_OK; + return; + case DIAG308_PV_START: + iplb = s390_ipl_get_iplb_pv(); diff --git a/s390x-protvirt-SCLP-interpretation.patch b/s390x-protvirt-SCLP-interpretation.patch new file mode 100644 index 00000000..20abaeaa --- /dev/null +++ b/s390x-protvirt-SCLP-interpretation.patch @@ -0,0 +1,156 @@ +From: Janosch Frank +Date: Mon, 3 Jun 2019 16:40:29 +0200 +Subject: s390x: protvirt: SCLP interpretation + +References: bsc#1167075 + +SCLP for a protected guest is done over the SIDAD, so we need to use +the s390_cpu_pv_mem_* functions to access the SIDAD instead of guest +memory when reading/writing SCBs. + +To not confuse the sclp emulation, we set 0x4000 as the SCCB address, +since the function that injects the sclp external interrupt would +reject a zero sccb address. + +Signed-off-by: Janosch Frank +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit 32633cf4539341180dbc7a92c2655c711b4a6996) +Signed-off-by: Bruce Rogers +--- + hw/s390x/sclp.c | 56 +++++++++++++++++++++++++++++++++-------- + include/hw/s390x/sclp.h | 2 ++ + target/s390x/kvm.c | 25 ++++++++++++++---- + 3 files changed, 67 insertions(+), 16 deletions(-) + +diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c +index f57ce7b73943564f4d44dcbe0cf0..1c380a49cc7140687329e43e9745 100644 +--- a/hw/s390x/sclp.c ++++ b/hw/s390x/sclp.c +@@ -33,6 +33,22 @@ static inline SCLPDevice *get_sclp_device(void) + return sclp; + } + ++static inline bool sclp_command_code_valid(uint32_t code) ++{ ++ switch (code & SCLP_CMD_CODE_MASK) { ++ case SCLP_CMDW_READ_SCP_INFO: ++ case SCLP_CMDW_READ_SCP_INFO_FORCED: ++ case SCLP_CMDW_READ_CPU_INFO: ++ case SCLP_CMDW_CONFIGURE_IOA: ++ case SCLP_CMDW_DECONFIGURE_IOA: ++ case SCLP_CMD_READ_EVENT_DATA: ++ case SCLP_CMD_WRITE_EVENT_DATA: ++ case SCLP_CMD_WRITE_EVENT_MASK: ++ return true; ++ } ++ return false; ++} ++ + static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count) + { + MachineState *ms = MACHINE(qdev_get_machine()); +@@ -193,6 +209,34 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code) + } + } + ++/* ++ * We only need the address to have something valid for the ++ * service_interrupt call. ++ */ ++#define SCLP_PV_DUMMY_ADDR 0x4000 ++int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb, ++ uint32_t code) ++{ ++ SCLPDevice *sclp = get_sclp_device(); ++ SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp); ++ SCCB work_sccb; ++ hwaddr sccb_len = sizeof(SCCB); ++ ++ s390_cpu_pv_mem_read(env_archcpu(env), 0, &work_sccb, sccb_len); ++ ++ if (!sclp_command_code_valid(code)) { ++ work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); ++ goto out_write; ++ } ++ ++ sclp_c->execute(sclp, &work_sccb, code); ++out_write: ++ s390_cpu_pv_mem_write(env_archcpu(env), 0, &work_sccb, ++ be16_to_cpu(work_sccb.h.length)); ++ sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR); ++ return 0; ++} ++ + int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) + { + SCLPDevice *sclp = get_sclp_device(); +@@ -230,17 +274,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code) + goto out; + } + +- switch (code & SCLP_CMD_CODE_MASK) { +- case SCLP_CMDW_READ_SCP_INFO: +- case SCLP_CMDW_READ_SCP_INFO_FORCED: +- case SCLP_CMDW_READ_CPU_INFO: +- case SCLP_CMDW_CONFIGURE_IOA: +- case SCLP_CMDW_DECONFIGURE_IOA: +- case SCLP_CMD_READ_EVENT_DATA: +- case SCLP_CMD_WRITE_EVENT_DATA: +- case SCLP_CMD_WRITE_EVENT_MASK: +- break; +- default: ++ if (!sclp_command_code_valid(code)) { + work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); + goto out_write; + } +diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h +index c54413b78cf01b274cc249b1409b..c0a3faa37d7304536e75d32f2050 100644 +--- a/include/hw/s390x/sclp.h ++++ b/include/hw/s390x/sclp.h +@@ -217,5 +217,7 @@ void s390_sclp_init(void); + void sclp_service_interrupt(uint32_t sccb); + void raise_irq_cpu_hotplug(void); + int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code); ++int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb, ++ uint32_t code); + + #endif +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index d00e05cc10d274790a215d0f4359..d94b915da419c3ad0a1f9622ca13 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -1230,12 +1230,27 @@ static void kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, + sccb = env->regs[ipbh0 & 0xf]; + code = env->regs[(ipbh0 & 0xf0) >> 4]; + +- r = sclp_service_call(env, sccb, code); +- if (r < 0) { +- kvm_s390_program_interrupt(cpu, -r); +- return; ++ switch (run->s390_sieic.icptcode) { ++ case ICPT_PV_INSTR_NOTIFICATION: ++ g_assert(s390_is_pv()); ++ /* The notification intercepts are currently handled by KVM */ ++ error_report("unexpected SCLP PV notification"); ++ exit(1); ++ break; ++ case ICPT_PV_INSTR: ++ g_assert(s390_is_pv()); ++ sclp_service_call_protected(env, sccb, code); ++ /* Setting the CC is done by the Ultravisor. */ ++ break; ++ case ICPT_INSTRUCTION: ++ g_assert(!s390_is_pv()); ++ r = sclp_service_call(env, sccb, code); ++ if (r < 0) { ++ kvm_s390_program_interrupt(cpu, -r); ++ return; ++ } ++ setcc(cpu, r); + } +- setcc(cpu, r); + } + + static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) diff --git a/s390x-protvirt-Set-guest-IPL-PSW.patch b/s390x-protvirt-Set-guest-IPL-PSW.patch new file mode 100644 index 00000000..d8c02aa6 --- /dev/null +++ b/s390x-protvirt-Set-guest-IPL-PSW.patch @@ -0,0 +1,45 @@ +From: Janosch Frank +Date: Tue, 23 Jul 2019 13:17:32 +0200 +Subject: s390x: protvirt: Set guest IPL PSW + +References: bsc#1167075 + +Handling of CPU reset and setting of the IPL psw from guest storage at +offset 0 is done by a Ultravisor call. Let's only fetch it if +necessary. + +Signed-off-by: Janosch Frank +Reviewed-by: Thomas Huth +Reviewed-by: David Hildenbrand +Reviewed-by: Christian Borntraeger +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit e8686d9849f1625f4f4b28403f0555181b72d1b6) +Signed-off-by: Bruce Rogers +--- + target/s390x/cpu.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 479f1978c974722ceeb72ac5fb32..6da0c3f15530310fba5f609b8c7f 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -77,8 +77,16 @@ static bool s390_cpu_has_work(CPUState *cs) + static void s390_cpu_load_normal(CPUState *s) + { + S390CPU *cpu = S390_CPU(s); +- cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR; +- cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64; ++ if (!s390_is_pv()) { ++ cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR; ++ cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64; ++ } else { ++ /* ++ * Firmware requires us to set the load state before we set ++ * the cpu to operating on protected guests. ++ */ ++ s390_cpu_set_state(S390_CPU_STATE_LOAD, cpu); ++ } + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); + } + #endif diff --git a/s390x-protvirt-Support-unpack-facility.patch b/s390x-protvirt-Support-unpack-facility.patch new file mode 100644 index 00000000..7e331413 --- /dev/null +++ b/s390x-protvirt-Support-unpack-facility.patch @@ -0,0 +1,868 @@ +From: Janosch Frank +Date: Mon, 11 Feb 2019 16:07:19 +0100 +Subject: s390x: protvirt: Support unpack facility + +References: bsc#1167075 + +The unpack facility provides the means to setup a protected guest. A +protected guest cannot be introspected by the hypervisor or any +user/administrator of the machine it is running on. + +Protected guests are encrypted at rest and need a special boot +mechanism via diag308 subcode 8 and 10. + +Code 8 sets the PV specific IPLB which is retained separately from +those set via code 5. + +Code 10 is used to unpack the VM into protected memory, verify its +integrity and start it. + +Signed-off-by: Janosch Frank +Co-developed-by: Christian Borntraeger [Changes +to machine] +Reviewed-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Reviewed-by: Cornelia Huck +(cherry picked from commit 2150c92b9b7d12b5fbdd2c59e5b17197d28f53db) +[BR: Needed to fix a compiler warning on i586 in hw/s390x/ipl.c] +Signed-off-by: Bruce Rogers +--- + MAINTAINERS | 2 + + hw/s390x/Makefile.objs | 1 + + hw/s390x/ipl.c | 59 +++++++++++++- + hw/s390x/ipl.h | 91 ++++++++++++++++++++- + hw/s390x/pv.c | 98 +++++++++++++++++++++++ + hw/s390x/s390-virtio-ccw.c | 119 +++++++++++++++++++++++++++- + include/hw/s390x/pv.h | 55 +++++++++++++ + include/hw/s390x/s390-virtio-ccw.h | 1 + + target/s390x/cpu.c | 1 + + target/s390x/cpu_features_def.inc.h | 1 + + target/s390x/diag.c | 39 ++++++++- + target/s390x/kvm-stub.c | 5 ++ + target/s390x/kvm.c | 5 ++ + target/s390x/kvm_s390x.h | 1 + + 14 files changed, 468 insertions(+), 10 deletions(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 5e5e3e52d614d05e7d6e8225e3b7..1dbe9345a022a25b7b40a5b5e9c8 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -385,6 +385,8 @@ F: target/s390x/machine.c + F: target/s390x/sigp.c + F: target/s390x/cpu_features*.[ch] + F: target/s390x/cpu_models.[ch] ++F: hw/s390x/pv.c ++F: include/hw/s390x/pv.h + F: hw/intc/s390_flic.c + F: hw/intc/s390_flic_kvm.c + F: include/hw/s390x/s390_flic.h +diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs +index e02ed80b6829a511362abc3525ec..a46a1c7894e0f612a2d74cec74f6 100644 +--- a/hw/s390x/Makefile.objs ++++ b/hw/s390x/Makefile.objs +@@ -31,6 +31,7 @@ obj-y += tod-qemu.o + obj-$(CONFIG_KVM) += tod-kvm.o + obj-$(CONFIG_KVM) += s390-skeys-kvm.o + obj-$(CONFIG_KVM) += s390-stattrib-kvm.o ++obj-$(CONFIG_KVM) += pv.o + obj-y += s390-ccw.o + obj-y += ap-device.o + obj-y += ap-bridge.o +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index ca544d64c5e04782fb49d12521d5..73e5210b4d4e7ad912cfe5475ac4 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -1,10 +1,11 @@ + /* + * bootloader support + * +- * Copyright IBM, Corp. 2012 ++ * Copyright IBM, Corp. 2012, 2020 + * + * Authors: + * Christian Borntraeger ++ * Janosch Frank + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. +@@ -27,6 +28,7 @@ + #include "hw/s390x/vfio-ccw.h" + #include "hw/s390x/css.h" + #include "hw/s390x/ebcdic.h" ++#include "hw/s390x/pv.h" + #include "ipl.h" + #include "qemu/error-report.h" + #include "qemu/config-file.h" +@@ -533,11 +535,30 @@ void s390_ipl_update_diag308(IplParameterBlock *iplb) + { + S390IPLState *ipl = get_ipl_device(); + +- ipl->iplb = *iplb; +- ipl->iplb_valid = true; ++ /* ++ * The IPLB set and retrieved by subcodes 8/9 is completely ++ * separate from the one managed via subcodes 5/6. ++ */ ++ if (iplb->pbt == S390_IPL_TYPE_PV) { ++ ipl->iplb_pv = *iplb; ++ ipl->iplb_valid_pv = true; ++ } else { ++ ipl->iplb = *iplb; ++ ipl->iplb_valid = true; ++ } + ipl->netboot = is_virtio_net_device(iplb); + } + ++IplParameterBlock *s390_ipl_get_iplb_pv(void) ++{ ++ S390IPLState *ipl = get_ipl_device(); ++ ++ if (!ipl->iplb_valid_pv) { ++ return NULL; ++ } ++ return &ipl->iplb_pv; ++} ++ + IplParameterBlock *s390_ipl_get_iplb(void) + { + S390IPLState *ipl = get_ipl_device(); +@@ -626,6 +647,38 @@ static void s390_ipl_prepare_qipl(S390CPU *cpu) + cpu_physical_memory_unmap(addr, len, 1, len); + } + ++int s390_ipl_prepare_pv_header(void) ++{ ++ IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); ++ IPLBlockPV *ipib_pv = &ipib->pv; ++ void *hdr = g_malloc(ipib_pv->pv_header_len); ++ int rc; ++ ++ cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr, ++ ipib_pv->pv_header_len); ++ rc = s390_pv_set_sec_parms((uint64_t)(uintptr_t)hdr, ++ ipib_pv->pv_header_len); ++ g_free(hdr); ++ return rc; ++} ++ ++int s390_ipl_pv_unpack(void) ++{ ++ IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); ++ IPLBlockPV *ipib_pv = &ipib->pv; ++ int i, rc = 0; ++ ++ for (i = 0; i < ipib_pv->num_comp; i++) { ++ rc = s390_pv_unpack(ipib_pv->components[i].addr, ++ TARGET_PAGE_ALIGN(ipib_pv->components[i].size), ++ ipib_pv->components[i].tweak_pref); ++ if (rc) { ++ break; ++ } ++ } ++ return rc; ++} ++ + void s390_ipl_prepare_cpu(S390CPU *cpu) + { + S390IPLState *ipl = get_ipl_device(); +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index a5665e6bfde2e8cfbb1b2e6c7234..89b3044d7a2ee54014daa8eeafc9 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -1,8 +1,9 @@ + /* + * s390 IPL device + * +- * Copyright 2015 IBM Corp. ++ * Copyright 2015, 2020 IBM Corp. + * Author(s): Zhang Fan ++ * Janosch Frank + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level +@@ -15,6 +16,24 @@ + #include "cpu.h" + #include "hw/qdev-core.h" + ++struct IPLBlockPVComp { ++ uint64_t tweak_pref; ++ uint64_t addr; ++ uint64_t size; ++} QEMU_PACKED; ++typedef struct IPLBlockPVComp IPLBlockPVComp; ++ ++struct IPLBlockPV { ++ uint8_t reserved18[87]; /* 0x18 */ ++ uint8_t version; /* 0x6f */ ++ uint32_t reserved70; /* 0x70 */ ++ uint32_t num_comp; /* 0x74 */ ++ uint64_t pv_header_addr; /* 0x78 */ ++ uint64_t pv_header_len; /* 0x80 */ ++ struct IPLBlockPVComp components[]; ++} QEMU_PACKED; ++typedef struct IPLBlockPV IPLBlockPV; ++ + struct IplBlockCcw { + uint8_t reserved0[85]; + uint8_t ssid; +@@ -71,6 +90,7 @@ union IplParameterBlock { + union { + IplBlockCcw ccw; + IplBlockFcp fcp; ++ IPLBlockPV pv; + IplBlockQemuScsi scsi; + }; + } QEMU_PACKED; +@@ -85,8 +105,11 @@ typedef union IplParameterBlock IplParameterBlock; + + int s390_ipl_set_loadparm(uint8_t *loadparm); + void s390_ipl_update_diag308(IplParameterBlock *iplb); ++int s390_ipl_prepare_pv_header(void); ++int s390_ipl_pv_unpack(void); + void s390_ipl_prepare_cpu(S390CPU *cpu); + IplParameterBlock *s390_ipl_get_iplb(void); ++IplParameterBlock *s390_ipl_get_iplb_pv(void); + + enum s390_reset { + /* default is a reset not triggered by a CPU e.g. issued by QMP */ +@@ -94,6 +117,7 @@ enum s390_reset { + S390_RESET_REIPL, + S390_RESET_MODIFIED_CLEAR, + S390_RESET_LOAD_NORMAL, ++ S390_RESET_PV, + }; + void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type); + void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type); +@@ -133,6 +157,7 @@ struct S390IPLState { + /*< private >*/ + DeviceState parent_obj; + IplParameterBlock iplb; ++ IplParameterBlock iplb_pv; + QemuIplParameters qipl; + uint64_t start_addr; + uint64_t compat_start_addr; +@@ -140,6 +165,7 @@ struct S390IPLState { + uint64_t compat_bios_start_addr; + bool enforce_bios; + bool iplb_valid; ++ bool iplb_valid_pv; + bool netboot; + /* reset related properties don't have to be migrated or reset */ + enum s390_reset reset_type; +@@ -162,6 +188,8 @@ QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + #define DIAG_308_RC_OK 0x0001 + #define DIAG_308_RC_NO_CONF 0x0102 + #define DIAG_308_RC_INVALID 0x0402 ++#define DIAG_308_RC_NO_PV_CONF 0x0902 ++#define DIAG_308_RC_INVAL_FOR_PV 0x0a02 + + #define DIAG308_RESET_MOD_CLR 0 + #define DIAG308_RESET_LOAD_NORM 1 +@@ -169,12 +197,17 @@ QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong"); + #define DIAG308_LOAD_NORMAL_DUMP 4 + #define DIAG308_SET 5 + #define DIAG308_STORE 6 ++#define DIAG308_PV_SET 8 ++#define DIAG308_PV_STORE 9 ++#define DIAG308_PV_START 10 + + #define S390_IPL_TYPE_FCP 0x00 + #define S390_IPL_TYPE_CCW 0x02 ++#define S390_IPL_TYPE_PV 0x05 + #define S390_IPL_TYPE_QEMU_SCSI 0xff + + #define S390_IPLB_HEADER_LEN 8 ++#define S390_IPLB_MIN_PV_LEN 148 + #define S390_IPLB_MIN_CCW_LEN 200 + #define S390_IPLB_MIN_FCP_LEN 384 + #define S390_IPLB_MIN_QEMU_SCSI_LEN 200 +@@ -184,6 +217,62 @@ static inline bool iplb_valid_len(IplParameterBlock *iplb) + return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock); + } + ++static inline bool ipl_valid_pv_components(IplParameterBlock *iplb) ++{ ++ IPLBlockPV *ipib_pv = &iplb->pv; ++ int i; ++ ++ if (ipib_pv->num_comp == 0) { ++ return false; ++ } ++ ++ for (i = 0; i < ipib_pv->num_comp; i++) { ++ /* Addr must be 4k aligned */ ++ if (ipib_pv->components[i].addr & ~TARGET_PAGE_MASK) { ++ return false; ++ } ++ ++ /* Tweak prefix is monotonically increasing with each component */ ++ if (i < ipib_pv->num_comp - 1 && ++ ipib_pv->components[i].tweak_pref >= ++ ipib_pv->components[i + 1].tweak_pref) { ++ return false; ++ } ++ } ++ return true; ++} ++ ++static inline bool ipl_valid_pv_header(IplParameterBlock *iplb) ++{ ++ IPLBlockPV *ipib_pv = &iplb->pv; ++ ++ if (ipib_pv->pv_header_len > 2 * TARGET_PAGE_SIZE) { ++ return false; ++ } ++ ++ if (!address_space_access_valid(&address_space_memory, ++ ipib_pv->pv_header_addr, ++ ipib_pv->pv_header_len, ++ false, ++ MEMTXATTRS_UNSPECIFIED)) { ++ return false; ++ } ++ ++ return true; ++} ++ ++static inline bool iplb_valid_pv(IplParameterBlock *iplb) ++{ ++ if (iplb->pbt != S390_IPL_TYPE_PV || ++ be32_to_cpu(iplb->len) < S390_IPLB_MIN_PV_LEN) { ++ return false; ++ } ++ if (!ipl_valid_pv_header(iplb)) { ++ return false; ++ } ++ return ipl_valid_pv_components(iplb); ++} ++ + static inline bool iplb_valid(IplParameterBlock *iplb) + { + switch (iplb->pbt) { +diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c +new file mode 100644 +index 0000000000000000000000000000000000000000..8cf5cd2c9bcd48b03af1e546fb3a85cdc7ac28bb +--- /dev/null ++++ b/hw/s390x/pv.c +@@ -0,0 +1,98 @@ ++/* ++ * Protected Virtualization functions ++ * ++ * Copyright IBM Corp. 2020 ++ * Author(s): ++ * Janosch Frank ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++#include "qemu/osdep.h" ++ ++#include ++ ++#include "qemu/error-report.h" ++#include "sysemu/kvm.h" ++#include "hw/s390x/pv.h" ++ ++static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data) ++{ ++ struct kvm_pv_cmd pv_cmd = { ++ .cmd = cmd, ++ .data = (uint64_t)data, ++ }; ++ int rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd); ++ ++ if (rc) { ++ error_report("KVM PV command %d (%s) failed: header rc %x rrc %x " ++ "IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc, ++ rc); ++ } ++ return rc; ++} ++ ++/* ++ * This macro lets us pass the command as a string to the function so ++ * we can print it on an error. ++ */ ++#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data); ++#define s390_pv_cmd_exit(cmd, data) \ ++{ \ ++ int rc; \ ++ \ ++ rc = __s390_pv_cmd(cmd, #cmd, data);\ ++ if (rc) { \ ++ exit(1); \ ++ } \ ++} ++ ++int s390_pv_vm_enable(void) ++{ ++ return s390_pv_cmd(KVM_PV_ENABLE, NULL); ++} ++ ++void s390_pv_vm_disable(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_DISABLE, NULL); ++} ++ ++int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) ++{ ++ struct kvm_s390_pv_sec_parm args = { ++ .origin = origin, ++ .length = length, ++ }; ++ ++ return s390_pv_cmd(KVM_PV_VM_SET_SEC_PARMS, &args); ++} ++ ++/* ++ * Called for each component in the SE type IPL parameter block 0. ++ */ ++int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) ++{ ++ struct kvm_s390_pv_unp args = { ++ .addr = addr, ++ .size = size, ++ .tweak = tweak, ++ }; ++ ++ return s390_pv_cmd(KVM_PV_VM_UNPACK, &args); ++} ++ ++void s390_pv_perf_clear_reset(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_VM_PREP_RESET, NULL); ++} ++ ++int s390_pv_verify(void) ++{ ++ return s390_pv_cmd(KVM_PV_VM_VERIFY, NULL); ++} ++ ++void s390_pv_unshare(void) ++{ ++ s390_pv_cmd_exit(KVM_PV_VM_UNSHARE_ALL, NULL); ++} +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index c1d1440272a42eef86eb14724f52..5149030d2216040c396a02d977c8 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -1,9 +1,10 @@ + /* + * virtio ccw machine + * +- * Copyright 2012 IBM Corp. ++ * Copyright 2012, 2020 IBM Corp. + * Copyright (c) 2009 Alexander Graf + * Author(s): Cornelia Huck ++ * Janosch Frank + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level +@@ -41,6 +42,8 @@ + #include "hw/qdev-properties.h" + #include "hw/s390x/tod.h" + #include "sysemu/sysemu.h" ++#include "hw/s390x/pv.h" ++#include + + S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) + { +@@ -318,10 +321,78 @@ static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg) + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); + } + ++static void s390_machine_unprotect(S390CcwMachineState *ms) ++{ ++ s390_pv_vm_disable(); ++ ms->pv = false; ++} ++ ++static int s390_machine_protect(S390CcwMachineState *ms) ++{ ++ int rc; ++ ++ /* Create SE VM */ ++ rc = s390_pv_vm_enable(); ++ if (rc) { ++ return rc; ++ } ++ ++ ms->pv = true; ++ ++ /* Set SE header and unpack */ ++ rc = s390_ipl_prepare_pv_header(); ++ if (rc) { ++ goto out_err; ++ } ++ ++ /* Decrypt image */ ++ rc = s390_ipl_pv_unpack(); ++ if (rc) { ++ goto out_err; ++ } ++ ++ /* Verify integrity */ ++ rc = s390_pv_verify(); ++ if (rc) { ++ goto out_err; ++ } ++ return rc; ++ ++out_err: ++ s390_machine_unprotect(ms); ++ return rc; ++} ++ ++static void s390_machine_inject_pv_error(CPUState *cs) ++{ ++ int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4; ++ CPUS390XState *env = &S390_CPU(cs)->env; ++ ++ /* Report that we are unable to enter protected mode */ ++ env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; ++} ++ ++static void s390_pv_prepare_reset(S390CcwMachineState *ms) ++{ ++ CPUState *cs; ++ ++ if (!s390_is_pv()) { ++ return; ++ } ++ /* Unsharing requires all cpus to be stopped */ ++ CPU_FOREACH(cs) { ++ s390_cpu_set_state(S390_CPU_STATE_STOPPED, S390_CPU(cs)); ++ } ++ s390_pv_unshare(); ++ s390_pv_perf_clear_reset(); ++} ++ + static void s390_machine_reset(MachineState *machine) + { ++ S390CcwMachineState *ms = S390_CCW_MACHINE(machine); + enum s390_reset reset_type; + CPUState *cs, *t; ++ S390CPU *cpu; + + /* get the reset parameters, reset them once done */ + s390_ipl_get_reset_request(&cs, &reset_type); +@@ -329,9 +400,15 @@ static void s390_machine_reset(MachineState *machine) + /* all CPUs are paused and synchronized at this point */ + s390_cmma_reset(); + ++ cpu = S390_CPU(cs); ++ + switch (reset_type) { + case S390_RESET_EXTERNAL: + case S390_RESET_REIPL: ++ if (s390_is_pv()) { ++ s390_machine_unprotect(ms); ++ } ++ + qemu_devices_reset(); + s390_crypto_reset(); + +@@ -339,22 +416,56 @@ static void s390_machine_reset(MachineState *machine) + run_on_cpu(cs, s390_do_cpu_ipl, RUN_ON_CPU_NULL); + break; + case S390_RESET_MODIFIED_CLEAR: ++ /* ++ * Susbsystem reset needs to be done before we unshare memory ++ * and lose access to VIRTIO structures in guest memory. ++ */ ++ subsystem_reset(); ++ s390_crypto_reset(); ++ s390_pv_prepare_reset(ms); + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); + } +- subsystem_reset(); +- s390_crypto_reset(); + run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); + break; + case S390_RESET_LOAD_NORMAL: ++ /* ++ * Susbsystem reset needs to be done before we unshare memory ++ * and lose access to VIRTIO structures in guest memory. ++ */ ++ subsystem_reset(); ++ s390_pv_prepare_reset(ms); + CPU_FOREACH(t) { + if (t == cs) { + continue; + } + run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); + } +- subsystem_reset(); + run_on_cpu(cs, s390_do_cpu_initial_reset, RUN_ON_CPU_NULL); ++ run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); ++ break; ++ case S390_RESET_PV: /* Subcode 10 */ ++ subsystem_reset(); ++ s390_crypto_reset(); ++ ++ CPU_FOREACH(t) { ++ if (t == cs) { ++ continue; ++ } ++ run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); ++ } ++ run_on_cpu(cs, s390_do_cpu_reset, RUN_ON_CPU_NULL); ++ ++ if (s390_machine_protect(ms)) { ++ s390_machine_inject_pv_error(cs); ++ /* ++ * Continue after the diag308 so the guest knows something ++ * went wrong. ++ */ ++ s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); ++ return; ++ } ++ + run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); + break; + default: +diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h +new file mode 100644 +index 0000000000000000000000000000000000000000..c6cb360f2f6a0a32a37970769e1bf2eb0220b199 +--- /dev/null ++++ b/include/hw/s390x/pv.h +@@ -0,0 +1,55 @@ ++/* ++ * Protected Virtualization header ++ * ++ * Copyright IBM Corp. 2020 ++ * Author(s): ++ * Janosch Frank ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++#ifndef HW_S390_PV_H ++#define HW_S390_PV_H ++ ++#ifdef CONFIG_KVM ++#include "hw/s390x/s390-virtio-ccw.h" ++ ++static inline bool s390_is_pv(void) ++{ ++ static S390CcwMachineState *ccw; ++ Object *obj; ++ ++ if (ccw) { ++ return ccw->pv; ++ } ++ ++ /* we have to bail out for the "none" machine */ ++ obj = object_dynamic_cast(qdev_get_machine(), ++ TYPE_S390_CCW_MACHINE); ++ if (!obj) { ++ return false; ++ } ++ ccw = S390_CCW_MACHINE(obj); ++ return ccw->pv; ++} ++ ++int s390_pv_vm_enable(void); ++void s390_pv_vm_disable(void); ++int s390_pv_set_sec_parms(uint64_t origin, uint64_t length); ++int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak); ++void s390_pv_perf_clear_reset(void); ++int s390_pv_verify(void); ++void s390_pv_unshare(void); ++#else /* CONFIG_KVM */ ++static inline bool s390_is_pv(void) { return false; } ++static inline int s390_pv_vm_enable(void) { return 0; } ++static inline void s390_pv_vm_disable(void) {} ++static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; } ++static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; } ++static inline void s390_pv_perf_clear_reset(void) {} ++static inline int s390_pv_verify(void) { return 0; } ++static inline void s390_pv_unshare(void) {} ++#endif /* CONFIG_KVM */ ++ ++#endif /* HW_S390_PV_H */ +diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h +index 8aa27199c9123bab03d3450313a5..cd1dccc6e3ba86455a9de5eb41cb 100644 +--- a/include/hw/s390x/s390-virtio-ccw.h ++++ b/include/hw/s390x/s390-virtio-ccw.h +@@ -28,6 +28,7 @@ typedef struct S390CcwMachineState { + /*< public >*/ + bool aes_key_wrap; + bool dea_key_wrap; ++ bool pv; + uint8_t loadparm[8]; + } S390CcwMachineState; + +diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c +index 52fefa1586caa3cbd366fe230630..479f1978c974722ceeb72ac5fb32 100644 +--- a/target/s390x/cpu.c ++++ b/target/s390x/cpu.c +@@ -37,6 +37,7 @@ + #include "sysemu/hw_accel.h" + #include "hw/qdev-properties.h" + #ifndef CONFIG_USER_ONLY ++#include "hw/s390x/pv.h" + #include "hw/boards.h" + #include "sysemu/arch_init.h" + #include "sysemu/sysemu.h" +diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h +index 31dff0d84e9724513b1945f8d447..60db28351d059091b6e05fd62c37 100644 +--- a/target/s390x/cpu_features_def.inc.h ++++ b/target/s390x/cpu_features_def.inc.h +@@ -107,6 +107,7 @@ DEF_FEAT(DEFLATE_BASE, "deflate-base", STFL, 151, "Deflate-conversion facility ( + DEF_FEAT(VECTOR_PACKED_DECIMAL_ENH, "vxpdeh", STFL, 152, "Vector-Packed-Decimal-Enhancement Facility") + DEF_FEAT(MSA_EXT_9, "msa9-base", STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)") + DEF_FEAT(ETOKEN, "etoken", STFL, 156, "Etoken facility") ++DEF_FEAT(UNPACK, "unpack", STFL, 161, "Unpack facility") + + /* Features exposed via SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ + DEF_FEAT(SIE_GSLS, "gsls", SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility") +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 8aba6341f94848e1ce8fff420ed8..b2cbefb8cfe4e5a244219e761fb4 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -20,6 +20,8 @@ + #include "sysemu/cpus.h" + #include "hw/s390x/ipl.h" + #include "hw/s390x/s390-virtio-ccw.h" ++#include "hw/s390x/pv.h" ++#include "kvm_s390x.h" + + int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + { +@@ -52,6 +54,10 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + uintptr_t ra, bool write) + { ++ /* Handled by the Ultravisor */ ++ if (s390_is_pv()) { ++ return 0; ++ } + if ((r1 & 1) || (addr & ~TARGET_PAGE_MASK)) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return -1; +@@ -67,6 +73,7 @@ static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, + + void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { ++ bool valid; + CPUState *cs = env_cpu(env); + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; +@@ -82,6 +89,11 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + return; + } + ++ if (subcode >= DIAG308_PV_SET && !s390_has_feat(S390_FEAT_UNPACK)) { ++ s390_program_interrupt(env, PGM_SPECIFICATION, ra); ++ return; ++ } ++ + switch (subcode) { + case DIAG308_RESET_MOD_CLR: + s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); +@@ -94,6 +106,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + s390_ipl_reset_request(cs, S390_RESET_REIPL); + break; + case DIAG308_SET: ++ case DIAG308_PV_SET: + if (diag308_parm_check(env, r1, addr, ra, false)) { + return; + } +@@ -106,7 +119,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + + cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); + +- if (!iplb_valid(iplb)) { ++ valid = subcode == DIAG308_PV_SET ? iplb_valid_pv(iplb) : iplb_valid(iplb); ++ if (!valid) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } +@@ -117,10 +131,15 @@ out: + g_free(iplb); + return; + case DIAG308_STORE: ++ case DIAG308_PV_STORE: + if (diag308_parm_check(env, r1, addr, ra, true)) { + return; + } +- iplb = s390_ipl_get_iplb(); ++ if (subcode == DIAG308_PV_STORE) { ++ iplb = s390_ipl_get_iplb_pv(); ++ } else { ++ iplb = s390_ipl_get_iplb(); ++ } + if (iplb) { + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); + env->regs[r1 + 1] = DIAG_308_RC_OK; +@@ -128,6 +147,22 @@ out: + env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; + } + return; ++ case DIAG308_PV_START: ++ iplb = s390_ipl_get_iplb_pv(); ++ if (!iplb) { ++ env->regs[r1 + 1] = DIAG_308_RC_NO_PV_CONF; ++ return; ++ } ++ ++ if (kvm_s390_get_hpage_1m()) { ++ error_report("Protected VMs can currently not be backed with " ++ "huge pages"); ++ env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; ++ return; ++ } ++ ++ s390_ipl_reset_request(cs, S390_RESET_PV); ++ break; + default: + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + break; +diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c +index c4cd497f850eb9c7a859932b0f1f..aa185017a2a886ca300fa75747ed 100644 +--- a/target/s390x/kvm-stub.c ++++ b/target/s390x/kvm-stub.c +@@ -39,6 +39,11 @@ int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu) + return 0; + } + ++int kvm_s390_get_hpage_1m(void) ++{ ++ return 0; ++} ++ + int kvm_s390_get_ri(void) + { + return 0; +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index f633472980b48757989db245fb1f..d8d02ff34f4fc942cb7935deec58 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -321,6 +321,11 @@ void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp) + cap_hpage_1m = 1; + } + ++int kvm_s390_get_hpage_1m(void) ++{ ++ return cap_hpage_1m; ++} ++ + static void ccw_machine_class_foreach(ObjectClass *oc, void *opaque) + { + MachineClass *mc = MACHINE_CLASS(oc); +diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h +index 0b21789796d7c462bdc72160166f..dea813f450153c34e1269424772d 100644 +--- a/target/s390x/kvm_s390x.h ++++ b/target/s390x/kvm_s390x.h +@@ -23,6 +23,7 @@ void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); + int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); + void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); + int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); ++int kvm_s390_get_hpage_1m(void); + int kvm_s390_get_ri(void); + int kvm_s390_get_gs(void); + int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); diff --git a/target-ppc-Fix-rlwinm-on-ppc64.patch b/target-ppc-Fix-rlwinm-on-ppc64.patch new file mode 100644 index 00000000..a0f24a43 --- /dev/null +++ b/target-ppc-Fix-rlwinm-on-ppc64.patch @@ -0,0 +1,59 @@ +From: Vitaly Chikunov +Date: Mon, 9 Mar 2020 23:45:57 +0300 +Subject: target/ppc: Fix rlwinm on ppc64 + +Git-commit: 94f040aaecf4e41cc68991b80204b1b6886bbdd0 + +rlwinm cannot just AND with Mask if shift value is zero on ppc64 when +Mask Begin is greater than Mask End and high bits are set to 1. + +Note that PowerISA 3.0B says that for `rlwinm' ROTL32 is used, and +ROTL32 is defined (in 3.3.14) so that rotated value should have two +copies of lower word of the source value. + +This seems to be another incarnation of the fix from 820724d170 +("target-ppc: Fix rlwimi, rlwinm, rlwnm again"), except I leave +optimization when Mask value is less than 32 bits. + +Fixes: 7b4d326f47 ("target-ppc: Use the new deposit and extract ops") +Cc: qemu-stable@nongnu.org +Signed-off-by: Vitaly Chikunov +Message-Id: <20200309204557.14836-1-vt@altlinux.org> +Reviewed-by: Richard Henderson +Signed-off-by: David Gibson +Signed-off-by: Bruce Rogers +--- + target/ppc/translate.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/target/ppc/translate.c b/target/ppc/translate.c +index f5fe5d06118a7c86d11f38767fab..f87f6eeaf7d988896c61b025320a 100644 +--- a/target/ppc/translate.c ++++ b/target/ppc/translate.c +@@ -1938,15 +1938,17 @@ static void gen_rlwinm(DisasContext *ctx) + me += 32; + #endif + mask = MASK(mb, me); +- if (sh == 0) { +- tcg_gen_andi_tl(t_ra, t_rs, mask); +- } else if (mask <= 0xffffffffu) { +- TCGv_i32 t0 = tcg_temp_new_i32(); +- tcg_gen_trunc_tl_i32(t0, t_rs); +- tcg_gen_rotli_i32(t0, t0, sh); +- tcg_gen_andi_i32(t0, t0, mask); +- tcg_gen_extu_i32_tl(t_ra, t0); +- tcg_temp_free_i32(t0); ++ if (mask <= 0xffffffffu) { ++ if (sh == 0) { ++ tcg_gen_andi_tl(t_ra, t_rs, mask); ++ } else { ++ TCGv_i32 t0 = tcg_temp_new_i32(); ++ tcg_gen_trunc_tl_i32(t0, t_rs); ++ tcg_gen_rotli_i32(t0, t0, sh); ++ tcg_gen_andi_i32(t0, t0, mask); ++ tcg_gen_extu_i32_tl(t_ra, t0); ++ tcg_temp_free_i32(t0); ++ } + } else { + #if defined(TARGET_PPC64) + tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32); diff --git a/vhost-correctly-turn-on-VIRTIO_F_IOMMU_P.patch b/vhost-correctly-turn-on-VIRTIO_F_IOMMU_P.patch new file mode 100644 index 00000000..d4a810c0 --- /dev/null +++ b/vhost-correctly-turn-on-VIRTIO_F_IOMMU_P.patch @@ -0,0 +1,56 @@ +From: Jason Wang +Date: Mon, 2 Mar 2020 12:24:54 +0800 +Subject: vhost: correctly turn on VIRTIO_F_IOMMU_PLATFORM + +References: bsc#1167075 + +We turn on device IOTLB via VIRTIO_F_IOMMU_PLATFORM unconditionally on +platform without IOMMU support. This can lead unnecessary IOTLB +transactions which will damage the performance. + +Fixing this by check whether the device is backed by IOMMU and disable +device IOTLB. + +Reported-by: Halil Pasic +Tested-by: Halil Pasic +Reviewed-by: Halil Pasic +Signed-off-by: Jason Wang +Message-Id: <20200302042454.24814-1-jasowang@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit f7ef7e6e3ba6e994e070cc609eb154339d1c4a11) +Signed-off-by: Bruce Rogers +--- + hw/virtio/vhost.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 4da0d5a6c5867325cb8cacab4894..554e76434ffaf2dc9ada0d4bdd7a 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -290,7 +290,14 @@ static int vhost_dev_has_iommu(struct vhost_dev *dev) + { + VirtIODevice *vdev = dev->vdev; + +- return virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); ++ /* ++ * For vhost, VIRTIO_F_IOMMU_PLATFORM means the backend support ++ * incremental memory mapping API via IOTLB API. For platform that ++ * does not have IOMMU, there's no need to enable this feature ++ * which may cause unnecessary IOTLB miss/update trnasactions. ++ */ ++ return vdev->dma_as != &address_space_memory && ++ virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + } + + static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, +@@ -762,6 +769,9 @@ static int vhost_dev_set_features(struct vhost_dev *dev, + if (enable_log) { + features |= 0x1ULL << VHOST_F_LOG_ALL; + } ++ if (!vhost_dev_has_iommu(dev)) { ++ features &= ~(0x1ULL << VIRTIO_F_IOMMU_PLATFORM); ++ } + r = dev->vhost_ops->vhost_set_features(dev, features); + if (r < 0) { + VHOST_OPS_DEBUG("vhost_set_features failed");