]> sourceware.org Git - systemtap.git/commitdiff
mips: add runtime support
authorMarcin Nowakowski <marcin.nowakowski@imgtec.com>
Tue, 11 Oct 2016 08:14:28 +0000 (10:14 +0200)
committerFrank Ch. Eigler <fche@redhat.com>
Tue, 11 Oct 2016 13:42:46 +0000 (09:42 -0400)
Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
runtime/linux/arith.c
runtime/linux/regs.c
runtime/loc2c-runtime.h
runtime/regs.h
runtime/syscall.h

index b64984ab7f8fbb57226f3cce12d67a8e2def0f8a..4bb89d52f8094f7729c22d65485047dd0210ba8e 100644 (file)
@@ -21,7 +21,8 @@
 /* Other 32-bit cpus will need to modify this file. */
 
 #if defined (__i386__) || defined(__arm__) || \
-       (defined(__powerpc__) && !defined(__powerpc64__))
+       (defined(__powerpc__) && !defined(__powerpc64__)) || \
+        (defined(__mips__) && !defined(__mips64))
 static long long _div64 (long long u, long long v);
 static long long _mod64 (long long u, long long v);
 #endif
@@ -116,7 +117,8 @@ static int _stp_random_pm (unsigned n)
 
 
 #if defined (__i386__) || defined (__arm__) || \
-       (defined(__powerpc__) && !defined(__powerpc64__))
+       (defined(__powerpc__) && !defined(__powerpc64__)) || \
+        (defined(__mips__) && !defined(__mips64))
 
 /* 64-bit division functions extracted from libgcc */
 typedef long long DWtype;
@@ -125,6 +127,7 @@ typedef unsigned long UWtype;
 typedef long Wtype;
 typedef unsigned int USItype;
 typedef unsigned int UQItype   __attribute__ ((mode (QI)));
+typedef unsigned int UDItype   __attribute__ ((mode (DI)));
 
 #ifdef _BIG_ENDIAN
 struct DWstruct {Wtype high, low;};
@@ -248,6 +251,95 @@ typedef union
           : "r" ((USItype) (a)),                                       \
             "r" ((USItype) (b)) __CLOBBER_CC );}
 
+#elif (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
+#if (__GNUC__ >= 5) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 4)
+#define umul_ppmm(w1, w0, u, v) \
+do {                                                                   \
+       typedef unsigned int __ll_UTItype __attribute__((mode(TI)));    \
+       __ll_UTItype __ll = (__ll_UTItype)(u) * (v);                    \
+       w1 = __ll >> 64;                                                \
+       w0 = __ll;                                                      \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+       __asm__ ("dmultu %2,%3" \
+       : "=l" ((UDItype)(w0)), \
+            "=h" ((UDItype)(w1)) \
+       : "d" ((UDItype)(u)), \
+            "d" ((UDItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+       __asm__ ("dmultu %2,%3\n" \
+          "mflo %0\n" \
+          "mfhi %1" \
+       : "=d" ((UDItype)(w0)), \
+            "=d" ((UDItype)(w1)) \
+       : "d" ((UDItype)(u)), \
+            "d" ((UDItype)(v)))
+#endif
+/* This comes from lib/mpi/longlong.h */
+#elif defined(__mips__) && W_TYPE_SIZE == 32
+#if (__GNUC__ >= 5) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 4)
+#define umul_ppmm(w1, w0, u, v)                        \
+do {                                           \
+       UDItype __ll = (UDItype)(u) * (v);      \
+       w1 = __ll >> 32;                        \
+       w0 = __ll;                              \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+       __asm__ ("multu %2,%3" \
+       : "=l" ((USItype)(w0)), \
+            "=h" ((USItype)(w1)) \
+       : "d" ((USItype)(u)), \
+            "d" ((USItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+       __asm__ ("multu %2,%3\n" \
+          "mflo %0\n" \
+          "mfhi %1" \
+       : "=d" ((USItype)(w0)), \
+            "=d" ((USItype)(w1)) \
+       : "d" ((USItype)(u)), \
+            "d" ((USItype)(v)))
+#endif
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {                                                                 \
+    UWtype __x;                                                        \
+    __x = (al) - (bl);                                                 \
+    (sh) = (ah) - (bh) - (__x > (al));                                 \
+    (sl) = __x;                                                        \
+  } while (0)
+#endif
+
+#elif (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
+#if (__GNUC__ >= 5) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 4)
+#define umul_ppmm(w1, w0, u, v) \
+do {                                                                   \
+       typedef unsigned int __ll_UTItype __attribute__((mode(TI)));    \
+       __ll_UTItype __ll = (__ll_UTItype)(u) * (v);                    \
+       w1 = __ll >> 64;                                                \
+       w0 = __ll;                                                      \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+       __asm__ ("dmultu %2,%3" \
+       : "=l" ((UDItype)(w0)), \
+            "=h" ((UDItype)(w1)) \
+       : "d" ((UDItype)(u)), \
+            "d" ((UDItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+       __asm__ ("dmultu %2,%3\n" \
+          "mflo %0\n" \
+          "mfhi %1" \
+       : "=d" ((UDItype)(w0)), \
+            "=d" ((UDItype)(w1)) \
+       : "d" ((UDItype)(u)), \
+            "d" ((UDItype)(v)))
+#endif
 #endif
 
 #define __udiv_qrnnd_c(q, r, n1, n0, d) \
index a7501ddfe17ecf9efa5d374558dd2ef57be1e953..6573967de1e5da4b3b47720efa170108bd201270 100644 (file)
@@ -312,6 +312,137 @@ static void _stp_print_regs(struct pt_regs * regs)
        _stp_printf("\n");
 }
 
+#elif defined (__mips__)
+/*
+ * MIPS_CPU_ISA_I was removed from the kernel (3.11) by
+ * Commit: 1990e5429c21 ("MIPS: Get rid of MIPS I flag and test macros.")
+ */
+#ifndef MIPS_CPU_ISA_I
+#define IS_CPU_ISA_MIPS_I(x) (!((x) & (MIPS_CPU_ISA_32BIT | MIPS_CPU_ISA_64BIT)))
+#else 
+#define IS_CPU_ISA_MIPS_I(x) ((x) == MIPS_CPU_ISA_I)
+#endif
+/*
+ * Only o32 application has 32bit registers. N32 and N64 both
+ * should use 64bit registers regardless of pointer size
+ */
+static int _stp_probing_app_with_32bit_regs(struct pt_regs *regs)
+{
+       if (!regs)
+               return 0;
+       return (user_mode(regs) &&
+                       test_tsk_thread_flag(current, TIF_32BIT_REGS));
+}
+
+void _stp_print_regs(struct pt_regs * regs)
+{
+#ifdef MIPS_PRINT_REGS_SHOW_SYMBOLS
+       /* it is too much stack to do symbol translation by default */
+       char symbol_name[KSYM_SYMBOL_LEN];
+#endif /* MIPS_PRINT_REGS_SHOW_SYMBOLS */
+       const int field = 2 * sizeof(unsigned long);
+       unsigned int cause = regs->cp0_cause;
+       int i;
+
+#ifdef CONFIG_SMP
+       _stp_printf("Cpu %d\n", smp_processor_id());
+#endif
+
+       /*
+        * Saved main processor registers
+        */
+       for (i = 0; i < 32;) {
+               if ((i % 4) == 0)
+                       _stp_printf("$%2d   :", i);
+               if (i == 0)
+                       _stp_printf(" %0*lx", field, 0UL);
+               else if (i == 26 || i == 27)
+                       _stp_printf(" %*s", field, "");
+               else
+                       _stp_printf(" %0*lx", field, regs->regs[i]);
+
+               i++;
+               if ((i % 4) == 0)
+                       _stp_printf("\n");
+       }
+
+       /* Hi and Lo don't exist for R6 */
+       if (current_cpu_data.isa_level != MIPS_CPU_ISA_M32R6
+               && current_cpu_data.isa_level != MIPS_CPU_ISA_M64R6) {
+               _stp_printf("Hi    : %0*lx\n", field, regs->hi);
+               _stp_printf("Lo    : %0*lx\n", field, regs->lo);
+       }
+
+       /*
+        * Saved cp0 registers
+        */
+       _stp_printf("epc   : %0*lx ", field, regs->cp0_epc);
+#ifdef MIPS_PRINT_REGS_SHOW_SYMBOLSx
+       sprint_symbol(symbol_name, regs->cp0_epc);
+       _stp_printf("%s ", symbol_name);
+#endif /* MIPS_PRINT_REGS_SHOW_SYMBOLS */
+
+       _stp_printf("ra    : %0*lx ", field, regs->regs[31]);
+#ifdef MIPS_PRINT_REGS_SHOW_SYMBOLS
+       sprint_symbol(symbol_name, regs->regs[31]);
+       _stp_printf("%s", symbol_name);
+#endif /* MIPS_PRINT_REGS_SHOW_SYMBOLS */
+       _stp_printf("\n");
+
+       _stp_printf("Status: %08x    ", (uint32_t) regs->cp0_status);
+
+       if (IS_CPU_ISA_MIPS_I(current_cpu_data.isa_level)) {
+               if (regs->cp0_status & ST0_KUO)
+                       _stp_printf("KUo ");
+               if (regs->cp0_status & ST0_IEO)
+                       _stp_printf("IEo ");
+               if (regs->cp0_status & ST0_KUP)
+                       _stp_printf("KUp ");
+               if (regs->cp0_status & ST0_IEP)
+                       _stp_printf("IEp ");
+               if (regs->cp0_status & ST0_KUC)
+                       _stp_printf("KUc ");
+               if (regs->cp0_status & ST0_IEC)
+                       _stp_printf("IEc ");
+       } else {
+               if (regs->cp0_status & ST0_KX)
+                       _stp_printf("KX ");
+               if (regs->cp0_status & ST0_SX)
+                       _stp_printf("SX ");
+               if (regs->cp0_status & ST0_UX)
+                       _stp_printf("UX ");
+               switch (regs->cp0_status & ST0_KSU) {
+               case KSU_USER:
+                       _stp_printf("USER ");
+                       break;
+               case KSU_SUPERVISOR:
+                       _stp_printf("SUPERVISOR ");
+                       break;
+               case KSU_KERNEL:
+                       _stp_printf("KERNEL ");
+                       break;
+               default:
+                       _stp_printf("BAD_MODE ");
+                       break;
+               }
+               if (regs->cp0_status & ST0_ERL)
+                       _stp_printf("ERL ");
+               if (regs->cp0_status & ST0_EXL)
+                       _stp_printf("EXL ");
+               if (regs->cp0_status & ST0_IE)
+                       _stp_printf("IE ");
+       }
+
+       _stp_printf("\n");
+
+       _stp_printf("Cause : %08x\n", cause);
+
+       cause = (((cause) & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE);
+       if (1 <= cause && cause <= 5)
+               _stp_printf("BadVA : %0*lx\n", field, regs->cp0_badvaddr);
+
+       _stp_printf("PrId  : %08x\n", read_c0_prid());
+}
 #endif
 
 
index 69df20536bff85d3571f7342248d195ae7fa545d..09eb3f1b0c303072440fde80205555b39be89c47 100644 (file)
 #define pt_regs_store_register(pt_regs,regno,value) \
   (pt_regs->gpr[regno] = (value))
 
+#elif defined __mips__
+
+#undef pt_regs_fetch_register
+#undef pt_regs_store_register
+#define pt_regs_fetch_register(pt_regs,regno) \
+  ((intptr_t) pt_regs->regs[regno])
+#define pt_regs_store_register(pt_regs,regno,value) \
+  (pt_regs->regs[regno] = (value))
+
 #elif defined (__aarch64__)
 
 #define pt_dwarf_register_0(pt_regs)   pt_regs->regs[0]
index 2f027ad8d4e52c1e97d58c1f4293fa20841636fd..94680af95a558878737a4238365157982faa037f 100644 (file)
 #define REG_SP(regs) regs->ARM_sp
 #define REG_LINK(regs) regs->ARM_lr
 
+#elif defined (__mips__)
+#define REG_IP(regs_arg) ((regs_arg)->cp0_epc)
+#define REG_SP(regs_arg) ((regs_arg)->regs[29])
+
 #elif defined (__s390__) || defined (__s390x__)
 
 #ifndef __s390x__
index b959d462f36a1d8eb83eeb6bceb1c1da8ff554db..5ed019869e471a3fd653e9b000bf3e3f31cb008d 100644 (file)
 #define MREMAP_SYSCALL_NO(tsk)         1156
 #endif
 
+#if defined(__mips__)
+/* n64 values: scall64-64.S */
+#define MMAP_SYSCALL_NO_MIPS_N64       5009
+#define MMAP2_SYSCALL_NO_MIPS_N64      ((unsigned long)-1) /* does not exits */
+#define MPROTECT_SYSCALL_NO_MIPS_N64   5010
+#define MUNMAP_SYSCALL_NO_MIPS_N64     5011
+#define MREMAP_SYSCALL_NO_MIPS_N64     5024
+
+/* n32 values: scall64-n32.S */
+#define MMAP_SYSCALL_NO_MIPS_N32       6009
+#define MMAP2_SYSCALL_NO_MIPS_N32      ((unsigned long)-1) /* does not exits */
+#define MPROTECT_SYSCALL_NO_MIPS_N32   6010
+#define MUNMAP_SYSCALL_NO_MIPS_N32     6011
+#define MREMAP_SYSCALL_NO_MIPS_N32     6024
+
+/* o32 values: scall32-o32.S */
+#define MMAP_SYSCALL_NO_MIPS_O32       4090
+#define MMAP2_SYSCALL_NO_MIPS_O32      4210
+#define MPROTECT_SYSCALL_NO_MIPS_O32   4125
+#define MUNMAP_SYSCALL_NO_MIPS_O32     4091
+#define MREMAP_SYSCALL_NO_MIPS_O32     4167
+
+#define MMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?     \
+                             ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?     \
+                              (MMAP_SYSCALL_NO_MIPS_O32) :                        \
+                              (MMAP_SYSCALL_NO_MIPS_N32)) :                       \
+                             (MMAP_SYSCALL_NO_MIPS_N64))
+#define MMAP2_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?    \
+                             ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?     \
+                              (MMAP2_SYSCALL_NO_MIPS_O32) :                       \
+                              (MMAP2_SYSCALL_NO_MIPS_N32)) :                      \
+                             (MMAP2_SYSCALL_NO_MIPS_N64))
+#define MPROTECT_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?  \
+                             ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?     \
+                              (MPROTECT_SYSCALL_NO_MIPS_O32) :                    \
+                              (MPROTECT_SYSCALL_NO_MIPS_N32)) :                   \
+                             (MPROTECT_SYSCALL_NO_MIPS_N64))
+#define MUNMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?           \
+                             ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?     \
+                              (MUNMAP_SYSCALL_NO_MIPS_O32) :                      \
+                              (MUNMAP_SYSCALL_NO_MIPS_N32)) :                     \
+                             (MUNMAP_SYSCALL_NO_MIPS_N64))
+#define MREMAP_SYSCALL_NO(tsk) ((test_tsk_thread_flag((tsk), TIF_32BIT_ADDR)) ?           \
+                             ((test_tsk_thread_flag((tsk), TIF_32BIT_REGS)) ?     \
+                              (MREMAP_SYSCALL_NO_MIPS_O32) :                      \
+                              (MREMAP_SYSCALL_NO_MIPS_N32)) :                     \
+                             (MREMAP_SYSCALL_NO_MIPS_N64))
+#endif
+
 #if defined(__s390__) || defined(__s390x__)
 #define MMAP_SYSCALL_NO(tsk)           90
 #define MMAP2_SYSCALL_NO(tsk)          192
@@ -122,6 +171,16 @@ _stp_syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 {
        return regs->ARM_r7;
 }
+
+#elif defined(__mips__)
+/* Define our own function as syscall_get_nr always returns 0 unless
+ * ftrace syscall tracing has been enabled */
+static inline long
+_stp_syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+       return regs->regs[2];
+}
+
 #else
 #define _stp_syscall_get_nr syscall_get_nr
 #endif
@@ -151,6 +210,14 @@ _stp_syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 }
 #endif
 
+#if defined(__mips__)
+static inline long
+_stp_syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+       return regs->regs[2];
+}
+#endif
+
 #if defined(__ia64__)
 static inline long
 _stp_syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
This page took 0.040572 seconds and 5 git commands to generate.