162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * c 2001 PPC 64 Team, IBM Corp
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/smp.h>
762306a36Sopenharmony_ci#include <linux/export.h>
862306a36Sopenharmony_ci#include <linux/memblock.h>
962306a36Sopenharmony_ci#include <linux/sched/task.h>
1062306a36Sopenharmony_ci#include <linux/numa.h>
1162306a36Sopenharmony_ci#include <linux/pgtable.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <asm/lppaca.h>
1462306a36Sopenharmony_ci#include <asm/paca.h>
1562306a36Sopenharmony_ci#include <asm/sections.h>
1662306a36Sopenharmony_ci#include <asm/kexec.h>
1762306a36Sopenharmony_ci#include <asm/svm.h>
1862306a36Sopenharmony_ci#include <asm/ultravisor.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include "setup.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#ifndef CONFIG_SMP
2362306a36Sopenharmony_ci#define boot_cpuid 0
2462306a36Sopenharmony_ci#endif
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic void *__init alloc_paca_data(unsigned long size, unsigned long align,
2762306a36Sopenharmony_ci				unsigned long limit, int cpu)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	void *ptr;
3062306a36Sopenharmony_ci	int nid;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	/*
3362306a36Sopenharmony_ci	 * boot_cpuid paca is allocated very early before cpu_to_node is up.
3462306a36Sopenharmony_ci	 * Set bottom-up mode, because the boot CPU should be on node-0,
3562306a36Sopenharmony_ci	 * which will put its paca in the right place.
3662306a36Sopenharmony_ci	 */
3762306a36Sopenharmony_ci	if (cpu == boot_cpuid) {
3862306a36Sopenharmony_ci		nid = NUMA_NO_NODE;
3962306a36Sopenharmony_ci		memblock_set_bottom_up(true);
4062306a36Sopenharmony_ci	} else {
4162306a36Sopenharmony_ci		nid = early_cpu_to_node(cpu);
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	ptr = memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,
4562306a36Sopenharmony_ci				     limit, nid);
4662306a36Sopenharmony_ci	if (!ptr)
4762306a36Sopenharmony_ci		panic("cannot allocate paca data");
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	if (cpu == boot_cpuid)
5062306a36Sopenharmony_ci		memblock_set_bottom_up(false);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	return ptr;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#ifdef CONFIG_PPC_PSERIES
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define LPPACA_SIZE 0x400
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic void *__init alloc_shared_lppaca(unsigned long size, unsigned long limit,
6062306a36Sopenharmony_ci					int cpu)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	size_t shared_lppaca_total_size = PAGE_ALIGN(nr_cpu_ids * LPPACA_SIZE);
6362306a36Sopenharmony_ci	static unsigned long shared_lppaca_size;
6462306a36Sopenharmony_ci	static void *shared_lppaca;
6562306a36Sopenharmony_ci	void *ptr;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	if (!shared_lppaca) {
6862306a36Sopenharmony_ci		memblock_set_bottom_up(true);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci		/*
7162306a36Sopenharmony_ci		 * See Documentation/powerpc/ultravisor.rst for more details.
7262306a36Sopenharmony_ci		 *
7362306a36Sopenharmony_ci		 * UV/HV data sharing is in PAGE_SIZE granularity. In order to
7462306a36Sopenharmony_ci		 * minimize the number of pages shared, align the allocation to
7562306a36Sopenharmony_ci		 * PAGE_SIZE.
7662306a36Sopenharmony_ci		 */
7762306a36Sopenharmony_ci		shared_lppaca =
7862306a36Sopenharmony_ci			memblock_alloc_try_nid(shared_lppaca_total_size,
7962306a36Sopenharmony_ci					       PAGE_SIZE, MEMBLOCK_LOW_LIMIT,
8062306a36Sopenharmony_ci					       limit, NUMA_NO_NODE);
8162306a36Sopenharmony_ci		if (!shared_lppaca)
8262306a36Sopenharmony_ci			panic("cannot allocate shared data");
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci		memblock_set_bottom_up(false);
8562306a36Sopenharmony_ci		uv_share_page(PHYS_PFN(__pa(shared_lppaca)),
8662306a36Sopenharmony_ci			      shared_lppaca_total_size >> PAGE_SHIFT);
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	ptr = shared_lppaca + shared_lppaca_size;
9062306a36Sopenharmony_ci	shared_lppaca_size += size;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	/*
9362306a36Sopenharmony_ci	 * This is very early in boot, so no harm done if the kernel crashes at
9462306a36Sopenharmony_ci	 * this point.
9562306a36Sopenharmony_ci	 */
9662306a36Sopenharmony_ci	BUG_ON(shared_lppaca_size > shared_lppaca_total_size);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	return ptr;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/*
10262306a36Sopenharmony_ci * See asm/lppaca.h for more detail.
10362306a36Sopenharmony_ci *
10462306a36Sopenharmony_ci * lppaca structures must must be 1kB in size, L1 cache line aligned,
10562306a36Sopenharmony_ci * and not cross 4kB boundary. A 1kB size and 1kB alignment will satisfy
10662306a36Sopenharmony_ci * these requirements.
10762306a36Sopenharmony_ci */
10862306a36Sopenharmony_cistatic inline void init_lppaca(struct lppaca *lppaca)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct lppaca) != 640);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	*lppaca = (struct lppaca) {
11362306a36Sopenharmony_ci		.desc = cpu_to_be32(0xd397d781),	/* "LpPa" */
11462306a36Sopenharmony_ci		.size = cpu_to_be16(LPPACA_SIZE),
11562306a36Sopenharmony_ci		.fpregs_in_use = 1,
11662306a36Sopenharmony_ci		.slb_count = cpu_to_be16(64),
11762306a36Sopenharmony_ci		.vmxregs_in_use = 0,
11862306a36Sopenharmony_ci		.page_ins = 0, };
11962306a36Sopenharmony_ci};
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic struct lppaca * __init new_lppaca(int cpu, unsigned long limit)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	struct lppaca *lp;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct lppaca) > LPPACA_SIZE);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (early_cpu_has_feature(CPU_FTR_HVMODE))
12862306a36Sopenharmony_ci		return NULL;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	if (is_secure_guest())
13162306a36Sopenharmony_ci		lp = alloc_shared_lppaca(LPPACA_SIZE, limit, cpu);
13262306a36Sopenharmony_ci	else
13362306a36Sopenharmony_ci		lp = alloc_paca_data(LPPACA_SIZE, 0x400, limit, cpu);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	init_lppaca(lp);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	return lp;
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci#endif /* CONFIG_PPC_PSERIES */
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci#ifdef CONFIG_PPC_64S_HASH_MMU
14262306a36Sopenharmony_ci/*
14362306a36Sopenharmony_ci * 3 persistent SLBs are allocated here.  The buffer will be zero
14462306a36Sopenharmony_ci * initially, hence will all be invaild until we actually write them.
14562306a36Sopenharmony_ci *
14662306a36Sopenharmony_ci * If you make the number of persistent SLB entries dynamic, please also
14762306a36Sopenharmony_ci * update PR KVM to flush and restore them accordingly.
14862306a36Sopenharmony_ci */
14962306a36Sopenharmony_cistatic struct slb_shadow * __init new_slb_shadow(int cpu, unsigned long limit)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	struct slb_shadow *s;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (cpu != boot_cpuid) {
15462306a36Sopenharmony_ci		/*
15562306a36Sopenharmony_ci		 * Boot CPU comes here before early_radix_enabled
15662306a36Sopenharmony_ci		 * is parsed (e.g., for disable_radix). So allocate
15762306a36Sopenharmony_ci		 * always and this will be fixed up in free_unused_pacas.
15862306a36Sopenharmony_ci		 */
15962306a36Sopenharmony_ci		if (early_radix_enabled())
16062306a36Sopenharmony_ci			return NULL;
16162306a36Sopenharmony_ci	}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	s = alloc_paca_data(sizeof(*s), L1_CACHE_BYTES, limit, cpu);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
16662306a36Sopenharmony_ci	s->buffer_length = cpu_to_be32(sizeof(*s));
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	return s;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci#endif /* CONFIG_PPC_64S_HASH_MMU */
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci/* The Paca is an array with one entry per processor.  Each contains an
17362306a36Sopenharmony_ci * lppaca, which contains the information shared between the
17462306a36Sopenharmony_ci * hypervisor and Linux.
17562306a36Sopenharmony_ci * On systems with hardware multi-threading, there are two threads
17662306a36Sopenharmony_ci * per processor.  The Paca array must contain an entry for each thread.
17762306a36Sopenharmony_ci * The VPD Areas will give a max logical processors = 2 * max physical
17862306a36Sopenharmony_ci * processors.  The processor VPD array needs one entry per physical
17962306a36Sopenharmony_ci * processor (not thread).
18062306a36Sopenharmony_ci */
18162306a36Sopenharmony_cistruct paca_struct **paca_ptrs __read_mostly;
18262306a36Sopenharmony_ciEXPORT_SYMBOL(paca_ptrs);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_civoid __init initialise_paca(struct paca_struct *new_paca, int cpu)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci#ifdef CONFIG_PPC_PSERIES
18762306a36Sopenharmony_ci	new_paca->lppaca_ptr = NULL;
18862306a36Sopenharmony_ci#endif
18962306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3E_64
19062306a36Sopenharmony_ci	new_paca->kernel_pgd = swapper_pg_dir;
19162306a36Sopenharmony_ci#endif
19262306a36Sopenharmony_ci	new_paca->lock_token = 0x8000;
19362306a36Sopenharmony_ci	new_paca->paca_index = cpu;
19462306a36Sopenharmony_ci#ifndef CONFIG_PPC_KERNEL_PCREL
19562306a36Sopenharmony_ci	new_paca->kernel_toc = kernel_toc_addr();
19662306a36Sopenharmony_ci#endif
19762306a36Sopenharmony_ci	new_paca->kernelbase = (unsigned long) _stext;
19862306a36Sopenharmony_ci	/* Only set MSR:IR/DR when MMU is initialized */
19962306a36Sopenharmony_ci	new_paca->kernel_msr = MSR_KERNEL & ~(MSR_IR | MSR_DR);
20062306a36Sopenharmony_ci	new_paca->hw_cpu_id = 0xffff;
20162306a36Sopenharmony_ci	new_paca->kexec_state = KEXEC_STATE_NONE;
20262306a36Sopenharmony_ci	new_paca->__current = &init_task;
20362306a36Sopenharmony_ci	new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
20462306a36Sopenharmony_ci#ifdef CONFIG_PPC_64S_HASH_MMU
20562306a36Sopenharmony_ci	new_paca->slb_shadow_ptr = NULL;
20662306a36Sopenharmony_ci#endif
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3E_64
20962306a36Sopenharmony_ci	/* For now -- if we have threads this will be adjusted later */
21062306a36Sopenharmony_ci	new_paca->tcd_ptr = &new_paca->tcd;
21162306a36Sopenharmony_ci#endif
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci/* Put the paca pointer into r13 and SPRG_PACA */
21562306a36Sopenharmony_civoid setup_paca(struct paca_struct *new_paca)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	/* Setup r13 */
21862306a36Sopenharmony_ci	local_paca = new_paca;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3E_64
22162306a36Sopenharmony_ci	/* On Book3E, initialize the TLB miss exception frames */
22262306a36Sopenharmony_ci	mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
22362306a36Sopenharmony_ci#else
22462306a36Sopenharmony_ci	/*
22562306a36Sopenharmony_ci	 * In HV mode, we setup both HPACA and PACA to avoid problems
22662306a36Sopenharmony_ci	 * if we do a GET_PACA() before the feature fixups have been
22762306a36Sopenharmony_ci	 * applied.
22862306a36Sopenharmony_ci	 *
22962306a36Sopenharmony_ci	 * Normally you should test against CPU_FTR_HVMODE, but CPU features
23062306a36Sopenharmony_ci	 * are not yet set up when we first reach here.
23162306a36Sopenharmony_ci	 */
23262306a36Sopenharmony_ci	if (mfmsr() & MSR_HV)
23362306a36Sopenharmony_ci		mtspr(SPRN_SPRG_HPACA, local_paca);
23462306a36Sopenharmony_ci#endif
23562306a36Sopenharmony_ci	mtspr(SPRN_SPRG_PACA, local_paca);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic int __initdata paca_nr_cpu_ids;
24062306a36Sopenharmony_cistatic int __initdata paca_ptrs_size;
24162306a36Sopenharmony_cistatic int __initdata paca_struct_size;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_civoid __init allocate_paca_ptrs(void)
24462306a36Sopenharmony_ci{
24562306a36Sopenharmony_ci	paca_nr_cpu_ids = nr_cpu_ids;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	paca_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
24862306a36Sopenharmony_ci	paca_ptrs = memblock_alloc_raw(paca_ptrs_size, SMP_CACHE_BYTES);
24962306a36Sopenharmony_ci	if (!paca_ptrs)
25062306a36Sopenharmony_ci		panic("Failed to allocate %d bytes for paca pointers\n",
25162306a36Sopenharmony_ci		      paca_ptrs_size);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	memset(paca_ptrs, 0x88, paca_ptrs_size);
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_civoid __init allocate_paca(int cpu)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	u64 limit;
25962306a36Sopenharmony_ci	struct paca_struct *paca;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	BUG_ON(cpu >= paca_nr_cpu_ids);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64
26462306a36Sopenharmony_ci	/*
26562306a36Sopenharmony_ci	 * We access pacas in real mode, and cannot take SLB faults
26662306a36Sopenharmony_ci	 * on them when in virtual mode, so allocate them accordingly.
26762306a36Sopenharmony_ci	 */
26862306a36Sopenharmony_ci	limit = min(ppc64_bolted_size(), ppc64_rma_size);
26962306a36Sopenharmony_ci#else
27062306a36Sopenharmony_ci	limit = ppc64_rma_size;
27162306a36Sopenharmony_ci#endif
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	paca = alloc_paca_data(sizeof(struct paca_struct), L1_CACHE_BYTES,
27462306a36Sopenharmony_ci				limit, cpu);
27562306a36Sopenharmony_ci	paca_ptrs[cpu] = paca;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	initialise_paca(paca, cpu);
27862306a36Sopenharmony_ci#ifdef CONFIG_PPC_PSERIES
27962306a36Sopenharmony_ci	paca->lppaca_ptr = new_lppaca(cpu, limit);
28062306a36Sopenharmony_ci#endif
28162306a36Sopenharmony_ci#ifdef CONFIG_PPC_64S_HASH_MMU
28262306a36Sopenharmony_ci	paca->slb_shadow_ptr = new_slb_shadow(cpu, limit);
28362306a36Sopenharmony_ci#endif
28462306a36Sopenharmony_ci	paca_struct_size += sizeof(struct paca_struct);
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_civoid __init free_unused_pacas(void)
28862306a36Sopenharmony_ci{
28962306a36Sopenharmony_ci	int new_ptrs_size;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	new_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
29262306a36Sopenharmony_ci	if (new_ptrs_size < paca_ptrs_size)
29362306a36Sopenharmony_ci		memblock_phys_free(__pa(paca_ptrs) + new_ptrs_size,
29462306a36Sopenharmony_ci				   paca_ptrs_size - new_ptrs_size);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	paca_nr_cpu_ids = nr_cpu_ids;
29762306a36Sopenharmony_ci	paca_ptrs_size = new_ptrs_size;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci#ifdef CONFIG_PPC_64S_HASH_MMU
30062306a36Sopenharmony_ci	if (early_radix_enabled()) {
30162306a36Sopenharmony_ci		/* Ugly fixup, see new_slb_shadow() */
30262306a36Sopenharmony_ci		memblock_phys_free(__pa(paca_ptrs[boot_cpuid]->slb_shadow_ptr),
30362306a36Sopenharmony_ci				   sizeof(struct slb_shadow));
30462306a36Sopenharmony_ci		paca_ptrs[boot_cpuid]->slb_shadow_ptr = NULL;
30562306a36Sopenharmony_ci	}
30662306a36Sopenharmony_ci#endif
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	printk(KERN_DEBUG "Allocated %u bytes for %u pacas\n",
30962306a36Sopenharmony_ci			paca_ptrs_size + paca_struct_size, nr_cpu_ids);
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci#ifdef CONFIG_PPC_64S_HASH_MMU
31362306a36Sopenharmony_civoid copy_mm_to_paca(struct mm_struct *mm)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	mm_context_t *context = &mm->context;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	VM_BUG_ON(!mm_ctx_slb_addr_limit(context));
31862306a36Sopenharmony_ci	memcpy(&get_paca()->mm_ctx_low_slices_psize, mm_ctx_low_slices(context),
31962306a36Sopenharmony_ci	       LOW_SLICE_ARRAY_SZ);
32062306a36Sopenharmony_ci	memcpy(&get_paca()->mm_ctx_high_slices_psize, mm_ctx_high_slices(context),
32162306a36Sopenharmony_ci	       TASK_SLICE_ARRAY_SZ(context));
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci#endif /* CONFIG_PPC_64S_HASH_MMU */
324