From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7956 invoked by alias); 11 Oct 2016 08:15:39 -0000 Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org Received: (qmail 7273 invoked by uid 89); 11 Oct 2016 08:15:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=BAYES_00,KAM_STOCKGEN,RP_MATCHES_RCVD,SPF_PASS autolearn=no version=3.3.2 spammy=3.11, 248,6, 7755, kup X-HELO: mailapp01.imgtec.com Received: from mailapp02.imgtec.com (HELO mailapp01.imgtec.com) (217.156.133.132) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 11 Oct 2016 08:15:24 +0000 Received: from HHMAIL03.hh.imgtec.org (unknown [10.44.0.21]) by Forcepoint Email with ESMTPS id 59297818F5143 for ; Tue, 11 Oct 2016 09:14:49 +0100 (IST) Received: from HHMAIL01.hh.imgtec.org (10.100.10.19) by HHMAIL03.hh.imgtec.org (10.44.0.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Tue, 11 Oct 2016 09:14:51 +0100 Received: from WR-NOWAKOWSKI.kl.imgtec.org (10.80.2.5) by HHMAIL01.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Tue, 11 Oct 2016 09:14:51 +0100 From: Marcin Nowakowski To: CC: Marcin Nowakowski Subject: [PATCH 12/12] mips: add runtime support Date: Tue, 11 Oct 2016 08:15:00 -0000 Message-ID: <1476173668-30787-13-git-send-email-marcin.nowakowski@imgtec.com> In-Reply-To: <1476173668-30787-1-git-send-email-marcin.nowakowski@imgtec.com> References: <1476173668-30787-1-git-send-email-marcin.nowakowski@imgtec.com> MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2016-q4/txt/msg00013.txt.bz2 Signed-off-by: Marcin Nowakowski --- runtime/linux/arith.c | 96 ++++++++++++++++++++++++++++++++++- runtime/linux/regs.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ runtime/loc2c-runtime.h | 9 ++++ runtime/regs.h | 4 ++ runtime/syscall.h | 67 +++++++++++++++++++++++++ 5 files changed, 305 insertions(+), 2 deletions(-) diff --git a/runtime/linux/arith.c b/runtime/linux/arith.c index b64984a..4bb89d5 100644 --- a/runtime/linux/arith.c +++ b/runtime/linux/arith.c @@ -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) \ diff --git a/runtime/linux/regs.c b/runtime/linux/regs.c index a7501dd..6573967 100644 --- a/runtime/linux/regs.c +++ b/runtime/linux/regs.c @@ -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 diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h index 69df205..09eb3f1 100644 --- a/runtime/loc2c-runtime.h +++ b/runtime/loc2c-runtime.h @@ -154,6 +154,15 @@ #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] diff --git a/runtime/regs.h b/runtime/regs.h index 2f027ad..94680af 100644 --- a/runtime/regs.h +++ b/runtime/regs.h @@ -54,6 +54,10 @@ #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__ diff --git a/runtime/syscall.h b/runtime/syscall.h index b959d46..5ed0198 100644 --- a/runtime/syscall.h +++ b/runtime/syscall.h @@ -77,6 +77,55 @@ #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) -- 2.7.4