0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/sched.h>
0010
0011 #include <asm/processor.h>
0012 #include <asm/watch.h>
0013
0014
0015
0016
0017
0018 void mips_install_watch_registers(struct task_struct *t)
0019 {
0020 struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264;
0021 unsigned int watchhi = MIPS_WATCHHI_G |
0022 MIPS_WATCHHI_IRW;
0023
0024 switch (current_cpu_data.watch_reg_use_cnt) {
0025 default:
0026 BUG();
0027 case 4:
0028 write_c0_watchlo3(watches->watchlo[3]);
0029 write_c0_watchhi3(watchhi | watches->watchhi[3]);
0030 fallthrough;
0031 case 3:
0032 write_c0_watchlo2(watches->watchlo[2]);
0033 write_c0_watchhi2(watchhi | watches->watchhi[2]);
0034 fallthrough;
0035 case 2:
0036 write_c0_watchlo1(watches->watchlo[1]);
0037 write_c0_watchhi1(watchhi | watches->watchhi[1]);
0038 fallthrough;
0039 case 1:
0040 write_c0_watchlo0(watches->watchlo[0]);
0041 write_c0_watchhi0(watchhi | watches->watchhi[0]);
0042 }
0043 }
0044
0045
0046
0047
0048
0049
0050 void mips_read_watch_registers(void)
0051 {
0052 struct mips3264_watch_reg_state *watches =
0053 ¤t->thread.watch.mips3264;
0054 unsigned int watchhi_mask = MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW;
0055
0056 switch (current_cpu_data.watch_reg_use_cnt) {
0057 default:
0058 BUG();
0059 case 4:
0060 watches->watchhi[3] = (read_c0_watchhi3() & watchhi_mask);
0061 fallthrough;
0062 case 3:
0063 watches->watchhi[2] = (read_c0_watchhi2() & watchhi_mask);
0064 fallthrough;
0065 case 2:
0066 watches->watchhi[1] = (read_c0_watchhi1() & watchhi_mask);
0067 fallthrough;
0068 case 1:
0069 watches->watchhi[0] = (read_c0_watchhi0() & watchhi_mask);
0070 }
0071 if (current_cpu_data.watch_reg_use_cnt == 1 &&
0072 (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) {
0073
0074
0075
0076
0077
0078 watches->watchhi[0] |= (watches->watchlo[0] & MIPS_WATCHHI_IRW);
0079 }
0080 }
0081
0082
0083
0084
0085
0086
0087 void mips_clear_watch_registers(void)
0088 {
0089 switch (current_cpu_data.watch_reg_count) {
0090 default:
0091 BUG();
0092 case 8:
0093 write_c0_watchlo7(0);
0094 fallthrough;
0095 case 7:
0096 write_c0_watchlo6(0);
0097 fallthrough;
0098 case 6:
0099 write_c0_watchlo5(0);
0100 fallthrough;
0101 case 5:
0102 write_c0_watchlo4(0);
0103 fallthrough;
0104 case 4:
0105 write_c0_watchlo3(0);
0106 fallthrough;
0107 case 3:
0108 write_c0_watchlo2(0);
0109 fallthrough;
0110 case 2:
0111 write_c0_watchlo1(0);
0112 fallthrough;
0113 case 1:
0114 write_c0_watchlo0(0);
0115 }
0116 }
0117
0118 void mips_probe_watch_registers(struct cpuinfo_mips *c)
0119 {
0120 unsigned int t;
0121
0122 if ((c->options & MIPS_CPU_WATCH) == 0)
0123 return;
0124
0125
0126
0127
0128 write_c0_watchlo0(MIPS_WATCHLO_IRW);
0129 back_to_back_c0_hazard();
0130 t = read_c0_watchlo0();
0131 write_c0_watchlo0(0);
0132 c->watch_reg_masks[0] = t & MIPS_WATCHLO_IRW;
0133
0134
0135
0136 c->watch_reg_count = 1;
0137 c->watch_reg_use_cnt = 1;
0138 t = read_c0_watchhi0();
0139 write_c0_watchhi0(t | MIPS_WATCHHI_MASK);
0140 back_to_back_c0_hazard();
0141 t = read_c0_watchhi0();
0142 c->watch_reg_masks[0] |= (t & MIPS_WATCHHI_MASK);
0143 if ((t & MIPS_WATCHHI_M) == 0)
0144 return;
0145
0146 write_c0_watchlo1(MIPS_WATCHLO_IRW);
0147 back_to_back_c0_hazard();
0148 t = read_c0_watchlo1();
0149 write_c0_watchlo1(0);
0150 c->watch_reg_masks[1] = t & MIPS_WATCHLO_IRW;
0151
0152 c->watch_reg_count = 2;
0153 c->watch_reg_use_cnt = 2;
0154 t = read_c0_watchhi1();
0155 write_c0_watchhi1(t | MIPS_WATCHHI_MASK);
0156 back_to_back_c0_hazard();
0157 t = read_c0_watchhi1();
0158 c->watch_reg_masks[1] |= (t & MIPS_WATCHHI_MASK);
0159 if ((t & MIPS_WATCHHI_M) == 0)
0160 return;
0161
0162 write_c0_watchlo2(MIPS_WATCHLO_IRW);
0163 back_to_back_c0_hazard();
0164 t = read_c0_watchlo2();
0165 write_c0_watchlo2(0);
0166 c->watch_reg_masks[2] = t & MIPS_WATCHLO_IRW;
0167
0168 c->watch_reg_count = 3;
0169 c->watch_reg_use_cnt = 3;
0170 t = read_c0_watchhi2();
0171 write_c0_watchhi2(t | MIPS_WATCHHI_MASK);
0172 back_to_back_c0_hazard();
0173 t = read_c0_watchhi2();
0174 c->watch_reg_masks[2] |= (t & MIPS_WATCHHI_MASK);
0175 if ((t & MIPS_WATCHHI_M) == 0)
0176 return;
0177
0178 write_c0_watchlo3(MIPS_WATCHLO_IRW);
0179 back_to_back_c0_hazard();
0180 t = read_c0_watchlo3();
0181 write_c0_watchlo3(0);
0182 c->watch_reg_masks[3] = t & MIPS_WATCHLO_IRW;
0183
0184 c->watch_reg_count = 4;
0185 c->watch_reg_use_cnt = 4;
0186 t = read_c0_watchhi3();
0187 write_c0_watchhi3(t | MIPS_WATCHHI_MASK);
0188 back_to_back_c0_hazard();
0189 t = read_c0_watchhi3();
0190 c->watch_reg_masks[3] |= (t & MIPS_WATCHHI_MASK);
0191 if ((t & MIPS_WATCHHI_M) == 0)
0192 return;
0193
0194
0195 c->watch_reg_count = 5;
0196 t = read_c0_watchhi4();
0197 if ((t & MIPS_WATCHHI_M) == 0)
0198 return;
0199
0200 c->watch_reg_count = 6;
0201 t = read_c0_watchhi5();
0202 if ((t & MIPS_WATCHHI_M) == 0)
0203 return;
0204
0205 c->watch_reg_count = 7;
0206 t = read_c0_watchhi6();
0207 if ((t & MIPS_WATCHHI_M) == 0)
0208 return;
0209
0210 c->watch_reg_count = 8;
0211 }