From fe8bd18ffea5327344d4ec2bf11f47951212abd0 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Mon, 19 Dec 2016 14:20:56 +0000 Subject: MIPS: Introduce irq_stack Allocate a per-cpu irq stack for use within interrupt handlers. Also add a utility function on_irq_stack to determine if a given stack pointer is within the irq stack for that cpu. Signed-off-by: Matt Redfearn Acked-by: Jason A. Donenfeld Cc: Thomas Gleixner Cc: Paolo Bonzini Cc: Chris Metcalf Cc: Petr Mladek Cc: James Hogan Cc: Paul Burton Cc: Aaron Tomlin Cc: Andrew Morton Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14740/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/asm-offsets.c | 1 + arch/mips/kernel/irq.c | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 6080582a26d1..a7277698d328 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -102,6 +102,7 @@ void output_thread_info_defines(void) OFFSET(TI_REGS, thread_info, regs); DEFINE(_THREAD_SIZE, THREAD_SIZE); DEFINE(_THREAD_MASK, THREAD_MASK); + DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); BLANK(); } diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index f8f5836eb3c1..ba150c755fcc 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -25,6 +25,8 @@ #include #include +void *irq_stack[NR_CPUS]; + /* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves. @@ -58,6 +60,15 @@ void __init init_IRQ(void) clear_c0_status(ST0_IM); arch_init_irq(); + + for_each_possible_cpu(i) { + int irq_pages = IRQ_STACK_SIZE / PAGE_SIZE; + void *s = (void *)__get_free_pages(GFP_KERNEL, irq_pages); + + irq_stack[i] = s; + pr_debug("CPU%d IRQ stack at 0x%p - 0x%p\n", i, + irq_stack[i], irq_stack[i] + IRQ_STACK_SIZE); + } } #ifdef CONFIG_DEBUG_STACKOVERFLOW -- cgit v1.2.3 From d42d8d106b0275b027c1e8992c42aecf933436ea Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Mon, 19 Dec 2016 14:20:57 +0000 Subject: MIPS: Stack unwinding while on IRQ stack Within unwind stack, check if the stack pointer being unwound is within the CPU's irq_stack and if so use that page rather than the task's stack page. Signed-off-by: Matt Redfearn Acked-by: Jason A. Donenfeld Cc: Thomas Gleixner Cc: Adam Buchbinder Cc: Maciej W. Rozycki Cc: Marcin Nowakowski Cc: Chris Metcalf Cc: James Hogan Cc: Paul Burton Cc: Jiri Slaby Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14741/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 5142b1dfe8a7..48e30e0469ef 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -511,7 +512,19 @@ EXPORT_SYMBOL(unwind_stack_by_address); unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, unsigned long pc, unsigned long *ra) { - unsigned long stack_page = (unsigned long)task_stack_page(task); + unsigned long stack_page = 0; + int cpu; + + for_each_possible_cpu(cpu) { + if (on_irq_stack(cpu, *sp)) { + stack_page = (unsigned long)irq_stack[cpu]; + break; + } + } + + if (!stack_page) + stack_page = (unsigned long)task_stack_page(task); + return unwind_stack_by_address(stack_page, sp, pc, ra); } #endif -- cgit v1.2.3 From dda45f701c9d7ad4ac0bb446e3a96f6df9a468d9 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Mon, 19 Dec 2016 14:20:59 +0000 Subject: MIPS: Switch to the irq_stack in interrupts When enterring interrupt context via handle_int or except_vec_vi, switch to the irq_stack of the current CPU if it is not already in use. The current stack pointer is masked with the thread size and compared to the base or the irq stack. If it does not match then the stack pointer is set to the top of that stack, otherwise this is a nested irq being handled on the irq stack so the stack pointer should be left as it was. The in-use stack pointer is placed in the callee saved register s1. It will be saved to the stack when plat_irq_dispatch is invoked and can be restored once control returns here. Signed-off-by: Matt Redfearn Acked-by: Jason A. Donenfeld Cc: Thomas Gleixner Cc: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14743/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/genex.S | 81 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index dc0b29612891..0a7ba4b2f687 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -187,9 +187,44 @@ NESTED(handle_int, PT_SIZE, sp) LONG_L s0, TI_REGS($28) LONG_S sp, TI_REGS($28) - PTR_LA ra, ret_from_irq - PTR_LA v0, plat_irq_dispatch - jr v0 + + /* + * SAVE_ALL ensures we are using a valid kernel stack for the thread. + * Check if we are already using the IRQ stack. + */ + move s1, sp # Preserve the sp + + /* Get IRQ stack for this CPU */ + ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG +#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) + lui k1, %hi(irq_stack) +#else + lui k1, %highest(irq_stack) + daddiu k1, %higher(irq_stack) + dsll k1, 16 + daddiu k1, %hi(irq_stack) + dsll k1, 16 +#endif + LONG_SRL k0, SMP_CPUID_PTRSHIFT + LONG_ADDU k1, k0 + LONG_L t0, %lo(irq_stack)(k1) + + # Check if already on IRQ stack + PTR_LI t1, ~(_THREAD_SIZE-1) + and t1, t1, sp + beq t0, t1, 2f + + /* Switch to IRQ stack */ + li t1, _IRQ_STACK_SIZE + PTR_ADD sp, t0, t1 + +2: + jal plat_irq_dispatch + + /* Restore sp */ + move sp, s1 + + j ret_from_irq #ifdef CONFIG_CPU_MICROMIPS nop #endif @@ -262,8 +297,44 @@ NESTED(except_vec_vi_handler, 0, sp) LONG_L s0, TI_REGS($28) LONG_S sp, TI_REGS($28) - PTR_LA ra, ret_from_irq - jr v0 + + /* + * SAVE_ALL ensures we are using a valid kernel stack for the thread. + * Check if we are already using the IRQ stack. + */ + move s1, sp # Preserve the sp + + /* Get IRQ stack for this CPU */ + ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG +#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) + lui k1, %hi(irq_stack) +#else + lui k1, %highest(irq_stack) + daddiu k1, %higher(irq_stack) + dsll k1, 16 + daddiu k1, %hi(irq_stack) + dsll k1, 16 +#endif + LONG_SRL k0, SMP_CPUID_PTRSHIFT + LONG_ADDU k1, k0 + LONG_L t0, %lo(irq_stack)(k1) + + # Check if already on IRQ stack + PTR_LI t1, ~(_THREAD_SIZE-1) + and t1, t1, sp + beq t0, t1, 2f + + /* Switch to IRQ stack */ + li t1, _IRQ_STACK_SIZE + PTR_ADD sp, t0, t1 + +2: + jal plat_irq_dispatch + + /* Restore sp */ + move sp, s1 + + j ret_from_irq END(except_vec_vi_handler) /* -- cgit v1.2.3 From 8cc709d7d4f013f51d38ceb2e3c8c82d230cf457 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Fri, 9 Dec 2016 02:36:22 -0600 Subject: MIPS: Relocatable: Provide plat_post_relocation hook This hook provides the platform the chance to perform any required setup before the boot processor switches to the relocated kernel. The relocated kernel has been copied and fixed up ready for execution at this point. Secondary CPUs may wish to switch to it early. There is also the opportunity for the platform to abort jumping to the relocated kernel if there is anything wrong with the chosen offset. Signed-off-by: Matt Redfearn Signed-off-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14651/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/relocate.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index 1958910b75c0..c82288569eb1 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -31,6 +31,17 @@ extern u32 _relocation_end[]; /* End relocation table */ extern long __start___ex_table; /* Start exception table */ extern long __stop___ex_table; /* End exception table */ +/* + * This function may be defined for a platform to perform any post-relocation + * fixup necessary. + * Return non-zero to abort relocation + */ +int __weak plat_post_relocation(long offset) +{ + return 0; +} + + static inline u32 __init get_synci_step(void) { u32 res; @@ -338,6 +349,15 @@ void *__init relocate_kernel(void) */ memcpy(RELOCATED(&__bss_start), &__bss_start, bss_length); + /* + * Last chance for the platform to abort relocation. + * This may also be used by the platform to perform any + * initialisation required now that the new kernel is + * resident in memory and ready to be executed. + */ + if (plat_post_relocation(offset)) + goto out; + /* The current thread is now within the relocated image */ __current_thread_info = RELOCATED(&init_thread_union); -- cgit v1.2.3 From 3f00f4d8f083bc61005d0a1ef592b149f5c88bbd Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 11:52:19 +0000 Subject: MIPS: Ensure bss section ends on a long-aligned address When clearing the .bss section in kernel_entry we do so using LONG_S instructions, and branch whilst the current write address doesn't equal the end of the .bss section minus the size of a long integer. The .bss section always begins at a long-aligned address and we always increment the write pointer by the size of a long integer - we therefore rely upon the .bss section ending at a long-aligned address. If this is not the case then the long-aligned write address can never be equal to the non-long-aligned end address & we will continue to increment past the end of the .bss section, attempting to zero the rest of memory. Despite this requirement that .bss end at a long-aligned address we pass 0 as the end alignment requirement to the BSS_SECTION macro and thus don't guarantee any particular alignment, allowing us to hit the error condition described above. Fix this by instead passing 8 bytes as the end alignment argument to the BSS_SECTION macro, ensuring that the end of the .bss section is always at least long-aligned. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14526/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/vmlinux.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index d5de67591735..f0a0e6d62be3 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -182,7 +182,7 @@ SECTIONS * Force .bss to 64K alignment so that .bss..swapper_pg_dir * gets that alignment. .sbss should be empty, so there will be * no holes after __init_end. */ - BSS_SECTION(0, 0x10000, 0) + BSS_SECTION(0, 0x10000, 8) _end = . ; -- cgit v1.2.3 From ccaf7caf2c73c6db920772bf08bf1d47b2170634 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 15:07:02 +0000 Subject: MIPS: Clear ISA bit correctly in get_frame_info() get_frame_info() can be called in microMIPS kernels with the ISA bit already clear. For example this happens when unwind_stack_by_address() is called because we begin with a PC that has the ISA bit set & subtract the (odd) offset from the preceding symbol (which does not have the ISA bit set). Since get_frame_info() unconditionally subtracts 1 from the PC in microMIPS kernels it incorrectly misaligns the address it then attempts to access code at, leading to an address error exception. Fix this by using msk_isa16_mode() to clear the ISA bit, which allows get_frame_info() to function regardless of whether it is provided with a PC that has the ISA bit set or not. Signed-off-by: Paul Burton Fixes: 34c2f668d0f6 ("MIPS: microMIPS: Add unaligned access support.") Cc: Leonid Yegoshin Cc: linux-mips@linux-mips.org Cc: # v3.10+ Patchwork: https://patchwork.linux-mips.org/patch/14528/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 48e30e0469ef..213278dbbc04 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -304,17 +304,14 @@ static inline int is_sp_move_ins(union mips_instruction *ip) static int get_frame_info(struct mips_frame_info *info) { -#ifdef CONFIG_CPU_MICROMIPS - union mips_instruction *ip = (void *) (((char *) info->func) - 1); -#else - union mips_instruction *ip = info->func; -#endif + union mips_instruction *ip; unsigned max_insns = info->func_size / sizeof(union mips_instruction); unsigned i; info->pc_offset = -1; info->frame_size = 0; + ip = (void *)msk_isa16_mode((ulong)info->func); if (!ip) goto err; -- cgit v1.2.3 From a3552dace7d1d0cabf573e88fc3025cb90c4a601 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 15:07:03 +0000 Subject: MIPS: Prevent unaligned accesses during stack unwinding During stack unwinding we call a number of functions to determine what type of instruction we're looking at. The union mips_instruction pointer provided to them may be pointing at a 2 byte, but not 4 byte, aligned address & we thus cannot directly access the 4 byte wide members of the union mips_instruction. To avoid this is_ra_save_ins() copies the required half-words of the microMIPS instruction to a correctly aligned union mips_instruction on the stack, which it can then access safely. The is_jump_ins() & is_sp_move_ins() functions do not correctly perform this temporary copy, and instead attempt to directly dereference 4 byte fields which may be misaligned and lead to an address exception. Fix this by copying the instruction halfwords to a temporary union mips_instruction in get_frame_info() such that we can provide a 4 byte aligned union mips_instruction to the is_*_ins() functions and they do not need to deal with misalignment themselves. Signed-off-by: Paul Burton Fixes: 34c2f668d0f6 ("MIPS: microMIPS: Add unaligned access support.") Cc: Leonid Yegoshin Cc: linux-mips@linux-mips.org Cc: # v3.10+ Patchwork: https://patchwork.linux-mips.org/patch/14529/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 70 +++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 213278dbbc04..8dddaef1a345 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -199,8 +199,6 @@ struct mips_frame_info { static inline int is_ra_save_ins(union mips_instruction *ip) { #ifdef CONFIG_CPU_MICROMIPS - union mips_instruction mmi; - /* * swsp ra,offset * swm16 reglist,offset(sp) @@ -210,23 +208,20 @@ static inline int is_ra_save_ins(union mips_instruction *ip) * * microMIPS is way more fun... */ - if (mm_insn_16bit(ip->halfword[0])) { - mmi.word = (ip->halfword[0] << 16); - return (mmi.mm16_r5_format.opcode == mm_swsp16_op && - mmi.mm16_r5_format.rt == 31) || - (mmi.mm16_m_format.opcode == mm_pool16c_op && - mmi.mm16_m_format.func == mm_swm16_op); + if (mm_insn_16bit(ip->halfword[1])) { + return (ip->mm16_r5_format.opcode == mm_swsp16_op && + ip->mm16_r5_format.rt == 31) || + (ip->mm16_m_format.opcode == mm_pool16c_op && + ip->mm16_m_format.func == mm_swm16_op); } else { - mmi.halfword[0] = ip->halfword[1]; - mmi.halfword[1] = ip->halfword[0]; - return (mmi.mm_m_format.opcode == mm_pool32b_op && - mmi.mm_m_format.rd > 9 && - mmi.mm_m_format.base == 29 && - mmi.mm_m_format.func == mm_swm32_func) || - (mmi.i_format.opcode == mm_sw32_op && - mmi.i_format.rs == 29 && - mmi.i_format.rt == 31); + return (ip->mm_m_format.opcode == mm_pool32b_op && + ip->mm_m_format.rd > 9 && + ip->mm_m_format.base == 29 && + ip->mm_m_format.func == mm_swm32_func) || + (ip->i_format.opcode == mm_sw32_op && + ip->i_format.rs == 29 && + ip->i_format.rt == 31); } #else /* sw / sd $ra, offset($sp) */ @@ -247,12 +242,8 @@ static inline int is_jump_ins(union mips_instruction *ip) * * microMIPS is kind of more fun... */ - union mips_instruction mmi; - - mmi.word = (ip->halfword[0] << 16); - - if ((mmi.mm16_r5_format.opcode == mm_pool16c_op && - (mmi.mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) || + if ((ip->mm16_r5_format.opcode == mm_pool16c_op && + (ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) || ip->j_format.opcode == mm_jal32_op) return 1; if (ip->r_format.opcode != mm_pool32a_op || @@ -281,15 +272,13 @@ static inline int is_sp_move_ins(union mips_instruction *ip) * * microMIPS is not more fun... */ - if (mm_insn_16bit(ip->halfword[0])) { - union mips_instruction mmi; - - mmi.word = (ip->halfword[0] << 16); - return (mmi.mm16_r3_format.opcode == mm_pool16d_op && - mmi.mm16_r3_format.simmediate && mm_addiusp_func) || - (mmi.mm16_r5_format.opcode == mm_pool16d_op && - mmi.mm16_r5_format.rt == 29); + if (mm_insn_16bit(ip->halfword[1])) { + return (ip->mm16_r3_format.opcode == mm_pool16d_op && + ip->mm16_r3_format.simmediate && mm_addiusp_func) || + (ip->mm16_r5_format.opcode == mm_pool16d_op && + ip->mm16_r5_format.rt == 29); } + return ip->mm_i_format.opcode == mm_addiu32_op && ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29; #else @@ -304,7 +293,8 @@ static inline int is_sp_move_ins(union mips_instruction *ip) static int get_frame_info(struct mips_frame_info *info) { - union mips_instruction *ip; + bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS); + union mips_instruction insn, *ip; unsigned max_insns = info->func_size / sizeof(union mips_instruction); unsigned i; @@ -320,11 +310,21 @@ static int get_frame_info(struct mips_frame_info *info) max_insns = min(128U, max_insns); for (i = 0; i < max_insns; i++, ip++) { + if (is_mmips && mm_insn_16bit(ip->halfword[0])) { + insn.halfword[0] = 0; + insn.halfword[1] = ip->halfword[0]; + } else if (is_mmips) { + insn.halfword[0] = ip->halfword[1]; + insn.halfword[1] = ip->halfword[0]; + } else { + insn.word = ip->word; + } - if (is_jump_ins(ip)) + if (is_jump_ins(&insn)) break; + if (!info->frame_size) { - if (is_sp_move_ins(ip)) + if (is_sp_move_ins(&insn)) { #ifdef CONFIG_CPU_MICROMIPS if (mm_insn_16bit(ip->halfword[0])) @@ -347,7 +347,7 @@ static int get_frame_info(struct mips_frame_info *info) } continue; } - if (info->pc_offset == -1 && is_ra_save_ins(ip)) { + if (info->pc_offset == -1 && is_ra_save_ins(&insn)) { info->pc_offset = ip->i_format.simmediate / sizeof(long); break; -- cgit v1.2.3 From b6c7a324df37bf05ef7a2c1580683cf10d082d97 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 15:07:04 +0000 Subject: MIPS: Fix get_frame_info() handling of microMIPS function size get_frame_info() is meant to iterate over up to the first 128 instructions within a function, but for microMIPS kernels it will not reach that many instructions unless the function is 512 bytes long since we calculate the maximum number of instructions to check by dividing the function length by the 4 byte size of a union mips_instruction. In microMIPS kernels this won't do since instructions are variable length. Fix this by instead checking whether the pointer to the current instruction has reached the end of the function, and use max_insns as a simple constant to check the number of iterations against. Signed-off-by: Paul Burton Fixes: 34c2f668d0f6 ("MIPS: microMIPS: Add unaligned access support.") Cc: Leonid Yegoshin Cc: linux-mips@linux-mips.org Cc: # v3.10+ Patchwork: https://patchwork.linux-mips.org/patch/14530/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 8dddaef1a345..9f7a19ca1d4c 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -294,9 +294,9 @@ static inline int is_sp_move_ins(union mips_instruction *ip) static int get_frame_info(struct mips_frame_info *info) { bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS); - union mips_instruction insn, *ip; - unsigned max_insns = info->func_size / sizeof(union mips_instruction); - unsigned i; + union mips_instruction insn, *ip, *ip_end; + const unsigned int max_insns = 128; + unsigned int i; info->pc_offset = -1; info->frame_size = 0; @@ -305,11 +305,9 @@ static int get_frame_info(struct mips_frame_info *info) if (!ip) goto err; - if (max_insns == 0) - max_insns = 128U; /* unknown function size */ - max_insns = min(128U, max_insns); + ip_end = (void *)ip + info->func_size; - for (i = 0; i < max_insns; i++, ip++) { + for (i = 0; i < max_insns && ip < ip_end; i++, ip++) { if (is_mmips && mm_insn_16bit(ip->halfword[0])) { insn.halfword[0] = 0; insn.halfword[1] = ip->halfword[0]; -- cgit v1.2.3 From 67c75057709a6d85c681c78b9b2f9b71191f01a2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 15:07:05 +0000 Subject: MIPS: Fix is_jump_ins() handling of 16b microMIPS instructions is_jump_ins() checks 16b instruction fields without verifying that the instruction is indeed 16b, as is done by is_ra_save_ins() & is_sp_move_ins(). Add the appropriate check. Signed-off-by: Paul Burton Fixes: 34c2f668d0f6 ("MIPS: microMIPS: Add unaligned access support.") Cc: Leonid Yegoshin Cc: linux-mips@linux-mips.org Cc: # v3.10+ Patchwork: https://patchwork.linux-mips.org/patch/14531/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 9f7a19ca1d4c..e03113493580 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -242,9 +242,14 @@ static inline int is_jump_ins(union mips_instruction *ip) * * microMIPS is kind of more fun... */ - if ((ip->mm16_r5_format.opcode == mm_pool16c_op && - (ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) || - ip->j_format.opcode == mm_jal32_op) + if (mm_insn_16bit(ip->halfword[1])) { + if ((ip->mm16_r5_format.opcode == mm_pool16c_op && + (ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op)) + return 1; + return 0; + } + + if (ip->j_format.opcode == mm_jal32_op) return 1; if (ip->r_format.opcode != mm_pool32a_op || ip->r_format.func != mm_pool32axf_op) -- cgit v1.2.3 From bb9bc4689b9c635714fbcd5d335bad9934a7ebfc Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 15:07:06 +0000 Subject: MIPS: Calculate microMIPS ra properly when unwinding the stack get_frame_info() calculates the offset of the return address within a stack frame simply by dividing a the bottom 16 bits of the instruction, treated as a signed integer, by the size of a long. Whilst this works for MIPS32 & MIPS64 ISAs where the sw or sd instructions are used, it's incorrect for microMIPS where encodings differ. The result is that we typically completely fail to unwind the stack on microMIPS. Fix this by adjusting is_ra_save_ins() to calculate the return address offset, and take into account the various different encodings there in the same place as we consider whether an instruction is storing the ra/$31 register. With this we are now able to unwind the stack for kernels targetting the microMIPS ISA, for example we can produce: Call Trace: [<80109e1f>] show_stack+0x63/0x7c [<8011ea17>] __warn+0x9b/0xac [<8011ea45>] warn_slowpath_fmt+0x1d/0x20 [<8013fe53>] register_console+0x43/0x314 [<8067c58d>] of_setup_earlycon+0x1dd/0x1ec [<8067f63f>] early_init_dt_scan_chosen_stdout+0xe7/0xf8 [<8066c115>] do_early_param+0x75/0xac [<801302f9>] parse_args+0x1dd/0x308 [<8066c459>] parse_early_options+0x25/0x28 [<8066c48b>] parse_early_param+0x2f/0x38 [<8066e8cf>] setup_arch+0x113/0x488 [<8066c4f3>] start_kernel+0x57/0x328 ---[ end trace 0000000000000000 ]--- Whereas previously we only produced: Call Trace: [<80109e1f>] show_stack+0x63/0x7c ---[ end trace 0000000000000000 ]--- Signed-off-by: Paul Burton Fixes: 34c2f668d0f6 ("MIPS: microMIPS: Add unaligned access support.") Cc: Leonid Yegoshin Cc: linux-mips@linux-mips.org Cc: # v3.10+ Patchwork: https://patchwork.linux-mips.org/patch/14532/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 83 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 20 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index e03113493580..801b399d4861 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -196,7 +196,7 @@ struct mips_frame_info { #define J_TARGET(pc,target) \ (((unsigned long)(pc) & 0xf0000000) | ((target) << 2)) -static inline int is_ra_save_ins(union mips_instruction *ip) +static inline int is_ra_save_ins(union mips_instruction *ip, int *poff) { #ifdef CONFIG_CPU_MICROMIPS /* @@ -209,25 +209,70 @@ static inline int is_ra_save_ins(union mips_instruction *ip) * microMIPS is way more fun... */ if (mm_insn_16bit(ip->halfword[1])) { - return (ip->mm16_r5_format.opcode == mm_swsp16_op && - ip->mm16_r5_format.rt == 31) || - (ip->mm16_m_format.opcode == mm_pool16c_op && - ip->mm16_m_format.func == mm_swm16_op); + switch (ip->mm16_r5_format.opcode) { + case mm_swsp16_op: + if (ip->mm16_r5_format.rt != 31) + return 0; + + *poff = ip->mm16_r5_format.simmediate; + *poff = (*poff << 2) / sizeof(ulong); + return 1; + + case mm_pool16c_op: + switch (ip->mm16_m_format.func) { + case mm_swm16_op: + *poff = ip->mm16_m_format.imm; + *poff += 1 + ip->mm16_m_format.rlist; + *poff = (*poff << 2) / sizeof(ulong); + return 1; + + default: + return 0; + } + + default: + return 0; + } } - else { - return (ip->mm_m_format.opcode == mm_pool32b_op && - ip->mm_m_format.rd > 9 && - ip->mm_m_format.base == 29 && - ip->mm_m_format.func == mm_swm32_func) || - (ip->i_format.opcode == mm_sw32_op && - ip->i_format.rs == 29 && - ip->i_format.rt == 31); + + switch (ip->i_format.opcode) { + case mm_sw32_op: + if (ip->i_format.rs != 29) + return 0; + if (ip->i_format.rt != 31) + return 0; + + *poff = ip->i_format.simmediate / sizeof(ulong); + return 1; + + case mm_pool32b_op: + switch (ip->mm_m_format.func) { + case mm_swm32_func: + if (ip->mm_m_format.rd < 0x10) + return 0; + if (ip->mm_m_format.base != 29) + return 0; + + *poff = ip->mm_m_format.simmediate; + *poff += (ip->mm_m_format.rd & 0xf) * sizeof(u32); + *poff /= sizeof(ulong); + return 1; + default: + return 0; + } + + default: + return 0; } #else /* sw / sd $ra, offset($sp) */ - return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) && - ip->i_format.rs == 29 && - ip->i_format.rt == 31; + if ((ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) && + ip->i_format.rs == 29 && ip->i_format.rt == 31) { + *poff = ip->i_format.simmediate / sizeof(ulong); + return 1; + } + + return 0; #endif } @@ -350,11 +395,9 @@ static int get_frame_info(struct mips_frame_info *info) } continue; } - if (info->pc_offset == -1 && is_ra_save_ins(&insn)) { - info->pc_offset = - ip->i_format.simmediate / sizeof(long); + if (info->pc_offset == -1 && + is_ra_save_ins(&insn, &info->pc_offset)) break; - } } if (info->frame_size && info->pc_offset >= 0) /* nested */ return 0; -- cgit v1.2.3 From 096a0de427ea333f56f0ee00328cff2a2731bcf1 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 15:07:07 +0000 Subject: MIPS: Handle microMIPS jumps in the same way as MIPS32/MIPS64 jumps is_jump_ins() checks for plain jump ("j") instructions since commit e7438c4b893e ("MIPS: Fix sibling call handling in get_frame_info") but that commit didn't make the same change to the microMIPS code, leaving it inconsistent with the MIPS32/MIPS64 code. Handle the microMIPS encoding of the jump instruction too such that it behaves consistently. Signed-off-by: Paul Burton Fixes: e7438c4b893e ("MIPS: Fix sibling call handling in get_frame_info") Cc: Tony Wu Cc: linux-mips@linux-mips.org Cc: # v3.10+ Patchwork: https://patchwork.linux-mips.org/patch/14533/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 801b399d4861..efa1df52c616 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -294,6 +294,8 @@ static inline int is_jump_ins(union mips_instruction *ip) return 0; } + if (ip->j_format.opcode == mm_j32_op) + return 1; if (ip->j_format.opcode == mm_jal32_op) return 1; if (ip->r_format.opcode != mm_pool32a_op || -- cgit v1.2.3 From a00eeede507c975087b7b8df8cf2c9f88ba285de Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 4 Nov 2016 09:28:56 +0000 Subject: MIPS: SMP: Use a completion event to signal CPU up If a secondary CPU failed to start, for any reason, the CPU requesting the secondary to start would get stuck in the loop waiting for the secondary to be present in the cpu_callin_map. Rather than that, use a completion event to signal that the secondary CPU has started and is waiting to synchronise counters. Since the CPU presence will no longer be marked in cpu_callin_map, remove the redundant test from arch_cpu_idle_dead(). Signed-off-by: Matt Redfearn Cc: Maciej W. Rozycki Cc: Jiri Slaby Cc: Paul Gortmaker Cc: Chris Metcalf Cc: Thomas Gleixner Cc: Qais Yousef Cc: James Hogan Cc: Paul Burton Cc: Marcin Nowakowski Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14502/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/process.c | 4 +--- arch/mips/kernel/smp.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index efa1df52c616..3da0161bdf84 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -50,9 +50,7 @@ #ifdef CONFIG_HOTPLUG_CPU void arch_cpu_idle_dead(void) { - /* What the heck is this check doing ? */ - if (!cpumask_test_cpu(smp_processor_id(), &cpu_callin_map)) - play_dead(); + play_dead(); } #endif diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 7ebb1918e2ac..03daf9008124 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -68,6 +68,8 @@ EXPORT_SYMBOL(cpu_sibling_map); cpumask_t cpu_core_map[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_core_map); +static DECLARE_COMPLETION(cpu_running); + /* * A logcal cpu mask containing only one VPE per core to * reduce the number of IPIs on large MT systems. @@ -369,7 +371,7 @@ asmlinkage void start_secondary(void) cpumask_set_cpu(cpu, &cpu_coherent_mask); notify_cpu_starting(cpu); - cpumask_set_cpu(cpu, &cpu_callin_map); + complete(&cpu_running); synchronise_count_slave(cpu); set_cpu_online(cpu, true); @@ -430,7 +432,6 @@ void smp_prepare_boot_cpu(void) { set_cpu_possible(0, true); set_cpu_online(0, true); - cpumask_set_cpu(0, &cpu_callin_map); } int __cpu_up(unsigned int cpu, struct task_struct *tidle) @@ -438,11 +439,13 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) mp_ops->boot_secondary(cpu, tidle); /* - * Trust is futile. We should really have timeouts ... + * We must check for timeout here, as the CPU will not be marked + * online until the counters are synchronised. */ - while (!cpumask_test_cpu(cpu, &cpu_callin_map)) { - udelay(100); - schedule(); + if (!wait_for_completion_timeout(&cpu_running, + msecs_to_jiffies(1000))) { + pr_crit("CPU%u: failed to start\n", cpu); + return -EIO; } synchronise_count_master(cpu); -- cgit v1.2.3 From 5892d6a60341d50e1765a86fba0976c747f4fb19 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 4 Nov 2016 09:28:57 +0000 Subject: MIPS: SMP: Remove cpu_callin_map The previous commit made cpu_callin_map redundant, since it is no longer used to signal secondary CPUs starting, or going offline. Remove it now. Signed-off-by: Matt Redfearn Cc: Sebastian Andrzej Siewior Cc: Qais Yousef Cc: Masahiro Yamada Cc: Huacai Chen Cc: Kevin Cernekee Cc: Thomas Gleixner Cc: Andrew Morton Cc: James Hogan Cc: Paul Burton Cc: Florian Fainelli Cc: Anna-Maria Gleixner Cc: Adam Buchbinder Cc: Yang Shi Cc: David Daney Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14503/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/smp.c | 1 - arch/mips/include/asm/smp.h | 2 -- arch/mips/kernel/smp-bmips.c | 1 - arch/mips/kernel/smp-cps.c | 1 - arch/mips/kernel/smp.c | 2 -- arch/mips/loongson64/loongson-3/smp.c | 1 - 6 files changed, 8 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 889c3f49dbc0..a3d731479141 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -290,7 +290,6 @@ static int octeon_cpu_disable(void) set_cpu_online(cpu, false); calculate_cpu_foreign_map(); - cpumask_clear_cpu(cpu, &cpu_callin_map); octeon_fixup_irqs(); __flush_cache_all(); diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 060f23ff1817..f8c5faa93584 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -46,8 +46,6 @@ extern int __cpu_logical_map[NR_CPUS]; #define SMP_DUMP 0x8 #define SMP_ASK_C0COUNT 0x10 -extern cpumask_t cpu_callin_map; - /* Mask of CPUs which are currently definitely operating coherently */ extern cpumask_t cpu_coherent_mask; diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 6d0f1321e084..f6700dc2fb09 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -364,7 +364,6 @@ static int bmips_cpu_disable(void) set_cpu_online(cpu, false); calculate_cpu_foreign_map(); - cpumask_clear_cpu(cpu, &cpu_callin_map); clear_c0_status(IE_IRQ5); local_flush_tlb_all(); diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 6183ad84cc73..44339b470ef4 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -399,7 +399,6 @@ static int cps_cpu_disable(void) smp_mb__after_atomic(); set_cpu_online(cpu, false); calculate_cpu_foreign_map(); - cpumask_clear_cpu(cpu, &cpu_callin_map); return 0; } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 03daf9008124..0a831f63b0ec 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -48,8 +48,6 @@ #include #include -cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ - int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ EXPORT_SYMBOL(__cpu_number_map); diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c index 99aab9f85904..cfcf240cedbe 100644 --- a/arch/mips/loongson64/loongson-3/smp.c +++ b/arch/mips/loongson64/loongson-3/smp.c @@ -418,7 +418,6 @@ static int loongson3_cpu_disable(void) set_cpu_online(cpu, false); calculate_cpu_foreign_map(); - cpumask_clear_cpu(cpu, &cpu_callin_map); local_irq_save(flags); fixup_irqs(); local_irq_restore(flags); -- cgit v1.2.3 From 5b0093f3a4acc7f393f102e7e064f70efc3375b9 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 4 Nov 2016 09:28:58 +0000 Subject: MIPS: SMP-CPS: Don't BUG if a CPU fails to start If there is no online CPU within a core which could receive the IPI to start another VP in that core, a BUG() is triggered. Instead print a warning and gracefully handle the failure such that the system remains usable, albeit without the requested secondary CPU. Signed-off-by: Matt Redfearn Cc: Masahiro Yamada Cc: James Hogan Cc: Paul Burton Cc: Qais Yousef Cc: Andrew Morton Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14504/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-cps.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 44339b470ef4..a2544c2394e4 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -326,7 +326,11 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) if (cpu_online(remote)) break; } - BUG_ON(remote >= NR_CPUS); + if (remote >= NR_CPUS) { + pr_crit("No online CPU in core %u to start CPU%d\n", + core, cpu); + goto out; + } err = smp_call_function_single(remote, remote_vpe_boot, NULL, 1); -- cgit v1.2.3 From 51ad4ace97ed5a4e96e60684281066b758e1de8b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 31 Oct 2016 14:17:36 -0700 Subject: MIPS: BMIPS: Migrate interrupts during bmips_cpu_disable While we properly disabled the per-CPU timer interrupt, we also need to make sure that all interrupts that can possibly have this CPU in their smp_affinity mask also have a chance to see this interrupt migrated to a CPU not being taken offline. [ralf@linux-mips.org: Fix merge conflict.] Fixes: 230b6ff57552 ("MIPS: BMIPS: Mask off timer IRQs when hot-unplugging a CPU") Signed-off-by: Florian Fainelli Cc: cernekee@gmail.com Cc: jaedon.shin@gmail.com Cc: justinpopo6@gmail.com Cc: tglx@linutronix.de Cc: marc.zyngier@arm.com Cc: jason@lakedaemon.net Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14488/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-bmips.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index f6700dc2fb09..16e37a28f876 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -364,6 +364,7 @@ static int bmips_cpu_disable(void) set_cpu_online(cpu, false); calculate_cpu_foreign_map(); + irq_cpu_offline(); clear_c0_status(IE_IRQ5); local_flush_tlb_all(); -- cgit v1.2.3 From d65e5677ad5b3a49c43f60ec07644dc1f87bbd2e Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Thu, 25 Aug 2016 10:37:38 -0700 Subject: MIPS: R2-on-R6 MULTU/MADDU/MSUBU emulation bugfix MIPS instructions MULTU, MADDU and MSUBU emulation requires registers HI/LO to be converted to signed 32bits before 64bit sign extension on MIPS64. Bug was found on running MIPS32 R2 test application on MIPS64 R6 kernel. Fixes: b0a668fb2038 ("MIPS: kernel: mips-r2-to-r6-emul: Add R2 emulator for MIPS R6") Signed-off-by: Leonid Yegoshin Reported-by: Nikola.Veljkovic@imgtec.com Cc: paul.burton@imgtec.com Cc: yamada.masahiro@socionext.com Cc: akpm@linux-foundation.org Cc: andrea.gelmini@gelma.net Cc: macro@imgtec.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14043/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-r2-to-r6-emul.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index ef2ca28a028b..d8f1cf1ec370 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -433,8 +433,8 @@ static int multu_func(struct pt_regs *regs, u32 ir) rs = regs->regs[MIPSInst_RS(ir)]; res = (u64)rt * (u64)rs; rt = res; - regs->lo = (s64)rt; - regs->hi = (s64)(res >> 32); + regs->lo = (s64)(s32)rt; + regs->hi = (s64)(s32)(res >> 32); MIPS_R2_STATS(muls); @@ -670,9 +670,9 @@ static int maddu_func(struct pt_regs *regs, u32 ir) res += ((((s64)rt) << 32) | (u32)rs); rt = res; - regs->lo = (s64)rt; + regs->lo = (s64)(s32)rt; rs = res >> 32; - regs->hi = (s64)rs; + regs->hi = (s64)(s32)rs; MIPS_R2_STATS(dsps); @@ -728,9 +728,9 @@ static int msubu_func(struct pt_regs *regs, u32 ir) res = ((((s64)rt) << 32) | (u32)rs) - res; rt = res; - regs->lo = (s64)rt; + regs->lo = (s64)(s32)rt; rs = res >> 32; - regs->hi = (s64)rs; + regs->hi = (s64)(s32)rs; MIPS_R2_STATS(dsps); -- cgit v1.2.3 From 35e6de38858f59b6b65dcfeaf700b5d06fc2b93d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 17 Oct 2016 16:01:07 +0100 Subject: MIPS: traps: Ensure L1 & L2 ECC checking match for CM3 systems On systems with CM3, we must ensure that the L1 & L2 ECC enables are set to the same value. This is presumed by the hardware & cache corruption can occur when it is not the case. Support enabling & disabling the L2 ECC checking on CM3 systems where this is controlled via a GCR, and ensure that it matches the state of L1 ECC checking. Remove I6400 from the switch statement it will no longer hit, and which was incorrect since the L2 ECC enable bit isn't in the CP0 ErrCtl register. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14413/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 7 +++++ arch/mips/kernel/traps.c | 63 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 2e4180797b21..cfdbab015769 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -187,6 +187,7 @@ BUILD_CM_R_(config, MIPS_CM_GCB_OFS + 0x00) BUILD_CM_RW(base, MIPS_CM_GCB_OFS + 0x08) BUILD_CM_RW(access, MIPS_CM_GCB_OFS + 0x20) BUILD_CM_R_(rev, MIPS_CM_GCB_OFS + 0x30) +BUILD_CM_RW(err_control, MIPS_CM_GCB_OFS + 0x38) BUILD_CM_RW(error_mask, MIPS_CM_GCB_OFS + 0x40) BUILD_CM_RW(error_cause, MIPS_CM_GCB_OFS + 0x48) BUILD_CM_RW(error_addr, MIPS_CM_GCB_OFS + 0x50) @@ -266,6 +267,12 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_REV_CM2_5 CM_ENCODE_REV(7, 0) #define CM_REV_CM3 CM_ENCODE_REV(8, 0) +/* GCR_ERR_CONTROL register fields */ +#define CM_GCR_ERR_CONTROL_L2_ECC_EN_SHF 1 +#define CM_GCR_ERR_CONTROL_L2_ECC_EN_MSK (_ULCAST_(0x1) << 1) +#define CM_GCR_ERR_CONTROL_L2_ECC_SUPPORT_SHF 0 +#define CM_GCR_ERR_CONTROL_L2_ECC_SUPPORT_MSK (_ULCAST_(0x1) << 0) + /* GCR_ERROR_CAUSE register fields */ #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF 27 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK (_ULCAST_(0x1f) << 27) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 6c7f9d7e92b3..9ea6959cd5bb 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -1644,6 +1645,65 @@ __setup("nol2par", nol2parity); */ static inline void parity_protection_init(void) { +#define ERRCTL_PE 0x80000000 +#define ERRCTL_L2P 0x00800000 + + if (mips_cm_revision() >= CM_REV_CM3) { + ulong gcr_ectl, cp0_ectl; + + /* + * With CM3 systems we need to ensure that the L1 & L2 + * parity enables are set to the same value, since this + * is presumed by the hardware engineers. + * + * If the user disabled either of L1 or L2 ECC checking, + * disable both. + */ + l1parity &= l2parity; + l2parity &= l1parity; + + /* Probe L1 ECC support */ + cp0_ectl = read_c0_ecc(); + write_c0_ecc(cp0_ectl | ERRCTL_PE); + back_to_back_c0_hazard(); + cp0_ectl = read_c0_ecc(); + + /* Probe L2 ECC support */ + gcr_ectl = read_gcr_err_control(); + + if (!(gcr_ectl & CM_GCR_ERR_CONTROL_L2_ECC_SUPPORT_MSK) || + !(cp0_ectl & ERRCTL_PE)) { + /* + * One of L1 or L2 ECC checking isn't supported, + * so we cannot enable either. + */ + l1parity = l2parity = 0; + } + + /* Configure L1 ECC checking */ + if (l1parity) + cp0_ectl |= ERRCTL_PE; + else + cp0_ectl &= ~ERRCTL_PE; + write_c0_ecc(cp0_ectl); + back_to_back_c0_hazard(); + WARN_ON(!!(read_c0_ecc() & ERRCTL_PE) != l1parity); + + /* Configure L2 ECC checking */ + if (l2parity) + gcr_ectl |= CM_GCR_ERR_CONTROL_L2_ECC_EN_MSK; + else + gcr_ectl &= ~CM_GCR_ERR_CONTROL_L2_ECC_EN_MSK; + write_gcr_err_control(gcr_ectl); + gcr_ectl = read_gcr_err_control(); + gcr_ectl &= CM_GCR_ERR_CONTROL_L2_ECC_EN_MSK; + WARN_ON(!!gcr_ectl != l2parity); + + pr_info("Cache parity protection %sabled\n", + l1parity ? "en" : "dis"); + return; + } + switch (current_cpu_type()) { case CPU_24K: case CPU_34K: @@ -1654,11 +1714,8 @@ static inline void parity_protection_init(void) case CPU_PROAPTIV: case CPU_P5600: case CPU_QEMU_GENERIC: - case CPU_I6400: case CPU_P6600: { -#define ERRCTL_PE 0x80000000 -#define ERRCTL_L2P 0x00800000 unsigned long errctl; unsigned int l1parity_present, l2parity_present; -- cgit v1.2.3 From e11124d8ffcdf893d64e0b29624fd88e0ae4ceac Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 17 Oct 2016 15:34:35 +0100 Subject: MIPS: Remove r2_emul_return from struct thread_info The r2_emul_return field in struct thread_info was used in order to take an alternate codepath when returning to userland, which (besides not implementing certain features) effectively used the eretnc instruction in place of eret. The difference is that eretnc doesn't clear LLBit, and therefore doesn't cause a linked load & store sequence to fail due to emulation like eret would. The reason eret would usually be used to clear LLBit is so that after context switching we ensure that a load performed by one task doesn't influence another task. However commit 7c151d3d5d7a ("MIPS: Make use of the ERETNC instruction on MIPS R6") which introduced the r2_emul_return field and conditional use of eretnc also for some reason began explicitly clearing LLBit during context switches - despite retaining the use of eret for everything but returns from the pre-r6 instruction emulation code. As LLBit is cleared upon context switches anyway, simplify this by using eretnc unconditionally for MIPSr6 kernels. This allows us to remove the 4 byte r2_emul_return boolean from struct thread_info, simplify the return to user code in entry.S and avoid the overhead of tracking & checking state which we don't need. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14408/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/stackframe.h | 4 ++++ arch/mips/include/asm/thread_info.h | 1 - arch/mips/kernel/asm-offsets.c | 1 - arch/mips/kernel/entry.S | 18 ------------------ arch/mips/kernel/traps.c | 2 -- 5 files changed, 4 insertions(+), 22 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h index 2f182bdf024f..6c74a804fe98 100644 --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h @@ -364,9 +364,13 @@ .macro RESTORE_SP_AND_RET LONG_L sp, PT_R29(sp) +#ifdef CONFIG_CPU_MIPSR6 + eretnc +#else .set arch=r4000 eret .set mips0 +#endif .endm #endif diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index e309d8fcb516..b439e512792b 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -27,7 +27,6 @@ struct thread_info { unsigned long tp_value; /* thread pointer */ __u32 cpu; /* current CPU */ int preempt_count; /* 0 => preemptable, <0 => BUG */ - int r2_emul_return; /* 1 => Returning from R2 emulator */ mm_segment_t addr_limit; /* * thread address space limit: * 0x7fffffff for user-thead diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index a7277698d328..bb5c5d34ba81 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -97,7 +97,6 @@ void output_thread_info_defines(void) OFFSET(TI_TP_VALUE, thread_info, tp_value); OFFSET(TI_CPU, thread_info, cpu); OFFSET(TI_PRE_COUNT, thread_info, preempt_count); - OFFSET(TI_R2_EMUL_RET, thread_info, r2_emul_return); OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit); OFFSET(TI_REGS, thread_info, regs); DEFINE(_THREAD_SIZE, THREAD_SIZE); diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 7791840cf22c..8d83fc2a96b7 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -47,11 +47,6 @@ resume_userspace: local_irq_disable # make sure we dont miss an # interrupt setting need_resched # between sampling and return -#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR - lw k0, TI_R2_EMUL_RET($28) - bnez k0, restore_all_from_r2_emul -#endif - LONG_L a2, TI_FLAGS($28) # current->work andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) bnez t0, work_pending @@ -120,19 +115,6 @@ restore_partial: # restore partial frame RESTORE_SP_AND_RET .set at -#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR -restore_all_from_r2_emul: # restore full frame - .set noat - sw zero, TI_R2_EMUL_RET($28) # reset it - RESTORE_TEMP - RESTORE_AT - RESTORE_STATIC - RESTORE_SOME - LONG_L sp, PT_R29(sp) - eretnc - .set at -#endif - work_pending: andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS beqz t0, work_notifysig diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 9ea6959cd5bb..cb479be31a50 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1108,7 +1108,6 @@ asmlinkage void do_ri(struct pt_regs *regs) switch (status) { case 0: case SIGEMT: - task_thread_info(current)->r2_emul_return = 1; return; case SIGILL: goto no_r2_instr; @@ -1116,7 +1115,6 @@ asmlinkage void do_ri(struct pt_regs *regs) process_fpemu_return(status, ¤t->thread.cp0_baduaddr, fcr31); - task_thread_info(current)->r2_emul_return = 1; return; } } -- cgit v1.2.3 From c83c2eed67e578576acf08611bfb630bd199714b Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Fri, 2 Dec 2016 09:58:28 +0100 Subject: MIPS: kexec: remove SMP_DUMP SMP_DUMP has been added as a new IPI signal when kexec support was added for Cavium Octeon CPUs ('commit 7aa1c8f47e7e ("MIPS: kdump: Add support")'. However, the new signal doesn't appear to ever have a proper handler added (octeon_message_functions[] array has an empty handler for it), and generic IPI handlers now trigger a BUG() on unhandled signal. As the method is unused remove it completely and replace its only invocation with a smp_call_function(). [ralf@linux-mips.org: Renumber SMP_ASK_C0COUNT to avoid numbering gaps.] Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14630/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/smp.h | 8 +------- arch/mips/kernel/crash.c | 2 +- arch/mips/kernel/smp.c | 17 ----------------- 3 files changed, 2 insertions(+), 25 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index f8c5faa93584..98a117a05fbc 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -42,9 +42,7 @@ extern int __cpu_logical_map[NR_CPUS]; #define SMP_CALL_FUNCTION 0x2 /* Octeon - Tell another core to flush its icache */ #define SMP_ICACHE_FLUSH 0x4 -/* Used by kexec crashdump to save all cpu's state */ -#define SMP_DUMP 0x8 -#define SMP_ASK_C0COUNT 0x10 +#define SMP_ASK_C0COUNT 0x8 /* Mask of CPUs which are currently definitely operating coherently */ extern cpumask_t cpu_coherent_mask; @@ -111,8 +109,4 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask) mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION); } -#if defined(CONFIG_KEXEC) -extern void (*dump_ipi_function_ptr)(void *); -void dump_send_ipi(void (*dump_ipi_callback)(void *)); -#endif #endif /* __ASM_SMP_H */ diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c index 1723b1762297..5a71518be0f1 100644 --- a/arch/mips/kernel/crash.c +++ b/arch/mips/kernel/crash.c @@ -56,7 +56,7 @@ static void crash_kexec_prepare_cpus(void) ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */ - dump_send_ipi(crash_shutdown_secondary); + smp_call_function(crash_shutdown_secondary, NULL, 0); smp_wmb(); /* diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 0a831f63b0ec..8c60a296294c 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -638,23 +638,6 @@ void flush_tlb_one(unsigned long vaddr) EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(flush_tlb_one); -#if defined(CONFIG_KEXEC) -void (*dump_ipi_function_ptr)(void *) = NULL; -void dump_send_ipi(void (*dump_ipi_callback)(void *)) -{ - int i; - int cpu = smp_processor_id(); - - dump_ipi_function_ptr = dump_ipi_callback; - smp_mb(); - for_each_online_cpu(i) - if (i != cpu) - mp_ops->send_ipi_single(i, SMP_DUMP); - -} -EXPORT_SYMBOL(dump_send_ipi); -#endif - #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST static DEFINE_PER_CPU(atomic_t, tick_broadcast_count); -- cgit v1.2.3 From 08c941bf6ec523d666a78f86e3d696ed45dfb6e5 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Mon, 21 Nov 2016 11:23:38 +0100 Subject: MIPS: Move register dump routines out of ptrace code Current register dump methods for MIPS are implemented inside ptrace methods, but there will be other uses in the kernel for them, so keep them separately in process.c and use those definitions for ptrace instead. Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14587/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/elf.h | 3 +++ arch/mips/kernel/process.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ arch/mips/kernel/ptrace.c | 34 ++-------------------------------- 3 files changed, 49 insertions(+), 32 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 2b3dc2973670..f61a4a14bb56 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -210,6 +210,9 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +void mips_dump_regs32(u32 *uregs, const struct pt_regs *regs); +void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs); + #ifdef CONFIG_32BIT /* * This is used to ensure we don't load something for the wrong architecture. diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 3da0161bdf84..803e255b6fc3 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -729,3 +729,47 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) return 0; } + +#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32) +void mips_dump_regs32(u32 *uregs, const struct pt_regs *regs) +{ + unsigned int i; + + for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) { + /* k0/k1 are copied as zero. */ + if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27) + uregs[i] = 0; + else + uregs[i] = regs->regs[i - MIPS32_EF_R0]; + } + + uregs[MIPS32_EF_LO] = regs->lo; + uregs[MIPS32_EF_HI] = regs->hi; + uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc; + uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr; + uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status; + uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause; +} +#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */ + +#ifdef CONFIG_64BIT +void mips_dump_regs64(u64 *uregs, const struct pt_regs *regs) +{ + unsigned int i; + + for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) { + /* k0/k1 are copied as zero. */ + if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27) + uregs[i] = 0; + else + uregs[i] = regs->regs[i - MIPS64_EF_R0]; + } + + uregs[MIPS64_EF_LO] = regs->lo; + uregs[MIPS64_EF_HI] = regs->hi; + uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc; + uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr; + uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status; + uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause; +} +#endif /* CONFIG_64BIT */ diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index c8ba26072132..fdef26382c37 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -294,23 +294,8 @@ static int gpr32_get(struct task_struct *target, { struct pt_regs *regs = task_pt_regs(target); u32 uregs[ELF_NGREG] = {}; - unsigned i; - - for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) { - /* k0/k1 are copied as zero. */ - if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27) - continue; - - uregs[i] = regs->regs[i - MIPS32_EF_R0]; - } - - uregs[MIPS32_EF_LO] = regs->lo; - uregs[MIPS32_EF_HI] = regs->hi; - uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc; - uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr; - uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status; - uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause; + mips_dump_regs32(uregs, regs); return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, sizeof(uregs)); } @@ -373,23 +358,8 @@ static int gpr64_get(struct task_struct *target, { struct pt_regs *regs = task_pt_regs(target); u64 uregs[ELF_NGREG] = {}; - unsigned i; - - for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) { - /* k0/k1 are copied as zero. */ - if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27) - continue; - - uregs[i] = regs->regs[i - MIPS64_EF_R0]; - } - - uregs[MIPS64_EF_LO] = regs->lo; - uregs[MIPS64_EF_HI] = regs->hi; - uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc; - uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr; - uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status; - uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause; + mips_dump_regs64(uregs, regs); return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, sizeof(uregs)); } -- cgit v1.2.3 From 269aa43aad0f96673478fe2446abe54d7ad42e8f Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 23 Nov 2016 14:43:43 +0100 Subject: MIPS: Do not request resources for crashkernel if one isn't defined When KEXEC is enabled but crashkernel details are not passed through the kernel commandline unnecessary resources are requested (start==end==0) Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14607/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index f66e5ce505b2..0058feaa65e5 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -672,6 +672,9 @@ static void __init request_crashkernel(struct resource *res) { int ret; + if (crashk_res.start == crashk_res.end) + return; + ret = request_resource(res, &crashk_res); if (!ret) pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", -- cgit v1.2.3 From e89ef66d7682f031f026eee6bba03c8c2248d2a9 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 23 Nov 2016 14:43:44 +0100 Subject: MIPS: init: Ensure reserved memory regions are not added to bootmem Memories managed through boot_mem_map are generally expected to define non-crossing areas. However, if part of a larger memory block is marked as reserved, it would still be added to bootmem allocator as an available block and could end up being overwritten by the allocator. Prevent this by explicitly marking the memory as reserved it if exists in the range used by bootmem allocator. Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14608/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 0058feaa65e5..8ebad247ce82 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -483,6 +483,10 @@ static void __init bootmem_init(void) continue; default: /* Not usable memory */ + if (start > min_low_pfn && end < max_low_pfn) + reserve_bootmem(boot_mem_map.map[i].addr, + boot_mem_map.map[i].size, + BOOTMEM_DEFAULT); continue; } -- cgit v1.2.3 From d9b5b658210f28ed9f70c757d553e679d76e2986 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 23 Nov 2016 14:43:45 +0100 Subject: MIPS: init: Ensure bootmem does not corrupt reserved memory Current init code initialises bootmem allocator with all of the low memory that it assumes is available, but does not check for reserved memory block, which can lead to corruption of data that may be stored there. Move bootmem's allocation map to a location that does not cross any reserved regions Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14609/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 8ebad247ce82..64b38d400987 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -153,6 +153,35 @@ void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_add add_memory_region(start, size, BOOT_MEM_RAM); } +bool __init memory_region_available(phys_addr_t start, phys_addr_t size) +{ + int i; + bool in_ram = false, free = true; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + phys_addr_t start_, end_; + + start_ = boot_mem_map.map[i].addr; + end_ = boot_mem_map.map[i].addr + boot_mem_map.map[i].size; + + switch (boot_mem_map.map[i].type) { + case BOOT_MEM_RAM: + if (start >= start_ && start + size <= end_) + in_ram = true; + break; + case BOOT_MEM_RESERVED: + if ((start >= start_ && start < end_) || + (start < start_ && start + size >= start_)) + free = false; + break; + default: + continue; + } + } + + return in_ram && free; +} + static void __init print_memory_map(void) { int i; @@ -332,11 +361,19 @@ static void __init bootmem_init(void) #else /* !CONFIG_SGI_IP27 */ +static unsigned long __init bootmap_bytes(unsigned long pages) +{ + unsigned long bytes = DIV_ROUND_UP(pages, 8); + + return ALIGN(bytes, sizeof(long)); +} + static void __init bootmem_init(void) { unsigned long reserved_end; unsigned long mapstart = ~0UL; unsigned long bootmap_size; + bool bootmap_valid = false; int i; /* @@ -430,11 +467,42 @@ static void __init bootmem_init(void) #endif /* - * Initialize the boot-time allocator with low memory only. + * check that mapstart doesn't overlap with any of + * memory regions that have been reserved through eg. DTB */ - bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, - min_low_pfn, max_low_pfn); + bootmap_size = bootmap_bytes(max_low_pfn - min_low_pfn); + + bootmap_valid = memory_region_available(PFN_PHYS(mapstart), + bootmap_size); + for (i = 0; i < boot_mem_map.nr_map && !bootmap_valid; i++) { + unsigned long mapstart_addr; + + switch (boot_mem_map.map[i].type) { + case BOOT_MEM_RESERVED: + mapstart_addr = PFN_ALIGN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + if (PHYS_PFN(mapstart_addr) < mapstart) + break; + + bootmap_valid = memory_region_available(mapstart_addr, + bootmap_size); + if (bootmap_valid) + mapstart = PHYS_PFN(mapstart_addr); + break; + default: + break; + } + } + if (!bootmap_valid) + panic("No memory area to place a bootmap bitmap"); + + /* + * Initialize the boot-time allocator with low memory only. + */ + if (bootmap_size != init_bootmem_node(NODE_DATA(0), mapstart, + min_low_pfn, max_low_pfn)) + panic("Unexpected memory size required for bootmap"); for (i = 0; i < boot_mem_map.nr_map; i++) { unsigned long start, end; -- cgit v1.2.3 From 73346081cac18732a959be580a90abc707dea52a Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 23 Nov 2016 14:43:46 +0100 Subject: MIPS: Use early_init_fdt_reserve_self to protect DTB location early_init_fdt_reserve_self is used to tell the boot memory allocator that a memory is occupied by the DTB, so add it in the MIPS init code to ensure information about the DTB is added to the boot memory array. Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14610/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/prom.c | 7 +++++++ arch/mips/kernel/setup.c | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 5fcec3032f38..0dbcd152a1a9 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -49,6 +49,13 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); } +int __init early_init_dt_reserve_memory_arch(phys_addr_t base, + phys_addr_t size, bool nomap) +{ + add_memory_region(base, size, BOOT_MEM_RESERVED); + return 0; +} + void __init __dt_setup_arch(void *bph) { if (!early_init_dt_scan(bph)) diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 64b38d400987..c22f0fdd4cfb 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -832,6 +833,9 @@ static void __init arch_mem_init(char **cmdline_p) print_memory_map(); } + early_init_fdt_reserve_self(); + early_init_fdt_scan_reserved_mem(); + bootmem_init(); #ifdef CONFIG_PROC_VMCORE if (setup_elfcorehdr && setup_elfcorehdr_size) { -- cgit v1.2.3 From 4c9fff362261d68cc35053a76afea85f1277ac66 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 23 Nov 2016 14:43:48 +0100 Subject: MIPS: relocate: Optionally relocate the DTB If the DTB is located in the target memory area for the relocated kernel it needs to be relocated as well before kernel relocation takes place. After copying the DTB use the new plat_fdt_relocated() API from the relocated kernel to ensure the relocated kernel updates any information that it may have cached about the location of the DTB. plat_fdt_relocated is declared as a weak symbol so that platforms that do not require it do not need to implement the method. Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14616/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/relocate.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index c82288569eb1..9103bebc9a8e 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -31,6 +31,8 @@ extern u32 _relocation_end[]; /* End relocation table */ extern long __start___ex_table; /* Start exception table */ extern long __stop___ex_table; /* End exception table */ +extern void __weak plat_fdt_relocated(void *new_location); + /* * This function may be defined for a platform to perform any post-relocation * fixup necessary. @@ -41,7 +43,6 @@ int __weak plat_post_relocation(long offset) return 0; } - static inline u32 __init get_synci_step(void) { u32 res; @@ -302,12 +303,14 @@ void *__init relocate_kernel(void) int res = 1; /* Default to original kernel entry point */ void *kernel_entry = start_kernel; + void *fdt = NULL; /* Get the command line */ fw_init_cmdline(); #if defined(CONFIG_USE_OF) /* Deal with the device tree */ - early_init_dt_scan(plat_get_fdt()); + fdt = plat_get_fdt(); + early_init_dt_scan(fdt); if (boot_command_line[0]) { /* Boot command line was passed in device tree */ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); @@ -327,6 +330,29 @@ void *__init relocate_kernel(void) arcs_cmdline[0] = '\0'; if (offset) { + void (*fdt_relocated_)(void *) = NULL; +#if defined(CONFIG_USE_OF) + unsigned long fdt_phys = virt_to_phys(fdt); + + /* + * If built-in dtb is used then it will have been relocated + * during kernel _text relocation. If appended DTB is used + * then it will not be relocated, but it should remain + * intact in the original location. If dtb is loaded by + * the bootloader then it may need to be moved if it crosses + * the target memory area + */ + + if (fdt_phys >= virt_to_phys(RELOCATED(&_text)) && + fdt_phys <= virt_to_phys(RELOCATED(&_end))) { + void *fdt_relocated = + RELOCATED(ALIGN((long)&_end, PAGE_SIZE)); + memcpy(fdt_relocated, fdt, fdt_totalsize(fdt)); + fdt = fdt_relocated; + fdt_relocated_ = RELOCATED(&plat_fdt_relocated); + } +#endif /* CONFIG_USE_OF */ + /* Copy the kernel to it's new location */ memcpy(loc_new, &_text, kernel_length); @@ -349,6 +375,14 @@ void *__init relocate_kernel(void) */ memcpy(RELOCATED(&__bss_start), &__bss_start, bss_length); + /* + * If fdt was stored outside of the kernel image and + * had to be moved then update platform's state data + * with the new fdt location + */ + if (fdt_relocated_) + fdt_relocated_(fdt); + /* * Last chance for the platform to abort relocation. * This may also be used by the platform to perform any -- cgit v1.2.3 From 73fbc1eba7ffa3bf0ad12486232a8a1edb4e4411 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 23 Nov 2016 14:43:49 +0100 Subject: MIPS: fix mem=X@Y commandline processing When a memory offset is specified through the commandline, add the memory in range PHYS_OFFSET:Y as reserved memory area. Otherwise the bootmem allocator is initialised with low page equal to min_low_pfn = PHYS_OFFSET, and in free_all_bootmem will process pages starting from min_low_pfn instead of PFN(Y). Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14613/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index c22f0fdd4cfb..ae888662bda3 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -662,6 +662,10 @@ static int __init early_parse_mem(char *p) start = memparse(p + 1, &p); add_memory_region(start, size, BOOT_MEM_RAM); + + if (start && start > PHYS_OFFSET) + add_memory_region(PHYS_OFFSET, start - PHYS_OFFSET, + BOOT_MEM_RESERVED); return 0; } early_param("mem", early_parse_mem); -- cgit v1.2.3 From a8f108d70c74d83574c157648383eb2e4285a190 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 23 Nov 2016 14:43:50 +0100 Subject: MIPS: kexec: Do not reserve invalid crashkernel memory on boot Do not reserve memory for the crashkernel if the commandline argument points to a wrong location. This can happen if the location is specified wrong or if the same commandline is reused when starting the crashkernel - in the latter case the reserved memory would point to the location from which the crashkernel is executing. Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14612/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/setup.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index ae888662bda3..01d1dbde5fbf 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -741,6 +741,11 @@ static void __init mips_parse_crashkernel(void) if (ret != 0 || crash_size <= 0) return; + if (!memory_region_available(crash_base, crash_size)) { + pr_warn("Invalid memory region reserved for crash kernel\n"); + return; + } + crashk_res.start = crash_base; crashk_res.end = crash_base + crash_size - 1; } -- cgit v1.2.3 From 856b0f591e951a234d6642cc466023df182eb51c Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 23 Nov 2016 14:43:51 +0100 Subject: MIPS: kexec: add debug info about the new kexec'ed image Print details of the new kexec image loaded. Based on the original code from commit 221f2c770e10d ("arm64/kexec: Add pr_debug output") Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14614/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/machine_kexec.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c index 59725204105c..8b574bcd39ba 100644 --- a/arch/mips/kernel/machine_kexec.c +++ b/arch/mips/kernel/machine_kexec.c @@ -28,9 +28,31 @@ atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0); void (*_crash_smp_send_stop)(void) = NULL; #endif +static void kexec_image_info(const struct kimage *kimage) +{ + unsigned long i; + + pr_debug("kexec kimage info:\n"); + pr_debug(" type: %d\n", kimage->type); + pr_debug(" start: %lx\n", kimage->start); + pr_debug(" head: %lx\n", kimage->head); + pr_debug(" nr_segments: %lu\n", kimage->nr_segments); + + for (i = 0; i < kimage->nr_segments; i++) { + pr_debug(" segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n", + i, + kimage->segment[i].mem, + kimage->segment[i].mem + kimage->segment[i].memsz, + (unsigned long)kimage->segment[i].memsz, + (unsigned long)kimage->segment[i].memsz / PAGE_SIZE); + } +} + int machine_kexec_prepare(struct kimage *kimage) { + kexec_image_info(kimage); + if (_machine_kexec_prepare) return _machine_kexec_prepare(kimage); return 0; -- cgit v1.2.3 From ef462f3b64e9fb0c8e1cd5d60f5bd7f13ac2156d Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 7 Dec 2016 17:16:26 -0800 Subject: MIPS: Add cacheinfo support Add cacheinfo support for MIPS architectures. Use information from the cpuinfo_mips struct to populate the cacheinfo struct. This allows an architecture agnostic approach, however this also means if cache information is not properly populated within the cpuinfo_mips struct, there is nothing we can do. (I.E. c-r3k.c) Signed-off-by: Justin Chen Cc: f.fainelli@gmail.com Cc: linux-mips@linux-mips.org Cc: bcm-kernel-feedback-list@broadcom.com Patchwork: https://patchwork.linux-mips.org/patch/14650/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/cacheinfo.c | 85 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 arch/mips/kernel/cacheinfo.c (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 4a603a3ea657..904a9c48553a 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds obj-y += cpu-probe.o branch.o elf.o entry.o genex.o idle.o irq.o \ process.o prom.o ptrace.o reset.o setup.o signal.o \ syscall.o time.o topology.o traps.o unaligned.o watch.o \ - vdso.o + vdso.o cacheinfo.o ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_ftrace.o = -pg diff --git a/arch/mips/kernel/cacheinfo.c b/arch/mips/kernel/cacheinfo.c new file mode 100644 index 000000000000..a92bbbae969b --- /dev/null +++ b/arch/mips/kernel/cacheinfo.c @@ -0,0 +1,85 @@ +/* + * MIPS cacheinfo support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include + +/* Populates leaf and increments to next leaf */ +#define populate_cache(cache, leaf, c_level, c_type) \ + leaf->type = c_type; \ + leaf->level = c_level; \ + leaf->coherency_line_size = c->cache.linesz; \ + leaf->number_of_sets = c->cache.sets; \ + leaf->ways_of_associativity = c->cache.ways; \ + leaf->size = c->cache.linesz * c->cache.sets * \ + c->cache.ways; \ + leaf++; + +static int __init_cache_level(unsigned int cpu) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + int levels = 0, leaves = 0; + + /* + * If Dcache is not set, we assume the cache structures + * are not properly initialized. + */ + if (c->dcache.waysize) + levels += 1; + else + return -ENOENT; + + + leaves += (c->icache.waysize) ? 2 : 1; + + if (c->scache.waysize) { + levels++; + leaves++; + } + + if (c->tcache.waysize) { + levels++; + leaves++; + } + + this_cpu_ci->num_levels = levels; + this_cpu_ci->num_leaves = leaves; + return 0; +} + +static int __populate_cache_leaves(unsigned int cpu) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + struct cacheinfo *this_leaf = this_cpu_ci->info_list; + + if (c->icache.waysize) { + populate_cache(dcache, this_leaf, 1, CACHE_TYPE_DATA); + populate_cache(icache, this_leaf, 1, CACHE_TYPE_INST); + } else { + populate_cache(dcache, this_leaf, 1, CACHE_TYPE_UNIFIED); + } + + if (c->scache.waysize) + populate_cache(scache, this_leaf, 2, CACHE_TYPE_UNIFIED); + + if (c->tcache.waysize) + populate_cache(tcache, this_leaf, 3, CACHE_TYPE_UNIFIED); + + return 0; +} + +DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level) +DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves) -- cgit v1.2.3 From cd854fc6f18f0c231f11f2c42167a07e3b265c72 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Tue, 13 Dec 2016 10:48:30 +0100 Subject: MIPS: uprobes: Remove __weak attribute from arch_uprobe_copy_ixol. Arch-specific implementation of arch_uprobe_copy_ixol is expected to override the weak implementation in generic code. As currently both implementations are marked as weak, it is up to the linker to chose one. Remove the __weak attribute from MIPS code to make sure the correct version is used. Fixes: 40e084a506eb ("MIPS: Add uprobes support.") Signed-off-by: Marcin Nowakowski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14660/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/uprobes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/uprobes.c b/arch/mips/kernel/uprobes.c index dbb917403131..e99e3fae5326 100644 --- a/arch/mips/kernel/uprobes.c +++ b/arch/mips/kernel/uprobes.c @@ -226,7 +226,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN); } -void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, +void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, void *src, unsigned long len) { unsigned long kaddr, kstart; -- cgit v1.2.3 From 29830c124d834c4ce0133aaf8ca85f045f9e758c Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 11:14:10 +0000 Subject: MIPS: Export _save_fp & _save_msa alongside their definitions Now that EXPORT_SYMBOL can be used from assembly source, move the EXPORT_SYMBOL invocations for _save_fp & _save_msa to be alongside their definitions. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14509/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips_ksyms.c | 8 -------- arch/mips/kernel/r2300_switch.S | 2 ++ arch/mips/kernel/r4k_switch.S | 3 +++ 3 files changed, 5 insertions(+), 8 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 93aeec705a6e..a7aca7b8097d 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -34,14 +34,6 @@ extern long __strnlen_kernel_asm(const char *s); extern long __strnlen_user_nocheck_asm(const char *s); extern long __strnlen_user_asm(const char *s); -/* - * Core architecture code - */ -EXPORT_SYMBOL_GPL(_save_fp); -#ifdef CONFIG_CPU_HAS_MSA -EXPORT_SYMBOL_GPL(_save_msa); -#endif - /* * String functions */ diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S index ac27ef7d4d0e..1049eeafd97d 100644 --- a/arch/mips/kernel/r2300_switch.S +++ b/arch/mips/kernel/r2300_switch.S @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include @@ -72,6 +73,7 @@ LEAF(resume) * Save a thread's fp context. */ LEAF(_save_fp) +EXPORT_SYMBOL(_save_fp) fpu_save_single a0, t1 # clobbers t1 jr ra END(_save_fp) diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 2f0a3b223c97..758577861523 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include @@ -75,6 +76,7 @@ * Save a thread's fp context. */ LEAF(_save_fp) +EXPORT_SYMBOL(_save_fp) #if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \ defined(CONFIG_CPU_MIPS32_R6) mfc0 t0, CP0_STATUS @@ -101,6 +103,7 @@ LEAF(_restore_fp) * Save a thread's MSA vector context. */ LEAF(_save_msa) +EXPORT_SYMBOL(_save_msa) msa_save_all a0 jr ra END(_save_msa) -- cgit v1.2.3 From 827456e71036681039e2c89f58e29f950ef3eb05 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 11:48:04 +0000 Subject: MIPS: Export _mcount alongside its definition Now that EXPORT_SYMBOL can be used from assembly source, move the EXPORT_SYMBOL invocation for _mcount to be alongside its definition. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14525/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mcount.S | 3 +++ arch/mips/kernel/mips_ksyms.c | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 2f7c734771f4..f2ee7e1e3342 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -10,6 +10,7 @@ * Author: Wu Zhangjin */ +#include #include #include #include @@ -66,6 +67,7 @@ NESTED(ftrace_caller, PT_SIZE, ra) .globl _mcount _mcount: +EXPORT_SYMBOL(_mcount) b ftrace_stub #ifdef CONFIG_32BIT addiu sp,sp,8 @@ -114,6 +116,7 @@ ftrace_stub: #else /* ! CONFIG_DYNAMIC_FTRACE */ NESTED(_mcount, PT_SIZE, ra) +EXPORT_SYMBOL(_mcount) PTR_LA t1, ftrace_stub PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ bne t1, t2, static_trace diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index a7aca7b8097d..02d8ce125c12 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -80,7 +80,3 @@ EXPORT_SYMBOL(__csum_partial_copy_from_user); #endif EXPORT_SYMBOL(invalid_pte_table); -#ifdef CONFIG_FUNCTION_TRACER -/* _mcount is defined in arch/mips/kernel/mcount.S */ -EXPORT_SYMBOL(_mcount); -#endif -- cgit v1.2.3 From aa4089e6ce54b5a7aaf5a0e8afb442395cca8503 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 11:14:12 +0000 Subject: MIPS: Export invalid_pte_table alongside its definition It's unclear to me why this wasn't always the case, but move the EXPORT_SYMBOL invocation for invalid_pte_table to be alongside its definition. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14511/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips_ksyms.c | 2 -- arch/mips/mm/init.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 02d8ce125c12..c284cb76f500 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -78,5 +78,3 @@ EXPORT_SYMBOL(__csum_partial_copy_kernel); EXPORT_SYMBOL(__csum_partial_copy_to_user); EXPORT_SYMBOL(__csum_partial_copy_from_user); #endif - -EXPORT_SYMBOL(invalid_pte_table); diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index e86ebcf5c071..9d1d54b8e1e8 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -540,3 +541,4 @@ pgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(.bss..swapper_pg_dir); pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss; #endif pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss; +EXPORT_SYMBOL(invalid_pte_table); -- cgit v1.2.3 From 231300423a5486cbd9e102d741190428b2783ab2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 11:14:13 +0000 Subject: MIPS: Export csum functions alongside their definitions Now that EXPORT_SYMBOL can be used from assembly source, move the EXPORT_SYMBOL invocations for the csum_partial_* functions to be alongside their definitions. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14512/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips_ksyms.c | 8 -------- arch/mips/lib/csum_partial.S | 6 ++++++ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index c284cb76f500..d6973f450288 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -70,11 +70,3 @@ EXPORT_SYMBOL(__strnlen_kernel_nocheck_asm); EXPORT_SYMBOL(__strnlen_kernel_asm); EXPORT_SYMBOL(__strnlen_user_nocheck_asm); EXPORT_SYMBOL(__strnlen_user_asm); - -#ifndef CONFIG_CPU_MIPSR6 -EXPORT_SYMBOL(csum_partial); -EXPORT_SYMBOL(csum_partial_copy_nocheck); -EXPORT_SYMBOL(__csum_partial_copy_kernel); -EXPORT_SYMBOL(__csum_partial_copy_to_user); -EXPORT_SYMBOL(__csum_partial_copy_from_user); -#endif diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index ed88647b57e2..2ff84f4b1717 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -13,6 +13,7 @@ #include #include #include +#include #include #ifdef CONFIG_64BIT @@ -103,6 +104,7 @@ .set noreorder .align 5 LEAF(csum_partial) +EXPORT_SYMBOL(csum_partial) move sum, zero move t7, zero @@ -460,6 +462,7 @@ LEAF(csum_partial) #endif .if \__nocheck == 1 FEXPORT(csum_partial_copy_nocheck) + EXPORT_SYMBOL(csum_partial_copy_nocheck) .endif move sum, zero move odd, zero @@ -823,9 +826,12 @@ LEAF(csum_partial) .endm LEAF(__csum_partial_copy_kernel) +EXPORT_SYMBOL(__csum_partial_copy_kernel) #ifndef CONFIG_EVA FEXPORT(__csum_partial_copy_to_user) +EXPORT_SYMBOL(__csum_partial_copy_to_user) FEXPORT(__csum_partial_copy_from_user) +EXPORT_SYMBOL(__csum_partial_copy_from_user) #endif __BUILD_CSUM_PARTIAL_COPY_USER LEGACY_MODE USEROP USEROP 1 END(__csum_partial_copy_kernel) -- cgit v1.2.3 From d6cb671589757ec3d20e5e0886505cdad327b1b3 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 11:14:14 +0000 Subject: MIPS: Export string functions alongside their definitions Now that EXPORT_SYMBOL can be used from assembly source, move the EXPORT_SYMBOL invocations for the strlen*, strnlen* & strncpy* functions to be alongside their definitions. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14513/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips_ksyms.c | 24 ------------------------ arch/mips/lib/strlen_user.S | 2 ++ arch/mips/lib/strncpy_user.S | 5 +++++ arch/mips/lib/strnlen_user.S | 3 +++ 4 files changed, 10 insertions(+), 24 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index d6973f450288..a84f75088247 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -19,20 +19,6 @@ extern void *__bzero_kernel(void *__s, size_t __count); extern void *__bzero(void *__s, size_t __count); -extern long __strncpy_from_kernel_nocheck_asm(char *__to, - const char *__from, long __len); -extern long __strncpy_from_kernel_asm(char *__to, const char *__from, - long __len); -extern long __strncpy_from_user_nocheck_asm(char *__to, - const char *__from, long __len); -extern long __strncpy_from_user_asm(char *__to, const char *__from, - long __len); -extern long __strlen_kernel_asm(const char *s); -extern long __strlen_user_asm(const char *s); -extern long __strnlen_kernel_nocheck_asm(const char *s); -extern long __strnlen_kernel_asm(const char *s); -extern long __strnlen_user_nocheck_asm(const char *s); -extern long __strnlen_user_asm(const char *s); /* * String functions @@ -60,13 +46,3 @@ EXPORT_SYMBOL(__copy_user_inatomic_eva); EXPORT_SYMBOL(__bzero_kernel); #endif EXPORT_SYMBOL(__bzero); -EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm); -EXPORT_SYMBOL(__strncpy_from_kernel_asm); -EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); -EXPORT_SYMBOL(__strncpy_from_user_asm); -EXPORT_SYMBOL(__strlen_kernel_asm); -EXPORT_SYMBOL(__strlen_user_asm); -EXPORT_SYMBOL(__strnlen_kernel_nocheck_asm); -EXPORT_SYMBOL(__strnlen_kernel_asm); -EXPORT_SYMBOL(__strnlen_user_nocheck_asm); -EXPORT_SYMBOL(__strnlen_user_asm); diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S index 929bbacd697e..c9cb7e6c59a6 100644 --- a/arch/mips/lib/strlen_user.S +++ b/arch/mips/lib/strlen_user.S @@ -9,6 +9,7 @@ */ #include #include +#include #include #define EX(insn,reg,addr,handler) \ @@ -24,6 +25,7 @@ */ .macro __BUILD_STRLEN_ASM func LEAF(__strlen_\func\()_asm) +EXPORT_SYMBOL(__strlen_\func\()_asm) LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? and v0, a0 bnez v0, .Lfault\@ diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S index 3c32baf8b494..af745b1d04e3 100644 --- a/arch/mips/lib/strncpy_user.S +++ b/arch/mips/lib/strncpy_user.S @@ -9,6 +9,7 @@ #include #include #include +#include #include #define EX(insn,reg,addr,handler) \ @@ -30,11 +31,13 @@ .macro __BUILD_STRNCPY_ASM func LEAF(__strncpy_from_\func\()_asm) +EXPORT_SYMBOL(__strncpy_from_\func\()_asm) LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? and v0, a1 bnez v0, .Lfault\@ FEXPORT(__strncpy_from_\func\()_nocheck_asm) +EXPORT_SYMBOL(__strncpy_from_\func\()_nocheck_asm) move t0, zero move v1, a1 .ifeqs "\func","kernel" @@ -72,6 +75,8 @@ FEXPORT(__strncpy_from_\func\()_nocheck_asm) .global __strncpy_from_user_nocheck_asm .set __strncpy_from_user_asm, __strncpy_from_kernel_asm .set __strncpy_from_user_nocheck_asm, __strncpy_from_kernel_nocheck_asm + EXPORT_SYMBOL(__strncpy_from_user_asm) + EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm) #endif __BUILD_STRNCPY_ASM kernel diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S index 77e64942f004..3ac38162d7f0 100644 --- a/arch/mips/lib/strnlen_user.S +++ b/arch/mips/lib/strnlen_user.S @@ -8,6 +8,7 @@ */ #include #include +#include #include #define EX(insn,reg,addr,handler) \ @@ -27,11 +28,13 @@ */ .macro __BUILD_STRNLEN_ASM func LEAF(__strnlen_\func\()_asm) +EXPORT_SYMBOL(__strnlen_\func\()_asm) LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? and v0, a0 bnez v0, .Lfault\@ FEXPORT(__strnlen_\func\()_nocheck_asm) +EXPORT_SYMBOL(__strnlen_\func\()_nocheck_asm) move v0, a0 PTR_ADDU a1, a0 # stop pointer 1: -- cgit v1.2.3 From 576a2f0c5c6d64648d2ba68a4edbbe61863e12e2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 11:14:15 +0000 Subject: MIPS: Export memcpy & memset functions alongside their definitions Now that EXPORT_SYMBOL can be used from assembly source, move the EXPORT_SYMBOL invocations for the memcpy & memset functions & variants thereof to be alongside their definitions. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14514/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-memcpy.S | 5 +++++ arch/mips/kernel/mips_ksyms.c | 24 ------------------------ arch/mips/lib/memcpy.S | 9 +++++++++ arch/mips/lib/memset.S | 5 +++++ 4 files changed, 19 insertions(+), 24 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S index 64e08df51d65..7d96d9c72c74 100644 --- a/arch/mips/cavium-octeon/octeon-memcpy.S +++ b/arch/mips/cavium-octeon/octeon-memcpy.S @@ -15,6 +15,7 @@ #include #include +#include #include #define dst a0 @@ -142,6 +143,7 @@ * t7 is used as a flag to note inatomic mode. */ LEAF(__copy_user_inatomic) +EXPORT_SYMBOL(__copy_user_inatomic) b __copy_user_common li t7, 1 END(__copy_user_inatomic) @@ -154,9 +156,11 @@ LEAF(__copy_user_inatomic) */ .align 5 LEAF(memcpy) /* a0=dst a1=src a2=len */ +EXPORT_SYMBOL(memcpy) move v0, dst /* return value */ __memcpy: FEXPORT(__copy_user) +EXPORT_SYMBOL(__copy_user) li t7, 0 /* not inatomic */ __copy_user_common: /* @@ -459,6 +463,7 @@ s_exc: .align 5 LEAF(memmove) +EXPORT_SYMBOL(memmove) ADD t0, a0, a2 ADD t1, a1, a2 sltu t0, a1, t0 # dst + len <= src -> memcpy diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index a84f75088247..f01838faae2b 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -17,32 +17,8 @@ #include #include -extern void *__bzero_kernel(void *__s, size_t __count); -extern void *__bzero(void *__s, size_t __count); - -/* - * String functions - */ -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memmove); - /* * Functions that operate on entire pages. Mostly used by memory management. */ EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(copy_page); - -/* - * Userspace access stuff. - */ -EXPORT_SYMBOL(__copy_user); -EXPORT_SYMBOL(__copy_user_inatomic); -#ifdef CONFIG_EVA -EXPORT_SYMBOL(__copy_from_user_eva); -EXPORT_SYMBOL(__copy_in_user_eva); -EXPORT_SYMBOL(__copy_to_user_eva); -EXPORT_SYMBOL(__copy_user_inatomic_eva); -EXPORT_SYMBOL(__bzero_kernel); -#endif -EXPORT_SYMBOL(__bzero); diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index 6c303a94a196..c3031f18c572 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S @@ -31,6 +31,7 @@ #include #include +#include #include #define dst a0 @@ -622,6 +623,7 @@ SEXC(1) .align 5 LEAF(memmove) +EXPORT_SYMBOL(memmove) ADD t0, a0, a2 ADD t1, a1, a2 sltu t0, a1, t0 # dst + len <= src -> memcpy @@ -674,6 +676,7 @@ LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ * t6 is used as a flag to note inatomic mode. */ LEAF(__copy_user_inatomic) +EXPORT_SYMBOL(__copy_user_inatomic) b __copy_user_common li t6, 1 END(__copy_user_inatomic) @@ -686,9 +689,11 @@ LEAF(__copy_user_inatomic) */ .align 5 LEAF(memcpy) /* a0=dst a1=src a2=len */ +EXPORT_SYMBOL(memcpy) move v0, dst /* return value */ .L__memcpy: FEXPORT(__copy_user) +EXPORT_SYMBOL(__copy_user) li t6, 0 /* not inatomic */ __copy_user_common: /* Legacy Mode, user <-> user */ @@ -704,6 +709,7 @@ __copy_user_common: */ LEAF(__copy_user_inatomic_eva) +EXPORT_SYMBOL(__copy_user_inatomic_eva) b __copy_from_user_common li t6, 1 END(__copy_user_inatomic_eva) @@ -713,6 +719,7 @@ LEAF(__copy_user_inatomic_eva) */ LEAF(__copy_from_user_eva) +EXPORT_SYMBOL(__copy_from_user_eva) li t6, 0 /* not inatomic */ __copy_from_user_common: __BUILD_COPY_USER EVA_MODE USEROP KERNELOP @@ -725,6 +732,7 @@ END(__copy_from_user_eva) */ LEAF(__copy_to_user_eva) +EXPORT_SYMBOL(__copy_to_user_eva) __BUILD_COPY_USER EVA_MODE KERNELOP USEROP END(__copy_to_user_eva) @@ -733,6 +741,7 @@ END(__copy_to_user_eva) */ LEAF(__copy_in_user_eva) +EXPORT_SYMBOL(__copy_in_user_eva) __BUILD_COPY_USER EVA_MODE USEROP USEROP END(__copy_in_user_eva) diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 18a1ccd4d134..a1456664d6c2 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S @@ -10,6 +10,7 @@ */ #include #include +#include #include #if LONGSIZE == 4 @@ -270,6 +271,7 @@ */ LEAF(memset) +EXPORT_SYMBOL(memset) beqz a1, 1f move v0, a0 /* result */ @@ -285,13 +287,16 @@ LEAF(memset) 1: #ifndef CONFIG_EVA FEXPORT(__bzero) +EXPORT_SYMBOL(__bzero) #else FEXPORT(__bzero_kernel) +EXPORT_SYMBOL(__bzero_kernel) #endif __BUILD_BZERO LEGACY_MODE #ifdef CONFIG_EVA LEAF(__bzero) +EXPORT_SYMBOL(__bzero) __BUILD_BZERO EVA_MODE END(__bzero) #endif -- cgit v1.2.3 From f44374f14c388d1170404d2206d4ff760d018212 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 7 Nov 2016 11:14:16 +0000 Subject: MIPS: Export {copy, clear}_page functions alongside their definitions Now that EXPORT_SYMBOL can be used from assembly source, move the EXPORT_SYMBOL invocations for the copy_page & clear_page functions to be alongside their definitions. With this change there are no longer any symbols exported from mips_ksyms.c so remove the file. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14515/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/mips_ksyms.c | 24 ------------------------ arch/mips/mm/page-funcs.S | 3 +++ arch/mips/mm/page.c | 2 ++ 4 files changed, 6 insertions(+), 25 deletions(-) delete mode 100644 arch/mips/kernel/mips_ksyms.c (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 904a9c48553a..9a0e37b92ce0 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -30,7 +30,7 @@ obj-$(CONFIG_SYNC_R4K) += sync-r4k.o obj-$(CONFIG_DEBUG_FS) += segment.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_MODULES) += mips_ksyms.o module.o +obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c deleted file mode 100644 index f01838faae2b..000000000000 --- a/arch/mips/kernel/mips_ksyms.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Export MIPS-specific functions needed for loadable modules. - * - * 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. - * - * Copyright (C) 1996, 97, 98, 99, 2000, 01, 03, 04, 05, 12 by Ralf Baechle - * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Functions that operate on entire pages. Mostly used by memory management. - */ -EXPORT_SYMBOL(clear_page); -EXPORT_SYMBOL(copy_page); diff --git a/arch/mips/mm/page-funcs.S b/arch/mips/mm/page-funcs.S index 48a6b38ff13e..43181ac0a1af 100644 --- a/arch/mips/mm/page-funcs.S +++ b/arch/mips/mm/page-funcs.S @@ -9,6 +9,7 @@ * Copyright (C) 2012 Ralf Baechle */ #include +#include #include #ifdef CONFIG_SIBYTE_DMA_PAGEOPS @@ -29,6 +30,7 @@ */ EXPORT(__clear_page_start) LEAF(cpu_clear_page_function_name) +EXPORT_SYMBOL(cpu_clear_page_function_name) 1: j 1b /* Dummy, will be replaced. */ .space 288 END(cpu_clear_page_function_name) @@ -44,6 +46,7 @@ EXPORT(__clear_page_end) */ EXPORT(__copy_page_start) LEAF(cpu_copy_page_function_name) +EXPORT_SYMBOL(cpu_copy_page_function_name) 1: j 1b /* Dummy, will be replaced. */ .space 1344 END(cpu_copy_page_function_name) diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 6f804f5960ab..d5d02993aa21 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -661,6 +661,7 @@ void clear_page(void *page) ; __raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE))); } +EXPORT_SYMBOL(clear_page); void copy_page(void *to, void *from) { @@ -687,5 +688,6 @@ void copy_page(void *to, void *from) ; __raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE))); } +EXPORT_SYMBOL(copy_page); #endif /* CONFIG_SIBYTE_DMA_PAGEOPS */ -- cgit v1.2.3 From 35e7f7885e1b1b272a73c0de3227fc9a3e95a7e3 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 3 Jan 2017 14:51:20 +0000 Subject: MIPS: Fix printk continuations in cpu-bugs64.c 64-bit pre-r6 kernels output the following broken printk continuation lines during boot: Checking for the multiply/shift bug... no. Checking for the daddiu bug... no. Checking for the daddi bug... no. Fix the printk continuations in cpu-bugs64.c to use pr_cont to restore the correct output: Checking for the multiply/shift bug... no. Checking for the daddiu bug... no. Checking for the daddi bug... no. Signed-off-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14916/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-bugs64.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index a378e44688f5..c9e8622b5a16 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -148,11 +148,11 @@ static inline void check_mult_sh(void) bug = 1; if (bug == 0) { - printk("no.\n"); + pr_cont("no.\n"); return; } - printk("yes, workaround... "); + pr_cont("yes, workaround... "); fix = 1; for (i = 0; i < 8; i++) @@ -160,11 +160,11 @@ static inline void check_mult_sh(void) fix = 0; if (fix == 1) { - printk("yes.\n"); + pr_cont("yes.\n"); return; } - printk("no.\n"); + pr_cont("no.\n"); panic(bug64hit, !R4000_WAR ? r4kwar : nowar); } @@ -218,11 +218,11 @@ static inline void check_daddi(void) local_irq_restore(flags); if (daddi_ov) { - printk("no.\n"); + pr_cont("no.\n"); return; } - printk("yes, workaround... "); + pr_cont("yes, workaround... "); local_irq_save(flags); handler = set_except_vector(EXCCODE_OV, handle_daddi_ov); @@ -236,11 +236,11 @@ static inline void check_daddi(void) local_irq_restore(flags); if (daddi_ov) { - printk("yes.\n"); + pr_cont("yes.\n"); return; } - printk("no.\n"); + pr_cont("no.\n"); panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); } @@ -288,11 +288,11 @@ static inline void check_daddiu(void) daddiu_bug = v != w; if (!daddiu_bug) { - printk("no.\n"); + pr_cont("no.\n"); return; } - printk("yes, workaround... "); + pr_cont("yes, workaround... "); asm volatile( "addiu %2, $0, %3\n\t" @@ -304,11 +304,11 @@ static inline void check_daddiu(void) : "I" (0xffffffffffffdb9aUL), "I" (0x1234)); if (v == w) { - printk("yes.\n"); + pr_cont("yes.\n"); return; } - printk("no.\n"); + pr_cont("no.\n"); panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); } -- cgit v1.2.3 From fcf4aec13b56edcfc837fa138d8b1d99b26e5ce4 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 18 Jan 2017 19:00:05 +0100 Subject: MIPS: Return directly in 32_mmap2() * Return a failure indication without storing it in an intermediate variable. * Delete the local variable "error" which became unnecessary with this refactoring. Signed-off-by: Markus Elfring Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: LKML Cc: kernel-janitors@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15071/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/linux32.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 0352f742d077..b01bdef101a8 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -64,15 +64,10 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, pgoff) { - unsigned long error; - - error = -EINVAL; if (pgoff & (~PAGE_MASK >> 12)) - goto out; - error = sys_mmap_pgoff(addr, len, prot, flags, fd, - pgoff >> (PAGE_SHIFT-12)); -out: - return error; + return -EINVAL; + return sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT-12)); } #define RLIM_INFINITY32 0x7fffffff -- cgit v1.2.3 From a45526bb78529911eb6b2525347762e977fce125 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 18 Jan 2017 19:18:37 +0100 Subject: MIPS: MT: Move an assignment for the variable "retval" in mipsmt_sys_sched_setaffinity() A local variable was set to an error code in one case before a concrete error situation was detected. Thus move the corresponding assignment into an if branch to indicate a software failure there. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: LKML Cc: kernel-janitors@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15072/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mips-mt-fpaff.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index a12904ea9f65..1a0a3b4ecc3e 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c @@ -99,9 +99,10 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, retval = -ENOMEM; goto out_free_new_mask; } - retval = -EPERM; - if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) + if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) { + retval = -EPERM; goto out_unlock; + } retval = security_task_setscheduler(p); if (retval) -- cgit v1.2.3 From c9d3fdf3372d06690fd5cbc1ac5beabe52927382 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 18 Jan 2017 19:30:47 +0100 Subject: MIPS: syscall: Return directly in mips_mmap() * Return an error code without storing it in an intermediate variable. * Delete the local variable "result" which became unnecessary with this refactoring. Signed-off-by: Markus Elfring Cc: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: LKML Cc: kernel-janitors@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15073/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/syscall.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 833f82210528..735733fd7145 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -60,16 +60,9 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, off_t, offset) { - unsigned long result; - - result = -EINVAL; if (offset & ~PAGE_MASK) - goto out; - - result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); - -out: - return result; + return -EINVAL; + return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); } SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len, -- cgit v1.2.3 From 4828b5f56f9596f014567ceef0e5c200fb582e13 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 10 Feb 2017 22:44:03 +0000 Subject: MIPS: Fix cacheinfo overflow The recently added MIPS cacheinfo support used a macro populate_cache() to populate the cacheinfo structures depending on which caches are present. However the macro contains multiple statements without enclosing them in a do {} while (0) loop, so the L2 and L3 cache conditionals in populate_cache_leaves() only conditionalised the first statement in the macro. This overflows the buffer allocated by detect_cache_attributes(), resulting in boot failures under QEMU where neither the L2 or L2 caches are present. Enclose the macro statements in a do {} while (0) block to keep the whole macro inside the conditionals. Fixes: ef462f3b64e9 ("MIPS: Add cacheinfo support") Reported-by: Guenter Roeck Signed-off-by: James Hogan Tested-by: Guenter Roeck Cc: Ralf Baechle Cc: Justin Chen Cc: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: bcm-kernel-feedback-list@broadcom.com Patchwork: https://patchwork.linux-mips.org/patch/15276/ --- arch/mips/kernel/cacheinfo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/cacheinfo.c b/arch/mips/kernel/cacheinfo.c index a92bbbae969b..97d5239ca47b 100644 --- a/arch/mips/kernel/cacheinfo.c +++ b/arch/mips/kernel/cacheinfo.c @@ -17,6 +17,7 @@ /* Populates leaf and increments to next leaf */ #define populate_cache(cache, leaf, c_level, c_type) \ +do { \ leaf->type = c_type; \ leaf->level = c_level; \ leaf->coherency_line_size = c->cache.linesz; \ @@ -24,7 +25,8 @@ leaf->ways_of_associativity = c->cache.ways; \ leaf->size = c->cache.linesz * c->cache.sets * \ c->cache.ways; \ - leaf++; + leaf++; \ +} while (0) static int __init_cache_level(unsigned int cpu) { -- cgit v1.2.3 From c25f8064c1d5731a2ce5664def890140dcdd3e5c Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Wed, 25 Jan 2017 17:00:25 +0000 Subject: MIPS: IRQ Stack: Fix erroneous jal to plat_irq_dispatch Commit dda45f701c9d ("MIPS: Switch to the irq_stack in interrupts") changed both the normal and vectored interrupt handlers. Unfortunately the vectored version, "except_vec_vi_handler", was incorrectly modified to unconditionally jal to plat_irq_dispatch, rather than doing a jalr to the vectored handler that has been set up. This is ok for many platforms which set the vectored handler to plat_irq_dispatch anyway, but will cause problems with platforms that use other handlers. Fixes: dda45f701c9d ("MIPS: Switch to the irq_stack in interrupts") Signed-off-by: Matt Redfearn Cc: Ralf Baechle Cc: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15110/ Signed-off-by: James Hogan --- arch/mips/kernel/genex.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 0a7ba4b2f687..7ec9612cb007 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -329,7 +329,7 @@ NESTED(except_vec_vi_handler, 0, sp) PTR_ADD sp, t0, t1 2: - jal plat_irq_dispatch + jalr v0 /* Restore sp */ move sp, s1 -- cgit v1.2.3 From 4fb69afa767777360201a43725ddd7f7c64459bb Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Thu, 2 Feb 2017 13:22:04 +0000 Subject: MIPS: sync-r4k: Fix KERN_CONT fallout Since commit 4bcc595ccd80 ("printk: reinstate KERN_CONT for printing continuation lines") the output of counter synchornisation has been split across lines: [ 0.665181] Synchronize counters for CPU 1: [ 0.678578] done. Fix this by using pr_cont, and replace printk with pr_info. Signed-off-by: Matt Redfearn Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15195/ Signed-off-by: James Hogan --- arch/mips/kernel/sync-r4k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c index 4472a7f98577..1df1160b6a47 100644 --- a/arch/mips/kernel/sync-r4k.c +++ b/arch/mips/kernel/sync-r4k.c @@ -29,7 +29,7 @@ void synchronise_count_master(int cpu) int i; unsigned long flags; - printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu); + pr_info("Synchronize counters for CPU %u: ", cpu); local_irq_save(flags); @@ -83,7 +83,7 @@ void synchronise_count_master(int cpu) * count registers were almost certainly out of sync * so no point in alarming people */ - printk("done.\n"); + pr_cont("done.\n"); } void synchronise_count_slave(int cpu) -- cgit v1.2.3 From 2654294bac83a64101c360eac4d42d5ac1b1b911 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 6 Feb 2017 12:37:45 +0000 Subject: MIPS: Unify perf counter register definitions Unify definitions for MIPS performance counter register fields in mipsregs.h rather than duplicating them in perf_events and oprofile. This will allow future patches to use them to expose performance counters to KVM guests. Signed-off-by: James Hogan Cc: Ralf Baechle Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Robert Richter Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: oprofile-list@lists.sf.net Patchwork: https://patchwork.linux-mips.org/patch/15212/ Signed-off-by: James Hogan --- arch/mips/include/asm/mipsregs.h | 33 ++++++++++++++++++++++ arch/mips/kernel/perf_event_mipsxx.c | 55 +++++++++++++++--------------------- arch/mips/oprofile/op_model_mipsxx.c | 40 +++++++++----------------- 3 files changed, 69 insertions(+), 59 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index df78b2ca70eb..f8d1d2f1d80d 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -685,6 +685,39 @@ #define MIPS_WATCHHI_W (_ULCAST_(1) << 0) #define MIPS_WATCHHI_IRW (_ULCAST_(0x7) << 0) +/* PerfCnt control register definitions */ +#define MIPS_PERFCTRL_EXL (_ULCAST_(1) << 0) +#define MIPS_PERFCTRL_K (_ULCAST_(1) << 1) +#define MIPS_PERFCTRL_S (_ULCAST_(1) << 2) +#define MIPS_PERFCTRL_U (_ULCAST_(1) << 3) +#define MIPS_PERFCTRL_IE (_ULCAST_(1) << 4) +#define MIPS_PERFCTRL_EVENT_S 5 +#define MIPS_PERFCTRL_EVENT (_ULCAST_(0x3ff) << MIPS_PERFCTRL_EVENT_S) +#define MIPS_PERFCTRL_PCTD (_ULCAST_(1) << 15) +#define MIPS_PERFCTRL_EC (_ULCAST_(0x3) << 23) +#define MIPS_PERFCTRL_EC_R (_ULCAST_(0) << 23) +#define MIPS_PERFCTRL_EC_RI (_ULCAST_(1) << 23) +#define MIPS_PERFCTRL_EC_G (_ULCAST_(2) << 23) +#define MIPS_PERFCTRL_EC_GRI (_ULCAST_(3) << 23) +#define MIPS_PERFCTRL_W (_ULCAST_(1) << 30) +#define MIPS_PERFCTRL_M (_ULCAST_(1) << 31) + +/* PerfCnt control register MT extensions used by MIPS cores */ +#define MIPS_PERFCTRL_VPEID_S 16 +#define MIPS_PERFCTRL_VPEID (_ULCAST_(0xf) << MIPS_PERFCTRL_VPEID_S) +#define MIPS_PERFCTRL_TCID_S 22 +#define MIPS_PERFCTRL_TCID (_ULCAST_(0xff) << MIPS_PERFCTRL_TCID_S) +#define MIPS_PERFCTRL_MT_EN (_ULCAST_(0x3) << 20) +#define MIPS_PERFCTRL_MT_EN_ALL (_ULCAST_(0) << 20) +#define MIPS_PERFCTRL_MT_EN_VPE (_ULCAST_(1) << 20) +#define MIPS_PERFCTRL_MT_EN_TC (_ULCAST_(2) << 20) + +/* PerfCnt control register MT extensions used by BMIPS5000 */ +#define BRCM_PERFCTRL_TC (_ULCAST_(1) << 30) + +/* PerfCnt control register MT extensions used by Netlogic XLR */ +#define XLR_PERFCTRL_ALLTHREADS (_ULCAST_(1) << 13) + /* MAAR bit definitions */ #define MIPS_MAAR_ADDR ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12) #define MIPS_MAAR_ADDR_SHIFT 12 diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index d3ba9f4105b5..8c35b3152e1e 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -101,40 +101,31 @@ struct mips_pmu { static struct mips_pmu mipspmu; -#define M_PERFCTL_EXL (1 << 0) -#define M_PERFCTL_KERNEL (1 << 1) -#define M_PERFCTL_SUPERVISOR (1 << 2) -#define M_PERFCTL_USER (1 << 3) -#define M_PERFCTL_INTERRUPT_ENABLE (1 << 4) -#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5) -#define M_PERFCTL_VPEID(vpe) ((vpe) << 16) +#define M_PERFCTL_EVENT(event) (((event) << MIPS_PERFCTRL_EVENT_S) & \ + MIPS_PERFCTRL_EVENT) +#define M_PERFCTL_VPEID(vpe) ((vpe) << MIPS_PERFCTRL_VPEID_S) #ifdef CONFIG_CPU_BMIPS5000 #define M_PERFCTL_MT_EN(filter) 0 #else /* !CONFIG_CPU_BMIPS5000 */ -#define M_PERFCTL_MT_EN(filter) ((filter) << 20) +#define M_PERFCTL_MT_EN(filter) (filter) #endif /* CONFIG_CPU_BMIPS5000 */ -#define M_TC_EN_ALL M_PERFCTL_MT_EN(0) -#define M_TC_EN_VPE M_PERFCTL_MT_EN(1) -#define M_TC_EN_TC M_PERFCTL_MT_EN(2) -#define M_PERFCTL_TCID(tcid) ((tcid) << 22) -#define M_PERFCTL_WIDE (1 << 30) -#define M_PERFCTL_MORE (1 << 31) -#define M_PERFCTL_TC (1 << 30) +#define M_TC_EN_ALL M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_ALL) +#define M_TC_EN_VPE M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_VPE) +#define M_TC_EN_TC M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_TC) -#define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \ - M_PERFCTL_KERNEL | \ - M_PERFCTL_USER | \ - M_PERFCTL_SUPERVISOR | \ - M_PERFCTL_INTERRUPT_ENABLE) +#define M_PERFCTL_COUNT_EVENT_WHENEVER (MIPS_PERFCTRL_EXL | \ + MIPS_PERFCTRL_K | \ + MIPS_PERFCTRL_U | \ + MIPS_PERFCTRL_S | \ + MIPS_PERFCTRL_IE) #ifdef CONFIG_MIPS_MT_SMP #define M_PERFCTL_CONFIG_MASK 0x3fff801f #else #define M_PERFCTL_CONFIG_MASK 0x1f #endif -#define M_PERFCTL_EVENT_MASK 0xfe0 #ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS @@ -345,11 +336,11 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) | (evt->config_base & M_PERFCTL_CONFIG_MASK) | /* Make sure interrupt enabled. */ - M_PERFCTL_INTERRUPT_ENABLE; + MIPS_PERFCTRL_IE; if (IS_ENABLED(CONFIG_CPU_BMIPS5000)) /* enable the counter for the calling thread */ cpuc->saved_ctrl[idx] |= - (1 << (12 + vpe_id())) | M_PERFCTL_TC; + (1 << (12 + vpe_id())) | BRCM_PERFCTRL_TC; /* * We do not actually let the counter run. Leave it until start(). @@ -754,11 +745,11 @@ static int __n_counters(void) { if (!cpu_has_perf) return 0; - if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) + if (!(read_c0_perfctrl0() & MIPS_PERFCTRL_M)) return 1; - if (!(read_c0_perfctrl1() & M_PERFCTL_MORE)) + if (!(read_c0_perfctrl1() & MIPS_PERFCTRL_M)) return 2; - if (!(read_c0_perfctrl2() & M_PERFCTL_MORE)) + if (!(read_c0_perfctrl2() & MIPS_PERFCTRL_M)) return 3; return 4; @@ -1339,7 +1330,7 @@ static int __hw_perf_event_init(struct perf_event *event) * We allow max flexibility on how each individual counter shared * by the single CPU operates (the mode exclusion and the range). */ - hwc->config_base = M_PERFCTL_INTERRUPT_ENABLE; + hwc->config_base = MIPS_PERFCTRL_IE; /* Calculate range bits and validate it. */ if (num_possible_cpus() > 1) @@ -1350,14 +1341,14 @@ static int __hw_perf_event_init(struct perf_event *event) mutex_unlock(&raw_event_mutex); if (!attr->exclude_user) - hwc->config_base |= M_PERFCTL_USER; + hwc->config_base |= MIPS_PERFCTRL_U; if (!attr->exclude_kernel) { - hwc->config_base |= M_PERFCTL_KERNEL; + hwc->config_base |= MIPS_PERFCTRL_K; /* MIPS kernel mode: KSU == 00b || EXL == 1 || ERL == 1 */ - hwc->config_base |= M_PERFCTL_EXL; + hwc->config_base |= MIPS_PERFCTRL_EXL; } if (!attr->exclude_hv) - hwc->config_base |= M_PERFCTL_SUPERVISOR; + hwc->config_base |= MIPS_PERFCTRL_S; hwc->config_base &= M_PERFCTL_CONFIG_MASK; /* @@ -1830,7 +1821,7 @@ init_hw_perf_events(void) mipspmu.num_counters = counters; mipspmu.irq = irq; - if (read_c0_perfctrl0() & M_PERFCTL_WIDE) { + if (read_c0_perfctrl0() & MIPS_PERFCTRL_W) { mipspmu.max_period = (1ULL << 63) - 1; mipspmu.valid_count = (1ULL << 63) - 1; mipspmu.overflow = 1ULL << 63; diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 45cb27469fba..c57da6f13929 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -15,26 +15,12 @@ #include "op_impl.h" -#define M_PERFCTL_EXL (1UL << 0) -#define M_PERFCTL_KERNEL (1UL << 1) -#define M_PERFCTL_SUPERVISOR (1UL << 2) -#define M_PERFCTL_USER (1UL << 3) -#define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4) -#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5) -#define M_PERFCTL_VPEID(vpe) ((vpe) << 16) -#define M_PERFCTL_MT_EN(filter) ((filter) << 20) -#define M_TC_EN_ALL M_PERFCTL_MT_EN(0) -#define M_TC_EN_VPE M_PERFCTL_MT_EN(1) -#define M_TC_EN_TC M_PERFCTL_MT_EN(2) -#define M_PERFCTL_TCID(tcid) ((tcid) << 22) -#define M_PERFCTL_WIDE (1UL << 30) -#define M_PERFCTL_MORE (1UL << 31) +#define M_PERFCTL_EVENT(event) (((event) << MIPS_PERFCTRL_EVENT_S) & \ + MIPS_PERFCTRL_EVENT) +#define M_PERFCTL_VPEID(vpe) ((vpe) << MIPS_PERFCTRL_VPEID_S) #define M_COUNTER_OVERFLOW (1UL << 31) -/* Netlogic XLR specific, count events in all threads in a core */ -#define M_PERFCTL_COUNT_ALL_THREADS (1UL << 13) - static int (*save_perf_irq)(void); static int perfcount_irq; @@ -51,7 +37,7 @@ static int perfcount_irq; #ifdef CONFIG_MIPS_MT_SMP static int cpu_has_mipsmt_pertccounters; -#define WHAT (M_TC_EN_VPE | \ +#define WHAT (MIPS_PERFCTRL_MT_EN_VPE | \ M_PERFCTL_VPEID(cpu_data[smp_processor_id()].vpe_id)) #define vpe_id() (cpu_has_mipsmt_pertccounters ? \ 0 : cpu_data[smp_processor_id()].vpe_id) @@ -161,15 +147,15 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr) continue; reg.control[i] = M_PERFCTL_EVENT(ctr[i].event) | - M_PERFCTL_INTERRUPT_ENABLE; + MIPS_PERFCTRL_IE; if (ctr[i].kernel) - reg.control[i] |= M_PERFCTL_KERNEL; + reg.control[i] |= MIPS_PERFCTRL_K; if (ctr[i].user) - reg.control[i] |= M_PERFCTL_USER; + reg.control[i] |= MIPS_PERFCTRL_U; if (ctr[i].exl) - reg.control[i] |= M_PERFCTL_EXL; + reg.control[i] |= MIPS_PERFCTRL_EXL; if (boot_cpu_type() == CPU_XLR) - reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS; + reg.control[i] |= XLR_PERFCTRL_ALLTHREADS; reg.counter[i] = 0x80000000 - ctr[i].count; } } @@ -254,7 +240,7 @@ static int mipsxx_perfcount_handler(void) case n + 1: \ control = r_c0_perfctrl ## n(); \ counter = r_c0_perfcntr ## n(); \ - if ((control & M_PERFCTL_INTERRUPT_ENABLE) && \ + if ((control & MIPS_PERFCTRL_IE) && \ (counter & M_COUNTER_OVERFLOW)) { \ oprofile_add_sample(get_irq_regs(), n); \ w_c0_perfcntr ## n(reg.counter[n]); \ @@ -273,11 +259,11 @@ static inline int __n_counters(void) { if (!cpu_has_perf) return 0; - if (!(read_c0_perfctrl0() & M_PERFCTL_MORE)) + if (!(read_c0_perfctrl0() & MIPS_PERFCTRL_M)) return 1; - if (!(read_c0_perfctrl1() & M_PERFCTL_MORE)) + if (!(read_c0_perfctrl1() & MIPS_PERFCTRL_M)) return 2; - if (!(read_c0_perfctrl2() & M_PERFCTL_MORE)) + if (!(read_c0_perfctrl2() & MIPS_PERFCTRL_M)) return 3; return 4; -- cgit v1.2.3 From 9606de36b21fe1fafb7b68a8ed5cfaf128871e97 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 6 Feb 2017 16:26:50 +0000 Subject: MIPS: sysmips: Remove duplicated include from syscall.c Remove duplicated include. Fixes: 7c0f6ba682b9 ("Replace with globally") Signed-off-by: Wei Yongjun Cc: Ralf Baechle Cc: Markus Elfring Cc: Wei Yongjun Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/15213/ Signed-off-by: James Hogan --- arch/mips/kernel/syscall.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 735733fd7145..c86ddbaa4598 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -36,7 +36,6 @@ #include #include #include -#include #include /* -- cgit v1.2.3