* [PATCH 0/8] MIPS: Loongson: new features and improvements
@ 2017-08-10 2:00 Huacai Chen
2017-08-10 2:00 ` [PATCH 1/8] MIPS: Loongson-3: Enable Store Fill Buffer at runtime Huacai Chen
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:00 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
This patchset is is prepared for the next 4.14 release for Linux/MIPS.
It 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 pmd_present() and
indexed scache flushing for Loongson-3, and introduces WAR_LLSC_MB to
improve stability.
Huacai Chen(8):
MIPS: Loongson-3: Enable Store Fill Buffer at runtime.
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: Loongson: Add kexec/kdump support.
MIPS: Loongson: Make CPUFreq usable for Loongson-3.
MIPS: Loongson: Introduce and use WAR_LLSC_MB.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
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/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 | 1 +
.../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 | 25 ++-
arch/mips/kernel/proc.c | 6 +
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 | 21 ++
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/smp.c | 5 +
arch/mips/loongson64/loongson-3/smp.h | 1 +
arch/mips/mm/c-r4k.c | 42 +++-
arch/mips/mm/tlbex.c | 11 +
drivers/cpufreq/Kconfig | 15 ++
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/loongson3_cpufreq.c | 236 +++++++++++++++++++++
38 files changed, 855 insertions(+), 52 deletions(-)
create mode 100644 arch/mips/loongson64/loongson-3/clock.c
create mode 100644 drivers/cpufreq/loongson3_cpufreq.c
--
2.7.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/8] MIPS: Loongson-3: Enable Store Fill Buffer at runtime
2017-08-10 2:00 [PATCH 0/8] MIPS: Loongson: new features and improvements Huacai Chen
@ 2017-08-10 2:00 ` Huacai Chen
2018-01-24 20:54 ` James Hogan
2017-08-10 2:04 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 Huacai Chen
2017-08-10 2:15 ` [PATCH 7/8] MIPS: Loongson: Make CPUFreq usable " Huacai Chen
2 siblings, 1 reply; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:00 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
New 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).
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/include/asm/io.h | 2 +-
.../asm/mach-loongson64/kernel-entry-init.h | 38 +++++++++++++---------
arch/mips/include/asm/mipsregs.h | 2 ++
3 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index ecabc00..d3e38af 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -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)
diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
index 8393bc54..4b7f58a 100644
--- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
@@ -19,19 +19,22 @@
.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
-#ifdef CONFIG_LOONGSON3_ENHANCEMENT
+ mtc0 t0, CP0_PAGEGRAIN
/* Enable STFill Buffer */
- mfc0 t0, $16, 6
+ mfc0 t0, CP0_PRID
+ andi t0, 0xffff
+ slti t0, 0x6308
+ bnez t0, 1f
+ mfc0 t0, CP0_CONFIG6
or t0, 0x100
- mtc0 t0, $16, 6
-#endif
+ mtc0 t0, CP0_CONFIG6
+1:
_ehb
.set pop
#endif
@@ -45,19 +48,22 @@
.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
-#ifdef CONFIG_LOONGSON3_ENHANCEMENT
+ mtc0 t0, CP0_PAGEGRAIN
/* Enable STFill Buffer */
- mfc0 t0, $16, 6
+ mfc0 t0, CP0_PRID
+ andi t0, 0xffff
+ slti t0, 0x6308
+ bnez t0, 1f
+ mfc0 t0, CP0_CONFIG6
or t0, 0x100
- mtc0 t0, $16, 6
-#endif
+ mtc0 t0, CP0_CONFIG6
+1:
_ehb
.set pop
#endif
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index dbb0ece..cb1ebc6 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -50,6 +50,7 @@
#define CP0_CONF $3
#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
@@ -76,6 +77,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
--
2.7.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3
2017-08-10 2:00 [PATCH 0/8] MIPS: Loongson: new features and improvements Huacai Chen
2017-08-10 2:00 ` [PATCH 1/8] MIPS: Loongson-3: Enable Store Fill Buffer at runtime Huacai Chen
@ 2017-08-10 2:04 ` Huacai Chen
2017-08-10 2:04 ` [PATCH 3/8] MIPS: Ensure pmd_present() returns false after pmd_mknotpresent() Huacai Chen
` (4 more replies)
2017-08-10 2:15 ` [PATCH 7/8] MIPS: Loongson: Make CPUFreq usable " Huacai Chen
2 siblings, 5 replies; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:04 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen, stable
For 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.
Cc: stable@vger.kernel.org
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/include/asm/r4kcache.h | 34 ++++++++++++++++++++++++++++++++
arch/mips/mm/c-r4k.c | 42 +++++++++++++++++++++++++++++++++-------
2 files changed, 69 insertions(+), 7 deletions(-)
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 7f12d7e..c1f2806 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -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 */
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 81d6a15..7b242e8 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -459,11 +459,28 @@ static void r4k_blast_scache_setup(void)
r4k_blast_scache = blast_scache128;
}
+static void (* r4k_blast_scache_node)(long node);
+
+static void r4k_blast_scache_node_setup(void)
+{
+ unsigned long sc_lsize = cpu_scache_line_size();
+
+ if (current_cpu_type() != CPU_LOONGSON3)
+ r4k_blast_scache_node = (void *)cache_noop;
+ else if (sc_lsize == 16)
+ r4k_blast_scache_node = blast_scache16_node;
+ else if (sc_lsize == 32)
+ r4k_blast_scache_node = blast_scache32_node;
+ else if (sc_lsize == 64)
+ r4k_blast_scache_node = blast_scache64_node;
+ else if (sc_lsize == 128)
+ r4k_blast_scache_node = blast_scache128_node;
+}
+
static inline void local_r4k___flush_cache_all(void * args)
{
switch (current_cpu_type()) {
case CPU_LOONGSON2:
- case CPU_LOONGSON3:
case CPU_R4000SC:
case CPU_R4000MC:
case CPU_R4400SC:
@@ -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);
+ 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)
preempt_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));
+ } else
blast_scache_range(addr, addr + size);
preempt_enable();
__sync();
@@ -872,9 +896,12 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
preempt_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));
+ } else {
/*
* There is no clearly documented alignment requirement
* for the cache instruction on MIPS processors and
@@ -1905,6 +1932,7 @@ void r4k_cache_init(void)
r4k_blast_scache_page_setup();
r4k_blast_scache_page_indexed_setup();
r4k_blast_scache_setup();
+ r4k_blast_scache_node_setup();
#ifdef CONFIG_EVA
r4k_blast_dcache_user_page_setup();
r4k_blast_icache_user_page_setup();
--
2.7.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/8] MIPS: Ensure pmd_present() returns false after pmd_mknotpresent()
2017-08-10 2:04 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 Huacai Chen
@ 2017-08-10 2:04 ` Huacai Chen
2018-01-24 21:47 ` James Hogan
2017-08-10 2:04 ` [PATCH 4/8] MIPS: Add __cpu_full_name[] to make CPU names more human-readable Huacai Chen
` (3 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:04 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen, stable
This patch is borrowed from ARM64 to ensure pmd_present() returns false
after pmd_mknotpresent(). This is needed for THP.
Cc: stable@vger.kernel.org
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/include/asm/pgtable-64.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
index 67fe6dc..a2252c2 100644
--- a/arch/mips/include/asm/pgtable-64.h
+++ b/arch/mips/include/asm/pgtable-64.h
@@ -271,6 +271,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;
}
--
2.7.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/8] MIPS: Add __cpu_full_name[] to make CPU names more human-readable
2017-08-10 2:04 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 Huacai Chen
2017-08-10 2:04 ` [PATCH 3/8] MIPS: Ensure pmd_present() returns false after pmd_mknotpresent() Huacai Chen
@ 2017-08-10 2:04 ` Huacai Chen
2018-01-24 22:14 ` James Hogan
2017-08-10 2:04 ` [PATCH 5/8] MIPS: Align kernel load address to 64KB Huacai Chen
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:04 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
In /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).
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
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(-)
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index cd6efb0..8a8a414 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -121,7 +121,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;
diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
index 9f9bb9c..b7ed31b 100644
--- a/arch/mips/include/asm/mach-loongson64/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
@@ -57,6 +57,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
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index 17d4cd2..efbfc48 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -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.
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index d08afc7..1b54a71 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1476,30 +1476,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;
}
@@ -1845,15 +1855,17 @@ 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:
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;
}
@@ -1973,6 +1985,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)
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 70604c7..3200c0e 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -14,6 +14,7 @@
#include <asm/mipsregs.h>
#include <asm/processor.h>
#include <asm/prom.h>
+#include <asm/time.h>
unsigned int vced_count, vcei_count;
@@ -62,6 +63,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);
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index c036157..7350944 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -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);
diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c
index 1e8a955..6891780 100644
--- a/arch/mips/loongson64/common/env.c
+++ b/arch/mips/loongson64/common/env.c
@@ -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;
@@ -210,5 +217,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;
}
diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
index b7a355c..c93a42a 100644
--- a/arch/mips/loongson64/loongson-3/smp.c
+++ b/arch/mips/loongson64/loongson-3/smp.c
@@ -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)
diff --git a/arch/mips/loongson64/loongson-3/smp.h b/arch/mips/loongson64/loongson-3/smp.h
index d98ff65..25cb992 100644
--- a/arch/mips/loongson64/loongson-3/smp.h
+++ b/arch/mips/loongson64/loongson-3/smp.h
@@ -2,6 +2,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 */
--
2.7.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/8] MIPS: Align kernel load address to 64KB
2017-08-10 2:04 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 Huacai Chen
2017-08-10 2:04 ` [PATCH 3/8] MIPS: Ensure pmd_present() returns false after pmd_mknotpresent() Huacai Chen
2017-08-10 2:04 ` [PATCH 4/8] MIPS: Add __cpu_full_name[] to make CPU names more human-readable Huacai Chen
@ 2017-08-10 2:04 ` Huacai Chen
2017-08-10 2:04 ` [PATCH 6/8] MIPS: Loongson: Add kexec/kdump support Huacai Chen
2018-01-24 21:22 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 James Hogan
4 siblings, 0 replies; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:04 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
KEXEC assume kernel align to PAGE_SIZE, and 64KB is the largest
PAGE_SIZE.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/boot/compressed/calc_vmlinuz_load_addr.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
index 37fe58c..1dcaef4 100644
--- a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
+++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
@@ -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);
--
2.7.0
\x11
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 6/8] MIPS: Loongson: Add kexec/kdump support
2017-08-10 2:04 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 Huacai Chen
` (2 preceding siblings ...)
2017-08-10 2:04 ` [PATCH 5/8] MIPS: Align kernel load address to 64KB Huacai Chen
@ 2017-08-10 2:04 ` Huacai Chen
2018-01-24 21:22 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 James Hogan
4 siblings, 0 replies; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:04 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
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(+)
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
index c6bbf21..e73edc7 100644
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -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
diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c
index 6891780..92e85ca 100644
--- a/arch/mips/loongson64/common/env.c
+++ b/arch/mips/loongson64/common/env.c
@@ -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 +
diff --git a/arch/mips/loongson64/common/reset.c b/arch/mips/loongson64/common/reset.c
index a60715e..5f65a4e 100644
--- a/arch/mips/loongson64/common/reset.c
+++ b/arch/mips/loongson64/common/reset.c
@@ -11,9 +11,14 @@
*/
#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>
#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
+#define KEXEC_ARGV_SIZE 3060
+#define KEXEC_ENVP_SIZE 4500
+
+void *kexec_argv;
+void *kexec_envp;
+extern const size_t relocate_new_kernel_size;
+
+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;
+ 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)
+{
+ int cpu = smp_processor_id();
+
+ local_irq_disable();
+ set_cpu_online(cpu, false);
+ while (!atomic_read(&kexec_ready_to_reboot))
+ cpu_relax();
+
+ asm volatile (
+ " sync \n"
+ " synci ($0) \n");
+
+ 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 */
+
+ smp_call_function(kexec_smp_down, NULL, 0);
+ smp_wmb();
+ 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);
+}
+
+static void loongson_crash_shutdown(struct pt_regs *regs)
+{
+ default_machine_crash_shutdown(regs);
+ memcpy((void *)fw_arg1, kexec_argv, KEXEC_ARGV_SIZE);
+ memcpy((void *)fw_arg2, kexec_envp, KEXEC_ENVP_SIZE);
+}
+
+#endif
+
static int __init mips_reboot_setup(void)
{
_machine_restart = loongson_restart;
_machine_halt = loongson_halt;
pm_power_off = loongson_poweroff;
+#ifdef CONFIG_KEXEC
+ kexec_argv = kmalloc(KEXEC_ARGV_SIZE, GFP_KERNEL);
+ kexec_envp = kmalloc(KEXEC_ENVP_SIZE, GFP_KERNEL);
+ fw_arg1 = KEXEC_ARGV_ADDR;
+ memcpy(kexec_envp, (void *)fw_arg2, KEXEC_ENVP_SIZE);
+
+ _machine_kexec_prepare = loongson_kexec_prepare;
+ _machine_kexec_shutdown = loongson_kexec_shutdown;
+ _machine_crash_shutdown = loongson_crash_shutdown;
+#endif
+
return 0;
}
diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
index c93a42a..cc160ee 100644
--- a/arch/mips/loongson64/loongson-3/smp.c
+++ b/arch/mips/loongson64/loongson-3/smp.c
@@ -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_data[0].core = cpu_logical_map(0) % loongson_sysconf.cores_per_package;
cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package;
}
--
2.7.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 7/8] MIPS: Loongson: Make CPUFreq usable for Loongson-3
2017-08-10 2:00 [PATCH 0/8] MIPS: Loongson: new features and improvements Huacai Chen
2017-08-10 2:00 ` [PATCH 1/8] MIPS: Loongson-3: Enable Store Fill Buffer at runtime Huacai Chen
2017-08-10 2:04 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 Huacai Chen
@ 2017-08-10 2:15 ` Huacai Chen
2017-08-10 2:15 ` [PATCH 8/8] MIPS: Loongson: Introduce and use WAR_LLSC_MB Huacai Chen
2 siblings, 1 reply; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:15 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, 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. 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.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
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 | 15 ++
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/loongson3_cpufreq.c | 236 +++++++++++++++++++++++
9 files changed, 458 insertions(+), 5 deletions(-)
create mode 100644 arch/mips/loongson64/loongson-3/clock.c
create mode 100644 drivers/cpufreq/loongson3_cpufreq.c
diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
index c68c0cc..271cabb 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson.h
@@ -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
/*
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 770d4d1..eb1bb0a 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -371,7 +371,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);
diff --git a/arch/mips/loongson64/Kconfig b/arch/mips/loongson64/Kconfig
index 8e6e292..7e5bb30 100644
--- a/arch/mips/loongson64/Kconfig
+++ b/arch/mips/loongson64/Kconfig
@@ -69,6 +69,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
diff --git a/arch/mips/loongson64/common/platform.c b/arch/mips/loongson64/common/platform.c
index 0ed3832..733a13f 100644
--- a/arch/mips/loongson64/common/platform.c
+++ b/arch/mips/loongson64/common/platform.c
@@ -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);
diff --git a/arch/mips/loongson64/loongson-3/Makefile b/arch/mips/loongson64/loongson-3/Makefile
index 44bc148..7b035b7 100644
--- a/arch/mips/loongson64/loongson-3/Makefile
+++ b/arch/mips/loongson64/loongson-3/Makefile
@@ -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
diff --git a/arch/mips/loongson64/loongson-3/clock.c b/arch/mips/loongson64/loongson-3/clock.c
new file mode 100644
index 0000000..118f539
--- /dev/null
+++ b/arch/mips/loongson64/loongson-3/clock.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2008 - 2014 Lemote Inc.
+ * Author: Yan Hua, yanh@lemote.com
+ * Chen Huacai, chenhc@lemote.com
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/platform_device.h>
+
+#include <asm/clock.h>
+
+#include <loongson.h>
+
+static LIST_HEAD(clock_list);
+static DEFINE_SPINLOCK(clock_lock);
+static DEFINE_MUTEX(clock_list_sem);
+
+/* Minimum CLK support */
+enum {
+ DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT,
+ DC_87PT, DC_DISABLE, DC_RESV
+};
+
+struct cpufreq_frequency_table loongson3_clockmod_table[] = {
+ {0, DC_RESV, CPUFREQ_ENTRY_INVALID},
+ {0, DC_ZERO, CPUFREQ_ENTRY_INVALID},
+ {0, DC_25PT, 0},
+ {0, DC_37PT, 0},
+ {0, DC_50PT, 0},
+ {0, DC_62PT, 0},
+ {0, DC_75PT, 0},
+ {0, DC_87PT, 0},
+ {0, DC_DISABLE, 0},
+ {0, DC_RESV, CPUFREQ_TABLE_END},
+};
+EXPORT_SYMBOL_GPL(loongson3_clockmod_table);
+
+static struct clk cpu_clks[NR_CPUS];
+static char clk_names[NR_CPUS][10];
+
+struct clk *cpu_clk_get(int cpu)
+{
+ return &cpu_clks[cpu];
+}
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ int i;
+ struct clk *clk;
+
+ if (!id)
+ return NULL;
+
+ for_each_possible_cpu(i) {
+ clk = &cpu_clks[i];
+ if (strcmp(clk->name, id) == 0)
+ return clk;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(clk_get);
+
+static void propagate_rate(struct clk *clk)
+{
+ struct clk *clkp;
+
+ list_for_each_entry(clkp, &clock_list, node) {
+ if (likely(clkp->parent != clk))
+ continue;
+ if (likely(clkp->ops && clkp->ops->recalc))
+ clkp->ops->recalc(clkp);
+ if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
+ propagate_rate(clkp);
+ }
+}
+
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (!clk)
+ return 0;
+
+ return (unsigned long)clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int regval, ret = 0;
+ struct cpufreq_frequency_table *pos;
+ int cpu = clk - cpu_clks;
+ uint64_t core_id = cpu_data[cpu].core;
+ uint64_t package_id = cpu_data[cpu].package;
+
+ if (likely(clk->ops && clk->ops->set_rate)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock_lock, flags);
+ ret = clk->ops->set_rate(clk, rate, 0);
+ spin_unlock_irqrestore(&clock_lock, flags);
+ }
+
+ if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
+ propagate_rate(clk);
+
+ cpufreq_for_each_valid_entry(pos, loongson3_clockmod_table)
+ if (rate == pos->frequency)
+ break;
+ if (rate != pos->frequency)
+ return -ENOTSUPP;
+
+ clk->rate = rate;
+
+ if ((read_c0_prid() & 0xf) == PRID_REV_LOONGSON3A_R1) {
+ regval = LOONGSON_CHIPCFG(package_id);
+ regval = (regval & ~0x7) | (pos->driver_data - 1);
+ LOONGSON_CHIPCFG(package_id) = regval;
+ } else {
+ regval = LOONGSON_FREQCTRL(package_id);
+ regval = (regval & ~(0x7 << (core_id*4))) |
+ ((pos->driver_data - 1) << (core_id*4));
+ LOONGSON_FREQCTRL(package_id) = regval;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (likely(clk->ops && clk->ops->round_rate)) {
+ unsigned long flags, rounded;
+
+ spin_lock_irqsave(&clock_lock, flags);
+ rounded = clk->ops->round_rate(clk, rate);
+ spin_unlock_irqrestore(&clock_lock, flags);
+
+ return rounded;
+ }
+
+ return rate;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+static int loongson3_clock_init(void)
+{
+ int i;
+
+ for_each_possible_cpu(i) {
+ sprintf(clk_names[i], "cpu%d_clk", i);
+ cpu_clks[i].name = clk_names[i];
+ cpu_clks[i].flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES;
+ cpu_clks[i].rate = cpu_clock_freq / 1000;
+ }
+
+ /* clock table init */
+ for (i = 2;
+ (loongson3_clockmod_table[i].frequency != CPUFREQ_TABLE_END);
+ i++)
+ loongson3_clockmod_table[i].frequency = ((cpu_clock_freq / 1000) * i) / 8;
+
+ return 0;
+}
+arch_initcall(loongson3_clock_init);
+
+MODULE_AUTHOR("Huacai Chen <chenhc@lemote.com>");
+MODULE_DESCRIPTION("CPUFreq driver for Loongson 3A/3B");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 4ebae43..7d79e5e 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -275,6 +275,7 @@ config BMIPS_CPUFREQ
config LOONGSON2_CPUFREQ
tristate "Loongson2 CPUFreq Driver"
+ depends on CPU_LOONGSON2
help
This option adds a CPUFreq driver for loongson processors which
support software configurable cpu frequency.
@@ -285,8 +286,22 @@ config LOONGSON2_CPUFREQ
If in doubt, say N.
+config LOONGSON3_CPUFREQ
+ tristate "Loongson3 CPUFreq Driver"
+ depends on CPU_LOONGSON3
+ 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 CPU_LOONGSON1
help
This option adds a CPUFreq driver for loongson1 processors which
support software configurable cpu frequency.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index ab3a42c..9b09a25 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -105,6 +105,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
diff --git a/drivers/cpufreq/loongson3_cpufreq.c b/drivers/cpufreq/loongson3_cpufreq.c
new file mode 100644
index 0000000..e71f3cd
--- /dev/null
+++ b/drivers/cpufreq/loongson3_cpufreq.c
@@ -0,0 +1,236 @@
+/*
+ * CPUFreq driver for the loongson-3 processors
+ *
+ * All revisions of Loongson-3 processor support this feature.
+ *
+ * Copyright (C) 2008 - 2014 Lemote Inc.
+ * Author: Yan Hua, yanh@lemote.com
+ * Chen Huacai, chenhc@lemote.com
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/cpufreq.h>
+#include <linux/platform_device.h>
+#include <asm/idle.h>
+#include <asm/clock.h>
+#include <asm/cevt-r4k.h>
+
+#include <loongson.h>
+
+static uint nowait = 1;
+static spinlock_t cpufreq_reg_lock[MAX_PACKAGES];
+
+static void (*saved_cpu_wait)(void);
+extern struct clk *cpu_clk_get(int cpu);
+
+static int loongson3_cpu_freq_notifier(struct notifier_block *nb,
+ unsigned long val, void *data);
+
+static struct notifier_block loongson3_cpufreq_notifier_block = {
+ .notifier_call = loongson3_cpu_freq_notifier
+};
+
+#ifdef CONFIG_SMP
+static int loongson3_cpu_freq_notifier(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ struct cpufreq_freqs *freqs = (struct cpufreq_freqs *)data;
+ unsigned long cpu = freqs->cpu;
+ struct clock_event_device *cd = &per_cpu(mips_clockevent_device, cpu);
+
+ if (val == CPUFREQ_POSTCHANGE) {
+ if (cpu == smp_processor_id())
+ clockevents_update_freq(cd, freqs->new * 1000 / 2);
+ else {
+ clockevents_calc_mult_shift(cd, freqs->new * 1000 / 2, 4);
+ cd->min_delta_ns = clockevent_delta2ns(cd->min_delta_ticks, cd);
+ cd->max_delta_ns = clockevent_delta2ns(cd->max_delta_ticks, cd);
+ }
+ cpu_data[cpu].udelay_val =
+ cpufreq_scale(loops_per_jiffy, cpu_clock_freq / 1000, freqs->new);
+ }
+
+ return 0;
+}
+#else
+static int loongson3_cpu_freq_notifier(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ struct cpufreq_freqs *freqs = (struct cpufreq_freqs *)data;
+ struct clock_event_device *cd = &per_cpu(mips_clockevent_device, 0);
+
+ if (val == CPUFREQ_POSTCHANGE) {
+ clockevents_update_freq(cd, freqs->new * 1000 / 2);
+ current_cpu_data.udelay_val = loops_per_jiffy;
+ }
+
+ return 0;
+}
+#endif
+
+static unsigned int loongson3_cpufreq_get(unsigned int cpu)
+{
+ return clk_get_rate(cpu_clk_get(cpu));
+}
+
+/*
+ * Here we notify other drivers of the proposed change and the final change.
+ */
+static int loongson3_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int index)
+{
+ unsigned int freq;
+ unsigned int cpu = policy->cpu;
+ unsigned int package = cpu_data[cpu].package;
+
+ if (!cpu_online(cpu))
+ return -ENODEV;
+
+ freq =
+ ((cpu_clock_freq / 1000) *
+ loongson3_clockmod_table[index].driver_data) / 8;
+
+ /* setting the cpu frequency */
+ spin_lock(&cpufreq_reg_lock[package]);
+ clk_set_rate(policy->clk, freq);
+ spin_unlock(&cpufreq_reg_lock[package]);
+
+ return 0;
+}
+
+static int loongson3_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ if (!cpu_online(policy->cpu))
+ return -ENODEV;
+
+ policy->clk = cpu_clk_get(policy->cpu);
+ policy->cur = loongson3_cpufreq_get(policy->cpu);
+
+ policy->cpuinfo.transition_latency = 1000;
+
+ /* Loongson-3A R1: all cores in a package share one clock */
+ if ((read_c0_prid() & 0xf) == PRID_REV_LOONGSON3A_R1)
+ cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+
+ return cpufreq_table_validate_and_show(policy,
+ &loongson3_clockmod_table[0]);
+}
+
+static int loongson3_cpufreq_exit(struct cpufreq_policy *policy)
+{
+ return 0;
+}
+
+static struct cpufreq_driver loongson3_cpufreq_driver = {
+ .name = "loongson3",
+ .init = loongson3_cpufreq_cpu_init,
+ .verify = cpufreq_generic_frequency_table_verify,
+ .target_index = loongson3_cpufreq_target,
+ .get = loongson3_cpufreq_get,
+ .exit = loongson3_cpufreq_exit,
+ .attr = cpufreq_generic_attr,
+};
+
+static struct platform_device_id platform_device_ids[] = {
+ {
+ .name = "loongson3_cpufreq",
+ },
+ {}
+};
+
+MODULE_DEVICE_TABLE(platform, platform_device_ids);
+
+static struct platform_driver platform_driver = {
+ .driver = {
+ .name = "loongson3_cpufreq",
+ .owner = THIS_MODULE,
+ },
+ .id_table = platform_device_ids,
+};
+
+/*
+ * This is the simple version of Loongson-3 wait, Maybe we need do this in
+ * interrupt disabled content
+ */
+
+void loongson3_cpu_wait(void)
+{
+ u32 cpu_freq, shared_cpus = 0;
+ int i, cpu = smp_processor_id();
+ uint64_t core_id = cpu_data[cpu].core;
+ uint64_t package_id = cpu_data[cpu].package;
+
+ for_each_online_cpu(i)
+ if (cpu_data[i].package == package_id)
+ shared_cpus++;
+
+ if (shared_cpus > 1)
+ goto out;
+
+ if ((read_c0_prid() & 0xf) == PRID_REV_LOONGSON3A_R1) {
+ cpu_freq = LOONGSON_CHIPCFG(package_id);
+ LOONGSON_CHIPCFG(package_id) &= ~0x7; /* Put CPU into wait mode */
+ LOONGSON_CHIPCFG(package_id) = cpu_freq; /* Restore CPU state */
+ } else {
+ cpu_freq = LOONGSON_FREQCTRL(package_id);
+ LOONGSON_FREQCTRL(package_id) &= ~(0x7 << (core_id*4)); /* Put CPU into wait mode */
+ LOONGSON_FREQCTRL(package_id) = cpu_freq; /* Restore CPU state */
+ }
+
+out:
+ local_irq_enable();
+}
+EXPORT_SYMBOL_GPL(loongson3_cpu_wait);
+
+static int __init cpufreq_init(void)
+{
+ int i, ret;
+
+ /* Register platform stuff */
+ ret = platform_driver_register(&platform_driver);
+ if (ret)
+ return ret;
+
+ pr_info("cpufreq: Loongson-3 CPU frequency driver.\n");
+
+ for (i = 0; i < MAX_PACKAGES; i++)
+ spin_lock_init(&cpufreq_reg_lock[i]);
+
+ cpufreq_register_notifier(&loongson3_cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+
+ ret = cpufreq_register_driver(&loongson3_cpufreq_driver);
+
+ if (!ret && !nowait) {
+ saved_cpu_wait = cpu_wait;
+ cpu_wait = loongson3_cpu_wait;
+ }
+
+ return ret;
+}
+
+static void __exit cpufreq_exit(void)
+{
+ if (!nowait && saved_cpu_wait)
+ cpu_wait = saved_cpu_wait;
+ cpufreq_unregister_driver(&loongson3_cpufreq_driver);
+ cpufreq_unregister_notifier(&loongson3_cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+
+ platform_driver_unregister(&platform_driver);
+}
+
+module_init(cpufreq_init);
+module_exit(cpufreq_exit);
+
+module_param(nowait, uint, 0644);
+MODULE_PARM_DESC(nowait, "Disable Loongson-3A/3B specific wait");
+
+MODULE_AUTHOR("Huacai Chen <chenhc@lemote.com>");
+MODULE_DESCRIPTION("CPUFreq driver for Loongson-3A/3B");
+MODULE_LICENSE("GPL");
--
2.7.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 8/8] MIPS: Loongson: Introduce and use WAR_LLSC_MB
2017-08-10 2:15 ` [PATCH 7/8] MIPS: Loongson: Make CPUFreq usable " Huacai Chen
@ 2017-08-10 2:15 ` Huacai Chen
0 siblings, 0 replies; 13+ messages in thread
From: Huacai Chen @ 2017-08-10 2:15 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J . Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, 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).
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
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(-)
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 0ab176b..99a6d01 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -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"
diff --git a/arch/mips/include/asm/barrier.h b/arch/mips/include/asm/barrier.h
index a5eb1bb..d892094 100644
--- a/arch/mips/include/asm/barrier.h
+++ b/arch/mips/include/asm/barrier.h
@@ -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
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index fa57cef..7f39180 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -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"
diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index 903f3bf..744723e 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -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"); \
diff --git a/arch/mips/include/asm/edac.h b/arch/mips/include/asm/edac.h
index 980b165..ecf1a76 100644
--- a/arch/mips/include/asm/edac.h
+++ b/arch/mips/include/asm/edac.h
@@ -21,13 +21,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++;
}
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index 1de190b..39a3566 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -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) \
@@ -184,7 +187,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"
@@ -200,8 +205,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),
diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index 8feaed6..9ba7a54 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -49,7 +49,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"
@@ -58,6 +60,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;
@@ -94,7 +97,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"
@@ -103,6 +108,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;
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 9e9e944..8af0dac 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -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))
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 58c6f63..342fbff 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -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();
diff --git a/arch/mips/loongson64/Platform b/arch/mips/loongson64/Platform
index 0fce460..3700dcf 100644
--- a/arch/mips/loongson64/Platform
+++ b/arch/mips/loongson64/Platform
@@ -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
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 5aadc69..b05e734 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -935,6 +935,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);
@@ -1560,6 +1562,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);
@@ -1660,6 +1663,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);
@@ -2277,6 +2282,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) {
@@ -2332,6 +2339,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) {
@@ -2388,6 +2397,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) {
--
2.7.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/8] MIPS: Loongson-3: Enable Store Fill Buffer at runtime
2017-08-10 2:00 ` [PATCH 1/8] MIPS: Loongson-3: Enable Store Fill Buffer at runtime Huacai Chen
@ 2018-01-24 20:54 ` James Hogan
0 siblings, 0 replies; 13+ messages in thread
From: James Hogan @ 2018-01-24 20:54 UTC (permalink / raw)
To: Huacai Chen
Cc: Ralf Baechle, John Crispin, Steven J . Hill, linux-mips,
Fuxin Zhang, Zhangjin Wu
[-- Attachment #1: Type: text/plain, Size: 3966 bytes --]
On Thu, Aug 10, 2017 at 10:00:26AM +0800, Huacai Chen wrote:
> New 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).
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> ---
> arch/mips/include/asm/io.h | 2 +-
> .../asm/mach-loongson64/kernel-entry-init.h | 38 +++++++++++++---------
> arch/mips/include/asm/mipsregs.h | 2 ++
> 3 files changed, 25 insertions(+), 17 deletions(-)
>
> diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
> index ecabc00..d3e38af 100644
> --- a/arch/mips/include/asm/io.h
> +++ b/arch/mips/include/asm/io.h
> @@ -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)
> diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> index 8393bc54..4b7f58a 100644
> --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> @@ -19,19 +19,22 @@
> .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
Please don't mix cleanups with functional changes.
Separately, both the cleanup and the main change look good to me.
Cheers
James
> or t0, (0x1 << 29)
> - mtc0 t0, $5, 1
> -#ifdef CONFIG_LOONGSON3_ENHANCEMENT
> + mtc0 t0, CP0_PAGEGRAIN
> /* Enable STFill Buffer */
> - mfc0 t0, $16, 6
> + mfc0 t0, CP0_PRID
> + andi t0, 0xffff
> + slti t0, 0x6308
> + bnez t0, 1f
> + mfc0 t0, CP0_CONFIG6
> or t0, 0x100
> - mtc0 t0, $16, 6
> -#endif
> + mtc0 t0, CP0_CONFIG6
> +1:
> _ehb
> .set pop
> #endif
> @@ -45,19 +48,22 @@
> .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
> -#ifdef CONFIG_LOONGSON3_ENHANCEMENT
> + mtc0 t0, CP0_PAGEGRAIN
> /* Enable STFill Buffer */
> - mfc0 t0, $16, 6
> + mfc0 t0, CP0_PRID
> + andi t0, 0xffff
> + slti t0, 0x6308
> + bnez t0, 1f
> + mfc0 t0, CP0_CONFIG6
> or t0, 0x100
> - mtc0 t0, $16, 6
> -#endif
> + mtc0 t0, CP0_CONFIG6
> +1:
> _ehb
> .set pop
> #endif
> diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
> index dbb0ece..cb1ebc6 100644
> --- a/arch/mips/include/asm/mipsregs.h
> +++ b/arch/mips/include/asm/mipsregs.h
> @@ -50,6 +50,7 @@
> #define CP0_CONF $3
> #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
> @@ -76,6 +77,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
> --
> 2.7.0
>
>
>
>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3
2017-08-10 2:04 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 Huacai Chen
` (3 preceding siblings ...)
2017-08-10 2:04 ` [PATCH 6/8] MIPS: Loongson: Add kexec/kdump support Huacai Chen
@ 2018-01-24 21:22 ` James Hogan
4 siblings, 0 replies; 13+ messages in thread
From: James Hogan @ 2018-01-24 21:22 UTC (permalink / raw)
To: Huacai Chen
Cc: Ralf Baechle, John Crispin, Steven J . Hill, linux-mips,
Fuxin Zhang, Zhangjin Wu, stable
[-- Attachment #1: Type: text/plain, Size: 983 bytes --]
On Thu, Aug 10, 2017 at 10:04:36AM +0800, Huacai Chen wrote:
> For 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.
>
> Cc: stable@vger.kernel.org
I believe Loongson 3 support was added in 3.15, so the following is
probably slightly better:
Cc: <stable@vger.kernel.org> # 3.15+
> diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
> index 81d6a15..7b242e8 100644
> --- a/arch/mips/mm/c-r4k.c
> +++ b/arch/mips/mm/c-r4k.c
> @@ -459,11 +459,28 @@ static void r4k_blast_scache_setup(void)
> r4k_blast_scache = blast_scache128;
> }
>
> +static void (* r4k_blast_scache_node)(long node);
Checkpatch objects to the space after '*'.
Other than those minor things this patch looks reasonable I think
Reviewed-by: James Hogan <jhogan@kernel.org>
Cheers
James
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/8] MIPS: Ensure pmd_present() returns false after pmd_mknotpresent()
2017-08-10 2:04 ` [PATCH 3/8] MIPS: Ensure pmd_present() returns false after pmd_mknotpresent() Huacai Chen
@ 2018-01-24 21:47 ` James Hogan
0 siblings, 0 replies; 13+ messages in thread
From: James Hogan @ 2018-01-24 21:47 UTC (permalink / raw)
To: Huacai Chen
Cc: Ralf Baechle, John Crispin, Steven J . Hill, linux-mips,
Fuxin Zhang, Zhangjin Wu, stable
[-- Attachment #1: Type: text/plain, Size: 1280 bytes --]
On Thu, Aug 10, 2017 at 10:04:37AM +0800, Huacai Chen wrote:
> This patch is borrowed from ARM64 to ensure pmd_present() returns false
I presume you're referring to commit 5bb1cc0ff9a6 ("arm64: Ensure
pmd_present() returns false after pmd_mknotpresent()"). I think it would
be worth mentioning that specifically.
> after pmd_mknotpresent(). This is needed for THP.
>
> Cc: stable@vger.kernel.org
Back to what version? 3.8 when THP was added?
Otherwise it looks reasonable:
Reviewed-by: James Hogan <jhogan@kernel.org>
Cheers
James
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> ---
> arch/mips/include/asm/pgtable-64.h | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
> index 67fe6dc..a2252c2 100644
> --- a/arch/mips/include/asm/pgtable-64.h
> +++ b/arch/mips/include/asm/pgtable-64.h
> @@ -271,6 +271,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;
> }
>
> --
> 2.7.0
>
>
>
>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 4/8] MIPS: Add __cpu_full_name[] to make CPU names more human-readable
2017-08-10 2:04 ` [PATCH 4/8] MIPS: Add __cpu_full_name[] to make CPU names more human-readable Huacai Chen
@ 2018-01-24 22:14 ` James Hogan
0 siblings, 0 replies; 13+ messages in thread
From: James Hogan @ 2018-01-24 22:14 UTC (permalink / raw)
To: Huacai Chen
Cc: Ralf Baechle, John Crispin, Steven J . Hill, linux-mips,
Fuxin Zhang, Zhangjin Wu
[-- Attachment #1: Type: text/plain, Size: 2098 bytes --]
On Thu, Aug 10, 2017 at 10:04:38AM +0800, Huacai Chen wrote:
> In /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).
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
> index 70604c7..3200c0e 100644
> --- a/arch/mips/kernel/proc.c
> +++ b/arch/mips/kernel/proc.c
> @@ -62,6 +63,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);
long line
> diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c
> index 1e8a955..6891780 100644
> --- a/arch/mips/loongson64/common/env.c
> +++ b/arch/mips/loongson64/common/env.c
> @@ -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));
long line
Otherwise this looks reasonable I think:
Reviewed-by: James Hogan <jhogan@kernel.org>
Cheers
James
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2018-01-24 22:14 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-10 2:00 [PATCH 0/8] MIPS: Loongson: new features and improvements Huacai Chen
2017-08-10 2:00 ` [PATCH 1/8] MIPS: Loongson-3: Enable Store Fill Buffer at runtime Huacai Chen
2018-01-24 20:54 ` James Hogan
2017-08-10 2:04 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 Huacai Chen
2017-08-10 2:04 ` [PATCH 3/8] MIPS: Ensure pmd_present() returns false after pmd_mknotpresent() Huacai Chen
2018-01-24 21:47 ` James Hogan
2017-08-10 2:04 ` [PATCH 4/8] MIPS: Add __cpu_full_name[] to make CPU names more human-readable Huacai Chen
2018-01-24 22:14 ` James Hogan
2017-08-10 2:04 ` [PATCH 5/8] MIPS: Align kernel load address to 64KB Huacai Chen
2017-08-10 2:04 ` [PATCH 6/8] MIPS: Loongson: Add kexec/kdump support Huacai Chen
2018-01-24 21:22 ` [PATCH 2/8] MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3 James Hogan
2017-08-10 2:15 ` [PATCH 7/8] MIPS: Loongson: Make CPUFreq usable " Huacai Chen
2017-08-10 2:15 ` [PATCH 8/8] MIPS: Loongson: Introduce and use WAR_LLSC_MB Huacai Chen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox