@@ -2728,6 +2728,91 @@ static bool virtio_mem_vmcore_pfn_is_ram(struct vmcore_cb *cb,
2728
2728
mutex_unlock (& vm -> hotplug_mutex );
2729
2729
return is_ram ;
2730
2730
}
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 */
2731
2816
#endif /* CONFIG_PROC_VMCORE */
2732
2817
2733
2818
static int virtio_mem_init_kdump (struct virtio_mem * vm )
@@ -2737,6 +2822,9 @@ static int virtio_mem_init_kdump(struct virtio_mem *vm)
2737
2822
#ifdef CONFIG_PROC_VMCORE
2738
2823
dev_info (& vm -> vdev -> dev , "memory hot(un)plug disabled in kdump kernel\n" );
2739
2824
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 */
2740
2828
register_vmcore_cb (& vm -> vmcore_cb );
2741
2829
return 0 ;
2742
2830
#else /* CONFIG_PROC_VMCORE */
0 commit comments