arch/powerpc/kernel/paca.c

Source file repositories/reference/linux-study-clean/arch/powerpc/kernel/paca.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/kernel/paca.c
Extension
.c
Size
8485 bytes
Lines
324
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * c 2001 PPC 64 Team, IBM Corp
 */

#include <linux/smp.h>
#include <linux/export.h>
#include <linux/memblock.h>
#include <linux/sched/task.h>
#include <linux/numa.h>
#include <linux/pgtable.h>

#include <asm/lppaca.h>
#include <asm/paca.h>
#include <asm/sections.h>
#include <asm/kexec.h>
#include <asm/svm.h>
#include <asm/ultravisor.h>

#include "setup.h"

#ifndef CONFIG_SMP
#define boot_cpuid 0
#endif

static void *__init alloc_paca_data(unsigned long size, unsigned long align,
				unsigned long limit, int cpu)
{
	void *ptr;
	int nid;

	/*
	 * boot_cpuid paca is allocated very early before cpu_to_node is up.
	 * Set bottom-up mode, because the boot CPU should be on node-0,
	 * which will put its paca in the right place.
	 */
	if (cpu == boot_cpuid) {
		nid = NUMA_NO_NODE;
		memblock_set_bottom_up(true);
	} else {
		nid = early_cpu_to_node(cpu);
	}

	ptr = memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,
				     limit, nid);
	if (!ptr)
		panic("cannot allocate paca data");

	if (cpu == boot_cpuid)
		memblock_set_bottom_up(false);

	return ptr;
}

#ifdef CONFIG_PPC_PSERIES

#define LPPACA_SIZE 0x400

static void *__init alloc_shared_lppaca(unsigned long size, unsigned long limit,
					int cpu)
{
	size_t shared_lppaca_total_size = PAGE_ALIGN(nr_cpu_ids * LPPACA_SIZE);
	static unsigned long shared_lppaca_size;
	static void *shared_lppaca;
	void *ptr;

	if (!shared_lppaca) {
		memblock_set_bottom_up(true);

		/*
		 * See Documentation/arch/powerpc/ultravisor.rst for more details.
		 *
		 * UV/HV data sharing is in PAGE_SIZE granularity. In order to
		 * minimize the number of pages shared, align the allocation to
		 * PAGE_SIZE.
		 */
		shared_lppaca =
			memblock_alloc_try_nid(shared_lppaca_total_size,
					       PAGE_SIZE, MEMBLOCK_LOW_LIMIT,
					       limit, NUMA_NO_NODE);
		if (!shared_lppaca)
			panic("cannot allocate shared data");

		memblock_set_bottom_up(false);
		uv_share_page(PHYS_PFN(__pa(shared_lppaca)),
			      shared_lppaca_total_size >> PAGE_SHIFT);
	}

	ptr = shared_lppaca + shared_lppaca_size;
	shared_lppaca_size += size;

Annotation

Implementation Notes