diff --git a/lcd-domains/arch/x86/include/asm/lcd_domains/liblcd.h b/lcd-domains/arch/x86/include/asm/lcd_domains/liblcd.h index 3c4a161b6ac8fb16733ef9e6796a4e73acfef420..9e54ebb8d95c70c2272beea20847e8ebc608938e 100644 --- a/lcd-domains/arch/x86/include/asm/lcd_domains/liblcd.h +++ b/lcd-domains/arch/x86/include/asm/lcd_domains/liblcd.h @@ -221,9 +221,9 @@ static inline int lcd_syscall_iommu_map_page(gpa_t gpa, unsigned int order, bool return lcd_syscall_three_args(LCD_SYSCALL_IOMMU_MAP_PAGE, gpa_val(gpa), order, force); } -static inline int lcd_syscall_iommu_unmap_page(gpa_t gpa) +static inline int lcd_syscall_iommu_unmap_page(gpa_t gpa, unsigned int order) { - return lcd_syscall_one_arg(LCD_SYSCALL_IOMMU_UNMAP_PAGE, gpa_val(gpa)); + return lcd_syscall_two_args(LCD_SYSCALL_IOMMU_UNMAP_PAGE, gpa_val(gpa), order); } static inline int lcd_syscall_create_sync_ep(cptr_t slot) diff --git a/lcd-domains/include/lcd_domains/lcd_iommu.h b/lcd-domains/include/lcd_domains/lcd_iommu.h index 8a3e88fbc9709d8a04b34dc7a37624a64125b8ab..287b9d9504dbd22034548a9814d2e8615f082503 100644 --- a/lcd-domains/include/lcd_domains/lcd_iommu.h +++ b/lcd-domains/include/lcd_domains/lcd_iommu.h @@ -36,7 +36,7 @@ int lcd_iommu_map_memory(struct lcd *lcd); */ int lcd_iommu_map_page(struct lcd *lcd, gpa_t gpa, unsigned int, bool force); -int lcd_iommu_unmap_page(struct lcd *lcd, gpa_t gpa); +int lcd_iommu_unmap_page(struct lcd *lcd, gpa_t gpa, unsigned int); /** * unmap the mappings from iommu. The logic is similar to mapping, except diff --git a/lcd-domains/microkernel/iommu.c b/lcd-domains/microkernel/iommu.c index b9f6a2e75d5aeb11fb2a0731b27e460dc35d3427..f09afff275ffecc99430b4d7ae2808a520c3787b 100644 --- a/lcd-domains/microkernel/iommu.c +++ b/lcd-domains/microkernel/iommu.c @@ -94,30 +94,46 @@ int lcd_iommu_map_page(struct lcd *lcd, gpa_t gpa, unsigned int order, return ret; } -int lcd_iommu_unmap_page(struct lcd *lcd, gpa_t gpa) +int lcd_iommu_unmap_page(struct lcd *lcd, gpa_t gpa, unsigned int order) { hpa_t hpa; int ret; + int i; + u64 gfn_start, gfn_end = 1 << order; - ret = lcd_arch_ept_gpa_to_hpa(lcd->lcd_arch, gpa, &hpa, true); - - /* no mapping. Just return */ - if (ret) { - LIBLCD_WARN("%s, spurious unmap to gpa:hpa %lx:%lx pair", - __func__, gpa_val(gpa), hpa_val(hpa)); - return 0; - } + gfn_start = gpa_to_gfn(gpa_val(gpa)); if (!lcd->domain) return -EINVAL; - ret = iommu_iova_to_phys(lcd->domain, gpa_val(gpa)); + for (i = 0; i < gfn_end; ++i) { + gpa_t ga = gfn_to_gpa(gfn_start + i); - if (ret) { - /* A valid mapping is present */ - ret = iommu_unmap(lcd->domain, gpa_val(gpa), PAGE_SIZE); - /* bug if not a page */ - BUG_ON(ret != PAGE_SIZE); + ret = lcd_arch_ept_gpa_to_hpa(lcd->lcd_arch, ga, &hpa, false); + + /* no mapping. Just return */ + /* TODO: it might be possible that the LCD has freed the memory + * without freeing the iommu mapping. in that case, it is + * messed up, but we can still go ahead and try to unmap it. + * This is has to be handled in a more cleaner way. + */ + if (ret) { + LIBLCD_WARN("%s, spurious unmap to gpa:hpa %lx:%lx pair", + __func__, gpa_val(ga), hpa_val(hpa)); + continue; + } + + ret = iommu_iova_to_phys(lcd->domain, gpa_val(ga)); + + printk("%s, unmapping gpa:hpa %lx:%lx pair\n", __func__, + gpa_val(ga), hpa_val(hpa)); + + if (ret) { + /* A valid mapping is present */ + ret = iommu_unmap(lcd->domain, gpa_val(ga), PAGE_SIZE); + /* bug if not a page */ + BUG_ON(ret != PAGE_SIZE); + } } /* return success */ return 0; diff --git a/lcd-domains/microkernel/run.c b/lcd-domains/microkernel/run.c index 3cf9223c252072c90c753658e28badd94d4e087f..b3d2df76f007bf384959b1876b6311d884ea6990 100644 --- a/lcd-domains/microkernel/run.c +++ b/lcd-domains/microkernel/run.c @@ -323,10 +323,12 @@ static int handle_syscall_iommu_unmap_page(struct lcd *lcd) { int ret; gpa_t gpa; + int order; gpa = __gpa(lcd_arch_get_syscall_arg0(lcd->lcd_arch)); + order = lcd_arch_get_syscall_arg1(lcd->lcd_arch); - ret = lcd_iommu_unmap_page(lcd, gpa); + ret = lcd_iommu_unmap_page(lcd, gpa, order); return ret; }