Skip to content

Commit

Permalink
arch/tile: Split the icache flush code off to a generic <arch> header.
Browse files Browse the repository at this point in the history
This code is used in other places in our system than in Linux, so
to share it we now implement it as an inline function in our low-level
<arch> headers, and instantiate it in one file in Linux's arch/tile/lib.
The file is now cacheflush.c and is C code rather than the strangely-named
and assembler-implemented __invalidate_icache.S.

Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
  • Loading branch information
Chris Metcalf committed Jul 6, 2010
1 parent 2db0982 commit c78095b
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 114 deletions.
94 changes: 94 additions & 0 deletions arch/tile/include/arch/icache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2010 Tilera Corporation. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for
* more details.
*
*/

/**
* @file
*
* Support for invalidating bytes in the instruction
*/

#ifndef __ARCH_ICACHE_H__
#define __ARCH_ICACHE_H__

#include <arch/chip.h>


/**
* Invalidate the instruction cache for the given range of memory.
*
* @param addr The start of memory to be invalidated.
* @param size The number of bytes to be invalidated.
* @param page_size The system's page size, typically the PAGE_SIZE constant
* in sys/page.h. This value must be a power of two no larger
* than the page containing the code to be invalidated. If the value
* is smaller than the actual page size, this function will still
* work, but may run slower than necessary.
*/
static __inline void
invalidate_icache(const void* addr, unsigned long size,
unsigned long page_size)
{
const unsigned long cache_way_size =
CHIP_L1I_CACHE_SIZE() / CHIP_L1I_ASSOC();
unsigned long max_useful_size;
const char* start, *end;
long num_passes;

if (__builtin_expect(size == 0, 0))
return;

#ifdef __tilegx__
/* Limit the number of bytes visited to avoid redundant iterations. */
max_useful_size = (page_size < cache_way_size) ? page_size : cache_way_size;

/* No PA aliasing is possible, so one pass always suffices. */
num_passes = 1;
#else
/* Limit the number of bytes visited to avoid redundant iterations. */
max_useful_size = cache_way_size;

/*
* Compute how many passes we need (we'll treat 0 as if it were 1).
* This works because we know the page size is a power of two.
*/
num_passes = cache_way_size >> __builtin_ctzl(page_size);
#endif

if (__builtin_expect(size > max_useful_size, 0))
size = max_useful_size;

/* Locate the first and last bytes to be invalidated. */
start = (const char *)((unsigned long)addr & -CHIP_L1I_LINE_SIZE());
end = (const char*)addr + size - 1;

__insn_mf();

do
{
const char* p;

for (p = start; p <= end; p += CHIP_L1I_LINE_SIZE())
__insn_icoh(p);

start += page_size;
end += page_size;
}
while (--num_passes > 0);

__insn_drain();
}


#endif /* __ARCH_ICACHE_H__ */
9 changes: 2 additions & 7 deletions arch/tile/include/asm/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/mm.h>
#include <linux/cache.h>
#include <asm/system.h>
#include <arch/icache.h>

/* Caches are physically-indexed and so don't need special treatment */
#define flush_cache_all() do { } while (0)
Expand All @@ -37,14 +38,8 @@
#define flush_icache_page(vma, pg) do { } while (0)
#define flush_icache_user_range(vma, pg, adr, len) do { } while (0)

/* See "arch/tile/lib/__invalidate_icache.S". */
extern void __invalidate_icache(unsigned long start, unsigned long size);

/* Flush the icache just on this cpu */
static inline void __flush_icache_range(unsigned long start, unsigned long end)
{
__invalidate_icache(start, end - start);
}
extern void __flush_icache_range(unsigned long start, unsigned long end);

/* Flush the entire icache on this cpu. */
#define __flush_icache() __flush_icache_range(0, CHIP_L1I_CACHE_SIZE())
Expand Down
2 changes: 1 addition & 1 deletion arch/tile/lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Makefile for TILE-specific library files..
#

lib-y = checksum.o cpumask.o delay.o __invalidate_icache.o \
lib-y = cacheflush.o checksum.o cpumask.o delay.o \
mb_incoherent.o uaccess.o \
memcpy_$(BITS).o memchr_$(BITS).o memmove_$(BITS).o memset_$(BITS).o \
strchr_$(BITS).o strlen_$(BITS).o
Expand Down
106 changes: 0 additions & 106 deletions arch/tile/lib/__invalidate_icache.S

This file was deleted.

23 changes: 23 additions & 0 deletions arch/tile/lib/cacheflush.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2010 Tilera Corporation. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for
* more details.
*/

#include <asm/page.h>
#include <asm/cacheflush.h>
#include <arch/icache.h>


void __flush_icache_range(unsigned long start, unsigned long end)
{
invalidate_icache((const void *)start, end - start, PAGE_SIZE);
}

0 comments on commit c78095b

Please sign in to comment.