Refactor map functions, add unmap
authorJack Miller <jack@codezen.org>
Sun, 20 Mar 2016 01:16:04 +0000 (20:16 -0500)
committerJack Miller <jack@codezen.org>
Sun, 20 Mar 2016 01:16:04 +0000 (20:16 -0500)
include/map.h
mm/map.c

index be4ffaa..993d8b6 100644 (file)
@@ -3,7 +3,14 @@
 
 #include <types.h>
 
-int map_page(u64 virtual, u64 physical);
-int map_page_nocache(u64 virtual, u64 physical);
 void *map_page_early(u64 virtual, u64 physical, u64 *alloc_base);
+
+int map_pages(u64 virtual, u64 physical, u64 num_pages);
+int map_pages_nocache(u64 virtual, u64 physical, u64 num_pages);
+
+void unmap_pages(u64 virtual, u64 num_pages);
+
+#define map_page(v, p)                 map_pages(v, p, 1)
+#define map_page_nocache(v, p) map_pages_nocache(v, p, 1)
+
 void map_page_summarize(u64 virtual);
index 4d6bca9..dd1a73d 100644 (file)
--- a/mm/map.c
+++ b/mm/map.c
@@ -46,7 +46,7 @@ void *map_page_early(u64 virtual, u64 physical, u64 *alloc_base)
 /* Similar to __early_map_check, except it can use page_alloc_phys, and check
  * its return value*/
 
-int __map_check(u64 *entry, u64 *target)
+static int __map_check(u64 *entry, u64 *target)
 {
        u64 phys = 0;
 
@@ -99,7 +99,6 @@ int __map_page_flags(u64 virtual, u64 physical, u8 flags)
 
        *pte = physical | PF_P | flags;
 
-       reset_cr3();
 
        return 0;
 
@@ -120,14 +119,102 @@ cleanup_pml4e:
        return -ENOMEM;
 }
 
-int map_page(u64 virtual, u64 physical)
+int __table_empty(u64 *table)
 {
-       return __map_page_flags(virtual, physical, PF_RW);
+       int i;
+       for(i = 0; i < 512; i++) {
+               if (table[i] & PF_P)
+                       return 0;
+       }
+
+       return 1;
 }
 
-int map_page_nocache(u64 virtual, u64 physical)
+void __unmap_page(u64 virtual)
 {
-       return __map_page_flags(virtual, physical, PF_RW | PF_DISABLE_CACHE);
+       u64 *pml4e,*pdpe,*pde,*pte = NULL;
+       u64 *pdp, *pd, *pt;
+
+       pml4e = (u64 *) PML4E_ADDR(virtual);
+       pdpe = (u64 *) PDPE_ADDR(virtual);
+       pde = (u64 *) PDE_ADDR(virtual);
+       pte = (u64 *) PTE_ADDR(virtual);
+
+       pdp = (u64 *) PAGE_ALIGN((u64) pdpe);
+       pd = (u64 *) PAGE_ALIGN((u64) pde);
+       pt = (u64 *) PAGE_ALIGN((u64) pte);
+
+       /* If the mapping doesn't exist, get out */
+       if (!(*pml4e & PF_P))
+               return;
+       if (!(*pdpe & PF_P))
+               return;
+       if (!(*pde & PF_P))
+               return;
+       if (!(*pte & PF_P))
+               return;
+
+       *pte = 0;
+       if(__table_empty(pt)) {
+               page_alloc_free_phys(PAGE_ALIGN(*pde));
+               *pde = 0;
+
+               if(__table_empty(pd)) {
+                       page_alloc_free_phys(PAGE_ALIGN(*pdpe));
+                       *pdpe = 0;
+
+                       if(__table_empty(pdp)) {
+                               page_alloc_free_phys(PAGE_ALIGN(*pml4e));
+                               *pml4e = 0;
+                       }
+               }
+       }
+}
+
+void unmap_pages(u64 virtual, u64 num_pages)
+{
+       while (num_pages) {
+               __unmap_page(virtual);
+               virtual += PAGE_SIZE;
+               num_pages--;
+       }
+}
+
+int __map_pages_flags(u64 virtual, u64 physical, u64 num_pages, u8 flags)
+{
+       int i, j, ret;
+
+       for ( i = 0; i < num_pages; i++) {
+               ret = __map_page_flags(virtual, physical, flags);
+
+               if (ret) {
+                       for (j = i; j > 0; j--) {
+                               virtual -= PAGE_SIZE;
+                               physical -= PAGE_SIZE;
+                               unmap_pages(virtual, 1);
+                       }
+                       return ret;
+               }
+
+               virtual += PAGE_SIZE;
+               physical += PAGE_SIZE;
+       }
+
+       return 0;
+}
+
+int map_pages(u64 virtual, u64 physical, u64 num_pages)
+{
+       int ret = __map_pages_flags(virtual, physical, num_pages, PF_RW);
+       reset_cr3();
+       return ret;
+}
+
+int map_pages_nocache(u64 virtual, u64 physical, u64 num_pages)
+{
+       int ret = __map_pages_flags(virtual, physical, num_pages, PF_RW | PF_DISABLE_CACHE);
+       reset_cr3();
+       return ret;
 }
 
 void map_page_summarize(u64 virtual)