From 6596cad46a372d42b5d2de239ba91b689f04ea4e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 29 Feb 2016 21:07:33 -0800 Subject: [PATCH] 4.4-stable patches added patches: arm-debug-ll-fix-bcm63xx-entry-for-multiplatform.patch arm64-errata-add-mpc-relative-literal-loads-to-build-flags.patch ext4-fix-bh-b_state-corruption.patch kvm-s390-fix-guest-fprs-memory-leak.patch kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch --- ...-fix-bcm63xx-entry-for-multiplatform.patch | 100 +++++++ ...elative-literal-loads-to-build-flags.patch | 42 +++ .../ext4-fix-bh-b_state-corruption.patch | 92 ++++++ .../kvm-s390-fix-guest-fprs-memory-leak.patch | 49 ++++ ...emory-overwrites-when-vx-is-disabled.patch | 276 ++++++++++++++++++ queue-4.4/series | 5 + 6 files changed, 564 insertions(+) create mode 100644 queue-4.4/arm-debug-ll-fix-bcm63xx-entry-for-multiplatform.patch create mode 100644 queue-4.4/arm64-errata-add-mpc-relative-literal-loads-to-build-flags.patch create mode 100644 queue-4.4/ext4-fix-bh-b_state-corruption.patch create mode 100644 queue-4.4/kvm-s390-fix-guest-fprs-memory-leak.patch create mode 100644 queue-4.4/kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch diff --git a/queue-4.4/arm-debug-ll-fix-bcm63xx-entry-for-multiplatform.patch b/queue-4.4/arm-debug-ll-fix-bcm63xx-entry-for-multiplatform.patch new file mode 100644 index 00000000000..8ed5a7befa6 --- /dev/null +++ b/queue-4.4/arm-debug-ll-fix-bcm63xx-entry-for-multiplatform.patch @@ -0,0 +1,100 @@ +From 6c54809977de3c9e2ef9e9934a2c6625f7e161e7 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Mon, 18 Jan 2016 10:45:00 +0100 +Subject: ARM: debug-ll: fix BCM63xx entry for multiplatform + +From: Arnd Bergmann + +commit 6c54809977de3c9e2ef9e9934a2c6625f7e161e7 upstream. + +During my randconfig build testing, I found that a kernel with +DEBUG_AT91_UART and ARCH_BCM_63XX fails to build: + +arch/arm/include/debug/at91.S:18:0: error: "CONFIG_DEBUG_UART_VIRT" redefined [-Werror] + +It turns out that the DEBUG_UART_BCM63XX option is enabled whenever +the ARCH_BCM_63XX is, and that breaks multiplatform kernels because +we then end up using the UART address from BCM63XX rather than the +one we actually configured (if any). + +This changes the BCM63XX options to only have one Kconfig option, +and only enable that if the user explicitly turns it on. + +Signed-off-by: Arnd Bergmann +Fixes: b51312bebfa4 ("ARM: BCM63XX: add low-level UART debug support") +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/Kconfig.debug | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +--- a/arch/arm/Kconfig.debug ++++ b/arch/arm/Kconfig.debug +@@ -162,10 +162,9 @@ choice + mobile SoCs in the Kona family of chips (e.g. bcm28155, + bcm11351, etc...) + +- config DEBUG_BCM63XX ++ config DEBUG_BCM63XX_UART + bool "Kernel low-level debugging on BCM63XX UART" + depends on ARCH_BCM_63XX +- select DEBUG_UART_BCM63XX + + config DEBUG_BERLIN_UART + bool "Marvell Berlin SoC Debug UART" +@@ -1348,7 +1347,7 @@ config DEBUG_LL_INCLUDE + default "debug/vf.S" if DEBUG_VF_UART + default "debug/vt8500.S" if DEBUG_VT8500_UART0 + default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1 +- default "debug/bcm63xx.S" if DEBUG_UART_BCM63XX ++ default "debug/bcm63xx.S" if DEBUG_BCM63XX_UART + default "debug/digicolor.S" if DEBUG_DIGICOLOR_UA0 + default "mach/debug-macro.S" + +@@ -1364,10 +1363,6 @@ config DEBUG_UART_8250 + ARCH_IOP33X || ARCH_IXP4XX || \ + ARCH_LPC32XX || ARCH_MV78XX0 || ARCH_ORION5X || ARCH_RPC + +-# Compatibility options for BCM63xx +-config DEBUG_UART_BCM63XX +- def_bool ARCH_BCM_63XX +- + config DEBUG_UART_PHYS + hex "Physical base address of debug UART" + default 0x00100a00 if DEBUG_NETX_UART +@@ -1462,7 +1457,7 @@ config DEBUG_UART_PHYS + default 0xfffb0000 if DEBUG_OMAP1UART1 || DEBUG_OMAP7XXUART1 + default 0xfffb0800 if DEBUG_OMAP1UART2 || DEBUG_OMAP7XXUART2 + default 0xfffb9800 if DEBUG_OMAP1UART3 || DEBUG_OMAP7XXUART3 +- default 0xfffe8600 if DEBUG_UART_BCM63XX ++ default 0xfffe8600 if DEBUG_BCM63XX_UART + default 0xfffff700 if ARCH_IOP33X + depends on ARCH_EP93XX || \ + DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \ +@@ -1474,7 +1469,7 @@ config DEBUG_UART_PHYS + DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \ + DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \ + DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \ +- DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \ ++ DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \ + DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \ + DEBUG_AT91_UART + +@@ -1515,7 +1510,7 @@ config DEBUG_UART_VIRT + default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT + default 0xfc40ab00 if DEBUG_BRCMSTB_UART + default 0xfc705000 if DEBUG_ZTE_ZX +- default 0xfcfe8600 if DEBUG_UART_BCM63XX ++ default 0xfcfe8600 if DEBUG_BCM63XX_UART + default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX + default 0xfd000000 if ARCH_SPEAR13XX + default 0xfd012000 if ARCH_MV78XX0 +@@ -1566,7 +1561,7 @@ config DEBUG_UART_VIRT + DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \ + DEBUG_NETX_UART || \ + DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \ +- DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \ ++ DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \ + DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 + + config DEBUG_UART_8250_SHIFT diff --git a/queue-4.4/arm64-errata-add-mpc-relative-literal-loads-to-build-flags.patch b/queue-4.4/arm64-errata-add-mpc-relative-literal-loads-to-build-flags.patch new file mode 100644 index 00000000000..c888d205f33 --- /dev/null +++ b/queue-4.4/arm64-errata-add-mpc-relative-literal-loads-to-build-flags.patch @@ -0,0 +1,42 @@ +From 67dfa1751ce71e629aad7c438e1678ad41054677 Mon Sep 17 00:00:00 2001 +From: dann frazier +Date: Mon, 25 Jan 2016 16:52:16 -0700 +Subject: arm64: errata: Add -mpc-relative-literal-loads to build flags + +From: dann frazier + +commit 67dfa1751ce71e629aad7c438e1678ad41054677 upstream. + +GCC6 (and Linaro's 2015.12 snapshot of GCC5) has a new default that uses +adrp/ldr or adrp/add to address literal pools. When CONFIG_ARM64_ERRATUM_843419 +is enabled, modules built with this toolchain fail to load: + + module libahci: unsupported RELA relocation: 275 + +This patch fixes the problem by passing '-mpc-relative-literal-loads' +to the compiler. + +Cc: stable@vger.kernel.org +Fixes: df057cc7b4fa ("arm64: errata: add module build workaround for erratum #843419") +BugLink: http://bugs.launchpad.net/bugs/1533009 +Acked-by: Ard Biesheuvel +Suggested-by: Christophe Lyon +Signed-off-by: Dann Frazier +[will: backport to 4.4-stable] +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm64/Makefile | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/Makefile ++++ b/arch/arm64/Makefile +@@ -27,6 +27,7 @@ $(warning LSE atomics not supported by b + endif + + KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) ++KBUILD_CFLAGS += $(call cc-option, -mpc-relative-literal-loads) + KBUILD_AFLAGS += $(lseinstr) + + ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) diff --git a/queue-4.4/ext4-fix-bh-b_state-corruption.patch b/queue-4.4/ext4-fix-bh-b_state-corruption.patch new file mode 100644 index 00000000000..0ec1826f634 --- /dev/null +++ b/queue-4.4/ext4-fix-bh-b_state-corruption.patch @@ -0,0 +1,92 @@ +From ed8ad83808f009ade97ebbf6519bc3a97fefbc0c Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 19 Feb 2016 00:18:25 -0500 +Subject: ext4: fix bh->b_state corruption + +From: Jan Kara + +commit ed8ad83808f009ade97ebbf6519bc3a97fefbc0c upstream. + +ext4 can update bh->b_state non-atomically in _ext4_get_block() and +ext4_da_get_block_prep(). Usually this is fine since bh is just a +temporary storage for mapping information on stack but in some cases it +can be fully living bh attached to a page. In such case non-atomic +update of bh->b_state can race with an atomic update which then gets +lost. Usually when we are mapping bh and thus updating bh->b_state +non-atomically, nobody else touches the bh and so things work out fine +but there is one case to especially worry about: ext4_finish_bio() uses +BH_Uptodate_Lock on the first bh in the page to synchronize handling of +PageWriteback state. So when blocksize < pagesize, we can be atomically +modifying bh->b_state of a buffer that actually isn't under IO and thus +can race e.g. with delalloc trying to map that buffer. The result is +that we can mistakenly set / clear BH_Uptodate_Lock bit resulting in the +corruption of PageWriteback state or missed unlock of BH_Uptodate_Lock. + +Fix the problem by always updating bh->b_state bits atomically. + +Reported-by: Nikolay Borisov +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +Signed-off-by: Nikolay Borisov +[NB: Backported to 4.4.2] +Acked-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inode.c | 32 ++++++++++++++++++++++++++++++-- + 1 file changed, 30 insertions(+), 2 deletions(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -657,6 +657,34 @@ has_zeroout: + return retval; + } + ++/* ++ * Update EXT4_MAP_FLAGS in bh->b_state. For buffer heads attached to pages ++ * we have to be careful as someone else may be manipulating b_state as well. ++ */ ++static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags) ++{ ++ unsigned long old_state; ++ unsigned long new_state; ++ ++ flags &= EXT4_MAP_FLAGS; ++ ++ /* Dummy buffer_head? Set non-atomically. */ ++ if (!bh->b_page) { ++ bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | flags; ++ return; ++ } ++ /* ++ * Someone else may be modifying b_state. Be careful! This is ugly but ++ * once we get rid of using bh as a container for mapping information ++ * to pass to / from get_block functions, this can go away. ++ */ ++ do { ++ old_state = READ_ONCE(bh->b_state); ++ new_state = (old_state & ~EXT4_MAP_FLAGS) | flags; ++ } while (unlikely( ++ cmpxchg(&bh->b_state, old_state, new_state) != old_state)); ++} ++ + /* Maximum number of blocks we map for direct IO at once. */ + #define DIO_MAX_BLOCKS 4096 + +@@ -693,7 +721,7 @@ static int _ext4_get_block(struct inode + ext4_io_end_t *io_end = ext4_inode_aio(inode); + + map_bh(bh, inode->i_sb, map.m_pblk); +- bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; ++ ext4_update_bh_state(bh, map.m_flags); + if (IS_DAX(inode) && buffer_unwritten(bh)) { + /* + * dgc: I suspect unwritten conversion on ext4+DAX is +@@ -1669,7 +1697,7 @@ int ext4_da_get_block_prep(struct inode + return ret; + + map_bh(bh, inode->i_sb, map.m_pblk); +- bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags; ++ ext4_update_bh_state(bh, map.m_flags); + + if (buffer_unwritten(bh)) { + /* A delayed write to unwritten bh should be marked diff --git a/queue-4.4/kvm-s390-fix-guest-fprs-memory-leak.patch b/queue-4.4/kvm-s390-fix-guest-fprs-memory-leak.patch new file mode 100644 index 00000000000..d7b3c6f43a7 --- /dev/null +++ b/queue-4.4/kvm-s390-fix-guest-fprs-memory-leak.patch @@ -0,0 +1,49 @@ +From 9c7ebb613bffea2feef4ec562ba1dbcaa810942b Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Fri, 22 Jan 2016 14:55:56 +0100 +Subject: KVM: s390: fix guest fprs memory leak + +From: David Hildenbrand + +commit 9c7ebb613bffea2feef4ec562ba1dbcaa810942b upstream. + +fprs is never freed, therefore resulting in a memory leak if +kvm_vcpu_init() fails or the vcpu is destroyed. + +Fixes: 9977e886cbbc ("s390/kernel: lazy restore fpu registers") +Reported-by: Eric Farman +Signed-off-by: David Hildenbrand +Reviewed-by: Eric Farman +Signed-off-by: Christian Borntraeger +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kvm/kvm-s390.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -1202,6 +1202,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vc + + if (vcpu->kvm->arch.use_cmma) + kvm_s390_vcpu_unsetup_cmma(vcpu); ++ kfree(vcpu->arch.guest_fpregs.fprs); + free_page((unsigned long)(vcpu->arch.sie_block)); + + kvm_vcpu_uninit(vcpu); +@@ -1516,12 +1517,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st + + rc = kvm_vcpu_init(vcpu, kvm, id); + if (rc) +- goto out_free_sie_block; ++ goto out_free_fprs; + VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu, + vcpu->arch.sie_block); + trace_kvm_s390_create_vcpu(id, vcpu, vcpu->arch.sie_block); + + return vcpu; ++out_free_fprs: ++ kfree(vcpu->arch.guest_fpregs.fprs); + out_free_sie_block: + free_page((unsigned long)(vcpu->arch.sie_block)); + out_free_cpu: diff --git a/queue-4.4/kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch b/queue-4.4/kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch new file mode 100644 index 00000000000..d8361205e18 --- /dev/null +++ b/queue-4.4/kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch @@ -0,0 +1,276 @@ +From 9abc2a08a7d665b02bdde974fd6c44aae86e923e Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Thu, 14 Jan 2016 22:12:47 +0100 +Subject: KVM: s390: fix memory overwrites when vx is disabled + +From: David Hildenbrand + +commit 9abc2a08a7d665b02bdde974fd6c44aae86e923e upstream. + +The kernel now always uses vector registers when available, however KVM +has special logic if support is really enabled for a guest. If support +is disabled, guest_fpregs.fregs will only contain memory for the fpu. +The kernel, however, will store vector registers into that area, +resulting in crazy memory overwrites. + +Simply extending that area is not enough, because the format of the +registers also changes. We would have to do additional conversions, making +the code even more complex. Therefore let's directly use one place for +the vector/fpu registers + fpc (in kvm_run). We just have to convert the +data properly when accessing it. This makes current code much easier. + +Please note that vector/fpu registers are now always stored to +vcpu->run->s.regs.vrs. Although this data is visible to QEMU and +used for migration, we only guarantee valid values to user space when +KVM_SYNC_VRS is set. As that is only the case when we have vector +register support, we are on the safe side. + +Fixes: b5510d9b68c3 ("s390/fpu: always enable the vector facility if it is available") +Signed-off-by: David Hildenbrand +Signed-off-by: Christian Borntraeger +[adopt to d9a3a09af54d] +Signed-off-by: Greg Kroah-Hartman + + +diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h +index efaac2c..e9a983f 100644 +--- a/arch/s390/include/asm/kvm_host.h ++++ b/arch/s390/include/asm/kvm_host.h +@@ -506,7 +506,6 @@ struct kvm_vcpu_arch { + struct kvm_s390_sie_block *sie_block; + unsigned int host_acrs[NUM_ACRS]; + struct fpu host_fpregs; +- struct fpu guest_fpregs; + struct kvm_s390_local_interrupt local_int; + struct hrtimer ckc_timer; + struct kvm_s390_pgm_info pgm; +diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c +index db7cca5..a08d0af 100644 +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -1202,7 +1202,6 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) + + if (vcpu->kvm->arch.use_cmma) + kvm_s390_vcpu_unsetup_cmma(vcpu); +- kfree(vcpu->arch.guest_fpregs.fprs); + free_page((unsigned long)(vcpu->arch.sie_block)); + + kvm_vcpu_uninit(vcpu); +@@ -1269,44 +1268,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) + return 0; + } + +-/* +- * Backs up the current FP/VX register save area on a particular +- * destination. Used to switch between different register save +- * areas. +- */ +-static inline void save_fpu_to(struct fpu *dst) +-{ +- dst->fpc = current->thread.fpu.fpc; +- dst->regs = current->thread.fpu.regs; +-} +- +-/* +- * Switches the FP/VX register save area from which to lazy +- * restore register contents. +- */ +-static inline void load_fpu_from(struct fpu *from) +-{ +- current->thread.fpu.fpc = from->fpc; +- current->thread.fpu.regs = from->regs; +-} +- + void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) + { + /* Save host register state */ + save_fpu_regs(); +- save_fpu_to(&vcpu->arch.host_fpregs); +- +- if (test_kvm_facility(vcpu->kvm, 129)) { +- current->thread.fpu.fpc = vcpu->run->s.regs.fpc; +- /* +- * Use the register save area in the SIE-control block +- * for register restore and save in kvm_arch_vcpu_put() +- */ +- current->thread.fpu.vxrs = +- (__vector128 *)&vcpu->run->s.regs.vrs; +- } else +- load_fpu_from(&vcpu->arch.guest_fpregs); ++ vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc; ++ vcpu->arch.host_fpregs.regs = current->thread.fpu.regs; + ++ /* Depending on MACHINE_HAS_VX, data stored to vrs either ++ * has vector register or floating point register format. ++ */ ++ current->thread.fpu.regs = vcpu->run->s.regs.vrs; ++ current->thread.fpu.fpc = vcpu->run->s.regs.fpc; + if (test_fp_ctl(current->thread.fpu.fpc)) + /* User space provided an invalid FPC, let's clear it */ + current->thread.fpu.fpc = 0; +@@ -1322,19 +1295,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) + atomic_andnot(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); + gmap_disable(vcpu->arch.gmap); + ++ /* Save guest register state */ + save_fpu_regs(); ++ vcpu->run->s.regs.fpc = current->thread.fpu.fpc; + +- if (test_kvm_facility(vcpu->kvm, 129)) +- /* +- * kvm_arch_vcpu_load() set up the register save area to +- * the &vcpu->run->s.regs.vrs and, thus, the vector registers +- * are already saved. Only the floating-point control must be +- * copied. +- */ +- vcpu->run->s.regs.fpc = current->thread.fpu.fpc; +- else +- save_fpu_to(&vcpu->arch.guest_fpregs); +- load_fpu_from(&vcpu->arch.host_fpregs); ++ /* Restore host register state */ ++ current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc; ++ current->thread.fpu.regs = vcpu->arch.host_fpregs.regs; + + save_access_regs(vcpu->run->s.regs.acrs); + restore_access_regs(vcpu->arch.host_acrs); +@@ -1352,8 +1319,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) + memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64)); + vcpu->arch.sie_block->gcr[0] = 0xE0UL; + vcpu->arch.sie_block->gcr[14] = 0xC2000000UL; +- vcpu->arch.guest_fpregs.fpc = 0; +- asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc)); ++ /* make sure the new fpc will be lazily loaded */ ++ save_fpu_regs(); ++ current->thread.fpu.fpc = 0; + vcpu->arch.sie_block->gbea = 1; + vcpu->arch.sie_block->pp = 0; + vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID; +@@ -1502,29 +1470,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, + vcpu->arch.local_int.wq = &vcpu->wq; + vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags; + +- /* +- * Allocate a save area for floating-point registers. If the vector +- * extension is available, register contents are saved in the SIE +- * control block. The allocated save area is still required in +- * particular places, for example, in kvm_s390_vcpu_store_status(). +- */ +- vcpu->arch.guest_fpregs.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS, +- GFP_KERNEL); +- if (!vcpu->arch.guest_fpregs.fprs) { +- rc = -ENOMEM; +- goto out_free_sie_block; +- } +- + rc = kvm_vcpu_init(vcpu, kvm, id); + if (rc) +- goto out_free_fprs; ++ goto out_free_sie_block; + VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu, + vcpu->arch.sie_block); + trace_kvm_s390_create_vcpu(id, vcpu, vcpu->arch.sie_block); + + return vcpu; +-out_free_fprs: +- kfree(vcpu->arch.guest_fpregs.fprs); + out_free_sie_block: + free_page((unsigned long)(vcpu->arch.sie_block)); + out_free_cpu: +@@ -1737,19 +1690,27 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, + + int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) + { ++ /* make sure the new values will be lazily loaded */ ++ save_fpu_regs(); + if (test_fp_ctl(fpu->fpc)) + return -EINVAL; +- memcpy(vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs)); +- vcpu->arch.guest_fpregs.fpc = fpu->fpc; +- save_fpu_regs(); +- load_fpu_from(&vcpu->arch.guest_fpregs); ++ current->thread.fpu.fpc = fpu->fpc; ++ if (MACHINE_HAS_VX) ++ convert_fp_to_vx(current->thread.fpu.vxrs, (freg_t *)fpu->fprs); ++ else ++ memcpy(current->thread.fpu.fprs, &fpu->fprs, sizeof(fpu->fprs)); + return 0; + } + + int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) + { +- memcpy(&fpu->fprs, vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs)); +- fpu->fpc = vcpu->arch.guest_fpregs.fpc; ++ /* make sure we have the latest values */ ++ save_fpu_regs(); ++ if (MACHINE_HAS_VX) ++ convert_vx_to_fp((freg_t *)fpu->fprs, current->thread.fpu.vxrs); ++ else ++ memcpy(fpu->fprs, current->thread.fpu.fprs, sizeof(fpu->fprs)); ++ fpu->fpc = current->thread.fpu.fpc; + return 0; + } + +@@ -2269,6 +2230,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) + int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa) + { + unsigned char archmode = 1; ++ freg_t fprs[NUM_FPRS]; + unsigned int px; + u64 clkcomp; + int rc; +@@ -2284,8 +2246,16 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa) + gpa = px; + } else + gpa -= __LC_FPREGS_SAVE_AREA; +- rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA, +- vcpu->arch.guest_fpregs.fprs, 128); ++ ++ /* manually convert vector registers if necessary */ ++ if (MACHINE_HAS_VX) { ++ convert_vx_to_fp(fprs, current->thread.fpu.vxrs); ++ rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA, ++ fprs, 128); ++ } else { ++ rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA, ++ vcpu->run->s.regs.vrs, 128); ++ } + rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA, + vcpu->run->s.regs.gprs, 128); + rc |= write_guest_abs(vcpu, gpa + __LC_PSW_SAVE_AREA, +@@ -2293,7 +2263,7 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa) + rc |= write_guest_abs(vcpu, gpa + __LC_PREFIX_SAVE_AREA, + &px, 4); + rc |= write_guest_abs(vcpu, gpa + __LC_FP_CREG_SAVE_AREA, +- &vcpu->arch.guest_fpregs.fpc, 4); ++ &vcpu->run->s.regs.fpc, 4); + rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA, + &vcpu->arch.sie_block->todpr, 4); + rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA, +@@ -2316,19 +2286,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) + * it into the save area + */ + save_fpu_regs(); +- if (test_kvm_facility(vcpu->kvm, 129)) { +- /* +- * If the vector extension is available, the vector registers +- * which overlaps with floating-point registers are saved in +- * the SIE-control block. Hence, extract the floating-point +- * registers and the FPC value and store them in the +- * guest_fpregs structure. +- */ +- vcpu->arch.guest_fpregs.fpc = current->thread.fpu.fpc; +- convert_vx_to_fp(vcpu->arch.guest_fpregs.fprs, +- current->thread.fpu.vxrs); +- } else +- save_fpu_to(&vcpu->arch.guest_fpregs); ++ vcpu->run->s.regs.fpc = current->thread.fpu.fpc; + save_access_regs(vcpu->run->s.regs.acrs); + + return kvm_s390_store_status_unloaded(vcpu, addr); +-- +2.3.9 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/queue-4.4/series b/queue-4.4/series index 8cd67313565..4fc18474a68 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -45,3 +45,8 @@ rtnl-rtm_getnetconf-fix-wrong-return-value.patch tipc-unlock-in-error-path.patch unix_diag-fix-incorrect-sign-extension-in-unix_lookup_by_ino.patch sctp-fix-port-hash-table-size-computation.patch +ext4-fix-bh-b_state-corruption.patch +arm-debug-ll-fix-bcm63xx-entry-for-multiplatform.patch +arm64-errata-add-mpc-relative-literal-loads-to-build-flags.patch +kvm-s390-fix-guest-fprs-memory-leak.patch +kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch -- 2.47.3