Skip to content

Commit c6a8239

Browse files
davidhildenbrandmstsirkin
authored andcommitted
virtio-mem: support CONFIG_PROC_VMCORE_DEVICE_RAM
Let's implement the get_device_ram() vmcore callback, so architectures that select NEED_PROC_VMCORE_NEED_DEVICE_RAM, like s390 soon, can include that memory in a crash dump. Merge ranges, and process ranges that might contain a mixture of plugged and unplugged, to reduce the total number of ranges. Signed-off-by: David Hildenbrand <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent fe1d79d commit c6a8239

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

drivers/virtio/virtio_mem.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2728,6 +2728,91 @@ static bool virtio_mem_vmcore_pfn_is_ram(struct vmcore_cb *cb,
27282728
mutex_unlock(&vm->hotplug_mutex);
27292729
return is_ram;
27302730
}
2731+
2732+
#ifdef CONFIG_PROC_VMCORE_DEVICE_RAM
2733+
static int virtio_mem_vmcore_add_device_ram(struct virtio_mem *vm,
2734+
struct list_head *list, uint64_t start, uint64_t end)
2735+
{
2736+
int rc;
2737+
2738+
rc = vmcore_alloc_add_range(list, start, end - start);
2739+
if (rc)
2740+
dev_err(&vm->vdev->dev,
2741+
"Error adding device RAM range: %d\n", rc);
2742+
return rc;
2743+
}
2744+
2745+
static int virtio_mem_vmcore_get_device_ram(struct vmcore_cb *cb,
2746+
struct list_head *list)
2747+
{
2748+
struct virtio_mem *vm = container_of(cb, struct virtio_mem,
2749+
vmcore_cb);
2750+
const uint64_t device_start = vm->addr;
2751+
const uint64_t device_end = vm->addr + vm->usable_region_size;
2752+
uint64_t chunk_size, cur_start, cur_end, plugged_range_start = 0;
2753+
LIST_HEAD(tmp_list);
2754+
int rc;
2755+
2756+
if (!vm->plugged_size)
2757+
return 0;
2758+
2759+
/* Process memory sections, unless the device block size is bigger. */
2760+
chunk_size = max_t(uint64_t, PFN_PHYS(PAGES_PER_SECTION),
2761+
vm->device_block_size);
2762+
2763+
mutex_lock(&vm->hotplug_mutex);
2764+
2765+
/*
2766+
* We process larger chunks and indicate the complete chunk if any
2767+
* block in there is plugged. This reduces the number of pfn_is_ram()
2768+
* callbacks and mimic what is effectively being done when the old
2769+
* kernel would add complete memory sections/blocks to the elfcore hdr.
2770+
*/
2771+
cur_start = device_start;
2772+
for (cur_start = device_start; cur_start < device_end; cur_start = cur_end) {
2773+
cur_end = ALIGN_DOWN(cur_start + chunk_size, chunk_size);
2774+
cur_end = min_t(uint64_t, cur_end, device_end);
2775+
2776+
rc = virtio_mem_send_state_request(vm, cur_start,
2777+
cur_end - cur_start);
2778+
2779+
if (rc < 0) {
2780+
dev_err(&vm->vdev->dev,
2781+
"Error querying block states: %d\n", rc);
2782+
goto out;
2783+
} else if (rc != VIRTIO_MEM_STATE_UNPLUGGED) {
2784+
/* Merge ranges with plugged memory. */
2785+
if (!plugged_range_start)
2786+
plugged_range_start = cur_start;
2787+
continue;
2788+
}
2789+
2790+
/* Flush any plugged range. */
2791+
if (plugged_range_start) {
2792+
rc = virtio_mem_vmcore_add_device_ram(vm, &tmp_list,
2793+
plugged_range_start,
2794+
cur_start);
2795+
if (rc)
2796+
goto out;
2797+
plugged_range_start = 0;
2798+
}
2799+
}
2800+
2801+
/* Flush any plugged range. */
2802+
if (plugged_range_start)
2803+
rc = virtio_mem_vmcore_add_device_ram(vm, &tmp_list,
2804+
plugged_range_start,
2805+
cur_start);
2806+
out:
2807+
mutex_unlock(&vm->hotplug_mutex);
2808+
if (rc < 0) {
2809+
vmcore_free_ranges(&tmp_list);
2810+
return rc;
2811+
}
2812+
list_splice_tail(&tmp_list, list);
2813+
return 0;
2814+
}
2815+
#endif /* CONFIG_PROC_VMCORE_DEVICE_RAM */
27312816
#endif /* CONFIG_PROC_VMCORE */
27322817

27332818
static int virtio_mem_init_kdump(struct virtio_mem *vm)
@@ -2737,6 +2822,9 @@ static int virtio_mem_init_kdump(struct virtio_mem *vm)
27372822
#ifdef CONFIG_PROC_VMCORE
27382823
dev_info(&vm->vdev->dev, "memory hot(un)plug disabled in kdump kernel\n");
27392824
vm->vmcore_cb.pfn_is_ram = virtio_mem_vmcore_pfn_is_ram;
2825+
#ifdef CONFIG_PROC_VMCORE_DEVICE_RAM
2826+
vm->vmcore_cb.get_device_ram = virtio_mem_vmcore_get_device_ram;
2827+
#endif /* CONFIG_PROC_VMCORE_DEVICE_RAM */
27402828
register_vmcore_cb(&vm->vmcore_cb);
27412829
return 0;
27422830
#else /* CONFIG_PROC_VMCORE */

fs/proc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ config NEED_PROC_VMCORE_DEVICE_RAM
6767
config PROC_VMCORE_DEVICE_RAM
6868
def_bool y
6969
depends on PROC_VMCORE && NEED_PROC_VMCORE_DEVICE_RAM
70+
depends on VIRTIO_MEM
7071
help
7172
If the elfcore hdr is allocated and prepared by the dump kernel
7273
("2nd kernel") instead of the crashed kernel, RAM provided by memory

0 commit comments

Comments
 (0)