Module Name:    src
Committed By:   maxv
Date:           Wed Dec 12 10:42:34 UTC 2018

Modified Files:
        src/lib/libnvmm: libnvmm.c

Log Message:
Change the map/unmap functions, again.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/lib/libnvmm/libnvmm.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libnvmm/libnvmm.c
diff -u src/lib/libnvmm/libnvmm.c:1.3 src/lib/libnvmm/libnvmm.c:1.4
--- src/lib/libnvmm/libnvmm.c:1.3	Thu Nov 29 19:55:20 2018
+++ src/lib/libnvmm/libnvmm.c	Wed Dec 12 10:42:34 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: libnvmm.c,v 1.3 2018/11/29 19:55:20 maxv Exp $	*/
+/*	$NetBSD: libnvmm.c,v 1.4 2018/12/12 10:42:34 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -57,89 +57,40 @@ static size_t nvmm_page_size = 0;
 
 /* -------------------------------------------------------------------------- */
 
-static int
-__area_unmap(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
- size_t size)
-{
-	struct nvmm_ioc_gpa_unmap args;
-	int ret;
-
-	args.machid = mach->machid;
-	args.gpa = gpa;
-	args.size = size;
-
-	ret = ioctl(nvmm_fd, NVMM_IOC_GPA_UNMAP, &args);
-	if (ret == -1)
-		return -1;
-
-	ret = munmap((void *)hva, size);
-
-	return ret;
-}
-
-static int
-__area_dig_hole(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
+static bool
+__area_isvalid(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
     size_t size)
 {
 	area_list_t *areas = mach->areas;
-	area_t *ent, *tmp, *nxt;
-	size_t diff;
+	area_t *ent;
 
-	LIST_FOREACH_SAFE(ent, areas, list, nxt) {
-		/* Case 1. */
-		if ((gpa < ent->gpa) && (gpa + size > ent->gpa)) {
-			diff = (gpa + size) - ent->gpa;
-			if (__area_unmap(mach, ent->hva, ent->gpa, diff) == -1) {
-				return -1;
-			}
-			ent->gpa  += diff;
-			ent->hva  += diff;
-			ent->size -= diff;
+	LIST_FOREACH(ent, areas, list) {
+		/* Collision on HVA */
+		if (hva >= ent->hva && hva < ent->hva + ent->size) {
+			return false;
 		}
-
-		/* Case 2. */
-		if ((gpa >= ent->gpa) && (gpa + size <= ent->gpa + ent->size)) {
-			/* First half. */
-			tmp = malloc(sizeof(*tmp));
-			tmp->gpa = ent->gpa;
-			tmp->hva = ent->hva;
-			tmp->size = (gpa - ent->gpa);
-			LIST_INSERT_BEFORE(ent, tmp, list);
-			/* Second half. */
-			ent->gpa  += tmp->size;
-			ent->hva  += tmp->size;
-			ent->size -= tmp->size;
-			diff = size;
-			if (__area_unmap(mach, ent->hva, ent->gpa, diff) == -1) {
-				return -1;
-			}
-			ent->gpa  += diff;
-			ent->hva  += diff;
-			ent->size -= diff;
+		if (hva + size >= ent->hva &&
+		    hva + size < ent->hva + ent->size) {
+			return false;
 		}
-
-		/* Case 3. */
-		if ((gpa < ent->gpa + ent->size) &&
-		    (gpa + size > ent->gpa + ent->size)) {
-			diff = (ent->gpa + ent->size) - gpa;
-			if (__area_unmap(mach, hva, gpa, diff) == -1) {
-				return -1;
-			}
-			ent->size -= diff;
+		if (hva <= ent->hva && hva + size >= ent->hva + ent->size) {
+			return false;
 		}
 
-		/* Case 4. */
-		if ((gpa < ent->gpa + ent->size) &&
-		    (gpa + size > ent->gpa + ent->size)) {
-			if (__area_unmap(mach, ent->hva, ent->gpa, ent->size) == -1) {
-				return -1;
-			}
-			LIST_REMOVE(ent, list);
-			free(ent);
+		/* Collision on GPA */
+		if (gpa >= ent->gpa && gpa < ent->gpa + ent->size) {
+			return false;
+		}
+		if (gpa + size >= ent->gpa &&
+		    gpa + size < ent->gpa + ent->size) {
+			return false;
+		}
+		if (gpa <= ent->gpa && gpa + size >= ent->gpa + ent->size) {
+			return false;
 		}
 	}
 
-	return 0;
+	return true;
 }
 
 static int
@@ -147,7 +98,11 @@ __area_add(struct nvmm_machine *mach, ui
 {
 	area_list_t *areas = mach->areas;
 	area_t *area;
-	int ret;
+
+	if (!__area_isvalid(mach, hva, gpa, size)) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	area = malloc(sizeof(*area));
 	if (area == NULL)
@@ -156,16 +111,29 @@ __area_add(struct nvmm_machine *mach, ui
 	area->hva = hva;
 	area->size = size;
 
-	ret = __area_dig_hole(mach, hva, gpa, size);
-	if (ret == -1) {
-		free(area);
-		return -1;
-	}
-
 	LIST_INSERT_HEAD(areas, area, list);
+
 	return 0;
 }
 
+static int
+__area_delete(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
+    size_t size)
+{
+	area_list_t *areas = mach->areas;
+	area_t *ent, *nxt;
+
+	LIST_FOREACH_SAFE(ent, areas, list, nxt) {
+		if (hva == ent->hva && gpa == ent->gpa && size == ent->size) {
+			LIST_REMOVE(ent, list);
+			free(ent);
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
 static void
 __area_remove_all(struct nvmm_machine *mach)
 {
@@ -450,11 +418,28 @@ int
 nvmm_gpa_unmap(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
     size_t size)
 {
+	struct nvmm_ioc_gpa_unmap args;
+	int ret;
+
 	if (nvmm_init() == -1) {
 		return -1;
 	}
 
-	return __area_dig_hole(mach, hva, gpa, size);
+	ret = __area_delete(mach, hva, gpa, size);
+	if (ret == -1)
+		return -1;
+
+	args.machid = mach->machid;
+	args.gpa = gpa;
+	args.size = size;
+
+	ret = ioctl(nvmm_fd, NVMM_IOC_GPA_UNMAP, &args);
+	if (ret == -1)
+		return -1;
+
+	ret = munmap((void *)hva, size);
+
+	return ret;
 }
 
 /*

Reply via email to