From e09b41010ba33a20a87472ee821fa407a5b8da36 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Mon, 11 Apr 2016 10:41:07 +0300 Subject: These changes are the raw update to linux-4.4.6-rt14. Kernel sources are taken from kernel.org, and rt patch from the rt wiki download page. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen --- kernel/arch/powerpc/platforms/85xx/smp.c | 121 ++++++++++++++++++------------- 1 file changed, 71 insertions(+), 50 deletions(-) (limited to 'kernel/arch/powerpc/platforms/85xx/smp.c') diff --git a/kernel/arch/powerpc/platforms/85xx/smp.c b/kernel/arch/powerpc/platforms/85xx/smp.c index 8631ac5f0..6b107cea1 100644 --- a/kernel/arch/powerpc/platforms/85xx/smp.c +++ b/kernel/arch/powerpc/platforms/85xx/smp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include #include @@ -173,15 +173,22 @@ static inline u32 read_spin_table_addr_l(void *spin_table) static void wake_hw_thread(void *info) { void fsl_secondary_thread_init(void); - unsigned long imsr1, inia1; + unsigned long imsr, inia; int nr = *(const int *)info; - imsr1 = MSR_KERNEL; - inia1 = *(unsigned long *)fsl_secondary_thread_init; + imsr = MSR_KERNEL; + inia = *(unsigned long *)fsl_secondary_thread_init; - mttmr(TMRN_IMSR1, imsr1); - mttmr(TMRN_INIA1, inia1); - mtspr(SPRN_TENS, TEN_THREAD(1)); + if (cpu_thread_in_core(nr) == 0) { + /* For when we boot on a secondary thread with kdump */ + mttmr(TMRN_IMSR0, imsr); + mttmr(TMRN_INIA0, inia); + mtspr(SPRN_TENS, TEN_THREAD(0)); + } else { + mttmr(TMRN_IMSR1, imsr); + mttmr(TMRN_INIA1, inia); + mtspr(SPRN_TENS, TEN_THREAD(1)); + } smp_generic_kick_cpu(nr); } @@ -224,6 +231,12 @@ static int smp_85xx_kick_cpu(int nr) smp_call_function_single(primary, wake_hw_thread, &nr, 0); return 0; + } else if (cpu_thread_in_core(boot_cpuid) != 0 && + cpu_first_thread_sibling(boot_cpuid) == nr) { + if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT))) + return -ENOENT; + + smp_call_function_single(boot_cpuid, wake_hw_thread, &nr, 0); } #endif @@ -331,13 +344,14 @@ struct smp_ops_t smp_85xx_ops = { .cpu_disable = generic_cpu_disable, .cpu_die = generic_cpu_die, #endif -#ifdef CONFIG_KEXEC +#if defined(CONFIG_KEXEC) && !defined(CONFIG_PPC64) .give_timebase = smp_generic_give_timebase, .take_timebase = smp_generic_take_timebase, #endif }; #ifdef CONFIG_KEXEC +#ifdef CONFIG_PPC32 atomic_t kexec_down_cpus = ATOMIC_INIT(0); void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) @@ -345,6 +359,7 @@ void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) local_irq_disable(); if (secondary) { + __flush_disable_L1(); atomic_inc(&kexec_down_cpus); /* loop forever */ while (1); @@ -356,62 +371,67 @@ static void mpc85xx_smp_kexec_down(void *arg) if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(0,1); } - -static void map_and_flush(unsigned long paddr) +#else +void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) { - struct page *page = pfn_to_page(paddr >> PAGE_SHIFT); - unsigned long kaddr = (unsigned long)kmap_atomic(page); + int cpu = smp_processor_id(); + int sibling = cpu_last_thread_sibling(cpu); + bool notified = false; + int disable_cpu; + int disable_threadbit = 0; + long start = mftb(); + long now; - flush_dcache_range(kaddr, kaddr + PAGE_SIZE); - kunmap_atomic((void *)kaddr); -} + local_irq_disable(); + hard_irq_disable(); + mpic_teardown_this_cpu(secondary); -/** - * Before we reset the other cores, we need to flush relevant cache - * out to memory so we don't get anything corrupted, some of these flushes - * are performed out of an overabundance of caution as interrupts are not - * disabled yet and we can switch cores - */ -static void mpc85xx_smp_flush_dcache_kexec(struct kimage *image) -{ - kimage_entry_t *ptr, entry; - unsigned long paddr; - int i; - - if (image->type == KEXEC_TYPE_DEFAULT) { - /* normal kexec images are stored in temporary pages */ - for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); - ptr = (entry & IND_INDIRECTION) ? - phys_to_virt(entry & PAGE_MASK) : ptr + 1) { - if (!(entry & IND_DESTINATION)) { - map_and_flush(entry); + if (cpu == crashing_cpu && cpu_thread_in_core(cpu) != 0) { + /* + * We enter the crash kernel on whatever cpu crashed, + * even if it's a secondary thread. If that's the case, + * disable the corresponding primary thread. + */ + disable_threadbit = 1; + disable_cpu = cpu_first_thread_sibling(cpu); + } else if (sibling != crashing_cpu && + cpu_thread_in_core(cpu) == 0 && + cpu_thread_in_core(sibling) != 0) { + disable_threadbit = 2; + disable_cpu = sibling; + } + + if (disable_threadbit) { + while (paca[disable_cpu].kexec_state < KEXEC_STATE_REAL_MODE) { + barrier(); + now = mftb(); + if (!notified && now - start > 1000000) { + pr_info("%s/%d: waiting for cpu %d to enter KEXEC_STATE_REAL_MODE (%d)\n", + __func__, smp_processor_id(), + disable_cpu, + paca[disable_cpu].kexec_state); + notified = true; } } - /* flush out last IND_DONE page */ - map_and_flush(entry); - } else { - /* crash type kexec images are copied to the crash region */ - for (i = 0; i < image->nr_segments; i++) { - struct kexec_segment *seg = &image->segment[i]; - for (paddr = seg->mem; paddr < seg->mem + seg->memsz; - paddr += PAGE_SIZE) { - map_and_flush(paddr); - } + + if (notified) { + pr_info("%s: cpu %d done waiting\n", + __func__, disable_cpu); } - } - /* also flush the kimage struct to be passed in as well */ - flush_dcache_range((unsigned long)image, - (unsigned long)image + sizeof(*image)); + mtspr(SPRN_TENC, disable_threadbit); + while (mfspr(SPRN_TENSR) & disable_threadbit) + cpu_relax(); + } } +#endif static void mpc85xx_smp_machine_kexec(struct kimage *image) { +#ifdef CONFIG_PPC32 int timeout = INT_MAX; int i, num_cpus = num_present_cpus(); - mpc85xx_smp_flush_dcache_kexec(image); - if (image->type == KEXEC_TYPE_DEFAULT) smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); @@ -429,6 +449,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image) if ( i == smp_processor_id() ) continue; mpic_reset_core(i); } +#endif default_machine_kexec(image); } -- cgit 1.2.3-korg