MIPS: Loongson: new features and improvements
Subsystems (7)
v2 cover MIPS: Loongson: new features and improvements
This patchset is prepared for the next 4.16 release for Linux/MIPS. It add Loongson-3A R3.1 support, enable Loongson-3's SFB at runtime, adds "model name" and "CPU MHz" knobs in /proc/cpuinfo which is needed by some userspace tools, adds Loongson-3 kexec/kdump and CPUFreq support, fixes CPU UART irq delivery problem, and introduces WAR_LLSC_MB to improve stability.
V1 -> V2:
1, Add Loongson-3A R3.1 basic support.
2, Fix CPU UART irq delivery problem.
3, Improve code and descriptions (Thank James Hogan). 4, Sync the code to upstream.
Huacai Chen(12):
MIPS: Loongson: Add Loongson-3A R3.1 basic support.
MIPS: Loongson-3: Define and use some CP0 registers.
MIPS: Loongson-3: Enable Store Fill Buffer at runtime.
MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3.
MIPS: Loongson fix name confict - MEM_RESERVED.
MIPS: Ensure pmd_present() returns false after pmd_mknotpresent().
MIPS: Add __cpu_full_name[] to make CPU names more human-readable.
MIPS: Align kernel load address to 64KB.
MIPS: Loongson: Add kexec/kdump support.
MIPS: Loongson: Make CPUFreq usable for Loongson-3.
MIPS: Loongson-3: Fix CPU UART irq delivery problem.
MIPS: Loongson: Introduce and use WAR_LLSC_MB.
--- arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 5 +- arch/mips/include/asm/atomic.h | 18 +- arch/mips/include/asm/barrier.h | 6 + arch/mips/include/asm/bitops.h | 15 ++ arch/mips/include/asm/cmpxchg.h | 9 +- arch/mips/include/asm/cpu-info.h | 2 + arch/mips/include/asm/cpu.h | 51 ++--- arch/mips/include/asm/edac.h | 5 +- arch/mips/include/asm/futex.h | 18 +- arch/mips/include/asm/io.h | 2 +- arch/mips/include/asm/local.h | 10 +- arch/mips/include/asm/mach-loongson64/boot_param.h | 3 +- .../asm/mach-loongson64/kernel-entry-init.h | 38 ++-- arch/mips/include/asm/mach-loongson64/loongson.h | 1 + arch/mips/include/asm/mipsregs.h | 2 + arch/mips/include/asm/pgtable-64.h | 5 + arch/mips/include/asm/pgtable.h | 5 +- arch/mips/include/asm/r4kcache.h | 34 +++ arch/mips/include/asm/time.h | 2 + arch/mips/kernel/cpu-probe.c | 28 ++- arch/mips/kernel/proc.c | 7 + arch/mips/kernel/relocate_kernel.S | 30 +++ arch/mips/kernel/smp.c | 3 +- arch/mips/kernel/syscall.c | 2 + arch/mips/kernel/time.c | 2 + arch/mips/loongson64/Kconfig | 1 + arch/mips/loongson64/Platform | 3 + arch/mips/loongson64/common/env.c | 24 ++- arch/mips/loongson64/common/mem.c | 2 +- arch/mips/loongson64/common/platform.c | 13 +- arch/mips/loongson64/common/reset.c | 119 +++++++++++ arch/mips/loongson64/loongson-3/Makefile | 2 +- arch/mips/loongson64/loongson-3/clock.c | 191 +++++++++++++++++ arch/mips/loongson64/loongson-3/irq.c | 41 +--- arch/mips/loongson64/loongson-3/numa.c | 2 +- arch/mips/loongson64/loongson-3/smp.c | 8 +- arch/mips/loongson64/loongson-3/smp.h | 1 + arch/mips/mm/c-r4k.c | 42 +++- arch/mips/mm/tlbex.c | 11 + drivers/cpufreq/Kconfig | 13 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/loongson3_cpufreq.c | 236 +++++++++++++++++++++ drivers/platform/mips/cpu_hwmon.c | 3 +- 43 files changed, 893 insertions(+), 123 deletions(-) create mode 100644 arch/mips/loongson64/loongson-3/clock.c create mode 100644 drivers/cpufreq/loongson3_cpufreq.c
--
2.7.0
PATCH v2 1/12 MIPS: Loongson: Add Loongson-3A R3.1 basic support
Loongson-3A R3.1 is the bugfix revision of Loongson-3A R3.
All Loongson-3 CPU family:
Code-name Brand-name PRId Loongson-3A R1 Loongson-3A1000 0x6305 Loongson-3A R2 Loongson-3A2000 0x6308 Loongson-3A R3 Loongson-3A3000 0x6309 Loongson-3A R3.1 Loongson-3A3000 0x630d Loongson-3B R1 Loongson-3B1000 0x6306 Loongson-3B R2 Loongson-3B1500 0x6307
--- arch/mips/include/asm/cpu.h | 51 ++++++++++++++++++----------------- arch/mips/kernel/cpu-probe.c | 3 ++- arch/mips/loongson64/common/env.c | 3 ++- arch/mips/loongson64/loongson-3/smp.c | 3 ++- drivers/platform/mips/cpu_hwmon.c | 3 ++- 5 files changed, 34 insertions(+), 29 deletions(-)
arch/mips/include/asm/cpu.h +26 -25
@@ -225,31 +225,32 @@* Definitions for 7:0 on legacy processors */ -#define PRID_REV_TX4927 0x0022 -#define PRID_REV_TX4937 0x0030 -#define PRID_REV_R4400 0x0040 -#define PRID_REV_R3000A 0x0030 -#define PRID_REV_R3000 0x0020 -#define PRID_REV_R2000A 0x0010 -#define PRID_REV_TX3912 0x0010 -#define PRID_REV_TX3922 0x0030 -#define PRID_REV_TX3927 0x0040 -#define PRID_REV_VR4111 0x0050 -#define PRID_REV_VR4181 0x0050/* Same as VR4111 */ -#define PRID_REV_VR4121 0x0060 -#define PRID_REV_VR4122 0x0070 -#define PRID_REV_VR4181A 0x0070/* Same as VR4122 */ -#define PRID_REV_VR4130 0x0080 -#define PRID_REV_34K_V1_0_2 0x0022 -#define PRID_REV_LOONGSON1B 0x0020 -#define PRID_REV_LOONGSON1C 0x0020/* Same as Loongson-1B */ -#define PRID_REV_LOONGSON2E 0x0002 -#define PRID_REV_LOONGSON2F 0x0003 -#define PRID_REV_LOONGSON3A_R1 0x0005 -#define PRID_REV_LOONGSON3B_R1 0x0006 -#define PRID_REV_LOONGSON3B_R2 0x0007 -#define PRID_REV_LOONGSON3A_R2 0x0008 -#define PRID_REV_LOONGSON3A_R3 0x0009 +#define PRID_REV_TX4927 0x0022 +#define PRID_REV_TX4937 0x0030 +#define PRID_REV_R4400 0x0040 +#define PRID_REV_R3000A 0x0030 +#define PRID_REV_R3000 0x0020 +#define PRID_REV_R2000A 0x0010 +#define PRID_REV_TX3912 0x0010 +#define PRID_REV_TX3922 0x0030 +#define PRID_REV_TX3927 0x0040 +#define PRID_REV_VR4111 0x0050 +#define PRID_REV_VR4181 0x0050/* Same as VR4111 */ +#define PRID_REV_VR4121 0x0060 +#define PRID_REV_VR4122 0x0070 +#define PRID_REV_VR4181A 0x0070/* Same as VR4122 */ +#define PRID_REV_VR4130 0x0080 +#define PRID_REV_34K_V1_0_2 0x0022 +#define PRID_REV_LOONGSON1B 0x0020 +#define PRID_REV_LOONGSON1C 0x0020/* Same as Loongson-1B */ +#define PRID_REV_LOONGSON2E 0x0002 +#define PRID_REV_LOONGSON2F 0x0003 +#define PRID_REV_LOONGSON3A_R1 0x0005 +#define PRID_REV_LOONGSON3B_R1 0x0006 +#define PRID_REV_LOONGSON3B_R2 0x0007 +#define PRID_REV_LOONGSON3A_R2 0x0008 +#define PRID_REV_LOONGSON3A_R3_0 0x0009 +#define PRID_REV_LOONGSON3A_R3_1 0x000d/* * Older processors used to encode processor version and revision in two
arch/mips/kernel/cpu-probe.c +2 -1
@@ -1834,7 +1834,8 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R2 );break ; -case PRID_REV_LOONGSON3A_R3 : +case PRID_REV_LOONGSON3A_R3_0 : +case PRID_REV_LOONGSON3A_R3_1 : c->cputype =CPU_LOONGSON3 ; __cpu_name[cpu] ="ICT Loongson-3" ;set_elf_platform (cpu,"loongson3a" );
arch/mips/loongson64/common/env.c +2 -1
@@ -198,7 +198,8 @@ void __init prom_init_env(void)break ;case PRID_REV_LOONGSON3A_R1 :case PRID_REV_LOONGSON3A_R2 : -case PRID_REV_LOONGSON3A_R3 : +case PRID_REV_LOONGSON3A_R3_0 : +case PRID_REV_LOONGSON3A_R3_1 : cpu_clock_freq =900000000 ;break ;case PRID_REV_LOONGSON3B_R1 :
arch/mips/loongson64/loongson-3/smp.c +2 -1
@@ -682,7 +682,8 @@ void play_dead(void) (void *)CKSEG1ADDR ((unsigned long )loongson3a_r1_play_dead);break ;case PRID_REV_LOONGSON3A_R2 : -case PRID_REV_LOONGSON3A_R3 : +case PRID_REV_LOONGSON3A_R3_0 : +case PRID_REV_LOONGSON3A_R3_1 : play_dead_at_ckseg1 = (void *)CKSEG1ADDR ((unsigned long )loongson3a_r2r3_play_dead);break ;
drivers/platform/mips/cpu_hwmon.c +2 -1
@@ -30,7 +30,8 @@ int loongson3_cpu_temp(int cpu)case PRID_REV_LOONGSON3B_R2 : reg = ((reg >>8 ) &0xff ) -100 ;break ; -case PRID_REV_LOONGSON3A_R3 : +case PRID_REV_LOONGSON3A_R3_0 : +case PRID_REV_LOONGSON3A_R3_1 : reg = (reg &0xffff )*731 /0x4000 -273 ;break ; }
Signature · 1 line
2.7.0
PATCH v2 2/12 MIPS: Loongson64: Define and use some CP0 registers
In reply to Huacai ChenThis patche defines CP0_CONFIG3, CP0_CONFIG6, CP0_PAGEGRAIN and uses them in kernel-entry-init.h for Loongson64.
--- .../asm/mach-loongson64/kernel-entry-init.h | 24 +++++++++++----------- arch/mips/include/asm/mipsregs.h | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-)
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +12 -12
@@ -19,18 +19,18 @@ .set push .set mips64/* Set LPA on LOONGSON3 config3 */ - mfc0 t0, $16, 3 + mfc0 t0, CP0_CONFIG3 or t0, (0x1 << 7) - mtc0 t0, $16, 3 + mtc0 t0, CP0_CONFIG3/* Set ELPA on LOONGSON3 pagegrain */ - mfc0 t0, $5, 1 + mfc0 t0, CP0_PAGEGRAIN or t0, (0x1 << 29) - mtc0 t0, $5, 1 + mtc0 t0, CP0_PAGEGRAIN #ifdef CONFIG_LOONGSON3_ENHANCEMENT/* Enable STFill Buffer */ - mfc0 t0, $16, 6 + mfc0 t0, CP0_CONFIG6 or t0, 0x100 - mtc0 t0, $16, 6 + mtc0 t0, CP0_CONFIG6 #endif _ehb .set pop
@@ -45,18 +45,18 @@ .set push .set mips64/* Set LPA on LOONGSON3 config3 */ - mfc0 t0, $16, 3 + mfc0 t0, CP0_CONFIG3 or t0, (0x1 << 7) - mtc0 t0, $16, 3 + mtc0 t0, CP0_CONFIG3/* Set ELPA on LOONGSON3 pagegrain */ - mfc0 t0, $5, 1 + mfc0 t0, CP0_PAGEGRAIN or t0, (0x1 << 29) - mtc0 t0, $5, 1 + mtc0 t0, CP0_PAGEGRAIN #ifdef CONFIG_LOONGSON3_ENHANCEMENT/* Enable STFill Buffer */ - mfc0 t0, $16, 6 + mfc0 t0, CP0_CONFIG6 or t0, 0x100 - mtc0 t0, $16, 6 + mtc0 t0, CP0_CONFIG6 #endif _ehb .set pop
arch/mips/include/asm/mipsregs.h +2 -0
@@ -51,6 +51,7 @@#define CP0_GLOBALNUMBER $3, 1#define CP0_CONTEXT $4#define CP0_PAGEMASK $5 +#define CP0_PAGEGRAIN $5, 1#define CP0_SEGCTL0 $5, 2#define CP0_SEGCTL1 $5, 3#define CP0_SEGCTL2 $5, 4
@@ -77,6 +78,7 @@#define CP0_CONFIG $16#define CP0_CONFIG3 $16, 3#define CP0_CONFIG5 $16, 5 +#define CP0_CONFIG6 $16, 6#define CP0_LLADDR $17#define CP0_WATCHLO $18#define CP0_WATCHHI $19
Signature · 1 line
2.7.0
Re: [PATCH V2 02/12] MIPS: Loongson64: Define and use some CP0 registers
Quoted 2 lines · Huacai Chen
This patche defines
CP0_CONFIG3,CP0_CONFIG6,CP0_PAGEGRAINand uses them inkernel-entry-init.hfor Loongson64.
Please write commit messages in the imerative mood (i.e. like you're telling the code how to change), and without referring to the patch itself, E.g.
Quoted 2 lines
Define
CP0_CONFIG3,CP0_CONFIG6,CP0_PAGEGRAINand use them inkernel-entry-init.hfor Loongson64.
Thanks for splitting this patch out.
Cheers
James
PATCH v2 3/12 MIPS: Loongson-3: Enable Store Fill Buffer at runtime
In reply to Huacai ChenNew Loongson-3 (Loongson-3A R2, Loongson-3A R3, and newer) has SFB (Store Fill Buffer) which can improve the performance of memory access. Now, SFB enablement is controlled by CONFIG_LOONGSON3_ENHANCEMENT, and the generic kernel has no benefit from SFB (even it is running on a new Loongson-3 machine). With this patch, we can enable SFB at runtime by detecting the CPU type (the expense is war_io_reorder_wmb() will always be a 'sync', which will hurt the performance of old Loongson-3).
--- arch/mips/include/asm/io.h | 2 +- arch/mips/include/asm/mach-loongson64/kernel-entry-init.h | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-)
arch/mips/include/asm/io.h +1 -1
@@ -304,7 +304,7 @@ static inline void iounmap(const volatile void __iomem *addr)#undef __IS_KSEG1 } -#if defined(CONFIG_CPU_CAVIUM_OCTEON ) || defined(CONFIG_LOONGSON3_ENHANCEMENT ) +#if defined(CONFIG_CPU_CAVIUM_OCTEON ) || defined(CONFIG_CPU_LOONGSON3 )#define war_io_reorder_wmb () wmb()#else #define war_io_reorder_wmb () do { } while (0)
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +10 -4
@@ -26,12 +26,15 @@mfc0 t0,CP0_PAGEGRAIN or t0, (0x1 << 29) mtc0 t0, CP0_PAGEGRAIN -#ifdef CONFIG_LOONGSON3_ENHANCEMENT/* Enable STFill Buffer */ + mfc0 t0, CP0_PRID + andi t0, 0xffff + slti t0, 0x6308 + bnez t0, 1f mfc0 t0, CP0_CONFIG6 or t0, 0x100 mtc0 t0, CP0_CONFIG6 -#endif +1: _ehb .set pop #endif
@@ -52,12 +55,15 @@mfc0 t0,CP0_PAGEGRAIN or t0, (0x1 << 29) mtc0 t0, CP0_PAGEGRAIN -#ifdef CONFIG_LOONGSON3_ENHANCEMENT/* Enable STFill Buffer */ + mfc0 t0, CP0_PRID + andi t0, 0xffff + slti t0, 0x6308 + bnez t0, 1f mfc0 t0, CP0_CONFIG6 or t0, 0x100 mtc0 t0, CP0_CONFIG6 -#endif +1: _ehb .set pop #endif
Signature · 1 line
2.7.0
Re: [PATCH V2 03/12] MIPS: Loongson-3: Enable Store Fill Buffer at runtime
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h line 31
Quoted 12 lines · Huacai Chen
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +2
-1@@ -26,12 +26,15 @@mfc0 t0,CP0_PAGEGRAIN or t0, (0x1 << 29) mtc0 t0, CP0_PAGEGRAIN -#ifdef CONFIG_LOONGSON3_ENHANCEMENT/* Enable STFill Buffer */ + mfc0 t0, CP0_PRID + andi t0, 0xffff
Maybe worth including <asm/cpu.h and doing:
andi t0, (PRID_IMP_MASK | PRID_REV_MASK)
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h line 32
Quoted 1 line
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +1
-0+ slti t0, 0x6308
and:
slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2)
With something like that here and in the other place:
Cheers
James
PATCH v2 4/12 MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3
In reply to Huacai ChenFor multi-node Loongson-3 (NUMA configuration), r4k_blast_scache() can only flush Node-0's scache. So we add r4k_blast_scache_node() by using (CAC_BASE | (node_id << NODE_ADDRSPACE_SHIFT)) instead of CKSEG0 as the start address.
--- arch/mips/include/asm/r4kcache.h | 34 ++++++++++++++++++++++++++++++++ arch/mips/mm/c-r4k.c | 42 +++++++++++++++++++++++++++++++++------- 2 files changed, 69 insertions(+), 7 deletions(-)
arch/mips/include/asm/r4kcache.h +34 -0
@@ -747,4 +747,38 @@ __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , ) __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , ) +#ifndef pa_to_nid +#define pa_to_nid(addr) 0 +#endif + +#ifndef NODE_ADDRSPACE_SHIFT +#define nid_to_addrbase(nid) 0 +#else +#define nid_to_addrbase(nid) (nid << NODE_ADDRSPACE_SHIFT) +#endif + +#define __BUILD_BLAST_CACHE_NODE(pfx, desc, indexop, hitop, lsize) \ +static inline void blast_##pfx##cache##lsize##_node(long node) \ +{ \ + unsigned long start = CAC_BASE | nid_to_addrbase(node); \ + unsigned long end = start + current_cpu_data.desc.waysize; \ + unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ + unsigned long ws_end = current_cpu_data.desc.ways << \ + current_cpu_data.desc.waybit; \ + unsigned long ws, addr; \ + \ + __##pfx##flush_prologue \ + \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ + for (addr = start; addr < end; addr += lsize * 32) \ + cache##lsize##_unroll32(addr|ws, indexop); \ + \ + __##pfx##flush_epilogue \ +} + +__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16) +__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) +__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) +__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) +#endif /* _ASM_R4KCACHE_H */
arch/mips/mm/c-r4k.c +35 -7
76 lines not on this page · raw message
Signature · 1 line
2.7.0
Re: [PATCH V2 04/12] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3
Quoted 17 lines · Huacai Chen
For multi-node Loongson-3 (NUMA configuration),
r4k_blast_scache()can only flush Node-0's scache. So we addr4k_blast_scache_node()by using (CAC_BASE| (node_id<<NODE_ADDRSPACE_SHIFT)) instead of CKSEG0 as the start address.Cc <[email protected]> # 3.15+Signed-off-by Huacai Chen <[email protected]>--- arch/mips/include/asm/r4kcache.h | 34 ++++++++++++++++++++++++++++++++ arch/mips/mm/c-r4k.c | 42 +++++++++++++++++++++++++++++++++------- 2 files changed, 69 insertions(+), 7 deletions(-)arch/mips/include/asm/r4kcache.h +0
-0
arch/mips/include/asm/r4kcache.h __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) · line 754
Quoted 8 lines
arch/mips/include/asm/r4kcache.h +5
-0@@ -747,4 +747,38 @@ __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , ) __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , ) +#ifndef pa_to_nid +#define pa_to_nid(addr) 0 +#endif + +#ifndef NODE_ADDRSPACE_SHIFT
To be sure you get the right definition of both of these if they exist, and wherever this header is included, we should explicitly #include the appropriate header (asm/mmzone.h?) from this header.
arch/mips/include/asm/r4kcache.h __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) · line 757
Quoted 3 lines
arch/mips/include/asm/r4kcache.h +3
-0+#define nid_to_addrbase (nid) 0 +#else +#define nid_to_addrbase (nid) (nid << NODE_ADDRSPACE_SHIFT)
Technically this should have parentheses around nid.
It seems slightly inconsistent to have pa_to_nid() defined in mmzone.h, but not the reverse nid_to_addrbase(). NODE_ADDRSPACE_SHIFT is very loongson specific afterall.
Would it make sense to move it into arch/mips/include/asm/mach-loongson64/mmzone.h and put the 0 definition in #ifndef nid_to_addrbase?
arch/mips/include/asm/r4kcache.h __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) · line 760
Quoted 3 lines
arch/mips/include/asm/r4kcache.h +3
-0+#endif + +#define __BUILD_BLAST_CACHE_NODE (pfx, desc, indexop, hitop, lsize) \
I think this is worthy of a quick comment to explain that this is very specific to Loongson3.
Quoted 5 lines
arch/mips/include/asm/r4kcache.h +0
-0#endif /* _ASM_R4KCACHE_H */ arch/mips/mm/c-r4k.c +0
-0
...
arch/mips/mm/c-r4k.c static inline void local_r4k___flush_cache_all(void * args) · line 501
Quoted 6 lines
arch/mips/mm/c-r4k.c +2
-0@@ -480,6 +497,10 @@ static inline void local_r4k___flush_cache_all(void * args)r4k_blast_scache ();break ; +case CPU_LOONGSON3 : +r4k_blast_scache_node (get_ebase_cpunum () >>2 );
I assume this can't use cpu_to_node() because it needs to work even when NUMA=n? If so, I think it deserves a brief comment to explain that.
Quoted 7 lines
arch/mips/mm/c-r4k.c +2
-0+break ; +case CPU_BMIPS5000 :r4k_blast_scache ();__sync ();@@ -839,9 +860,12 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
arch/mips/mm/c-r4k.c static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) · line 867
Quoted 10 lines
arch/mips/mm/c-r4k.c +5
-3preempt_disable ();if (cpu_has_inclusive_pcaches) { -if (size >= scache_size) -r4k_blast_scache (); -else +if (size >= scache_size) { +if (current_cpu_type () !=CPU_LOONGSON3 ) +r4k_blast_scache (); +else +r4k_blast_scache_node (pa_to_nid (addr));
If I read this right, addr is a virtual address so this feels a bit hacky, but I suppose its harmless since it'll probably always be memory in xkphys space where pa_to_nid() will do the right thing. Perhaps a comment along the lines of:
/* This assumes that addr is in XKPhys */
arch/mips/mm/c-r4k.c static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) · line 868
Quoted 1 line
arch/mips/mm/c-r4k.c +1
-0+ }else
Please keep braces consistent, i.e. add to the trailing else statement too.
Other than those niggles, the actual mechanism looks reasonable to me.
Thanks
James
PATCH v2 5/12 MIPS: Loongson fix name confict - MEM_RESERVED
In reply to Huacai ChenMEM_RESERVED is used as a value of enum mem_type in include/linux/ edac.h. This will make failure to build for Loongson in some case:
for example with CONFIG_RAS enabled.
So here rename MEM_RESERVED to SYSTEM_RAM_RESERVED in Loongson code.
--- arch/mips/include/asm/mach-loongson64/boot_param.h | 2 +- arch/mips/loongson64/common/mem.c | 2 +- arch/mips/loongson64/loongson-3/numa.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
arch/mips/include/asm/mach-loongson64/boot_param.h +1 -1
@@ -4,7 +4,7 @@#define SYSTEM_RAM_LOW 1#define SYSTEM_RAM_HIGH 2 -#define MEM_RESERVED 3 +#define SYSTEM_RAM_RESERVED 3#define PCI_IO 4#define PCI_MEM 5#define LOONGSON_CFG_REG 6
arch/mips/loongson64/common/mem.c +1 -1
@@ -79,7 +79,7 @@ void __init prom_init_memory(void) (u64 )loongson_memmap->map[i].mem_size <<20 , BOOT_MEM_RAM);break ; -case MEM_RESERVED : +case SYSTEM_RAM_RESERVED :add_memory_region (loongson_memmap->map[i].mem_start, (u64 )loongson_memmap->map[i].mem_size <<20 ,BOOT_MEM_RESERVED );
arch/mips/loongson64/loongson-3/numa.c +1 -1
@@ -166,7 +166,7 @@ static void __init szmem(unsigned int node)memblock_add_node (PFN_PHYS (start_pfn),PFN_PHYS (end_pfn - start_pfn), node);break ; -case MEM_RESERVED : +case SYSTEM_RAM_RESERVED :pr_info ("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n" , (u32 )node_id, mem_type, mem_start, mem_size); add_memory_region((node_id << 44) + mem_start,
Signature · 1 line
2.7.0
PATCH v2 6/12 MIPS: Ensure pmd_present() returns false after pmd_mknotpresent()
In reply to Huacai ChenThis patch is borrowed from ARM64 to ensure pmd_present() returns false after pmd_mknotpresent(). This is needed for THP.
Cc: <[email protected]> # 3.8+
References: 5bb1cc0ff9a6 ("arm64: Ensure pmd_present() returns false after pmd_mknotpresent()")
--- arch/mips/include/asm/pgtable-64.h | 5 +++++ 1 file changed, 5 insertions(+)
arch/mips/include/asm/pgtable-64.h +5 -0
@@ -265,6 +265,11 @@ static inline int pmd_bad(pmd_t pmd)static inline int pmd_present (pmd_t pmd) { +#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT +if (unlikely (pmd_val (pmd) & _PAGE_HUGE)) +return pmd_val (pmd) & _PAGE_PRESENT; +#endif +return pmd_val (pmd) != (unsigned long ) invalid_pte_table; }
Signature · 1 line
2.7.0
PATCH v2 7/12 MIPS: Add __cpu_full_name[] to make CPU names more human-readable
In reply to Huacai ChenIn /proc/cpuinfo, we keep "cpu model" as is, since GCC should use it for -march=native. Besides, we add __cpu_full_name[] to describe the processor in a more human-readable manner. The full name is displayed as "model name" in cpuinfo, which is needed by some userspace tools such as gnome-system-monitor.
The CPU frequency in "model name" is the default value (highest), and there is also a "CPU MHz" whose value can be changed by cpufreq.
This is only used by Loongson now (ICT is dropped in cpu name, and cpu name can be overwritten by BIOS).
--- arch/mips/include/asm/cpu-info.h | 2 ++ arch/mips/include/asm/mach-loongson64/boot_param.h | 1 + arch/mips/include/asm/time.h | 2 ++ arch/mips/kernel/cpu-probe.c | 25 ++++++++++++++++------ arch/mips/kernel/proc.c | 7 ++++++ arch/mips/kernel/time.c | 2 ++ arch/mips/loongson64/common/env.c | 13 +++++++++++ arch/mips/loongson64/loongson-3/smp.c | 1 + arch/mips/loongson64/loongson-3/smp.h | 1 + 9 files changed, 48 insertions(+), 6 deletions(-)
arch/mips/include/asm/cpu-info.h +2 -0
@@ -116,7 +116,9 @@ extern void cpu_probe(void);extern void cpu_report (void );extern const char *__cpu_name[]; +extern const char *__cpu_full_name[];#define cpu_name_string () __cpu_name[raw_smp_processor_id()] +#define cpu_full_name_string () __cpu_full_name[raw_smp_processor_id()]struct seq_file ;struct notifier_block ;
arch/mips/include/asm/mach-loongson64/boot_param.h +1 -0
@@ -58,6 +58,7 @@ struct efi_cpuinfo_loongson {u16 reserved_cores_mask;u32 cpu_clock_freq;/* cpu_clock */ u32 nr_cpus; +char cpuname[64 ]; } __packed;#define MAX_UARTS 64
arch/mips/include/asm/time.h +2 -0
@@ -35,6 +35,8 @@ extern int rtc_mips_set_mmss(unsigned long);*/ extern void plat_time_init (void ); +extern unsigned int mips_cpu_frequency; +/* * mips_hpt_frequency - must be set if you intend to use an R4k-compatible * counter as a timer interrupt source.
arch/mips/kernel/cpu-probe.c +19 -6
@@ -1461,30 +1461,40 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)switch (c->processor_id &PRID_REV_MASK ) {case PRID_REV_LOONGSON2E : c->cputype =CPU_LOONGSON2 ; - __cpu_name[cpu] ="ICT Loongson-2" ; + __cpu_name[cpu] ="Loongson-2" ;set_elf_platform (cpu,"loongson2e" );set_isa (c,MIPS_CPU_ISA_III ); c->fpu_msk31 |=FPU_CSR_CONDX ; + __cpu_full_name[cpu] ="Loongson-2E" ;break ;case PRID_REV_LOONGSON2F : c->cputype =CPU_LOONGSON2 ; - __cpu_name[cpu] ="ICT Loongson-2" ; + __cpu_name[cpu] ="Loongson-2" ;set_elf_platform (cpu,"loongson2f" );set_isa (c,MIPS_CPU_ISA_III ); c->fpu_msk31 |=FPU_CSR_CONDX ; + __cpu_full_name[cpu] ="Loongson-2F" ;break ;case PRID_REV_LOONGSON3A_R1 : c->cputype =CPU_LOONGSON3 ; - __cpu_name[cpu] ="ICT Loongson-3" ; + __cpu_name[cpu] ="Loongson-3" ;set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R1 ); + __cpu_full_name[cpu] ="Loongson-3A R1 (Loongson-3A1000)" ;break ;case PRID_REV_LOONGSON3B_R1 : + c->cputype =CPU_LOONGSON3 ; + __cpu_name[cpu] ="Loongson-3" ; +set_elf_platform (cpu,"loongson3b" ); +set_isa (c,MIPS_CPU_ISA_M64R1 ); + __cpu_full_name[cpu] ="Loongson-3B R1 (Loongson-3B1000)" ; +break ;case PRID_REV_LOONGSON3B_R2 : c->cputype =CPU_LOONGSON3 ; - __cpu_name[cpu] ="ICT Loongson-3" ; + __cpu_name[cpu] ="Loongson-3" ;set_elf_platform (cpu,"loongson3b" );set_isa (c,MIPS_CPU_ISA_M64R1 ); + __cpu_full_name[cpu] ="Loongson-3B R2 (Loongson-3B1500)" ;break ; }
@@ -1830,16 +1840,18 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)switch (c->processor_id &PRID_REV_MASK ) {case PRID_REV_LOONGSON3A_R2 : c->cputype =CPU_LOONGSON3 ; - __cpu_name[cpu] ="ICT Loongson-3" ; + __cpu_name[cpu] ="Loongson-3" ;set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R2 ); + __cpu_full_name[cpu] ="Loongson-3A R2 (Loongson-3A2000)" ;break ;case PRID_REV_LOONGSON3A_R3_0 :case PRID_REV_LOONGSON3A_R3_1 : c->cputype =CPU_LOONGSON3 ; - __cpu_name[cpu] ="ICT Loongson-3" ; + __cpu_name[cpu] ="Loongson-3" ;set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R2 ); + __cpu_full_name[cpu] ="Loongson-3A R3 (Loongson-3A3000)" ;break ; }
@@ -1959,6 +1971,7 @@ EXPORT_SYMBOL(__ua_limit);#endif const char *__cpu_name[NR_CPUS ]; +const char *__cpu_full_name[NR_CPUS ];const char *__elf_platform;void cpu_probe (void )
arch/mips/kernel/proc.c +7 -0
@@ -15,6 +15,7 @@#include <asm/mipsregs.h> #include <asm/processor.h> #include <asm/prom.h> +#include <asm/time.h> unsigned int vced_count, vcei_count;
@@ -63,6 +64,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)seq_printf (m, fmt, __cpu_name[n], (version >>4 ) &0x0f , version &0x0f , (fp_vers >>4 ) &0x0f , fp_vers &0x0f ); +if (__cpu_full_name[n]) +seq_printf (m,"model name\t\t: %s\n" , __cpu_full_name[n]); +if (mips_cpu_frequency) +seq_printf (m,"CPU MHz\t\t\t: %u.%02u\n" , + mips_cpu_frequency /1000000 , + (mips_cpu_frequency /10000 ) %100 );seq_printf (m,"BogoMIPS\t\t: %u.%02u\n" , cpu_data[n].udelay_val / (500000 /HZ ), (cpu_data[n].udelay_val / (5000 /HZ )) %100 );
arch/mips/kernel/time.c +2 -0
@@ -69,6 +69,8 @@ EXPORT_SYMBOL(perf_irq);* 2) calculate a couple of cached variables for later usage */ +unsigned int mips_cpu_frequency; +EXPORT_SYMBOL_GPL (mips_cpu_frequency);unsigned int mips_hpt_frequency;EXPORT_SYMBOL_GPL (mips_hpt_frequency);
arch/mips/loongson64/common/env.c +13 -0
@@ -18,6 +18,7 @@* option) any later version. */ #include <linux/export.h> +#include <asm/time.h> #include <asm/bootinfo.h> #include <loongson.h> #include <boot_param.h>
@@ -25,6 +26,7 @@u32 cpu_clock_freq;EXPORT_SYMBOL (cpu_clock_freq); +char cpu_full_name[64 ];struct efi_memory_map_loongson *loongson_memmap;struct loongson_system_configuration loongson_sysconf;
@@ -45,6 +47,7 @@ do { \void __init prom_init_env (void ) {/* pmon passes arguments in 32bit pointers */ +char freq[12 ];unsigned int processor_id;#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
@@ -151,6 +154,10 @@ void __init prom_init_env(void) loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus + loongson_sysconf.cores_per_node -1 ) / loongson_sysconf.cores_per_node; +if (!strncmp (ecpu->cpuname,"Loongson" ,8 )) +strncpy (cpu_full_name, ecpu->cpuname,sizeof (cpu_full_name)); +if (cpu_full_name[0 ] ==0 ) +strncpy (cpu_full_name, __cpu_full_name[0 ],sizeof (cpu_full_name)); loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr; loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
@@ -211,5 +218,11 @@ void __init prom_init_env(void)break ; } } + mips_cpu_frequency = cpu_clock_freq;pr_info ("CpuClock = %u\n" , cpu_clock_freq); + +/* Append default cpu frequency with round-off */ +sprintf (freq," @ %uMHz" , (cpu_clock_freq +500000 ) /1000000 ); +strncat (cpu_full_name, freq,sizeof (cpu_full_name)); + __cpu_full_name[0 ] = cpu_full_name; }
arch/mips/loongson64/loongson-3/smp.c +1 -0
@@ -340,6 +340,7 @@ static void loongson3_init_secondary(void) initcount = core0_c0count[cpu] + i/2 ;write_c0_count (initcount); + __cpu_full_name[cpu] = cpu_full_name; }static void loongson3_smp_finish (void )
arch/mips/loongson64/loongson-3/smp.h +1 -0
@@ -3,6 +3,7 @@#define __LOONGSON_SMP_H_/* for Loongson-3 smp support */ +extern char cpu_full_name[64 ];extern unsigned long long smp_group[4 ];/* 4 groups(nodes) in maximum in numa case */
Signature · 1 line
2.7.0
PATCH v2 8/12 MIPS: Align kernel load address to 64KB
KEXEC assume kernel align to PAGE_SIZE, and 64KB is the largest PAGE_SIZE.
--- arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +2 -3
@@ -45,11 +45,10 @@ int main(int argc, char *argv[]) vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;/* -* Align with 16 bytes: "greater than that used for any standard data -* types by a MIPS compiler." -- See MIPS Run Linux (Second Edition). +* Align with 64KB: KEXEC assume kernel align to PAGE_SIZE */ - vmlinuz_load_addr += (16 - vmlinux_size %16 ); + vmlinuz_load_addr += (65536 - vmlinux_size %65536 );printf ("0x%llx\n" , vmlinuz_load_addr);
Signature · 1 line
2.7.0
Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB
Quoted 2 lines · Huacai Chen
KEXEC assume kernel align to
PAGE_SIZE, and 64KB is the largestPAGE_SIZE.
Please expand, maybe referring to sanity_check_segment_list() which does the actual check. Maybe something like this:
Kexec needs the new kernel's load address to be aligned on a page boundary (see sanity_check_segment_list()), but on MIPS the default vmlinuz load address is only explicitly aligned to 16 bytes.
Since the largest PAGE_SIZE supported by MIPS kernels is 64KB, increase the alignment calculated by calc_vmlinuz_load_addr to 64KB.
I suppose it'd be a bit ugly for the kexec userland code to increase the size of the load segment downwards to make it page aligned...
Quoted 11 lines
Signed-off-by Huacai Chen <[email protected]>--- arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +0
-0
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c int main(int argc, char *argv[]) · line 48
Quoted 6 lines
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +1
-2@@ -45,11 +45,10 @@ int main(int argc, char *argv[]) vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;/* -* Align with 16 bytes: "greater than that used for any standard data -* types by a MIPS compiler." -- See MIPS Run Linux (Second Edition). +* Align with 64KB: KEXEC assume kernel align to PAGE_SIZE
"Align to 64KB: kexec needs load sections to be aligned to PAGE_SIZE, which may be as large as 64KB depending on the kernel configuration".
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c int main(int argc, char *argv[]) · line 51
Quoted 4 lines
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +1
-1*/ - vmlinuz_load_addr += (16 - vmlinux_size %16 ); + vmlinuz_load_addr += (65536 - vmlinux_size %65536 );
Personally I find (64 * 1024) (or even SZ_64K) easier to read, but no big deal.
Thanks
James
Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB
Quoted 6 lines · James Hogan
Quoted 2 lines
KEXEC assume kernel align to
PAGE_SIZE, and 64KB is the largestPAGE_SIZE.Please expand, maybe referring to
sanity_check_segment_list()which does the actual check. Maybe something like this:
Quoted 6 lines
Kexec needs the new kernel's load address to be aligned on a page boundary (see
sanity_check_segment_list()), but on MIPS the default vmlinuz load address is only explicitly aligned to 16 bytes.Since the largest
PAGE_SIZEsupported by MIPS kernels is 64KB, increase the alignment calculated bycalc_vmlinuz_load_addrto 64KB.
But why does it have to be hardcoded? Shouldn't it be inherited from
the image being loaded? I'm missing bits of context here, but that would be either CONFIG_PAGE_SIZE_* settings or the ELF program header's `p_align' value, depending on how this code operates. Wasting say 60kB of memory on smaller systems due to excessive alignment might not be a good idea.
Maciej
Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB
Quoted 15 lines · Maciej W. Rozycki
Quoted 6 lines · James Hogan
Quoted 2 lines
KEXEC assume kernel align to
PAGE_SIZE, and 64KB is the largestPAGE_SIZE.Please expand, maybe referring to
sanity_check_segment_list()which does the actual check. Maybe something like this:Quoted 6 lines
Kexec needs the new kernel's load address to be aligned on a page boundary (see
sanity_check_segment_list()), but on MIPS the default vmlinuz load address is only explicitly aligned to 16 bytes.Since the largest
PAGE_SIZEsupported by MIPS kernels is 64KB, increase the alignment calculated bycalc_vmlinuz_load_addrto 64KB.
Quoted 6 lines
But why does it have to be hardcoded? Shouldn't it be inherited from
the image being loaded? I'm missing bits of context here, but that would be either CONFIG_PAGE_SIZE_* settings or the ELF program header's `p_align' value, depending on how this code operates. Wasting say 60kB of memory on smaller systems due to excessive alignment might not be a good idea.
I presume there's nothing to stop a kernel with 64KB pages (and hence requiring 64KB alignment of load sections) loading a new kernel with 4KB pages (which is the one we're looking at).
Cheers
James
Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB
Quoted 10 lines · James Hogan
Quoted 9 lines
Quoted 2 lines
Since the largest
PAGE_SIZEsupported by MIPS kernels is 64KB, increase the alignment calculated bycalc_vmlinuz_load_addrto 64KB.But why does it have to be hardcoded? Shouldn't it be inherited from
the image being loaded? I'm missing bits of context here, but that would be either CONFIG_PAGE_SIZE_* settings or the ELF program header's `p_align' value, depending on how this code operates. Wasting say 60kB of memory on smaller systems due to excessive alignment might not be a good idea.
Quoted 3 lines
I presume there's nothing to stop a kernel with 64KB pages (and hence requiring 64KB alignment of load sections) loading a new kernel with 4KB pages (which is the one we're looking at).
As I say, I'm missing bits of context. If you say that a 64kiB-page
kernel loads a 4kiB-page kernel, then the alignment for the latter is obviously 4kiB. So I repeat my question: why hardcode the alignment to 64kiB while we only need 4kiB in this case?
Maciej
Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB
Quoted 12 lines · Maciej W. Rozycki
Quoted 10 lines · James Hogan
Quoted 9 lines
Quoted 2 lines
Since the largest
PAGE_SIZEsupported by MIPS kernels is 64KB, increase the alignment calculated bycalc_vmlinuz_load_addrto 64KB.But why does it have to be hardcoded? Shouldn't it be inherited from
the image being loaded? I'm missing bits of context here, but that would be either CONFIG_PAGE_SIZE_* settings or the ELF program header's `p_align' value, depending on how this code operates. Wasting say 60kB of memory on smaller systems due to excessive alignment might not be a good idea.
Quoted 8 lines
Quoted 3 lines
I presume there's nothing to stop a kernel with 64KB pages (and hence requiring 64KB alignment of load sections) loading a new kernel with 4KB pages (which is the one we're looking at).
As I say, I'm missing bits of context. If you say that a 64kiB-page
kernel loads a 4kiB-page kernel, then the alignment for the latter is obviously 4kiB. So I repeat my question: why hardcode the alignment to 64kiB while we only need 4kiB in this case?
Because its the 1st kernel which is doing the kexec'ing of the 2nd kernel. The 2nd kernel might not even have kexec enabled, but you still might want to boot it using kexec.
The only alternative is for the kexec userland tools to be able to automatically adjust the load segments to load a bit more before the start of the kernel image so that its aligned, and i'm not sure how universally safe that would be.
Cheers
James
Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB
Quoted 8 lines · James Hogan
Quoted 4 lines
As I say, I'm missing bits of context. If you say that a 64kiB-page
kernel loads a 4kiB-page kernel, then the alignment for the latter is obviously 4kiB. So I repeat my question: why hardcode the alignment to 64kiB while we only need 4kiB in this case?Because its the 1st kernel which is doing the kexec'ing of the 2nd kernel. The 2nd kernel might not even have kexec enabled, but you still might want to boot it using kexec.
Forgive my dumbness, but I don't understand what's preventing the 1st
kernel from getting the alignment of the 2nd kernel (regardless of whether the 2nd kernel has kexec enabled). What prevents the 1st kernel from interpreting the `p_align' value from the relevant program header of the 2nd kernel before loading the segment the header describes? It has to load the header anyway or it wouldn't know how much data to load and where from into the file, and how much BSS space to initialise.
Here's an example program header dump from `vmlinux':
$ readelf -l vmlinux
Elf file type is EXEC (Executable file) Entry point 0x80506e70
There are 3 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align ABIFLAGS 0x4b02e8 0x805ac2e8 0x805ac2e8 0x00018 0x00018 R 0x8 LOAD 0x004000 0x80100000 0x80100000 0x534650 0x569710 RWE 0x4000 NOTE 0x4145a8 0x805105a8 0x805105a8 0x00024 0x00024 R 0x4
Section to Segment mapping:
Segment Sections...
00 .MIPS.abiflags 01 .text __ex_table .notes .rodata .MIPS.abiflags .pci_fixup __ksymtab __ksymtab_gpl __kcrctab __kcrctab_gpl __ksymtab_strings __param __modver .data .init.text .init.data .exit.text .bss 02 .notes
$
As you can see there's only one loadable segment (the usual case) and its alignment is 0x4000, that is 16kiB. So this kernel uses a page size of 16kiB.
Maciej
Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB
Quoted 11 lines · Maciej W. Rozycki
Quoted 8 lines · James Hogan
Quoted 4 lines
As I say, I'm missing bits of context. If you say that a 64kiB-page
kernel loads a 4kiB-page kernel, then the alignment for the latter is obviously 4kiB. So I repeat my question: why hardcode the alignment to 64kiB while we only need 4kiB in this case?Because its the 1st kernel which is doing the kexec'ing of the 2nd kernel. The 2nd kernel might not even have kexec enabled, but you still might want to boot it using kexec.
Quoted 7 lines
Forgive my dumbness, but I don't understand what's preventing the 1st
kernel from getting the alignment of the 2nd kernel (regardless of whether the 2nd kernel has kexec enabled). What prevents the 1st kernel from interpreting the `p_align' value from the relevant program header of the 2nd kernel before loading the segment the header describes? It has to load the header anyway or it wouldn't know how much data to load and where from into the file, and how much BSS space to initialise.
The kernel doesn't always get an elf through kexec_load(2), but rather a list of load segments. In any case though its not about knowing the page size of 2nd kernel, its about kexec working with page size chunks. See the comment in sanity_check_segment_list().
Quoted 4 lines
Here's an example program header dump from `vmlinux':
$ readelf -l vmlinux
Yeh but its not a vmlinux, its a vmlinuz. Thats the whole point. Though it sounds like you'd have the same problem with vmlinux too if you tried reducing the page size, so perhaps its fine for compressed kernels to just align to the page size of the 2nd kernel, so they're no worse than vmlinux.
Quoted 13 lines
Elf file type is EXEC (Executable file) Entry point
0x80506e70
There are 3 program headers, starting at offset 52Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align ABIFLAGS 0x4b02e8 0x805ac2e8 0x805ac2e8 0x00018 0x00018 R 0x8 LOAD 0x004000 0x80100000 0x80100000 0x534650 0x569710 RWE 0x4000 NOTE 0x4145a8 0x805105a8 0x805105a8 0x00024 0x00024 R 0x4Section to Segment mapping:
Segment Sections...
Quoted 8 lines
00 .MIPS.abiflags 01 .text __ex_table .notes .rodata .MIPS.abiflags .pci_fixup __ksymtab __ksymtab_gpl __kcrctab __kcrctab_gpl __ksymtab_strings __param __modver .data .init.text .init.data .exit.text .bss 02 .notes$
As you can see there's only one loadable segment (the usual case) and its alignment is
0x4000, that is 16kiB. So this kernel uses a page size of 16kiB.
For malta_defconfig *vmlinuz* however (CONFIG_PAGE_SIZE_16KB=y), I get this:
LOAD 0x008320 0x80828320 0x80828320 0x35e580 0x8605a0 RWE 0x10000
Cheers
James
Re: [PATCH V2 08/12] MIPS: Align kernel load address to 64KB
Quoted 8 lines · James Hogan
Quoted 7 lines
Forgive my dumbness, but I don't understand what's preventing the 1st
kernel from getting the alignment of the 2nd kernel (regardless of whether the 2nd kernel has kexec enabled). What prevents the 1st kernel from interpreting the `p_align' value from the relevant program header of the 2nd kernel before loading the segment the header describes? It has to load the header anyway or it wouldn't know how much data to load and where from into the file, and how much BSS space to initialise.
Quoted 4 lines
The kernel doesn't always get an elf through
kexec_load(2), but rather a list of load segments. In any case though its not about knowing the page size of 2nd kernel, its about kexec working with page size chunks. See the comment insanity_check_segment_list().
So this is 1st kernel's page size AFAICT. And I can see `structkexec_segment' drops ELF program header information, sigh.
Quoted 9 lines
Quoted 3 lines
Here's an example program header dump from `vmlinux':
$ readelf -l vmlinuxYeh but its not a vmlinux, its a vmlinuz. Thats the whole point. Though it sounds like you'd have the same problem with vmlinux too if you tried reducing the page size, so perhaps its fine for compressed kernels to just align to the page size of the 2nd kernel, so they're no worse than vmlinux.
Well, even if compressed you need to preserve the original structures
somehow so that once uncompressed the memory image is the same as if `vmlinux' was loaded directly.
Quoted 7 lines
Quoted 3 lines
As you can see there's only one loadable segment (the usual case) and its alignment is
0x4000, that is 16kiB. So this kernel uses a page size of 16kiB.For
malta_defconfig*vmlinuz* however (CONFIG_PAGE_SIZE_16KB=y), I get this:
LOAD0x0083200x808283200x808283200x35e5800x8605a0RWE0x10000
Hmm, now you've left me stumped, so I'll shut up.
Maciej
PATCH v2 9/12 MIPS: Loongson: Add kexec/kdump support
In reply to Huacai Chen--- arch/mips/kernel/relocate_kernel.S | 30 +++++++++ arch/mips/loongson64/common/env.c | 8 +++ arch/mips/loongson64/common/reset.c | 119 ++++++++++++++++++++++++++++++++++ arch/mips/loongson64/loongson-3/smp.c | 4 ++ 4 files changed, 161 insertions(+)
arch/mips/kernel/relocate_kernel.S +30 -0
@@ -135,6 +135,36 @@ LEAF(kexec_smp_wait) #else sync #endif + +#ifdef CONFIG_CPU_LOONGSON3 + /* s0:prid s1:initfn */ + /* t0:base t1:cpuid t2:node t3:core t9:count */ + mfc0 t1, $15, 1 + andi t1, 0x3ff + dli t0, 0x900000003ff01000 + andi t3, t1, 0x3 + sll t3, 8 /* get core id */ + or t0, t0, t3 + andi t2, t1, 0xc + dsll t2, 42 /* get node id */ + or t0, t0, t2 + mfc0 s0, $15, 0 + andi s0, s0, 0xf + blt s0, 0x6, 1f /* Loongson-3A1000 */ + bgt s0, 0x7, 1f /* Loongson-3A2000/3A3000 */ + dsrl t2, 30 /* Loongson-3B1000/3B1500 need bit15:14 */ + or t0, t0, t2 +1: li t9, 0x100 /* wait for init loop */ +2: addiu t9, -1 /* limit mailbox access */ + bnez t9, 2b + ld s1, 0x20(t0) /* get PC via mailbox */ + beqz s1, 1b + ld sp, 0x28(t0) /* get SP via mailbox */ + ld gp, 0x30(t0) /* get GP via mailbox */ + ld a1, 0x38(t0) + jr s1 /* jump to initial PC */ +#endif + j s1 END(kexec_smp_wait) #endif
arch/mips/loongson64/common/env.c +8 -0
@@ -72,6 +72,7 @@ void __init prom_init_env(void)pr_info ("memsize=%u, highmemsize=%u\n" , memsize, highmemsize);#else +int i;struct boot_params *boot_p;struct loongson_params *loongson_p;struct system_loongson *esys;
@@ -149,6 +150,13 @@ void __init prom_init_env(void) loongson_sysconf.nr_cpus = ecpu->nr_cpus; loongson_sysconf.boot_cpu_id = ecpu->cpu_startup_core_id; loongson_sysconf.reserved_cpus_mask = ecpu->reserved_cores_mask; +#ifdef CONFIG_KEXEC + loongson_sysconf.boot_cpu_id =get_ebase_cpunum (); +for (i =0 ; i < loongson_sysconf.boot_cpu_id; i++) + loongson_sysconf.reserved_cpus_mask |= (1 <<i); +pr_info ("Boot CPU ID is being fixed from %d to %d\n" , + ecpu->cpu_startup_core_id, loongson_sysconf.boot_cpu_id); +#endif if (ecpu->nr_cpus >NR_CPUS || ecpu->nr_cpus ==0 ) loongson_sysconf.nr_cpus =NR_CPUS ; loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
arch/mips/loongson64/common/reset.c +119 -0
140 lines not on this page · raw message
arch/mips/loongson64/loongson-3/smp.c +4 -0
@@ -387,6 +387,10 @@ static void __init loongson3_smp_setup(void)ipi_status0_regs_init ();ipi_en0_regs_init ();ipi_mailbox_buf_init (); + +for (i =0 ; i < loongson_sysconf.nr_cpus; i++) +loongson3_ipi_write64 (0 , (void *)(ipi_mailbox_buf[i]+0x0 )); +cpu_set_core (&cpu_data[0 ],cpu_logical_map (0 ) % loongson_sysconf.cores_per_package); cpu_data[0 ].package =cpu_logical_map (0 ) / loongson_sysconf.cores_per_package;
Signature · 1 line
2.7.0
Re: [PATCH V2 09/12] MIPS: Loongson: Add kexec/kdump support
Quoted 1 line · Huacai Chen
Signed-off-by Huacai Chen <[email protected]>
Please add a commit message.
Worth Cc'ing kexec maintainers?
Quoted 12 lines
--- arch/mips/kernel/relocate_kernel.S | 30 +++++++++ arch/mips/loongson64/common/env.c | 8 +++ arch/mips/loongson64/common/reset.c | 119 ++++++++++++++++++++++++++++++++++ arch/mips/loongson64/loongson-3/smp.c | 4 ++ 4 files changed, 161 insertions(+)arch/mips/kernel/relocate_kernel.S +0
-0
arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 142
Quoted 8 lines
arch/mips/kernel/relocate_kernel.S +5
-0@@ -135,6 +135,36 @@ LEAF(kexec_smp_wait) #else sync #endif + +#ifdef CONFIG_CPU_LOONGSON3 + /* s0:prid s1:initfn */ + /* t0:base t1:cpuid t2:node t3:core t9:count */ + mfc0 t1, $15, 1
Can you use CP0_EBASE from mipsregs.h?
arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 143
Quoted 1 line
arch/mips/kernel/relocate_kernel.S +1
-0+ andi t1, 0x3ff
MIPS_EBASE_CPUNUM
arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 144
Quoted 1 line
arch/mips/kernel/relocate_kernel.S +1
-0+ dli t0, 0x900000003ff01000
Whats that?
arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 147
Quoted 3 lines
arch/mips/kernel/relocate_kernel.S +3
-0+ andi t3, t1, 0x3 + sll t3, 8 /* get core id */ + or t0, t0, t3
Do you have the INS instruction on loongson? Does it make sense to do this, even if only for readability?
dins t0, t1, 8, 2
arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 150
Quoted 3 lines
arch/mips/kernel/relocate_kernel.S +3
-0+ andi t2, t1, 0xc + dsll t2, 42 /* get node id */ + or t0, t0, t2
Does it make sense to do this, especially for readability (44 vs 42)?
dext t2, t1, 2, 2 dins t0, t2, 44, 2
arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 151
Quoted 1 line
arch/mips/kernel/relocate_kernel.S +1
-0+ mfc0 s0, $15, 0
CP0_PRID
arch/mips/kernel/relocate_kernel.S LEAF(kexec_smp_wait) · line 156
Quoted 6 lines
arch/mips/kernel/relocate_kernel.S +5
-0+ andi s0, s0, 0xf + blt s0, 0x6, 1f /* Loongson-3A1000 */ + bgt s0, 0x7, 1f /* Loongson-3A2000/3A3000 */ + dsrl t2, 30 /* Loongson-3B1000/3B1500 need bit15:14 */ + or t0, t0, t2
maybe:
dins t0, t2, 14, 2
Quoted 27 lines
arch/mips/kernel/relocate_kernel.S +11
-0+1: li t9, 0x100 /* wait for init loop */ +2: addiu t9, -1 /* limit mailbox access */ + bnez t9, 2b + ld s1, 0x20(t0) /* get PC via mailbox */ + beqz s1, 1b + ld sp, 0x28(t0) /* get SP via mailbox */ + ld gp, 0x30(t0) /* get GP via mailbox */ + ld a1, 0x38(t0) + jr s1 /* jump to initial PC */ +#endif + j s1 END(kexec_smp_wait)#endif
arch/mips/loongson64/common/env.c +1
-0@@ -72,6 +72,7 @@ void __init prom_init_env(void)pr_info ("memsize=%u, highmemsize=%u\n" , memsize, highmemsize);#else +int i;struct boot_params *boot_p;struct loongson_params *loongson_p;struct system_loongson *esys;
arch/mips/loongson64/common/env.c void __init prom_init_env(void) · line 156
Quoted 7 lines
arch/mips/loongson64/common/env.c +4
-0@@ -149,6 +150,13 @@ void __init prom_init_env(void) loongson_sysconf.nr_cpus = ecpu->nr_cpus; loongson_sysconf.boot_cpu_id = ecpu->cpu_startup_core_id; loongson_sysconf.reserved_cpus_mask = ecpu->reserved_cores_mask; +#ifdef CONFIG_KEXEC + loongson_sysconf.boot_cpu_id =get_ebase_cpunum (); +for (i =0 ; i < loongson_sysconf.boot_cpu_id; i++) + loongson_sysconf.reserved_cpus_mask |= (1 <<i);
maybe this?
loongson_sysconf.reserved_cpus_mask |= (1 << loongson_sysconf.boot_cpu_id) - 1;
Quoted 12 lines
arch/mips/loongson64/common/env.c +3
-0+pr_info ("Boot CPU ID is being fixed from %d to %d\n" , + ecpu->cpu_startup_core_id, loongson_sysconf.boot_cpu_id); +#endif if (ecpu->nr_cpus >NR_CPUS || ecpu->nr_cpus ==0 ) loongson_sysconf.nr_cpus =NR_CPUS ; loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +arch/mips/loongson64/common/reset.c +0
-0@@ -11,9 +11,14 @@*/
arch/mips/loongson64/common/reset.c line 21
Quoted 10 lines
arch/mips/loongson64/common/reset.c +5
-0#include <linux/init.h> #include <linux/pm.h> +#include <linux/cpu.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/kexec.h> #include <asm/idle.h> #include <asm/reboot.h> +#include <asm/bootinfo.h>
alphabetical ordering wherever possible please.
arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 93
Quoted 13 lines
arch/mips/loongson64/common/reset.c +6
-0#include <loongson.h> #include <boot_param.h> @@ -80,12 +85,126 @@ static void loongson_halt(void) } } +#ifdef CONFIG_KEXEC + +/* 0X80000000~0X80200000 is safe */ +#define MAX_ARGS 64 +#define KEXEC_CTRL_CODE 0XFFFFFFFF80100000UL +#define KEXEC_ARGV_ADDR 0XFFFFFFFF80108000UL
lower case 0x please.
arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 99
Quoted 6 lines
arch/mips/loongson64/common/reset.c +6
-0+#define KEXEC_ARGV_SIZE 3060 +#define KEXEC_ENVP_SIZE 4500 + +void *kexec_argv; +void *kexec_envp; +extern const size_t relocate_new_kernel_size;
A couple of other architectures have moved this declaration to asm/kexec.h.
arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 108
Quoted 9 lines
arch/mips/loongson64/common/reset.c +9
-0+ +static int loongson_kexec_prepare (struct kimage *image) +{ +int i, argc =0 ; +unsigned int *argv; +char *str, *ptr, *bootloader ="kexec" ; + +/* argv at offset 0, argv[] at offset KEXEC_ARGV_SIZE/2 */ + argv = (unsigned int *)kexec_argv;
the cast is redundant as kexec_argv is void *.
Quoted 38 lines
arch/mips/loongson64/common/reset.c +38
-0+ argv[argc++] = (unsigned int )(KEXEC_ARGV_ADDR +KEXEC_ARGV_SIZE /2 ); + +for (i =0 ; i < image->nr_segments; i++) { +if (!strncmp (bootloader, (char *)image->segment[i].buf, +strlen (bootloader))) { +/* +* convert command line string to array +* of parameters (as bootloader does). +*/ +int offt; +memcpy (kexec_argv +KEXEC_ARGV_SIZE /2 , image->segment[i].buf,KEXEC_ARGV_SIZE /2 ); + str = (char *)kexec_argv +KEXEC_ARGV_SIZE /2 ; + ptr =strchr (str,' ' ); + +while (ptr && (argc <MAX_ARGS )) { + *ptr ='\0' ; +if (ptr[1 ] !=' ' ) { + offt = (int )(ptr - str +1 ); + argv[argc] =KEXEC_ARGV_ADDR +KEXEC_ARGV_SIZE /2 + offt; + argc++; + } + ptr =strchr (ptr +1 ,' ' ); + } +break ; + } + } + + kexec_args[0 ] = argc; + kexec_args[1 ] = fw_arg1; + kexec_args[2 ] = fw_arg2; + image->control_code_page =virt_to_page ((void *)KEXEC_CTRL_CODE ); + +return 0 ; +} + +#ifdef CONFIG_SMP +static void kexec_smp_down (void *ignored) +{
arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 156
Quoted 10 lines
arch/mips/loongson64/common/reset.c +10
-0+int cpu =smp_processor_id (); + +local_irq_disable (); +set_cpu_online (cpu, false); +while (!atomic_read (&kexec_ready_to_reboot)) +cpu_relax (); + + asmvolatile ( +" sync \n" +" synci ($0) \n" );
The intermediate assembly looks nicer, and you'd get fewer checkpatch complaints, if you do something more like this:
asm volatile ("sync\n\t"
"synci ($0)");arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 169
Quoted 13 lines
arch/mips/loongson64/common/reset.c +13
-0+ + relocated_kexec_smp_wait(NULL); +} +#endif + +static void loongson_kexec_shutdown (void ) +{ +#ifdef CONFIG_SMP +int cpu; + +for_each_possible_cpu (cpu) +if (!cpu_online (cpu)) +cpu_up (cpu);/* Everyone should go to reboot_code_buffer */
long line
arch/mips/loongson64/common/reset.c static void loongson_halt(void) · line 172
Quoted 3 lines
arch/mips/loongson64/common/reset.c +3
-0+ +smp_call_function (kexec_smp_down,NULL ,0 ); +smp_wmb ();
This probably needs a comment to explain what smp_rmb() it pairs with, or what writes need a barrier between them and why. It certainly isn't clear from reading the code.
Quoted 14 lines
arch/mips/loongson64/common/reset.c +8
-0+while (num_online_cpus () >1 ) { +mdelay (1 ); +cpu_relax (); + } +#endif +memcpy ((void *)fw_arg1, kexec_argv,KEXEC_ARGV_SIZE ); +memcpy ((void *)fw_arg2, kexec_envp,KEXEC_ENVP_SIZE ); +}arch/mips/loongson64/loongson-3/smp.c +0
-0
arch/mips/loongson64/loongson-3/smp.c static void __init loongson3_smp_setup(void) · line 392
Quoted 6 lines
arch/mips/loongson64/loongson-3/smp.c +3
-0@@ -387,6 +387,10 @@ static void __init loongson3_smp_setup(void)ipi_status0_regs_init ();ipi_en0_regs_init ();ipi_mailbox_buf_init (); + +for (i =0 ; i < loongson_sysconf.nr_cpus; i++) +loongson3_ipi_write64 (0 , (void *)(ipi_mailbox_buf[i]+0x0 ));
what does that do? Please consider adding a comment.
Cheers
James
PATCH v2 10/12 MIPS: Loongson: Make CPUFreq usable for Loongson-3
In reply to Huacai ChenLoongson-3A/3B support frequency scaling. But due to hardware limitation, Loongson-3A's frequency scaling is not independent for each core, we suggest enable Loongson-3A's CPUFreq only when there is one core online. Loongson-3B can adjust frequency independently for each core, so it can be always enabled.
Each package has only one register (ChipConfig or FreqCtrl) to control frequency, so we need spinlocks to protect register access for multi- cores. However, we cannot use spinlock when a core becomes into "wait" status (frequency = 0), so we only enable "wait" when there is one core in a package online.
arch/mips/kernel/smp.c is modified to guarantee udelay_val has the correct value while both CPU hotplug and CPUFreq are enabled.
--- arch/mips/include/asm/mach-loongson64/loongson.h | 1 + arch/mips/kernel/smp.c | 3 +- arch/mips/loongson64/Kconfig | 1 + arch/mips/loongson64/common/platform.c | 13 +- arch/mips/loongson64/loongson-3/Makefile | 2 +- arch/mips/loongson64/loongson-3/clock.c | 191 ++++++++++++++++++ drivers/cpufreq/Kconfig | 13 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/loongson3_cpufreq.c | 236 +++++++++++++++++++++++ 9 files changed, 456 insertions(+), 5 deletions(-) create mode 100644 arch/mips/loongson64/loongson-3/clock.c create mode 100644 drivers/cpufreq/loongson3_cpufreq.c
arch/mips/include/asm/mach-loongson64/loongson.h +1 -0
@@ -277,6 +277,7 @@ extern u64 loongson_freqctrl[MAX_PACKAGES];#ifdef CONFIG_CPU_SUPPORTS_CPUFREQ #include <linux/cpufreq.h> extern struct cpufreq_frequency_table loongson2_clockmod_table[]; +extern struct cpufreq_frequency_table loongson3_clockmod_table[];#endif /*
arch/mips/kernel/smp.c +2 -1
@@ -370,7 +370,8 @@ asmlinkage void start_secondary(void)calibrate_delay ();preempt_disable (); cpu =smp_processor_id (); - cpu_data[cpu].udelay_val = loops_per_jiffy; +if (!cpu_data[cpu].udelay_val) + cpu_data[cpu].udelay_val = loops_per_jiffy;cpumask_set_cpu (cpu, &cpu_coherent_mask);notify_cpu_starting (cpu);
arch/mips/loongson64/Kconfig +1 -0
@@ -70,6 +70,7 @@ config LOONGSON_MACH3X select CSRC_R4K select CEVT_R4K select CPU_HAS_WB + select HAVE_CLK select HW_HAS_PCI select ISA select HT_PCI
arch/mips/loongson64/common/platform.c +10 -3
@@ -17,15 +17,22 @@ static struct platform_device loongson2_cpufreq_device = { .id = -1, }; -static int __init loongson2_cpufreq_init (void ) +static struct platform_device loongson3_cpufreq_device = { + .name ="loongson3_cpufreq" , + .id =-1 , +}; + +static int __init loongson_cpufreq_init (void ) {struct cpuinfo_mips *c = ¤t_cpu_data;/* Only 2F revision and it's successors support CPUFreq */ -if ((c->processor_id &PRID_REV_MASK ) >=PRID_REV_LOONGSON2F ) +if ((c->processor_id &PRID_REV_MASK ) ==PRID_REV_LOONGSON2F )return platform_device_register (&loongson2_cpufreq_device); +if ((c->processor_id &PRID_REV_MASK ) >=PRID_REV_LOONGSON3A_R1 ) +return platform_device_register (&loongson3_cpufreq_device);return -ENODEV ; } -arch_initcall (loongson2_cpufreq_init); +arch_initcall (loongson_cpufreq_init);
arch/mips/loongson64/loongson-3/Makefile +1 -1
@@ -1,7 +1,7 @@ # # Makefile for Loongson-3 family machines # -obj-y += irq.o cop2-ex.o platform.o acpi_init.o +obj-y += irq.o cop2-ex.o platform.o acpi_init.o clock.o obj-$(CONFIG_SMP) += smp.o
arch/mips/loongson64/loongson-3/clock.c new file +191 -0
191 lines not on this page · raw message
drivers/cpufreq/Kconfig +13 -0
@@ -286,6 +286,19 @@ config LOONGSON2_CPUFREQ If in doubt, say N. +config LOONGSON3_CPUFREQ + tristate "Loongson3 CPUFreq Driver" + depends on LOONGSON_MACH3X + help + This option adds a CPUFreq driver for loongson processors which + support software configurable cpu frequency. + + Loongson-3A and it's successors support this feature. + + For details, take a look at <file:Documentation/cpu-freq/>. + + If in doubt, say N. + config LOONGSON1_CPUFREQ tristate "Loongson1 CPUFreq Driver" depends on LOONGSON1_LS1B
drivers/cpufreq/Makefile +1 -0
@@ -106,6 +106,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o obj-$(CONFIG_ETRAXFS) += cris-etraxfs-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ) += ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o +obj-$(CONFIG_LOONGSON3_CPUFREQ) += loongson3_cpufreq.o obj-$(CONFIG_LOONGSON1_CPUFREQ) += loongson1-cpufreq.o obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o
drivers/cpufreq/loongson3_cpufreq.c new file +236 -0
236 lines not on this page · raw message
Signature · 1 line
2.7.0
PATCH v2 11/12 MIPS: Loongson-3: Fix CPU UART irq delivery problem
Masking/unmasking the CPU UART irq in CP0_Status (and redirecting it to other CPUs) may cause interrupts be lost, especially in multi-package machines (Package-0's UART irq cannot be delivered to others). So make mask_loongson_irq() and unmask_loongson_irq() be no-ops.
--- arch/mips/loongson64/loongson-3/irq.c | 41 ++--------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-)
arch/mips/loongson64/loongson-3/irq.c +2 -39
@@ -102,45 +102,8 @@ static struct irqaction cascade_irqaction = { .name = "cascade", }; -static inline void mask_loongson_irq (struct irq_data *d) -{ -clear_c0_status (0x100 << (d->irq -MIPS_CPU_IRQ_BASE )); -irq_disable_hazard (); - -/* Workaround: UART IRQ may deliver to any core */ -if (d->irq ==LOONGSON_UART_IRQ ) { -int cpu =smp_processor_id (); -int node_id =cpu_logical_map (cpu) / loongson_sysconf.cores_per_node; -int core_id =cpu_logical_map (cpu) % loongson_sysconf.cores_per_node; -u64 intenclr_addr = smp_group[node_id] | - (u64)(&LOONGSON_INT_ROUTER_INTENCLR ); -u64 introuter_lpc_addr = smp_group[node_id] | - (u64)(&LOONGSON_INT_ROUTER_LPC ); - - *(volatile u32 *)intenclr_addr =1 <<10 ; - *(volatile u8 *)introuter_lpc_addr =0x10 + (1 <<core_id); - } -} - -static inline void unmask_loongson_irq (struct irq_data *d) -{ -/* Workaround: UART IRQ may deliver to any core */ -if (d->irq ==LOONGSON_UART_IRQ ) { -int cpu =smp_processor_id (); -int node_id =cpu_logical_map (cpu) / loongson_sysconf.cores_per_node; -int core_id =cpu_logical_map (cpu) % loongson_sysconf.cores_per_node; -u64 intenset_addr = smp_group[node_id] | - (u64)(&LOONGSON_INT_ROUTER_INTENSET ); -u64 introuter_lpc_addr = smp_group[node_id] | - (u64)(&LOONGSON_INT_ROUTER_LPC ); - - *(volatile u32 *)intenset_addr =1 <<10 ; - *(volatile u8 *)introuter_lpc_addr =0x10 + (1 <<core_id); - } - -set_c0_status (0x100 << (d->irq -MIPS_CPU_IRQ_BASE )); -irq_enable_hazard (); -} +static inline void mask_loongson_irq (struct irq_data *d) { } +static inline void unmask_loongson_irq (struct irq_data *d) { }/* For MIPS IRQs which shared by all cores */ static struct irq_chip loongson_irq_chip = {
Signature · 1 line
2.7.0
Re: [PATCH V2 11/12] MIPS: Loongson-3: Fix CPU UART irq delivery problem
Quoted 6 lines · Huacai Chen
Masking/unmasking the CPU UART irq in
CP0_Status(and redirecting it to other CPUs) may cause interrupts be lost, especially in multi-package machines (Package-0's UART irq cannot be delivered to others). So makemask_loongson_irq()andunmask_loongson_irq()be no-ops.
...
arch/mips/loongson64/loongson-3/irq.c static struct irqaction cascade_irqaction = { · line 110
Quoted 6 lines
arch/mips/loongson64/loongson-3/irq.c +0
-6-static inline void mask_loongson_irq (struct irq_data *d) -{ -clear_c0_status (0x100 << (d->irq -MIPS_CPU_IRQ_BASE )); -irq_disable_hazard (); - -/* Workaround: UART IRQ may deliver to any core */
Wouldn't removing this self-described "workaround" bring back the original problem?
At the very least you need a much better explanation of why these workarounds are no longer applicable and can be safely removed.
Cheers
James
PATCH v2 12/12 MIPS: Loongson: Introduce and use WAR_LLSC_MB
In reply to Huacai ChenOn the Loongson-2G/2H/3A/3B there is a hardware flaw that ll/sc and lld/scd is very weak ordering. We should add sync instructions before each ll/lld and after the last sc/scd to workaround. Otherwise, this flaw will cause deadlock occationally (e.g. when doing heavy load test with LTP).
--- arch/mips/include/asm/atomic.h | 18 ++++++++++++++++-- arch/mips/include/asm/barrier.h | 6 ++++++ arch/mips/include/asm/bitops.h | 15 +++++++++++++++ arch/mips/include/asm/cmpxchg.h | 9 +++++++-- arch/mips/include/asm/edac.h | 5 ++++- arch/mips/include/asm/futex.h | 18 ++++++++++++------ arch/mips/include/asm/local.h | 10 ++++++++-- arch/mips/include/asm/pgtable.h | 5 ++++- arch/mips/kernel/syscall.c | 2 ++ arch/mips/loongson64/Platform | 3 +++ arch/mips/mm/tlbex.c | 11 +++++++++++ 11 files changed, 88 insertions(+), 14 deletions(-)
arch/mips/include/asm/atomic.h +16 -2
@@ -62,6 +62,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \ do { \ __asm__ __volatile__( \ " .set "MIPS_ISA_LEVEL" \n" \ + __WAR_LLSC_MB \ " ll %0, %1 # atomic_" #op "\n" \ " " #asm_op " %0, %2 \n" \ " sc %0, %1 \n" \
@@ -69,6 +70,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \ : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ : "Ir" (i)); \ }while (unlikely (!temp)); \ + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); \ }else { \unsigned long flags; \ \
@@ -103,6 +105,7 @@ static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v) \ do { \ __asm__ __volatile__( \ " .set "MIPS_ISA_LEVEL" \n" \ + __WAR_LLSC_MB \ " ll %1, %2 # atomic_" #op "_return \n" \ " " #asm_op " %0, %1, %3 \n" \ " sc %0, %2 \n" \
@@ -151,6 +154,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \ do { \ __asm__ __volatile__( \ " .set "MIPS_ISA_LEVEL" \n" \ + __WAR_LLSC_MB \ " ll %1, %2 # atomic_fetch_" #op " \n" \ " " #asm_op " %0, %1, %3 \n" \ " sc %0, %2 \n" \
@@ -159,6 +163,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \ "+" GCC_OFF_SMALL_ASM() (v->counter) \ : "Ir" (i)); \} while (unlikely(!result)); \ +__asm__ __volatile__(__WAR_LLSC_MB : : :" memory"); \ \ result = temp; \ } else { \
@@ -242,7 +247,9 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) __asm__ __volatile__(" .set " MIPS_ISA_LEVEL " \n" -"1: ll %1, %2 # atomic_sub_if_positive\n" +"1: # atomic_sub_if_positive \n" + __WAR_LLSC_MB +" ll %1, %2 \n" " subu %0, %1, %3 \n" " bltz %0, 1f \n" " sc %0, %2 \n"
@@ -404,6 +411,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v) \ do { \ __asm__ __volatile__( \ " .set "MIPS_ISA_LEVEL" \n" \ + __WAR_LLSC_MB \ " lld %0, %1 # atomic64_" #op "\n" \ " " #asm_op " %0, %2 \n" \ " scd %0, %1 \n" \
@@ -411,6 +419,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v) \ : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ : "Ir" (i)); \ }while (unlikely (!temp)); \ + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); \ }else { \unsigned long flags; \ \
@@ -445,6 +454,7 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \ do { \ __asm__ __volatile__( \ " .set "MIPS_ISA_LEVEL" \n" \ + __WAR_LLSC_MB \ " lld %1, %2 # atomic64_" #op "_return\n" \ " " #asm_op " %0, %1, %3 \n" \ " scd %0, %2 \n" \
@@ -494,6 +504,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \ do { \ __asm__ __volatile__( \ " .set "MIPS_ISA_LEVEL" \n" \ + __WAR_LLSC_MB \ " lld %1, %2 # atomic64_fetch_" #op "\n" \ " " #asm_op " %0, %1, %3 \n" \ " scd %0, %2 \n" \
@@ -503,6 +514,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \ : "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter) \ : "memory"); \ }while (unlikely (!result)); \ + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); \ \ result = temp; \ }else { \
@@ -587,7 +599,9 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) __asm__ __volatile__(" .set " MIPS_ISA_LEVEL " \n" -"1: lld %1, %2 # atomic64_sub_if_positive\n" +"1: # atomic64_sub_if_positive \n" + __WAR_LLSC_MB +" lld %1, %2 \n" " dsubu %0, %1, %3 \n" " bltz %0, 1f \n" " scd %0, %2 \n"
arch/mips/include/asm/barrier.h +6 -0
@@ -203,6 +203,12 @@#define __WEAK_LLSC_MB " \n"#endif +#if defined(CONFIG_LOONGSON3 ) && defined(CONFIG_SMP )/* Loongson-3's LLSC workaround */ +#define __WAR_LLSC_MB " sync \n" +#else +#define __WAR_LLSC_MB " \n" +#endif +#define smp_llsc_mb () __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")#ifdef CONFIG_CPU_CAVIUM_OCTEON
arch/mips/include/asm/bitops.h +15 -0
@@ -70,17 +70,20 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {do { __asm__ __volatile__( + __WAR_LLSC_MB" " __LL"%0, %1 # set_bit \n" " " __INS"%0, %3, %2, 1 \n" " " __SC"%0, %1 \n" : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m) :"ir" (bit),"r" (~0 )); }while (unlikely (!temp)); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory");#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */ }else if (kernel_uses_llsc) { do { __asm__ __volatile__( " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # set_bit \n" " or %0, %2 \n" " " __SC "%0, %1 \n"
@@ -88,6 +91,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m) : "ir" (1UL << bit)); }while (unlikely (!temp)); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); }else __mips_set_bit (nr, addr); }
@@ -122,17 +126,20 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {do { __asm__ __volatile__( + __WAR_LLSC_MB" " __LL"%0, %1 # clear_bit \n" " " __INS"%0, $0, %2, 1 \n" " " __SC"%0, %1 \n" : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m) :"ir" (bit)); }while (unlikely (!temp)); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory");#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */ }else if (kernel_uses_llsc) { do { __asm__ __volatile__( " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # clear_bit \n" " and %0, %2 \n" " " __SC "%0, %1 \n"
@@ -140,6 +147,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m) : "ir" (~(1UL << bit))); }while (unlikely (!temp)); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); }else __mips_clear_bit (nr, addr); }
@@ -191,6 +199,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) do { __asm__ __volatile__( " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # change_bit \n" " xor %0, %2 \n" " " __SC "%0, %1 \n"
@@ -198,6 +207,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m) : "ir" (1UL << bit)); }while (unlikely (!temp)); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); }else __mips_change_bit (nr, addr); }
@@ -240,6 +250,7 @@ static inline int test_and_set_bit(unsigned long nr, do { __asm__ __volatile__( " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # test_and_set_bit \n" " or %2, %0, %3 \n" " " __SC "%2, %1 \n"
@@ -294,6 +305,7 @@ static inline int test_and_set_bit_lock(unsigned long nr, do { __asm__ __volatile__( " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # test_and_set_bit \n" " or %2, %0, %3 \n" " " __SC "%2, %1 \n"
@@ -350,6 +362,7 @@ static inline int test_and_clear_bit(unsigned long nr, do { __asm__ __volatile__( + __WAR_LLSC_MB " " __LL "%0, %1 # test_and_clear_bit \n" " " __EXT "%2, %0, %3, 1 \n" " " __INS "%0, $0, %3, 1 \n"
@@ -366,6 +379,7 @@ static inline int test_and_clear_bit(unsigned long nr, do { __asm__ __volatile__( " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # test_and_clear_bit \n" " or %2, %0, %3 \n" " xor %2, %3 \n"
@@ -423,6 +437,7 @@ static inline int test_and_change_bit(unsigned long nr, do { __asm__ __volatile__( " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # test_and_change_bit \n" " xor %2, %0, %3 \n" " " __SC "\t%2, %1 \n"
arch/mips/include/asm/cmpxchg.h +7 -2
@@ -48,7 +48,9 @@ extern unsigned long __xchg_called_with_bad_pointer(void)" .set push \n" \" .set noat \n" \" .set " MIPS_ISA_ARCH_LEVEL " \n" \ -"1: " ld" %0, %2 # __xchg_asm \n" \ +"1: # __xchg_asm \n" \ + __WAR_LLSC_MB \ +" " ld" %0, %2 \n" \" .set mips0 \n" \" move $1, %z3 \n" \" .set " MIPS_ISA_ARCH_LEVEL " \n" \
@@ -118,7 +120,9 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x," .set push \n" \" .set noat \n" \" .set " MIPS_ISA_ARCH_LEVEL " \n" \ -"1: " ld" %0, %2 # __cmpxchg_asm \n" \ +"1: # __cmpxchg_asm \n" \ + __WAR_LLSC_MB \ +" " ld" %0, %2 \n" \" bne %0, %z3, 2f \n" \" .set mips0 \n" \" move $1, %z4 \n" \
@@ -127,6 +131,7 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x,"\t" __scbeqz" $1, 1b \n" \" .set pop \n" \"2: \n" \ + __WAR_LLSC_MB \ : "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m) \: GCC_OFF_SMALL_ASM() (*m), " Jr" (old), " Jr" (new) \ : "memory"); \
arch/mips/include/asm/edac.h +4 -1
@@ -22,13 +22,16 @@ static inline void edac_atomic_scrub(void *va, u32 size) __asm__ __volatile__ (" .set mips2 \n" -"1: ll %0, %1 # edac_atomic_scrub \n" +"1: # edac_atomic_scrub \n" + __WAR_LLSC_MB +" ll %0, %1 \n" " addu %0, $0 \n" " sc %0, %1 \n" " beqz %0, 1b \n" " .set mips0 \n" : "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*virt_addr) : GCC_OFF_SMALL_ASM() (*virt_addr)); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); virt_addr++; }
arch/mips/include/asm/futex.h +12 -6
@@ -54,7 +54,9 @@" .set push \n" \" .set noat \n" \" .set " MIPS_ISA_ARCH_LEVEL " \n" \ - "1: "user_ll("%1", "%4")" # __futex_atomic_op\n" \ +"1: # __futex_atomic_op\n" \ + __WAR_LLSC_MB \ + " "user_ll("%1", "%4")" \n" \" .set mips0 \n" \" " insn" \n" \" .set " MIPS_ISA_ARCH_LEVEL " \n" \
@@ -70,8 +72,9 @@" j 3b \n" \" .previous \n" \" .section __ex_table,\"a\" \n" \ -" " __UA_ADDR"\t1b, 4b \n" \ -" " __UA_ADDR"\t2b, 4b \n" \ +" " __UA_ADDR"\t(1b + 0), 4b \n" \ +" " __UA_ADDR"\t(1b + 4), 4b \n" \ +" " __UA_ADDR"\t(2b + 0), 4b \n" \" .previous \n" \ : "=r" (ret), "=&r" (oldval), \"=" GCC_OFF_SMALL_ASM () (*uaddr) \
@@ -167,7 +170,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr," .set push \n" " .set noat \n" " .set " MIPS_ISA_ARCH_LEVEL " \n" - "1: "user_ll("%1", "%3")" \n" +"1: \n" + __WAR_LLSC_MB + " "user_ll("%1", "%3")" \n"" bne %1, %z4, 3f \n" " .set mips0 \n" " move $1, %z5 \n"
@@ -183,8 +188,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr," j 3b \n" " .previous \n" " .section __ex_table,\"a\" \n" -" " __UA_ADDR"\t1b, 4b \n" -" " __UA_ADDR"\t2b, 4b \n" +" " __UA_ADDR"\t(1b + 0), 4b \n" +" " __UA_ADDR"\t(1b + 4), 4b \n" +" " __UA_ADDR"\t(2b + 0), 4b \n" " .previous \n" : "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr) : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
arch/mips/include/asm/local.h +8 -2
@@ -50,7 +50,9 @@ static __inline__ long local_add_return(long i, local_t * l) __asm__ __volatile__(" .set " MIPS_ISA_ARCH_LEVEL " \n" -"1:" __LL"%1, %2 # local_add_return \n" +"1: # local_add_return \n" + __WAR_LLSC_MB + __LL"%1, %2 \n" " addu %0, %1, %3 \n" __SC"%0, %2 \n" " beqz %0, 1b \n"
@@ -59,6 +61,7 @@ static __inline__ long local_add_return(long i, local_t * l) : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) : "Ir" (i), "m" (l->a.counter) : "memory"); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); }else {unsigned long flags;
@@ -95,7 +98,9 @@ static __inline__ long local_sub_return(long i, local_t * l) __asm__ __volatile__(" .set " MIPS_ISA_ARCH_LEVEL " \n" -"1:" __LL"%1, %2 # local_sub_return \n" +"1: # local_sub_return \n" + __WAR_LLSC_MB + __LL"%1, %2 \n" " subu %0, %1, %3 \n" __SC"%0, %2 \n" " beqz %0, 1b \n"
@@ -104,6 +109,7 @@ static __inline__ long local_sub_return(long i, local_t * l) : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) : "Ir" (i), "m" (l->a.counter) : "memory"); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); }else {unsigned long flags;
arch/mips/include/asm/pgtable.h +4 -1
@@ -233,7 +233,9 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)" .set " MIPS_ISA_ARCH_LEVEL " \n" " .set push \n" " .set noreorder \n" -"1:" __LL"%[tmp], %[buddy] \n" +"1: \n" + __WAR_LLSC_MB + __LL"%[tmp], %[buddy] \n" " bnez %[tmp], 2f \n" " or %[tmp], %[tmp], %[global] \n" __SC"%[tmp], %[buddy] \n"
@@ -244,6 +246,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)" .set mips0 \n" : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp) : [global] "r" (page_global)); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); }#else /* !CONFIG_SMP */ if (pte_none (*buddy))
arch/mips/kernel/syscall.c +2 -0
@@ -133,6 +133,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)" .set " MIPS_ISA_ARCH_LEVEL " \n" " li %[err], 0 \n" "1: \n" + __WAR_LLSC_MB user_ll("%[old]", "(%[addr])")" move %[tmp], %[new] \n" "2: \n"
@@ -156,6 +157,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) [new] "r" (new), [efault] "i" (-EFAULT) : "memory"); + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); }else { do { preempt_disable();
arch/mips/loongson64/Platform +3 -0
@@ -23,6 +23,9 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS endif cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap +ifneq ($(call as-option,-Wa$(comma)-mfix-loongson3-llsc,),) + cflags-$(CONFIG_CPU_LOONGSON3) += -Wa$(comma)-mno-fix-loongson3-llsc +endif # # binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a # as MIPS64 R2; older versions as just R1. This leaves the possibility open
arch/mips/mm/tlbex.c +11 -0
@@ -919,6 +919,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,* to mimic that here by taking a load/istream page * fault. */ +if (current_cpu_type () ==CPU_LOONGSON3 ) +uasm_i_sync (p,0 );UASM_i_LA (p, ptr, (unsigned long )tlb_do_page_fault_0);uasm_i_jr (p, ptr);
@@ -1545,6 +1547,7 @@ static void build_loongson3_tlb_refill_handler(void)if (check_for_high_segbits) {uasm_l_large_segbits_fault (&l, p); +uasm_i_sync (&p,0 );UASM_i_LA (&p,K1 , (unsigned long )tlb_do_page_fault_0);uasm_i_jr (&p,K1 );uasm_i_nop (&p);
@@ -1645,6 +1648,8 @@ static void iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) {#ifdef CONFIG_SMP +if (current_cpu_type () ==CPU_LOONGSON3 ) +uasm_i_sync (p,0 );# ifdef CONFIG_PHYS_ADDR_T_64BIT if (cpu_has_64bits)uasm_i_lld (p, pte,0 , ptr);
@@ -2262,6 +2267,8 @@ static void build_r4000_tlb_load_handler(void)#endif uasm_l_nopage_tlbl (&l, p); +if (current_cpu_type () ==CPU_LOONGSON3 ) +uasm_i_sync (&p,0 );build_restore_work_registers (&p);#ifdef CONFIG_CPU_MICROMIPS if ((unsigned long )tlb_do_page_fault_0 &1 ) {
@@ -2317,6 +2324,8 @@ static void build_r4000_tlb_store_handler(void)#endif uasm_l_nopage_tlbs (&l, p); +if (current_cpu_type () ==CPU_LOONGSON3 ) +uasm_i_sync (&p,0 );build_restore_work_registers (&p);#ifdef CONFIG_CPU_MICROMIPS if ((unsigned long )tlb_do_page_fault_1 &1 ) {
@@ -2373,6 +2382,8 @@ static void build_r4000_tlb_modify_handler(void)#endif uasm_l_nopage_tlbm (&l, p); +if (current_cpu_type () ==CPU_LOONGSON3 ) +uasm_i_sync (&p,0 );build_restore_work_registers (&p);#ifdef CONFIG_CPU_MICROMIPS if ((unsigned long )tlb_do_page_fault_1 &1 ) {
Signature · 1 line
2.7.0
Re: [PATCH V2 12/12] MIPS: Loongson: Introduce and use WAR_LLSC_MB
Quoted 5 lines · Huacai Chen
On the Loongson-2G/2H/3A/3B there is a hardware flaw that ll/sc and lld/scd is very weak ordering. We should add sync instructions before each ll/lld and after the last sc/scd to workaround. Otherwise, this flaw will cause deadlock occationally (e.g. when doing heavy load test with LTP).
How confident are you that this is the minimal change required to fix the issue? Is the problem well understood?
It'd be helpful to have some more details about the flaw if you have them.
I.e. does it really have to be done on every loop iteration (such that using WEAK_REORDERING_BEYOND_LLSC is insufficient)?
Quoted 13 lines
arch/mips/include/asm/atomic.h +1
-0@@ -62,6 +62,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \ do { \ __asm__ __volatile__( \ " .set "MIPS_ISA_LEVEL" \n" \ + __WAR_LLSC_MB \ " ll %0, %1 # atomic_" #op "\n" \ " " #asm_op " %0, %2 \n" \ " sc %0, %1 \n" \
arch/mips/include/asm/atomic.h static __inline__ void atomic_##op(int i, atomic_t * v) \ · line 73
Quoted 4 lines
arch/mips/include/asm/atomic.h +1
-0@@ -69,6 +70,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \ : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ : "Ir" (i)); \ }while (unlikely (!temp)); \ + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); \
This still results in an additional compiler barrier on other platforms, so if it must remain it needs abstracting.
arch/mips/include/asm/barrier.h line 210
Quoted 13 lines
arch/mips/include/asm/barrier.h +5
-0@@ -203,6 +203,12 @@#define __WEAK_LLSC_MB " \n"#endif +#if defined(CONFIG_LOONGSON3 ) && defined(CONFIG_SMP )/* Loongson-3's LLSC workaround */ +#define __WAR_LLSC_MB " sync \n" +#else +#define __WAR_LLSC_MB " \n" +#endif
A comment explaining the whole issue would be helpful for others trying to decipher this.
arch/mips/loongson64/Platform ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS · line 28
Quoted 11 lines
arch/mips/loongson64/Platform +3
-0@@ -23,6 +23,9 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS endif cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap +ifneq ($(call as-option,-Wa$(comma)-mfix-loongson3-llsc,),) + cflags-$(CONFIG_CPU_LOONGSON3) += -Wa$(comma)-mno-fix-loongson3-llsc +endif
Could this be a separate patch?
This needs more explanation.
- What does this do exactly?
- Why are you turning *OFF* the compiler fix?
- Was some fix we don't want already in use by default?
arch/mips/mm/tlbex.c build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, · line 923
Quoted 10 lines
arch/mips/mm/tlbex.c +2
-0@@ -919,6 +919,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,* to mimic that here by taking a load/istream page * fault. */ +if (current_cpu_type () ==CPU_LOONGSON3 ) +uasm_i_sync (p,0 );
I suggest abstracting this out with a nice comment explaining why it is necessary.
Cheers
James
Re: [PATCH V2 12/12] MIPS: Loongson: Introduce and use WAR_LLSC_MB
Quoted 14 lines · James Hogan
arch/mips/loongson64/Platform ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS · line 28
Quoted 11 lines
arch/mips/loongson64/Platform +3
-0@@ -23,6 +23,9 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS endif cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap +ifneq ($(call as-option,-Wa$(comma)-mfix-loongson3-llsc,),) + cflags-$(CONFIG_CPU_LOONGSON3) += -Wa$(comma)-mno-fix-loongson3-llsc +endifCould this be a separate patch?
Quoted 4 lines
This needs more explanation.
- What does this do exactly?
- Why are you turning *OFF* the compiler fix?
- Was some fix we don't want already in use by default?
FYI, support for `-mfix-loongson3-llsc' in GAS has only recently been
proposed: <https://sourceware.org/ml/binutils/2018-01/msg00303.html> and is still pending review.
Maciej
Re: [PATCH V2 12/12] MIPS: Loongson: Introduce and use WAR_LLSC_MB
Quoted 16 lines · Maciej W. Rozycki
Quoted 14 lines · James Hogan
arch/mips/loongson64/Platform ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS · line 28
Quoted 11 lines
arch/mips/loongson64/Platform +3
-0@@ -23,6 +23,9 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS endif cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap +ifneq ($(call as-option,-Wa$(comma)-mfix-loongson3-llsc,),) + cflags-$(CONFIG_CPU_LOONGSON3) += -Wa$(comma)-mno-fix-loongson3-llsc +endifCould this be a separate patch?
Quoted 8 lines
Quoted 4 lines
This needs more explanation.
- What does this do exactly?
- Why are you turning *OFF* the compiler fix?
- Was some fix we don't want already in use by default?FYI, support for `-mfix-loongson3-llsc' in GAS has only recently been
proposed: <https://sourceware.org/ml/binutils/2018-01/msg00303.html> and is still pending review.
Thanks for that link Maciej. GNU changelogs are useless, so this is the interesting bit:
Review
Quoted 5 lines
+@item -mfix-loongson3-llsc
+@itemx -mno-fix-loongson3-llsc(quoted diff) +3
-0+Insert @code{sync} instruction before @samp{ll} or @samp{lld} instrction +to work around Loongson3 @samp{LL}/@samp{SC} errata. +This issue exists in all Loongson3 CPUs.
Cheers
James
Re: [PATCH V2 10/12] MIPS: Loongson: Make CPUFreq usable for Loongson-3
In reply to Huacai ChenQuoted 4 lines · Huacai Chen
Loongson-3A/3B support frequency scaling. But due to hardware limitation, Loongson-3A's frequency scaling is not independent for each core, we suggest enable Loongson-3A's CPUFreq only when there is one core online.
Does the code do anything to enforce that?
If not, should it?
Will it just work suboptimally if you tried?
Quoted 9 lines
arch/mips/include/asm/mach-loongson64/loongson.h | 1 + arch/mips/kernel/smp.c | 3 +- arch/mips/loongson64/Kconfig | 1 + arch/mips/loongson64/common/platform.c | 13 +- arch/mips/loongson64/loongson-3/Makefile | 2 +- arch/mips/loongson64/loongson-3/clock.c | 191 ++++++++++++++++++ drivers/cpufreq/Kconfig | 13 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/loongson3_cpufreq.c | 236 +++++++++++++++++++++++
This could presumably be fairly neatly divided into 3 separate changes:
- New clocks driver
- New cpufreq driver
- Minimal platform changes in arch/mips to instantiate the drivers
Please can you use the common clock framework i.e. a driver in drivers/clk/, rather than adding yet another implementation of the clk api in arch/mips/.
Each change needs the appropriate maintainers on Cc or you'll never get the required review.
Cheers
James
Quoted 7 lines · Huacai Chen
This patchset is prepared for the next 4.16 release for Linux/MIPS. It add Loongson-3A R3.1 support, enable Loongson-3's SFB at runtime, adds "model name" and "CPU MHz" knobs in
/proc/cpuinfowhich is needed by some userspace tools, adds Loongson-3 kexec/kdump and CPUFreq support, fixes CPU UART irq delivery problem, and introducesWAR_LLSC_MBto improve stability.
Quoted 5 lines
V1 -> V2:
1, Add Loongson-3A R3.1 basic support.
2, Fix CPU UART irq delivery problem.
3, Improve code and descriptions (Thank James Hogan). 4, Sync the code to upstream.
I few general suggestions that I hope will help you to get your patches applied quicker:
- Please have a separate series for each group of related changes in future. It makes them more manageable, makes dependencies clearer, and avoids unchanged resends of unrelated patches when you respin the whole series. Series are mainly to group tightly related patches, or because of dependencies of later patches on earlier ones (and even if you have a series of 30 dependent patches, you can still sometimes split it into groups and mention in the cover letters which other pending series each series depends on).
- More importantly, avoid moving patches between series or adding unrelated patches to a series if possible (so probably best not to split this series now). It makes it harder to see what has changed, whether past feedback has been addressed, and whether new/removed patches are new/abandoned or simply moved from/to a different series.
- Please don't resend a series without changes, ping it if you are concerned. It clutters patchwork for no good reason and makes it harder to see if past feedback has been addressed.
- Please run checkpatch on all patches before submission, and fix any reasonable warnings and errors (i.e. there are various lines exceeding 80 characters in this series which should be split, but some are acceptable where its to keep a string together).
- Please include Fixes tags where appropriate, especially where you've Cc'd stable.
- If you Cc stable, please state how far back it should be backported wherever possible,
E.g. Cc: <[email protected]> # 4.14+
This may help finding what version a commit is first included in:
https://www.linux-mips.org/archives/linux-mips/2017-07/msg00149.html
- Please run get_maintainer.pl on each patch to make sure you cc the appropriate maintainers and lists (and Cc them on the cover letter too). Its fine to skip LKML for lots of MIPS patches, but don't miss out the appropriate subsystem maintainers and lists for patches touching drivers/ or they'll never get acked and never get applied.
- Split arch/mips/ and drivers/ patches wherever possible.
Cheers
James
Hi, James,
I really don't want send many patches in a seris. But in practise, my single patch in linux-mips usually be ignored (even they are very simple and well described)....
For example:
https://patchwork.linux-mips.org/patch/17723/
https://patchwork.linux-mips.org/patch/18587/
https://patchwork.linux-mips.org/patch/18682/
Anyway, thank you for your susggestions, I will rework other patches.
Huacai
Quoted 60 lines · James Hogan
Quoted 7 lines · Huacai Chen
This patchset is prepared for the next 4.16 release for Linux/MIPS. It add Loongson-3A R3.1 support, enable Loongson-3's SFB at runtime, adds "model name" and "CPU MHz" knobs in
/proc/cpuinfowhich is needed by some userspace tools, adds Loongson-3 kexec/kdump and CPUFreq support, fixes CPU UART irq delivery problem, and introducesWAR_LLSC_MBto improve stability.Quoted 5 lines
V1 -> V2:
1, Add Loongson-3A R3.1 basic support.
2, Fix CPU UART irq delivery problem.
3, Improve code and descriptions (Thank James Hogan). 4, Sync the code to upstream.I few general suggestions that I hope will help you to get your patches applied quicker:
- Please have a separate series for each group of related changes in future. It makes them more manageable, makes dependencies clearer, and avoids unchanged resends of unrelated patches when you respin the whole series. Series are mainly to group tightly related patches, or because of dependencies of later patches on earlier ones (and even if you have a series of 30 dependent patches, you can still sometimes split it into groups and mention in the cover letters which other pending series each series depends on).
- More importantly, avoid moving patches between series or adding unrelated patches to a series if possible (so probably best not to split this series now). It makes it harder to see what has changed, whether past feedback has been addressed, and whether new/removed patches are new/abandoned or simply moved from/to a different series.
- Please don't resend a series without changes, ping it if you are concerned. It clutters patchwork for no good reason and makes it harder to see if past feedback has been addressed.
- Please run checkpatch on all patches before submission, and fix any reasonable warnings and errors (i.e. there are various lines exceeding 80 characters in this series which should be split, but some are acceptable where its to keep a string together).
- Please include Fixes tags where appropriate, especially where you've Cc'd stable.
- If you Cc stable, please state how far back it should be backported wherever possible,
E.g. Cc: <[email protected]> # 4.14+
This may help finding what version a commit is first included in:
https://www.linux-mips.org/archives/linux-mips/2017-07/msg00149.html- Please run get_maintainer.pl on each patch to make sure you cc the appropriate maintainers and lists (and Cc them on the cover letter too). Its fine to skip LKML for lots of MIPS patches, but don't miss out the appropriate subsystem maintainers and lists for patches touching
drivers/or they'll never get acked and never get applied.- Split
arch/mips/anddrivers/patches wherever possible.Cheers
James
Quoted 5 lines · Huacai Chen
Hi, James,
I really don't want send many patches in a seris. But in practise, my single patch in linux-mips usually be ignored (even they are very simple and well described)....
Then please feel free to reply to the patch and ask if anybody has feedback, stating how important the patch is for you, so it can be prioritised. Resends as part of other series just adds to the noise.
Quoted 3 lines
For example:
https://patchwork.linux-mips.org/patch/17723/
Yes, that one needs a proper look.
Quoted 1 line
This one apparently knowingly breaks the feature on other platforms, so can't really be applied as is. I think Matt Redfearn & I were thinking his single IPI stuff could potentially be helpful there too.
Quoted 1 line
You sent that this morning so its hardly had time to be ignored, and I had already spotted it on my phone and intended to apply it today. Also I disagree that "Commit x breaks Loongson64 platforms, so fix it" counts as well described, even if it is simple, and obvious (to me at least) what you're talking about.
E.g. a better description would along the lines of:
Commit 7a407aa5e0d3 ("MIPS: Push ARCH_MIGHT_HAVE_PC_SERIO down to platform level") moves the global MIPS ARCH_MIGHT_HAVE_PC_SERIO select down to various platforms, but doesn't add it to Loongson64 platforms which need it, so add the selects to these platforms too.
Quoted 2 lines
Anyway, thank you for your susggestions, I will rework other patches.
Thank you.
Cheers
James
Quoted 15 lines · James Hogan
Quoted 5 lines · Huacai Chen
Hi, James,
I really don't want send many patches in a seris. But in practise, my single patch in linux-mips usually be ignored (even they are very simple and well described)....
Then please feel free to reply to the patch and ask if anybody has feedback, stating how important the patch is for you, so it can be prioritised. Resends as part of other series just adds to the noise.
Quoted 3 lines
For example:
https://patchwork.linux-mips.org/patch/17723/
Quoted 7 lines
Yes, that one needs a proper look.
Quoted 1 line
This one apparently knowingly breaks the feature on other platforms, so can't really be applied as is. I think Matt Redfearn & I were thinking his single IPI stuff could potentially be helpful there too.
I think this does't break other platforms, because:
1, arch_trigger_cpumask_backtrace() will not be called in normal cases; 2, If arch_trigger_cpumask_backtrace() really be called, the old code also doesn't work (deadlock).
Quoted 9 lines
Quoted 2 lines
You sent that this morning so its hardly had time to be ignored, and I had already spotted it on my phone and intended to apply it today. Also I disagree that "Commit x breaks Loongson64 platforms, so fix it" counts as well described, even if it is simple, and obvious (to me at least) what you're talking about.
Quoted 6 lines
E.g. a better description would along the lines of:
Commit
7a407aa5e0d3("MIPS: PushARCH_MIGHT_HAVE_PC_SERIOdown to platform level") moves the global MIPSARCH_MIGHT_HAVE_PC_SERIOselect down to various platforms, but doesn't add it to Loongson64 platforms which need it, so add the selects to these platforms too.
I'll update my commit messages.
Quoted 8 lines
Quoted 3 lines
Anyway, thank you for your susggestions, I will rework other patches.
Thank you.
Cheers
James