ia64/xen-unstable

changeset 19253:9c4a38f70b16

minios: add ioremap/iounmap

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@netronome.com>
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Mar 02 10:50:59 2009 +0000 (2009-03-02)
parents b3774712e654
children 08916e5135b3
files extras/mini-os/arch/ia64/mm.c extras/mini-os/arch/x86/ioremap.c extras/mini-os/arch/x86/mm.c extras/mini-os/include/ioremap.h extras/mini-os/include/mm.h extras/mini-os/include/x86/arch_mm.h extras/mini-os/lib/sys.c
line diff
     1.1 --- a/extras/mini-os/arch/ia64/mm.c	Mon Mar 02 10:34:37 2009 +0000
     1.2 +++ b/extras/mini-os/arch/ia64/mm.c	Mon Mar 02 10:50:59 2009 +0000
     1.3 @@ -156,6 +156,12 @@ map_frames_ex(unsigned long* frames, uns
     1.4  	return (void*) __va(frames[0] << PAGE_SHIFT);
     1.5  }
     1.6  
     1.7 +int unmap_frames(unsigned long virt_addr, unsigned long num_frames)
     1.8 +{  
     1.9 +    /* TODO */
    1.10 +    ASSERT(0);
    1.11 +}
    1.12 +
    1.13  void arch_init_p2m(unsigned long max_pfn)
    1.14  {
    1.15      printk("Warn: p2m map not implemented.\n");
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/extras/mini-os/arch/x86/ioremap.c	Mon Mar 02 10:50:59 2009 +0000
     2.3 @@ -0,0 +1,88 @@
     2.4 +/*
     2.5 + * Copyright (C) 2009,  Netronome Systems, Inc.
     2.6 + *                
     2.7 + * Permission is hereby granted, free of charge, to any person obtaining a copy
     2.8 + * of this software and associated documentation files (the "Software"), to
     2.9 + * deal in the Software without restriction, including without limitation the
    2.10 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    2.11 + * sell copies of the Software, and to permit persons to whom the Software is
    2.12 + * furnished to do so, subject to the following conditions:
    2.13 + * 
    2.14 + * The above copyright notice and this permission notice shall be included in
    2.15 + * all copies or substantial portions of the Software.
    2.16 + * 
    2.17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    2.18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    2.19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    2.20 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    2.21 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    2.22 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    2.23 + * DEALINGS IN THE SOFTWARE.
    2.24 + */
    2.25 +
    2.26 +
    2.27 +#include <types.h>
    2.28 +#include <lib.h>
    2.29 +#include <xmalloc.h>
    2.30 +#include <mm.h>
    2.31 +#include <ioremap.h>
    2.32 +
    2.33 +/* Map a physical address range into virtual address space with provided
    2.34 + * flags. Return a virtual address range it is mapped to. */
    2.35 +static void *__do_ioremap(unsigned long phys_addr, unsigned long size, 
    2.36 +                          unsigned long prot)
    2.37 +{
    2.38 +    unsigned long va;
    2.39 +    unsigned long mfns, mfn;
    2.40 +    unsigned long num_pages, offset;
    2.41 +    int i;
    2.42 +
    2.43 +    /* allow non page aligned addresses but for mapping we need to align them */
    2.44 +    offset = (phys_addr & ~PAGE_MASK);
    2.45 +    num_pages = (offset + size + PAGE_SIZE - 1) / PAGE_SIZE;
    2.46 +    phys_addr &= PAGE_MASK;
    2.47 +    mfns = mfn = phys_addr >> PAGE_SHIFT;
    2.48 +    
    2.49 +    /* sanity checks on list of MFNs */
    2.50 +    for ( i = 0; i < num_pages; i++, mfn++ )
    2.51 +    {
    2.52 +        if ( mfn_is_ram(mfn) )
    2.53 +        {
    2.54 +            printk("ioremap: mfn 0x%ulx is RAM\n", mfn);
    2.55 +            goto mfn_invalid;
    2.56 +        }
    2.57 +    }   
    2.58 +    va = (unsigned long)map_frames_ex(&mfns, num_pages, 0, 1, 1,
    2.59 +                                      DOMID_IO, 0, prot);
    2.60 +    return (void *)(va + offset);
    2.61 +    
    2.62 +mfn_invalid:
    2.63 +    return NULL;
    2.64 +}
    2.65 +
    2.66 +void *ioremap(unsigned long phys_addr, unsigned long size)
    2.67 +{
    2.68 +    return __do_ioremap(phys_addr, size, IO_PROT);
    2.69 +}
    2.70 +
    2.71 +void *ioremap_nocache(unsigned long phys_addr, unsigned long size)
    2.72 +{
    2.73 +    return __do_ioremap(phys_addr, size, IO_PROT_NOCACHE);
    2.74 +}
    2.75 +
    2.76 +/* Un-map the io-remapped region. Currently no list of existing mappings is
    2.77 + * maintained, so the caller has to supply the size */
    2.78 +void iounmap(void *virt_addr, unsigned long size)
    2.79 +{   
    2.80 +    unsigned long num_pages;
    2.81 +    unsigned long va = (unsigned long)virt_addr;
    2.82 +
    2.83 +    /* work out number of frames to unmap */
    2.84 +    num_pages = ((va & ~PAGE_MASK) + size + PAGE_SIZE - 1) / PAGE_SIZE;
    2.85 +
    2.86 +    unmap_frames(va & PAGE_MASK, num_pages);
    2.87 +}
    2.88 +
    2.89 +
    2.90 +
    2.91 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 indent-tabs-mode:nil -*- */
     3.1 --- a/extras/mini-os/arch/x86/mm.c	Mon Mar 02 10:34:37 2009 +0000
     3.2 +++ b/extras/mini-os/arch/x86/mm.c	Mon Mar 02 10:50:59 2009 +0000
     3.3 @@ -316,31 +316,60 @@ static void set_readonly(void *text, voi
     3.4      }
     3.5  }
     3.6  
     3.7 -void mem_test(unsigned long *start_add, unsigned long *end_add)
     3.8 +/*
     3.9 + * A useful mem testing function. Write the address to every address in the
    3.10 + * range provided and read back the value. If verbose, print page walk to
    3.11 + * some VA
    3.12 + * 
    3.13 + * If we get MEM_TEST_MAX_ERRORS we might as well stop
    3.14 + */
    3.15 +#define MEM_TEST_MAX_ERRORS 10 
    3.16 +int mem_test(unsigned long *start_va, unsigned long *end_va, int verbose)
    3.17  {
    3.18      unsigned long mask = 0x10000;
    3.19      unsigned long *pointer;
    3.20 -
    3.21 -    for(pointer = start_add; pointer < end_add; pointer++)
    3.22 +    int error_count = 0;
    3.23 + 
    3.24 +    /* write values and print page walks */
    3.25 +    if ( verbose && (((unsigned long)start_va) & 0xfffff) )
    3.26      {
    3.27 -        if(!(((unsigned long)pointer) & 0xfffff))
    3.28 +        printk("MemTest Start: 0x%lx\n", start_va);
    3.29 +        page_walk((unsigned long)start_va);
    3.30 +    }
    3.31 +    for ( pointer = start_va; pointer < end_va; pointer++ )
    3.32 +    {
    3.33 +        if ( verbose && !(((unsigned long)pointer) & 0xfffff) )
    3.34          {
    3.35              printk("Writing to %lx\n", pointer);
    3.36              page_walk((unsigned long)pointer);
    3.37          }
    3.38          *pointer = (unsigned long)pointer & ~mask;
    3.39      }
    3.40 -
    3.41 -    for(pointer = start_add; pointer < end_add; pointer++)
    3.42 +    if ( verbose && (((unsigned long)end_va) & 0xfffff) )
    3.43      {
    3.44 -        if(((unsigned long)pointer & ~mask) != *pointer)
    3.45 +        printk("MemTest End: %lx\n", end_va-1);
    3.46 +        page_walk((unsigned long)end_va-1);
    3.47 +    }
    3.48 + 
    3.49 +    /* verify values */
    3.50 +    for ( pointer = start_va; pointer < end_va; pointer++ )
    3.51 +    {
    3.52 +        if ( ((unsigned long)pointer & ~mask) != *pointer )
    3.53 +        {
    3.54              printk("Read error at 0x%lx. Read: 0x%lx, should read 0x%lx\n",
    3.55 -                (unsigned long)pointer, 
    3.56 -                *pointer, 
    3.57 -                ((unsigned long)pointer & ~mask));
    3.58 +                   (unsigned long)pointer, *pointer, 
    3.59 +                   ((unsigned long)pointer & ~mask));
    3.60 +            error_count++;
    3.61 +            if ( error_count >= MEM_TEST_MAX_ERRORS )
    3.62 +            {
    3.63 +                printk("mem_test: too many errors\n");
    3.64 +                return -1;
    3.65 +            }
    3.66 +        }
    3.67      }
    3.68 +    return 0;
    3.69 +}
    3.70  
    3.71 -}
    3.72  
    3.73  static pgentry_t *get_pgt(unsigned long addr)
    3.74  {
    3.75 @@ -537,6 +566,72 @@ void *map_frames_ex(unsigned long *f, un
    3.76      return (void *)addr;
    3.77  }
    3.78  
    3.79 +/*
    3.80 + * Unmap nun_frames frames mapped at virtual address va.
    3.81 + */
    3.82 +#define UNMAP_BATCH ((STACK_SIZE / 2) / sizeof(multicall_entry_t))
    3.83 +int unmap_frames(unsigned long va, unsigned long num_frames)
    3.84 +{
    3.85 +    int n = UNMAP_BATCH;
    3.86 +    multicall_entry_t call[n];
    3.87 +    int ret;
    3.88 +    int i;
    3.89 +
    3.90 +    ASSERT(!((unsigned long)va & ~PAGE_MASK));
    3.91 +
    3.92 +    DEBUG("va=%p, num=0x%lx\n", va, num_frames);
    3.93 +
    3.94 +    while ( num_frames ) {
    3.95 +        if ( n > num_frames )
    3.96 +            n = num_frames;
    3.97 +
    3.98 +        for ( i = 0; i < n; i++ )
    3.99 +        {
   3.100 +            int arg = 0;
   3.101 +            /* simply update the PTE for the VA and invalidate TLB */
   3.102 +            call[i].op = __HYPERVISOR_update_va_mapping;
   3.103 +            call[i].args[arg++] = va;
   3.104 +            call[i].args[arg++] = 0;
   3.105 +#ifdef __i386__
   3.106 +            call[i].args[arg++] = 0;
   3.107 +#endif  
   3.108 +            call[i].args[arg++] = UVMF_INVLPG;
   3.109 +
   3.110 +            va += PAGE_SIZE;
   3.111 +        }
   3.112 +
   3.113 +        ret = HYPERVISOR_multicall(call, n);
   3.114 +        if ( ret )
   3.115 +        {
   3.116 +            printk("update_va_mapping hypercall failed with rc=%d.\n", ret);
   3.117 +            return -ret;
   3.118 +        }
   3.119 +
   3.120 +        for ( i = 0; i < n; i++ )
   3.121 +        {
   3.122 +            if ( call[i].result ) 
   3.123 +            {
   3.124 +                printk("update_va_mapping failed for with rc=%d.\n", ret);
   3.125 +                return -(call[i].result);
   3.126 +            }
   3.127 +        }
   3.128 +        num_frames -= n;
   3.129 +    }
   3.130 +    return 0;
   3.131 +}
   3.132 +
   3.133 +/*
   3.134 + * Check if a given MFN refers to real memory
   3.135 + */
   3.136 +static long system_ram_end_mfn;
   3.137 +int mfn_is_ram(unsigned long mfn)
   3.138 +{
   3.139 +    /* very crude check if a given MFN is memory or not. Probably should
   3.140 +     * make this a little more sophisticated ;) */
   3.141 +    return (mfn <= system_ram_end_mfn) ? 1 : 0;
   3.142 +}
   3.143 +
   3.144 +
   3.145  static void clear_bootstrap(void)
   3.146  {
   3.147      pte_t nullpte = { };
   3.148 @@ -625,6 +720,10 @@ void arch_init_mm(unsigned long* start_p
   3.149      clear_bootstrap();
   3.150      set_readonly(&_text, &_erodata);
   3.151  
   3.152 +    /* get the number of physical pages the system has. Used to check for
   3.153 +     * system memory. */
   3.154 +    system_ram_end_mfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
   3.155 +
   3.156      *start_pfn_p = start_pfn;
   3.157      *max_pfn_p = max_pfn;
   3.158  }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/extras/mini-os/include/ioremap.h	Mon Mar 02 10:50:59 2009 +0000
     4.3 @@ -0,0 +1,33 @@
     4.4 +/**
     4.5 + * Copyright (C) 2009 Netronome Systems, Inc.  All rights reserved.
     4.6 + *
     4.7 + * Permission is hereby granted, free of charge, to any person obtaining a copy
     4.8 + * of this software and associated documentation files (the "Software"), to
     4.9 + * deal in the Software without restriction, including without limitation the
    4.10 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    4.11 + * sell copies of the Software, and to permit persons to whom the Software is
    4.12 + * furnished to do so, subject to the following conditions:
    4.13 + * 
    4.14 + * The above copyright notice and this permission notice shall be included in
    4.15 + * all copies or substantial portions of the Software.
    4.16 + * 
    4.17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    4.18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    4.19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    4.20 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    4.21 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    4.22 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    4.23 + * DEALINGS IN THE SOFTWARE.
    4.24 + */
    4.25 +
    4.26 +
    4.27 +#ifndef _IOREMAP_H_
    4.28 +#define _IOREMAP_H_
    4.29 +
    4.30 +void *ioremap(unsigned long phys_addr, unsigned long size);
    4.31 +void *ioremap_nocache(unsigned long phys_addr, unsigned long size);
    4.32 +void iounmap(void *virt_addr, unsigned long size);
    4.33 +
    4.34 +#endif /* _IOREMAP_H_ */
    4.35 +
    4.36 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 indent-tabs-mode:nil -*- */
     5.1 --- a/extras/mini-os/include/mm.h	Mon Mar 02 10:34:37 2009 +0000
     5.2 +++ b/extras/mini-os/include/mm.h	Mon Mar 02 10:50:59 2009 +0000
     5.3 @@ -71,6 +71,7 @@ void *map_frames_ex(unsigned long *f, un
     5.4  void do_map_frames(unsigned long addr,
     5.5          unsigned long *f, unsigned long n, unsigned long stride,
     5.6  	unsigned long increment, domid_t id, int may_fail, unsigned long prot);
     5.7 +int unmap_frames(unsigned long va, unsigned long num_frames);
     5.8  #ifdef HAVE_LIBC
     5.9  extern unsigned long heap, brk, heap_mapped, heap_end;
    5.10  #endif
     6.1 --- a/extras/mini-os/include/x86/arch_mm.h	Mon Mar 02 10:34:37 2009 +0000
     6.2 +++ b/extras/mini-os/include/x86/arch_mm.h	Mon Mar 02 10:50:59 2009 +0000
     6.3 @@ -133,6 +133,10 @@ typedef unsigned long pgentry_t;
     6.4  #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
     6.5  #endif /* __i386__ || __x86_64__ */
     6.6  
     6.7 +/* flags for ioremap */
     6.8 +#define IO_PROT (L1_PROT)
     6.9 +#define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD)
    6.10 +
    6.11  #include "arch_limits.h"
    6.12  #define PAGE_SIZE       __PAGE_SIZE
    6.13  #define PAGE_SHIFT      __PAGE_SHIFT
    6.14 @@ -222,5 +226,6 @@ static __inline__ paddr_t machine_to_phy
    6.15  #define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, DOMID_SELF, 0, L1_PROT_RO)
    6.16  
    6.17  pgentry_t *need_pgt(unsigned long addr);
    6.18 +int mfn_is_ram(unsigned long mfn);
    6.19  
    6.20  #endif /* _ARCH_MM_H_ */
     7.1 --- a/extras/mini-os/lib/sys.c	Mon Mar 02 10:34:37 2009 +0000
     7.2 +++ b/extras/mini-os/lib/sys.c	Mon Mar 02 10:50:59 2009 +0000
     7.3 @@ -1206,47 +1206,15 @@ void *mmap(void *start, size_t length, i
     7.4      } else ASSERT(0);
     7.5  }
     7.6  
     7.7 -#define UNMAP_BATCH ((STACK_SIZE / 2) / sizeof(multicall_entry_t))
     7.8  int munmap(void *start, size_t length)
     7.9  {
    7.10      int total = length / PAGE_SIZE;
    7.11 -    ASSERT(!((unsigned long)start & ~PAGE_MASK));
    7.12 -    while (total) {
    7.13 -        int n = UNMAP_BATCH;
    7.14 -        if (n > total)
    7.15 -            n = total;
    7.16 -        {
    7.17 -            int i;
    7.18 -            multicall_entry_t call[n];
    7.19 -            unsigned char (*data)[PAGE_SIZE] = start;
    7.20 -            int ret;
    7.21 +    int ret;
    7.22  
    7.23 -            for (i = 0; i < n; i++) {
    7.24 -                int arg = 0;
    7.25 -                call[i].op = __HYPERVISOR_update_va_mapping;
    7.26 -                call[i].args[arg++] = (unsigned long) &data[i];
    7.27 -                call[i].args[arg++] = 0;
    7.28 -#ifdef __i386__
    7.29 -                call[i].args[arg++] = 0;
    7.30 -#endif
    7.31 -                call[i].args[arg++] = UVMF_INVLPG;
    7.32 -            }
    7.33 -
    7.34 -            ret = HYPERVISOR_multicall(call, n);
    7.35 -            if (ret) {
    7.36 -                errno = -ret;
    7.37 -                return -1;
    7.38 -            }
    7.39 -
    7.40 -            for (i = 0; i < n; i++) {
    7.41 -                if (call[i].result) {
    7.42 -                    errno = call[i].result;
    7.43 -                    return -1;
    7.44 -                }
    7.45 -            }
    7.46 -        }
    7.47 -        start = (char *)start + n * PAGE_SIZE;
    7.48 -        total -= n;
    7.49 +    ret = unmap_frames((unsigned long)start, (unsigned long)total);
    7.50 +    if (ret) {
    7.51 +        errno = ret;
    7.52 +        return -1;
    7.53      }
    7.54      return 0;
    7.55  }