From 6e5fab79a140db9812b935f48be2a64e1eefd646 Mon Sep 17 00:00:00 2001 From: Vikram Narayanan Date: Wed, 3 May 2017 14:00:50 -0600 Subject: [PATCH] lcd/iommu: Allow unmapping over multiple pages Signed-off-by: Vikram Narayanan --- .../arch/x86/include/asm/lcd_domains/liblcd.h | 4 +- lcd-domains/include/lcd_domains/lcd_iommu.h | 2 +- lcd-domains/microkernel/iommu.c | 46 +++++++++++++------ lcd-domains/microkernel/run.c | 4 +- 4 files changed, 37 insertions(+), 19 deletions(-) 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 3c4a161b6ac8..9e54ebb8d95c 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 8a3e88fbc970..287b9d9504db 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 b9f6a2e75d5a..f09afff275ff 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 3cf9223c2520..b3d2df76f007 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; } -- GitLab