From e2827fe5c1566f66a922dd7493cbe4522c50580a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 8 Jan 2017 17:31:47 -0600 Subject: [PATCH] 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: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/cache.h | 24 ++-- arch/powerpc/include/asm/page_64.h | 4 +- arch/powerpc/kernel/align.c | 2 +- arch/powerpc/kernel/asm-offsets.c | 12 +- arch/powerpc/kernel/setup_64.c | 181 ++++++++++++++--------------- arch/powerpc/kernel/vdso.c | 16 +-- 6 files changed, 118 insertions(+), 121 deletions(-) diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h index 1fa364340146..823750fa6e66 100644 --- a/arch/powerpc/include/asm/cache.h +++ b/arch/powerpc/include/asm/cache.h @@ -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; diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h index c50a666308dd..3e83d2a20b6f 100644 --- a/arch/powerpc/include/asm/page_64.h +++ b/arch/powerpc/include/asm/page_64.h @@ -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; diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 30ff6590a2dd..cbc7c42cdb74 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -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 diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 125442107b40..b4324db94741 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -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)); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 75c9a8641ba1..b87dcb2968d9 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -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; + /* + * 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"); - 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; - } + 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"); } diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 9c0a85776c6c..22b01a3962f0 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -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