root/arch/mips/netlogic/xlp/cop2-ex.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nlm_cop2_save
  2. nlm_cop2_restore
  3. nlm_cu2_call
  4. nlm_cu2_setup

   1 /*
   2  * This file is subject to the terms and conditions of the GNU General Public
   3  * License.  See the file "COPYING" in the main directory of this archive
   4  * for more details.
   5  *
   6  * Copyright (C) 2013 Broadcom Corporation.
   7  *
   8  * based on arch/mips/cavium-octeon/cpu.c
   9  * Copyright (C) 2009 Wind River Systems,
  10  *   written by Ralf Baechle <ralf@linux-mips.org>
  11  */
  12 #include <linux/capability.h>
  13 #include <linux/init.h>
  14 #include <linux/irqflags.h>
  15 #include <linux/notifier.h>
  16 #include <linux/prefetch.h>
  17 #include <linux/ptrace.h>
  18 #include <linux/sched.h>
  19 #include <linux/sched/task_stack.h>
  20 
  21 #include <asm/cop2.h>
  22 #include <asm/current.h>
  23 #include <asm/mipsregs.h>
  24 #include <asm/page.h>
  25 
  26 #include <asm/netlogic/mips-extns.h>
  27 
  28 /*
  29  * 64 bit ops are done in inline assembly to support 32 bit
  30  * compilation
  31  */
  32 void nlm_cop2_save(struct nlm_cop2_state *r)
  33 {
  34         asm volatile(
  35                 ".set   push\n"
  36                 ".set   noat\n"
  37                 "dmfc2  $1, $0, 0\n"
  38                 "sd     $1, 0(%1)\n"
  39                 "dmfc2  $1, $0, 1\n"
  40                 "sd     $1, 8(%1)\n"
  41                 "dmfc2  $1, $0, 2\n"
  42                 "sd     $1, 16(%1)\n"
  43                 "dmfc2  $1, $0, 3\n"
  44                 "sd     $1, 24(%1)\n"
  45                 "dmfc2  $1, $1, 0\n"
  46                 "sd     $1, 0(%2)\n"
  47                 "dmfc2  $1, $1, 1\n"
  48                 "sd     $1, 8(%2)\n"
  49                 "dmfc2  $1, $1, 2\n"
  50                 "sd     $1, 16(%2)\n"
  51                 "dmfc2  $1, $1, 3\n"
  52                 "sd     $1, 24(%2)\n"
  53                 ".set   pop\n"
  54                 : "=m"(*r)
  55                 : "r"(r->tx), "r"(r->rx));
  56 
  57         r->tx_msg_status = __read_32bit_c2_register($2, 0);
  58         r->rx_msg_status = __read_32bit_c2_register($3, 0) & 0x0fffffff;
  59 }
  60 
  61 void nlm_cop2_restore(struct nlm_cop2_state *r)
  62 {
  63         u32 rstat;
  64 
  65         asm volatile(
  66                 ".set   push\n"
  67                 ".set   noat\n"
  68                 "ld     $1, 0(%1)\n"
  69                 "dmtc2  $1, $0, 0\n"
  70                 "ld     $1, 8(%1)\n"
  71                 "dmtc2  $1, $0, 1\n"
  72                 "ld     $1, 16(%1)\n"
  73                 "dmtc2  $1, $0, 2\n"
  74                 "ld     $1, 24(%1)\n"
  75                 "dmtc2  $1, $0, 3\n"
  76                 "ld     $1, 0(%2)\n"
  77                 "dmtc2  $1, $1, 0\n"
  78                 "ld     $1, 8(%2)\n"
  79                 "dmtc2  $1, $1, 1\n"
  80                 "ld     $1, 16(%2)\n"
  81                 "dmtc2  $1, $1, 2\n"
  82                 "ld     $1, 24(%2)\n"
  83                 "dmtc2  $1, $1, 3\n"
  84                 ".set   pop\n"
  85                 : : "m"(*r), "r"(r->tx), "r"(r->rx));
  86 
  87         __write_32bit_c2_register($2, 0, r->tx_msg_status);
  88         rstat = __read_32bit_c2_register($3, 0) & 0xf0000000u;
  89         __write_32bit_c2_register($3, 0, r->rx_msg_status | rstat);
  90 }
  91 
  92 static int nlm_cu2_call(struct notifier_block *nfb, unsigned long action,
  93         void *data)
  94 {
  95         unsigned long flags;
  96         unsigned int status;
  97 
  98         switch (action) {
  99         case CU2_EXCEPTION:
 100                 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 101                         break;
 102                 local_irq_save(flags);
 103                 KSTK_STATUS(current) |= ST0_CU2;
 104                 status = read_c0_status();
 105                 write_c0_status(status | ST0_CU2);
 106                 nlm_cop2_restore(&(current->thread.cp2));
 107                 write_c0_status(status & ~ST0_CU2);
 108                 local_irq_restore(flags);
 109                 pr_info("COP2 access enabled for pid %d (%s)\n",
 110                                         current->pid, current->comm);
 111                 return NOTIFY_BAD;      /* Don't call default notifier */
 112         }
 113 
 114         return NOTIFY_OK;               /* Let default notifier send signals */
 115 }
 116 
 117 static int __init nlm_cu2_setup(void)
 118 {
 119         return cu2_notifier(nlm_cu2_call, 0);
 120 }
 121 early_initcall(nlm_cu2_setup);

/* [<][>][^][v][top][bottom][index][help] */