summaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2015-06-05 02:35:01 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2015-06-11 01:14:55 -0400
commit2d270df8f71a0fded9ef01cb9282b46fd3bc0986 (patch)
tree3801ebd1fbf14e2cd1b77ac68a8de64e1d854e39 /drivers/vfio
parent00663d4ee05dafe97033003fd5479cf9efd4bf96 (diff)
vfio: powerpc/spapr: Move locked_vm accounting to helpers
There moves locked pages accounting to helpers. Later they will be reused for Dynamic DMA windows (DDW). This reworks debug messages to show the current value and the limit. This stores the locked pages number in the container so when unlocking the iommu table pointer won't be needed. This does not have an effect now but it will with the multiple tables per container as then we will allow attaching/detaching groups on fly and we may end up having a container with no group attached but with the counter incremented. While we are here, update the comment explaining why RLIMIT_MEMLOCK might be required to be bigger than the guest RAM. This also prints pid of the current process in pr_warn/pr_debug. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> [aw: for the vfio related changes] Acked-by: Alex Williamson <alex.williamson@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/vfio_iommu_spapr_tce.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
index 64300ccb05db..6e2e15fdb0df 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
@@ -29,6 +29,51 @@
29static void tce_iommu_detach_group(void *iommu_data, 29static void tce_iommu_detach_group(void *iommu_data,
30 struct iommu_group *iommu_group); 30 struct iommu_group *iommu_group);
31 31
32static long try_increment_locked_vm(long npages)
33{
34 long ret = 0, locked, lock_limit;
35
36 if (!current || !current->mm)
37 return -ESRCH; /* process exited */
38
39 if (!npages)
40 return 0;
41
42 down_write(&current->mm->mmap_sem);
43 locked = current->mm->locked_vm + npages;
44 lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
45 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
46 ret = -ENOMEM;
47 else
48 current->mm->locked_vm += npages;
49
50 pr_debug("[%d] RLIMIT_MEMLOCK +%ld %ld/%ld%s\n", current->pid,
51 npages << PAGE_SHIFT,
52 current->mm->locked_vm << PAGE_SHIFT,
53 rlimit(RLIMIT_MEMLOCK),
54 ret ? " - exceeded" : "");
55
56 up_write(&current->mm->mmap_sem);
57
58 return ret;
59}
60
61static void decrement_locked_vm(long npages)
62{
63 if (!current || !current->mm || !npages)
64 return; /* process exited */
65
66 down_write(&current->mm->mmap_sem);
67 if (WARN_ON_ONCE(npages > current->mm->locked_vm))
68 npages = current->mm->locked_vm;
69 current->mm->locked_vm -= npages;
70 pr_debug("[%d] RLIMIT_MEMLOCK -%ld %ld/%ld\n", current->pid,
71 npages << PAGE_SHIFT,
72 current->mm->locked_vm << PAGE_SHIFT,
73 rlimit(RLIMIT_MEMLOCK));
74 up_write(&current->mm->mmap_sem);
75}
76
32/* 77/*
33 * VFIO IOMMU fd for SPAPR_TCE IOMMU implementation 78 * VFIO IOMMU fd for SPAPR_TCE IOMMU implementation
34 * 79 *
@@ -45,6 +90,7 @@ struct tce_container {
45 struct mutex lock; 90 struct mutex lock;
46 struct iommu_table *tbl; 91 struct iommu_table *tbl;
47 bool enabled; 92 bool enabled;
93 unsigned long locked_pages;
48}; 94};
49 95
50static bool tce_page_is_contained(struct page *page, unsigned page_shift) 96static bool tce_page_is_contained(struct page *page, unsigned page_shift)
@@ -60,7 +106,7 @@ static bool tce_page_is_contained(struct page *page, unsigned page_shift)
60static int tce_iommu_enable(struct tce_container *container) 106static int tce_iommu_enable(struct tce_container *container)
61{ 107{
62 int ret = 0; 108 int ret = 0;
63 unsigned long locked, lock_limit, npages; 109 unsigned long locked;
64 struct iommu_table *tbl = container->tbl; 110 struct iommu_table *tbl = container->tbl;
65 111
66 if (!container->tbl) 112 if (!container->tbl)
@@ -89,21 +135,22 @@ static int tce_iommu_enable(struct tce_container *container)
89 * Also we don't have a nice way to fail on H_PUT_TCE due to ulimits, 135 * Also we don't have a nice way to fail on H_PUT_TCE due to ulimits,
90 * that would effectively kill the guest at random points, much better 136 * that would effectively kill the guest at random points, much better
91 * enforcing the limit based on the max that the guest can map. 137 * enforcing the limit based on the max that the guest can map.
138 *
139 * Unfortunately at the moment it counts whole tables, no matter how
140 * much memory the guest has. I.e. for 4GB guest and 4 IOMMU groups
141 * each with 2GB DMA window, 8GB will be counted here. The reason for
142 * this is that we cannot tell here the amount of RAM used by the guest
143 * as this information is only available from KVM and VFIO is
144 * KVM agnostic.
92 */ 145 */
93 down_write(&current->mm->mmap_sem); 146 locked = (tbl->it_size << tbl->it_page_shift) >> PAGE_SHIFT;
94 npages = (tbl->it_size << tbl->it_page_shift) >> PAGE_SHIFT; 147 ret = try_increment_locked_vm(locked);
95 locked = current->mm->locked_vm + npages; 148 if (ret)
96 lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 149 return ret;
97 if (locked > lock_limit && !capable(CAP_IPC_LOCK)) {
98 pr_warn("RLIMIT_MEMLOCK (%ld) exceeded\n",
99 rlimit(RLIMIT_MEMLOCK));
100 ret = -ENOMEM;
101 } else {
102 150
103 current->mm->locked_vm += npages; 151 container->locked_pages = locked;
104 container->enabled = true; 152
105 } 153 container->enabled = true;
106 up_write(&current->mm->mmap_sem);
107 154
108 return ret; 155 return ret;
109} 156}
@@ -115,13 +162,10 @@ static void tce_iommu_disable(struct tce_container *container)
115 162
116 container->enabled = false; 163 container->enabled = false;
117 164
118 if (!container->tbl || !current->mm) 165 if (!current->mm)
119 return; 166 return;
120 167
121 down_write(&current->mm->mmap_sem); 168 decrement_locked_vm(container->locked_pages);
122 current->mm->locked_vm -= (container->tbl->it_size <<
123 container->tbl->it_page_shift) >> PAGE_SHIFT;
124 up_write(&current->mm->mmap_sem);
125} 169}
126 170
127static void *tce_iommu_open(unsigned long arg) 171static void *tce_iommu_open(unsigned long arg)