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

[Xen-devel] Re: [PATCH 1/3] minios: add ioremap/iounmap





Samuel Thibault wrote:
Rolf Neugebauer, le Thu 19 Feb 2009 18:04:41 +0000, a écrit :
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy

The lines of the patch got wrapped.

+    /* create a list of MFNs to map */
+    mfns = xmalloc_array(unsigned long, num_pages);
+    for ( i = 0; i < num_pages; i++, mfn++ )
+    {
+        if ( mfn_is_ram(mfn) )
+        {
+            printk("ioremap: mfn 0x%ulx is RAM\n", mfn);
+            goto mfn_invalid;
+        }
+
+        mfns[i] = mfn;
+    }
+    va = (unsigned long)map_frames_ex(mfns, num_pages, 1, 0, 1,
+                                      DOMID_IO, 0, prot);

Instead of allocating an array, why not using the incr parameter of
map_frames_ex?

+/* Maybe these should be defined in the respective arch_mm.h */
+#if defined(__i386__) || defined(__x86_64__)
+#define IO_PROT (L1_PROT)
+#define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD)
+#elif defined(__ia64__)
+/* XXX IA64 needs to define these as appropriate. */
+#define IO_PROT 0
+#define IO_PROT_NOCACHE 0
+#else
+#error "Unsupported architecture"
+#endif

Shouldn't these go to include/<arch>/arch_mm.h?

Samuel

Thanks for your comments. An updated patch is
attached (hopefully without my mailer wrapping the line)

rolf

Add ioremap and iounmap functions to minios. Also move some unmapping
code from and clean up mem_test.

Signed-off-by: Rolf Neugebauer <rolf.neugebauer@xxxxxxxxxxxxx>
---
diff -r 13688a8401c1 extras/mini-os/arch/ia64/mm.c
--- a/extras/mini-os/arch/ia64/mm.c     Thu Feb 19 17:28:28 2009 +0000
+++ b/extras/mini-os/arch/ia64/mm.c     Tue Feb 24 10:58:46 2009 +0000
@@ -156,6 +156,12 @@
        return (void*) __va(frames[0] << PAGE_SHIFT);
 }

+int unmap_frames(unsigned long virt_addr, unsigned long num_frames)
+{
+    /* TODO */
+    ASSERT(0);
+}
+
 void arch_init_p2m(unsigned long max_pfn)
 {
     printk("Warn: p2m map not implemented.\n");
diff -r 13688a8401c1 extras/mini-os/arch/x86/ioremap.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/arch/x86/ioremap.c Tue Feb 24 10:58:46 2009 +0000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2009,  Netronome Systems, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <types.h>
+#include <lib.h>
+#include <xmalloc.h>
+#include <mm.h>
+#include <ioremap.h>
+
+/* Map a physical address range into virtual address space with provided
+ * flags. Return a virtual address range it is mapped to. */
+static void *__do_ioremap(unsigned long phys_addr, unsigned long size,
+                          unsigned long prot)
+{
+    unsigned long va;
+    unsigned long mfns, mfn;
+    unsigned long num_pages, offset;
+    int i;
+
+ /* allow non page aligned addresses but for mapping we need to align them */
+    offset = (phys_addr & ~PAGE_MASK);
+    num_pages = (offset + size + PAGE_SIZE - 1) / PAGE_SIZE;
+    phys_addr &= PAGE_MASK;
+    mfns = mfn = phys_addr >> PAGE_SHIFT;
+
+    /* sanity checks on list of MFNs */
+    for ( i = 0; i < num_pages; i++, mfn++ )
+    {
+        if ( mfn_is_ram(mfn) )
+        {
+            printk("ioremap: mfn 0x%ulx is RAM\n", mfn);
+            goto mfn_invalid;
+        }
+    }
+    va = (unsigned long)map_frames_ex(&mfns, num_pages, 0, 1, 1,
+                                      DOMID_IO, 0, prot);
+    return (void *)(va + offset);
+
+mfn_invalid:
+    return NULL;
+}
+
+void *ioremap(unsigned long phys_addr, unsigned long size)
+{
+    return __do_ioremap(phys_addr, size, IO_PROT);
+}
+
+void *ioremap_nocache(unsigned long phys_addr, unsigned long size)
+{
+    return __do_ioremap(phys_addr, size, IO_PROT_NOCACHE);
+}
+
+/* Un-map the io-remapped region. Currently no list of existing mappings is
+ * maintained, so the caller has to supply the size */
+void iounmap(void *virt_addr, unsigned long size)
+{
+    unsigned long num_pages;
+    unsigned long va = (unsigned long)virt_addr;
+
+    /* work out number of frames to unmap */
+    num_pages = ((va & ~PAGE_MASK) + size + PAGE_SIZE - 1) / PAGE_SIZE;
+
+    unmap_frames(va & PAGE_MASK, num_pages);
+}
+
+
+
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4 indent-tabs-mode:nil -*- */
diff -r 13688a8401c1 extras/mini-os/arch/x86/mm.c
--- a/extras/mini-os/arch/x86/mm.c      Thu Feb 19 17:28:28 2009 +0000
+++ b/extras/mini-os/arch/x86/mm.c      Tue Feb 24 10:58:46 2009 +0000
@@ -316,31 +316,60 @@
     }
 }

-void mem_test(unsigned long *start_add, unsigned long *end_add)
+/*
+ * A useful mem testing function. Write the address to every address in the
+ * range provided and read back the value. If verbose, print page walk to
+ * some VA
+ *
+ * If we get MEM_TEST_MAX_ERRORS we might as well stop
+ */
+#define MEM_TEST_MAX_ERRORS 10
+int mem_test(unsigned long *start_va, unsigned long *end_va, int verbose)
 {
     unsigned long mask = 0x10000;
     unsigned long *pointer;
-
-    for(pointer = start_add; pointer < end_add; pointer++)
+    int error_count = 0;
+
+    /* write values and print page walks */
+    if ( verbose && (((unsigned long)start_va) & 0xfffff) )
     {
-        if(!(((unsigned long)pointer) & 0xfffff))
+        printk("MemTest Start: 0x%lx\n", start_va);
+        page_walk((unsigned long)start_va);
+    }
+    for ( pointer = start_va; pointer < end_va; pointer++ )
+    {
+        if ( verbose && !(((unsigned long)pointer) & 0xfffff) )
         {
             printk("Writing to %lx\n", pointer);
             page_walk((unsigned long)pointer);
         }
         *pointer = (unsigned long)pointer & ~mask;
     }
+    if ( verbose && (((unsigned long)end_va) & 0xfffff) )
+    {
+        printk("MemTest End: %lx\n", end_va-1);
+        page_walk((unsigned long)end_va-1);
+    }
+
+    /* verify values */
+    for ( pointer = start_va; pointer < end_va; pointer++ )
+    {
+        if ( ((unsigned long)pointer & ~mask) != *pointer )
+        {
+            printk("Read error at 0x%lx. Read: 0x%lx, should read 0x%lx\n",
+                   (unsigned long)pointer, *pointer,
+                   ((unsigned long)pointer & ~mask));
+            error_count++;
+            if ( error_count >= MEM_TEST_MAX_ERRORS )
+            {
+                printk("mem_test: too many errors\n");
+                return -1;
+            }
+        }
+    }
+    return 0;
+}

-    for(pointer = start_add; pointer < end_add; pointer++)
-    {
-        if(((unsigned long)pointer & ~mask) != *pointer)
-            printk("Read error at 0x%lx. Read: 0x%lx, should read 0x%lx\n",
-                (unsigned long)pointer,
-                *pointer,
-                ((unsigned long)pointer & ~mask));
-    }
-
-}

 static pgentry_t *get_pgt(unsigned long addr)
 {
@@ -537,6 +566,72 @@
     return (void *)addr;
 }

+/*
+ * Unmap nun_frames frames mapped at virtual address va.
+ */
+#define UNMAP_BATCH ((STACK_SIZE / 2) / sizeof(multicall_entry_t))
+int unmap_frames(unsigned long va, unsigned long num_frames)
+{
+    int n = UNMAP_BATCH;
+    multicall_entry_t call[n];
+    int ret;
+    int i;
+
+    ASSERT(!((unsigned long)va & ~PAGE_MASK));
+
+    DEBUG("va=%p, num=0x%lx\n", va, num_frames);
+
+    while ( num_frames ) {
+        if ( n > num_frames )
+            n = num_frames;
+
+        for ( i = 0; i < n; i++ )
+        {
+            int arg = 0;
+            /* simply update the PTE for the VA and invalidate TLB */
+            call[i].op = __HYPERVISOR_update_va_mapping;
+            call[i].args[arg++] = va;
+            call[i].args[arg++] = 0;
+#ifdef __i386__
+            call[i].args[arg++] = 0;
+#endif
+            call[i].args[arg++] = UVMF_INVLPG;
+
+            va += PAGE_SIZE;
+        }
+
+        ret = HYPERVISOR_multicall(call, n);
+        if ( ret )
+        {
+ printk("update_va_mapping hypercall failed with rc=%d.\n", ret);
+            return -ret;
+        }
+
+        for ( i = 0; i < n; i++ )
+        {
+            if ( call[i].result )
+            {
+                printk("update_va_mapping failed for with rc=%d.\n", ret);
+                return -(call[i].result);
+            }
+        }
+        num_frames -= n;
+    }
+    return 0;
+}
+
+/*
+ * Check if a given MFN refers to real memory
+ */
+static long system_ram_end_mfn;
+int mfn_is_ram(unsigned long mfn)
+{
+    /* very crude check if a given MFN is memory or not. Probably should
+     * make this a little more sophisticated ;) */
+    return (mfn <= system_ram_end_mfn) ? 1 : 0;
+}
+
+
 static void clear_bootstrap(void)
 {
     pte_t nullpte = { };
@@ -625,6 +720,10 @@
     clear_bootstrap();
     set_readonly(&_text, &_erodata);

+    /* get the number of physical pages the system has. Used to check for
+     * system memory. */
+ system_ram_end_mfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
+
     *start_pfn_p = start_pfn;
     *max_pfn_p = max_pfn;
 }
diff -r 13688a8401c1 extras/mini-os/include/ioremap.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/ioremap.h  Tue Feb 24 10:58:46 2009 +0000
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2009 Netronome Systems, Inc.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _IOREMAP_H_
+#define _IOREMAP_H_
+
+void *ioremap(unsigned long phys_addr, unsigned long size);
+void *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+void iounmap(void *virt_addr, unsigned long size);
+
+#endif /* _IOREMAP_H_ */
+
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4 indent-tabs-mode:nil -*- */
diff -r 13688a8401c1 extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h       Thu Feb 19 17:28:28 2009 +0000
+++ b/extras/mini-os/include/mm.h       Tue Feb 24 10:58:46 2009 +0000
@@ -71,6 +71,7 @@
 void do_map_frames(unsigned long addr,
         unsigned long *f, unsigned long n, unsigned long stride,
        unsigned long increment, domid_t id, int may_fail, unsigned long prot);
+int unmap_frames(unsigned long va, unsigned long num_frames);
 #ifdef HAVE_LIBC
 extern unsigned long heap, brk, heap_mapped, heap_end;
 #endif
diff -r 13688a8401c1 extras/mini-os/include/x86/arch_mm.h
--- a/extras/mini-os/include/x86/arch_mm.h      Thu Feb 19 17:28:28 2009 +0000
+++ b/extras/mini-os/include/x86/arch_mm.h      Tue Feb 24 10:58:46 2009 +0000
@@ -133,6 +133,10 @@
#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
 #endif /* __i386__ || __x86_64__ */

+/* flags for ioremap */
+#define IO_PROT (L1_PROT)
+#define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD)
+
 #include "arch_limits.h"
 #define PAGE_SIZE       __PAGE_SIZE
 #define PAGE_SHIFT      __PAGE_SHIFT
@@ -222,5 +226,6 @@
#define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, DOMID_SELF, 0, L1_PROT_RO)

 pgentry_t *need_pgt(unsigned long addr);
+int mfn_is_ram(unsigned long mfn);

 #endif /* _ARCH_MM_H_ */
diff -r 13688a8401c1 extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c  Thu Feb 19 17:28:28 2009 +0000
+++ b/extras/mini-os/lib/sys.c  Tue Feb 24 10:58:46 2009 +0000
@@ -1206,47 +1206,15 @@
     } else ASSERT(0);
 }

-#define UNMAP_BATCH ((STACK_SIZE / 2) / sizeof(multicall_entry_t))
 int munmap(void *start, size_t length)
 {
     int total = length / PAGE_SIZE;
-    ASSERT(!((unsigned long)start & ~PAGE_MASK));
-    while (total) {
-        int n = UNMAP_BATCH;
-        if (n > total)
-            n = total;
-        {
-            int i;
-            multicall_entry_t call[n];
-            unsigned char (*data)[PAGE_SIZE] = start;
-            int ret;
+    int ret;

-            for (i = 0; i < n; i++) {
-                int arg = 0;
-                call[i].op = __HYPERVISOR_update_va_mapping;
-                call[i].args[arg++] = (unsigned long) &data[i];
-                call[i].args[arg++] = 0;
-#ifdef __i386__
-                call[i].args[arg++] = 0;
-#endif
-                call[i].args[arg++] = UVMF_INVLPG;
-            }
-
-            ret = HYPERVISOR_multicall(call, n);
-            if (ret) {
-                errno = -ret;
-                return -1;
-            }
-
-            for (i = 0; i < n; i++) {
-                if (call[i].result) {
-                    errno = call[i].result;
-                    return -1;
-                }
-            }
-        }
-        start = (char *)start + n * PAGE_SIZE;
-        total -= n;
+    ret = unmap_frames((unsigned long)start, (unsigned long)total);
+    if (ret) {
+        errno = ret;
+        return -1;
     }
     return 0;
 }

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


 


Rackspace

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