[kernel] Bug fixes and refactoring
authorcoderain <coderain@sdf.org>
Wed, 15 Nov 2017 04:44:35 +0000 (05:44 +0100)
committercoderain <coderain@sdf.org>
Wed, 15 Nov 2017 04:44:35 +0000 (05:44 +0100)
kernel/src/memory/memory.c

index 4479209c26273c69a6447d3e4624130b9dc94e0e..f1f0da1ad65173004fd4c162bfec09bf6f384804 100644 (file)
@@ -889,7 +889,7 @@ dword_t map_memory_in_address_space(memory_address_space_t *address_space,
                                     dword_t block_flags)
 {
     dword_t ret;
-    void *address = *virtual;
+    void *address = (void*)PAGE_ALIGN((uintptr_t)*virtual);
 
     acquire_resource_exclusive(&address_space->resource);
 
@@ -963,7 +963,7 @@ dword_t pin_memory(const void *virtual, void **pinned, uintptr_t size, bool_t lo
 {
     uintptr_t i;
     uintptr_t virt_addr = PAGE_ALIGN((uintptr_t)virtual);
-    void *address = *pinned;
+    void *address = (void*)PAGE_ALIGN((uintptr_t)*pinned);
     size = PAGE_ALIGN_UP(size);
 
     memory_address_space_t *address_space = check_usermode(virtual, 1) ? &get_current_process()->memory_space : &kernel_address_space;
@@ -1091,7 +1091,7 @@ dword_t alloc_memory_in_address_space(memory_address_space_t *address_space,
                                       memory_section_t *section,
                                       qword_t section_offset)
 {
-    void *base_address = *address;
+    void *base_address = (void*)PAGE_ALIGN((uintptr_t)*address);
 
     block_flags &= ~(MEMORY_BLOCK_FREE | MEMORY_BLOCK_COPY_ON_WRITE);
     size = PAGE_ALIGN_UP(size) >> 12;
@@ -1825,6 +1825,8 @@ sysret_t syscall_map_memory_section(handle_t process, handle_t section, void **a
     memory_section_t *mem_sec = NULL;
     void *safe_address;
 
+    if (PAGE_OFFSET(offset) != 0) return ERR_INVALID;
+
     if (process != INVALID_HANDLE)
     {
         if (!reference_by_handle(process, OBJECT_PROCESS, (object_t**)&proc))
@@ -2280,6 +2282,41 @@ void delete_address_space(memory_address_space_t *mem_space)
     release_resource(&mem_space->resource);
 }
 
+static bool_t find_evicted_page(memory_block_t *block, void *address, page_store_t **store, page_store_entry_t **entry)
+{
+    list_entry_t *i;
+
+    for (i = transition_pages.next; i != &transition_pages; i = i->next)
+    {
+        *entry = CONTAINER_OF(i, page_store_entry_t, link);
+
+        if ((*entry)->address_space == block->address_space
+            && PAGE_ALIGN((dword_t)(*entry)->address) == PAGE_ALIGN((dword_t)address))
+        {
+            return TRUE;
+        }
+    }
+
+    for (i = page_stores.next; i != &page_stores; i = i->next)
+    {
+        list_entry_t *j;
+        *store = CONTAINER_OF(i, page_store_t, link);
+
+        for (j = (*store)->entry_list.next; j != &(*store)->entry_list; j = j->next)
+        {
+            *entry = CONTAINER_OF(j, page_store_entry_t, link);
+
+            if ((*entry)->address_space == block->address_space
+                && PAGE_ALIGN((dword_t)(*entry)->address) == PAGE_ALIGN((dword_t)address))
+            {
+                return TRUE;
+            }
+        }
+    }
+
+    return FALSE;
+}
+
 bool_t memory_fault_handler(void *address, registers_t *regs)
 {
     int i;
@@ -2316,50 +2353,81 @@ bool_t memory_fault_handler(void *address, registers_t *regs)
 
     if ((block->flags & MEMORY_BLOCK_ACCESSIBLE) && (problem == PAGE_ERROR_NOTPRESENT))
     {
-        list_entry_t *i;
         page_store_t *store = NULL;
         page_store_entry_t *entry = NULL;
         byte_t buffer[PAGE_SIZE];
-        bool_t found = FALSE;
         dword_t bytes_read;
         dword_t page_flags = 0;
 
-        for (i = transition_pages.next; i != &transition_pages; i = i->next)
+        if (find_evicted_page(block, address, &store, &entry))
         {
-            page_store_entry_t *entry = CONTAINER_OF(i, page_store_entry_t, link);
-
-            if (entry->address_space == block->address_space
-                && PAGE_ALIGN((dword_t)entry->address) == PAGE_ALIGN((dword_t)address))
+            if (block->flags & MEMORY_BLOCK_ACCESSIBLE) page_flags |= PAGE_PRESENT;
+            if ((block->flags & (MEMORY_BLOCK_WRITABLE | MEMORY_BLOCK_COPY_ON_WRITE))
+                == MEMORY_BLOCK_WRITABLE)
             {
-                found = TRUE;
-                goto done;
+                page_flags |= PAGE_WRITABLE;
             }
-        }
 
-        for (i = page_stores.next; i != &page_stores; i = i->next)
-        {
-            list_entry_t *j;
-            store = CONTAINER_OF(i, page_store_t, link);
+            if (block->flags & MEMORY_BLOCK_USERMODE) page_flags |= PAGE_USERMODE;
+            else page_flags |= PAGE_GLOBAL;
 
-            for (j = store->entry_list.next; j != &store->entry_list; j = j->next)
+            if (entry->number != INVALID_STORE_NUMBER)
             {
-                entry = CONTAINER_OF(j, page_store_entry_t, link);
+                enable_ints();
+                dword_t ret = syscall_read_file(store->file_handle, buffer, (qword_t)entry->number * (qword_t)PAGE_SIZE, PAGE_SIZE, &bytes_read);
+                disable_ints();
 
-                if (entry->address_space == block->address_space
-                    && PAGE_ALIGN((dword_t)entry->address) == PAGE_ALIGN((dword_t)address))
+                if ((page_directory[pd_index] & PAGE_PRESENT) && (page_table[pt_index] & PAGE_PRESENT))
                 {
-                    found = TRUE;
-                    goto done;
+                    return TRUE;
+                }
+
+                if (ret != ERR_SUCCESS) return FALSE;
+
+                ret = alloc_page((void*)aligned_address, page_flags);
+                if (ret != ERR_SUCCESS) return FALSE;
+
+                list_entry_t *ptr;
+                for (ptr = store->entry_list.next; ptr != &store->entry_list; ptr = ptr->next)
+                {
+                    page_store_entry_t *other_entry = CONTAINER_OF(ptr, page_store_entry_t, link);
+
+                    if (entry != other_entry && other_entry->number == entry->number)
+                    {
+                        list_remove(&other_entry->link);
+                        list_append(&transition_pages, &other_entry->link);
+
+                        other_entry->physical = get_physical_address((void*)aligned_address);
+                        other_entry->number = INVALID_STORE_NUMBER;
+                    }
+                }
+
+                clear_bit(store->bitmap, entry->number);
+                list_remove(&entry->link);
+                free(entry);
+
+                memcpy((void*)aligned_address, buffer, PAGE_SIZE);
+                address_space->stats.evicted -= PAGE_SIZE;
+                return TRUE;
+            }
+            else
+            {
+                if (map_page(entry->physical, entry->address, page_flags) == ERR_SUCCESS)
+                {
+                    list_remove(&entry->link);
+                    free(entry);
+                    address_space->stats.evicted -= PAGE_SIZE;
+                    return TRUE;
                 }
             }
-        }
 
-done:
-        if (!found)
+            return FALSE;
+        }
+        else
         {
             list_entry_t *ptr;
             shared_page_t *page = NULL;
-            dword_t offset = aligned_address - (dword_t)block->by_addr_tree.key;
+            qword_t offset = block->section_offset + (qword_t)aligned_address - (qword_t)block->by_addr_tree.key;
 
             page_flags = PAGE_PRESENT;
             if (block->flags & MEMORY_BLOCK_WRITABLE) page_flags |= PAGE_WRITABLE;
@@ -2367,8 +2435,10 @@ done:
             if (block->flags & MEMORY_BLOCK_USERMODE) page_flags |= PAGE_USERMODE;
             else page_flags |= PAGE_GLOBAL;
 
-            if (block->section)
+            if (block->section && offset < (qword_t)block->section->size)
             {
+                ASSERT(PAGE_OFFSET(offset) == 0);
+
                 for (ptr = block->section->page_list.next; ptr != &block->section->page_list; ptr = ptr->next)
                 {
                     page = CONTAINER_OF(ptr, shared_page_t, link);
@@ -2383,15 +2453,15 @@ done:
 
             memset(buffer, 0, PAGE_SIZE);
 
-            if (block->section && block->section->file)
+            if (block->section && block->section->file && offset < (qword_t)block->section->size)
             {
                 enable_ints();
                 file_instance_t *file = block->section->file;
                 acquire_resource_shared(&file->global->volume->resource);
-                dword_t ret = file->global->volume->driver->read_file(file, buffer, block->section_offset + offset, PAGE_SIZE, &bytes_read);
+                dword_t ret = file->global->volume->driver->read_file(file, buffer, offset, PAGE_SIZE, &bytes_read);
                 release_resource(&file->global->volume->resource);
                 disable_ints();
-                if (ret != ERR_SUCCESS) return FALSE;
+                if (ret != ERR_SUCCESS && ret != ERR_BEYOND) return FALSE;
             }
 
             dword_t ret = alloc_page((void*)aligned_address, page_flags | PAGE_WRITABLE);
@@ -2400,7 +2470,7 @@ done:
             memcpy((void*)aligned_address, buffer, PAGE_SIZE);
             set_page_flags((void*)aligned_address, page_flags);
 
-            if (block->section)
+            if (block->section && offset < (qword_t)block->section->size)
             {
                 page = (shared_page_t*)malloc(sizeof(shared_page_t));
                 if (page == NULL)
@@ -2418,68 +2488,6 @@ done:
             address_space->stats.committed += PAGE_SIZE;
             return TRUE;
         }
-
-        if (block->flags & MEMORY_BLOCK_ACCESSIBLE) page_flags |= PAGE_PRESENT;
-        if ((block->flags & (MEMORY_BLOCK_WRITABLE | MEMORY_BLOCK_COPY_ON_WRITE))
-            == MEMORY_BLOCK_WRITABLE)
-        {
-            page_flags |= PAGE_WRITABLE;
-        }
-
-        if (block->flags & MEMORY_BLOCK_USERMODE) page_flags |= PAGE_USERMODE;
-        else page_flags |= PAGE_GLOBAL;
-
-        if (entry->number != INVALID_STORE_NUMBER)
-        {
-            enable_ints();
-            dword_t ret = syscall_read_file(store->file_handle, buffer, (qword_t)entry->number * (qword_t)PAGE_SIZE, PAGE_SIZE, &bytes_read);
-            disable_ints();
-
-            if ((page_directory[pd_index] & PAGE_PRESENT) && (page_table[pt_index] & PAGE_PRESENT))
-            {
-                return TRUE;
-            }
-
-            if (ret != ERR_SUCCESS) return FALSE;
-
-            ret = alloc_page((void*)aligned_address, page_flags);
-            if (ret != ERR_SUCCESS) return FALSE;
-
-            list_entry_t *ptr;
-            for (ptr = store->entry_list.next; ptr != &store->entry_list; ptr = ptr->next)
-            {
-                page_store_entry_t *other_entry = CONTAINER_OF(ptr, page_store_entry_t, link);
-
-                if (entry != other_entry && other_entry->number == entry->number)
-                {
-                    list_remove(&other_entry->link);
-                    list_append(&transition_pages, &other_entry->link);
-
-                    other_entry->physical = get_physical_address((void*)aligned_address);
-                    other_entry->number = INVALID_STORE_NUMBER;
-                }
-            }
-
-            clear_bit(store->bitmap, entry->number);
-            list_remove(&entry->link);
-            free(entry);
-
-            memcpy((void*)aligned_address, buffer, PAGE_SIZE);
-            address_space->stats.evicted -= PAGE_SIZE;
-            return TRUE;
-        }
-        else
-        {
-            if (map_page(entry->physical, entry->address, page_flags) == ERR_SUCCESS)
-            {
-                list_remove(&entry->link);
-                free(entry);
-                address_space->stats.evicted -= PAGE_SIZE;
-                return TRUE;
-            }
-        }
-
-        return FALSE;
     }
 
     if ((block->flags & (MEMORY_BLOCK_COPY_ON_WRITE | MEMORY_BLOCK_WRITABLE))