Commit 6e5fab79 authored by Vikram Narayanan's avatar Vikram Narayanan

lcd/iommu: Allow unmapping over multiple pages

Signed-off-by: Vikram Narayanan's avatarVikram Narayanan <vikram186@gmail.com>
parent 35d42a24
...@@ -221,9 +221,9 @@ static inline int lcd_syscall_iommu_map_page(gpa_t gpa, unsigned int order, bool ...@@ -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); 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) static inline int lcd_syscall_create_sync_ep(cptr_t slot)
......
...@@ -36,7 +36,7 @@ int lcd_iommu_map_memory(struct lcd *lcd); ...@@ -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_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 * unmap the mappings from iommu. The logic is similar to mapping, except
......
...@@ -94,30 +94,46 @@ int lcd_iommu_map_page(struct lcd *lcd, gpa_t gpa, unsigned int order, ...@@ -94,30 +94,46 @@ int lcd_iommu_map_page(struct lcd *lcd, gpa_t gpa, unsigned int order,
return ret; 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; hpa_t hpa;
int ret; int ret;
int i;
u64 gfn_start, gfn_end = 1 << order;
ret = lcd_arch_ept_gpa_to_hpa(lcd->lcd_arch, gpa, &hpa, true); gfn_start = gpa_to_gfn(gpa_val(gpa));
/* 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;
}
if (!lcd->domain) if (!lcd->domain)
return -EINVAL; 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) { ret = lcd_arch_ept_gpa_to_hpa(lcd->lcd_arch, ga, &hpa, false);
/* A valid mapping is present */
ret = iommu_unmap(lcd->domain, gpa_val(gpa), PAGE_SIZE); /* no mapping. Just return */
/* bug if not a page */ /* TODO: it might be possible that the LCD has freed the memory
BUG_ON(ret != PAGE_SIZE); * 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 success */
return 0; return 0;
......
...@@ -323,10 +323,12 @@ static int handle_syscall_iommu_unmap_page(struct lcd *lcd) ...@@ -323,10 +323,12 @@ static int handle_syscall_iommu_unmap_page(struct lcd *lcd)
{ {
int ret; int ret;
gpa_t gpa; gpa_t gpa;
int order;
gpa = __gpa(lcd_arch_get_syscall_arg0(lcd->lcd_arch)); 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; return ret;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment