~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/kernel/watch.c

Version: ~ [ linux-5.16-rc3 ] ~ [ linux-5.15.5 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.82 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.162 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.218 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.256 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.291 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.293 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp