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

[Xen-changelog] [xen-unstable] [MINIOS]Mapping page frames on demand added to the memory management.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 4db818a7dc3f3bb3b9dace0a7fa8a1f80f2b0d26
# Parent  462d6e4cb29a620685f7c382a2372edcc99e2e4a
[MINIOS]Mapping page frames on demand added to the memory management.
Signed-off-by: Steven Smith <sos22@xxxxxxxxx>
Signed-off-by: Grzegorz Milos <gm281@xxxxxxxxx>
---
 extras/mini-os/include/mm.h |    8 ++
 extras/mini-os/mm.c         |  125 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 129 insertions(+), 4 deletions(-)

diff -r 462d6e4cb29a -r 4db818a7dc3f extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h       Wed Jul 05 14:27:27 2006 +0100
+++ b/extras/mini-os/include/mm.h       Wed Jul 05 14:29:13 2006 +0100
@@ -196,9 +196,11 @@ static __inline__ paddr_t machine_to_phy
 #define to_virt(x)                 ((void *)((unsigned long)(x)+VIRT_START))
 
 #define virt_to_pfn(_virt)         (PFN_DOWN(to_phys(_virt)))
+#define virt_to_mfn(_virt)         (pfn_to_mfn(virt_to_pfn(_virt)))
 #define mach_to_virt(_mach)        (to_virt(machine_to_phys(_mach)))
+#define virt_to_mach(_virt)        (phys_to_machine(to_phys(_virt)))
 #define mfn_to_virt(_mfn)          (to_virt(mfn_to_pfn(_mfn) << PAGE_SHIFT))
-#define pfn_to_virt(_pfn)          (to_virt(_pfn << PAGE_SHIFT))
+#define pfn_to_virt(_pfn)          (to_virt((_pfn) << PAGE_SHIFT))
 
 /* Pagetable walking. */
 #define pte_to_mfn(_pte)           (((_pte) & (PADDR_MASK&PAGE_MASK)) >> 
L1_PAGETABLE_SHIFT)
@@ -206,7 +208,7 @@ static __inline__ paddr_t machine_to_phy
 
 void init_mm(void);
 unsigned long alloc_pages(int order);
-#define alloc_page()    alloc_pages(0);
+#define alloc_page()    alloc_pages(0)
 void free_pages(void *pointer, int order);
 
 static __inline__ int get_order(unsigned long size)
@@ -219,4 +221,6 @@ static __inline__ int get_order(unsigned
 }
 
 
+void *map_frames(unsigned long *f, unsigned long n);
+
 #endif /* _MM_H_ */
diff -r 462d6e4cb29a -r 4db818a7dc3f extras/mini-os/mm.c
--- a/extras/mini-os/mm.c       Wed Jul 05 14:27:27 2006 +0100
+++ b/extras/mini-os/mm.c       Wed Jul 05 14:29:13 2006 +0100
@@ -343,7 +343,7 @@ void free_pages(void *pointer, int order
                 break;
             
             /* Merge with successor */
-            freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask);
+            freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask) - 1;
         }
         
         /* We are commited to merging, unlink the chunk */
@@ -612,6 +612,107 @@ void mem_test(unsigned long *start_add, 
 
 }
 
+static pgentry_t *demand_map_pgt;
+static void *demand_map_area_start;
+
+static void init_demand_mapping_area(unsigned long max_pfn)
+{
+    unsigned long mfn;
+    pgentry_t *tab;
+    unsigned long start_addr;
+    unsigned long pt_pfn;
+    unsigned offset;
+
+    /* Round up to four megs.  + 1024 rather than + 1023 since we want
+       to be sure we don't end up in the same place we started. */
+    max_pfn = (max_pfn + L1_PAGETABLE_ENTRIES) & ~(L1_PAGETABLE_ENTRIES - 1);
+    if (max_pfn == 0 ||
+            (unsigned long)pfn_to_virt(max_pfn + L1_PAGETABLE_ENTRIES) >=
+            HYPERVISOR_VIRT_START) {
+        printk("Too much memory; no room for demand map hole.\n");
+        do_exit();
+    }
+
+    demand_map_area_start = pfn_to_virt(max_pfn);
+    printk("Demand map pfns start at %lx (%p).\n", max_pfn,
+            demand_map_area_start);
+    start_addr = (unsigned long)demand_map_area_start;
+
+    tab = (pgentry_t *)start_info.pt_base;
+    mfn = virt_to_mfn(start_info.pt_base);
+    pt_pfn = virt_to_pfn(alloc_page());
+
+#if defined(__x86_64__)
+    offset = l4_table_offset(start_addr);
+    if (!(tab[offset] & _PAGE_PRESENT)) {
+        new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME);
+        pt_pfn = virt_to_pfn(alloc_page());
+    }
+    ASSERT(tab[offset] & _PAGE_PRESENT);
+    mfn = pte_to_mfn(tab[offset]);
+    tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+#endif
+#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
+    offset = l3_table_offset(start_addr);
+    if (!(tab[offset] & _PAGE_PRESENT)) {
+        new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME);
+        pt_pfn = virt_to_pfn(alloc_page());
+    }
+    ASSERT(tab[offset] & _PAGE_PRESENT);
+    mfn = pte_to_mfn(tab[offset]);
+    tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+#endif
+    offset = l2_table_offset(start_addr);
+    if (tab[offset] & _PAGE_PRESENT) {
+        printk("Demand map area already has a page table covering it?\n");
+        BUG();
+    }
+    demand_map_pgt = pfn_to_virt(pt_pfn);
+    new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME);
+    ASSERT(tab[offset] & _PAGE_PRESENT);
+}
+
+void *map_frames(unsigned long *f, unsigned long n)
+{
+    unsigned long x;
+    unsigned long y = 0;
+    mmu_update_t mmu_updates[16];
+    int rc;
+
+    if (n > 16) {
+        printk("Tried to map too many (%ld) frames at once.\n", n);
+        return NULL;
+    }
+
+    /* Find a run of n contiguous frames */
+    for (x = 0; x <= 1024 - n; x += y + 1) {
+        for (y = 0; y < n; y++)
+            if (demand_map_pgt[y] & _PAGE_PRESENT)
+                break;
+        if (y == n)
+            break;
+    }
+    if (y != n) {
+        printk("Failed to map %ld frames!\n", n);
+        return NULL;
+    }
+
+    /* Found it at x.  Map it in. */
+    for (y = 0; y < n; y++) {
+        mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + y]);
+        mmu_updates[y].val = (f[y] << PAGE_SHIFT) | L1_PROT;
+    }
+
+    rc = HYPERVISOR_mmu_update(mmu_updates, n, NULL, DOMID_SELF);
+    if (rc < 0) {
+        printk("Map %ld failed: %d.\n", n, rc);
+        return NULL;
+    } else {
+        return (void *)(unsigned long)((unsigned long)demand_map_area_start +
+                x * PAGE_SIZE);
+    }
+}
+
 void init_mm(void)
 {
 
@@ -643,4 +744,24 @@ void init_mm(void)
            (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
     init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
     printk("MM: done\n");
-}
+
+    init_demand_mapping_area(max_pfn);
+    printk("Initialised demand area.\n");
+}
+
+void sanity_check(void)
+{
+    int x;
+    chunk_head_t *head;
+
+    for (x = 0; x < FREELIST_SIZE; x++) {
+        for (head = free_head[x]; !FREELIST_EMPTY(head); head = head->next) {
+            ASSERT(!allocated_in_map(virt_to_pfn(head)));
+            if (head->next)
+                ASSERT(head->next->pprev == &head->next);
+        }
+        if (free_head[x]) {
+            ASSERT(free_head[x]->pprev == &free_head[x]);
+        }
+    }
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.