Commit e2827fe5 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Michael Ellerman

powerpc/64: Clean up ppc64_caches using a struct per cache

We have two set of identical struct members for the I and D sides
and mostly identical bunches of code to parse the device-tree to
populate them. Instead make a ppc_cache_info structure with one
copy for I and one for D
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 5d451a87
......@@ -30,19 +30,19 @@
#define IFETCH_ALIGN_BYTES (1 << IFETCH_ALIGN_SHIFT)
#if defined(__powerpc64__) && !defined(__ASSEMBLY__)
struct ppc_cache_info {
u32 size;
u32 line_size;
u32 block_size; /* L1 only */
u32 log_block_size;
u32 blocks_per_page;
u32 sets;
};
struct ppc64_caches {
u32 dsize; /* L1 d-cache size */
u32 dline_size; /* L1 d-cache line size */
u32 dblock_size; /* L1 d-cache block size */
u32 log_dblock_size;
u32 dblocks_per_page;
u32 dsets;
u32 isize; /* L1 i-cache size */
u32 iline_size; /* L1 d-cache line size */
u32 iblock_size; /* L1 i-cache block size */
u32 log_iblock_size;
u32 iblocks_per_page;
u32 isets;
struct ppc_cache_info l1d;
struct ppc_cache_info l1i;
};
extern struct ppc64_caches ppc64_caches;
......
......@@ -47,14 +47,14 @@ static inline void clear_page(void *addr)
unsigned long iterations;
unsigned long onex, twox, fourx, eightx;
iterations = ppc64_caches.dblocks_per_page / 8;
iterations = ppc64_caches.l1d.blocks_per_page / 8;
/*
* Some verisions of gcc use multiply instructions to
* calculate the offsets so lets give it a hand to
* do better.
*/
onex = ppc64_caches.dblock_size;
onex = ppc64_caches.l1d.block_size;
twox = onex << 1;
fourx = onex << 2;
eightx = onex << 3;
......
......@@ -204,7 +204,7 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
int i, size;
#ifdef __powerpc64__
size = ppc64_caches.dblock_size;
size = ppc64_caches.l1d.block_size;
#else
size = L1_CACHE_BYTES;
#endif
......
......@@ -163,12 +163,12 @@ int main(void)
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
#ifdef CONFIG_PPC64
DEFINE(DCACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, dblock_size));
DEFINE(DCACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, log_dblock_size));
DEFINE(DCACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, dblocks_per_page));
DEFINE(ICACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, iblock_size));
DEFINE(ICACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, log_iblock_size));
DEFINE(ICACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, iblocks_per_page));
DEFINE(DCACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, l1d.block_size));
DEFINE(DCACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, l1d.log_block_size));
DEFINE(DCACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, l1d.blocks_per_page));
DEFINE(ICACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, l1i.block_size));
DEFINE(ICACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, l1i.log_block_size));
DEFINE(ICACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, l1i.blocks_per_page));
/* paca */
DEFINE(PACA_SIZE, sizeof(struct paca_struct));
DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
......
......@@ -78,10 +78,14 @@ int spinning_secondaries;
u64 ppc64_pft_size;
struct ppc64_caches ppc64_caches = {
.dblock_size = 0x40,
.log_dblock_size = 6,
.iblock_size = 0x40,
.log_iblock_size = 6
.l1d = {
.block_size = 0x40,
.log_block_size = 6,
},
.l1i = {
.block_size = 0x40,
.log_block_size = 6
},
};
EXPORT_SYMBOL_GPL(ppc64_caches);
......@@ -397,105 +401,98 @@ void smp_release_cpus(void)
* cache informations about the CPU that will be used by cache flush
* routines and/or provided to userland
*/
static void init_cache_info(struct ppc_cache_info *info, u32 size, u32 lsize,
u32 bsize, u32 sets)
{
info->size = size;
info->sets = sets;
info->line_size = lsize;
info->block_size = bsize;
info->log_block_size = __ilog2(bsize);
info->blocks_per_page = PAGE_SIZE / bsize;
}
static bool __init parse_cache_info(struct device_node *np,
bool icache,
struct ppc_cache_info *info)
{
static const char *ipropnames[] __initdata = {
"i-cache-size",
"i-cache-sets",
"i-cache-block-size",
"i-cache-line-size",
};
static const char *dpropnames[] __initdata = {
"d-cache-size",
"d-cache-sets",
"d-cache-block-size",
"d-cache-line-size",
};
const char **propnames = icache ? ipropnames : dpropnames;
const __be32 *sizep, *lsizep, *bsizep, *setsp;
u32 size, lsize, bsize, sets;
bool success = true;
size = 0;
sets = -1u;
lsize = bsize = cur_cpu_spec->dcache_bsize;
sizep = of_get_property(np, propnames[0], NULL);
if (sizep != NULL)
size = be32_to_cpu(*sizep);
setsp = of_get_property(np, propnames[1], NULL);
if (setsp != NULL)
sets = be32_to_cpu(*setsp);
bsizep = of_get_property(np, propnames[2], NULL);
lsizep = of_get_property(np, propnames[3], NULL);
if (bsizep == NULL)
bsizep = lsizep;
if (lsizep != NULL)
lsize = be32_to_cpu(*lsizep);
if (bsizep != NULL)
bsize = be32_to_cpu(*bsizep);
if (sizep == NULL || bsizep == NULL || lsizep == NULL)
success = false;
/*
* OF is weird .. it represents fully associative caches
* as "1 way" which doesn't make much sense and doesn't
* leave room for direct mapped. We'll assume that 0
* in OF means direct mapped for that reason.
*/
if (sets == 1)
sets = 0;
else if (sets == 0)
sets = 1;
init_cache_info(info, size, lsize, bsize, sets);
return success;
}
void __init initialize_cache_info(void)
{
struct device_node *np;
unsigned long num_cpus = 0;
DBG(" -> initialize_cache_info()\n");
for_each_node_by_type(np, "cpu") {
num_cpus += 1;
np = of_find_node_by_type(NULL, "cpu");
/*
* We're assuming *all* of the CPUs have the same
* d-cache and i-cache sizes... -Peter
*/
if (num_cpus == 1) {
const __be32 *sizep, *lsizep, *bsizep, *setsp;
u32 size, lsize, bsize, sets;
size = 0;
sets = -1u;
lsize = bsize = cur_cpu_spec->dcache_bsize;
sizep = of_get_property(np, "d-cache-size", NULL);
if (sizep != NULL)
size = be32_to_cpu(*sizep);
setsp = of_get_property(np, "d-cache-sets", NULL);
if (setsp != NULL)
sets = be32_to_cpu(*setsp);
bsizep = of_get_property(np, "d-cache-block-size",
NULL);
lsizep = of_get_property(np, "d-cache-line-size",
NULL);
if (bsizep == NULL)
bsizep = lsizep;
if (lsizep != NULL)
lsize = be32_to_cpu(*lsizep);
if (bsizep != NULL)
bsize = be32_to_cpu(*bsizep);
if (sizep == NULL || bsizep == NULL || lsizep == NULL)
DBG("Argh, can't find dcache properties ! "
"sizep: %p, bsizep: %p, lsizep: %p\n",
sizep, bsizep, lsizep);
/*
* OF is weird .. it represents fully associative caches
* as "1 way" which doesn't make much sense and doesn't
* leave room for direct mapped. We'll assume that 0
* in OF means direct mapped for that reason.
*/
if (sets == 1)
sets = 0;
else if (sets == 0)
sets = 1;
ppc64_caches.dsize = size;
ppc64_caches.dsets = sets;
ppc64_caches.dline_size = lsize;
ppc64_caches.dblock_size = bsize;
ppc64_caches.log_dblock_size = __ilog2(bsize);
ppc64_caches.dblocks_per_page = PAGE_SIZE / bsize;
size = 0;
sets = -1u;
lsize = bsize = cur_cpu_spec->icache_bsize;
sizep = of_get_property(np, "i-cache-size", NULL);
if (sizep != NULL)
size = be32_to_cpu(*sizep);
setsp = of_get_property(np, "i-cache-sets", NULL);
if (setsp != NULL)
sets = be32_to_cpu(*setsp);
bsizep = of_get_property(np, "i-cache-block-size",
NULL);
lsizep = of_get_property(np, "i-cache-line-size",
NULL);
if (bsizep == NULL)
bsizep = lsizep;
if (lsizep != NULL)
lsize = be32_to_cpu(*lsizep);
if (bsizep != NULL)
bsize = be32_to_cpu(*bsizep);
if (sizep == NULL || bsizep == NULL || lsizep == NULL)
DBG("Argh, can't find icache properties ! "
"sizep: %p, bsizep: %p, lsizep: %p\n",
sizep, bsizep, lsizep);
if (sets == 1)
sets = 0;
else if (sets == 0)
sets = 1;
ppc64_caches.isize = size;
ppc64_caches.isets = sets;
ppc64_caches.iline_size = lsize;
ppc64_caches.iblock_size = bsize;
ppc64_caches.log_iblock_size = __ilog2(bsize);
ppc64_caches.iblocks_per_page = PAGE_SIZE / bsize;
}
/*
* We're assuming *all* of the CPUs have the same
* d-cache and i-cache sizes... -Peter
*/
if (np) {
if (!parse_cache_info(np, false, &ppc64_caches.l1d))
DBG("Argh, can't find dcache properties !\n");
if (!parse_cache_info(np, true, &ppc64_caches.l1i))
DBG("Argh, can't find icache properties !\n");
}
/* For use by binfmt_elf */
dcache_bsize = ppc64_caches.dblock_size;
icache_bsize = ppc64_caches.iblock_size;
dcache_bsize = ppc64_caches.l1d.block_size;
icache_bsize = ppc64_caches.l1i.block_size;
DBG(" <- initialize_cache_info()\n");
}
......
......@@ -736,14 +736,14 @@ static int __init vdso_init(void)
if (firmware_has_feature(FW_FEATURE_LPAR))
vdso_data->platform |= 1;
vdso_data->physicalMemorySize = memblock_phys_mem_size();
vdso_data->dcache_size = ppc64_caches.dsize;
vdso_data->dcache_line_size = ppc64_caches.dline_size;
vdso_data->icache_size = ppc64_caches.isize;
vdso_data->icache_line_size = ppc64_caches.iline_size;
vdso_data->dcache_block_size = ppc64_caches.dblock_size;
vdso_data->icache_block_size = ppc64_caches.iblock_size;
vdso_data->dcache_log_block_size = ppc64_caches.log_dblock_size;
vdso_data->icache_log_block_size = ppc64_caches.log_iblock_size;
vdso_data->dcache_size = ppc64_caches.l1d.size;
vdso_data->dcache_line_size = ppc64_caches.l1d.line_size;
vdso_data->icache_size = ppc64_caches.l1i.size;
vdso_data->icache_line_size = ppc64_caches.l1i.line_size;
vdso_data->dcache_block_size = ppc64_caches.l1d.block_size;
vdso_data->icache_block_size = ppc64_caches.l1i.block_size;
vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size;
vdso_data->icache_log_block_size = ppc64_caches.l1i.log_block_size;
/*
* Calculate the size of the 64 bits vDSO
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment