From 2e68d87a056b02ae570e2b583f2ba4fd34a5db88 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 8 Jun 2021 18:03:43 +0200 Subject: [PATCH] 4.19-stable patches added patches: btrfs-fix-unmountable-seed-device-after-fstrim.patch kvm-arm64-fix-debug-register-indexing.patch kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch --- ...unmountable-seed-device-after-fstrim.patch | 111 ++++++++++ ...vm-arm64-fix-debug-register-indexing.patch | 208 ++++++++++++++++++ ...or-dr-and-cr-accesses-in-64-bit-mode.patch | 66 ++++++ queue-4.19/series | 3 + 4 files changed, 388 insertions(+) create mode 100644 queue-4.19/btrfs-fix-unmountable-seed-device-after-fstrim.patch create mode 100644 queue-4.19/kvm-arm64-fix-debug-register-indexing.patch create mode 100644 queue-4.19/kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch diff --git a/queue-4.19/btrfs-fix-unmountable-seed-device-after-fstrim.patch b/queue-4.19/btrfs-fix-unmountable-seed-device-after-fstrim.patch new file mode 100644 index 00000000000..4dd620ec069 --- /dev/null +++ b/queue-4.19/btrfs-fix-unmountable-seed-device-after-fstrim.patch @@ -0,0 +1,111 @@ +From foo@baz Tue Jun 8 05:36:16 PM CEST 2021 +From: Anand Jain +Date: Fri, 30 Apr 2021 19:59:51 +0800 +Subject: btrfs: fix unmountable seed device after fstrim + +From: Anand Jain + +commit 5e753a817b2d5991dfe8a801b7b1e8e79a1c5a20 upstream. + +The following test case reproduces an issue of wrongly freeing in-use +blocks on the readonly seed device when fstrim is called on the rw sprout +device. As shown below. + +Create a seed device and add a sprout device to it: + + $ mkfs.btrfs -fq -dsingle -msingle /dev/loop0 + $ btrfstune -S 1 /dev/loop0 + $ mount /dev/loop0 /btrfs + $ btrfs dev add -f /dev/loop1 /btrfs + BTRFS info (device loop0): relocating block group 290455552 flags system + BTRFS info (device loop0): relocating block group 1048576 flags system + BTRFS info (device loop0): disk added /dev/loop1 + $ umount /btrfs + +Mount the sprout device and run fstrim: + + $ mount /dev/loop1 /btrfs + $ fstrim /btrfs + $ umount /btrfs + +Now try to mount the seed device, and it fails: + + $ mount /dev/loop0 /btrfs + mount: /btrfs: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error. + +Block 5292032 is missing on the readonly seed device: + + $ dmesg -kt | tail + + BTRFS error (device loop0): bad tree block start, want 5292032 have 0 + BTRFS warning (device loop0): couldn't read-tree root + BTRFS error (device loop0): open_ctree failed + +>From the dump-tree of the seed device (taken before the fstrim). Block +5292032 belonged to the block group starting at 5242880: + + $ btrfs inspect dump-tree -e /dev/loop0 | grep -A1 BLOCK_GROUP + + item 3 key (5242880 BLOCK_GROUP_ITEM 8388608) itemoff 16169 itemsize 24 + block group used 114688 chunk_objectid 256 flags METADATA + + +>From the dump-tree of the sprout device (taken before the fstrim). +fstrim used block-group 5242880 to find the related free space to free: + + $ btrfs inspect dump-tree -e /dev/loop1 | grep -A1 BLOCK_GROUP + + item 1 key (5242880 BLOCK_GROUP_ITEM 8388608) itemoff 16226 itemsize 24 + block group used 32768 chunk_objectid 256 flags METADATA + + +BPF kernel tracing the fstrim command finds the missing block 5292032 +within the range of the discarded blocks as below: + + kprobe:btrfs_discard_extent { + printf("freeing start %llu end %llu num_bytes %llu:\n", + arg1, arg1+arg2, arg2); + } + + freeing start 5259264 end 5406720 num_bytes 147456 + + +Fix this by avoiding the discard command to the readonly seed device. + +Reported-by: Chris Murphy +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Filipe Manana +Signed-off-by: Anand Jain +Signed-off-by: David Sterba +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/extent-tree.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -1984,16 +1984,20 @@ int btrfs_discard_extent(struct btrfs_fs + for (i = 0; i < bbio->num_stripes; i++, stripe++) { + u64 bytes; + struct request_queue *req_q; ++ struct btrfs_device *device = stripe->dev; + +- if (!stripe->dev->bdev) { ++ if (!device->bdev) { + ASSERT(btrfs_test_opt(fs_info, DEGRADED)); + continue; + } +- req_q = bdev_get_queue(stripe->dev->bdev); ++ req_q = bdev_get_queue(device->bdev); + if (!blk_queue_discard(req_q)) + continue; + +- ret = btrfs_issue_discard(stripe->dev->bdev, ++ if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) ++ continue; ++ ++ ret = btrfs_issue_discard(device->bdev, + stripe->physical, + stripe->length, + &bytes); diff --git a/queue-4.19/kvm-arm64-fix-debug-register-indexing.patch b/queue-4.19/kvm-arm64-fix-debug-register-indexing.patch new file mode 100644 index 00000000000..6a294bc7623 --- /dev/null +++ b/queue-4.19/kvm-arm64-fix-debug-register-indexing.patch @@ -0,0 +1,208 @@ +From cb853ded1d25e5b026ce115dbcde69e3d7e2e831 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Fri, 14 May 2021 09:05:41 +0100 +Subject: KVM: arm64: Fix debug register indexing + +From: Marc Zyngier + +commit cb853ded1d25e5b026ce115dbcde69e3d7e2e831 upstream. + +Commit 03fdfb2690099 ("KVM: arm64: Don't write junk to sysregs on +reset") flipped the register number to 0 for all the debug registers +in the sysreg table, hereby indicating that these registers live +in a separate shadow structure. + +However, the author of this patch failed to realise that all the +accessors are using that particular index instead of the register +encoding, resulting in all the registers hitting index 0. Not quite +a valid implementation of the architecture... + +Address the issue by fixing all the accessors to use the CRm field +of the encoding, which contains the debug register index. + +Fixes: 03fdfb2690099 ("KVM: arm64: Don't write junk to sysregs on reset") +Reported-by: Ricardo Koller +Signed-off-by: Marc Zyngier +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/sys_regs.c | 42 +++++++++++++++++++++--------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +--- a/arch/arm64/kvm/sys_regs.c ++++ b/arch/arm64/kvm/sys_regs.c +@@ -426,14 +426,14 @@ static bool trap_bvr(struct kvm_vcpu *vc + struct sys_reg_params *p, + const struct sys_reg_desc *rd) + { +- u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg]; ++ u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm]; + + if (p->is_write) + reg_to_dbg(vcpu, p, dbg_reg); + else + dbg_to_reg(vcpu, p, dbg_reg); + +- trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg); ++ trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg); + + return true; + } +@@ -441,7 +441,7 @@ static bool trap_bvr(struct kvm_vcpu *vc + static int set_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm]; + + if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -451,7 +451,7 @@ static int set_bvr(struct kvm_vcpu *vcpu + static int get_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm]; + + if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -461,21 +461,21 @@ static int get_bvr(struct kvm_vcpu *vcpu + static void reset_bvr(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) + { +- vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg] = rd->val; ++ vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm] = rd->val; + } + + static bool trap_bcr(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *rd) + { +- u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg]; ++ u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm]; + + if (p->is_write) + reg_to_dbg(vcpu, p, dbg_reg); + else + dbg_to_reg(vcpu, p, dbg_reg); + +- trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg); ++ trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg); + + return true; + } +@@ -483,7 +483,7 @@ static bool trap_bcr(struct kvm_vcpu *vc + static int set_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm]; + + if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -494,7 +494,7 @@ static int set_bcr(struct kvm_vcpu *vcpu + static int get_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm]; + + if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -504,22 +504,22 @@ static int get_bcr(struct kvm_vcpu *vcpu + static void reset_bcr(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) + { +- vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg] = rd->val; ++ vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm] = rd->val; + } + + static bool trap_wvr(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *rd) + { +- u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]; ++ u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]; + + if (p->is_write) + reg_to_dbg(vcpu, p, dbg_reg); + else + dbg_to_reg(vcpu, p, dbg_reg); + +- trace_trap_reg(__func__, rd->reg, p->is_write, +- vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]); ++ trace_trap_reg(__func__, rd->CRm, p->is_write, ++ vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]); + + return true; + } +@@ -527,7 +527,7 @@ static bool trap_wvr(struct kvm_vcpu *vc + static int set_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]; + + if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -537,7 +537,7 @@ static int set_wvr(struct kvm_vcpu *vcpu + static int get_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]; + + if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -547,21 +547,21 @@ static int get_wvr(struct kvm_vcpu *vcpu + static void reset_wvr(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) + { +- vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg] = rd->val; ++ vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm] = rd->val; + } + + static bool trap_wcr(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *rd) + { +- u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg]; ++ u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm]; + + if (p->is_write) + reg_to_dbg(vcpu, p, dbg_reg); + else + dbg_to_reg(vcpu, p, dbg_reg); + +- trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg); ++ trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg); + + return true; + } +@@ -569,7 +569,7 @@ static bool trap_wcr(struct kvm_vcpu *vc + static int set_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm]; + + if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -579,7 +579,7 @@ static int set_wcr(struct kvm_vcpu *vcpu + static int get_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm]; + + if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -589,7 +589,7 @@ static int get_wcr(struct kvm_vcpu *vcpu + static void reset_wcr(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) + { +- vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg] = rd->val; ++ vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm] = rd->val; + } + + static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) diff --git a/queue-4.19/kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch b/queue-4.19/kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch new file mode 100644 index 00000000000..1edafa6c15d --- /dev/null +++ b/queue-4.19/kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch @@ -0,0 +1,66 @@ +From foo@baz Tue Jun 8 05:38:40 PM CEST 2021 +From: Sean Christopherson +Date: Wed, 21 Apr 2021 19:21:22 -0700 +Subject: KVM: SVM: Truncate GPR value for DR and CR accesses in !64-bit mode + +From: Sean Christopherson + +commit 0884335a2e653b8a045083aa1d57ce74269ac81d upstream. + +Drop bits 63:32 on loads/stores to/from DRs and CRs when the vCPU is not +in 64-bit mode. The APM states bits 63:32 are dropped for both DRs and +CRs: + + In 64-bit mode, the operand size is fixed at 64 bits without the need + for a REX prefix. In non-64-bit mode, the operand size is fixed at 32 + bits and the upper 32 bits of the destination are forced to 0. + +Fixes: 7ff76d58a9dc ("KVM: SVM: enhance MOV CR intercept handler") +Fixes: cae3797a4639 ("KVM: SVM: enhance mov DR intercept handler") +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Message-Id: <20210422022128.3464144-4-seanjc@google.com> +Signed-off-by: Paolo Bonzini +[sudip: manual backport to old file] +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -4033,7 +4033,7 @@ static int cr_interception(struct vcpu_s + err = 0; + if (cr >= 16) { /* mov to cr */ + cr -= 16; +- val = kvm_register_read(&svm->vcpu, reg); ++ val = kvm_register_readl(&svm->vcpu, reg); + switch (cr) { + case 0: + if (!check_selective_cr0_intercepted(svm, val)) +@@ -4078,7 +4078,7 @@ static int cr_interception(struct vcpu_s + kvm_queue_exception(&svm->vcpu, UD_VECTOR); + return 1; + } +- kvm_register_write(&svm->vcpu, reg, val); ++ kvm_register_writel(&svm->vcpu, reg, val); + } + return kvm_complete_insn_gp(&svm->vcpu, err); + } +@@ -4108,13 +4108,13 @@ static int dr_interception(struct vcpu_s + if (dr >= 16) { /* mov to DRn */ + if (!kvm_require_dr(&svm->vcpu, dr - 16)) + return 1; +- val = kvm_register_read(&svm->vcpu, reg); ++ val = kvm_register_readl(&svm->vcpu, reg); + kvm_set_dr(&svm->vcpu, dr - 16, val); + } else { + if (!kvm_require_dr(&svm->vcpu, dr)) + return 1; + kvm_get_dr(&svm->vcpu, dr, &val); +- kvm_register_write(&svm->vcpu, reg, val); ++ kvm_register_writel(&svm->vcpu, reg, val); + } + + return kvm_skip_emulated_instruction(&svm->vcpu); diff --git a/queue-4.19/series b/queue-4.19/series index 0596a8ff0b8..c14c1e6f306 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -49,3 +49,6 @@ selftests-bpf-avoid-running-unprivileged-tests-with-alignment-requirements.patch bnxt_en-remove-the-setting-of-dev_port.patch perf-cgroups-don-t-rotate-events-for-cgroups-unnecessarily.patch perf-core-fix-corner-case-in-perf_rotate_context.patch +btrfs-fix-unmountable-seed-device-after-fstrim.patch +kvm-svm-truncate-gpr-value-for-dr-and-cr-accesses-in-64-bit-mode.patch +kvm-arm64-fix-debug-register-indexing.patch -- 2.47.3