struct umem_info {
__be64 *buf; /* data buffer for usable-memory property */
u32 size; /* size allocated for the data buffer */
u32 max_entries; /* maximum no. of entries */
u32 idx; /* index of current entry */
/* usable memory ranges to look up */ unsignedint nr_ranges; conststruct range *ranges;
};
if (snprintf(path, NODE_PATH_LEN, "%pOF", dn) > (NODE_PATH_LEN - 1)) {
pr_err("Buffer (%d) too small for memory node: %pOF\n",
NODE_PATH_LEN, dn); return -EOVERFLOW;
}
kexec_dprintk("Memory node path: %s\n", path);
/* Now that we know the path, find its offset in kdump kernel's fdt */
node = fdt_path_offset(fdt, path); if (node < 0) {
pr_err("Malformed device tree: error reading %s\n", path);
ret = -EINVAL; goto out;
}
um_info->idx = 0; if (!check_realloc_usable_mem(um_info, 2)) {
ret = -ENOMEM; goto out;
}
/* *"reg"propertyrepresentssequenceof(addr,size)tuples *eachrepresentingamemoryrange.
*/ for (i = 0; ; i++) {
ret = of_property_read_reg(dn, i, &base, &size); if (ret) break;
ret = add_usable_mem(um_info, base, base + size - 1); if (ret) goto out;
}
// No reg or empty reg? Skip this node. if (i == 0) goto out;
ret = get_crash_memory_ranges(&cmem); if (ret) goto out;
/* Setup elfcorehdr segment */
ret = crash_prepare_elf64_headers(cmem, false, &headers, &headers_sz); if (ret) {
pr_err("Failed to prepare elf headers for the core\n"); goto out;
}
/* Fix the offset for backup region in the ELF header */
update_backup_region_phdr(image, headers);
/** *load_crashdump_segments_ppc64-Initializetheadditionalsegementsneeded *toloadkdumpkernel. *@image:Kexecimage. *@kbuf:Buffercontentsandmemoryparameters. * *Returns0onsuccess,negativeerrnoonerror.
*/ int load_crashdump_segments_ppc64(struct kimage *image, struct kexec_buf *kbuf)
{ int ret;
/* Load backup segment - first 64K bytes of the crashing kernel */
ret = load_backup_segment(image, kbuf); if (ret) {
pr_err("Failed to load backup segment\n"); return ret;
}
kexec_dprintk("Loaded the backup region at 0x%lx\n", kbuf->mem);
/* Load elfcorehdr segment - to export crashing kernel's vmcore */
ret = load_elfcorehdr_segment(image, kbuf); if (ret) {
pr_err("Failed to load elfcorehdr segment\n"); return ret;
}
kexec_dprintk("Loaded elf core header at 0x%lx, bufsz=0x%lx memsz=0x%lx\n",
image->elf_load_addr, kbuf->bufsz, kbuf->memsz);
ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
fdt_load_addr); if (ret) goto out;
if (image->type == KEXEC_TYPE_CRASH) {
u32 my_run_at_load = 1;
/* *Tellrelocatablekerneltorunatloadaddress *viathewordmeantforthatat0x5c.
*/
ret = kexec_purgatory_get_set_symbol(image, "run_at_load",
&my_run_at_load, sizeof(my_run_at_load), false); if (ret) goto out;
}
/* Tell purgatory where to look for backup region */
ret = kexec_purgatory_get_set_symbol(image, "backup_start",
&image->arch.backup_start, sizeof(image->arch.backup_start), false); if (ret) goto out;
/* Setup OPAL base & entry values */
dn = of_find_node_by_path("/ibm,opal"); if (dn) {
u64 val;
ret = of_property_read_u64(dn, "opal-base-address", &val); if (ret) goto out;
ret = kexec_purgatory_get_set_symbol(image, "opal_base", &val, sizeof(val), false); if (ret) goto out;
ret = of_property_read_u64(dn, "opal-entry-address", &val); if (ret) goto out;
ret = kexec_purgatory_get_set_symbol(image, "opal_entry", &val, sizeof(val), false);
}
out: if (ret)
pr_err("Failed to setup purgatory symbols");
of_node_put(dn); return ret;
}
// Budget some space for the password blob. There's already extra space // for the key name if (plpks_is_available())
extra_size += (unsignedint)plpks_get_passwordlen();
/* Get the number of CPU nodes in the current device tree */
for_each_node_by_type(dn, "cpu") {
cpu_nodes++;
}
/* Consider extra space for CPU nodes added since the boot time */ if (cpu_nodes > boot_cpu_node_count)
extra_size += (cpu_nodes - boot_cpu_node_count) * cpu_node_size();
/* Consider extra space for reserved memory ranges if any */ if (rmem->nr_ranges > 0)
extra_size += sizeof(struct fdt_reserve_entry) * rmem->nr_ranges;
/* Ensure backup region is not used by kdump/capture kernel */
ret = fdt_add_mem_rsv(fdt, image->arch.backup_start,
BACKUP_SRC_SIZE); if (ret) {
pr_err("Error reserving memory for backup: %s\n",
fdt_strerror(ret)); goto out;
}
} #endif
/* Update cpus nodes information to account hotplug CPUs. */
ret = update_cpus_node(fdt); if (ret < 0) goto out;
ret = update_pci_dma_nodes(fdt, DIRECT64_PROPNAME); if (ret < 0) goto out;
ret = update_pci_dma_nodes(fdt, DMA64_PROPNAME); if (ret < 0) goto out;
/* Update memory reserve map */
nr_ranges = rmem ? rmem->nr_ranges : 0; for (i = 0; i < nr_ranges; i++) {
u64 base, size;
base = rmem->ranges[i].start;
size = rmem->ranges[i].end - base + 1;
ret = fdt_add_mem_rsv(fdt, base, size); if (ret) {
pr_err("Error updating memory reserve map: %s\n",
fdt_strerror(ret)); goto out;
}
}
// If we have PLPKS active, we need to provide the password to the new kernel if (plpks_is_available())
ret = plpks_populate_fdt(fdt);
out:
kfree(umem); return ret;
}
/** *arch_kexec_kernel_image_probe-Doesadditionalhandlingneededtosetup *kexecsegments. *@image:kexecimagebeingloaded. *@buf:Bufferpointingtoelfdata. *@buf_len:Lengthofthebuffer. * *Returns0onsuccess,negativeerrnoonerror.
*/ int arch_kexec_kernel_image_probe(struct kimage *image, void *buf, unsignedlong buf_len)
{ int ret;
/* Get exclude memory ranges needed for setting up kexec segments */
ret = get_exclude_memory_ranges(&(image->arch.exclude_ranges)); if (ret) {
pr_err("Failed to setup exclude memory ranges for buffer lookup\n"); return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.