@@ -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
27332818static 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 */
0 commit comments