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
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)
......
......@@ -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
......
......@@ -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;
......
......@@ -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;
}
......
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