WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: Xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 1/3] minios: add ioremap/iounmap
From: Rolf Neugebauer <rolf.neugebauer@xxxxxxxxxxxxx>
Date: Thu, 19 Feb 2009 18:04:41 +0000
Cc: samuel.thibault@xxxxxxxxxxxx
Delivery-date: Thu, 19 Feb 2009 10:06:13 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 2.0.0.12 (X11/20080226)
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 11c2a7e44ee6 extras/mini-os/arch/ia64/mm.c
--- a/extras/mini-os/arch/ia64/mm.c     Thu Feb 19 16:38:53 2009 +0000
+++ b/extras/mini-os/arch/ia64/mm.c     Thu Feb 19 16:39:01 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 11c2a7e44ee6 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 Thu Feb 19 16:39:01 2009 +0000
@@ -0,0 +1,93 @@
+/*
+ * 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;
+    mfn = phys_addr >> PAGE_SHIFT;
+
+    /* 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);
+    return (void *)(va + offset);
+
+
+mfn_invalid:
+    xfree(mfns);
+    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 11c2a7e44ee6 extras/mini-os/arch/x86/mm.c
--- a/extras/mini-os/arch/x86/mm.c      Thu Feb 19 16:38:53 2009 +0000
+++ b/extras/mini-os/arch/x86/mm.c      Thu Feb 19 16:39:01 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 11c2a7e44ee6 extras/mini-os/include/ioremap.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/ioremap.h  Thu Feb 19 16:39:01 2009 +0000
@@ -0,0 +1,45 @@
+/**
+ * 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_
+
+/* 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
+
+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 11c2a7e44ee6 extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h       Thu Feb 19 16:38:53 2009 +0000
+++ b/extras/mini-os/include/mm.h       Thu Feb 19 16:39:01 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 11c2a7e44ee6 extras/mini-os/include/x86/arch_mm.h
--- a/extras/mini-os/include/x86/arch_mm.h      Thu Feb 19 16:38:53 2009 +0000
+++ b/extras/mini-os/include/x86/arch_mm.h      Thu Feb 19 16:39:01 2009 +0000
@@ -222,5 +222,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 11c2a7e44ee6 extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c  Thu Feb 19 16:38:53 2009 +0000
+++ b/extras/mini-os/lib/sys.c  Thu Feb 19 16:39:01 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

<Prev in Thread] Current Thread [Next in Thread>