@@ -128,6 +128,83 @@ static int get_usable_memory_ranges(struct crash_mem **mem_ranges)
128
128
return ret ;
129
129
}
130
130
131
+ /**
132
+ * get_crash_memory_ranges - Get crash memory ranges. This list includes
133
+ * first/crashing kernel's memory regions that
134
+ * would be exported via an elfcore.
135
+ * @mem_ranges: Range list to add the memory ranges to.
136
+ *
137
+ * Returns 0 on success, negative errno on error.
138
+ */
139
+ static int get_crash_memory_ranges (struct crash_mem * * mem_ranges )
140
+ {
141
+ struct memblock_region * reg ;
142
+ struct crash_mem * tmem ;
143
+ int ret ;
144
+
145
+ for_each_memblock (memory , reg ) {
146
+ u64 base , size ;
147
+
148
+ base = (u64 )reg -> base ;
149
+ size = (u64 )reg -> size ;
150
+
151
+ /* Skip backup memory region, which needs a separate entry */
152
+ if (base == BACKUP_SRC_START ) {
153
+ if (size > BACKUP_SRC_SIZE ) {
154
+ base = BACKUP_SRC_END + 1 ;
155
+ size -= BACKUP_SRC_SIZE ;
156
+ } else
157
+ continue ;
158
+ }
159
+
160
+ ret = add_mem_range (mem_ranges , base , size );
161
+ if (ret )
162
+ goto out ;
163
+
164
+ /* Try merging adjacent ranges before reallocation attempt */
165
+ if ((* mem_ranges )-> nr_ranges == (* mem_ranges )-> max_nr_ranges )
166
+ sort_memory_ranges (* mem_ranges , true);
167
+ }
168
+
169
+ /* Reallocate memory ranges if there is no space to split ranges */
170
+ tmem = * mem_ranges ;
171
+ if (tmem && (tmem -> nr_ranges == tmem -> max_nr_ranges )) {
172
+ tmem = realloc_mem_ranges (mem_ranges );
173
+ if (!tmem )
174
+ goto out ;
175
+ }
176
+
177
+ /* Exclude crashkernel region */
178
+ ret = crash_exclude_mem_range (tmem , crashk_res .start , crashk_res .end );
179
+ if (ret )
180
+ goto out ;
181
+
182
+ /*
183
+ * FIXME: For now, stay in parity with kexec-tools but if RTAS/OPAL
184
+ * regions are exported to save their context at the time of
185
+ * crash, they should actually be backed up just like the
186
+ * first 64K bytes of memory.
187
+ */
188
+ ret = add_rtas_mem_range (mem_ranges );
189
+ if (ret )
190
+ goto out ;
191
+
192
+ ret = add_opal_mem_range (mem_ranges );
193
+ if (ret )
194
+ goto out ;
195
+
196
+ /* create a separate program header for the backup region */
197
+ ret = add_mem_range (mem_ranges , BACKUP_SRC_START , BACKUP_SRC_SIZE );
198
+ if (ret )
199
+ goto out ;
200
+
201
+ sort_memory_ranges (* mem_ranges , false);
202
+ out :
203
+ if (ret )
204
+ pr_err ("Failed to setup crash memory ranges\n" );
205
+ return ret ;
206
+ }
207
+
131
208
/**
132
209
* __locate_mem_hole_top_down - Looks top down for a large enough memory hole
133
210
* in the memory regions between buf_min & buf_max
@@ -647,6 +724,81 @@ static int load_backup_segment(struct kimage *image, struct kexec_buf *kbuf)
647
724
return 0 ;
648
725
}
649
726
727
+ /**
728
+ * update_backup_region_phdr - Update backup region's offset for the core to
729
+ * export the region appropriately.
730
+ * @image: Kexec image.
731
+ * @ehdr: ELF core header.
732
+ *
733
+ * Assumes an exclusive program header is setup for the backup region
734
+ * in the ELF headers
735
+ *
736
+ * Returns nothing.
737
+ */
738
+ static void update_backup_region_phdr (struct kimage * image , Elf64_Ehdr * ehdr )
739
+ {
740
+ Elf64_Phdr * phdr ;
741
+ unsigned int i ;
742
+
743
+ phdr = (Elf64_Phdr * )(ehdr + 1 );
744
+ for (i = 0 ; i < ehdr -> e_phnum ; i ++ ) {
745
+ if (phdr -> p_paddr == BACKUP_SRC_START ) {
746
+ phdr -> p_offset = image -> arch .backup_start ;
747
+ pr_debug ("Backup region offset updated to 0x%lx\n" ,
748
+ image -> arch .backup_start );
749
+ return ;
750
+ }
751
+ }
752
+ }
753
+
754
+ /**
755
+ * load_elfcorehdr_segment - Setup crash memory ranges and initialize elfcorehdr
756
+ * segment needed to load kdump kernel.
757
+ * @image: Kexec image.
758
+ * @kbuf: Buffer contents and memory parameters.
759
+ *
760
+ * Returns 0 on success, negative errno on error.
761
+ */
762
+ static int load_elfcorehdr_segment (struct kimage * image , struct kexec_buf * kbuf )
763
+ {
764
+ struct crash_mem * cmem = NULL ;
765
+ unsigned long headers_sz ;
766
+ void * headers = NULL ;
767
+ int ret ;
768
+
769
+ ret = get_crash_memory_ranges (& cmem );
770
+ if (ret )
771
+ goto out ;
772
+
773
+ /* Setup elfcorehdr segment */
774
+ ret = crash_prepare_elf64_headers (cmem , false, & headers , & headers_sz );
775
+ if (ret ) {
776
+ pr_err ("Failed to prepare elf headers for the core\n" );
777
+ goto out ;
778
+ }
779
+
780
+ /* Fix the offset for backup region in the ELF header */
781
+ update_backup_region_phdr (image , headers );
782
+
783
+ kbuf -> buffer = headers ;
784
+ kbuf -> mem = KEXEC_BUF_MEM_UNKNOWN ;
785
+ kbuf -> bufsz = kbuf -> memsz = headers_sz ;
786
+ kbuf -> top_down = false;
787
+
788
+ ret = kexec_add_buffer (kbuf );
789
+ if (ret ) {
790
+ vfree (headers );
791
+ goto out ;
792
+ }
793
+
794
+ image -> arch .elfcorehdr_addr = kbuf -> mem ;
795
+ image -> arch .elf_headers_sz = headers_sz ;
796
+ image -> arch .elf_headers = headers ;
797
+ out :
798
+ kfree (cmem );
799
+ return ret ;
800
+ }
801
+
650
802
/**
651
803
* load_crashdump_segments_ppc64 - Initialize the additional segements needed
652
804
* to load kdump kernel.
@@ -668,6 +820,15 @@ int load_crashdump_segments_ppc64(struct kimage *image,
668
820
}
669
821
pr_debug ("Loaded the backup region at 0x%lx\n" , kbuf -> mem );
670
822
823
+ /* Load elfcorehdr segment - to export crashing kernel's vmcore */
824
+ ret = load_elfcorehdr_segment (image , kbuf );
825
+ if (ret ) {
826
+ pr_err ("Failed to load elfcorehdr segment\n" );
827
+ return ret ;
828
+ }
829
+ pr_debug ("Loaded elf core header at 0x%lx, bufsz=0x%lx memsz=0x%lx\n" ,
830
+ image -> arch .elfcorehdr_addr , kbuf -> bufsz , kbuf -> memsz );
831
+
671
832
return 0 ;
672
833
}
673
834
@@ -887,5 +1048,9 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
887
1048
vfree (image -> arch .backup_buf );
888
1049
image -> arch .backup_buf = NULL ;
889
1050
1051
+ vfree (image -> arch .elf_headers );
1052
+ image -> arch .elf_headers = NULL ;
1053
+ image -> arch .elf_headers_sz = 0 ;
1054
+
890
1055
return kexec_image_post_load_cleanup_default (image );
891
1056
}
0 commit comments