powerpc: Adjust CPU_FTR_SMT on all platforms
PATCH 1/7 powerpc: Adjust CPU_FTR_SMT on all platforms
For historical reasons that code was under #ifdef CONFIG_PPC_PSERIES but it applies equally to all 64-bit platforms.
--- arch/powerpc/kernel/prom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/prom.c +1 -1
@@ -378,7 +378,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,check_cpu_pa_features (node);check_cpu_slb_size (node); -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC64 if (nthreads >1 ) cur_cpu_spec->cpu_features |=CPU_FTR_SMT ;else
Signature · 1 line
1.8.3.2
PATCH 2/7 powerpc: Make boot_cpuid common between 32 and 64-bit
Move the definition to setup-common.c and set the init value to -1 on both 32 and 64-bit (it was 0 on 64-bit).
Additionally add a check to prom.c to garantee that the init value has been udpated after the DT scan.
--- arch/powerpc/kernel/prom.c | 4 ++++ arch/powerpc/kernel/setup-common.c | 3 +++ arch/powerpc/kernel/setup_32.c | 2 -- arch/powerpc/kernel/setup_64.c | 1 - 4 files changed, 7 insertions(+), 3 deletions(-)
arch/powerpc/kernel/prom.c +4 -0
@@ -744,6 +744,10 @@ void __init early_init_devtree(void *params)* (altivec support, boot CPU ID, ...) */ of_scan_flat_dt (early_init_dt_scan_cpus,NULL ); +if (boot_cpuid <0 ) { +printk ("Failed to indentify boot CPU !\n" ); +BUG (); + }#if defined(CONFIG_SMP ) && defined(CONFIG_PPC64 )/* We'll later wait for secondaries to check in; there are
arch/powerpc/kernel/setup-common.c +3 -0
@@ -76,6 +76,9 @@ EXPORT_SYMBOL(ppc_md);struct machdep_calls *machine_id;EXPORT_SYMBOL (machine_id); +int boot_cpuid =-1 ; +EXPORT_SYMBOL_GPL (boot_cpuid); +unsigned long klimit = (unsigned long ) _end;char cmd_line[COMMAND_LINE_SIZE ];
arch/powerpc/kernel/setup_32.c +0 -2
@@ -44,8 +44,6 @@extern void bootx_init (unsigned long r4,unsigned long phys); -int boot_cpuid =-1 ; -EXPORT_SYMBOL_GPL (boot_cpuid);int boot_cpuid_phys;EXPORT_SYMBOL_GPL (boot_cpuid_phys);
arch/powerpc/kernel/setup_64.c +0 -1
@@ -74,7 +74,6 @@ #define DBG(fmt...)#endif -int boot_cpuid =0 ;int spinning_secondaries;u64 ppc64_pft_size;
Signature · 1 line
1.8.3.2
PATCH 3/7 powerpc/prom: early_init_dt_scan_cpus() updates cpu features only once
In reply to Benjamin HerrenschmidtAll our cpu feature updates were done for every CPU in the device-tree, thus overwriting the cputable bits over and over again. Instead do them only for the boot CPU.
--- arch/powerpc/kernel/prom.c | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-)
arch/powerpc/kernel/prom.c +26 -26
@@ -346,33 +346,34 @@ static int __init early_init_dt_scan_cpus(unsigned long node,#endif } -if (found >=0 ) { -DBG ("boot cpu: logical %d physical %d\n" , found, -be32_to_cpu (intserv[found_thread])); - boot_cpuid = found; -set_hard_smp_processor_id (found, -be32_to_cpu (intserv[found_thread])); +/* Not the boot CPU */ +if (found <0 ) +return 0 ; -/* -* PAPR defines "logical" PVR values for cpus that -* meet various levels of the architecture: -* 0x0f000001 Architecture version 2.04 -* 0x0f000002 Architecture version 2.05 -* If the cpu-version property in the cpu node contains -* such a value, we call identify_cpu again with the -* logical PVR value in order to use the cpu feature -* bits appropriate for the architecture level. -* -* A POWER6 partition in "POWER6 architected" mode -* uses the 0x0f000002 PVR value; in POWER5+ mode -* it uses 0x0f000001. -*/ - prop =of_get_flat_dt_prop (node,"cpu-version" ,NULL ); -if (prop && (be32_to_cpup (prop) &0xff000000 ) ==0x0f000000 ) -identify_cpu (0 ,be32_to_cpup (prop)); +DBG ("boot cpu: logical %d physical %d\n" , found, +be32_to_cpu (intserv[found_thread])); + boot_cpuid = found; +set_hard_smp_processor_id (found,be32_to_cpu (intserv[found_thread])); -identical_pvr_fixup (node); - } +/* +* PAPR defines "logical" PVR values for cpus that +* meet various levels of the architecture: +* 0x0f000001 Architecture version 2.04 +* 0x0f000002 Architecture version 2.05 +* If the cpu-version property in the cpu node contains +* such a value, we call identify_cpu again with the +* logical PVR value in order to use the cpu feature +* bits appropriate for the architecture level. +* +* A POWER6 partition in "POWER6 architected" mode +* uses the 0x0f000002 PVR value; in POWER5+ mode +* it uses 0x0f000001. +*/ + prop =of_get_flat_dt_prop (node,"cpu-version" ,NULL ); +if (prop && (be32_to_cpup (prop) &0xff000000 ) ==0x0f000000 ) +identify_cpu (0 ,be32_to_cpup (prop)); + +identical_pvr_fixup (node);check_cpu_feature_properties (node);check_cpu_pa_features (node);
@@ -384,7 +385,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, else cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;#endif -return 0 ; }
Signature · 1 line
1.8.3.2
PATCH 4/7 powerpc/ppc64: Gracefully handle early interrupts
In reply to Benjamin HerrenschmidtIf we take an interrupt such as a trap caused by a BUG_ON before the MMU has been setup, the interrupt handlers try to enable virutal mode and cause a recursive crash, making the original problem very hard to debug.
This fixes it by adjusting the "kernel_msr" value in the PACA so that it only has MSR_IR and MSR_DR (translation for instruction and data) set after the MMU has been initialized for the processor.
We may still not have a console yet but at least we don't get into a recursive fault (and early debug console or memory dump via JTAG of the kernel buffer *will* give us the proper error).
--- arch/powerpc/kernel/paca.c | 3 ++- arch/powerpc/kernel/setup_64.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-)
arch/powerpc/kernel/paca.c +2 -1
@@ -152,7 +152,8 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu) new_paca->paca_index = cpu; new_paca->kernel_toc = kernel_toc; new_paca->kernelbase = (unsigned long ) _stext; - new_paca->kernel_msr =MSR_KERNEL ; +/* Only set MSR:IR/DR when MMU is initialized */ + new_paca->kernel_msr =MSR_KERNEL & ~(MSR_IR |MSR_DR ); new_paca->hw_cpu_id =0xffff ; new_paca->kexec_state =KEXEC_STATE_NONE ; new_paca->__current = &init_task;
arch/powerpc/kernel/setup_64.c +15 -0
@@ -261,6 +261,14 @@ void __init early_setup(unsigned long dt_ptr)/* Initialize the hash table or TLB handling */ early_init_mmu (); +/* +* At this point, we can let interrupts switch to virtual mode +* (the MMU has been setup), so adjust the MSR in the PACA to +* have IR and DR set. +*/ +get_paca ()->kernel_msr =MSR_KERNEL ; + +/* Reserve large chunks of memory for use by CMA for KVM */ kvm_cma_reserve ();/*
@@ -293,6 +301,13 @@ void early_setup_secondary(void)/* Initialize the hash table or TLB handling */ early_init_mmu_secondary (); + +/* +* At this point, we can let interrupts switch to virtual mode +* (the MMU has been setup), so adjust the MSR in the PACA to +* have IR and DR set. +*/ + get_paca()->kernel_msr = MSR_KERNEL; }#endif /* CONFIG_SMP */
Signature · 1 line
1.8.3.2
PATCH 5/7 powerpc/ppc64: Do not turn AIL (reloc-on interrupts) too early
In reply to Benjamin HerrenschmidtTurn them on at the same time as we allow MSR_IR/DR in the paca kernel MSR, ie, after the MMU has been setup enough to be able to handle relocated access to the linear mapping.
--- arch/powerpc/kernel/cpu_setup_power.S | 2 -- arch/powerpc/kernel/setup_64.c | 18 +++++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-)
arch/powerpc/kernel/cpu_setup_power.S +0 -2
@@ -56,7 +56,6 @@ _GLOBAL(__setup_cpu_power8) li r0,0 mtspr SPRN_LPID,r0 mfspr r3,SPRN_LPCR - oris r3, r3, LPCR_AIL_3@h bl __init_LPCR bl __init_HFSCR bl __init_tlb_power8
@@ -75,7 +74,6 @@ _GLOBAL(__restore_cpu_power8) li r0,0 mtspr SPRN_LPID,r0 mfspr r3,SPRN_LPCR - oris r3, r3, LPCR_AIL_3@h bl __init_LPCR bl __init_HFSCR bl __init_tlb_power8
arch/powerpc/kernel/setup_64.c +15 -3
@@ -195,6 +195,18 @@ static void fixup_boot_paca(void)get_paca ()->data_offset =0 ; } +static void cpu_ready_for_interrupts (void ) +{ +/* Set IR and DR in PACA MSR */ +get_paca ()->kernel_msr =MSR_KERNEL ; + +/* Enable AIL if supported */ +if (cpu_has_feature (CPU_FTR_ARCH_207S )) { +unsigned long lpcr =mfspr (SPRN_LPCR ); +mtspr (SPRN_LPCR , lpcr |LPCR_AIL_3 ); + } +} +/* * Early initialization entry point. This is called by head.S * with MMU translation disabled. We rely on the "feature" of
@@ -264,9 +276,9 @@ void __init early_setup(unsigned long dt_ptr)/* * At this point, we can let interrupts switch to virtual mode * (the MMU has been setup), so adjust the MSR in the PACA to -* have IR and DR set. +* have IR and DR set and enable AIL if it exists */ -get_paca ()->kernel_msr =MSR_KERNEL ; +cpu_ready_for_interrupts ();/* Reserve large chunks of memory for use by CMA for KVM */ kvm_cma_reserve ();
@@ -307,7 +319,7 @@ void early_setup_secondary(void)* (the MMU has been setup), so adjust the MSR in the PACA to * have IR and DR set. */ - get_paca()->kernel_msr = MSR_KERNEL; + cpu_ready_for_interrupts(); }#endif /* CONFIG_SMP */
Signature · 1 line
1.8.3.2
Re: [PATCH 5/7] powerpc/ppc64: Do not turn AIL (reloc-on interrupts) too early
Quoted 23 lines · Benjamin Herrenschmidt
Turn them on at the same time as we allow MSR_IR/DR in the paca kernel MSR, ie, after the MMU has been setup enough to be able to handle relocated access to the linear mapping.
Signed-off-by Benjamin Herrenschmidt <[email protected]>--- arch/powerpc/kernel/cpu_setup_power.S | 2 -- arch/powerpc/kernel/setup_64.c | 18 +++++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-)arch/powerpc/kernel/cpu_setup_power.S +0
-1@@ -56,7 +56,6 @@ _GLOBAL(__setup_cpu_power8) li r0,0 mtspr SPRN_LPID,r0 mfspr r3,SPRN_LPCR - oris r3, r3, LPCR_AIL_3@h bl __init_LPCR bl __init_HFSCR bl __init_tlb_power8
arch/powerpc/kernel/cpu_setup_power.S _GLOBAL(__restore_cpu_power8) · line 79
Quoted 7 lines
arch/powerpc/kernel/cpu_setup_power.S +0
-1@@ -75,7 +74,6 @@ _GLOBAL(__restore_cpu_power8) li r0,0 mtspr SPRN_LPID,r0 mfspr r3,SPRN_LPCR - oris r3, r3, LPCR_AIL_3@h bl __init_LPCR bl __init_HFSCR bl __init_tlb_power8
BTW with this we can put the "mfspr r3,SPRN_LPCR" in __init_LPCR
and clean this code up bit.
Mikey
Quoted 51 lines
arch/powerpc/kernel/setup_64.c +15
-3@@ -195,6 +195,18 @@ static void fixup_boot_paca(void)get_paca ()->data_offset =0 ; } +static void cpu_ready_for_interrupts (void ) +{ +/* Set IR and DR in PACA MSR */ +get_paca ()->kernel_msr =MSR_KERNEL ; + +/* Enable AIL if supported */ +if (cpu_has_feature (CPU_FTR_ARCH_207S )) { +unsigned long lpcr =mfspr (SPRN_LPCR ); +mtspr (SPRN_LPCR , lpcr |LPCR_AIL_3 ); + } +} +/* * Early initialization entry point. This is called by head.S * with MMU translation disabled. We rely on the "feature" of @@ -264,9 +276,9 @@ void __init early_setup(unsigned long dt_ptr)/* * At this point, we can let interrupts switch to virtual mode * (the MMU has been setup), so adjust the MSR in the PACA to -* have IR and DR set. +* have IR and DR set and enable AIL if it exists */ -get_paca ()->kernel_msr =MSR_KERNEL ; +cpu_ready_for_interrupts ();/* Reserve large chunks of memory for use by CMA for KVM */ kvm_cma_reserve ();@@ -307,7 +319,7 @@ void early_setup_secondary(void)* (the MMU has been setup), so adjust the MSR in the PACA to * have IR and DR set. */ - get_paca()->kernel_msr = MSR_KERNEL; + cpu_ready_for_interrupts(); }#endif /* CONFIG_SMP */ Signature · 6 lines
1.8.3.2 _______________________________________________ Linuxppc-dev mailing list [email protected] https://lists.ozlabs.org/listinfo/linuxppc-dev
PATCH 6/7 powerpc/powernv: Add opal_notifier_unregister() and export to modules
In reply to Benjamin Herrenschmidtopal_notifier_register() is missing a pending "unregister" variant and should be exposed to modules.
--- arch/powerpc/include/asm/opal.h | 2 ++ arch/powerpc/platforms/powernv/opal.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+)
arch/powerpc/include/asm/opal.h +2 -0
@@ -891,6 +891,8 @@ extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);extern int opal_notifier_register (struct notifier_block *nb); +extern int opal_notifier_unregister (struct notifier_block *nb); +extern int opal_message_notifier_register (enum OpalMessageType msg_type,struct notifier_block *nb);extern void opal_notifier_enable (void );
arch/powerpc/platforms/powernv/opal.c +14 -0
@@ -180,6 +180,20 @@ int opal_notifier_register(struct notifier_block *nb)atomic_notifier_chain_register (&opal_notifier_head, nb);return 0 ; } +EXPORT_SYMBOL_GPL (opal_notifier_register); + +int opal_notifier_unregister (struct notifier_block *nb) +{ +if (!nb) { +pr_warning ("%s: Invalid argument (%p)\n" , + __func__, nb); +return -EINVAL ; + } + +atomic_notifier_chain_unregister (&opal_notifier_head, nb); +return 0 ; +} +EXPORT_SYMBOL_GPL (opal_notifier_unregister);static void opal_do_notifier (uint64_t events) {
Signature · 1 line
1.8.3.2
PATCH 7/7 tty/hvc_opal: Kick the HVC thread on OPAL console events
In reply to Benjamin HerrenschmidtThe firmware can notify us when new input data is available, so let's make sure we wakeup the HVC thread in that case.
--- drivers/tty/hvc/hvc_opal.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
drivers/tty/hvc/hvc_opal.c +25 -1
@@ -61,6 +61,7 @@ static struct hvc_opal_priv *hvc_opal_privs[MAX_NR_HVC_CONSOLES];/* For early boot console */ static struct hvc_opal_priv hvc_opal_boot_priv;static u32 hvc_opal_boot_termno; +static bool hvc_opal_event_registered;static const struct hv_ops hvc_opal_raw_ops = { .get_chars = opal_get_chars,
@@ -161,6 +162,18 @@ static const struct hv_ops hvc_opal_hvsi_ops = { .tiocmset = hvc_opal_hvsi_tiocmset, }; +static int hvc_opal_console_event (struct notifier_block *nb, +unsigned long events,void *change) +{ +if (events &OPAL_EVENT_CONSOLE_INPUT ) +hvc_kick (); +return 0 ; +} + +static struct notifier_block hvc_opal_console_nb = { + .notifier_call = hvc_opal_console_event, +}; +static int hvc_opal_probe (struct platform_device *dev) {const struct hv_ops *ops;
@@ -170,6 +183,7 @@ static int hvc_opal_probe(struct platform_device *dev)unsigned int termno, boot =0 ;const __be32 *reg; +if (of_device_is_compatible (dev->dev.of_node,"ibm,opal-console-raw" )) { proto =HV_PROTOCOL_RAW ; ops = &hvc_opal_raw_ops;
@@ -213,12 +227,18 @@ static int hvc_opal_probe(struct platform_device *dev) dev->dev.of_node->full_name, boot ? " (boot console)" : ""); -/* We don't do IRQ yet */ +/* We don't do IRQ ... */ hp =hvc_alloc (termno,0 , ops,MAX_VIO_PUT_CHARS );if (IS_ERR (hp))return PTR_ERR (hp);dev_set_drvdata (&dev->dev, hp); +/* ... but we use OPAL event to kick the console */ +if (!hvc_opal_event_registered) { +opal_notifier_register (&hvc_opal_console_nb); + hvc_opal_event_registered = true; + } +return 0 ; }
@@ -259,6 +279,10 @@ module_init(hvc_opal_init); static void __exit hvc_opal_exit(void) { +if (hvc_opal_event_registered) +opal_notifier_unregister (&hvc_opal_console_nb); + hvc_opal_event_registered = false; +platform_driver_unregister (&hvc_opal_driver); }module_exit (hvc_opal_exit);
Signature · 1 line
1.8.3.2