linux/arch/riscv/kernel/process.c
Linus Torvalds dbf8381731 RISC-V Patches for the 5.9 Merge Window, Part 1
We have a lot of new kernel features for this merge window:
 
 * ARCH_SUPPORTS_ATOMIC_RMW, to allow OSQ locks to be enabled.
 * The ability to enable NO_HZ_FULL
 * Support for enabling kcov, kmemleak, stack protector, and VM debugging.
 * JUMP_LABEL support.
 
 There are also a handful of cleanups.
 
 next points out a trivial Kconfig merge conflict.  I don't see any way to have
 done this better: the symbols are sorted, it just happens that
 HAVE_COPY_THREAD_TLS was in the middle of two new symbols.  In case it helps
 any, here's a pretty current conflict resolution:
 
 diff --cc arch/riscv/Kconfig
 index bc37241a6875,6c4bce7cad8a..7b5905529146
 --- a/arch/riscv/Kconfig
 +++ b/arch/riscv/Kconfig
 @@@ -57,9 -54,6 +59,8 @@@ config RISC
         select HAVE_ARCH_SECCOMP_FILTER
         select HAVE_ARCH_TRACEHOOK
         select HAVE_ASM_MODVERSIONS
  +      select HAVE_CONTEXT_TRACKING
 -       select HAVE_COPY_THREAD_TLS
  +      select HAVE_DEBUG_KMEMLEAK
         select HAVE_DMA_CONTIGUOUS if MMU
         select HAVE_EBPF_JIT if MMU
         select HAVE_FUTEX_CMPXCHG if FUTEX
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCgAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAl8sa2YTHHBhbG1lckBk
 YWJiZWx0LmNvbQAKCRAuExnzX7sYieFTD/0RlhicBrn5UGpaUwtgwuMENYOrb3pn
 5SsPzhCni3/8HvMzr/gOGHWM2YOQZkY5FReIqy1IdbPSe/exjv6DyKMdZr+OI+3+
 232TAwAtILGlKB+zBMJWA3eLah0pbDvs7RpuhiPfWSzzWUrAMHcGSq0TzM2pYe1r
 KPOLj6bSKpnZO+Dto80V8w4ZeWmtAArVDiujIy8zlvgpM1Z66C2SazloQH7HkPS7
 D2hvLZZU00etyAZI/aJJsemCBRg9nsVoqGTBSXWpUPATBRMZFfHovbh7AUJlqY5E
 HPHBSf3KDeOjoF8EXkvT/6z5Q6+LUpRyK+KKwWCs/337i1652P31nczDps9J6Eq0
 IC3J/YWcy4eZ7pMEps0vQmr9aX+FusOCJUmJqJW77Uzi0fHHTXa+O3olwiz/JqYz
 c3yIihVAvtw9eCSoqlL7YoL9HNyfrXKCtZ4l/DLjwGG5WJw7C7mGMbBMClcD4ytU
 /Z91ON/UgWFW5805dBaajp72SStp1FP54HsAH5E12XYZSiepnu70G3BUNJHvDJT5
 QOKkrhOswwit5DW30Celh6kmtidAWiavy6R0AbbpcqI+bItkEZWD1BSStTc0WdhV
 JgOp0ieCzu5Jyw03KC1nZA8VgM3zrAmU0moSDqirddzNYuuBTqt39doZOEs1MS2W
 TiR1JSnGNaKl4Q==
 =asH5
 -----END PGP SIGNATURE-----

Merge tag 'riscv-for-linus-5.9-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V updates from Palmer Dabbelt:
 "We have a lot of new kernel features for this merge window:

   - ARCH_SUPPORTS_ATOMIC_RMW, to allow OSQ locks to be enabled

   - The ability to enable NO_HZ_FULL

   - Support for enabling kcov, kmemleak, stack protector, and VM
     debugging

   - JUMP_LABEL support

  There are also a handful of cleanups"

* tag 'riscv-for-linus-5.9-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (24 commits)
  riscv: disable stack-protector for vDSO
  RISC-V: Fix build warning for smpboot.c
  riscv: fix build warning of mm/pageattr
  riscv: Fix build warning for mm/init
  RISC-V: Setup exception vector early
  riscv: Select ARCH_HAS_DEBUG_VM_PGTABLE
  riscv: Use generic pgprot_* macros from <linux/pgtable.h>
  mm: pgtable: Make generic pgprot_* macros available for no-MMU
  riscv: Cleanup unnecessary define in asm-offset.c
  riscv: Add jump-label implementation
  riscv: Support R_RISCV_ADD64 and R_RISCV_SUB64 relocs
  Replace HTTP links with HTTPS ones: RISC-V
  riscv: Add STACKPROTECTOR supported
  riscv: Fix typo in asm/hwcap.h uapi header
  riscv: Add kmemleak support
  riscv: Allow building with kcov coverage
  riscv: Enable context tracking
  riscv: Support irq_work via self IPIs
  riscv: Enable LOCKDEP_SUPPORT & fixup TRACE_IRQFLAGS_SUPPORT
  riscv: Fixup lockdep_assert_held with wrong param cpu_running
  ...
2020-08-07 10:11:12 -07:00

138 lines
3.9 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
* Chen Liqin <liqin.chen@sunplusct.com>
* Lennox Wu <lennox.wu@sunplusct.com>
* Copyright (C) 2012 Regents of the University of California
* Copyright (C) 2017 SiFive
*/
#include <linux/cpu.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/tick.h>
#include <linux/ptrace.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
#include <asm/processor.h>
#include <asm/csr.h>
#include <asm/string.h>
#include <asm/switch_to.h>
#include <asm/thread_info.h>
register unsigned long gp_in_global __asm__("gp");
#ifdef CONFIG_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif
extern asmlinkage void ret_from_fork(void);
extern asmlinkage void ret_from_kernel_thread(void);
void arch_cpu_idle(void)
{
wait_for_interrupt();
local_irq_enable();
}
void show_regs(struct pt_regs *regs)
{
show_regs_print_info(KERN_DEFAULT);
pr_cont("epc: " REG_FMT " ra : " REG_FMT " sp : " REG_FMT "\n",
regs->epc, regs->ra, regs->sp);
pr_cont(" gp : " REG_FMT " tp : " REG_FMT " t0 : " REG_FMT "\n",
regs->gp, regs->tp, regs->t0);
pr_cont(" t1 : " REG_FMT " t2 : " REG_FMT " s0 : " REG_FMT "\n",
regs->t1, regs->t2, regs->s0);
pr_cont(" s1 : " REG_FMT " a0 : " REG_FMT " a1 : " REG_FMT "\n",
regs->s1, regs->a0, regs->a1);
pr_cont(" a2 : " REG_FMT " a3 : " REG_FMT " a4 : " REG_FMT "\n",
regs->a2, regs->a3, regs->a4);
pr_cont(" a5 : " REG_FMT " a6 : " REG_FMT " a7 : " REG_FMT "\n",
regs->a5, regs->a6, regs->a7);
pr_cont(" s2 : " REG_FMT " s3 : " REG_FMT " s4 : " REG_FMT "\n",
regs->s2, regs->s3, regs->s4);
pr_cont(" s5 : " REG_FMT " s6 : " REG_FMT " s7 : " REG_FMT "\n",
regs->s5, regs->s6, regs->s7);
pr_cont(" s8 : " REG_FMT " s9 : " REG_FMT " s10: " REG_FMT "\n",
regs->s8, regs->s9, regs->s10);
pr_cont(" s11: " REG_FMT " t3 : " REG_FMT " t4 : " REG_FMT "\n",
regs->s11, regs->t3, regs->t4);
pr_cont(" t5 : " REG_FMT " t6 : " REG_FMT "\n",
regs->t5, regs->t6);
pr_cont("status: " REG_FMT " badaddr: " REG_FMT " cause: " REG_FMT "\n",
regs->status, regs->badaddr, regs->cause);
}
void start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
regs->status = SR_PIE;
if (has_fpu) {
regs->status |= SR_FS_INITIAL;
/*
* Restore the initial value to the FP register
* before starting the user program.
*/
fstate_restore(current, regs);
}
regs->epc = pc;
regs->sp = sp;
set_fs(USER_DS);
}
void flush_thread(void)
{
#ifdef CONFIG_FPU
/*
* Reset FPU state and context
* frm: round to nearest, ties to even (IEEE default)
* fflags: accrued exceptions cleared
*/
fstate_off(current, task_pt_regs(current));
memset(&current->thread.fstate, 0, sizeof(current->thread.fstate));
#endif
}
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
fstate_save(src, task_pt_regs(src));
*dst = *src;
return 0;
}
int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
struct task_struct *p, unsigned long tls)
{
struct pt_regs *childregs = task_pt_regs(p);
/* p->thread holds context to be restored by __switch_to() */
if (unlikely(p->flags & PF_KTHREAD)) {
/* Kernel thread */
memset(childregs, 0, sizeof(struct pt_regs));
childregs->gp = gp_in_global;
/* Supervisor/Machine, irqs on: */
childregs->status = SR_PP | SR_PIE;
p->thread.ra = (unsigned long)ret_from_kernel_thread;
p->thread.s[0] = usp; /* fn */
p->thread.s[1] = arg;
} else {
*childregs = *(current_pt_regs());
if (usp) /* User fork */
childregs->sp = usp;
if (clone_flags & CLONE_SETTLS)
childregs->tp = tls;
childregs->a0 = 0; /* Return value of fork() */
p->thread.ra = (unsigned long)ret_from_fork;
}
p->thread.sp = (unsigned long)childregs; /* kernel sp */
return 0;
}