Home Home > GIT Browse > SLE15-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Thumshirn <jthumshirn@suse.de>2018-07-26 12:49:16 +0200
committerJohannes Thumshirn <jthumshirn@suse.de>2018-07-26 12:49:16 +0200
commit1d68293567e57b0be893b2e2d224714f59dbbb81 (patch)
tree766632b86fb30ba779ae08708208123a916115cb
parentbbb121bf914634763a9f6c4b87d2aaa18358c5d9 (diff)
parent8c801ff7beebb0f1b94acee76ba31308367ad7fd (diff)
Merge remote-tracking branch 'origin/users/jroedel/SLE12-SP4/for-next' into SLE12-SP4
Pull KVM fixes from Joerg Roedel. Conflicts: patches.drivers/nvme-move-init-of-keep_alive-work-item-to-controller.patch
-rw-r--r--patches.drivers/0001-iommu-iova-add-flush-queue-data-structures151
-rw-r--r--patches.drivers/0002-iommu-iova-implement-flush-queue-ring-buffer145
-rw-r--r--patches.drivers/0003-iommu-iova-add-flush-counters-to-flush-queue-implementation137
-rw-r--r--patches.drivers/0004-iommu-iova-add-locking-to-flush-queues87
-rw-r--r--patches.drivers/0005-iommu-iova-add-flush-timer111
-rw-r--r--patches.drivers/0005-iommu-vt-d-use-domain-instead-of-cache-fetching4
-rw-r--r--patches.drivers/0006-iommu-amd-make-use-of-iova-queue-flushing300
-rw-r--r--patches.drivers/0007-iommu-vt-d-allow-to-flush-more-than-4gb-of-device-tlbs27
-rw-r--r--patches.drivers/0008-iommu-vt-d-make-use-of-iova-deferred-flushing300
-rw-r--r--patches.drivers/kvm-svm-add-pause-filter-threshold64
-rw-r--r--patches.drivers/kvm-svm-implement-pause-loop-exit-logic-in-svm191
-rw-r--r--patches.drivers/kvm-vmx-bring-the-common-code-to-header-file159
-rw-r--r--patches.drivers/kvm-vmx-fix-the-module-parameters-for-vmx85
-rw-r--r--patches.drivers/kvm-vmx-remove-ple_window_actual_max102
-rw-r--r--patches.suse/0001-iommu-vt-d-Fix-race-condition-in-add_unmap.patch34
-rw-r--r--series.conf15
16 files changed, 1874 insertions, 38 deletions
diff --git a/patches.drivers/0001-iommu-iova-add-flush-queue-data-structures b/patches.drivers/0001-iommu-iova-add-flush-queue-data-structures
new file mode 100644
index 0000000000..e600d48075
--- /dev/null
+++ b/patches.drivers/0001-iommu-iova-add-flush-queue-data-structures
@@ -0,0 +1,151 @@
+From: Joerg Roedel <jroedel@suse.de>
+Date: Thu, 10 Aug 2017 14:44:28 +0200
+Subject: iommu/iova: Add flush-queue data structures
+Git-commit: 42f87e71c3df12d8f29ec1bb7b47772ffaeaf1ee
+Patch-mainline: v4.14-rc1
+References: bsc#1096790 bsc#1097034
+
+This patch adds the basic data-structures to implement
+flush-queues in the generic IOVA code. It also adds the
+initialization and destroy routines for these data
+structures.
+
+The initialization routine is designed so that the use of
+this feature is optional for the users of IOVA code.
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+---
+ drivers/iommu/iova.c | 39 +++++++++++++++++++++++++++++++++++++++
+ include/linux/iova.h | 41 +++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 80 insertions(+)
+
+--- a/drivers/iommu/iova.c
++++ b/drivers/iommu/iova.c
+@@ -49,10 +49,48 @@ init_iova_domain(struct iova_domain *iov
+ iovad->granule = granule;
+ iovad->start_pfn = start_pfn;
+ iovad->dma_32bit_pfn = pfn_32bit;
++ iovad->flush_cb = NULL;
++ iovad->fq = NULL;
+ init_iova_rcaches(iovad);
+ }
+ EXPORT_SYMBOL_GPL(init_iova_domain);
+
++static void free_iova_flush_queue(struct iova_domain *iovad)
++{
++ if (!iovad->fq)
++ return;
++
++ free_percpu(iovad->fq);
++
++ iovad->fq = NULL;
++ iovad->flush_cb = NULL;
++ iovad->entry_dtor = NULL;
++}
++
++int init_iova_flush_queue(struct iova_domain *iovad,
++ iova_flush_cb flush_cb, iova_entry_dtor entry_dtor)
++{
++ int cpu;
++
++ iovad->fq = alloc_percpu(struct iova_fq);
++ if (!iovad->fq)
++ return -ENOMEM;
++
++ iovad->flush_cb = flush_cb;
++ iovad->entry_dtor = entry_dtor;
++
++ for_each_possible_cpu(cpu) {
++ struct iova_fq *fq;
++
++ fq = per_cpu_ptr(iovad->fq, cpu);
++ fq->head = 0;
++ fq->tail = 0;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(init_iova_flush_queue);
++
+ static struct rb_node *
+ __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
+ {
+@@ -437,6 +475,7 @@ void put_iova_domain(struct iova_domain
+ struct rb_node *node;
+ unsigned long flags;
+
++ free_iova_flush_queue(iovad);
+ free_iova_rcaches(iovad);
+ spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+ node = rb_first(&iovad->rbroot);
+--- a/include/linux/iova.h
++++ b/include/linux/iova.h
+@@ -36,6 +36,30 @@ struct iova_rcache {
+ struct iova_cpu_rcache __percpu *cpu_rcaches;
+ };
+
++struct iova_domain;
++
++/* Call-Back from IOVA code into IOMMU drivers */
++typedef void (* iova_flush_cb)(struct iova_domain *domain);
++
++/* Destructor for per-entry data */
++typedef void (* iova_entry_dtor)(unsigned long data);
++
++/* Number of entries per Flush Queue */
++#define IOVA_FQ_SIZE 256
++
++/* Flush Queue entry for defered flushing */
++struct iova_fq_entry {
++ unsigned long iova_pfn;
++ unsigned long pages;
++ unsigned long data;
++};
++
++/* Per-CPU Flush Queue structure */
++struct iova_fq {
++ struct iova_fq_entry entries[IOVA_FQ_SIZE];
++ unsigned head, tail;
++};
++
+ /* holds all the iova translations for a domain */
+ struct iova_domain {
+ spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */
+@@ -45,6 +69,14 @@ struct iova_domain {
+ unsigned long start_pfn; /* Lower limit for this domain */
+ unsigned long dma_32bit_pfn;
+ struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE]; /* IOVA range caches */
++
++ iova_flush_cb flush_cb; /* Call-Back function to flush IOMMU
++ TLBs */
++
++ iova_entry_dtor entry_dtor; /* IOMMU driver specific destructor for
++ iova entry */
++
++ struct iova_fq __percpu *fq; /* Flush Queue */
+ };
+
+ static inline unsigned long iova_size(struct iova *iova)
+@@ -102,6 +134,8 @@ struct iova *reserve_iova(struct iova_do
+ void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
+ void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
+ unsigned long start_pfn, unsigned long pfn_32bit);
++int init_iova_flush_queue(struct iova_domain *iovad,
++ iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
+ struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
+ void put_iova_domain(struct iova_domain *iovad);
+ struct iova *split_and_remove_iova(struct iova_domain *iovad,
+@@ -174,6 +208,13 @@ static inline void init_iova_domain(stru
+ {
+ }
+
++static inline int init_iova_flush_queue(struct iova_domain *iovad,
++ iova_flush_cb flush_cb,
++ iova_entry_dtor entry_dtor)
++{
++ return -ENODEV;
++}
++
+ static inline struct iova *find_iova(struct iova_domain *iovad,
+ unsigned long pfn)
+ {
diff --git a/patches.drivers/0002-iommu-iova-implement-flush-queue-ring-buffer b/patches.drivers/0002-iommu-iova-implement-flush-queue-ring-buffer
new file mode 100644
index 0000000000..66eed3dd36
--- /dev/null
+++ b/patches.drivers/0002-iommu-iova-implement-flush-queue-ring-buffer
@@ -0,0 +1,145 @@
+From: Joerg Roedel <jroedel@suse.de>
+Date: Thu, 10 Aug 2017 15:49:44 +0200
+Subject: iommu/iova: Implement Flush-Queue ring buffer
+Git-commit: 1928210107edd4fa786199fef6b875d3af3bef88
+Patch-mainline: v4.14-rc1
+References: bsc#1096790 bsc#1097034
+
+Add a function to add entries to the Flush-Queue ring
+buffer. If the buffer is full, call the flush-callback and
+free the entries.
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+---
+ drivers/iommu/iova.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/iova.h | 9 ++++++
+ 2 files changed, 89 insertions(+)
+
+--- a/drivers/iommu/iova.c
++++ b/drivers/iommu/iova.c
+@@ -31,6 +31,7 @@ static unsigned long iova_rcache_get(str
+ unsigned long limit_pfn);
+ static void init_iova_rcaches(struct iova_domain *iovad);
+ static void free_iova_rcaches(struct iova_domain *iovad);
++static void fq_destroy_all_entries(struct iova_domain *iovad);
+
+ void
+ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
+@@ -60,6 +61,7 @@ static void free_iova_flush_queue(struct
+ if (!iovad->fq)
+ return;
+
++ fq_destroy_all_entries(iovad);
+ free_percpu(iovad->fq);
+
+ iovad->fq = NULL;
+@@ -465,6 +467,84 @@ free_iova_fast(struct iova_domain *iovad
+ }
+ EXPORT_SYMBOL_GPL(free_iova_fast);
+
++#define fq_ring_for_each(i, fq) \
++ for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
++
++static inline bool fq_full(struct iova_fq *fq)
++{
++ return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
++}
++
++static inline unsigned fq_ring_add(struct iova_fq *fq)
++{
++ unsigned idx = fq->tail;
++
++ fq->tail = (idx + 1) % IOVA_FQ_SIZE;
++
++ return idx;
++}
++
++static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
++{
++ unsigned idx;
++
++ fq_ring_for_each(idx, fq) {
++
++ if (iovad->entry_dtor)
++ iovad->entry_dtor(fq->entries[idx].data);
++
++ free_iova_fast(iovad,
++ fq->entries[idx].iova_pfn,
++ fq->entries[idx].pages);
++ }
++
++ fq->head = 0;
++ fq->tail = 0;
++}
++
++static void fq_destroy_all_entries(struct iova_domain *iovad)
++{
++ int cpu;
++
++ /*
++ * This code runs when the iova_domain is being detroyed, so don't
++ * bother to free iovas, just call the entry_dtor on all remaining
++ * entries.
++ */
++ if (!iovad->entry_dtor)
++ return;
++
++ for_each_possible_cpu(cpu) {
++ struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
++ int idx;
++
++ fq_ring_for_each(idx, fq)
++ iovad->entry_dtor(fq->entries[idx].data);
++ }
++}
++
++void queue_iova(struct iova_domain *iovad,
++ unsigned long pfn, unsigned long pages,
++ unsigned long data)
++{
++ struct iova_fq *fq = get_cpu_ptr(iovad->fq);
++ unsigned idx;
++
++ if (fq_full(fq)) {
++ iovad->flush_cb(iovad);
++ fq_ring_free(iovad, fq);
++ }
++
++ idx = fq_ring_add(fq);
++
++ fq->entries[idx].iova_pfn = pfn;
++ fq->entries[idx].pages = pages;
++ fq->entries[idx].data = data;
++
++ put_cpu_ptr(iovad->fq);
++}
++EXPORT_SYMBOL_GPL(queue_iova);
++
+ /**
+ * put_iova_domain - destroys the iova doamin
+ * @iovad: - iova domain in question.
+--- a/include/linux/iova.h
++++ b/include/linux/iova.h
+@@ -127,6 +127,9 @@ struct iova *alloc_iova(struct iova_doma
+ bool size_aligned);
+ void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
+ unsigned long size);
++void queue_iova(struct iova_domain *iovad,
++ unsigned long pfn, unsigned long pages,
++ unsigned long data);
+ unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
+ unsigned long limit_pfn);
+ struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
+@@ -182,6 +185,12 @@ static inline void free_iova_fast(struct
+ {
+ }
+
++static inline void queue_iova(struct iova_domain *iovad,
++ unsigned long pfn, unsigned long pages,
++ unsigned long data)
++{
++}
++
+ static inline unsigned long alloc_iova_fast(struct iova_domain *iovad,
+ unsigned long size,
+ unsigned long limit_pfn)
diff --git a/patches.drivers/0003-iommu-iova-add-flush-counters-to-flush-queue-implementation b/patches.drivers/0003-iommu-iova-add-flush-counters-to-flush-queue-implementation
new file mode 100644
index 0000000000..1b54a4e108
--- /dev/null
+++ b/patches.drivers/0003-iommu-iova-add-flush-counters-to-flush-queue-implementation
@@ -0,0 +1,137 @@
+From: Joerg Roedel <jroedel@suse.de>
+Date: Thu, 10 Aug 2017 16:14:59 +0200
+Subject: iommu/iova: Add flush counters to Flush-Queue implementation
+Git-commit: fb418dab8a4f01dde0c025d15145c589ec02796b
+Patch-mainline: v4.14-rc1
+References: bsc#1096790 bsc#1097034
+
+There are two counters:
+
+ * fq_flush_start_cnt - Increased when a TLB flush
+ is started.
+
+ * fq_flush_finish_cnt - Increased when a TLB flush
+ is finished.
+
+The fq_flush_start_cnt is assigned to every Flush-Queue
+entry on its creation. When freeing entries from the
+Flush-Queue, the value in the entry is compared to the
+fq_flush_finish_cnt. The entry can only be freed when its
+value is less than the value of fq_flush_finish_cnt.
+
+The reason for these counters it to take advantage of IOMMU
+TLB flushes that happened on other CPUs. These already
+flushed the TLB for Flush-Queue entries on other CPUs so
+that they can already be freed without flushing the TLB
+again.
+
+This makes it less likely that the Flush-Queue is full and
+saves IOMMU TLB flushes.
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+---
+ drivers/iommu/iova.c | 27 ++++++++++++++++++++++++---
+ include/linux/iova.h | 8 ++++++++
+ 2 files changed, 32 insertions(+), 3 deletions(-)
+
+--- a/drivers/iommu/iova.c
++++ b/drivers/iommu/iova.c
+@@ -74,6 +74,9 @@ int init_iova_flush_queue(struct iova_do
+ {
+ int cpu;
+
++ atomic64_set(&iovad->fq_flush_start_cnt, 0);
++ atomic64_set(&iovad->fq_flush_finish_cnt, 0);
++
+ iovad->fq = alloc_percpu(struct iova_fq);
+ if (!iovad->fq)
+ return -ENOMEM;
+@@ -486,20 +489,30 @@ static inline unsigned fq_ring_add(struc
+
+ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
+ {
++ u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
+ unsigned idx;
+
+ fq_ring_for_each(idx, fq) {
+
++ if (fq->entries[idx].counter >= counter)
++ break;
++
+ if (iovad->entry_dtor)
+ iovad->entry_dtor(fq->entries[idx].data);
+
+ free_iova_fast(iovad,
+ fq->entries[idx].iova_pfn,
+ fq->entries[idx].pages);
++
++ fq->head = (fq->head + 1) % IOVA_FQ_SIZE;
+ }
++}
+
+- fq->head = 0;
+- fq->tail = 0;
++static void iova_domain_flush(struct iova_domain *iovad)
++{
++ atomic64_inc(&iovad->fq_flush_start_cnt);
++ iovad->flush_cb(iovad);
++ atomic64_inc(&iovad->fq_flush_finish_cnt);
+ }
+
+ static void fq_destroy_all_entries(struct iova_domain *iovad)
+@@ -530,8 +543,15 @@ void queue_iova(struct iova_domain *iova
+ struct iova_fq *fq = get_cpu_ptr(iovad->fq);
+ unsigned idx;
+
++ /*
++ * First remove all entries from the flush queue that have already been
++ * flushed out on another CPU. This makes the fq_full() check below less
++ * likely to be true.
++ */
++ fq_ring_free(iovad, fq);
++
+ if (fq_full(fq)) {
+- iovad->flush_cb(iovad);
++ iova_domain_flush(iovad);
+ fq_ring_free(iovad, fq);
+ }
+
+@@ -540,6 +560,7 @@ void queue_iova(struct iova_domain *iova
+ fq->entries[idx].iova_pfn = pfn;
+ fq->entries[idx].pages = pages;
+ fq->entries[idx].data = data;
++ fq->entries[idx].counter = atomic64_read(&iovad->fq_flush_start_cnt);
+
+ put_cpu_ptr(iovad->fq);
+ }
+--- a/include/linux/iova.h
++++ b/include/linux/iova.h
+@@ -14,6 +14,7 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/rbtree.h>
++#include <linux/atomic.h>
+ #include <linux/dma-mapping.h>
+
+ /* iova structure */
+@@ -52,6 +53,7 @@ struct iova_fq_entry {
+ unsigned long iova_pfn;
+ unsigned long pages;
+ unsigned long data;
++ u64 counter; /* Flush counter when this entrie was added */
+ };
+
+ /* Per-CPU Flush Queue structure */
+@@ -77,6 +79,12 @@ struct iova_domain {
+ iova entry */
+
+ struct iova_fq __percpu *fq; /* Flush Queue */
++
++ atomic64_t fq_flush_start_cnt; /* Number of TLB flushes that
++ have been started */
++
++ atomic64_t fq_flush_finish_cnt; /* Number of TLB flushes that
++ have been finished */
+ };
+
+ static inline unsigned long iova_size(struct iova *iova)
diff --git a/patches.drivers/0004-iommu-iova-add-locking-to-flush-queues b/patches.drivers/0004-iommu-iova-add-locking-to-flush-queues
new file mode 100644
index 0000000000..e4cac40914
--- /dev/null
+++ b/patches.drivers/0004-iommu-iova-add-locking-to-flush-queues
@@ -0,0 +1,87 @@
+From: Joerg Roedel <jroedel@suse.de>
+Date: Thu, 10 Aug 2017 16:31:17 +0200
+Subject: iommu/iova: Add locking to Flush-Queues
+Git-commit: 8109c2a2f8463852dddd6a1c3fcf262047c0c124
+Patch-mainline: v4.14-rc1
+References: bsc#1096790 bsc#1097034
+
+The lock is taken from the same CPU most of the time. But
+having it allows to flush the queue also from another CPU if
+necessary.
+
+This will be used by a timer to regularily flush any pending
+IOVAs from the Flush-Queues.
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+---
+ drivers/iommu/iova.c | 11 +++++++++++
+ include/linux/iova.h | 1 +
+ 2 files changed, 12 insertions(+)
+
+--- a/drivers/iommu/iova.c
++++ b/drivers/iommu/iova.c
+@@ -90,6 +90,8 @@ int init_iova_flush_queue(struct iova_do
+ fq = per_cpu_ptr(iovad->fq, cpu);
+ fq->head = 0;
+ fq->tail = 0;
++
++ spin_lock_init(&fq->lock);
+ }
+
+ return 0;
+@@ -475,6 +477,7 @@ EXPORT_SYMBOL_GPL(free_iova_fast);
+
+ static inline bool fq_full(struct iova_fq *fq)
+ {
++ assert_spin_locked(&fq->lock);
+ return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
+ }
+
+@@ -482,6 +485,8 @@ static inline unsigned fq_ring_add(struc
+ {
+ unsigned idx = fq->tail;
+
++ assert_spin_locked(&fq->lock);
++
+ fq->tail = (idx + 1) % IOVA_FQ_SIZE;
+
+ return idx;
+@@ -492,6 +497,8 @@ static void fq_ring_free(struct iova_dom
+ u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
+ unsigned idx;
+
++ assert_spin_locked(&fq->lock);
++
+ fq_ring_for_each(idx, fq) {
+
+ if (fq->entries[idx].counter >= counter)
+@@ -541,8 +548,11 @@ void queue_iova(struct iova_domain *iova
+ unsigned long data)
+ {
+ struct iova_fq *fq = get_cpu_ptr(iovad->fq);
++ unsigned long flags;
+ unsigned idx;
+
++ spin_lock_irqsave(&fq->lock, flags);
++
+ /*
+ * First remove all entries from the flush queue that have already been
+ * flushed out on another CPU. This makes the fq_full() check below less
+@@ -562,6 +572,7 @@ void queue_iova(struct iova_domain *iova
+ fq->entries[idx].data = data;
+ fq->entries[idx].counter = atomic64_read(&iovad->fq_flush_start_cnt);
+
++ spin_unlock_irqrestore(&fq->lock, flags);
+ put_cpu_ptr(iovad->fq);
+ }
+ EXPORT_SYMBOL_GPL(queue_iova);
+--- a/include/linux/iova.h
++++ b/include/linux/iova.h
+@@ -60,6 +60,7 @@ struct iova_fq_entry {
+ struct iova_fq {
+ struct iova_fq_entry entries[IOVA_FQ_SIZE];
+ unsigned head, tail;
++ spinlock_t lock;
+ };
+
+ /* holds all the iova translations for a domain */
diff --git a/patches.drivers/0005-iommu-iova-add-flush-timer b/patches.drivers/0005-iommu-iova-add-flush-timer
new file mode 100644
index 0000000000..9854c4cfdf
--- /dev/null
+++ b/patches.drivers/0005-iommu-iova-add-flush-timer
@@ -0,0 +1,111 @@
+From: Joerg Roedel <jroedel@suse.de>
+Date: Thu, 10 Aug 2017 16:58:18 +0200
+Subject: iommu/iova: Add flush timer
+Git-commit: 9a005a800ae817c2c90ef117d7cd77614d866777
+Patch-mainline: v4.14-rc1
+References: bsc#1096790 bsc#1097034
+
+Add a timer to flush entries from the Flush-Queues every
+10ms. This makes sure that no stale TLB entries remain for
+too long after an IOVA has been unmapped.
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+---
+ drivers/iommu/iova.c | 32 ++++++++++++++++++++++++++++++++
+ include/linux/iova.h | 8 ++++++++
+ 2 files changed, 40 insertions(+)
+
+--- a/drivers/iommu/iova.c
++++ b/drivers/iommu/iova.c
+@@ -32,6 +32,7 @@ static unsigned long iova_rcache_get(str
+ static void init_iova_rcaches(struct iova_domain *iovad);
+ static void free_iova_rcaches(struct iova_domain *iovad);
+ static void fq_destroy_all_entries(struct iova_domain *iovad);
++static void fq_flush_timeout(unsigned long data);
+
+ void
+ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
+@@ -61,7 +62,11 @@ static void free_iova_flush_queue(struct
+ if (!iovad->fq)
+ return;
+
++ if (timer_pending(&iovad->fq_timer))
++ del_timer(&iovad->fq_timer);
++
+ fq_destroy_all_entries(iovad);
++
+ free_percpu(iovad->fq);
+
+ iovad->fq = NULL;
+@@ -94,6 +99,9 @@ int init_iova_flush_queue(struct iova_do
+ spin_lock_init(&fq->lock);
+ }
+
++ setup_timer(&iovad->fq_timer, fq_flush_timeout, (unsigned long)iovad);
++ atomic_set(&iovad->fq_timer_on, 0);
++
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(init_iova_flush_queue);
+@@ -543,6 +551,25 @@ static void fq_destroy_all_entries(struc
+ }
+ }
+
++static void fq_flush_timeout(unsigned long data)
++{
++ struct iova_domain *iovad = (struct iova_domain *)data;
++ int cpu;
++
++ atomic_set(&iovad->fq_timer_on, 0);
++ iova_domain_flush(iovad);
++
++ for_each_possible_cpu(cpu) {
++ unsigned long flags;
++ struct iova_fq *fq;
++
++ fq = per_cpu_ptr(iovad->fq, cpu);
++ spin_lock_irqsave(&fq->lock, flags);
++ fq_ring_free(iovad, fq);
++ spin_unlock_irqrestore(&fq->lock, flags);
++ }
++}
++
+ void queue_iova(struct iova_domain *iovad,
+ unsigned long pfn, unsigned long pages,
+ unsigned long data)
+@@ -573,6 +600,11 @@ void queue_iova(struct iova_domain *iova
+ fq->entries[idx].counter = atomic64_read(&iovad->fq_flush_start_cnt);
+
+ spin_unlock_irqrestore(&fq->lock, flags);
++
++ if (atomic_cmpxchg(&iovad->fq_timer_on, 0, 1) == 0)
++ mod_timer(&iovad->fq_timer,
++ jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
++
+ put_cpu_ptr(iovad->fq);
+ }
+ EXPORT_SYMBOL_GPL(queue_iova);
+--- a/include/linux/iova.h
++++ b/include/linux/iova.h
+@@ -48,6 +48,9 @@ typedef void (* iova_entry_dtor)(unsigne
+ /* Number of entries per Flush Queue */
+ #define IOVA_FQ_SIZE 256
+
++/* Timeout (in ms) after which entries are flushed from the Flush-Queue */
++#define IOVA_FQ_TIMEOUT 10
++
+ /* Flush Queue entry for defered flushing */
+ struct iova_fq_entry {
+ unsigned long iova_pfn;
+@@ -86,6 +89,11 @@ struct iova_domain {
+
+ atomic64_t fq_flush_finish_cnt; /* Number of TLB flushes that
+ have been finished */
++
++ struct timer_list fq_timer; /* Timer to regularily empty the
++ flush-queues */
++ atomic_t fq_timer_on; /* 1 when timer is active, 0
++ when not */
+ };
+
+ static inline unsigned long iova_size(struct iova *iova)
diff --git a/patches.drivers/0005-iommu-vt-d-use-domain-instead-of-cache-fetching b/patches.drivers/0005-iommu-vt-d-use-domain-instead-of-cache-fetching
index 40d857cbb3..115d20e126 100644
--- a/patches.drivers/0005-iommu-vt-d-use-domain-instead-of-cache-fetching
+++ b/patches.drivers/0005-iommu-vt-d-use-domain-instead-of-cache-fetching
@@ -83,7 +83,7 @@ Signed-off-by: Joerg Roedel <jroedel@suse.de>
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
-@@ -1618,8 +1618,7 @@ static void iommu_flush_iotlb_psi(struct
+@@ -1600,8 +1600,7 @@ static void iommu_flush_iotlb_psi(struct
* flush. However, device IOTLB doesn't need to be flushed in this case.
*/
if (!cap_caching_mode(iommu->cap) || !map)
@@ -92,4 +92,4 @@ Signed-off-by: Joerg Roedel <jroedel@suse.de>
+ iommu_flush_dev_iotlb(domain, addr, mask);
}
- static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
+ static void iommu_flush_iova(struct iova_domain *iovad)
diff --git a/patches.drivers/0006-iommu-amd-make-use-of-iova-queue-flushing b/patches.drivers/0006-iommu-amd-make-use-of-iova-queue-flushing
new file mode 100644
index 0000000000..8d7d12de3c
--- /dev/null
+++ b/patches.drivers/0006-iommu-amd-make-use-of-iova-queue-flushing
@@ -0,0 +1,300 @@
+From: Joerg Roedel <jroedel@suse.de>
+Date: Thu, 10 Aug 2017 17:19:13 +0200
+Subject: iommu/amd: Make use of iova queue flushing
+Git-commit: 9003d6186321e22b19125721b6fb2aa390ff8be6
+Patch-mainline: v4.14-rc1
+References: bsc#1096790 bsc#1097034
+
+Rip out the implementation in the AMD IOMMU driver and use
+the one in the common iova code instead.
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+---
+ drivers/iommu/amd_iommu.c | 229 ++--------------------------------------------
+ 1 file changed, 9 insertions(+), 220 deletions(-)
+
+--- a/drivers/iommu/amd_iommu.c
++++ b/drivers/iommu/amd_iommu.c
+@@ -135,20 +135,7 @@ struct kmem_cache *amd_iommu_irq_cache;
+ static void update_domain(struct protection_domain *domain);
+ static int protection_domain_init(struct protection_domain *domain);
+ static void detach_device(struct device *dev);
+-
+-#define FLUSH_QUEUE_SIZE 256
+-
+-struct flush_queue_entry {
+- unsigned long iova_pfn;
+- unsigned long pages;
+- u64 counter; /* Flush counter when this entry was added to the queue */
+-};
+-
+-struct flush_queue {
+- struct flush_queue_entry *entries;
+- unsigned head, tail;
+- spinlock_t lock;
+-};
++static void iova_domain_flush_tlb(struct iova_domain *iovad);
+
+ /*
+ * Data container for a dma_ops specific protection domain
+@@ -159,36 +146,6 @@ struct dma_ops_domain {
+
+ /* IOVA RB-Tree */
+ struct iova_domain iovad;
+-
+- struct flush_queue __percpu *flush_queue;
+-
+- /*
+- * We need two counter here to be race-free wrt. IOTLB flushing and
+- * adding entries to the flush queue.
+- *
+- * The flush_start_cnt is incremented _before_ the IOTLB flush starts.
+- * New entries added to the flush ring-buffer get their 'counter' value
+- * from here. This way we can make sure that entries added to the queue
+- * (or other per-cpu queues of the same domain) while the TLB is about
+- * to be flushed are not considered to be flushed already.
+- */
+- atomic64_t flush_start_cnt;
+-
+- /*
+- * The flush_finish_cnt is incremented when an IOTLB flush is complete.
+- * This value is always smaller than flush_start_cnt. The queue_add
+- * function frees all IOVAs that have a counter value smaller than
+- * flush_finish_cnt. This makes sure that we only free IOVAs that are
+- * flushed out of the IOTLB of the domain.
+- */
+- atomic64_t flush_finish_cnt;
+-
+- /*
+- * Timer to make sure we don't keep IOVAs around unflushed
+- * for too long
+- */
+- struct timer_list flush_timer;
+- atomic_t flush_timer_on;
+ };
+
+ static struct iova_domain reserved_iova_ranges;
+@@ -1788,178 +1745,19 @@ static void free_gcr3_table(struct prote
+ free_page((unsigned long)domain->gcr3_tbl);
+ }
+
+-static void dma_ops_domain_free_flush_queue(struct dma_ops_domain *dom)
+-{
+- int cpu;
+-
+- for_each_possible_cpu(cpu) {
+- struct flush_queue *queue;
+-
+- queue = per_cpu_ptr(dom->flush_queue, cpu);
+- kfree(queue->entries);
+- }
+-
+- free_percpu(dom->flush_queue);
+-
+- dom->flush_queue = NULL;
+-}
+-
+-static int dma_ops_domain_alloc_flush_queue(struct dma_ops_domain *dom)
+-{
+- int cpu;
+-
+- atomic64_set(&dom->flush_start_cnt, 0);
+- atomic64_set(&dom->flush_finish_cnt, 0);
+-
+- dom->flush_queue = alloc_percpu(struct flush_queue);
+- if (!dom->flush_queue)
+- return -ENOMEM;
+-
+- /* First make sure everything is cleared */
+- for_each_possible_cpu(cpu) {
+- struct flush_queue *queue;
+-
+- queue = per_cpu_ptr(dom->flush_queue, cpu);
+- queue->head = 0;
+- queue->tail = 0;
+- queue->entries = NULL;
+- }
+-
+- /* Now start doing the allocation */
+- for_each_possible_cpu(cpu) {
+- struct flush_queue *queue;
+-
+- queue = per_cpu_ptr(dom->flush_queue, cpu);
+- queue->entries = kzalloc(FLUSH_QUEUE_SIZE * sizeof(*queue->entries),
+- GFP_KERNEL);
+- if (!queue->entries) {
+- dma_ops_domain_free_flush_queue(dom);
+- return -ENOMEM;
+- }
+-
+- spin_lock_init(&queue->lock);
+- }
+-
+- return 0;
+-}
+-
+ static void dma_ops_domain_flush_tlb(struct dma_ops_domain *dom)
+ {
+- atomic64_inc(&dom->flush_start_cnt);
+ domain_flush_tlb(&dom->domain);
+ domain_flush_complete(&dom->domain);
+- atomic64_inc(&dom->flush_finish_cnt);
+-}
+-
+-static inline bool queue_ring_full(struct flush_queue *queue)
+-{
+- assert_spin_locked(&queue->lock);
+-
+- return (((queue->tail + 1) % FLUSH_QUEUE_SIZE) == queue->head);
+-}
+-
+-#define queue_ring_for_each(i, q) \
+- for (i = (q)->head; i != (q)->tail; i = (i + 1) % FLUSH_QUEUE_SIZE)
+-
+-static inline unsigned queue_ring_add(struct flush_queue *queue)
+-{
+- unsigned idx = queue->tail;
+-
+- assert_spin_locked(&queue->lock);
+- queue->tail = (idx + 1) % FLUSH_QUEUE_SIZE;
+-
+- return idx;
+-}
+-
+-static inline void queue_ring_remove_head(struct flush_queue *queue)
+-{
+- assert_spin_locked(&queue->lock);
+- queue->head = (queue->head + 1) % FLUSH_QUEUE_SIZE;
+-}
+-
+-static void queue_ring_free_flushed(struct dma_ops_domain *dom,
+- struct flush_queue *queue)
+-{
+- u64 counter = atomic64_read(&dom->flush_finish_cnt);
+- int idx;
+-
+- queue_ring_for_each(idx, queue) {
+- /*
+- * This assumes that counter values in the ring-buffer are
+- * monotonously rising.
+- */
+- if (queue->entries[idx].counter >= counter)
+- break;
+-
+- free_iova_fast(&dom->iovad,
+- queue->entries[idx].iova_pfn,
+- queue->entries[idx].pages);
+-
+- queue_ring_remove_head(queue);
+- }
+-}
+-
+-static void queue_add(struct dma_ops_domain *dom,
+- unsigned long address, unsigned long pages)
+-{
+- struct flush_queue *queue;
+- unsigned long flags;
+- int idx;
+-
+- pages = __roundup_pow_of_two(pages);
+- address >>= PAGE_SHIFT;
+-
+- queue = get_cpu_ptr(dom->flush_queue);
+- spin_lock_irqsave(&queue->lock, flags);
+-
+- /*
+- * First remove the enries from the ring-buffer that are already
+- * flushed to make the below queue_ring_full() check less likely
+- */
+- queue_ring_free_flushed(dom, queue);
+-
+- /*
+- * When ring-queue is full, flush the entries from the IOTLB so
+- * that we can free all entries with queue_ring_free_flushed()
+- * below.
+- */
+- if (queue_ring_full(queue)) {
+- dma_ops_domain_flush_tlb(dom);
+- queue_ring_free_flushed(dom, queue);
+- }
+-
+- idx = queue_ring_add(queue);
+-
+- queue->entries[idx].iova_pfn = address;
+- queue->entries[idx].pages = pages;
+- queue->entries[idx].counter = atomic64_read(&dom->flush_start_cnt);
+-
+- spin_unlock_irqrestore(&queue->lock, flags);
+-
+- if (atomic_cmpxchg(&dom->flush_timer_on, 0, 1) == 0)
+- mod_timer(&dom->flush_timer, jiffies + msecs_to_jiffies(10));
+-
+- put_cpu_ptr(dom->flush_queue);
+ }
+
+-static void queue_flush_timeout(unsigned long data)
++static void iova_domain_flush_tlb(struct iova_domain *iovad)
+ {
+- struct dma_ops_domain *dom = (struct dma_ops_domain *)data;
+- int cpu;
++ struct dma_ops_domain *dom;
+
+- atomic_set(&dom->flush_timer_on, 0);
++ dom = container_of(iovad, struct dma_ops_domain, iovad);
+
+ dma_ops_domain_flush_tlb(dom);
+-
+- for_each_possible_cpu(cpu) {
+- struct flush_queue *queue;
+- unsigned long flags;
+-
+- queue = per_cpu_ptr(dom->flush_queue, cpu);
+- spin_lock_irqsave(&queue->lock, flags);
+- queue_ring_free_flushed(dom, queue);
+- spin_unlock_irqrestore(&queue->lock, flags);
+- }
+ }
+
+ /*
+@@ -1973,11 +1771,6 @@ static void dma_ops_domain_free(struct d
+
+ del_domain_from_list(&dom->domain);
+
+- if (timer_pending(&dom->flush_timer))
+- del_timer(&dom->flush_timer);
+-
+- dma_ops_domain_free_flush_queue(dom);
+-
+ put_iova_domain(&dom->iovad);
+
+ free_pagetable(&dom->domain);
+@@ -2013,16 +1806,11 @@ static struct dma_ops_domain *dma_ops_do
+ init_iova_domain(&dma_dom->iovad, PAGE_SIZE,
+ IOVA_START_PFN, DMA_32BIT_PFN);
+
+- /* Initialize reserved ranges */
+- copy_reserved_iova(&reserved_iova_ranges, &dma_dom->iovad);
+-
+- if (dma_ops_domain_alloc_flush_queue(dma_dom))
++ if (init_iova_flush_queue(&dma_dom->iovad, iova_domain_flush_tlb, NULL))
+ goto free_dma_dom;
+
+- setup_timer(&dma_dom->flush_timer, queue_flush_timeout,
+- (unsigned long)dma_dom);
+-
+- atomic_set(&dma_dom->flush_timer_on, 0);
++ /* Initialize reserved ranges */
++ copy_reserved_iova(&reserved_iova_ranges, &dma_dom->iovad);
+
+ add_domain_to_list(&dma_dom->domain);
+
+@@ -2619,7 +2407,8 @@ static void __unmap_single(struct dma_op
+ domain_flush_tlb(&dma_dom->domain);
+ domain_flush_complete(&dma_dom->domain);
+ } else {
+- queue_add(dma_dom, dma_addr, pages);
++ pages = __roundup_pow_of_two(pages);
++ queue_iova(&dma_dom->iovad, dma_addr >> PAGE_SHIFT, pages, 0);
+ }
+ }
+
diff --git a/patches.drivers/0007-iommu-vt-d-allow-to-flush-more-than-4gb-of-device-tlbs b/patches.drivers/0007-iommu-vt-d-allow-to-flush-more-than-4gb-of-device-tlbs
new file mode 100644
index 0000000000..5dd110aa64
--- /dev/null
+++ b/patches.drivers/0007-iommu-vt-d-allow-to-flush-more-than-4gb-of-device-tlbs
@@ -0,0 +1,27 @@
+From: Joerg Roedel <jroedel@suse.de>
+Date: Fri, 11 Aug 2017 11:42:46 +0200
+Subject: iommu/vt-d: Allow to flush more than 4GB of device TLBs
+Git-commit: c8acb28b331364b32a5c81dbfbdfc8475b2f1f27
+Patch-mainline: v4.14-rc1
+References: bsc#1096790 bsc#1097034
+
+The shift qi_flush_dev_iotlb() is done on an int, which
+limits the mask to 32 bits. Make the mask 64 bits wide so
+that more than 4GB of address range can be flushed at once.
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+---
+ drivers/iommu/dmar.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/iommu/dmar.c
++++ b/drivers/iommu/dmar.c
+@@ -1343,7 +1343,7 @@ void qi_flush_dev_iotlb(struct intel_iom
+
+ if (mask) {
+ BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
+- addr |= (1 << (VTD_PAGE_SHIFT + mask - 1)) - 1;
++ addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1;
+ desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
+ } else
+ desc.high = QI_DEV_IOTLB_ADDR(addr);
diff --git a/patches.drivers/0008-iommu-vt-d-make-use-of-iova-deferred-flushing b/patches.drivers/0008-iommu-vt-d-make-use-of-iova-deferred-flushing
new file mode 100644
index 0000000000..188ad329f7
--- /dev/null
+++ b/patches.drivers/0008-iommu-vt-d-make-use-of-iova-deferred-flushing
@@ -0,0 +1,300 @@
+From: Joerg Roedel <jroedel@suse.de>
+Date: Fri, 11 Aug 2017 11:40:10 +0200
+Subject: iommu/vt-d: Make use of iova deferred flushing
+Git-commit: 13cf01744608e1dc3f13dd316c95cb7a1fdaf740
+Patch-mainline: v4.14-rc1
+References: bsc#1096790 bsc#1097034
+
+Remove the deferred flushing implementation in the Intel
+VT-d driver and use the one from the common iova code
+instead.
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+---
+ drivers/iommu/intel-iommu.c | 197 +++++++++-----------------------------------
+ 1 file changed, 38 insertions(+), 159 deletions(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -458,31 +458,6 @@ static LIST_HEAD(dmar_rmrr_units);
+ #define for_each_rmrr_units(rmrr) \
+ list_for_each_entry(rmrr, &dmar_rmrr_units, list)
+
+-static void flush_unmaps_timeout(unsigned long data);
+-
+-struct deferred_flush_entry {
+- unsigned long iova_pfn;
+- unsigned long nrpages;
+- struct dmar_domain *domain;
+- struct page *freelist;
+-};
+-
+-#define HIGH_WATER_MARK 250
+-struct deferred_flush_table {
+- int next;
+- struct deferred_flush_entry entries[HIGH_WATER_MARK];
+-};
+-
+-struct deferred_flush_data {
+- spinlock_t lock;
+- int timer_on;
+- struct timer_list timer;
+- long size;
+- struct deferred_flush_table *tables;
+-};
+-
+-DEFINE_PER_CPU(struct deferred_flush_data, deferred_flush);
+-
+ /* bitmap for indexing intel_iommus */
+ static int g_num_of_iommus;
+
+@@ -1309,6 +1284,13 @@ static void dma_free_pagelist(struct pag
+ }
+ }
+
++static void iova_entry_free(unsigned long data)
++{
++ struct page *freelist = (struct page *)data;
++
++ dma_free_pagelist(freelist);
++}
++
+ /* iommu handling */
+ static int iommu_alloc_root_entry(struct intel_iommu *iommu)
+ {
+@@ -1622,6 +1604,25 @@ static void iommu_flush_iotlb_psi(struct
+ addr, mask);
+ }
+
++static void iommu_flush_iova(struct iova_domain *iovad)
++{
++ struct dmar_domain *domain;
++ int idx;
++
++ domain = container_of(iovad, struct dmar_domain, iovad);
++
++ for_each_domain_iommu(idx, domain) {
++ struct intel_iommu *iommu = g_iommus[idx];
++ u16 did = domain->iommu_did[iommu->seq_id];
++
++ iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
++
++ if (!cap_caching_mode(iommu->cap))
++ iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
++ 0, MAX_AGAW_PFN_WIDTH);
++ }
++}
++
+ static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
+ {
+ u32 pmen;
+@@ -1932,9 +1933,16 @@ static int domain_init(struct dmar_domai
+ {
+ int adjust_width, agaw;
+ unsigned long sagaw;
++ int err;
+
+ init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN,
+ DMA_32BIT_PFN);
++
++ err = init_iova_flush_queue(&domain->iovad,
++ iommu_flush_iova, iova_entry_free);
++ if (err)
++ return err;
++
+ domain_reserve_special_ranges(domain);
+
+ /* calculate AGAW */
+@@ -1986,14 +1994,6 @@ static void domain_exit(struct dmar_doma
+ if (!domain)
+ return;
+
+- /* Flush any lazy unmaps that may reference this domain */
+- if (!intel_iommu_strict) {
+- int cpu;
+-
+- for_each_possible_cpu(cpu)
+- flush_unmaps_timeout(cpu);
+- }
+-
+ /* Remove associated devices and clear attached or cached domains */
+ rcu_read_lock();
+ domain_remove_dev_info(domain);
+@@ -3206,7 +3206,7 @@ static int __init init_dmars(void)
+ bool copied_tables = false;
+ struct device *dev;
+ struct intel_iommu *iommu;
+- int i, ret, cpu;
++ int i, ret;
+
+ /*
+ * for each drhd
+@@ -3239,22 +3239,6 @@ static int __init init_dmars(void)
+ goto error;
+ }
+
+- for_each_possible_cpu(cpu) {
+- struct deferred_flush_data *dfd = per_cpu_ptr(&deferred_flush,
+- cpu);
+-
+- dfd->tables = kzalloc(g_num_of_iommus *
+- sizeof(struct deferred_flush_table),
+- GFP_KERNEL);
+- if (!dfd->tables) {
+- ret = -ENOMEM;
+- goto free_g_iommus;
+- }
+-
+- spin_lock_init(&dfd->lock);
+- setup_timer(&dfd->timer, flush_unmaps_timeout, cpu);
+- }
+-
+ for_each_active_iommu(iommu, drhd) {
+ g_iommus[iommu->seq_id] = iommu;
+
+@@ -3437,10 +3421,9 @@ free_iommu:
+ disable_dmar_iommu(iommu);
+ free_dmar_iommu(iommu);
+ }
+-free_g_iommus:
+- for_each_possible_cpu(cpu)
+- kfree(per_cpu_ptr(&deferred_flush, cpu)->tables);
++
+ kfree(g_iommus);
++
+ error:
+ return ret;
+ }
+@@ -3657,114 +3640,6 @@ static dma_addr_t intel_map_page(struct
+ dir, *dev->dma_mask);
+ }
+
+-static void flush_unmaps(struct deferred_flush_data *flush_data)
+-{
+- int i, j;
+-
+- flush_data->timer_on = 0;
+-
+- /* just flush them all */
+- for (i = 0; i < g_num_of_iommus; i++) {
+- struct intel_iommu *iommu = g_iommus[i];
+- struct deferred_flush_table *flush_table =
+- &flush_data->tables[i];
+- if (!iommu)
+- continue;
+-
+- if (!flush_table->next)
+- continue;
+-
+- /* In caching mode, global flushes turn emulation expensive */
+- if (!cap_caching_mode(iommu->cap))
+- iommu->flush.flush_iotlb(iommu, 0, 0, 0,
+- DMA_TLB_GLOBAL_FLUSH);
+- for (j = 0; j < flush_table->next; j++) {
+- unsigned long mask;
+- struct deferred_flush_entry *entry =
+- &flush_table->entries[j];
+- unsigned long iova_pfn = entry->iova_pfn;
+- unsigned long nrpages = entry->nrpages;
+- struct dmar_domain *domain = entry->domain;
+- struct page *freelist = entry->freelist;
+-
+- /* On real hardware multiple invalidations are expensive */
+- if (cap_caching_mode(iommu->cap))
+- iommu_flush_iotlb_psi(iommu, domain,
+- mm_to_dma_pfn(iova_pfn),
+- nrpages, !freelist, 0);
+- else {
+- mask = ilog2(nrpages);
+- iommu_flush_dev_iotlb(domain,
+- (uint64_t)iova_pfn << PAGE_SHIFT, mask);
+- }
+- free_iova_fast(&domain->iovad, iova_pfn, nrpages);
+- if (freelist)
+- dma_free_pagelist(freelist);
+- }
+- flush_table->next = 0;
+- }
+-
+- flush_data->size = 0;
+-}
+-
+-static void flush_unmaps_timeout(unsigned long cpuid)
+-{
+- struct deferred_flush_data *flush_data = per_cpu_ptr(&deferred_flush, cpuid);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&flush_data->lock, flags);
+- flush_unmaps(flush_data);
+- spin_unlock_irqrestore(&flush_data->lock, flags);
+-}
+-
+-static void add_unmap(struct dmar_domain *dom, unsigned long iova_pfn,
+- unsigned long nrpages, struct page *freelist)
+-{
+- unsigned long flags;
+- int entry_id, iommu_id;
+- struct intel_iommu *iommu;
+- struct deferred_flush_entry *entry;
+- struct deferred_flush_data *flush_data;
+- unsigned int cpuid;
+-
+- cpuid = get_cpu();
+- flush_data = per_cpu_ptr(&deferred_flush, cpuid);
+-
+- /* Flush all CPUs' entries to avoid deferring too much. If
+- * this becomes a bottleneck, can just flush us, and rely on
+- * flush timer for the rest.
+- */
+- if (flush_data->size == HIGH_WATER_MARK) {
+- int cpu;
+-
+- for_each_online_cpu(cpu)
+- flush_unmaps_timeout(cpu);
+- }
+-
+- spin_lock_irqsave(&flush_data->lock, flags);
+-
+- iommu = domain_get_iommu(dom);
+- iommu_id = iommu->seq_id;
+-
+- entry_id = flush_data->tables[iommu_id].next;
+- ++(flush_data->tables[iommu_id].next);
+-
+- entry = &flush_data->tables[iommu_id].entries[entry_id];
+- entry->domain = dom;
+- entry->iova_pfn = iova_pfn;
+- entry->nrpages = nrpages;
+- entry->freelist = freelist;
+-
+- if (!flush_data->timer_on) {
+- mod_timer(&flush_data->timer, jiffies + msecs_to_jiffies(10));
+- flush_data->timer_on = 1;
+- }
+- flush_data->size++;
+- spin_unlock_irqrestore(&flush_data->lock, flags);
+-
+- put_cpu();
+-}
+-
+ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
+ {
+ struct dmar_domain *domain;
+@@ -3800,7 +3675,8 @@ static void intel_unmap(struct device *d
+ free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
+ dma_free_pagelist(freelist);
+ } else {
+- add_unmap(domain, iova_pfn, nrpages, freelist);
++ queue_iova(&domain->iovad, iova_pfn, nrpages,
++ (unsigned long)freelist);
+ /*
+ * queue up the release of the unmap to save the 1/6th of the
+ * cpu used up by the iotlb flush operation...
+@@ -4734,7 +4610,6 @@ static void free_all_cpu_cached_iovas(un
+ static int intel_iommu_cpu_dead(unsigned int cpu)
+ {
+ free_all_cpu_cached_iovas(cpu);
+- flush_unmaps_timeout(cpu);
+ return 0;
+ }
+
diff --git a/patches.drivers/kvm-svm-add-pause-filter-threshold b/patches.drivers/kvm-svm-add-pause-filter-threshold
new file mode 100644
index 0000000000..f856c03d9a
--- /dev/null
+++ b/patches.drivers/kvm-svm-add-pause-filter-threshold
@@ -0,0 +1,64 @@
+From: Babu Moger <babu.moger@amd.com>
+Date: Fri, 16 Mar 2018 16:37:25 -0400
+Subject: KVM: SVM: Add pause filter threshold
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Git-commit: 1d8fb44a728b7a34604307976a7d2a003bc84f16
+Patch-mainline: v3.20-rc1
+References: fate#325605
+
+This patch adds the support for pause filtering threshold. This feature
+support is indicated by CPUID Fn8000_000A_EDX. See AMD APM Vol 2 Section
+15.14.4 Pause Intercept Filtering for more details.
+
+In this mode, a 16-bit pause filter threshold field is added in VMCB.
+The threshold value is a cycle count that is used to reset the pause
+counter. As with simple pause filtering, VMRUN loads the pause count
+value from VMCB into an internal counter. Then, on each pause instruction
+the hardware checks the elapsed number of cycles since the most recent
+pause instruction against the pause Filter Threshold. If the elapsed cycle
+count is greater than the pause filter threshold, then the internal pause
+count is reloaded from VMCB and execution continues. If the elapsed cycle
+count is less than the pause filter threshold, then the internal pause
+count is decremented. If the count value is less than zero and pause
+intercept is enabled, a #VMEXIT is triggered. If advanced pause filtering
+is supported and pause filter threshold field is set to zero, the filter
+will operate in the simpler, count only mode.
+
+Signed-off-by: Babu Moger <babu.moger@amd.com>
+Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
+Acked-by: Joerg Roedel <jroedel@suse.de>
+---
+ arch/x86/include/asm/svm.h | 3 ++-
+ arch/x86/kvm/svm.c | 2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
+index 0487ac054870..93b462e48067 100644
+--- a/arch/x86/include/asm/svm.h
++++ b/arch/x86/include/asm/svm.h
+@@ -60,7 +60,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
+ u32 intercept_dr;
+ u32 intercept_exceptions;
+ u64 intercept;
+- u8 reserved_1[42];
++ u8 reserved_1[40];
++ u16 pause_filter_thresh;
+ u16 pause_filter_count;
+ u64 iopm_base_pa;
+ u64 msrpm_base_pa;
+diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
+index 2d175c36ffa2..282aeff5d100 100644
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -4662,6 +4662,8 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
+ pr_err("%-20s%08x\n", "exceptions:", control->intercept_exceptions);
+ pr_err("%-20s%016llx\n", "intercepts:", control->intercept);
+ pr_err("%-20s%d\n", "pause filter count:", control->pause_filter_count);
++ pr_err("%-20s%d\n", "pause filter threshold:",
++ control->pause_filter_thresh);
+ pr_err("%-20s%016llx\n", "iopm_base_pa:", control->iopm_base_pa);
+ pr_err("%-20s%016llx\n", "msrpm_base_pa:", control->msrpm_base_pa);
+ pr_err("%-20s%016llx\n", "tsc_offset:", control->tsc_offset);
+
diff --git a/patches.drivers/kvm-svm-implement-pause-loop-exit-logic-in-svm b/patches.drivers/kvm-svm-implement-pause-loop-exit-logic-in-svm
new file mode 100644
index 0000000000..334e8becef
--- /dev/null
+++ b/patches.drivers/kvm-svm-implement-pause-loop-exit-logic-in-svm
@@ -0,0 +1,191 @@
+From: Babu Moger <babu.moger@amd.com>
+Date: Fri, 16 Mar 2018 16:37:26 -0400
+Subject: KVM: SVM: Implement pause loop exit logic in SVM
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Git-commit: 8566ac8b8e7cac5814fb744ff5159d1797a1a6bd
+Patch-mainline: v3.20-rc1
+References: fate#325605
+
+Bring the PLE(pause loop exit) logic to AMD svm driver.
+
+While testing, we found this helping in situations where numerous
+pauses are generated. Without these patches we could see continuos
+VMEXITS due to pause interceptions. Tested it on AMD EPYC server with
+boot parameter idle=poll on a VM with 32 vcpus to simulate extensive
+pause behaviour. Here are VMEXITS in 10 seconds interval.
+
+Pauses 810199 504
+Total 882184 325415
+
+Signed-off-by: Babu Moger <babu.moger@amd.com>
+[Prevented the window from dropping below the initial value. - Radim]
+Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
+Acked-by: Joerg Roedel <jroedel@suse.de>
+---
+ arch/x86/kvm/svm.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++--
+ arch/x86/kvm/x86.h | 2 +
+ 2 files changed, 105 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -275,6 +275,54 @@ static bool npt_enabled = true;
+ static bool npt_enabled;
+ #endif
+
++/*
++ * These 2 parameters are used to config the controls for Pause-Loop Exiting:
++ * pause_filter_count: On processors that support Pause filtering(indicated
++ * by CPUID Fn8000_000A_EDX), the VMCB provides a 16 bit pause filter
++ * count value. On VMRUN this value is loaded into an internal counter.
++ * Each time a pause instruction is executed, this counter is decremented
++ * until it reaches zero at which time a #VMEXIT is generated if pause
++ * intercept is enabled. Refer to AMD APM Vol 2 Section 15.14.4 Pause
++ * Intercept Filtering for more details.
++ * This also indicate if ple logic enabled.
++ *
++ * pause_filter_thresh: In addition, some processor families support advanced
++ * pause filtering (indicated by CPUID Fn8000_000A_EDX) upper bound on
++ * the amount of time a guest is allowed to execute in a pause loop.
++ * In this mode, a 16-bit pause filter threshold field is added in the
++ * VMCB. The threshold value is a cycle count that is used to reset the
++ * pause counter. As with simple pause filtering, VMRUN loads the pause
++ * count value from VMCB into an internal counter. Then, on each pause
++ * instruction the hardware checks the elapsed number of cycles since
++ * the most recent pause instruction against the pause filter threshold.
++ * If the elapsed cycle count is greater than the pause filter threshold,
++ * then the internal pause count is reloaded from the VMCB and execution
++ * continues. If the elapsed cycle count is less than the pause filter
++ * threshold, then the internal pause count is decremented. If the count
++ * value is less than zero and PAUSE intercept is enabled, a #VMEXIT is
++ * triggered. If advanced pause filtering is supported and pause filter
++ * threshold field is set to zero, the filter will operate in the simpler,
++ * count only mode.
++ */
++
++static unsigned short pause_filter_thresh = KVM_DEFAULT_PLE_GAP;
++module_param(pause_filter_thresh, ushort, 0444);
++
++static unsigned short pause_filter_count = KVM_SVM_DEFAULT_PLE_WINDOW;
++module_param(pause_filter_count, ushort, 0444);
++
++/* Default doubles per-vcpu window every exit. */
++static unsigned short pause_filter_count_grow = KVM_DEFAULT_PLE_WINDOW_GROW;
++module_param(pause_filter_count_grow, ushort, 0444);
++
++/* Default resets per-vcpu window every exit to pause_filter_count. */
++static unsigned short pause_filter_count_shrink = KVM_DEFAULT_PLE_WINDOW_SHRINK;
++module_param(pause_filter_count_shrink, ushort, 0444);
++
++/* Default is to compute the maximum so we can never overflow. */
++static unsigned short pause_filter_count_max = KVM_SVM_DEFAULT_PLE_WINDOW_MAX;
++module_param(pause_filter_count_max, ushort, 0444);
++
+ /* allow nested paging (virtualized MMU) for all guests */
+ static int npt = true;
+ module_param(npt, int, S_IRUGO);
+@@ -1169,6 +1217,42 @@ err:
+ return rc;
+ }
+
++static void grow_ple_window(struct kvm_vcpu *vcpu)
++{
++ struct vcpu_svm *svm = to_svm(vcpu);
++ struct vmcb_control_area *control = &svm->vmcb->control;
++ int old = control->pause_filter_count;
++
++ control->pause_filter_count = __grow_ple_window(old,
++ pause_filter_count,
++ pause_filter_count_grow,
++ pause_filter_count_max);
++
++ if (control->pause_filter_count != old)
++ mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
++
++ trace_kvm_ple_window_grow(vcpu->vcpu_id,
++ control->pause_filter_count, old);
++}
++
++static void shrink_ple_window(struct kvm_vcpu *vcpu)
++{
++ struct vcpu_svm *svm = to_svm(vcpu);
++ struct vmcb_control_area *control = &svm->vmcb->control;
++ int old = control->pause_filter_count;
++
++ control->pause_filter_count =
++ __shrink_ple_window(old,
++ pause_filter_count,
++ pause_filter_count_shrink,
++ pause_filter_count);
++ if (control->pause_filter_count != old)
++ mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
++
++ trace_kvm_ple_window_shrink(vcpu->vcpu_id,
++ control->pause_filter_count, old);
++}
++
+ static __init int svm_hardware_setup(void)
+ {
+ int cpu;
+@@ -1199,6 +1283,14 @@ static __init int svm_hardware_setup(voi
+ kvm_tsc_scaling_ratio_frac_bits = 32;
+ }
+
++ /* Check for pause filtering support */
++ if (!boot_cpu_has(X86_FEATURE_PAUSEFILTER)) {
++ pause_filter_count = 0;
++ pause_filter_thresh = 0;
++ } else if (!boot_cpu_has(X86_FEATURE_PFTHRESHOLD)) {
++ pause_filter_thresh = 0;
++ }
++
+ if (nested) {
+ printk(KERN_INFO "kvm: Nested Virtualization enabled\n");
+ kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE);
+@@ -1445,9 +1537,13 @@ static void init_vmcb(struct vcpu_svm *s
+ svm->nested.vmcb = 0;
+ svm->vcpu.arch.hflags = 0;
+
+- if (boot_cpu_has(X86_FEATURE_PAUSEFILTER)) {
+- control->pause_filter_count = 3000;
++ if (pause_filter_count) {
++ control->pause_filter_count = pause_filter_count;
++ if (pause_filter_thresh)
++ control->pause_filter_thresh = pause_filter_thresh;
+ set_intercept(svm, INTERCEPT_PAUSE);
++ } else {
++ clr_intercept(svm, INTERCEPT_PAUSE);
+ }
+
+ if (kvm_vcpu_apicv_active(&svm->vcpu))
+@@ -4188,6 +4284,9 @@ static int pause_interception(struct vcp
+ struct kvm_vcpu *vcpu = &svm->vcpu;
+ bool in_kernel = (svm_get_cpl(vcpu) == 0);
+
++ if (pause_filter_thresh)
++ grow_ple_window(vcpu);
++
+ kvm_vcpu_on_spin(vcpu, in_kernel);
+ return 1;
+ }
+@@ -5873,6 +5972,8 @@ static void svm_handle_external_intr(str
+
+ static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
+ {
++ if (pause_filter_thresh)
++ shrink_ple_window(vcpu);
+ }
+
+ static inline void avic_post_state_restore(struct kvm_vcpu *vcpu)
+--- a/arch/x86/kvm/x86.h
++++ b/arch/x86/kvm/x86.h
+@@ -12,6 +12,8 @@
+ #define KVM_DEFAULT_PLE_WINDOW_GROW 2
+ #define KVM_DEFAULT_PLE_WINDOW_SHRINK 0
+ #define KVM_VMX_DEFAULT_PLE_WINDOW_MAX UINT_MAX
++#define KVM_SVM_DEFAULT_PLE_WINDOW_MAX USHRT_MAX
++#define KVM_SVM_DEFAULT_PLE_WINDOW 3000
+
+ static inline unsigned int __grow_ple_window(unsigned int val,
+ unsigned int base, unsigned int modifier, unsigned int max)
diff --git a/patches.drivers/kvm-vmx-bring-the-common-code-to-header-file b/patches.drivers/kvm-vmx-bring-the-common-code-to-header-file
new file mode 100644
index 0000000000..fd84fdc5f0
--- /dev/null
+++ b/patches.drivers/kvm-vmx-bring-the-common-code-to-header-file
@@ -0,0 +1,159 @@
+From: Babu Moger <babu.moger@amd.com>
+Date: Fri, 16 Mar 2018 16:37:24 -0400
+Subject: KVM: VMX: Bring the common code to header file
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Git-commit: c8e88717cfc6b36bedea22368d97667446318291
+Patch-mainline: v3.20-rc1
+References: fate#325605
+
+This patch brings some of the code from vmx to x86.h header file. Now, we
+can share this code between vmx and svm. Modified couple functions to make
+it common.
+
+Signed-off-by: Babu Moger <babu.moger@amd.com>
+Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
+Acked-by: Joerg Roedel <jroedel@suse.de>
+---
+ arch/x86/kvm/vmx.c | 51 +++++++++------------------------------------------
+ arch/x86/kvm/x86.h | 36 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 45 insertions(+), 42 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
+index 7a92e2e1ea2e..48d93d8cb883 100644
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -168,24 +168,17 @@ module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
+ * Time is measured based on a counter that runs at the same rate as the TSC,
+ * refer SDM volume 3b section 21.6.13 & 22.1.3.
+ */
+-#define KVM_VMX_DEFAULT_PLE_GAP 128
+-#define KVM_VMX_DEFAULT_PLE_WINDOW 4096
+-#define KVM_VMX_DEFAULT_PLE_WINDOW_GROW 2
+-#define KVM_VMX_DEFAULT_PLE_WINDOW_SHRINK 0
+-#define KVM_VMX_DEFAULT_PLE_WINDOW_MAX UINT_MAX
+-
+-static unsigned int ple_gap = KVM_VMX_DEFAULT_PLE_GAP;
+-module_param(ple_gap, uint, 0444);
++static unsigned int ple_gap = KVM_DEFAULT_PLE_GAP;
+
+ static unsigned int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
+ module_param(ple_window, uint, 0444);
+
+ /* Default doubles per-vcpu window every exit. */
+-static unsigned int ple_window_grow = KVM_VMX_DEFAULT_PLE_WINDOW_GROW;
++static unsigned int ple_window_grow = KVM_DEFAULT_PLE_WINDOW_GROW;
+ module_param(ple_window_grow, uint, 0444);
+
+ /* Default resets per-vcpu window every exit to ple_window. */
+-static unsigned int ple_window_shrink = KVM_VMX_DEFAULT_PLE_WINDOW_SHRINK;
++static unsigned int ple_window_shrink = KVM_DEFAULT_PLE_WINDOW_SHRINK;
+ module_param(ple_window_shrink, uint, 0444);
+
+ /* Default is to compute the maximum so we can never overflow. */
+@@ -6982,41 +6975,14 @@ out:
+ return ret;
+ }
+
+-static unsigned int __grow_ple_window(unsigned int val)
+-{
+- u64 ret = val;
+-
+- if (ple_window_grow < 1)
+- return ple_window;
+-
+- if (ple_window_grow < ple_window)
+- ret *= ple_window_grow;
+- else
+- ret += ple_window_grow;
+-
+- return min(ret, (u64)ple_window_max);
+-}
+-
+-static unsigned int __shrink_ple_window(unsigned int val,
+- unsigned int modifier, unsigned int minimum)
+-{
+- if (modifier < 1)
+- return ple_window;
+-
+- if (modifier < ple_window)
+- val /= modifier;
+- else
+- val -= modifier;
+-
+- return max(val, minimum);
+-}
+-
+ static void grow_ple_window(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int old = vmx->ple_window;
+
+- vmx->ple_window = __grow_ple_window(old);
++ vmx->ple_window = __grow_ple_window(old, ple_window,
++ ple_window_grow,
++ ple_window_max);
+
+ if (vmx->ple_window != old)
+ vmx->ple_window_dirty = true;
+@@ -7029,8 +6995,9 @@ static void shrink_ple_window(struct kvm_vcpu *vcpu)
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int old = vmx->ple_window;
+
+- vmx->ple_window = __shrink_ple_window(old,
+- ple_window_shrink, ple_window);
++ vmx->ple_window = __shrink_ple_window(old, ple_window,
++ ple_window_shrink,
++ ple_window);
+
+ if (vmx->ple_window != old)
+ vmx->ple_window_dirty = true;
+diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
+index 35efd567a676..0804722b809e 100644
+--- a/arch/x86/kvm/x86.h
++++ b/arch/x86/kvm/x86.h
+@@ -6,6 +6,42 @@
+ #include <asm/pvclock.h>
+ #include "kvm_cache_regs.h"
+
++#define KVM_DEFAULT_PLE_GAP 128
++#define KVM_VMX_DEFAULT_PLE_WINDOW 4096
++#define KVM_DEFAULT_PLE_WINDOW_GROW 2
++#define KVM_DEFAULT_PLE_WINDOW_SHRINK 0
++#define KVM_VMX_DEFAULT_PLE_WINDOW_MAX UINT_MAX
++
++static inline unsigned int __grow_ple_window(unsigned int val,
++ unsigned int base, unsigned int modifier, unsigned int max)
++{
++ u64 ret = val;
++
++ if (modifier < 1)
++ return base;
++
++ if (modifier < base)
++ ret *= modifier;
++ else
++ ret += modifier;
++
++ return min(ret, (u64)max);
++}
++
++static inline unsigned int __shrink_ple_window(unsigned int val,
++ unsigned int base, unsigned int modifier, unsigned int min)
++{
++ if (modifier < 1)
++ return base;
++
++ if (modifier < base)
++ val /= modifier;
++ else
++ val -= modifier;
++
++ return max(val, min);
++}
++
+ #define MSR_IA32_CR_PAT_DEFAULT 0x0007040600070406ULL
+
+ static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu)
+
diff --git a/patches.drivers/kvm-vmx-fix-the-module-parameters-for-vmx b/patches.drivers/kvm-vmx-fix-the-module-parameters-for-vmx
new file mode 100644
index 0000000000..866aa94929
--- /dev/null
+++ b/patches.drivers/kvm-vmx-fix-the-module-parameters-for-vmx
@@ -0,0 +1,85 @@
+From: Babu Moger <babu.moger@amd.com>
+Date: Fri, 16 Mar 2018 16:37:22 -0400
+Subject: KVM: VMX: Fix the module parameters for vmx
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Git-commit: 7fbc85a5fb2b018d7030cba53f4c42ab90304acd
+Patch-mainline: v3.20-rc1
+References: fate#325605
+
+The vmx module parameters are supposed to be unsigned variants.
+
+Also fixed the checkpatch errors like the one below.
+
+WARNING: Symbolic permissions 'S_IRUGO' are not preferred. Consider using octal permissions '0444'.
++module_param(ple_gap, uint, S_IRUGO);
+
+Signed-off-by: Babu Moger <babu.moger@amd.com>
+[Expanded uint to unsigned int in code. - Radim]
+Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
+Acked-by: Joerg Roedel <jroedel@suse.de>
+---
+ arch/x86/kvm/vmx.c | 27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
+index 0e5510ebd3f2..4eb252b13121 100644
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -175,24 +175,24 @@ module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
+ #define KVM_VMX_DEFAULT_PLE_WINDOW_MAX \
+ INT_MAX / KVM_VMX_DEFAULT_PLE_WINDOW_GROW
+
+-static int ple_gap = KVM_VMX_DEFAULT_PLE_GAP;
+-module_param(ple_gap, int, S_IRUGO);
++static unsigned int ple_gap = KVM_VMX_DEFAULT_PLE_GAP;
++module_param(ple_gap, uint, 0444);
+
+-static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
+-module_param(ple_window, int, S_IRUGO);
++static unsigned int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
++module_param(ple_window, uint, 0444);
+
+ /* Default doubles per-vcpu window every exit. */
+-static int ple_window_grow = KVM_VMX_DEFAULT_PLE_WINDOW_GROW;
+-module_param(ple_window_grow, int, S_IRUGO);
++static unsigned int ple_window_grow = KVM_VMX_DEFAULT_PLE_WINDOW_GROW;
++module_param(ple_window_grow, uint, 0444);
+
+ /* Default resets per-vcpu window every exit to ple_window. */
+-static int ple_window_shrink = KVM_VMX_DEFAULT_PLE_WINDOW_SHRINK;
+-module_param(ple_window_shrink, int, S_IRUGO);
++static unsigned int ple_window_shrink = KVM_VMX_DEFAULT_PLE_WINDOW_SHRINK;
++module_param(ple_window_shrink, uint, 0444);
+
+ /* Default is to compute the maximum so we can never overflow. */
+-static int ple_window_actual_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
+-static int ple_window_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
+-module_param(ple_window_max, int, S_IRUGO);
++static unsigned int ple_window_actual_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
++static unsigned int ple_window_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
++module_param(ple_window_max, uint, 0444);
+
+ extern const ulong vmx_return;
+
+@@ -6984,7 +6984,7 @@ out:
+ return ret;
+ }
+
+-static int __grow_ple_window(int val)
++static unsigned int __grow_ple_window(unsigned int val)
+ {
+ if (ple_window_grow < 1)
+ return ple_window;
+@@ -6999,7 +6999,8 @@ static int __grow_ple_window(int val)
+ return val;
+ }
+
+-static int __shrink_ple_window(int val, int modifier, int minimum)
++static unsigned int __shrink_ple_window(unsigned int val,
++ unsigned int modifier, unsigned int minimum)
+ {
+ if (modifier < 1)
+ return ple_window;
+
diff --git a/patches.drivers/kvm-vmx-remove-ple_window_actual_max b/patches.drivers/kvm-vmx-remove-ple_window_actual_max
new file mode 100644
index 0000000000..a882bd43c4
--- /dev/null
+++ b/patches.drivers/kvm-vmx-remove-ple_window_actual_max
@@ -0,0 +1,102 @@
+From: Babu Moger <babu.moger@amd.com>
+Date: Fri, 16 Mar 2018 16:37:23 -0400
+Subject: KVM: VMX: Remove ple_window_actual_max
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Git-commit: 18abdc3425aa546424672d3b1f932ecc55132368
+Patch-mainline: v3.20-rc1
+References: fate#325605
+
+Get rid of ple_window_actual_max, because its benefits are really
+minuscule and the logic is complicated.
+
+The overflows(and underflow) are controlled in __ple_window_grow
+and _ple_window_shrink respectively.
+
+Suggested-by: Radim Krčmář <rkrcmar@redhat.com>
+Signed-off-by: Babu Moger <babu.moger@amd.com>
+[Fixed potential wraparound and change the max to UINT_MAX. - Radim]
+Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
+Acked-by: Joerg Roedel <jroedel@suse.de>
+---
+ arch/x86/kvm/vmx.c | 31 ++++++-------------------------
+ 1 file changed, 6 insertions(+), 25 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
+index 4eb252b13121..7a92e2e1ea2e 100644
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -172,8 +172,7 @@ module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
+ #define KVM_VMX_DEFAULT_PLE_WINDOW 4096
+ #define KVM_VMX_DEFAULT_PLE_WINDOW_GROW 2
+ #define KVM_VMX_DEFAULT_PLE_WINDOW_SHRINK 0
+-#define KVM_VMX_DEFAULT_PLE_WINDOW_MAX \
+- INT_MAX / KVM_VMX_DEFAULT_PLE_WINDOW_GROW
++#define KVM_VMX_DEFAULT_PLE_WINDOW_MAX UINT_MAX
+
+ static unsigned int ple_gap = KVM_VMX_DEFAULT_PLE_GAP;
+ module_param(ple_gap, uint, 0444);
+@@ -190,7 +189,6 @@ static unsigned int ple_window_shrink = KVM_VMX_DEFAULT_PLE_WINDOW_SHRINK;
+ module_param(ple_window_shrink, uint, 0444);
+
+ /* Default is to compute the maximum so we can never overflow. */
+-static unsigned int ple_window_actual_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
+ static unsigned int ple_window_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
+ module_param(ple_window_max, uint, 0444);
+
+@@ -6986,17 +6984,17 @@ out:
+
+ static unsigned int __grow_ple_window(unsigned int val)
+ {
++ u64 ret = val;
++
+ if (ple_window_grow < 1)
+ return ple_window;
+
+- val = min(val, ple_window_actual_max);
+-
+ if (ple_window_grow < ple_window)
+- val *= ple_window_grow;
++ ret *= ple_window_grow;
+ else
+- val += ple_window_grow;
++ ret += ple_window_grow;
+
+- return val;
++ return min(ret, (u64)ple_window_max);
+ }
+
+ static unsigned int __shrink_ple_window(unsigned int val,
+@@ -7041,21 +7039,6 @@ static void shrink_ple_window(struct kvm_vcpu *vcpu)
+ }
+
+ /*
+- * ple_window_actual_max is computed to be one grow_ple_window() below
+- * ple_window_max. (See __grow_ple_window for the reason.)
+- * This prevents overflows, because ple_window_max is int.
+- * ple_window_max effectively rounded down to a multiple of ple_window_grow in
+- * this process.
+- * ple_window_max is also prevented from setting vmx->ple_window < ple_window.
+- */
+-static void update_ple_window_actual_max(void)
+-{
+- ple_window_actual_max =
+- __shrink_ple_window(max(ple_window_max, ple_window),
+- ple_window_grow, INT_MIN);
+-}
+-
+-/*
+ * Handler for POSTED_INTERRUPT_WAKEUP_VECTOR.
+ */
+ static void wakeup_handler(void)
+@@ -7175,8 +7158,6 @@ static __init int hardware_setup(void)
+ else
+ kvm_disable_tdp();
+
+- update_ple_window_actual_max();
+-
+ /*
+ * Only enable PML when hardware supports PML feature, and both EPT
+ * and EPT A/D bit features are enabled -- PML depends on them to work.
+
diff --git a/patches.suse/0001-iommu-vt-d-Fix-race-condition-in-add_unmap.patch b/patches.suse/0001-iommu-vt-d-Fix-race-condition-in-add_unmap.patch
deleted file mode 100644
index 655f5bb8ea..0000000000
--- a/patches.suse/0001-iommu-vt-d-Fix-race-condition-in-add_unmap.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From: Joerg Roedel <jroedel@suse.de>
-Date: Fri, 15 Jun 2018 15:09:43 +0200
-Subject: iommu/vt-d: Fix race condition in add_unmap()
-Patch-mainline: No, upstream switched to a different implementation
-References: bsc#1096790, bsc#1097034
-
-The high-water-mark needs to be checked again after the lock
-is taken, otherwise flush_data->size might grow larger than
-the high-water-mark and we write behind the array limits of
-the deferred flush tables.
-
-Signed-off-by: Joerg Roedel <jroedel@suse.de>
----
- drivers/iommu/intel-iommu.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
-index 880830d..919ede7 100644
---- a/drivers/iommu/intel-iommu.c
-+++ b/drivers/iommu/intel-iommu.c
-@@ -3742,6 +3742,10 @@ static void add_unmap(struct dmar_domain *dom, unsigned long iova_pfn,
-
- spin_lock_irqsave(&flush_data->lock, flags);
-
-+ /* Need to check that again after we own the lock */
-+ if (unlikely(flush_data->size == HIGH_WATER_MARK))
-+ flush_unmaps(flush_data);
-+
- iommu = domain_get_iommu(dom);
- iommu_id = iommu->seq_id;
-
---
-2.12.3
-
diff --git a/series.conf b/series.conf
index 8ca7530aef..70ad46a456 100644
--- a/series.conf
+++ b/series.conf
@@ -6417,6 +6417,14 @@
patches.drivers/0001-power-supply-Fix-power_supply_am_i_supplied-to-retur.patch
patches.drivers/0013-iommu-rockchip-add-multi-irqs-support.patch
patches.drivers/0014-iommu-rockchip-ignore-isp-mmu-reset-operation.patch
+ patches.drivers/0001-iommu-iova-add-flush-queue-data-structures
+ patches.drivers/0002-iommu-iova-implement-flush-queue-ring-buffer
+ patches.drivers/0003-iommu-iova-add-flush-counters-to-flush-queue-implementation
+ patches.drivers/0004-iommu-iova-add-locking-to-flush-queues
+ patches.drivers/0005-iommu-iova-add-flush-timer
+ patches.drivers/0006-iommu-amd-make-use-of-iova-queue-flushing
+ patches.drivers/0007-iommu-vt-d-allow-to-flush-more-than-4gb-of-device-tlbs
+ patches.drivers/0008-iommu-vt-d-make-use-of-iova-deferred-flushing
patches.drivers/iommu-vt-d-avoid-calling-virt_to_phys-on-null-pointer
patches.drivers/0001-iommu-amd-detect-pre-enabled-translation
patches.drivers/0002-iommu-amd-add-several-helper-functions
@@ -13672,6 +13680,11 @@
patches.arch/s390-report-spectre-mitigation-via-syslog.patch
patches.arch/s390-add-sysfs-attributes-for-spectre.patch
patches.drivers/0007-KVM-arm64-Fix-HYP-idmap-unmap-when-using-52bit-PA.patch
+ patches.drivers/kvm-vmx-fix-the-module-parameters-for-vmx
+ patches.drivers/kvm-vmx-remove-ple_window_actual_max
+ patches.drivers/kvm-vmx-bring-the-common-code-to-header-file
+ patches.drivers/kvm-svm-add-pause-filter-threshold
+ patches.drivers/kvm-svm-implement-pause-loop-exit-logic-in-svm
patches.suse/net-fool-proof-dev_valid_name.patch
patches.suse/ip_tunnel-better-validate-user-provided-tunnel-names.patch
patches.suse/ipv6-sit-better-validate-user-provided-tunnel-names.patch
@@ -15117,8 +15130,6 @@
patches.arch/0011-arm64-ssbd-Introduce-thread-flag-to-control-userspac.patch
patches.arch/0012-arm64-ssbd-Add-prctl-interface-for-per-thread-mitiga.patch
- patches.suse/0001-iommu-vt-d-Fix-race-condition-in-add_unmap.patch
-
########################################################
# Filesystem
########################################################