From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51670) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aagLq-0001H5-70 for qemu-devel@nongnu.org; Tue, 01 Mar 2016 04:12:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aagLo-0007W1-1S for qemu-devel@nongnu.org; Tue, 01 Mar 2016 04:12:18 -0500 Received: from e23smtp06.au.ibm.com ([202.81.31.148]:46343) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aagLn-0007U3-FW for qemu-devel@nongnu.org; Tue, 01 Mar 2016 04:12:15 -0500 Received: from localhost by e23smtp06.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 1 Mar 2016 19:12:12 +1000 From: Alexey Kardashevskiy Date: Tue, 1 Mar 2016 20:10:35 +1100 Message-Id: <1456823441-46757-11-git-send-email-aik@ozlabs.ru> In-Reply-To: <1456823441-46757-1-git-send-email-aik@ozlabs.ru> References: <1456823441-46757-1-git-send-email-aik@ozlabs.ru> Subject: [Qemu-devel] [PATCH qemu v13 10/16] vfio: Use different page size for different IOMMU types List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Alexey Kardashevskiy , Alex Williamson , qemu-ppc@nongnu.org The existing memory listener is called on RAM or PCI address space which implies potentially different page size. This uses new memory_region_iommu_get_page_sizes() for IOMMU regions or falls back to qemu_real_host_page_size if RAM. Signed-off-by: Alexey Kardashevskiy --- Changes: * uses the smallest page size for mask as IOMMU MR can support multple page sizes --- hw/vfio/common.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 0e67a5a..3aaa6b5 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -318,6 +318,16 @@ static hwaddr vfio_container_granularity(VFIOContainer *container) return (hwaddr)1 << ctz64(container->iova_pgsizes); } +static hwaddr vfio_iommu_page_mask(MemoryRegion *mr) +{ + if (memory_region_is_iommu(mr)) { + int smallest = ffs(memory_region_iommu_get_page_sizes(mr)) - 1; + + return ~((1ULL << smallest) - 1); + } + return qemu_real_host_page_mask; +} + static void vfio_listener_region_add(VFIOMemoryListener *vlistener, MemoryRegionSection *section) { @@ -326,6 +336,7 @@ static void vfio_listener_region_add(VFIOMemoryListener *vlistener, Int128 llend; void *vaddr; int ret; + hwaddr page_mask = vfio_iommu_page_mask(section->mr); if (vfio_listener_skipped_section(section)) { trace_vfio_listener_region_add_skip( @@ -335,16 +346,16 @@ static void vfio_listener_region_add(VFIOMemoryListener *vlistener, return; } - if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != - (section->offset_within_region & ~TARGET_PAGE_MASK))) { + if (unlikely((section->offset_within_address_space & ~page_mask) != + (section->offset_within_region & ~page_mask))) { error_report("%s received unaligned region", __func__); return; } - iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); + iova = ROUND_UP(section->offset_within_address_space, ~page_mask + 1); llend = int128_make64(section->offset_within_address_space); llend = int128_add(llend, section->size); - llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK)); + llend = int128_and(llend, int128_exts64(page_mask)); if (int128_ge(int128_make64(iova), llend)) { return; @@ -432,6 +443,7 @@ static void vfio_listener_region_del(VFIOMemoryListener *vlistener, hwaddr iova, end; int ret; MemoryRegion *iommu = NULL; + hwaddr page_mask = vfio_iommu_page_mask(section->mr); if (vfio_listener_skipped_section(section)) { trace_vfio_listener_region_del_skip( @@ -441,8 +453,8 @@ static void vfio_listener_region_del(VFIOMemoryListener *vlistener, return; } - if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != - (section->offset_within_region & ~TARGET_PAGE_MASK))) { + if (unlikely((section->offset_within_address_space & ~page_mask) != + (section->offset_within_region & ~page_mask))) { error_report("%s received unaligned region", __func__); return; } @@ -469,9 +481,9 @@ static void vfio_listener_region_del(VFIOMemoryListener *vlistener, */ } - iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); + iova = ROUND_UP(section->offset_within_address_space, ~page_mask + 1); end = (section->offset_within_address_space + int128_get64(section->size)) & - TARGET_PAGE_MASK; + page_mask; if (iova >= end) { return; -- 2.5.0.rc3