--- /dev/null
+From 9424ef56e13a1f14c57ea161eed3ecfdc7b2770e Mon Sep 17 00:00:00 2001
+From: Shijie Luo <luoshijie1@huawei.com>
+Date: Sat, 15 Feb 2020 03:02:06 -0500
+Subject: ext4: add cond_resched() to __ext4_find_entry()
+
+From: Shijie Luo <luoshijie1@huawei.com>
+
+commit 9424ef56e13a1f14c57ea161eed3ecfdc7b2770e upstream.
+
+We tested a soft lockup problem in linux 4.19 which could also
+be found in linux 5.x.
+
+When dir inode takes up a large number of blocks, and if the
+directory is growing when we are searching, it's possible the
+restart branch could be called many times, and the do while loop
+could hold cpu a long time.
+
+Here is the call trace in linux 4.19.
+
+[ 473.756186] Call trace:
+[ 473.756196] dump_backtrace+0x0/0x198
+[ 473.756199] show_stack+0x24/0x30
+[ 473.756205] dump_stack+0xa4/0xcc
+[ 473.756210] watchdog_timer_fn+0x300/0x3e8
+[ 473.756215] __hrtimer_run_queues+0x114/0x358
+[ 473.756217] hrtimer_interrupt+0x104/0x2d8
+[ 473.756222] arch_timer_handler_virt+0x38/0x58
+[ 473.756226] handle_percpu_devid_irq+0x90/0x248
+[ 473.756231] generic_handle_irq+0x34/0x50
+[ 473.756234] __handle_domain_irq+0x68/0xc0
+[ 473.756236] gic_handle_irq+0x6c/0x150
+[ 473.756238] el1_irq+0xb8/0x140
+[ 473.756286] ext4_es_lookup_extent+0xdc/0x258 [ext4]
+[ 473.756310] ext4_map_blocks+0x64/0x5c0 [ext4]
+[ 473.756333] ext4_getblk+0x6c/0x1d0 [ext4]
+[ 473.756356] ext4_bread_batch+0x7c/0x1f8 [ext4]
+[ 473.756379] ext4_find_entry+0x124/0x3f8 [ext4]
+[ 473.756402] ext4_lookup+0x8c/0x258 [ext4]
+[ 473.756407] __lookup_hash+0x8c/0xe8
+[ 473.756411] filename_create+0xa0/0x170
+[ 473.756413] do_mkdirat+0x6c/0x140
+[ 473.756415] __arm64_sys_mkdirat+0x28/0x38
+[ 473.756419] el0_svc_common+0x78/0x130
+[ 473.756421] el0_svc_handler+0x38/0x78
+[ 473.756423] el0_svc+0x8/0xc
+[ 485.755156] watchdog: BUG: soft lockup - CPU#2 stuck for 22s! [tmp:5149]
+
+Add cond_resched() to avoid soft lockup and to provide a better
+system responding.
+
+Link: https://lore.kernel.org/r/20200215080206.13293-1-luoshijie1@huawei.com
+Signed-off-by: Shijie Luo <luoshijie1@huawei.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/namei.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1430,6 +1430,7 @@ restart:
+ /*
+ * We deal with the read-ahead logic here.
+ */
++ cond_resched();
+ if (ra_ptr >= ra_max) {
+ /* Refill the readahead buffer */
+ ra_ptr = 0;
--- /dev/null
+From 35df4299a6487f323b0aca120ea3f485dfee2ae3 Mon Sep 17 00:00:00 2001
+From: Qian Cai <cai@lca.pw>
+Date: Fri, 7 Feb 2020 09:29:11 -0500
+Subject: ext4: fix a data race in EXT4_I(inode)->i_disksize
+
+From: Qian Cai <cai@lca.pw>
+
+commit 35df4299a6487f323b0aca120ea3f485dfee2ae3 upstream.
+
+EXT4_I(inode)->i_disksize could be accessed concurrently as noticed by
+KCSAN,
+
+ BUG: KCSAN: data-race in ext4_write_end [ext4] / ext4_writepages [ext4]
+
+ write to 0xffff91c6713b00f8 of 8 bytes by task 49268 on cpu 127:
+ ext4_write_end+0x4e3/0x750 [ext4]
+ ext4_update_i_disksize at fs/ext4/ext4.h:3032
+ (inlined by) ext4_update_inode_size at fs/ext4/ext4.h:3046
+ (inlined by) ext4_write_end at fs/ext4/inode.c:1287
+ generic_perform_write+0x208/0x2a0
+ ext4_buffered_write_iter+0x11f/0x210 [ext4]
+ ext4_file_write_iter+0xce/0x9e0 [ext4]
+ new_sync_write+0x29c/0x3b0
+ __vfs_write+0x92/0xa0
+ vfs_write+0x103/0x260
+ ksys_write+0x9d/0x130
+ __x64_sys_write+0x4c/0x60
+ do_syscall_64+0x91/0xb47
+ entry_SYSCALL_64_after_hwframe+0x49/0xbe
+
+ read to 0xffff91c6713b00f8 of 8 bytes by task 24872 on cpu 37:
+ ext4_writepages+0x10ac/0x1d00 [ext4]
+ mpage_map_and_submit_extent at fs/ext4/inode.c:2468
+ (inlined by) ext4_writepages at fs/ext4/inode.c:2772
+ do_writepages+0x5e/0x130
+ __writeback_single_inode+0xeb/0xb20
+ writeback_sb_inodes+0x429/0x900
+ __writeback_inodes_wb+0xc4/0x150
+ wb_writeback+0x4bd/0x870
+ wb_workfn+0x6b4/0x960
+ process_one_work+0x54c/0xbe0
+ worker_thread+0x80/0x650
+ kthread+0x1e0/0x200
+ ret_from_fork+0x27/0x50
+
+ Reported by Kernel Concurrency Sanitizer on:
+ CPU: 37 PID: 24872 Comm: kworker/u261:2 Tainted: G W O L 5.5.0-next-20200204+ #5
+ Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40 07/10/2019
+ Workqueue: writeback wb_workfn (flush-7:0)
+
+Since only the read is operating as lockless (outside of the
+"i_data_sem"), load tearing could introduce a logic bug. Fix it by
+adding READ_ONCE() for the read and WRITE_ONCE() for the write.
+
+Signed-off-by: Qian Cai <cai@lca.pw>
+Link: https://lore.kernel.org/r/1581085751-31793-1-git-send-email-cai@lca.pw
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4.h | 2 +-
+ fs/ext4/inode.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2867,7 +2867,7 @@ static inline void ext4_update_i_disksiz
+ !inode_is_locked(inode));
+ down_write(&EXT4_I(inode)->i_data_sem);
+ if (newsize > EXT4_I(inode)->i_disksize)
+- EXT4_I(inode)->i_disksize = newsize;
++ WRITE_ONCE(EXT4_I(inode)->i_disksize, newsize);
+ up_write(&EXT4_I(inode)->i_data_sem);
+ }
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2564,7 +2564,7 @@ update_disksize:
+ * truncate are avoided by checking i_size under i_data_sem.
+ */
+ disksize = ((loff_t)mpd->first_page) << PAGE_SHIFT;
+- if (disksize > EXT4_I(inode)->i_disksize) {
++ if (disksize > READ_ONCE(EXT4_I(inode)->i_disksize)) {
+ int err2;
+ loff_t i_size;
+
--- /dev/null
+From 9db176bceb5c5df4990486709da386edadc6bd1d Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 21 Feb 2020 11:08:35 +0100
+Subject: ext4: fix mount failure with quota configured as module
+
+From: Jan Kara <jack@suse.cz>
+
+commit 9db176bceb5c5df4990486709da386edadc6bd1d upstream.
+
+When CONFIG_QFMT_V2 is configured as a module, the test in
+ext4_feature_set_ok() fails and so mount of filesystems with quota or
+project features fails. Fix the test to use IS_ENABLED macro which
+works properly even for modules.
+
+Link: https://lore.kernel.org/r/20200221100835.9332-1-jack@suse.cz
+Fixes: d65d87a07476 ("ext4: improve explanation of a mount failure caused by a misconfigured kernel")
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2863,7 +2863,7 @@ static int ext4_feature_set_ok(struct su
+ return 0;
+ }
+
+-#if !defined(CONFIG_QUOTA) || !defined(CONFIG_QFMT_V2)
++#if !IS_ENABLED(CONFIG_QUOTA) || !IS_ENABLED(CONFIG_QFMT_V2)
+ if (!readonly && (ext4_has_feature_quota(sb) ||
+ ext4_has_feature_project(sb))) {
+ ext4_msg(sb, KERN_ERR,
--- /dev/null
+From cb85f4d23f794e24127f3e562cb3b54b0803f456 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Wed, 19 Feb 2020 10:30:47 -0800
+Subject: ext4: fix race between writepages and enabling EXT4_EXTENTS_FL
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit cb85f4d23f794e24127f3e562cb3b54b0803f456 upstream.
+
+If EXT4_EXTENTS_FL is set on an inode while ext4_writepages() is running
+on it, the following warning in ext4_add_complete_io() can be hit:
+
+WARNING: CPU: 1 PID: 0 at fs/ext4/page-io.c:234 ext4_put_io_end_defer+0xf0/0x120
+
+Here's a minimal reproducer (not 100% reliable) (root isn't required):
+
+ while true; do
+ sync
+ done &
+ while true; do
+ rm -f file
+ touch file
+ chattr -e file
+ echo X >> file
+ chattr +e file
+ done
+
+The problem is that in ext4_writepages(), ext4_should_dioread_nolock()
+(which only returns true on extent-based files) is checked once to set
+the number of reserved journal credits, and also again later to select
+the flags for ext4_map_blocks() and copy the reserved journal handle to
+ext4_io_end::handle. But if EXT4_EXTENTS_FL is being concurrently set,
+the first check can see dioread_nolock disabled while the later one can
+see it enabled, causing the reserved handle to unexpectedly be NULL.
+
+Since changing EXT4_EXTENTS_FL is uncommon, and there may be other races
+related to doing so as well, fix this by synchronizing changing
+EXT4_EXTENTS_FL with ext4_writepages() via the existing
+s_writepages_rwsem (previously called s_journal_flag_rwsem).
+
+This was originally reported by syzbot without a reproducer at
+https://syzkaller.appspot.com/bug?extid=2202a584a00fffd19fbf,
+but now that dioread_nolock is the default I also started seeing this
+when running syzkaller locally.
+
+Link: https://lore.kernel.org/r/20200219183047.47417-3-ebiggers@kernel.org
+Reported-by: syzbot+2202a584a00fffd19fbf@syzkaller.appspotmail.com
+Fixes: 6b523df4fb5a ("ext4: use transaction reservation for extent conversion in ext4_end_io")
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4.h | 5 ++++-
+ fs/ext4/migrate.c | 27 +++++++++++++++++++--------
+ 2 files changed, 23 insertions(+), 9 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1532,7 +1532,10 @@ struct ext4_sb_info {
+ struct ratelimit_state s_warning_ratelimit_state;
+ struct ratelimit_state s_msg_ratelimit_state;
+
+- /* Barrier between changing inodes' journal flags and writepages ops. */
++ /*
++ * Barrier between writepages ops and changing any inode's JOURNAL_DATA
++ * or EXTENTS flag.
++ */
+ struct percpu_rw_semaphore s_writepages_rwsem;
+ struct dax_device *s_daxdev;
+ };
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -434,6 +434,7 @@ static int free_ext_block(handle_t *hand
+
+ int ext4_ext_migrate(struct inode *inode)
+ {
++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+ handle_t *handle;
+ int retval = 0, i;
+ __le32 *i_data;
+@@ -458,6 +459,8 @@ int ext4_ext_migrate(struct inode *inode
+ */
+ return retval;
+
++ percpu_down_write(&sbi->s_writepages_rwsem);
++
+ /*
+ * Worst case we can touch the allocation bitmaps, a bgd
+ * block, and a block to link in the orphan list. We do need
+@@ -468,7 +471,7 @@ int ext4_ext_migrate(struct inode *inode
+
+ if (IS_ERR(handle)) {
+ retval = PTR_ERR(handle);
+- return retval;
++ goto out_unlock;
+ }
+ goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) *
+ EXT4_INODES_PER_GROUP(inode->i_sb)) + 1;
+@@ -479,7 +482,7 @@ int ext4_ext_migrate(struct inode *inode
+ if (IS_ERR(tmp_inode)) {
+ retval = PTR_ERR(tmp_inode);
+ ext4_journal_stop(handle);
+- return retval;
++ goto out_unlock;
+ }
+ i_size_write(tmp_inode, i_size_read(inode));
+ /*
+@@ -521,7 +524,7 @@ int ext4_ext_migrate(struct inode *inode
+ */
+ ext4_orphan_del(NULL, tmp_inode);
+ retval = PTR_ERR(handle);
+- goto out;
++ goto out_tmp_inode;
+ }
+
+ ei = EXT4_I(inode);
+@@ -602,10 +605,11 @@ err_out:
+ /* Reset the extent details */
+ ext4_ext_tree_init(handle, tmp_inode);
+ ext4_journal_stop(handle);
+-out:
++out_tmp_inode:
+ unlock_new_inode(tmp_inode);
+ iput(tmp_inode);
+-
++out_unlock:
++ percpu_up_write(&sbi->s_writepages_rwsem);
+ return retval;
+ }
+
+@@ -615,7 +619,8 @@ out:
+ int ext4_ind_migrate(struct inode *inode)
+ {
+ struct ext4_extent_header *eh;
+- struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
++ struct ext4_super_block *es = sbi->s_es;
+ struct ext4_inode_info *ei = EXT4_I(inode);
+ struct ext4_extent *ex;
+ unsigned int i, len;
+@@ -639,9 +644,13 @@ int ext4_ind_migrate(struct inode *inode
+ if (test_opt(inode->i_sb, DELALLOC))
+ ext4_alloc_da_blocks(inode);
+
++ percpu_down_write(&sbi->s_writepages_rwsem);
++
+ handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
+- if (IS_ERR(handle))
+- return PTR_ERR(handle);
++ if (IS_ERR(handle)) {
++ ret = PTR_ERR(handle);
++ goto out_unlock;
++ }
+
+ down_write(&EXT4_I(inode)->i_data_sem);
+ ret = ext4_ext_check_inode(inode);
+@@ -676,5 +685,7 @@ int ext4_ind_migrate(struct inode *inode
+ errout:
+ ext4_journal_stop(handle);
+ up_write(&EXT4_I(inode)->i_data_sem);
++out_unlock:
++ percpu_up_write(&sbi->s_writepages_rwsem);
+ return ret;
+ }
--- /dev/null
+From bbd55937de8f2754adc5792b0f8e5ff7d9c0420e Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Wed, 19 Feb 2020 10:30:46 -0800
+Subject: ext4: rename s_journal_flag_rwsem to s_writepages_rwsem
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit bbd55937de8f2754adc5792b0f8e5ff7d9c0420e upstream.
+
+In preparation for making s_journal_flag_rwsem synchronize
+ext4_writepages() with changes to both the EXTENTS and JOURNAL_DATA
+flags (rather than just JOURNAL_DATA as it does currently), rename it to
+s_writepages_rwsem.
+
+Link: https://lore.kernel.org/r/20200219183047.47417-2-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4.h | 2 +-
+ fs/ext4/inode.c | 10 +++++-----
+ fs/ext4/super.c | 6 +++---
+ 3 files changed, 9 insertions(+), 9 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1533,7 +1533,7 @@ struct ext4_sb_info {
+ struct ratelimit_state s_msg_ratelimit_state;
+
+ /* Barrier between changing inodes' journal flags and writepages ops. */
+- struct percpu_rw_semaphore s_journal_flag_rwsem;
++ struct percpu_rw_semaphore s_writepages_rwsem;
+ struct dax_device *s_daxdev;
+ };
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2744,7 +2744,7 @@ static int ext4_writepages(struct addres
+ if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
+ return -EIO;
+
+- percpu_down_read(&sbi->s_journal_flag_rwsem);
++ percpu_down_read(&sbi->s_writepages_rwsem);
+ trace_ext4_writepages(inode, wbc);
+
+ if (dax_mapping(mapping)) {
+@@ -2974,7 +2974,7 @@ unplug:
+ out_writepages:
+ trace_ext4_writepages_result(inode, wbc, ret,
+ nr_to_write - wbc->nr_to_write);
+- percpu_up_read(&sbi->s_journal_flag_rwsem);
++ percpu_up_read(&sbi->s_writepages_rwsem);
+ return ret;
+ }
+
+@@ -6050,7 +6050,7 @@ int ext4_change_inode_journal_flag(struc
+ }
+ }
+
+- percpu_down_write(&sbi->s_journal_flag_rwsem);
++ percpu_down_write(&sbi->s_writepages_rwsem);
+ jbd2_journal_lock_updates(journal);
+
+ /*
+@@ -6067,7 +6067,7 @@ int ext4_change_inode_journal_flag(struc
+ err = jbd2_journal_flush(journal);
+ if (err < 0) {
+ jbd2_journal_unlock_updates(journal);
+- percpu_up_write(&sbi->s_journal_flag_rwsem);
++ percpu_up_write(&sbi->s_writepages_rwsem);
+ ext4_inode_resume_unlocked_dio(inode);
+ return err;
+ }
+@@ -6076,7 +6076,7 @@ int ext4_change_inode_journal_flag(struc
+ ext4_set_aops(inode);
+
+ jbd2_journal_unlock_updates(journal);
+- percpu_up_write(&sbi->s_journal_flag_rwsem);
++ percpu_up_write(&sbi->s_writepages_rwsem);
+
+ if (val)
+ up_write(&EXT4_I(inode)->i_mmap_sem);
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -939,7 +939,7 @@ static void ext4_put_super(struct super_
+ percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ percpu_counter_destroy(&sbi->s_dirs_counter);
+ percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+- percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
++ percpu_free_rwsem(&sbi->s_writepages_rwsem);
+ #ifdef CONFIG_QUOTA
+ for (i = 0; i < EXT4_MAXQUOTAS; i++)
+ kfree(get_qf_name(sb, sbi, i));
+@@ -4396,7 +4396,7 @@ no_journal:
+ err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
+ GFP_KERNEL);
+ if (!err)
+- err = percpu_init_rwsem(&sbi->s_journal_flag_rwsem);
++ err = percpu_init_rwsem(&sbi->s_writepages_rwsem);
+
+ if (err) {
+ ext4_msg(sb, KERN_ERR, "insufficient memory");
+@@ -4490,7 +4490,7 @@ failed_mount6:
+ percpu_counter_destroy(&sbi->s_freeinodes_counter);
+ percpu_counter_destroy(&sbi->s_dirs_counter);
+ percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+- percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
++ percpu_free_rwsem(&sbi->s_writepages_rwsem);
+ failed_mount5:
+ ext4_ext_release(sb);
+ ext4_release_system_zone(sb);
--- /dev/null
+From 35a571346a94fb93b5b3b6a599675ef3384bc75c Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oupton@google.com>
+Date: Tue, 4 Feb 2020 15:26:31 -0800
+Subject: KVM: nVMX: Check IO instruction VM-exit conditions
+
+From: Oliver Upton <oupton@google.com>
+
+commit 35a571346a94fb93b5b3b6a599675ef3384bc75c upstream.
+
+Consult the 'unconditional IO exiting' and 'use IO bitmaps' VM-execution
+controls when checking instruction interception. If the 'use IO bitmaps'
+VM-execution control is 1, check the instruction access against the IO
+bitmaps to determine if the instruction causes a VM-exit.
+
+Signed-off-by: Oliver Upton <oupton@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/vmx.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 52 insertions(+), 7 deletions(-)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -4997,7 +4997,7 @@ static bool nested_vmx_exit_handled_io(s
+ struct vmcs12 *vmcs12)
+ {
+ unsigned long exit_qualification;
+- unsigned int port;
++ unsigned short port;
+ int size;
+
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+@@ -12335,6 +12335,39 @@ static void nested_vmx_entry_failure(str
+ to_vmx(vcpu)->nested.sync_shadow_vmcs = true;
+ }
+
++static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
++ struct x86_instruction_info *info)
++{
++ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
++ unsigned short port;
++ bool intercept;
++ int size;
++
++ if (info->intercept == x86_intercept_in ||
++ info->intercept == x86_intercept_ins) {
++ port = info->src_val;
++ size = info->dst_bytes;
++ } else {
++ port = info->dst_val;
++ size = info->src_bytes;
++ }
++
++ /*
++ * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
++ * VM-exits depend on the 'unconditional IO exiting' VM-execution
++ * control.
++ *
++ * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
++ */
++ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
++ intercept = nested_cpu_has(vmcs12,
++ CPU_BASED_UNCOND_IO_EXITING);
++ else
++ intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
++
++ return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
++}
++
+ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
+ struct x86_instruction_info *info,
+ enum x86_intercept_stage stage)
+@@ -12342,18 +12375,30 @@ static int vmx_check_intercept(struct kv
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
+
++ switch (info->intercept) {
+ /*
+ * RDPID causes #UD if disabled through secondary execution controls.
+ * Because it is marked as EmulateOnUD, we need to intercept it here.
+ */
+- if (info->intercept == x86_intercept_rdtscp &&
+- !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+- ctxt->exception.vector = UD_VECTOR;
+- ctxt->exception.error_code_valid = false;
+- return X86EMUL_PROPAGATE_FAULT;
+- }
++ case x86_intercept_rdtscp:
++ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
++ ctxt->exception.vector = UD_VECTOR;
++ ctxt->exception.error_code_valid = false;
++ return X86EMUL_PROPAGATE_FAULT;
++ }
++ break;
++
++ case x86_intercept_in:
++ case x86_intercept_ins:
++ case x86_intercept_out:
++ case x86_intercept_outs:
++ return vmx_check_intercept_io(vcpu, info);
+
+ /* TODO: check more intercepts... */
++ default:
++ break;
++ }
++
+ return X86EMUL_UNHANDLEABLE;
+ }
+
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- arch/x86/kvm/vmx.c | 2 +-
+ arch/x86/kvm/vmx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
-diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
-index a116548a4ade1..fc00fbffcd7fc 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
-@@ -12325,7 +12325,7 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
- struct x86_instruction_info *info,
- enum x86_intercept_stage stage)
- {
+@@ -12340,7 +12340,7 @@ static int vmx_check_intercept(struct kv
+ }
+
+ /* TODO: check more intercepts... */
- return X86EMUL_CONTINUE;
+ return X86EMUL_UNHANDLEABLE;
}
#ifdef CONFIG_X86_64
---
-2.20.1
-
--- /dev/null
+From e71237d3ff1abf9f3388337cfebf53b96df2020d Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oupton@google.com>
+Date: Tue, 4 Feb 2020 15:26:30 -0800
+Subject: KVM: nVMX: Refactor IO bitmap checks into helper function
+
+From: Oliver Upton <oupton@google.com>
+
+commit e71237d3ff1abf9f3388337cfebf53b96df2020d upstream.
+
+Checks against the IO bitmap are useful for both instruction emulation
+and VM-exit reflection. Refactor the IO bitmap checks into a helper
+function.
+
+Signed-off-by: Oliver Upton <oupton@google.com>
+Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/vmx.c | 40 +++++++++++++++++++++++++++-------------
+ 1 file changed, 27 insertions(+), 13 deletions(-)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -4991,6 +4991,26 @@ static bool cs_ss_rpl_check(struct kvm_v
+ (ss.selector & SEGMENT_RPL_MASK));
+ }
+
++static bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu,
++ unsigned int port, int size);
++static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
++ struct vmcs12 *vmcs12)
++{
++ unsigned long exit_qualification;
++ unsigned int port;
++ int size;
++
++ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
++ return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
++
++ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
++
++ port = exit_qualification >> 16;
++ size = (exit_qualification & 7) + 1;
++
++ return nested_vmx_check_io_bitmaps(vcpu, port, size);
++}
++
+ /*
+ * Check if guest state is valid. Returns true if valid, false if
+ * not.
+@@ -8521,23 +8541,17 @@ static int (*const kvm_vmx_exit_handlers
+ static const int kvm_vmx_max_exit_handlers =
+ ARRAY_SIZE(kvm_vmx_exit_handlers);
+
+-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+- struct vmcs12 *vmcs12)
++/*
++ * Return true if an IO instruction with the specified port and size should cause
++ * a VM-exit into L1.
++ */
++bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
++ int size)
+ {
+- unsigned long exit_qualification;
++ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ gpa_t bitmap, last_bitmap;
+- unsigned int port;
+- int size;
+ u8 b;
+
+- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+- return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+-
+- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+-
+- port = exit_qualification >> 16;
+- size = (exit_qualification & 7) + 1;
+-
+ last_bitmap = (gpa_t)-1;
+ b = -1;
+
--- /dev/null
+From fb6d4d340e0532032c808a9933eaaa7b8de435ab Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 12 Jul 2016 11:04:26 +0200
+Subject: KVM: x86: emulate RDPID
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit fb6d4d340e0532032c808a9933eaaa7b8de435ab upstream.
+
+This is encoded as F3 0F C7 /7 with a register argument. The register
+argument is the second array in the group9 GroupDual, while F3 is the
+fourth element of a Prefix.
+
+Reviewed-by: Wanpeng Li <wanpeng.li@hotmail.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/cpuid.c | 7 ++++++-
+ arch/x86/kvm/emulate.c | 22 +++++++++++++++++++++-
+ arch/x86/kvm/vmx.c | 15 +++++++++++++++
+ 3 files changed, 42 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/cpuid.c
++++ b/arch/x86/kvm/cpuid.c
+@@ -291,13 +291,18 @@ static int __do_cpuid_ent_emulated(struc
+ {
+ switch (func) {
+ case 0:
+- entry->eax = 1; /* only one leaf currently */
++ entry->eax = 7;
+ ++*nent;
+ break;
+ case 1:
+ entry->ecx = F(MOVBE);
+ ++*nent;
+ break;
++ case 7:
++ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
++ if (index == 0)
++ entry->ecx = F(RDPID);
++ ++*nent;
+ default:
+ break;
+ }
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -3539,6 +3539,16 @@ static int em_cwd(struct x86_emulate_ctx
+ return X86EMUL_CONTINUE;
+ }
+
++static int em_rdpid(struct x86_emulate_ctxt *ctxt)
++{
++ u64 tsc_aux = 0;
++
++ if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux))
++ return emulate_gp(ctxt, 0);
++ ctxt->dst.val = tsc_aux;
++ return X86EMUL_CONTINUE;
++}
++
+ static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
+ {
+ u64 tsc = 0;
+@@ -4431,10 +4441,20 @@ static const struct opcode group8[] = {
+ F(DstMem | SrcImmByte | Lock | PageTable, em_btc),
+ };
+
++/*
++ * The "memory" destination is actually always a register, since we come
++ * from the register case of group9.
++ */
++static const struct gprefix pfx_0f_c7_7 = {
++ N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp),
++};
++
++
+ static const struct group_dual group9 = { {
+ N, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N,
+ }, {
+- N, N, N, N, N, N, N, N,
++ N, N, N, N, N, N, N,
++ GP(0, &pfx_0f_c7_7),
+ } };
+
+ static const struct opcode group11[] = {
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -12322,6 +12322,21 @@ static int vmx_check_intercept(struct kv
+ struct x86_instruction_info *info,
+ enum x86_intercept_stage stage)
+ {
++ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
++ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
++
++ /*
++ * RDPID causes #UD if disabled through secondary execution controls.
++ * Because it is marked as EmulateOnUD, we need to intercept it here.
++ */
++ if (info->intercept == x86_intercept_rdtscp &&
++ !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
++ ctxt->exception.vector = UD_VECTOR;
++ ctxt->exception.error_code_valid = false;
++ return X86EMUL_PROPAGATE_FAULT;
++ }
++
++ /* TODO: check more intercepts... */
+ return X86EMUL_CONTINUE;
+ }
+
+kvm-x86-emulate-rdpid.patch
iommu-qcom-fix-bogus-detach-logic.patch
alsa-hda-use-scnprintf-for-printing-texts-for-sysfs-procfs.patch
asoc-sun8i-codec-fix-setting-dai-data-format.patch
lib-stackdepot-fix-outdated-comments.patch
lib-stackdepot.c-fix-global-out-of-bounds-in-stack_s.patch
kvm-nvmx-don-t-emulate-instructions-in-guest-mode.patch
+ext4-fix-a-data-race-in-ext4_i-inode-i_disksize.patch
+ext4-add-cond_resched-to-__ext4_find_entry.patch
+ext4-fix-mount-failure-with-quota-configured-as-module.patch
+ext4-rename-s_journal_flag_rwsem-to-s_writepages_rwsem.patch
+ext4-fix-race-between-writepages-and-enabling-ext4_extents_fl.patch
+kvm-nvmx-refactor-io-bitmap-checks-into-helper-function.patch
+kvm-nvmx-check-io-instruction-vm-exit-conditions.patch