* [PATCH v1 0/2] vfio/iova_bitmap: bug fixes @ 2022-10-25 19:31 Joao Martins 2022-10-25 19:31 ` [PATCH v1 1/2] vfio/iova_bitmap: Explicitly include linux/slab.h Joao Martins ` (3 more replies) 0 siblings, 4 replies; 9+ messages in thread From: Joao Martins @ 2022-10-25 19:31 UTC (permalink / raw) To: kvm; +Cc: Alex Williamson, Cornelia Huck, Avihai Horon, Yishai Hadas Hey, This small series addresses one small improvement and one bug fix: 1) Avoid obscurity into how I use slab helpers yet I was never include it directly. And it wasn't detected thanks to a unrelated commit in v5.18 that lead linux/mm.h to indirectly include slab.h. 2) A bug reported by Avihai reported during migration testing where we weren't handling correctly PAGE_SIZE unaligned bitmaps, which lead to miss dirty marked correctly on some IOVAs. Comments appreciated Thanks, Joao Joao Martins (2): vfio/iova_bitmap: Explicitly include linux/slab.h vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps drivers/vfio/iova_bitmap.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) -- 2.17.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 1/2] vfio/iova_bitmap: Explicitly include linux/slab.h 2022-10-25 19:31 [PATCH v1 0/2] vfio/iova_bitmap: bug fixes Joao Martins @ 2022-10-25 19:31 ` Joao Martins 2022-10-25 19:31 ` [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps Joao Martins ` (2 subsequent siblings) 3 siblings, 0 replies; 9+ messages in thread From: Joao Martins @ 2022-10-25 19:31 UTC (permalink / raw) To: kvm; +Cc: Alex Williamson, Cornelia Huck, Avihai Horon, Yishai Hadas kzalloc/kzfree are used so include `slab.h`. While it happens to work without it, due to commit 8b9f3ac5b01d ("fs: introduce alloc_inode_sb() to allocate filesystems specific inode") which indirectly includes via: . ./include/linux/mm.h .. ./include/linux/huge_mm.h ... ./include/linux/fs.h .... ./include/linux/slab.h Make it explicit should any of its indirect dependencies be dropped/changed for entirely different reasons as it was the cause prior to commit above recently (i.e. <= v5.18). Signed-off-by: Joao Martins <joao.m.martins@oracle.com> --- drivers/vfio/iova_bitmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/vfio/iova_bitmap.c b/drivers/vfio/iova_bitmap.c index c20ffce1a0fd..389f36cae355 100644 --- a/drivers/vfio/iova_bitmap.c +++ b/drivers/vfio/iova_bitmap.c @@ -5,6 +5,7 @@ */ #include <linux/iova_bitmap.h> #include <linux/mm.h> +#include <linux/slab.h> #include <linux/highmem.h> #define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_BYTE) -- 2.17.2 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps 2022-10-25 19:31 [PATCH v1 0/2] vfio/iova_bitmap: bug fixes Joao Martins 2022-10-25 19:31 ` [PATCH v1 1/2] vfio/iova_bitmap: Explicitly include linux/slab.h Joao Martins @ 2022-10-25 19:31 ` Joao Martins 2022-11-24 18:20 ` Jason Gunthorpe 2022-11-09 20:09 ` [PATCH v1 0/2] vfio/iova_bitmap: bug fixes Joao Martins 2022-11-10 20:16 ` Alex Williamson 3 siblings, 1 reply; 9+ messages in thread From: Joao Martins @ 2022-10-25 19:31 UTC (permalink / raw) To: kvm; +Cc: Alex Williamson, Cornelia Huck, Avihai Horon, Yishai Hadas iova_bitmap_set() doesn't consider the end of the page boundary when the first bitmap page offset isn't zero, and wrongly changes the consecutive page right after. Consequently this leads to missing dirty pages from reported by the device as seen from the VMM. The current logic iterates over a given number of base pages and clamps it to the remaining indexes to iterate in the last page. Instead of having to consider extra pages to pin (e.g. first and extra pages), just handle the first page as its own range and let the rest of the bitmap be handled as if it was base page aligned. This is done by changing iova_bitmap_mapped_remaining() to return PAGE_SIZE - pgoff (on the first bitmap page), and leads to pgoff being set to 0 on following iterations. Fixes: 58ccf0190d19 ("vfio: Add an IOVA bitmap support") Reported-by: Avihai Horon <avihaih@nvidia.com> Tested-by: Avihai Horon <avihaih@nvidia.com> Signed-off-by: Joao Martins <joao.m.martins@oracle.com> --- I have a small test suite that I have been using for functional and some performance tests; I try to cover all the edge cases. Though I happened to miss having a test case (which is also fixed) ... leading to this bug. I wonder if this test suite is something of interest to have in tree? --- drivers/vfio/iova_bitmap.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/iova_bitmap.c b/drivers/vfio/iova_bitmap.c index 389f36cae355..40463c51da31 100644 --- a/drivers/vfio/iova_bitmap.c +++ b/drivers/vfio/iova_bitmap.c @@ -296,11 +296,15 @@ void iova_bitmap_free(struct iova_bitmap *bitmap) */ static unsigned long iova_bitmap_mapped_remaining(struct iova_bitmap *bitmap) { - unsigned long remaining; + unsigned long remaining, bytes; + + /* Cap to one page in the first iteration, if PAGE_SIZE unaligned. */ + bytes = !bitmap->mapped.pgoff ? bitmap->mapped.npages << PAGE_SHIFT : + PAGE_SIZE - bitmap->mapped.pgoff; remaining = bitmap->mapped_total_index - bitmap->mapped_base_index; remaining = min_t(unsigned long, remaining, - (bitmap->mapped.npages << PAGE_SHIFT) / sizeof(*bitmap->bitmap)); + bytes / sizeof(*bitmap->bitmap)); return remaining; } -- 2.17.2 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps 2022-10-25 19:31 ` [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps Joao Martins @ 2022-11-24 18:20 ` Jason Gunthorpe 2022-11-25 10:37 ` Joao Martins 0 siblings, 1 reply; 9+ messages in thread From: Jason Gunthorpe @ 2022-11-24 18:20 UTC (permalink / raw) To: Joao Martins Cc: kvm, Alex Williamson, Cornelia Huck, Avihai Horon, Yishai Hadas On Tue, Oct 25, 2022 at 08:31:14PM +0100, Joao Martins wrote: > iova_bitmap_set() doesn't consider the end of the page boundary when the > first bitmap page offset isn't zero, and wrongly changes the consecutive > page right after. Consequently this leads to missing dirty pages from > reported by the device as seen from the VMM. > > The current logic iterates over a given number of base pages and clamps it > to the remaining indexes to iterate in the last page. Instead of having to > consider extra pages to pin (e.g. first and extra pages), just handle the > first page as its own range and let the rest of the bitmap be handled as if > it was base page aligned. > > This is done by changing iova_bitmap_mapped_remaining() to return PAGE_SIZE > - pgoff (on the first bitmap page), and leads to pgoff being set to 0 on > following iterations. > > Fixes: 58ccf0190d19 ("vfio: Add an IOVA bitmap support") > Reported-by: Avihai Horon <avihaih@nvidia.com> > Tested-by: Avihai Horon <avihaih@nvidia.com> > Signed-off-by: Joao Martins <joao.m.martins@oracle.com> > --- > I have a small test suite that I have been using for functional and some > performance tests; I try to cover all the edge cases. Though I happened to > miss having a test case (which is also fixed) ... leading to this bug. > I wonder if this test suite is something of interest to have in > tree? Yes, when we move this to iommufd the test suite should be included, either as integrated using the mock domain and the selftests or otherwise. This is really a problem in iova_bitmap_set(), it isn't doing the math right. > + /* Cap to one page in the first iteration, if PAGE_SIZE unaligned. */ Why isn't it just bitmap->mapped.npages * PAGE_SIZE - bitmap->mapped.pgoff And fix the bug in iova_bitmap_set: void iova_bitmap_set(struct iova_bitmap *bitmap, unsigned long iova, size_t length) { struct iova_bitmap_map *mapped = &bitmap->mapped; unsigned cur_bit = ((iova - mapped->iova) >> mapped->pgshift) + mapped->pgoff * 8; unsigned long last_bit = (((iova + length - 1) - mapped->iova) >> mapped->pgshift) + mapped->pgoff * 8; do { unsigned int page_idx = cur_bit / BITS_PER_PAGE; unsigned int nbits = min(BITS_PER_PAGE - cur_bit, last_bit - cur_bit + 1); void *kaddr; kaddr = kmap_local_page(mapped->pages[page_idx]); bitmap_set(kaddr, cur_bit % BITS_PER_PAGE, nbits); kunmap_local(kaddr); cur_bit += nbits; } while (cur_bit <= last_bit); } EXPORT_SYMBOL_GPL(iova_bitmap_set); Jason ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps 2022-11-24 18:20 ` Jason Gunthorpe @ 2022-11-25 10:37 ` Joao Martins 2022-11-25 12:42 ` Jason Gunthorpe 0 siblings, 1 reply; 9+ messages in thread From: Joao Martins @ 2022-11-25 10:37 UTC (permalink / raw) To: Jason Gunthorpe Cc: kvm, Alex Williamson, Cornelia Huck, Avihai Horon, Yishai Hadas On 24/11/2022 18:20, Jason Gunthorpe wrote: > On Tue, Oct 25, 2022 at 08:31:14PM +0100, Joao Martins wrote: >> iova_bitmap_set() doesn't consider the end of the page boundary when the >> first bitmap page offset isn't zero, and wrongly changes the consecutive >> page right after. Consequently this leads to missing dirty pages from >> reported by the device as seen from the VMM. >> >> The current logic iterates over a given number of base pages and clamps it >> to the remaining indexes to iterate in the last page. Instead of having to >> consider extra pages to pin (e.g. first and extra pages), just handle the >> first page as its own range and let the rest of the bitmap be handled as if >> it was base page aligned. >> >> This is done by changing iova_bitmap_mapped_remaining() to return PAGE_SIZE >> - pgoff (on the first bitmap page), and leads to pgoff being set to 0 on >> following iterations. >> >> Fixes: 58ccf0190d19 ("vfio: Add an IOVA bitmap support") >> Reported-by: Avihai Horon <avihaih@nvidia.com> >> Tested-by: Avihai Horon <avihaih@nvidia.com> >> Signed-off-by: Joao Martins <joao.m.martins@oracle.com> >> --- >> I have a small test suite that I have been using for functional and some >> performance tests; I try to cover all the edge cases. Though I happened to >> miss having a test case (which is also fixed) ... leading to this bug. >> I wonder if this test suite is something of interest to have in >> tree? > > Yes, when we move this to iommufd the test suite should be included, > either as integrated using the mock domain and the selftests or > otherwise. > So in iommufd counterpart I have already tests which exercise this. But not as extensive. This testsuite is a bit more focused on all the functions in iova_bitmap and making sure I iterate the ranges right with small and huge bitmaps (up to 4T of IOVA space bitmaps), and testing that all the bits are set as expected, etc. I'll see if I merge both of these, there's probably no need for two separate units in the testsuite. The only test infra need for standalone iova-bitmap tests was the fact that I use GUP, and so I couldn't but this enterily in userspace. > This is really a problem in iova_bitmap_set(), it isn't doing the math > right. > Ack > >> + /* Cap to one page in the first iteration, if PAGE_SIZE unaligned. */ > > Why isn't it just > > bitmap->mapped.npages * PAGE_SIZE - bitmap->mapped.pgoff > This would return a higher than necessary number of indexes. But in fact the logic currently is correct and if we instead fix iova_bitmap_set() this new capping I was doing isn't needed at all. > And fix the bug in iova_bitmap_set: > This is right. I'm not handling cross page boundaries right in iova_bitmap_set() > void iova_bitmap_set(struct iova_bitmap *bitmap, > unsigned long iova, size_t length) > { > struct iova_bitmap_map *mapped = &bitmap->mapped; > unsigned cur_bit = > ((iova - mapped->iova) >> mapped->pgshift) + mapped->pgoff * 8; > unsigned long last_bit = > (((iova + length - 1) - mapped->iova) >> mapped->pgshift) + > mapped->pgoff * 8; > > do { > unsigned int page_idx = cur_bit / BITS_PER_PAGE; > unsigned int nbits = > min(BITS_PER_PAGE - cur_bit, last_bit - cur_bit + 1); > void *kaddr; > > kaddr = kmap_local_page(mapped->pages[page_idx]); > bitmap_set(kaddr, cur_bit % BITS_PER_PAGE, nbits); > kunmap_local(kaddr); > cur_bit += nbits; > } while (cur_bit <= last_bit); > } > EXPORT_SYMBOL_GPL(iova_bitmap_set); > Let me test this and respin. Not sure if the vfio tree is a rebasing tree (or not?) and can just send a new version, or whether I should explicitly revert the already commited one and apply a new version. I'll do a v2 of this patch and wait for Alex direction on where to go on the v2 patch in case I need to go via the latter. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps 2022-11-25 10:37 ` Joao Martins @ 2022-11-25 12:42 ` Jason Gunthorpe 2022-11-25 14:31 ` Joao Martins 0 siblings, 1 reply; 9+ messages in thread From: Jason Gunthorpe @ 2022-11-25 12:42 UTC (permalink / raw) To: Joao Martins Cc: kvm, Alex Williamson, Cornelia Huck, Avihai Horon, Yishai Hadas On Fri, Nov 25, 2022 at 10:37:39AM +0000, Joao Martins wrote: > > Yes, when we move this to iommufd the test suite should be included, > > either as integrated using the mock domain and the selftests or > > otherwise. > > So in iommufd counterpart I have already tests which exercise this. But not as > extensive. We are getting to the point where we should start posting the iommufd dirty tracking stuff. Do you have time to work on it for the next cycle? Meaning get it largely sorted out in the next 3 weeks for review? > > void iova_bitmap_set(struct iova_bitmap *bitmap, > > unsigned long iova, size_t length) > > { > > struct iova_bitmap_map *mapped = &bitmap->mapped; > > unsigned cur_bit = > > ((iova - mapped->iova) >> mapped->pgshift) + mapped->pgoff * 8; > > unsigned long last_bit = > > (((iova + length - 1) - mapped->iova) >> mapped->pgshift) + > > mapped->pgoff * 8; > > > > do { > > unsigned int page_idx = cur_bit / BITS_PER_PAGE; > > unsigned int nbits = > > min(BITS_PER_PAGE - cur_bit, last_bit - cur_bit + 1); min(BITS_PER_PAGE - (cur_bit % BITS_PER_PAGE), ...) > Not sure if the vfio tree is a rebasing tree (or not?) and can just send a new > version, It isn't, you should just post a new patch on top of Alex's current tree "rework iova_bitmap_et to handle all page crossings" and along the way revert the first bit Jason ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps 2022-11-25 12:42 ` Jason Gunthorpe @ 2022-11-25 14:31 ` Joao Martins 0 siblings, 0 replies; 9+ messages in thread From: Joao Martins @ 2022-11-25 14:31 UTC (permalink / raw) To: Jason Gunthorpe Cc: kvm, Alex Williamson, Cornelia Huck, Avihai Horon, Yishai Hadas On 25/11/2022 12:42, Jason Gunthorpe wrote: > On Fri, Nov 25, 2022 at 10:37:39AM +0000, Joao Martins wrote: > >>> Yes, when we move this to iommufd the test suite should be included, >>> either as integrated using the mock domain and the selftests or >>> otherwise. >> >> So in iommufd counterpart I have already tests which exercise this. But not as >> extensive. > > We are getting to the point where we should start posting the iommufd > dirty tracking stuff. Do you have time to work on it for the next > cycle? Meaning get it largely sorted out in the next 3 weeks for review? > I'll post it for the next cycle -- It has been a bit on crazy on my end this past month or so. >>> void iova_bitmap_set(struct iova_bitmap *bitmap, >>> unsigned long iova, size_t length) >>> { >>> struct iova_bitmap_map *mapped = &bitmap->mapped; >>> unsigned cur_bit = >>> ((iova - mapped->iova) >> mapped->pgshift) + mapped->pgoff * 8; >>> unsigned long last_bit = >>> (((iova + length - 1) - mapped->iova) >> mapped->pgshift) + >>> mapped->pgoff * 8; >>> >>> do { >>> unsigned int page_idx = cur_bit / BITS_PER_PAGE; >>> unsigned int nbits = >>> min(BITS_PER_PAGE - cur_bit, last_bit - cur_bit + 1); > > min(BITS_PER_PAGE - (cur_bit % BITS_PER_PAGE), ...) > I actually had this already in my changeset :) as the earlier snip wasn't passing my tests. Plus I need to account for less indexes with pgoff, contrary to what I said earlier in the remaining() function calculation. >> Not sure if the vfio tree is a rebasing tree (or not?) and can just send a new >> version, > > It isn't, you should just post a new patch on top of Alex's current > tree "rework iova_bitmap_et to handle all page crossings" and along > the way revert the first bit OK -- makes sense. The other fix wasn't incorrect either (as we need to account for pgoff on the same function), this one though fixes the real issue of iova_bitmap_set(). Also, I'll add your Signed-off-by+Co-developed-by -- let me know otherwise if I should not. Joao ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 0/2] vfio/iova_bitmap: bug fixes 2022-10-25 19:31 [PATCH v1 0/2] vfio/iova_bitmap: bug fixes Joao Martins 2022-10-25 19:31 ` [PATCH v1 1/2] vfio/iova_bitmap: Explicitly include linux/slab.h Joao Martins 2022-10-25 19:31 ` [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps Joao Martins @ 2022-11-09 20:09 ` Joao Martins 2022-11-10 20:16 ` Alex Williamson 3 siblings, 0 replies; 9+ messages in thread From: Joao Martins @ 2022-11-09 20:09 UTC (permalink / raw) To: kvm; +Cc: Alex Williamson, Cornelia Huck, Avihai Horon, Yishai Hadas On 25/10/2022 20:31, Joao Martins wrote: > Hey, > > This small series addresses one small improvement and one bug fix: > > 1) Avoid obscurity into how I use slab helpers yet I was > never include it directly. And it wasn't detected thanks to a unrelated > commit in v5.18 that lead linux/mm.h to indirectly include slab.h. > > 2) A bug reported by Avihai reported during migration testing where > we weren't handling correctly PAGE_SIZE unaligned bitmaps, which lead > to miss dirty marked correctly on some IOVAs. > > Comments appreciated > Ping? > Thanks, > Joao > > Joao Martins (2): > vfio/iova_bitmap: Explicitly include linux/slab.h > vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps > > drivers/vfio/iova_bitmap.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 0/2] vfio/iova_bitmap: bug fixes 2022-10-25 19:31 [PATCH v1 0/2] vfio/iova_bitmap: bug fixes Joao Martins ` (2 preceding siblings ...) 2022-11-09 20:09 ` [PATCH v1 0/2] vfio/iova_bitmap: bug fixes Joao Martins @ 2022-11-10 20:16 ` Alex Williamson 3 siblings, 0 replies; 9+ messages in thread From: Alex Williamson @ 2022-11-10 20:16 UTC (permalink / raw) To: Joao Martins; +Cc: kvm, Cornelia Huck, Avihai Horon, Yishai Hadas On Tue, 25 Oct 2022 20:31:12 +0100 Joao Martins <joao.m.martins@oracle.com> wrote: > Hey, > > This small series addresses one small improvement and one bug fix: > > 1) Avoid obscurity into how I use slab helpers yet I was > never include it directly. And it wasn't detected thanks to a unrelated > commit in v5.18 that lead linux/mm.h to indirectly include slab.h. > > 2) A bug reported by Avihai reported during migration testing where > we weren't handling correctly PAGE_SIZE unaligned bitmaps, which lead > to miss dirty marked correctly on some IOVAs. > > Comments appreciated > > Thanks, > Joao > > Joao Martins (2): > vfio/iova_bitmap: Explicitly include linux/slab.h > vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps > > drivers/vfio/iova_bitmap.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > Applied to vfio next branch for v6.2. Thanks, Alex ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2022-11-25 14:31 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-10-25 19:31 [PATCH v1 0/2] vfio/iova_bitmap: bug fixes Joao Martins 2022-10-25 19:31 ` [PATCH v1 1/2] vfio/iova_bitmap: Explicitly include linux/slab.h Joao Martins 2022-10-25 19:31 ` [PATCH v1 2/2] vfio/iova_bitmap: Fix PAGE_SIZE unaligned bitmaps Joao Martins 2022-11-24 18:20 ` Jason Gunthorpe 2022-11-25 10:37 ` Joao Martins 2022-11-25 12:42 ` Jason Gunthorpe 2022-11-25 14:31 ` Joao Martins 2022-11-09 20:09 ` [PATCH v1 0/2] vfio/iova_bitmap: bug fixes Joao Martins 2022-11-10 20:16 ` Alex Williamson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.