[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Lost] [Patch] kernel: Kernelspace-PDEs synchronisieren



! kernel: Direkt unterhalb von 4 GB ist nicht das urspruengliche Kernel-PD 
gemappt, sondern das PD des aktuellen Tasks
! kernel: Wenn fuer den Kernelspace eine neue PT benoetigt wird, muss das Page 
Directory in allen Tasks geaendert werden
Index: trunk/src/kernel/src/mm/kmm.c
===================================================================
--- trunk.orig/src/kernel/src/mm/kmm.c
+++ trunk/src/kernel/src/mm/kmm.c
@@ -53,6 +53,7 @@ bool kernel_identity_map(paddr_t paddr,
 // Der Teil des Page Directorys, der den Kernelraum mappt und für alle Prozesse gleich ist
 #define kernel_page_tables ((dword*)(kernel_page_directory + (KERNEL_BASE >> PGDIR_SHIFT)))
 extern page_directory_t kernel_page_directory;
+extern dword kernel_pd_id;
 
 /**
  * Errechnet die virtuelle Adresse der Page Table, die zur Adresse addr gehört.
@@ -85,6 +86,8 @@ static void map_kernel_page_table(int pg
     // Jede Page Table ist genau 4KB groß, also wird sie mit genau einem Eintrag
     // in der Page Table der Kernel Page Tables gemappt.
     page_table[pgdir_index] = (addr & PAGE_MASK) | PTE_W | PTE_P;
+
+    asm volatile("invlpg %0" : : "m" (*page_table));
 }
 
 /**
@@ -101,67 +104,6 @@ static void map_kernel_page_table(int pg
 }
 
 /**
- * Allokiert eine Seite (4 KBytes) im Kernel-Adressraum
- */
-vaddr_t alloc_kernel_page()
-{
-    int i, j;
-    page_table_t page_table;
-    vaddr_t vaddr;
-    
-    // Eine Page Table suchen, die frei ist.
-    for(i = 0; i < NUM_KERNEL_PAGE_TABLES; i++)
-    {
-        if(kernel_page_tables[i] & PTE_P)
-        {
-            page_table = (page_table_t)(KERNEL_PAGE_TABLES_VADDR + (i << PAGE_SHIFT));
-            
-            for(j = 0; j < PAGE_TABLE_LENGTH; j++)
-            {
-                if(!(page_table[j] & PTE_P))
-                {
-                    vaddr = (vaddr_t)(KERNEL_BASE + (i << PGDIR_SHIFT) + (j << PAGE_SHIFT));
-                    
-                    if((dword)vaddr > KERNEL_PAGE_TABLES_VADDR)
-                    {
-                        // Eine Adresse über KERNEL_PAGE_TABLES_VADDR ist für die Kernel Page Tables reserviert
-                        break;
-                    }
-
-                    // Unsere neue Page in die Page Table eintragen
-                    page_table[j] = (dword)phys_alloc_page() | PTE_W | PTE_P;
-
-                    return vaddr;
-                }
-            }
-        }
-    }
-
-    // Eine freien Eintrag im Page Directory für eine neue Page Table suchen.
-    for(i = 0; i < NUM_KERNEL_PAGE_TABLES; i++)
-    {
-        if(!(kernel_page_tables[i] & PTE_P))
-        {
-            
-            // Speicher für eine neue Page Table reservieren und nach KERNEL_PAGE_TABLES_VADDR mappen
-            kernel_page_tables[i] = (dword)phys_alloc_page() | PTE_W | PTE_P;
-            map_kernel_page_table(i, kernel_page_tables[i]);
-            page_table = (page_table_t)(KERNEL_PAGE_TABLES_VADDR + (i << PAGE_SHIFT)); 
-
-            // Page Table mit Nullen initialisieren
-            memset(page_table, PAGE_SIZE, 0);
-
-            // Unsere neue Page an den Anfang eintragen
-            page_table[0] = (dword)phys_alloc_page() | PTE_W | PTE_P;
-
-            return (void*)(KERNEL_BASE + (i << PGDIR_SHIFT));
-        }
-    }
-            
-    panic("Der virtuelle Adressraum > 3GB ist voll.");
-}
-
-/**
  * Gibt eine Seite (4 KBytes) im Kernel-Adressraum frei.
  */
 void free_kernel_page(vaddr_t page)
@@ -306,6 +248,8 @@ vaddr_t alloc_kernel_pages(int num)
 
             // Page Table mit Nullen initialisieren
             memset(page_table, PAGE_SIZE, 0);
+
+            kernel_pd_id++;
         }
         else
         {
@@ -316,6 +260,7 @@ vaddr_t alloc_kernel_pages(int num)
         for(j = (i == pgdir_index) ? pgtbl_index : 0; j < PAGE_TABLE_LENGTH && num; j++, num--)
         {
             page_table[j] = (dword)phys_alloc_page() | PTE_W | PTE_P;
+            asm volatile("invlpg %0" : : "m" (*(char*)(page_table[j] & PAGE_MASK)));
         }
     }
 
Index: trunk/src/kernel/include/tasks.h
===================================================================
--- trunk.orig/src/kernel/include/tasks.h
+++ trunk/src/kernel/include/tasks.h
@@ -24,6 +24,7 @@ struct task
     vaddr_t rpc_handler;
     list_t* rpcs;
     page_directory_t cr3;
+    dword pd_id;
     dword slices;
     dword blocked_by_pid;
     dword blocked_count;
Index: trunk/src/kernel/src/intr.c
===================================================================
--- trunk.orig/src/kernel/src/intr.c
+++ trunk/src/kernel/src/intr.c
@@ -117,6 +117,7 @@ void handle_exception(dword* esp);
 
 void send_irqs(dword* esp);
 dword irqs_to_send[16];
+extern dword kernel_pd_id;
 
 /*
  * gibt einen neuen Wert für esp zurck
@@ -163,6 +164,14 @@ dword handle_int(dword esp)
         //kprintf("PID=%d  cr3=0x%08x  kernel_pd=0x%08x eip=0x%08x\n", 
         //  current_task->pid, current_task->cr3, (dword)kernel_page_directory, isf->eip);
         //memcpy((void*)current_task->cr3, kernel_page_directory, 1024);
+
+        // Aktuelles Kernel-PD kopieren, wenn noetig
+        if (kernel_pd_id != current_task->pd_id) {
+            memcpy((void*) current_task->cr3, kernel_page_directory, 1020);
+            current_task->pd_id = kernel_pd_id;
+        }
+
+        // Page Directory des neuen Tasks laden
         __asm("mov %0, %%cr3" : : "r"(resolve_vaddr(kernel_page_directory, current_task->cr3)));
     }
 
Index: trunk/src/kernel/src/mm/paging.c
===================================================================
--- trunk.orig/src/kernel/src/mm/paging.c
+++ trunk/src/kernel/src/mm/paging.c
@@ -49,6 +49,7 @@ bool map_page(page_directory_t page_dire
 bool map_page_range(page_directory_t page_directory, vaddr_t vaddr, paddr_t paddr, int flags, int num_pages);
 
 page_directory_t kernel_page_directory;
+dword kernel_pd_id = 0;
 
 /**
  * Wenn TRUE, werden Page Tables nicht über ihre virtuelle Adresse
@@ -217,6 +218,9 @@ bool map_page(page_directory_t page_dire
             page_table = kernel_page_table;
         }
 
+        if (vaddr < (vaddr_t) 0x40000000) {
+            kernel_pd_id++;
+        }
         
         memset(page_table, 0, PAGE_SIZE);
         
Index: trunk/src/kernel/src/task.c
===================================================================
--- trunk.orig/src/kernel/src/task.c
+++ trunk/src/kernel/src/task.c
@@ -196,6 +196,7 @@ struct task * create_task(void* entry, c
 
     memset((void*) pagedir, 0, PAGE_SIZE);
     memcpy((void*) pagedir, kernel_page_directory, 1024);
+    pagedir[0xff] = (dword) phys_pagedir | PTE_W | PTE_P;
     new_task->cr3 = pagedir;
 
     // Speicher fuer die Stacks allokieren