root/arch/mips/kernel/watch.c

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

DEFINITIONS

This source file includes following definitions.
  1. mips_install_watch_registers
  2. mips_read_watch_registers
  3. mips_clear_watch_registers
  4. mips_probe_watch_registers

   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) 2008 David Daney
   7  */
   8 
   9 #include <linux/sched.h>
  10 
  11 #include <asm/processor.h>
  12 #include <asm/watch.h>
  13 
  14 /*
  15  * Install the watch registers for the current thread.  A maximum of
  16  * four registers are installed although the machine may have more.
  17  */
  18 void mips_install_watch_registers(struct task_struct *t)
  19 {
  20         struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264;
  21         unsigned int watchhi = MIPS_WATCHHI_G |         /* Trap all ASIDs */
  22                                MIPS_WATCHHI_IRW;        /* Clear result bits */
  23 
  24         switch (current_cpu_data.watch_reg_use_cnt) {
  25         default:
  26                 BUG();
  27         case 4:
  28                 write_c0_watchlo3(watches->watchlo[3]);
  29                 write_c0_watchhi3(watchhi | watches->watchhi[3]);
  30                 /* fall through */
  31         case 3:
  32                 write_c0_watchlo2(watches->watchlo[2]);
  33                 write_c0_watchhi2(watchhi | watches->watchhi[2]);
  34                 /* fall through */
  35         case 2:
  36                 write_c0_watchlo1(watches->watchlo[1]);
  37                 write_c0_watchhi1(watchhi | watches->watchhi[1]);
  38                 /* fall through */
  39         case 1:
  40                 write_c0_watchlo0(watches->watchlo[0]);
  41                 write_c0_watchhi0(watchhi | watches->watchhi[0]);
  42         }
  43 }
  44 
  45 /*
  46  * Read back the watchhi registers so the user space debugger has
  47  * access to the I, R, and W bits.  A maximum of four registers are
  48  * read although the machine may have more.
  49  */
  50 void mips_read_watch_registers(void)
  51 {
  52         struct mips3264_watch_reg_state *watches =
  53                 &current->thread.watch.mips3264;
  54         unsigned int watchhi_mask = MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW;
  55 
  56         switch (current_cpu_data.watch_reg_use_cnt) {
  57         default:
  58                 BUG();
  59         case 4:
  60                 watches->watchhi[3] = (read_c0_watchhi3() & watchhi_mask);
  61                 /* fall through */
  62         case 3:
  63                 watches->watchhi[2] = (read_c0_watchhi2() & watchhi_mask);
  64                 /* fall through */
  65         case 2:
  66                 watches->watchhi[1] = (read_c0_watchhi1() & watchhi_mask);
  67                 /* fall through */
  68         case 1:
  69                 watches->watchhi[0] = (read_c0_watchhi0() & watchhi_mask);
  70         }
  71         if (current_cpu_data.watch_reg_use_cnt == 1 &&
  72             (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) {
  73                 /* Pathological case of release 1 architecture that
  74                  * doesn't set the condition bits.  We assume that
  75                  * since we got here, the watch condition was met and
  76                  * signal that the conditions requested in watchlo
  77                  * were met.  */
  78                 watches->watchhi[0] |= (watches->watchlo[0] & MIPS_WATCHHI_IRW);
  79         }
  80  }
  81 
  82 /*
  83  * Disable all watch registers.  Although only four registers are
  84  * installed, all are cleared to eliminate the possibility of endless
  85  * looping in the watch handler.
  86  */
  87 void mips_clear_watch_registers(void)
  88 {
  89         switch (current_cpu_data.watch_reg_count) {
  90         default:
  91                 BUG();
  92         case 8:
  93                 write_c0_watchlo7(0);
  94                 /* fall through */
  95         case 7:
  96                 write_c0_watchlo6(0);
  97                 /* fall through */
  98         case 6:
  99                 write_c0_watchlo5(0);
 100                 /* fall through */
 101         case 5:
 102                 write_c0_watchlo4(0);
 103                 /* fall through */
 104         case 4:
 105                 write_c0_watchlo3(0);
 106                 /* fall through */
 107         case 3:
 108                 write_c0_watchlo2(0);
 109                 /* fall through */
 110         case 2:
 111                 write_c0_watchlo1(0);
 112                 /* fall through */
 113         case 1:
 114                 write_c0_watchlo0(0);
 115         }
 116 }
 117 
 118 void mips_probe_watch_registers(struct cpuinfo_mips *c)
 119 {
 120         unsigned int t;
 121 
 122         if ((c->options & MIPS_CPU_WATCH) == 0)
 123                 return;
 124         /*
 125          * Check which of the I,R and W bits are supported, then
 126          * disable the register.
 127          */
 128         write_c0_watchlo0(MIPS_WATCHLO_IRW);
 129         back_to_back_c0_hazard();
 130         t = read_c0_watchlo0();
 131         write_c0_watchlo0(0);
 132         c->watch_reg_masks[0] = t & MIPS_WATCHLO_IRW;
 133 
 134         /* Write the mask bits and read them back to determine which
 135          * can be used. */
 136         c->watch_reg_count = 1;
 137         c->watch_reg_use_cnt = 1;
 138         t = read_c0_watchhi0();
 139         write_c0_watchhi0(t | MIPS_WATCHHI_MASK);
 140         back_to_back_c0_hazard();
 141         t = read_c0_watchhi0();
 142         c->watch_reg_masks[0] |= (t & MIPS_WATCHHI_MASK);
 143         if ((t & MIPS_WATCHHI_M) == 0)
 144                 return;
 145 
 146         write_c0_watchlo1(MIPS_WATCHLO_IRW);
 147         back_to_back_c0_hazard();
 148         t = read_c0_watchlo1();
 149         write_c0_watchlo1(0);
 150         c->watch_reg_masks[1] = t & MIPS_WATCHLO_IRW;
 151 
 152         c->watch_reg_count = 2;
 153         c->watch_reg_use_cnt = 2;
 154         t = read_c0_watchhi1();
 155         write_c0_watchhi1(t | MIPS_WATCHHI_MASK);
 156         back_to_back_c0_hazard();
 157         t = read_c0_watchhi1();
 158         c->watch_reg_masks[1] |= (t & MIPS_WATCHHI_MASK);
 159         if ((t & MIPS_WATCHHI_M) == 0)
 160                 return;
 161 
 162         write_c0_watchlo2(MIPS_WATCHLO_IRW);
 163         back_to_back_c0_hazard();
 164         t = read_c0_watchlo2();
 165         write_c0_watchlo2(0);
 166         c->watch_reg_masks[2] = t & MIPS_WATCHLO_IRW;
 167 
 168         c->watch_reg_count = 3;
 169         c->watch_reg_use_cnt = 3;
 170         t = read_c0_watchhi2();
 171         write_c0_watchhi2(t | MIPS_WATCHHI_MASK);
 172         back_to_back_c0_hazard();
 173         t = read_c0_watchhi2();
 174         c->watch_reg_masks[2] |= (t & MIPS_WATCHHI_MASK);
 175         if ((t & MIPS_WATCHHI_M) == 0)
 176                 return;
 177 
 178         write_c0_watchlo3(MIPS_WATCHLO_IRW);
 179         back_to_back_c0_hazard();
 180         t = read_c0_watchlo3();
 181         write_c0_watchlo3(0);
 182         c->watch_reg_masks[3] = t & MIPS_WATCHLO_IRW;
 183 
 184         c->watch_reg_count = 4;
 185         c->watch_reg_use_cnt = 4;
 186         t = read_c0_watchhi3();
 187         write_c0_watchhi3(t | MIPS_WATCHHI_MASK);
 188         back_to_back_c0_hazard();
 189         t = read_c0_watchhi3();
 190         c->watch_reg_masks[3] |= (t & MIPS_WATCHHI_MASK);
 191         if ((t & MIPS_WATCHHI_M) == 0)
 192                 return;
 193 
 194         /* We use at most 4, but probe and report up to 8. */
 195         c->watch_reg_count = 5;
 196         t = read_c0_watchhi4();
 197         if ((t & MIPS_WATCHHI_M) == 0)
 198                 return;
 199 
 200         c->watch_reg_count = 6;
 201         t = read_c0_watchhi5();
 202         if ((t & MIPS_WATCHHI_M) == 0)
 203                 return;
 204 
 205         c->watch_reg_count = 7;
 206         t = read_c0_watchhi6();
 207         if ((t & MIPS_WATCHHI_M) == 0)
 208                 return;
 209 
 210         c->watch_reg_count = 8;
 211 }

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