powerpc/64: Clean up ppc64_caches using a struct per cache
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Sun, 8 Jan 2017 23:31:47 +0000 (17:31 -0600)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 6 Feb 2017 08:46:04 +0000 (19:46 +1100)
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 <benh@kernel.crashing.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/page_64.h
arch/powerpc/kernel/align.c
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/vdso.c

index 1fa3643..823750f 100644 (file)
 #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;
index c50a666..3e83d2a 100644 (file)
@@ -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;
index 30ff659..cbc7c42 100644 (file)
@@ -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
index 1254421..b4324db 100644 (file)
@@ -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));
index 75c9a86..b87dcb2 100644 (file)
@@ -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");
 }
index 9c0a857..22b01a3 100644 (file)
@@ -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