[PATCH V7 08/20] csky: Process management and Signal

2018-10-04 Thread Guo Ren
This patch adds files related to task_switch, sigcontext, signal.

Changelog:
 - abiv2/fpu.c: Userspace should never be sent NSIGXXX as a si_code.
   Use FPE_FLTUNK instead.
 - abiv2/fpu.c: Use force_sig_fault instead.

Signed-off-by: Guo Ren 
---
 arch/csky/abiv2/fpu.c   | 275 +
 arch/csky/abiv2/inc/abi/fpu.h   |  66 ++
 arch/csky/include/asm/mmu_context.h | 150 ++
 arch/csky/include/asm/processor.h   | 121 +++
 arch/csky/include/asm/switch_to.h   |  36 
 arch/csky/include/asm/thread_info.h |  75 +++
 arch/csky/include/uapi/asm/sigcontext.h |  14 ++
 arch/csky/kernel/process.c  | 136 
 arch/csky/kernel/signal.c   | 355 
 arch/csky/kernel/time.c |  11 +
 10 files changed, 1239 insertions(+)
 create mode 100644 arch/csky/abiv2/fpu.c
 create mode 100644 arch/csky/abiv2/inc/abi/fpu.h
 create mode 100644 arch/csky/include/asm/mmu_context.h
 create mode 100644 arch/csky/include/asm/processor.h
 create mode 100644 arch/csky/include/asm/switch_to.h
 create mode 100644 arch/csky/include/asm/thread_info.h
 create mode 100644 arch/csky/include/uapi/asm/sigcontext.h
 create mode 100644 arch/csky/kernel/process.c
 create mode 100644 arch/csky/kernel/signal.c
 create mode 100644 arch/csky/kernel/time.c

diff --git a/arch/csky/abiv2/fpu.c b/arch/csky/abiv2/fpu.c
new file mode 100644
index 000..e7e1134
--- /dev/null
+++ b/arch/csky/abiv2/fpu.c
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+
+#include 
+#include 
+#include 
+
+#define MTCR_MASK  0xFC00FFE0
+#define MFCR_MASK  0xFC00FFE0
+#define MTCR_DIST  0xC0006420
+#define MFCR_DIST  0xC0006020
+
+void __init init_fpu(void)
+{
+   mtcr("cr<1, 2>", 0);
+}
+
+/*
+ * fpu_libc_helper() is to help libc to excute:
+ *  - mfcr %a, cr<1, 2>
+ *  - mfcr %a, cr<2, 2>
+ *  - mtcr %a, cr<1, 2>
+ *  - mtcr %a, cr<2, 2>
+ */
+int fpu_libc_helper(struct pt_regs *regs)
+{
+   int fault;
+   unsigned long instrptr, regx = 0;
+   unsigned long index = 0, tmp = 0;
+   unsigned long tinstr = 0;
+   u16 instr_hi, instr_low;
+
+   instrptr = instruction_pointer(regs);
+   if (instrptr & 1)
+   return 0;
+
+   fault = __get_user(instr_low, (u16 *)instrptr);
+   if (fault)
+   return 0;
+
+   fault = __get_user(instr_hi, (u16 *)(instrptr + 2));
+   if (fault)
+   return 0;
+
+   tinstr = instr_hi | ((unsigned long)instr_low << 16);
+
+   if (((tinstr >> 21) & 0x1F) != 2)
+   return 0;
+
+   if ((tinstr & MTCR_MASK) == MTCR_DIST) {
+   index = (tinstr >> 16) & 0x1F;
+   if (index > 13)
+   return 0;
+
+   tmp = tinstr & 0x1F;
+   if (tmp > 2)
+   return 0;
+
+   regx =  *(>a0 + index);
+
+   if (tmp == 1)
+   mtcr("cr<1, 2>", regx);
+   else if (tmp == 2)
+   mtcr("cr<2, 2>", regx);
+   else
+   return 0;
+
+   regs->pc += 4;
+   return 1;
+   }
+
+   if ((tinstr & MFCR_MASK) == MFCR_DIST) {
+   index = tinstr & 0x1F;
+   if (index > 13)
+   return 0;
+
+   tmp = ((tinstr >> 16) & 0x1F);
+   if (tmp > 2)
+   return 0;
+
+   if (tmp == 1)
+   regx = mfcr("cr<1, 2>");
+   else if (tmp == 2)
+   regx = mfcr("cr<2, 2>");
+   else
+   return 0;
+
+   *(>a0 + index) = regx;
+
+   regs->pc += 4;
+   return 1;
+   }
+
+   return 0;
+}
+
+void fpu_fpe(struct pt_regs *regs)
+{
+   int sig, code;
+   unsigned int fesr;
+
+   fesr = mfcr("cr<2, 2>");
+
+   sig = SIGFPE;
+   code = FPE_FLTUNK;
+
+   if (fesr & FPE_ILLE) {
+   sig = SIGILL;
+   code = ILL_ILLOPC;
+   } else if (fesr & FPE_IDC) {
+   sig = SIGILL;
+   code = ILL_ILLOPN;
+   } else if (fesr & FPE_FEC) {
+   sig = SIGFPE;
+   if (fesr & FPE_IOC)
+   code = FPE_FLTINV;
+   else if (fesr & FPE_DZC)
+   code = FPE_FLTDIV;
+   else if (fesr & FPE_UFC)
+   code = FPE_FLTUND;
+   else if (fesr & FPE_OFC)
+   code = FPE_FLTOVF;
+   else if (fesr & FPE_IXC)
+   code = FPE_FLTRES;
+   }
+
+   force_sig_fault(sig, code, (void __user *)regs->pc, current);
+}
+
+#define FMFVR_FPU_REGS(vrx, vry)   \
+   "fmfvrl %0, "#vrx"\n"   \
+   "fmfvrh %1, "#vrx"\n"   

[PATCH V7 08/20] csky: Process management and Signal

2018-10-04 Thread Guo Ren
This patch adds files related to task_switch, sigcontext, signal.

Changelog:
 - abiv2/fpu.c: Userspace should never be sent NSIGXXX as a si_code.
   Use FPE_FLTUNK instead.
 - abiv2/fpu.c: Use force_sig_fault instead.

Signed-off-by: Guo Ren 
---
 arch/csky/abiv2/fpu.c   | 275 +
 arch/csky/abiv2/inc/abi/fpu.h   |  66 ++
 arch/csky/include/asm/mmu_context.h | 150 ++
 arch/csky/include/asm/processor.h   | 121 +++
 arch/csky/include/asm/switch_to.h   |  36 
 arch/csky/include/asm/thread_info.h |  75 +++
 arch/csky/include/uapi/asm/sigcontext.h |  14 ++
 arch/csky/kernel/process.c  | 136 
 arch/csky/kernel/signal.c   | 355 
 arch/csky/kernel/time.c |  11 +
 10 files changed, 1239 insertions(+)
 create mode 100644 arch/csky/abiv2/fpu.c
 create mode 100644 arch/csky/abiv2/inc/abi/fpu.h
 create mode 100644 arch/csky/include/asm/mmu_context.h
 create mode 100644 arch/csky/include/asm/processor.h
 create mode 100644 arch/csky/include/asm/switch_to.h
 create mode 100644 arch/csky/include/asm/thread_info.h
 create mode 100644 arch/csky/include/uapi/asm/sigcontext.h
 create mode 100644 arch/csky/kernel/process.c
 create mode 100644 arch/csky/kernel/signal.c
 create mode 100644 arch/csky/kernel/time.c

diff --git a/arch/csky/abiv2/fpu.c b/arch/csky/abiv2/fpu.c
new file mode 100644
index 000..e7e1134
--- /dev/null
+++ b/arch/csky/abiv2/fpu.c
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+
+#include 
+#include 
+#include 
+
+#define MTCR_MASK  0xFC00FFE0
+#define MFCR_MASK  0xFC00FFE0
+#define MTCR_DIST  0xC0006420
+#define MFCR_DIST  0xC0006020
+
+void __init init_fpu(void)
+{
+   mtcr("cr<1, 2>", 0);
+}
+
+/*
+ * fpu_libc_helper() is to help libc to excute:
+ *  - mfcr %a, cr<1, 2>
+ *  - mfcr %a, cr<2, 2>
+ *  - mtcr %a, cr<1, 2>
+ *  - mtcr %a, cr<2, 2>
+ */
+int fpu_libc_helper(struct pt_regs *regs)
+{
+   int fault;
+   unsigned long instrptr, regx = 0;
+   unsigned long index = 0, tmp = 0;
+   unsigned long tinstr = 0;
+   u16 instr_hi, instr_low;
+
+   instrptr = instruction_pointer(regs);
+   if (instrptr & 1)
+   return 0;
+
+   fault = __get_user(instr_low, (u16 *)instrptr);
+   if (fault)
+   return 0;
+
+   fault = __get_user(instr_hi, (u16 *)(instrptr + 2));
+   if (fault)
+   return 0;
+
+   tinstr = instr_hi | ((unsigned long)instr_low << 16);
+
+   if (((tinstr >> 21) & 0x1F) != 2)
+   return 0;
+
+   if ((tinstr & MTCR_MASK) == MTCR_DIST) {
+   index = (tinstr >> 16) & 0x1F;
+   if (index > 13)
+   return 0;
+
+   tmp = tinstr & 0x1F;
+   if (tmp > 2)
+   return 0;
+
+   regx =  *(>a0 + index);
+
+   if (tmp == 1)
+   mtcr("cr<1, 2>", regx);
+   else if (tmp == 2)
+   mtcr("cr<2, 2>", regx);
+   else
+   return 0;
+
+   regs->pc += 4;
+   return 1;
+   }
+
+   if ((tinstr & MFCR_MASK) == MFCR_DIST) {
+   index = tinstr & 0x1F;
+   if (index > 13)
+   return 0;
+
+   tmp = ((tinstr >> 16) & 0x1F);
+   if (tmp > 2)
+   return 0;
+
+   if (tmp == 1)
+   regx = mfcr("cr<1, 2>");
+   else if (tmp == 2)
+   regx = mfcr("cr<2, 2>");
+   else
+   return 0;
+
+   *(>a0 + index) = regx;
+
+   regs->pc += 4;
+   return 1;
+   }
+
+   return 0;
+}
+
+void fpu_fpe(struct pt_regs *regs)
+{
+   int sig, code;
+   unsigned int fesr;
+
+   fesr = mfcr("cr<2, 2>");
+
+   sig = SIGFPE;
+   code = FPE_FLTUNK;
+
+   if (fesr & FPE_ILLE) {
+   sig = SIGILL;
+   code = ILL_ILLOPC;
+   } else if (fesr & FPE_IDC) {
+   sig = SIGILL;
+   code = ILL_ILLOPN;
+   } else if (fesr & FPE_FEC) {
+   sig = SIGFPE;
+   if (fesr & FPE_IOC)
+   code = FPE_FLTINV;
+   else if (fesr & FPE_DZC)
+   code = FPE_FLTDIV;
+   else if (fesr & FPE_UFC)
+   code = FPE_FLTUND;
+   else if (fesr & FPE_OFC)
+   code = FPE_FLTOVF;
+   else if (fesr & FPE_IXC)
+   code = FPE_FLTRES;
+   }
+
+   force_sig_fault(sig, code, (void __user *)regs->pc, current);
+}
+
+#define FMFVR_FPU_REGS(vrx, vry)   \
+   "fmfvrl %0, "#vrx"\n"   \
+   "fmfvrh %1, "#vrx"\n"