0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kexec.h>
0012 #include <linux/smp.h>
0013 #include <linux/thread_info.h>
0014 #include <linux/init_task.h>
0015 #include <linux/errno.h>
0016 #include <linux/kernel.h>
0017 #include <linux/cpu.h>
0018 #include <linux/hardirq.h>
0019 #include <linux/of.h>
0020
0021 #include <asm/page.h>
0022 #include <asm/current.h>
0023 #include <asm/machdep.h>
0024 #include <asm/cacheflush.h>
0025 #include <asm/firmware.h>
0026 #include <asm/paca.h>
0027 #include <asm/mmu.h>
0028 #include <asm/sections.h> /* _end */
0029 #include <asm/smp.h>
0030 #include <asm/hw_breakpoint.h>
0031 #include <asm/svm.h>
0032 #include <asm/ultravisor.h>
0033
0034 int machine_kexec_prepare(struct kimage *image)
0035 {
0036 int i;
0037 unsigned long begin, end;
0038 unsigned long low, high;
0039 struct device_node *node;
0040 const unsigned long *basep;
0041 const unsigned int *sizep;
0042
0043
0044
0045
0046
0047
0048 for (i = 0; i < image->nr_segments; i++)
0049 if (image->segment[i].mem < __pa(_end))
0050 return -ETXTBSY;
0051
0052
0053 for_each_node_by_type(node, "pci") {
0054 basep = of_get_property(node, "linux,tce-base", NULL);
0055 sizep = of_get_property(node, "linux,tce-size", NULL);
0056 if (basep == NULL || sizep == NULL)
0057 continue;
0058
0059 low = *basep;
0060 high = low + (*sizep);
0061
0062 for (i = 0; i < image->nr_segments; i++) {
0063 begin = image->segment[i].mem;
0064 end = begin + image->segment[i].memsz;
0065
0066 if ((begin < high) && (end > low)) {
0067 of_node_put(node);
0068 return -ETXTBSY;
0069 }
0070 }
0071 }
0072
0073 return 0;
0074 }
0075
0076
0077 static notrace void copy_segments(unsigned long ind)
0078 {
0079 unsigned long entry;
0080 unsigned long *ptr;
0081 void *dest;
0082 void *addr;
0083
0084
0085
0086
0087
0088
0089
0090 ptr = NULL;
0091 dest = NULL;
0092
0093 for (entry = ind; !(entry & IND_DONE); entry = *ptr++) {
0094 addr = __va(entry & PAGE_MASK);
0095
0096 switch (entry & IND_FLAGS) {
0097 case IND_DESTINATION:
0098 dest = addr;
0099 break;
0100 case IND_INDIRECTION:
0101 ptr = addr;
0102 break;
0103 case IND_SOURCE:
0104 copy_page(dest, addr);
0105 dest += PAGE_SIZE;
0106 }
0107 }
0108 }
0109
0110
0111 notrace void kexec_copy_flush(struct kimage *image)
0112 {
0113 long i, nr_segments = image->nr_segments;
0114 struct kexec_segment ranges[KEXEC_SEGMENT_MAX];
0115
0116
0117 memcpy(ranges, image->segment, sizeof(ranges));
0118
0119
0120
0121
0122
0123
0124
0125 copy_segments(image->head);
0126
0127
0128
0129
0130
0131 for (i = 0; i < nr_segments; i++)
0132 flush_icache_range((unsigned long)__va(ranges[i].mem),
0133 (unsigned long)__va(ranges[i].mem + ranges[i].memsz));
0134 }
0135
0136 #ifdef CONFIG_SMP
0137
0138 static int kexec_all_irq_disabled = 0;
0139
0140 static void kexec_smp_down(void *arg)
0141 {
0142 local_irq_disable();
0143 hard_irq_disable();
0144
0145 mb();
0146 get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF;
0147 while(kexec_all_irq_disabled == 0)
0148 cpu_relax();
0149 mb();
0150 hw_breakpoint_disable();
0151
0152
0153
0154
0155 if (ppc_md.kexec_cpu_down)
0156 ppc_md.kexec_cpu_down(0, 1);
0157
0158 reset_sprs();
0159
0160 kexec_smp_wait();
0161
0162 }
0163
0164 static void kexec_prepare_cpus_wait(int wait_state)
0165 {
0166 int my_cpu, i, notified=-1;
0167
0168 hw_breakpoint_disable();
0169 my_cpu = get_cpu();
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 for_each_online_cpu(i) {
0186 if (i == my_cpu)
0187 continue;
0188
0189 while (paca_ptrs[i]->kexec_state < wait_state) {
0190 barrier();
0191 if (i != notified) {
0192 printk(KERN_INFO "kexec: waiting for cpu %d "
0193 "(physical %d) to enter %i state\n",
0194 i, paca_ptrs[i]->hw_cpu_id, wait_state);
0195 notified = i;
0196 }
0197 }
0198 }
0199 mb();
0200 }
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212 static void wake_offline_cpus(void)
0213 {
0214 int cpu = 0;
0215
0216 for_each_present_cpu(cpu) {
0217 if (!cpu_online(cpu)) {
0218 printk(KERN_INFO "kexec: Waking offline cpu %d.\n",
0219 cpu);
0220 WARN_ON(add_cpu(cpu));
0221 }
0222 }
0223 }
0224
0225 static void kexec_prepare_cpus(void)
0226 {
0227 wake_offline_cpus();
0228 smp_call_function(kexec_smp_down, NULL, 0);
0229 local_irq_disable();
0230 hard_irq_disable();
0231
0232 mb();
0233 get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF;
0234
0235 kexec_prepare_cpus_wait(KEXEC_STATE_IRQS_OFF);
0236
0237 kexec_all_irq_disabled = 1;
0238
0239
0240
0241
0242
0243 kexec_prepare_cpus_wait(KEXEC_STATE_REAL_MODE);
0244
0245
0246 if (ppc_md.kexec_cpu_down)
0247 ppc_md.kexec_cpu_down(0, 0);
0248
0249 put_cpu();
0250 }
0251
0252 #else
0253
0254 static void kexec_prepare_cpus(void)
0255 {
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 smp_release_cpus();
0266 if (ppc_md.kexec_cpu_down)
0267 ppc_md.kexec_cpu_down(0, 0);
0268 local_irq_disable();
0269 hard_irq_disable();
0270 }
0271
0272 #endif
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 static union thread_union kexec_stack __init_task_data =
0287 { };
0288
0289
0290
0291
0292
0293 static struct paca_struct kexec_paca;
0294
0295
0296 extern void kexec_sequence(void *newstack, unsigned long start,
0297 void *image, void *control,
0298 void (*clear_all)(void),
0299 bool copy_with_mmu_off) __noreturn;
0300
0301
0302 void default_machine_kexec(struct kimage *image)
0303 {
0304 bool copy_with_mmu_off;
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 if (!kdump_in_progress())
0317 kexec_prepare_cpus();
0318
0319 printk("kexec: Starting switchover sequence.\n");
0320
0321
0322
0323
0324
0325 current_thread_info()->flags = 0;
0326 current_thread_info()->preempt_count = HARDIRQ_OFFSET;
0327
0328
0329
0330
0331
0332 memcpy(&kexec_paca, get_paca(), sizeof(struct paca_struct));
0333 kexec_paca.data_offset = 0xedeaddeadeeeeeeeUL;
0334 #ifdef CONFIG_PPC_PSERIES
0335 kexec_paca.lppaca_ptr = NULL;
0336 #endif
0337
0338 if (is_secure_guest() && !(image->preserve_context ||
0339 image->type == KEXEC_TYPE_CRASH)) {
0340 uv_unshare_all_pages();
0341 printk("kexec: Unshared all shared pages.\n");
0342 }
0343
0344 paca_ptrs[kexec_paca.paca_index] = &kexec_paca;
0345
0346 setup_paca(&kexec_paca);
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363 #ifdef CONFIG_PPC_BOOK3E
0364 copy_with_mmu_off = false;
0365 #else
0366 copy_with_mmu_off = radix_enabled() ||
0367 !(firmware_has_feature(FW_FEATURE_LPAR) ||
0368 firmware_has_feature(FW_FEATURE_PS3_LV1));
0369 #endif
0370
0371
0372
0373
0374 kexec_sequence(&kexec_stack, image->start, image,
0375 page_address(image->control_code_page),
0376 mmu_cleanup_all, copy_with_mmu_off);
0377
0378 }
0379
0380 #ifdef CONFIG_PPC_64S_HASH_MMU
0381
0382 static unsigned long htab_base;
0383 static unsigned long htab_size;
0384
0385 static struct property htab_base_prop = {
0386 .name = "linux,htab-base",
0387 .length = sizeof(unsigned long),
0388 .value = &htab_base,
0389 };
0390
0391 static struct property htab_size_prop = {
0392 .name = "linux,htab-size",
0393 .length = sizeof(unsigned long),
0394 .value = &htab_size,
0395 };
0396
0397 static int __init export_htab_values(void)
0398 {
0399 struct device_node *node;
0400
0401
0402 if (!htab_address)
0403 return -ENODEV;
0404
0405 node = of_find_node_by_path("/chosen");
0406 if (!node)
0407 return -ENODEV;
0408
0409
0410 of_remove_property(node, of_find_property(node, htab_base_prop.name, NULL));
0411 of_remove_property(node, of_find_property(node, htab_size_prop.name, NULL));
0412
0413 htab_base = cpu_to_be64(__pa(htab_address));
0414 of_add_property(node, &htab_base_prop);
0415 htab_size = cpu_to_be64(htab_size_bytes);
0416 of_add_property(node, &htab_size_prop);
0417
0418 of_node_put(node);
0419 return 0;
0420 }
0421 late_initcall(export_htab_values);
0422 #endif