+ MemoryListener *listener,
MemoryRegionSection *section)
{
- VFIOContainer *container = container_of(listener, VFIOContainer,
- iommu_data.type1.listener);
hwaddr iova, end;
Int128 llend;
void *vaddr;
@@ -330,16 +330,16 @@ static void vfio_listener_region_add(MemoryListener
*listener,
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;
@@ -416,11 +416,11 @@ static void vfio_listener_region_add(MemoryListener
*listener,
}
}
-static void vfio_listener_region_del(MemoryListener *listener,
+static void vfio_listener_region_del(VFIOContainer *container,
+ hwaddr page_mask,
+ MemoryListener *listener,
MemoryRegionSection *section)
{
- VFIOContainer *container = container_of(listener, VFIOContainer,
- iommu_data.type1.listener);
hwaddr iova, end;
int ret;
@@ -432,8 +432,8 @@ static void vfio_listener_region_del(MemoryListener
*listener,
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;
}
@@ -459,9 +459,9 @@ static void vfio_listener_region_del(MemoryListener
*listener,
*/
}
- 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;
@@ -478,9 +478,66 @@ static void vfio_listener_region_del(MemoryListener
*listener,
}
}
-static const MemoryListener vfio_memory_listener = {
- .region_add = vfio_listener_region_add,
- .region_del = vfio_listener_region_del,
+static void vfio_type1_iommu_listener_region_add(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ VFIOContainer *container = container_of(listener, VFIOContainer,
+ iommu_data.type1.listener);
+
+ vfio_listener_region_add(container, qemu_real_host_page_mask, listener,
+ section);
+}
+
+
+static void vfio_type1_iommu_listener_region_del(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ VFIOContainer *container = container_of(listener, VFIOContainer,
+ iommu_data.type1.listener);
+
+ vfio_listener_region_del(container, qemu_real_host_page_mask, listener,
+ section);
+}
+
+static const MemoryListener vfio_type1_iommu_listener = {
+ .region_add = vfio_type1_iommu_listener_region_add,
+ .region_del = vfio_type1_iommu_listener_region_del,
+};
+
+static void vfio_spapr_iommu_listener_region_add(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ VFIOContainer *container;
+ hwaddr page_mask;
+
+ if (!memory_region_is_iommu(section->mr)) {
+ return;
+ }
+ container = container_of(listener, VFIOContainer,
+ iommu_data.type1.listener);
+ page_mask = ~(memory_region_iommu_get_page_sizes(section->mr) - 1);
+ vfio_listener_region_add(container, page_mask, listener, section);
+}
+
+
+static void vfio_spapr_iommu_listener_region_del(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ VFIOContainer *container;
+ hwaddr page_mask;
+
+ if (!memory_region_is_iommu(section->mr)) {
+ return;
+ }
+ container = container_of(listener, VFIOContainer,
+ iommu_data.type1.listener);
+ page_mask = ~(memory_region_iommu_get_page_sizes(section->mr) - 1);
+ vfio_listener_region_del(container, page_mask, listener, section);
+}
+
+static const MemoryListener vfio_spapr_iommu_listener = {
+ .region_add = vfio_spapr_iommu_listener_region_add,
+ .region_del = vfio_spapr_iommu_listener_region_del,
};