MIPS: Loongson: new features and improvements
Subsystems (6)
v5 cover MIPS: Loongson: new features and improvements
This patchset is prepared for the next 4.21 release for Linux/MIPS. It add Loongson-3A R2.1 basic support, adds "model name" and "CPU MHz" knobs in /proc/cpuinfo which is needed by some userspace tools, adds Loongson-3 kexec/kdump support, 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.
V2 -> V3:
1, Remove merged patches.
2, Improve code and descriptions (Thank James Hogan). 3, Sync the code to upstream.
V3 -> V4:
1, Remove merged patches.
2, Improve kdump support.
3, Sync the code to upstream.
V4 -> V5:
1, Remove merged patches.
2, Add Loongson-3A R2.1 support.
3, Improve kexec/kdump support.
4, Sync the code to upstream.
Huacai Chen(8):
MIPS: Loongson: Add Loongson-3A R2.1 basic support.
MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3.
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: Reserve extra memory for crash dump.
MIPS: Loongson: Add kexec/kdump support.
MIPS: Loongson: Introduce and use WAR_LLSC_MB.
--- arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 7 +- arch/mips/include/asm/atomic.h | 36 ++++++-- 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 | 3 +- 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/mach-loongson64/boot_param.h | 1 + .../asm/mach-loongson64/kernel-entry-init.h | 4 +- arch/mips/include/asm/mach-loongson64/mmzone.h | 1 + arch/mips/include/asm/mmzone.h | 8 ++ arch/mips/include/asm/pgtable-64.h | 5 ++ arch/mips/include/asm/pgtable.h | 5 +- arch/mips/include/asm/r4kcache.h | 21 +++++ arch/mips/include/asm/time.h | 2 + arch/mips/kernel/cpu-probe.c | 28 +++++-- arch/mips/kernel/idle.c | 2 +- arch/mips/kernel/proc.c | 6 ++ arch/mips/kernel/relocate_kernel.S | 26 ++++++ arch/mips/kernel/setup.c | 51 ++++++++++++ arch/mips/kernel/syscall.c | 2 + arch/mips/kernel/time.c | 2 + arch/mips/loongson64/Platform | 3 + arch/mips/loongson64/common/env.c | 23 +++++- arch/mips/loongson64/common/reset.c | 95 ++++++++++++++++++++++ arch/mips/loongson64/loongson-3/smp.c | 9 +- arch/mips/loongson64/loongson-3/smp.h | 1 + arch/mips/mm/c-r4k.c | 46 +++++++++-- arch/mips/mm/tlbex.c | 11 +++ drivers/platform/mips/cpu_hwmon.c | 3 +- 33 files changed, 421 insertions(+), 45 deletions(-)
--
2.7.0
PATCH v5 1/8 MIPS: Loongson: Add Loongson-3A R2.1 basic support
Loongson-3A R2.1 is the bugfix revision of Loongson-3A R2.
All Loongson-3 CPU family:
Code-name Brand-name PRId Loongson-3A R1 Loongson-3A1000 0x6305 Loongson-3A R2 Loongson-3A2000 0x6308 Loongson-3A R2.1 Loongson-3A2000 0x630c 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 | 3 ++- arch/mips/include/asm/mach-loongson64/kernel-entry-init.h | 4 ++-- arch/mips/kernel/cpu-probe.c | 3 ++- arch/mips/kernel/idle.c | 2 +- arch/mips/loongson64/common/env.c | 3 ++- arch/mips/loongson64/loongson-3/smp.c | 3 ++- arch/mips/mm/c-r4k.c | 2 +- drivers/platform/mips/cpu_hwmon.c | 3 ++- 8 files changed, 14 insertions(+), 9 deletions(-)
arch/mips/include/asm/cpu.h +2 -1
@@ -248,8 +248,9 @@#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_R2_0 0x0008#define PRID_REV_LOONGSON3A_R3_0 0x0009 +#define PRID_REV_LOONGSON3A_R2_1 0x000c#define PRID_REV_LOONGSON3A_R3_1 0x000d/*
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +2 -2
@@ -31,7 +31,7 @@/* Enable STFill Buffer */ mfc0 t0,CP0_PRID andi t0, (PRID_IMP_MASK | PRID_REV_MASK) - slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2) + slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0) bnez t0, 1f mfc0 t0, CP0_CONFIG6 or t0, 0x100
@@ -60,7 +60,7 @@/* Enable STFill Buffer */ mfc0 t0,CP0_PRID andi t0, (PRID_IMP_MASK | PRID_REV_MASK) - slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2) + slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0) bnez t0, 1f mfc0 t0, CP0_CONFIG6 or t0, 0x100
arch/mips/kernel/cpu-probe.c +2 -1
@@ -1871,7 +1871,8 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)switch (c->processor_id &PRID_IMP_MASK ) {case PRID_IMP_LOONGSON_64 :/* Loongson-2/3 */ switch (c->processor_id &PRID_REV_MASK ) { -case PRID_REV_LOONGSON3A_R2 : +case PRID_REV_LOONGSON3A_R2_0 : +case PRID_REV_LOONGSON3A_R2_1 : c->cputype =CPU_LOONGSON3 ; __cpu_name[cpu] ="ICT Loongson-3" ;set_elf_platform (cpu,"loongson3a" );
arch/mips/kernel/idle.c +1 -1
@@ -184,7 +184,7 @@ void __init check_wait(void) cpu_wait = r4k_wait;break ;case CPU_LOONGSON3 : -if ((c->processor_id &PRID_REV_MASK ) >=PRID_REV_LOONGSON3A_R2 ) +if ((c->processor_id &PRID_REV_MASK ) >=PRID_REV_LOONGSON3A_R2_0 ) cpu_wait = r4k_wait;break ;
arch/mips/loongson64/common/env.c +2 -1
@@ -197,7 +197,8 @@ void __init prom_init_env(void) cpu_clock_freq =797000000 ;break ;case PRID_REV_LOONGSON3A_R1 : -case PRID_REV_LOONGSON3A_R2 : +case PRID_REV_LOONGSON3A_R2_0 : +case PRID_REV_LOONGSON3A_R2_1 :case PRID_REV_LOONGSON3A_R3_0 :case PRID_REV_LOONGSON3A_R3_1 : cpu_clock_freq =900000000 ;
arch/mips/loongson64/loongson-3/smp.c +2 -1
@@ -682,7 +682,8 @@ void play_dead(void) play_dead_at_ckseg1 = (void *)CKSEG1ADDR ((unsigned long )loongson3a_r1_play_dead);break ; -case PRID_REV_LOONGSON3A_R2 : +case PRID_REV_LOONGSON3A_R2_0 : +case PRID_REV_LOONGSON3A_R2_1 :case PRID_REV_LOONGSON3A_R3_0 :case PRID_REV_LOONGSON3A_R3_1 : play_dead_at_ckseg1 =
arch/mips/mm/c-r4k.c +1 -1
@@ -1352,7 +1352,7 @@ static void probe_pcache(void) c->dcache.ways * c->dcache.linesz; c->dcache.waybit =0 ; -if ((prid &PRID_REV_MASK ) >=PRID_REV_LOONGSON3A_R2 ) +if ((prid &PRID_REV_MASK ) >=PRID_REV_LOONGSON3A_R2_0 ) c->options |=MIPS_CPU_PREFETCH ;break ;
drivers/platform/mips/cpu_hwmon.c +2 -1
@@ -25,9 +25,10 @@ int loongson3_cpu_temp(int cpu)case PRID_REV_LOONGSON3A_R1 : reg = (reg >>8 ) &0xff ;break ; -case PRID_REV_LOONGSON3A_R2 :case PRID_REV_LOONGSON3B_R1 :case PRID_REV_LOONGSON3B_R2 : +case PRID_REV_LOONGSON3A_R2_0 : +case PRID_REV_LOONGSON3A_R2_1 : reg = ((reg >>8 ) &0xff ) -100 ;break ;case PRID_REV_LOONGSON3A_R3_0 :
Signature · 1 line
2.7.0
PATCH v5 2/8 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/mach-loongson64/mmzone.h | 1 + arch/mips/include/asm/mmzone.h | 8 +++++ arch/mips/include/asm/r4kcache.h | 25 +++++++++++++++ arch/mips/mm/c-r4k.c | 44 ++++++++++++++++++++++---- 4 files changed, 71 insertions(+), 7 deletions(-)
arch/mips/include/asm/mach-loongson64/mmzone.h +1 -0
@@ -21,6 +21,7 @@#define NODE3_ADDRSPACE_OFFSET 0x300000000000UL#define pa_to_nid (addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT) +#define nid_to_addrbase (nid) ((nid) << NODE_ADDRSPACE_SHIFT)#define LEVELS_PER_SLICE 128
arch/mips/include/asm/mmzone.h +8 -0
@@ -9,6 +9,14 @@#include <asm/page.h> #include <mmzone.h> +#ifndef pa_to_nid +#define pa_to_nid (addr) 0 +#endif + +#ifndef nid_to_addrbase +#define nid_to_addrbase (nid) 0 +#endif +#ifdef CONFIG_DISCONTIGMEM #define pfn_to_nid (pfn) pa_to_nid((pfn) << PAGE_SHIFT)
arch/mips/include/asm/r4kcache.h +21 -0
@@ -674,4 +674,25 @@ __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, , ) +/* Currently, this is very specific to Loongson-3 */ +#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; \ + \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ + for (addr = start; addr < end; addr += lsize * 32) \ + cache##lsize##_unroll32(addr|ws, indexop); \ +} + +__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 +37 -7
79 lines not on this page · raw message
Signature · 1 line
2.7.0
PATCH v5 3/8 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 v5 4/8 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 | 6 ++++++ 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, 47 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
@@ -26,6 +26,8 @@ extern spinlock_t rtc_lock;*/ 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
@@ -1500,30 +1500,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 ; }
@@ -1874,16 +1884,18 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)case PRID_REV_LOONGSON3A_R2_0 :case PRID_REV_LOONGSON3A_R2_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 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 ; }
@@ -2003,6 +2015,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 +6 -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,11 @@ 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
@@ -54,6 +54,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;
@@ -212,5 +219,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
@@ -341,6 +341,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 v5 5/8 MIPS: Align kernel load address to 64KB
In reply to Huacai ChenKEXEC 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.
--- arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c +4 -3
@@ -13,6 +13,7 @@#include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include "../../../../include/linux/sizes.h" int main (int argc,char *argv[]) {
@@ -45,11 +46,11 @@ 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 needs load sections to be aligned to PAGE_SIZE, +* which may be as large as 64KB depending on the kernel configuration. */ - vmlinuz_load_addr += (16 - vmlinux_size %16 ); + vmlinuz_load_addr += (SZ_64K - vmlinux_size %SZ_64K );printf ("0x%llx\n" , vmlinuz_load_addr);
Signature · 1 line
2.7.0
PATCH v5 6/8 MIPS: Reserve extra memory for crash dump
In reply to Huacai ChenTraditionally, MIPS's contiguous low memory can be as less as 256M, so crashkernel=X@Y may be unable to large enough in some cases. Moreover, for the "multi numa node + sparse memory model" case, it is attempt to allocate section_mem_maps on every node. Thus, if the total memory of a node is more than 1GB, we reserve the top 128MB for the crash kernel.
--- arch/mips/kernel/setup.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
arch/mips/kernel/setup.c +51 -0
@@ -27,6 +27,7 @@#include <linux/dma-contiguous.h> #include <linux/decompress/generic.h> #include <linux/of_fdt.h> +#include <linux/crash_dump.h> #include <asm/addrspace.h> #include <asm/bootinfo.h>
@@ -756,6 +757,48 @@ static void __init request_crashkernel(struct resource *res)#define BUILTIN_EXTEND_WITH_PROM \ IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND) +/* Traditionally, MIPS's contiguous low memory is 256M, so crashkernel=X@Y is +* unable to be large enough in some cases. Thus, if the total memory of a node +* is more than 1GB, we reserve the top 128MB for the crash kernel */ +static void reserve_crashm_region (int node,unsigned long s0,unsigned long e0) +{ +#ifdef CONFIG_KEXEC +if (crashk_res.start == crashk_res.end) +return ; + +if ((e0 - s0) <= (SZ_1G >>PAGE_SHIFT )) +return ; + + s0 = e0 - (SZ_128M >>PAGE_SHIFT ); + +memblock_reserve (PFN_PHYS (s0), (e0 - s0) <<PAGE_SHIFT ); +#endif +} + +static void reserve_oldmem_region (int node,unsigned long s0,unsigned long e0) +{ +#ifdef CONFIG_CRASH_DUMP +unsigned long s1, e1; + +if (!is_kdump_kernel ()) +return ; + +if ((e0 - s0) > (SZ_1G >>PAGE_SHIFT )) + e0 = e0 - (SZ_128M >>PAGE_SHIFT ); + +/* boot_mem_map.map[0] is crashk_res reserved by primary kernel */ + s1 =PFN_UP (boot_mem_map.map[0 ].addr); + e1 =PFN_DOWN (boot_mem_map.map[0 ].addr + boot_mem_map.map[0 ].size); + +if (node ==0 ) { +memblock_reserve (PFN_PHYS (s0), (s1 - s0) <<PAGE_SHIFT ); +memblock_reserve (PFN_PHYS (e1), (e0 - e1) <<PAGE_SHIFT ); + }else { +memblock_reserve (PFN_PHYS (s0), (e0 - s0) <<PAGE_SHIFT ); + } +#endif +} +/* * arch_mem_init - initialize memory management subsystem *
@@ -780,6 +823,8 @@ static void __init request_crashkernel(struct resource *res)*/ static void __init arch_mem_init (char **cmdline_p) { +unsigned int node; +unsigned long start_pfn, end_pfn;struct memblock_region *reg;extern void plat_mem_setup (void );
@@ -877,6 +922,12 @@ static void __init arch_mem_init(char **cmdline_p)memblock_reserve (crashk_res.start, crashk_res.end - crashk_res.start +1 );#endif +for_each_online_node (node) { +get_pfn_range_for_nid (node, &start_pfn, &end_pfn); +reserve_crashm_region (node, start_pfn, end_pfn); +reserve_oldmem_region (node, start_pfn, end_pfn); + } +device_tree_init ();sparse_init ();plat_swiotlb_setup ();
Signature · 1 line
2.7.0
PATCH v5 7/8 MIPS: Loongson64: Add kexec/kdump support
In reply to Huacai ChenAdd kexec/kdump support for Loongson64 by:
1, Provide Loongson-specific kexec functions: loongson_kexec_prepare,
loongson_kexec_shutdown and loongson_crash_shutdown;
2, Provide Loongson-specific code in kexec_smp_wait;
3, Clear mailbox in loongson3_smp_setup() since KEXEC bypass BIOS; 4, KEXEC always run at boot-cpu, but KDUMP may triggered at non-boot-
cpu. Loongson64 assume boot-cpu is the first possible cpu, so fix boot_cpu_id in prom_init_env();
--- arch/mips/kernel/relocate_kernel.S | 26 ++++++++++ arch/mips/loongson64/common/env.c | 7 +++ arch/mips/loongson64/common/reset.c | 95 +++++++++++++++++++++++++++++++++++ arch/mips/loongson64/loongson-3/smp.c | 5 ++ 4 files changed, 133 insertions(+)
arch/mips/kernel/relocate_kernel.S +26 -0
@@ -135,6 +135,32 @@ LEAF(kexec_smp_wait) #else sync #endif + +#ifdef CONFIG_CPU_LOONGSON3 + /* s0:prid s1:initfn */ + /* t0:base t1:cpuid t2:node t9:count */ + mfc0 t1, CP0_EBASE + andi t1, MIPS_EBASE_CPUNUM + dli t0, 0x900000003ff01000 /* mailbox base */ + dins t0, t1, 8, 2 /* insert core id*/ + dext t2, t1, 2, 2 + dins t0, t2, 44, 2 /* insert node id */ + mfc0 s0, CP0_PRID + andi s0, s0, 0xf + blt s0, 0x6, 1f /* Loongson-3A1000 */ + bgt s0, 0x7, 1f /* Loongson-3A2000/3A3000 */ + dins t0, t2, 14, 2 /* Loongson-3B1000/3B1500 need bit 15~14 */ +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 +7 -0
@@ -149,6 +149,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 (); + loongson_sysconf.reserved_cpus_mask |= + (1 << loongson_sysconf.boot_cpu_id) -1 ; +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 +95 -0
116 lines not on this page · raw message
arch/mips/loongson64/loongson-3/smp.c +5 -0
@@ -388,6 +388,11 @@ static void __init loongson3_smp_setup(void)ipi_status0_regs_init ();ipi_en0_regs_init ();ipi_mailbox_buf_init (); + +/* BIOS clear the mailbox, but KEXEC bypass BIOS so clear here */ +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
PATCH v5 8/8 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).
This patch is not a minimal change (it is very difficult to make a minimal change), but it is a safest change.
Why disable fix-loongson3-llsc in compiler?
Because compiler fix will cause problems in kernel's .fixup section.
--- arch/mips/include/asm/atomic.h | 36 ++++++++++++++++++++++++++++-------- 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, 100 insertions(+), 20 deletions(-)
arch/mips/include/asm/atomic.h +28 -8
@@ -61,13 +61,16 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \ __asm__ __volatile__( \ " .set push \n" \ " .set "MIPS_ISA_LEVEL" \n" \ - "1: ll %0, %1 # atomic_" #op " \n" \ + "1: # atomic_" #op " \n" \ + __WAR_LLSC_MB \ + " ll %0, %1 \n" \ " " #asm_op " %0, %2 \n" \ " sc %0, %1 \n" \ "\t" __scbeqz " %0, 1b \n" \ " .set pop \n" \ : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ : "Ir" (i)); \ + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); \ } else { \ unsigned long flags; \ \
@@ -88,7 +91,9 @@ static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v) \ __asm__ __volatile__( \ " .set push \n" \ " .set "MIPS_ISA_LEVEL" \n" \ - "1: ll %1, %2 # atomic_" #op "_return \n" \ + "1: # atomic_" #op "_return \n" \ + __WAR_LLSC_MB \ + " ll %1, %2 \n" \ " " #asm_op " %0, %1, %3 \n" \ " sc %0, %2 \n" \ "\t" __scbeqz " %0, 1b \n" \
@@ -121,7 +126,9 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \ __asm__ __volatile__( \ " .set push \n" \ " .set "MIPS_ISA_LEVEL" \n" \ - "1: ll %1, %2 # atomic_fetch_" #op " \n" \ + "1: # atomic_fetch_" #op " \n" \ + __WAR_LLSC_MB \ + " ll %1, %2 \n" \ " " #asm_op " %0, %1, %3 \n" \ " sc %0, %2 \n" \ "\t" __scbeqz " %0, 1b \n" \
@@ -130,6 +137,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \ : "=&r" (result), "=&r" (temp), \ "+" GCC_OFF_SMALL_ASM() (v->counter) \ : "Ir" (i)); \ + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); \ }else { \unsigned long flags; \ \
@@ -193,7 +201,9 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) __asm__ __volatile__(" .set push \n" " .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" " .set pop \n" " subu %0, %1, %3 \n" " move %1, %0 \n"
@@ -259,13 +269,16 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v) \ __asm__ __volatile__( \ " .set push \n" \ " .set "MIPS_ISA_LEVEL" \n" \ - "1: lld %0, %1 # atomic64_" #op " \n" \ + "1: # atomic64_" #op " \n" \ + __WAR_LLSC_MB \ + " lld %0, %1 \n" \ " " #asm_op " %0, %2 \n" \ " scd %0, %1 \n" \ "\t" __scbeqz " %0, 1b \n" \ " .set pop \n" \ : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ : "Ir" (i)); \ + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); \ } else { \ unsigned long flags; \ \
@@ -286,7 +299,9 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \ __asm__ __volatile__( \ " .set push \n" \ " .set "MIPS_ISA_LEVEL" \n" \ - "1: lld %1, %2 # atomic64_" #op "_return\n" \ + "1: # atomic64_" #op "_return\n" \ + __WAR_LLSC_MB \ + " lld %1, %2 \n" \ " " #asm_op " %0, %1, %3 \n" \ " scd %0, %2 \n" \ "\t" __scbeqz " %0, 1b \n" \
@@ -319,7 +334,9 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \ __asm__ __volatile__( \ " .set push \n" \ " .set "MIPS_ISA_LEVEL" \n" \ - "1: lld %1, %2 # atomic64_fetch_" #op "\n" \ + "1: # atomic64_fetch_" #op "\n" \ + __WAR_LLSC_MB \ + " lld %1, %2 \n" \ " " #asm_op " %0, %1, %3 \n" \ " scd %0, %2 \n" \ "\t" __scbeqz " %0, 1b \n" \
@@ -328,6 +345,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \ : "=&r" (result), "=&r" (temp), \ "+" GCC_OFF_SMALL_ASM() (v->counter) \ : "Ir" (i)); \ + __asm__ __volatile__(__WAR_LLSC_MB : : :"memory"); \ }else { \unsigned long flags; \ \
@@ -392,7 +410,9 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) __asm__ __volatile__(" .set push \n" " .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" " move %1, %0 \n" " bltz %0, 1f \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
@@ -71,18 +71,21 @@ 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 push \n" " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # set_bit \n" " or %0, %2 \n" " " __SC "%0, %1 \n"
@@ -90,6 +93,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); }
@@ -125,18 +129,21 @@ 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 push \n" " .set "MIPS_ISA_ARCH_LEVEL" \n" + __WAR_LLSC_MB " " __LL "%0, %1 # clear_bit \n" " and %0, %2 \n" " " __SC "%0, %1 \n"
@@ -144,6 +151,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); }
@@ -197,6 +205,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) __asm__ __volatile__(" .set push \n" " .set " MIPS_ISA_ARCH_LEVEL " \n" + __WAR_LLSC_MB" " __LL"%0, %1 # change_bit \n" " xor %0, %2 \n" " " __SC "%0, %1 \n"
@@ -204,6 +213,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); }
@@ -248,6 +258,7 @@ static inline int test_and_set_bit(unsigned long nr, __asm__ __volatile__(" .set push \n" " .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"
@@ -304,6 +315,7 @@ static inline int test_and_set_bit_lock(unsigned long nr, __asm__ __volatile__(" .set push \n" " .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"
@@ -361,6 +373,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"
@@ -378,6 +391,7 @@ static inline int test_and_clear_bit(unsigned long nr, __asm__ __volatile__(" .set push \n" " .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"
@@ -437,6 +451,7 @@ static inline int test_and_change_bit(unsigned long nr, __asm__ __volatile__(" .set push \n" " .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
@@ -49,7 +49,9 @@ extern unsigned long __xchg_called_with_bad_pointer(void)" .set noat \n" \" .set push \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 pop \n" \" move $1, %z3 \n" \" .set " MIPS_ISA_ARCH_LEVEL " \n" \
@@ -120,7 +122,9 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x," .set noat \n" \" .set push \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 pop \n" \" move $1, %z4 \n" \
@@ -129,6 +133,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
@@ -23,13 +23,16 @@ static inline void edac_atomic_scrub(void *va, u32 size) __asm__ __volatile__ (" .set push \n" " .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 pop \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
@@ -55,7 +55,9 @@" .set noat \n" \" .set push \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 pop \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) \
@@ -169,7 +172,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr," .set noat \n" " .set push \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 pop \n" " move $1, %z5 \n"
@@ -185,8 +190,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
@@ -52,7 +52,9 @@ static __inline__ long local_add_return(long i, local_t * l) __asm__ __volatile__(" .set push \n" " .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"
@@ -61,6 +63,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;
@@ -99,7 +102,9 @@ static __inline__ long local_sub_return(long i, local_t * l) __asm__ __volatile__(" .set push \n" " .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"
@@ -108,6 +113,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
@@ -232,7 +232,9 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)" .set push \n" " .set " MIPS_ISA_ARCH_LEVEL " \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"
@@ -242,6 +244,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)" .set pop \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
@@ -137,6 +137,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"
@@ -160,6 +161,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
@@ -931,6 +931,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);
@@ -1555,6 +1557,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);
@@ -2258,6 +2263,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 ) {
@@ -2312,6 +2319,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 ) {
@@ -2367,6 +2376,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
I'm sorry that I send this series to a wrong place, please ignore.
Huacai
Quoted 77 lines · Huacai Chen
This patchset is prepared for the next 4.21 release for Linux/MIPS. It add Loongson-3A R2.1 basic support, adds "model name" and "CPU MHz" knobs in
/proc/cpuinfowhich is needed by some userspace tools, adds Loongson-3 kexec/kdump support, and introducesWAR_LLSC_MBto 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.V2 -> V3:
1, Remove merged patches.
2, Improve code and descriptions (Thank James Hogan). 3, Sync the code to upstream.V3 -> V4:
1, Remove merged patches.
2, Improve kdump support.
3, Sync the code to upstream.V4 -> V5:
1, Remove merged patches.
2, Add Loongson-3A R2.1 support.
3, Improve kexec/kdump support.
4, Sync the code to upstream.Huacai Chen(8):
MIPS: Loongson: Add Loongson-3A R2.1 basic support.
MIPS: c-r4k: Addr4k_blast_scache_nodefor Loongson-3.
MIPS: Ensurepmd_present()returns false afterpmd_mknotpresent().
MIPS: Add __cpu_full_name[] to make CPU names more human-readable.
MIPS: Align kernel load address to 64KB.
MIPS: Reserve extra memory for crash dump.
MIPS: Loongson: Add kexec/kdump support.
MIPS: Loongson: Introduce and useWAR_LLSC_MB.Signed-off-by Huacai Chen <[email protected]>--- arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 7 +- arch/mips/include/asm/atomic.h | 36 ++++++-- 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 | 3 +- 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/mach-loongson64/boot_param.h | 1 + .../asm/mach-loongson64/kernel-entry-init.h | 4 +- arch/mips/include/asm/mach-loongson64/mmzone.h | 1 + arch/mips/include/asm/mmzone.h | 8 ++ arch/mips/include/asm/pgtable-64.h | 5 ++ arch/mips/include/asm/pgtable.h | 5 +- arch/mips/include/asm/r4kcache.h | 21 +++++ arch/mips/include/asm/time.h | 2 + arch/mips/kernel/cpu-probe.c | 28 +++++-- arch/mips/kernel/idle.c | 2 +- arch/mips/kernel/proc.c | 6 ++ arch/mips/kernel/relocate_kernel.S | 26 ++++++ arch/mips/kernel/setup.c | 51 ++++++++++++ arch/mips/kernel/syscall.c | 2 + arch/mips/kernel/time.c | 2 + arch/mips/loongson64/Platform | 3 + arch/mips/loongson64/common/env.c | 23 +++++- arch/mips/loongson64/common/reset.c | 95 ++++++++++++++++++++++ arch/mips/loongson64/loongson-3/smp.c | 9 +- arch/mips/loongson64/loongson-3/smp.h | 1 + arch/mips/mm/c-r4k.c | 46 +++++++++-- arch/mips/mm/tlbex.c | 11 +++ drivers/platform/mips/cpu_hwmon.c | 3 +- 33 files changed, 421 insertions(+), 45 deletions(-)--
2.7.0