Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f4441ef authored by Jeremy Kerr's avatar Jeremy Kerr Committed by Benjamin Herrenschmidt
Browse files

powerpc: Dynamically allocate slb_shadow from memblock



Currently, the slb_shadow buffer is our largest symbol:

  [jk@pablo linux]$ nm --size-sort -r -S obj/vmlinux | head -1
  c000000000da0000 0000000000040000 d slb_shadow

- we allocate 128 bytes per cpu; so 256k with NR_CPUS=2048. As we have
constant initialisers, it's allocated in .text, causing a larger vmlinux
image. We may also allocate unecessary slb_shadow buffers (> no. pacas),
since we use the build-time NR_CPUS rather than the run-time nr_cpu_ids.

We could move this to the bss, but then we still have the NR_CPUS vs
nr_cpu_ids potential for overallocation.

This change dynamically allocates the slb_shadow array, during
initialise_pacas(). At a cost of 104 bytes of text, we save 256k of
data:

  [jk@pablo linux]$ size obj/vmlinux{.orig,}
     text     data      bss       dec     hex	filename
  9202795  5244676  1169576  15617047  ee4c17	obj/vmlinux.orig
  9202899  4982532  1169576  15355007  ea4c7f	obj/vmlinux

Tested on pseries.

Signed-off-by: default avatarJeremy Kerr <jk@ozlabs.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 1a8f6f97
Loading
Loading
Loading
Loading
+25 −7
Original line number Diff line number Diff line
@@ -99,12 +99,28 @@ static inline void free_lppacas(void) { }
 * 3 persistent SLBs are registered here.  The buffer will be zero
 * initially, hence will all be invaild until we actually write them.
 */
static struct slb_shadow slb_shadow[] __cacheline_aligned = {
	[0 ... (NR_CPUS-1)] = {
		.persistent = cpu_to_be32(SLB_NUM_BOLTED),
		.buffer_length = cpu_to_be32(sizeof(struct slb_shadow)),
	},
};
static struct slb_shadow *slb_shadow;

static void __init allocate_slb_shadows(int nr_cpus, int limit)
{
	int size = PAGE_ALIGN(sizeof(struct slb_shadow) * nr_cpus);
	slb_shadow = __va(memblock_alloc_base(size, PAGE_SIZE, limit));
	memset(slb_shadow, 0, size);
}

static struct slb_shadow * __init init_slb_shadow(int cpu)
{
	struct slb_shadow *s = &slb_shadow[cpu];

	s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
	s->buffer_length = cpu_to_be32(sizeof(*s));

	return s;
}

#else /* CONFIG_PPC_STD_MMU_64 */

static void __init allocate_slb_shadows(int nr_cpus, int limit) { }

#endif /* CONFIG_PPC_STD_MMU_64 */

@@ -142,7 +158,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
	new_paca->__current = &init_task;
	new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
#ifdef CONFIG_PPC_STD_MMU_64
	new_paca->slb_shadow_ptr = &slb_shadow[cpu];
	new_paca->slb_shadow_ptr = init_slb_shadow(cpu);
#endif /* CONFIG_PPC_STD_MMU_64 */
}

@@ -190,6 +206,8 @@ void __init allocate_pacas(void)

	allocate_lppacas(nr_cpu_ids, limit);

	allocate_slb_shadows(nr_cpu_ids, limit);

	/* Can't use for_each_*_cpu, as they aren't functional yet */
	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
		initialise_paca(&paca[cpu], cpu);