static __init int register_e820_pmem(void) { struct platform_device *pdev; int rc; rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY, IORESOURCE_MEM, 0, -1, NULL, found); if (rc <= 0) return 0; /* * See drivers/nvdimm/e820.c for the implementation, this is * simply here to trigger the module to load on demand. */ pdev = platform_device_alloc("e820_pmem", -1); return platform_device_add(pdev); }
/* * Helper function for placing a buffer in a kexec segment. This assumes * that kexec_mutex is held. */ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, unsigned long memsz, unsigned long buf_align, unsigned long buf_min, unsigned long buf_max, bool top_down, unsigned long *load_addr) { struct kexec_segment *ksegment; struct kexec_buf buf, *kbuf; int ret; /* Currently adding segment this way is allowed only in file mode */ if (!image->file_mode) return -EINVAL; if (image->nr_segments >= KEXEC_SEGMENT_MAX) return -EINVAL; /* * Make sure we are not trying to add buffer after allocating * control pages. All segments need to be placed first before * any control pages are allocated. As control page allocation * logic goes through list of segments to make sure there are * no destination overlaps. */ if (!list_empty(&image->control_pages)) { WARN_ON(1); return -EINVAL; } memset(&buf, 0, sizeof(struct kexec_buf)); kbuf = &buf; kbuf->image = image; kbuf->buffer = buffer; kbuf->bufsz = bufsz; kbuf->memsz = ALIGN(memsz, PAGE_SIZE); kbuf->buf_align = max(buf_align, PAGE_SIZE); kbuf->buf_min = buf_min; kbuf->buf_max = buf_max; kbuf->top_down = top_down; /* Walk the RAM ranges and allocate a suitable range for the buffer */ if (image->type == KEXEC_TYPE_CRASH) ret = walk_iomem_res_desc(crashk_res.desc, IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, crashk_res.start, crashk_res.end, kbuf, locate_mem_hole_callback); else ret = walk_system_ram_res(0, -1, kbuf, locate_mem_hole_callback); if (ret != 1) { /* A suitable memory range could not be found for buffer */ return -EADDRNOTAVAIL; } /* Found a suitable memory range */ ksegment = &image->segment[image->nr_segments]; ksegment->kbuf = kbuf->buffer; ksegment->bufsz = kbuf->bufsz; ksegment->mem = kbuf->mem; ksegment->memsz = kbuf->memsz; image->nr_segments++; *load_addr = ksegment->mem; return 0; }