]> xenbits.xensource.com Git - mini-os.git/commitdiff
minios: extend map_frames into being able to map a series of
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 18 Jan 2008 15:22:42 +0000 (15:22 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 18 Jan 2008 15:22:42 +0000 (15:22 +0000)
contiguous frames, or the same frame several times, aligned, from
another domain, with specific protection, and with potential
failures.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
arch/ia64/mm.c
arch/x86/mm.c
include/ia64/arch_mm.h
include/mm.h
include/x86/arch_mm.h

index cb1699a9ab1d97fb753aeb8f4d7acabb5f26ab43..f55773025749a5ce287ea965b9f176752c42a7a7 100644 (file)
@@ -124,9 +124,14 @@ arch_init_demand_mapping_area(unsigned long max_pfn)
 
 /* Helper function used in gnttab.c. */
 void*
-map_frames(unsigned long* frames, unsigned long n)
+map_frames_ex(unsigned long* frames, unsigned long n, unsigned long stride,
+       unsigned long increment, unsigned long alignment, domid_t id,
+       int may_fail, unsigned long prot)
 {
-       n = n;
+        /* TODO: incomplete! */
+        ASSERT(n == 1 || (stride == 0 && increment == 1));
+        ASSERT(id == DOMID_SELF);
+        ASSERT(prot == 0);
        return (void*) __va(SWAP(frames[0]) << PAGE_SHIFT);
 }
 
index 78e6c7638b78317215d4d9f08224f8d1b1aa87f9..53becda146bd769bbe5a4cd443c9907586686e8c 100644 (file)
@@ -367,6 +367,7 @@ void mem_test(unsigned long *start_add, unsigned long *end_add)
 
 static pgentry_t *demand_map_pgt;
 static void *demand_map_area_start;
+#define DEMAND_MAP_PAGES 1024
 
 void arch_init_demand_mapping_area(unsigned long max_pfn)
 {
@@ -426,20 +427,19 @@ void arch_init_demand_mapping_area(unsigned long max_pfn)
     printk("Initialised demand area.\n");
 }
 
-void *map_frames(unsigned long *f, unsigned long n)
+#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
+
+void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
+       unsigned long increment, unsigned long alignment, domid_t id,
+       int may_fail, unsigned long prot)
 {
     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;
-    }
+    unsigned long done = 0;
 
     /* Find a run of n contiguous frames */
-    for (x = 0; x <= 1024 - n; x += y + 1) {
+    for (x = 0; x <= DEMAND_MAP_PAGES - n; x = (x + y + 1 + alignment - 1) & ~(alignment - 1)) {
         for (y = 0; y < n; y++)
             if (demand_map_pgt[x+y] & _PAGE_PRESENT)
                 break;
@@ -447,24 +447,46 @@ void *map_frames(unsigned long *f, unsigned long n)
             break;
     }
     if (y != n) {
-        printk("Failed to map %ld frames!\n", n);
+        printk("Failed to find %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);
+    while (done < n) {
+       unsigned long todo;
+
+       if (may_fail)
+           todo = 1;
+       else
+           todo = n - done;
+
+       if (todo > MAP_BATCH)
+               todo = MAP_BATCH;
+
+       {
+           mmu_update_t mmu_updates[todo];
+
+           for (y = 0; y < todo; y++) {
+               mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + done + y]);
+               mmu_updates[y].val = ((f[(done + y) * stride] + (done + y) * increment) << PAGE_SHIFT) | prot;
+           }
+
+           rc = HYPERVISOR_mmu_update(mmu_updates, todo, NULL, id);
+           if (rc < 0) {
+               if (may_fail)
+                   f[done * stride] |= 0xF0000000;
+               else {
+                   printk("Map %ld (%lx, ...) failed: %d.\n", todo, f[done * stride], rc);
+                   return NULL;
+               }
+           }
+       }
+
+       done += todo;
     }
+    return (void *)(unsigned long)((unsigned long)demand_map_area_start +
+           x * PAGE_SIZE);
 }
 
 static void clear_bootstrap(void)
index 9c18e003781bf74381afee8084a9dd8e773fd762..c1506ac9885c61bd4537342ab964c8588f1d4d3a 100644 (file)
@@ -36,4 +36,6 @@
 #define STACK_SIZE_PAGE_ORDER   1
 #define STACK_SIZE              (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER))
 
+#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, 0)
+
 #endif /* __ARCH_MM_H__ */
index a9c0f2c181c51b2c0dd69a2e5137b93ea701b7b0..4319fa26405bd50e31410ee6203422de516457c0 100644 (file)
@@ -57,6 +57,9 @@ void arch_init_demand_mapping_area(unsigned long max_pfn);
 void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p);
 void arch_init_p2m(unsigned long max_pfn_p);
 
-void *map_frames(unsigned long *f, unsigned long n);
+/* map f[i*stride]+i*increment for i in 0..n-1, aligned on alignment pages */
+void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
+       unsigned long increment, unsigned long alignment, domid_t id,
+       int may_fail, unsigned long prot);
 
 #endif /* _MM_H_ */
index 5c7f06147190caa60f010d94fa5d5e5311cff624..8ae845131a00e7ba813a3916b9a98cb0ebe47988 100644 (file)
@@ -223,5 +223,6 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine)
 #define pte_to_mfn(_pte)           (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT)
 #define pte_to_virt(_pte)          to_virt(mfn_to_pfn(pte_to_mfn(_pte)) << PAGE_SHIFT)
 
+#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, L1_PROT)
 
 #endif /* _ARCH_MM_H_ */