aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/vfio_iommu_spapr_tce.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
index b95fa2b64680..735b308709e5 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
@@ -47,6 +47,16 @@ struct tce_container {
47 bool enabled; 47 bool enabled;
48}; 48};
49 49
50static bool tce_page_is_contained(struct page *page, unsigned page_shift)
51{
52 /*
53 * Check that the TCE table granularity is not bigger than the size of
54 * a page we just found. Otherwise the hardware can get access to
55 * a bigger memory chunk that it should.
56 */
57 return (PAGE_SHIFT + compound_order(compound_head(page))) >= page_shift;
58}
59
50static int tce_iommu_enable(struct tce_container *container) 60static int tce_iommu_enable(struct tce_container *container)
51{ 61{
52 int ret = 0; 62 int ret = 0;
@@ -189,6 +199,12 @@ static long tce_iommu_build(struct tce_container *container,
189 ret = -EFAULT; 199 ret = -EFAULT;
190 break; 200 break;
191 } 201 }
202
203 if (!tce_page_is_contained(page, tbl->it_page_shift)) {
204 ret = -EPERM;
205 break;
206 }
207
192 hva = (unsigned long) page_address(page) + offset; 208 hva = (unsigned long) page_address(page) + offset;
193 209
194 ret = iommu_tce_build(tbl, entry + i, hva, direction); 210 ret = iommu_tce_build(tbl, entry + i, hva, direction);