Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 #include <unistd.h>
     29 #include <sys/cachectl.h>
     30 
     31 #ifdef DEBUG
     32 #include <private/libc_logging.h>
     33 #define  XLOG(...) __libc_format_log(ANDROID_LOG_DEBUG,"libc-cacheflush",__VA_ARGS__)
     34 #endif
     35 
     36 /*
     37  * Linux historically defines a cacheflush(3) routine for MIPS
     38  * with this signature:
     39  * int cacheflush(char *addr, int nbytes, int cache);
     40  *
     41  * Android defines an alternate cacheflush routine which exposes the
     42  * ARM system call interface:
     43  * int cacheflush (long start, long end, long flags)
     44  *
     45  * This is an attempt to maintain compatibility between the historical MIPS
     46  * usage for software previously ported to MIPS and Android specific
     47  * uses of cacheflush()
     48  *
     49  * Use the gcc __clear_cache builtin if possible. This will generate inline synci
     50  * instructions if available or call _flush_cache(start, len, BCACHE) directly
     51  */
     52 
     53 #if defined (__GNUC__)
     54 #define GCC_VERSION ((__GNUC__*10000) + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
     55 #endif
     56 
     57 /* This is the Android signature */
     58 int cacheflush (long start, long end, long flags)
     59 {
     60 	if (end < start) {
     61 		/*
     62 		 * It looks like this is really MIPS style cacheflush call
     63 		 * start => addr
     64 		 * end => nbytes
     65 		 */
     66 #ifdef DEBUG
     67 		static int warned = 0;
     68 		if (!warned) {
     69 			XLOG("called with (start,len) instead of (start,end)");
     70 			warned = 1;
     71 		}
     72 #endif
     73 		end += start;
     74 	}
     75 
     76 #if !defined(ARCH_MIPS_USE_FLUSHCACHE_SYSCALL) && \
     77 	defined(GCC_VERSION) && (GCC_VERSION >= 40300)
     78 
     79 #if (__mips_isa_rev >= 2) && (GCC_VERSION < 40403)
     80 	/*
     81 	 * Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in
     82 	 * mips_expand_synci_loop that may execute synci one more time.
     83 	 * "start" points to the first byte of the cache line.
     84 	 * "end" points to the last byte of the line before the last cache line.
     85 	 * Because size is always a multiple of 4, this is safe to set
     86 	 * "end" to the last byte.
     87 	 */
     88 	{
     89 		int lineSize;
     90 		asm("rdhwr %0, $1" : "=r" (lineSize));
     91 		start = start & (-lineSize);
     92 		end = (end & (-lineSize)) - 1;
     93 	}
     94 #endif
     95 	__builtin___clear_cache((char *)start, (char *)end);
     96 #else
     97 	_flush_cache((char *)start, end-start, BCACHE);
     98 #endif
     99 	return 0;
    100 }
    101