summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2013-06-14 23:41:23 +0200
committerRichard Braun <rbraun@sceen.net>2013-06-14 23:41:23 +0200
commit2e68b49825c2b334b1f498a6bc066c4d8939e160 (patch)
tree9839dcdaa8fe57536aab8c395bc8fc5f8bb9360c
parent5fc5d2d1156b60b3c22f89ddba354eb3f43da310 (diff)
vm/vm_map: fix map entry merging
Map entry merging would not consider requests with objects, but it would merge two neighbor entries without checking their object. Make checking the object of both entries and requests part of the generic compatibility test.
-rw-r--r--vm/vm_map.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/vm/vm_map.c b/vm/vm_map.c
index 49b9e629..27361558 100644
--- a/vm/vm_map.c
+++ b/vm/vm_map.c
@@ -635,9 +635,14 @@ vm_map_prepare(struct vm_map *map, struct vm_object *object, unsigned long offse
*/
static inline int
-vm_map_try_merge_compatible(int flags1, int flags2)
+vm_map_try_merge_compatible(const struct vm_map_request *request,
+ const struct vm_map_entry *entry)
{
- return (flags1 & VM_MAP_ENTRY_MASK) == (flags2 & VM_MAP_ENTRY_MASK);
+ /* Only merge special kernel mappings for now */
+ return (request->object == NULL)
+ && (entry->object == NULL)
+ && ((request->flags & VM_MAP_ENTRY_MASK)
+ == (entry->flags & VM_MAP_ENTRY_MASK));
}
static struct vm_map_entry *
@@ -648,7 +653,7 @@ vm_map_try_merge_prev(struct vm_map *map, const struct vm_map_request *request,
assert(entry != NULL);
- if (!vm_map_try_merge_compatible(entry->flags, request->flags))
+ if (!vm_map_try_merge_compatible(request, entry))
return NULL;
if (entry->end != request->start)
@@ -671,7 +676,7 @@ vm_map_try_merge_next(struct vm_map *map, const struct vm_map_request *request,
assert(entry != NULL);
- if (!vm_map_try_merge_compatible(entry->flags, request->flags))
+ if (!vm_map_try_merge_compatible(request, entry))
return NULL;
end = request->start + request->size;
@@ -698,8 +703,8 @@ vm_map_try_merge_near(struct vm_map *map, const struct vm_map_request *request,
if ((first->end == request->start)
&& ((request->start + request->size) == second->start)
- && vm_map_try_merge_compatible(first->flags, request->flags)
- && vm_map_try_merge_compatible(request->flags, second->flags)) {
+ && vm_map_try_merge_compatible(request, first)
+ && vm_map_try_merge_compatible(request, second)) {
struct vm_map_entry *prev, *next;
prev = vm_map_prev(map, first);
@@ -726,12 +731,9 @@ vm_map_try_merge(struct vm_map *map, const struct vm_map_request *request)
struct vm_map_entry *entry, *prev;
struct list *node;
+ /* Statically allocated map entries must not be merged */
assert(!(request->flags & VM_MAP_NOMERGE));
- /* Only merge special kernel mappings for now */
- if (request->object != NULL)
- return NULL;
-
if (request->next == NULL) {
node = list_last(&map->entry_list);