From 508c5757a72873d007e932faff5fa0014b25812d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 18 Sep 2017 13:38:40 +0200 Subject: MIPS: make thread_saved_pc static The only user of thread_saved_pc() in non-arch-specific code was removed in commit 8243d5597793 ("sched/core: Remove pointless printout in sched_show_task()"), so it no longer needs to be globally defined for MIPS and can be made static. Signed-off-by: Tobias Klauser Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/17303/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/processor.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/mips/include') diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 95b8c471f572..af34afbc32d9 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -368,8 +368,6 @@ struct task_struct; /* Free all resources held by a thread. */ #define release_thread(thread) do { } while(0) -extern unsigned long thread_saved_pc(struct task_struct *tsk); - /* * Do necessary setup to start up a newly executed thread. */ -- cgit v1.2.3-59-g8ed1b From 34ae9c915f9d12f1ddaa19a23fb3e8984e6a1098 Mon Sep 17 00:00:00 2001 From: Chad Reese Date: Fri, 15 Sep 2017 12:31:28 -0500 Subject: MIPS: Add nudges to writes for bit unlocks. Flushing the writes lets other CPUs waiting for the lock to get it sooner. Signed-off-by: Chad Reese Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/17289/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/bitops.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/include') diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index fa57cef12a46..da1b8718861e 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -456,6 +456,7 @@ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long * { smp_mb__before_llsc(); __clear_bit(nr, addr); + nudge_writes(); } /* -- cgit v1.2.3-59-g8ed1b From 7820b84be844d8d863122b1323f2a4bc2441b783 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 28 Sep 2017 12:34:04 -0500 Subject: MIPS: Allow __cpu_number_map to be larger than NR_CPUS In systems where the CPU id space is sparse, this allows a smaller NR_CPUS to be chosen, thus keeping internal data structures smaller. Signed-off-by: David Daney Signed-off-by: Carlos Munoz Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/17388/ [jhogan@kernel.org: Add depends on SMP to fix "warning: symbol value '' invalid for MIPS_NR_CPU_NR_MAP"] Signed-off-by: James Hogan --- arch/mips/Kconfig | 12 +++++++++++- arch/mips/include/asm/smp.h | 2 +- arch/mips/kernel/smp.c | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'arch/mips/include') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index cb7fcc4216fd..b6af63fb8544 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -915,7 +915,8 @@ config CAVIUM_OCTEON_SOC select USE_OF select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_SMP - select NR_CPUS_DEFAULT_16 + select NR_CPUS_DEFAULT_64 + select MIPS_NR_CPU_NR_MAP_1024 select BUILTIN_DTB select MTD_COMPLEX_MAPPINGS select SYS_SUPPORTS_RELOCATABLE @@ -2725,6 +2726,15 @@ config NR_CPUS config MIPS_PERF_SHARED_TC_COUNTERS bool +config MIPS_NR_CPU_NR_MAP_1024 + bool + +config MIPS_NR_CPU_NR_MAP + int + depends on SMP + default 1024 if MIPS_NR_CPU_NR_MAP_1024 + default NR_CPUS if !MIPS_NR_CPU_NR_MAP_1024 + # # Timer Interrupt Frequency Configuration # diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 9e494f8d9c03..88ebd83b3bf9 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -29,7 +29,7 @@ extern cpumask_t cpu_foreign_map[]; /* Map from cpu id to sequential logical cpu number. This will only not be idempotent when cpus failed to come on-line. */ -extern int __cpu_number_map[NR_CPUS]; +extern int __cpu_number_map[CONFIG_MIPS_NR_CPU_NR_MAP]; #define cpu_number_map(cpu) __cpu_number_map[cpu] /* The reverse map from sequential logical cpu number to cpu id. */ diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index bbe19b64def5..5576888e4a2a 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -48,7 +48,7 @@ #include #include -int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ +int __cpu_number_map[CONFIG_MIPS_NR_CPU_NR_MAP]; /* Map physical to logical */ EXPORT_SYMBOL(__cpu_number_map); int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ -- cgit v1.2.3-59-g8ed1b From edf188bee1d908ea8181d2067ddaeefab9264688 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 28 Sep 2017 12:34:05 -0500 Subject: MIPS: Octeon: Remove usage of cvmx_wait() everywhere. Signed-off-by: Steven J. Hill Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/17389/ Signed-off-by: James Hogan --- arch/mips/cavium-octeon/executive/cvmx-helper.c | 2 +- arch/mips/cavium-octeon/executive/cvmx-spi.c | 10 +++++----- arch/mips/include/asm/octeon/cvmx-fpa.h | 4 +++- arch/mips/include/asm/octeon/cvmx.h | 15 ++------------- arch/mips/pci/pcie-octeon.c | 12 ++++++------ 5 files changed, 17 insertions(+), 26 deletions(-) (limited to 'arch/mips/include') diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c index f24be0b5db50..75108ec669eb 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c @@ -862,7 +862,7 @@ int __cvmx_helper_errata_fix_ipd_ptr_alignment(void) */ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0); - cvmx_wait(100000000ull); + __delay(100000000ull); for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) { retry_cnt = 100000; diff --git a/arch/mips/cavium-octeon/executive/cvmx-spi.c b/arch/mips/cavium-octeon/executive/cvmx-spi.c index 459e3b1eb61f..f51957a3e915 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-spi.c +++ b/arch/mips/cavium-octeon/executive/cvmx-spi.c @@ -215,7 +215,7 @@ int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode) spxx_clk_ctl.u64 = 0; spxx_clk_ctl.s.runbist = 1; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); - cvmx_wait(10 * MS); + __delay(10 * MS); spxx_bist_stat.u64 = cvmx_read_csr(CVMX_SPXX_BIST_STAT(interface)); if (spxx_bist_stat.s.stat0) cvmx_dprintf @@ -265,14 +265,14 @@ int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode) spxx_clk_ctl.s.rcvtrn = 0; spxx_clk_ctl.s.srxdlck = 0; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); - cvmx_wait(100 * MS); + __delay(100 * MS); /* Reset SRX0 DLL */ spxx_clk_ctl.s.srxdlck = 1; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); /* Waiting for Inf0 Spi4 RX DLL to lock */ - cvmx_wait(100 * MS); + __delay(100 * MS); /* Enable dynamic alignment */ spxx_trn4_ctl.s.trntest = 0; @@ -527,7 +527,7 @@ int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, int timeout) spxx_clk_ctl.s.rcvtrn = 1; spxx_clk_ctl.s.srxdlck = 1; cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64); - cvmx_wait(1000 * MS); + __delay(1000 * MS); /* SRX0 clear the boot bit */ spxx_trn4_ctl.u64 = cvmx_read_csr(CVMX_SPXX_TRN4_CTL(interface)); @@ -536,7 +536,7 @@ int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, int timeout) /* Wait for the training sequence to complete */ cvmx_dprintf("SPI%d: Waiting for training\n", interface); - cvmx_wait(1000 * MS); + __delay(1000 * MS); /* Wait a really long time here */ timeout_time = cvmx_get_cycle() + 1000ull * MS * 600; /* diff --git a/arch/mips/include/asm/octeon/cvmx-fpa.h b/arch/mips/include/asm/octeon/cvmx-fpa.h index c00501d0f7ae..29ae63606ab4 100644 --- a/arch/mips/include/asm/octeon/cvmx-fpa.h +++ b/arch/mips/include/asm/octeon/cvmx-fpa.h @@ -36,6 +36,8 @@ #ifndef __CVMX_FPA_H__ #define __CVMX_FPA_H__ +#include + #include #include @@ -165,7 +167,7 @@ static inline void cvmx_fpa_enable(void) } /* Enforce a 10 cycle delay between config and enable */ - cvmx_wait(10); + __delay(10); } /* FIXME: CVMX_FPA_CTL_STATUS read is unmodelled */ diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h index 205ab2ce10f8..25854abc95f8 100644 --- a/arch/mips/include/asm/octeon/cvmx.h +++ b/arch/mips/include/asm/octeon/cvmx.h @@ -30,6 +30,7 @@ #include #include +#include enum cvmx_mips_space { CVMX_MIPS_SPACE_XKSEG = 3LL, @@ -428,18 +429,6 @@ static inline uint64_t cvmx_get_cycle(void) return cycle; } -/** - * Wait for the specified number of cycle - * - */ -static inline void cvmx_wait(uint64_t cycles) -{ - uint64_t done = cvmx_get_cycle() + cycles; - - while (cvmx_get_cycle() < done) - ; /* Spin */ -} - /** * Reads a chip global cycle counter. This counts CPU cycles since * chip reset. The counter is 64 bit. @@ -481,7 +470,7 @@ static inline uint64_t cvmx_get_cycle_global(void) result = -1; \ break; \ } else \ - cvmx_wait(100); \ + __delay(100); \ } \ } while (0); \ result; \ diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index fd2887415bc8..87ba86bd8696 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c @@ -639,7 +639,7 @@ static int __cvmx_pcie_rc_initialize_link_gen1(int pcie_port) cvmx_dprintf("PCIe: Port %d link timeout\n", pcie_port); return -1; } - cvmx_wait(10000); + __delay(10000); pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); } while (pciercx_cfg032.s.dlla == 0); @@ -821,7 +821,7 @@ retry: * don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a * fixed number of cycles. */ - cvmx_wait(400000); + __delay(400000); /* * PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of @@ -1018,7 +1018,7 @@ retry: i = in_p_offset; while (i--) { cvmx_write64_uint32(write_address, 0); - cvmx_wait(10000); + __delay(10000); } /* @@ -1034,7 +1034,7 @@ retry: dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); old_in_fif_p_count = dbg_data.s.data & 0xff; cvmx_write64_uint32(write_address, 0); - cvmx_wait(10000); + __delay(10000); dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); in_fif_p_count = dbg_data.s.data & 0xff; } while (in_fif_p_count != ((old_in_fif_p_count+1) & 0xff)); @@ -1053,7 +1053,7 @@ retry: cvmx_dprintf("PCIe: Port %d aligning TLP counters as workaround to maintain ordering\n", pcie_port); while (in_fif_p_count != 0) { cvmx_write64_uint32(write_address, 0); - cvmx_wait(10000); + __delay(10000); in_fif_p_count = (in_fif_p_count + 1) & 0xff; } /* @@ -1105,7 +1105,7 @@ static int __cvmx_pcie_rc_initialize_link_gen2(int pcie_port) do { if (cvmx_get_cycle() - start_cycle > octeon_get_clock_rate()) return -1; - cvmx_wait(10000); + __delay(10000); pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); } while ((pciercx_cfg032.s.dlla == 0) || (pciercx_cfg032.s.lt == 1)); -- cgit v1.2.3-59-g8ed1b From d3a0b968186a7e197b7551e4d6080676372152ce Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 29 Sep 2017 16:26:31 +0100 Subject: MIPS: Use SLL by 0 for 32-bit truncation in `__read_64bit_c0_split' Optimize `__read_64bit_c0_split' and reduce the instruction count by 1, observing that a DSLL/DSRA pair by 32, is equivalent to SLL by 0, which architecturally truncates the value requested to 32 bits on 64-bit MIPS hardware regardless of whether the input operand is or is not a properly sign-extended 32-bit value. Signed-off-by: Maciej W. Rozycki Reviewed-by: James Hogan Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/17399/ Signed-off-by: James Hogan --- arch/mips/include/asm/mipsregs.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'arch/mips/include') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index a6810923b3f0..6b1f1ad0542c 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1355,19 +1355,17 @@ do { \ if (sel == 0) \ __asm__ __volatile__( \ ".set\tmips64\n\t" \ - "dmfc0\t%M0, " #source "\n\t" \ - "dsll\t%L0, %M0, 32\n\t" \ - "dsra\t%M0, %M0, 32\n\t" \ - "dsra\t%L0, %L0, 32\n\t" \ + "dmfc0\t%L0, " #source "\n\t" \ + "dsra\t%M0, %L0, 32\n\t" \ + "sll\t%L0, %L0, 0\n\t" \ ".set\tmips0" \ : "=r" (__val)); \ else \ __asm__ __volatile__( \ ".set\tmips64\n\t" \ - "dmfc0\t%M0, " #source ", " #sel "\n\t" \ - "dsll\t%L0, %M0, 32\n\t" \ - "dsra\t%M0, %M0, 32\n\t" \ - "dsra\t%L0, %L0, 32\n\t" \ + "dmfc0\t%L0, " #source ", " #sel "\n\t" \ + "dsra\t%M0, %L0, 32\n\t" \ + "sll\t%L0, %L0, 0\n\t" \ ".set\tmips0" \ : "=r" (__val)); \ local_irq_restore(__flags); \ -- cgit v1.2.3-59-g8ed1b From 37d15948eb72533757ff352cf6f92dc64daa291f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 9 Mar 2017 13:11:49 -0800 Subject: MIPS: page.h: Define virt_to_pfn() Define virt_to_pfn() based on the existing definition of virt_to_page() which already does a PFN_DOWN(vir_to_phys(kaddr)). Signed-off-by: Florian Fainelli Cc: Ralf Baechle Cc: Paul Burton Cc: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15409/ Signed-off-by: James Hogan --- arch/mips/include/asm/page.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/include') diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index 5f987598054f..ad461216b5a1 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -240,8 +240,8 @@ static inline int pfn_valid(unsigned long pfn) #endif -#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(virt_to_phys((void *) \ - (kaddr)))) +#define virt_to_pfn(kaddr) PFN_DOWN(virt_to_phys((void *)(kaddr))) +#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr)) extern int __virt_addr_valid(const volatile void *kaddr); #define virt_addr_valid(kaddr) \ -- cgit v1.2.3-59-g8ed1b From 22b8ba765a726d90e9830ff6134c32b04f12c10f Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 3 Jul 2017 23:41:47 +0100 Subject: MIPS: Fix MIPS64 FP save/restore on 32-bit kernels 32-bit kernels can be configured to support MIPS64, in which case neither CONFIG_64BIT or CONFIG_CPU_MIPS32_R* will be set. This causes the CP0_Status.FR checks at the point of floating point register save and restore to be compiled out, which results in odd FP registers not being saved or restored to the task or signal context even when CP0_Status.FR is set. Fix the ifdefs to use CONFIG_CPU_MIPSR2 and CONFIG_CPU_MIPSR6, which are enabled for the relevant revisions of either MIPS32 or MIPS64, along with some other CPUs such as Octeon (r2), Loongson1 (r2), XLP (r2), Loongson 3A R2. The suspect code originates from commit 597ce1723e0f ("MIPS: Support for 64-bit FP with O32 binaries") in v3.14, however the code in __enable_fpu() was consistent and refused to set FR=1, falling back to software FPU emulation. This was suboptimal but should be functionally correct. Commit fcc53b5f6c38 ("MIPS: fpu.h: Allow 64-bit FPU on a 64-bit MIPS R6 CPU") in v4.2 (and stable tagged back to 4.0) later introduced the bug by updating __enable_fpu() to set FR=1 but failing to update the other similar ifdefs to enable FR=1 state handling. Fixes: fcc53b5f6c38 ("MIPS: fpu.h: Allow 64-bit FPU on a 64-bit MIPS R6 CPU") Signed-off-by: James Hogan Cc: Ralf Baechle Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: # 4.0+ Patchwork: https://patchwork.linux-mips.org/patch/16739/ --- arch/mips/include/asm/asmmacro.h | 8 ++++---- arch/mips/kernel/r4k_fpu.S | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'arch/mips/include') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 83054f79f72a..b815d7b3bd27 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -126,8 +126,8 @@ .endm .macro fpu_save_double thread status tmp -#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ - defined(CONFIG_CPU_MIPS32_R6) +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ + defined(CONFIG_CPU_MIPSR6) sll \tmp, \status, 5 bgez \tmp, 10f fpu_save_16odd \thread @@ -184,8 +184,8 @@ .endm .macro fpu_restore_double thread status tmp -#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ - defined(CONFIG_CPU_MIPS32_R6) +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ + defined(CONFIG_CPU_MIPSR6) sll \tmp, \status, 5 bgez \tmp, 10f # 16 register mode? diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index 0a83b1708b3c..8e3a6020c613 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -40,8 +40,8 @@ */ LEAF(_save_fp) EXPORT_SYMBOL(_save_fp) -#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ - defined(CONFIG_CPU_MIPS32_R6) +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ + defined(CONFIG_CPU_MIPSR6) mfc0 t0, CP0_STATUS #endif fpu_save_double a0 t0 t1 # clobbers t1 @@ -52,8 +52,8 @@ EXPORT_SYMBOL(_save_fp) * Restore a thread's fp context. */ LEAF(_restore_fp) -#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ - defined(CONFIG_CPU_MIPS32_R6) +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ + defined(CONFIG_CPU_MIPSR6) mfc0 t0, CP0_STATUS #endif fpu_restore_double a0 t0 t1 # clobbers t1 @@ -246,11 +246,11 @@ LEAF(_save_fp_context) cfc1 t1, fcr31 .set pop -#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ - defined(CONFIG_CPU_MIPS32_R6) +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ + defined(CONFIG_CPU_MIPSR6) .set push SET_HARDFLOAT -#ifdef CONFIG_CPU_MIPS32_R2 +#ifdef CONFIG_CPU_MIPSR2 .set mips32r2 .set fp=64 mfc0 t0, CP0_STATUS @@ -314,11 +314,11 @@ LEAF(_save_fp_context) LEAF(_restore_fp_context) EX lw t1, 0(a1) -#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ - defined(CONFIG_CPU_MIPS32_R6) +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPSR2) || \ + defined(CONFIG_CPU_MIPSR6) .set push SET_HARDFLOAT -#ifdef CONFIG_CPU_MIPS32_R2 +#ifdef CONFIG_CPU_MIPSR2 .set mips32r2 .set fp=64 mfc0 t0, CP0_STATUS -- cgit v1.2.3-59-g8ed1b From de8cd0dc834f2294bcf20240ea037c3864bc4f9a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 11 Aug 2017 21:56:52 +0100 Subject: MIPS/ptrace: Update syscall nr on register changes Update the thread_info::syscall field when registers are modified via ptrace to change or cancel the system call being entered. This is important to allow seccomp and the syscall entry and exit trace events to observe the new syscall number changed by the normal ptrace hook or seccomp. That includes allowing seccomp's recheck of the system call number after SECCOMP_RET_TRACE to notice if the syscall is changed to a denied one, which happens in seccomp since commit ce6526e8afa4 ("seccomp: recheck the syscall after RET_TRACE") in v4.8. In the process of doing this, the logic to determine whether an indirect system call is in progress (i.e. the O32 ABI's syscall()) is abstracted into mips_syscall_is_indirect(), and a new mips_syscall_update_nr() is used to update the thread_info::syscall based on the register state. The following ptrace operations are updated: - PTRACE_SETREGS (ptrace_setregs()). - PTRACE_SETREGSET with NT_PRSTATUS (gpr32_set() and gpr64_set()). - PTRACE_POKEUSR with 2/v0 or 4/a0 for indirect syscall ([compat_]arch_ptrace()). Fixes: c2d9f1775731 ("MIPS: Fix syscall_get_nr for the syscall exit tracing.") Signed-off-by: James Hogan Cc: Ralf Baechle Cc: Lars Persson Cc: Oleg Nesterov Cc: Kees Cook Cc: Andy Lutomirski Cc: Will Drewry Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/16995/ --- arch/mips/include/asm/syscall.h | 29 +++++++++++++++++++++++++---- arch/mips/kernel/ptrace.c | 15 +++++++++++++++ arch/mips/kernel/ptrace32.c | 7 +++++++ 3 files changed, 47 insertions(+), 4 deletions(-) (limited to 'arch/mips/include') diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h index 7c713025b23f..0170602a1e4e 100644 --- a/arch/mips/include/asm/syscall.h +++ b/arch/mips/include/asm/syscall.h @@ -26,12 +26,34 @@ #define __NR_syscall 4000 #endif +static inline bool mips_syscall_is_indirect(struct task_struct *task, + struct pt_regs *regs) +{ + /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */ + return (IS_ENABLED(CONFIG_32BIT) || + test_tsk_thread_flag(task, TIF_32BIT_REGS)) && + (regs->regs[2] == __NR_syscall); +} + static inline long syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { return current_thread_info()->syscall; } +static inline void mips_syscall_update_nr(struct task_struct *task, + struct pt_regs *regs) +{ + /* + * v0 is the system call number, except for O32 ABI syscall(), where it + * ends up in a0. + */ + if (mips_syscall_is_indirect(task, regs)) + task_thread_info(task)->syscall = regs->regs[4]; + else + task_thread_info(task)->syscall = regs->regs[2]; +} + static inline unsigned long mips_get_syscall_arg(unsigned long *arg, struct task_struct *task, struct pt_regs *regs, unsigned int n) { @@ -98,10 +120,9 @@ static inline void syscall_get_arguments(struct task_struct *task, unsigned long *args) { int ret; - /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */ - if ((IS_ENABLED(CONFIG_32BIT) || - test_tsk_thread_flag(task, TIF_32BIT_REGS)) && - (regs->regs[2] == __NR_syscall)) + + /* O32 ABI syscall() */ + if (mips_syscall_is_indirect(task, regs)) i++; while (n--) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 011993e0cce2..efbd8df8b665 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -144,6 +144,9 @@ int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data) /* badvaddr, status, and cause may not be written. */ + /* System call number may have been changed */ + mips_syscall_update_nr(child, regs); + return 0; } @@ -345,6 +348,9 @@ static int gpr32_set(struct task_struct *target, } } + /* System call number may have been changed */ + mips_syscall_update_nr(target, regs); + return 0; } @@ -405,6 +411,9 @@ static int gpr64_set(struct task_struct *target, } } + /* System call number may have been changed */ + mips_syscall_update_nr(target, regs); + return 0; } @@ -770,6 +779,12 @@ long arch_ptrace(struct task_struct *child, long request, switch (addr) { case 0 ... 31: regs->regs[addr] = data; + /* System call number may have been changed */ + if (addr == 2) + mips_syscall_update_nr(child, regs); + else if (addr == 4 && + mips_syscall_is_indirect(child, regs)) + mips_syscall_update_nr(child, regs); break; case FPR_BASE ... FPR_BASE + 31: { union fpureg *fregs = get_fpu_regs(child); diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 40e212d6b26b..2b9260f92ccd 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -195,6 +196,12 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, switch (addr) { case 0 ... 31: regs->regs[addr] = data; + /* System call number may have been changed */ + if (addr == 2) + mips_syscall_update_nr(child, regs); + else if (addr == 4 && + mips_syscall_is_indirect(child, regs)) + mips_syscall_update_nr(child, regs); break; case FPR_BASE ... FPR_BASE + 31: { union fpureg *fregs = get_fpu_regs(child); -- cgit v1.2.3-59-g8ed1b From c7fd89a6407ea3a44a2a2fa12d290162c42499c4 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 10 Nov 2017 11:46:54 +0000 Subject: MIPS: Fix odd fp register warnings with MIPS64r2 Building 32-bit MIPS64r2 kernels produces warnings like the following on certain toolchains (such as GNU assembler 2.24.90, but not GNU assembler 2.28.51) since commit 22b8ba765a72 ("MIPS: Fix MIPS64 FP save/restore on 32-bit kernels"), due to the exposure of fpu_save_16odd from fpu_save_double and fpu_restore_16odd from fpu_restore_double: arch/mips/kernel/r4k_fpu.S:47: Warning: float register should be even, was 1 ... arch/mips/kernel/r4k_fpu.S:59: Warning: float register should be even, was 1 ... This appears to be because .set mips64r2 does not change the FPU ABI to 64-bit when -march=mips64r2 (or e.g. -march=xlp) is provided on the command line on that toolchain, from the default FPU ABI of 32-bit due to the -mabi=32. This makes access to the odd FPU registers invalid. Fix by explicitly changing the FPU ABI with .set fp=64 directives in fpu_save_16odd and fpu_restore_16odd, and moving the undefine of fp up in asmmacro.h so fp doesn't turn into $30. Fixes: 22b8ba765a72 ("MIPS: Fix MIPS64 FP save/restore on 32-bit kernels") Signed-off-by: James Hogan Cc: Ralf Baechle Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: # 4.0+: 22b8ba765a72: MIPS: Fix MIPS64 FP save/restore on 32-bit kernels Cc: # 4.0+ Patchwork: https://patchwork.linux-mips.org/patch/17656/ --- arch/mips/include/asm/asmmacro.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/mips/include') diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index b815d7b3bd27..feb069cbf44e 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -19,6 +19,9 @@ #include #endif +/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */ +#undef fp + /* * Helper macros for generating raw instruction encodings. */ @@ -105,6 +108,7 @@ .macro fpu_save_16odd thread .set push .set mips64r2 + .set fp=64 SET_HARDFLOAT sdc1 $f1, THREAD_FPR1(\thread) sdc1 $f3, THREAD_FPR3(\thread) @@ -163,6 +167,7 @@ .macro fpu_restore_16odd thread .set push .set mips64r2 + .set fp=64 SET_HARDFLOAT ldc1 $f1, THREAD_FPR1(\thread) ldc1 $f3, THREAD_FPR3(\thread) @@ -234,9 +239,6 @@ .endm #ifdef TOOLCHAIN_SUPPORTS_MSA -/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */ -#undef fp - .macro _cfcmsa rd, cs .set push .set mips32r2 -- cgit v1.2.3-59-g8ed1b From a3f143106596d739e7fbc4b84c96b1475247d876 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 4 Oct 2017 03:46:14 +0100 Subject: MIPS: cmpxchg64() and HAVE_VIRT_CPU_ACCOUNTING_GEN don't work for 32-bit SMP __cmpxchg64_local_generic() is atomic only w.r.t tasks and interrupts on the same CPU (that's what the 'local' means). We can't use it to implement cmpxchg64() in SMP configurations. So, for 32-bit SMP configurations: - Don't define cmpxchg64() - Don't enable HAVE_VIRT_CPU_ACCOUNTING_GEN, which requires it Fixes: e2093c7b03c1 ("MIPS: Fall back to generic implementation of ...") Fixes: bb877e96bea1 ("MIPS: Add support for full dynticks CPU time accounting") Signed-off-by: Ben Hutchings Cc: Ralf Baechle Cc: Deng-Cheng Zhu Cc: linux-mips@linux-mips.org Cc: # 4.1+ Patchwork: https://patchwork.linux-mips.org/patch/17413/ Signed-off-by: James Hogan --- arch/mips/Kconfig | 2 +- arch/mips/include/asm/cmpxchg.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/mips/include') diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 43411118dd4f..b09b644cd57c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -64,7 +64,7 @@ config MIPS select HAVE_PERF_EVENTS select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_SYSCALL_TRACEPOINTS - select HAVE_VIRT_CPU_ACCOUNTING_GEN + select HAVE_VIRT_CPU_ACCOUNTING_GEN if 64BIT || !SMP select IRQ_FORCED_THREADING select MODULES_USE_ELF_RELA if MODULES && 64BIT select MODULES_USE_ELF_REL if MODULES diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h index 903f3bf48419..ae2b4583b486 100644 --- a/arch/mips/include/asm/cmpxchg.h +++ b/arch/mips/include/asm/cmpxchg.h @@ -202,8 +202,10 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #else #include #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#ifndef CONFIG_SMP #define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n)) #endif +#endif #undef __scbeqz -- cgit v1.2.3-59-g8ed1b