arch/powerpc/platforms/powernv/opal-fadump.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/powernv/opal-fadump.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/powernv/opal-fadump.c
Extension
.c
Size
21405 bytes
Lines
720
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source 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

while (i < be16_to_cpu(fdm->region_cnt)) {
			pr_warn("\t[%03d] base: 0x%llx, size: 0x%llx\n",
				i, be64_to_cpu(fdm->rgn[i].src),
				be64_to_cpu(fdm->rgn[i].size));
			i++;
		}

		pr_warn("If the unsaved regions only contain pages that are filtered out (eg. free/user pages), the vmcore should still be usable.\n");
		pr_warn("WARNING: If the unsaved regions contain kernel pages, the vmcore will be corrupted.\n");
	}

	fadump_conf->boot_mem_top = (fadump_conf->boot_memory_size + hole_size);
	fadump_conf->boot_mem_regs_cnt = be16_to_cpu(fdm->region_cnt);
	opal_fadump_update_config(fadump_conf, fdm);
}

/* Initialize kernel metadata */
static void opal_fadump_init_metadata(struct opal_fadump_mem_struct *fdm)
{
	fdm->version = OPAL_FADUMP_VERSION;
	fdm->region_cnt = cpu_to_be16(0);
	fdm->registered_regions = cpu_to_be16(0);
	fdm->fadumphdr_addr = cpu_to_be64(0);
}

static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf)
{
	u64 addr = fadump_conf->reserve_dump_area_start;
	u16 reg_cnt;
	int i;

	opal_fdm = __va(fadump_conf->kernel_metadata);
	opal_fadump_init_metadata(opal_fdm);

	/* Boot memory regions */
	reg_cnt = be16_to_cpu(opal_fdm->region_cnt);
	for (i = 0; i < fadump_conf->boot_mem_regs_cnt; i++) {
		opal_fdm->rgn[i].src	= cpu_to_be64(fadump_conf->boot_mem_addr[i]);
		opal_fdm->rgn[i].dest	= cpu_to_be64(addr);
		opal_fdm->rgn[i].size	= cpu_to_be64(fadump_conf->boot_mem_sz[i]);

		reg_cnt++;
		addr += fadump_conf->boot_mem_sz[i];
	}
	opal_fdm->region_cnt = cpu_to_be16(reg_cnt);

	/*
	 * Kernel metadata is passed to f/w and retrieved in capture kernel.
	 * So, use it to save fadump header address instead of calculating it.
	 */
	opal_fdm->fadumphdr_addr = cpu_to_be64(be64_to_cpu(opal_fdm->rgn[0].dest) +
					       fadump_conf->boot_memory_size);

	opal_fadump_update_config(fadump_conf, opal_fdm);

	return addr;
}

static u64 opal_fadump_get_metadata_size(void)
{
	return PAGE_ALIGN(sizeof(struct opal_fadump_mem_struct));
}

static int opal_fadump_setup_metadata(struct fw_dump *fadump_conf)
{
	int err = 0;
	s64 ret;

	/*
	 * Use the last page(s) in FADump memory reservation for
	 * kernel metadata.
	 */
	fadump_conf->kernel_metadata = (fadump_conf->reserve_dump_area_start +
					fadump_conf->reserve_dump_area_size -
					opal_fadump_get_metadata_size());
	pr_info("Kernel metadata addr: %llx\n", fadump_conf->kernel_metadata);

	/* Initialize kernel metadata before registering the address with f/w */
	opal_fdm = __va(fadump_conf->kernel_metadata);
	opal_fadump_init_metadata(opal_fdm);

	/*
	 * Register metadata address with f/w. Can be retrieved in
	 * the capture kernel.
	 */
	ret = opal_mpipl_register_tag(OPAL_MPIPL_TAG_KERNEL,
				      fadump_conf->kernel_metadata);
	if (ret != OPAL_SUCCESS) {
		pr_err("Failed to set kernel metadata tag!\n");
		err = -EPERM;

Annotation

Implementation Notes