16aa3524cSDavid Daney /* 26aa3524cSDavid Daney * This file is subject to the terms and conditions of the GNU General Public 36aa3524cSDavid Daney * License. See the file "COPYING" in the main directory of this archive 46aa3524cSDavid Daney * for more details. 56aa3524cSDavid Daney * 66aa3524cSDavid Daney * Copyright (C) 2008 David Daney 76aa3524cSDavid Daney */ 86aa3524cSDavid Daney 96aa3524cSDavid Daney #include <linux/sched.h> 106aa3524cSDavid Daney 116aa3524cSDavid Daney #include <asm/processor.h> 126aa3524cSDavid Daney #include <asm/watch.h> 136aa3524cSDavid Daney 146aa3524cSDavid Daney /* 156aa3524cSDavid Daney * Install the watch registers for the current thread. A maximum of 166aa3524cSDavid Daney * four registers are installed although the machine may have more. 176aa3524cSDavid Daney */ mips_install_watch_registers(struct task_struct * t)18a7e89326SJames Hoganvoid mips_install_watch_registers(struct task_struct *t) 196aa3524cSDavid Daney { 20a7e89326SJames Hogan struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264; 21f609cc3aSMatt Redfearn unsigned int watchhi = MIPS_WATCHHI_G | /* Trap all ASIDs */ 22f609cc3aSMatt Redfearn MIPS_WATCHHI_IRW; /* Clear result bits */ 23f609cc3aSMatt Redfearn 246aa3524cSDavid Daney switch (current_cpu_data.watch_reg_use_cnt) { 256aa3524cSDavid Daney default: 266aa3524cSDavid Daney BUG(); 276aa3524cSDavid Daney case 4: 286aa3524cSDavid Daney write_c0_watchlo3(watches->watchlo[3]); 29f609cc3aSMatt Redfearn write_c0_watchhi3(watchhi | watches->watchhi[3]); 30*c9b02990SLiangliang Huang fallthrough; 316aa3524cSDavid Daney case 3: 326aa3524cSDavid Daney write_c0_watchlo2(watches->watchlo[2]); 33f609cc3aSMatt Redfearn write_c0_watchhi2(watchhi | watches->watchhi[2]); 34*c9b02990SLiangliang Huang fallthrough; 356aa3524cSDavid Daney case 2: 366aa3524cSDavid Daney write_c0_watchlo1(watches->watchlo[1]); 37f609cc3aSMatt Redfearn write_c0_watchhi1(watchhi | watches->watchhi[1]); 38*c9b02990SLiangliang Huang fallthrough; 396aa3524cSDavid Daney case 1: 406aa3524cSDavid Daney write_c0_watchlo0(watches->watchlo[0]); 41f609cc3aSMatt Redfearn write_c0_watchhi0(watchhi | watches->watchhi[0]); 426aa3524cSDavid Daney } 436aa3524cSDavid Daney } 446aa3524cSDavid Daney 456aa3524cSDavid Daney /* 466aa3524cSDavid Daney * Read back the watchhi registers so the user space debugger has 476aa3524cSDavid Daney * access to the I, R, and W bits. A maximum of four registers are 486aa3524cSDavid Daney * read although the machine may have more. 496aa3524cSDavid Daney */ mips_read_watch_registers(void)506aa3524cSDavid Daneyvoid mips_read_watch_registers(void) 516aa3524cSDavid Daney { 526aa3524cSDavid Daney struct mips3264_watch_reg_state *watches = 536aa3524cSDavid Daney ¤t->thread.watch.mips3264; 54705e71adSMatt Redfearn unsigned int watchhi_mask = MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW; 55705e71adSMatt Redfearn 566aa3524cSDavid Daney switch (current_cpu_data.watch_reg_use_cnt) { 576aa3524cSDavid Daney default: 586aa3524cSDavid Daney BUG(); 596aa3524cSDavid Daney case 4: 60705e71adSMatt Redfearn watches->watchhi[3] = (read_c0_watchhi3() & watchhi_mask); 61*c9b02990SLiangliang Huang fallthrough; 626aa3524cSDavid Daney case 3: 63705e71adSMatt Redfearn watches->watchhi[2] = (read_c0_watchhi2() & watchhi_mask); 64*c9b02990SLiangliang Huang fallthrough; 656aa3524cSDavid Daney case 2: 66705e71adSMatt Redfearn watches->watchhi[1] = (read_c0_watchhi1() & watchhi_mask); 67*c9b02990SLiangliang Huang fallthrough; 686aa3524cSDavid Daney case 1: 69705e71adSMatt Redfearn watches->watchhi[0] = (read_c0_watchhi0() & watchhi_mask); 706aa3524cSDavid Daney } 716aa3524cSDavid Daney if (current_cpu_data.watch_reg_use_cnt == 1 && 7250af501cSJames Hogan (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) { 736aa3524cSDavid Daney /* Pathological case of release 1 architecture that 746aa3524cSDavid Daney * doesn't set the condition bits. We assume that 756aa3524cSDavid Daney * since we got here, the watch condition was met and 766aa3524cSDavid Daney * signal that the conditions requested in watchlo 776aa3524cSDavid Daney * were met. */ 7850af501cSJames Hogan watches->watchhi[0] |= (watches->watchlo[0] & MIPS_WATCHHI_IRW); 796aa3524cSDavid Daney } 806aa3524cSDavid Daney } 816aa3524cSDavid Daney 826aa3524cSDavid Daney /* 836aa3524cSDavid Daney * Disable all watch registers. Although only four registers are 846aa3524cSDavid Daney * installed, all are cleared to eliminate the possibility of endless 856aa3524cSDavid Daney * looping in the watch handler. 866aa3524cSDavid Daney */ mips_clear_watch_registers(void)876aa3524cSDavid Daneyvoid mips_clear_watch_registers(void) 886aa3524cSDavid Daney { 896aa3524cSDavid Daney switch (current_cpu_data.watch_reg_count) { 906aa3524cSDavid Daney default: 916aa3524cSDavid Daney BUG(); 926aa3524cSDavid Daney case 8: 936aa3524cSDavid Daney write_c0_watchlo7(0); 94*c9b02990SLiangliang Huang fallthrough; 956aa3524cSDavid Daney case 7: 966aa3524cSDavid Daney write_c0_watchlo6(0); 97*c9b02990SLiangliang Huang fallthrough; 986aa3524cSDavid Daney case 6: 996aa3524cSDavid Daney write_c0_watchlo5(0); 100*c9b02990SLiangliang Huang fallthrough; 1016aa3524cSDavid Daney case 5: 1026aa3524cSDavid Daney write_c0_watchlo4(0); 103*c9b02990SLiangliang Huang fallthrough; 1046aa3524cSDavid Daney case 4: 1056aa3524cSDavid Daney write_c0_watchlo3(0); 106*c9b02990SLiangliang Huang fallthrough; 1076aa3524cSDavid Daney case 3: 1086aa3524cSDavid Daney write_c0_watchlo2(0); 109*c9b02990SLiangliang Huang fallthrough; 1106aa3524cSDavid Daney case 2: 1116aa3524cSDavid Daney write_c0_watchlo1(0); 112*c9b02990SLiangliang Huang fallthrough; 1136aa3524cSDavid Daney case 1: 1146aa3524cSDavid Daney write_c0_watchlo0(0); 1156aa3524cSDavid Daney } 1166aa3524cSDavid Daney } 1176aa3524cSDavid Daney mips_probe_watch_registers(struct cpuinfo_mips * c)118078a55fcSPaul Gortmakervoid mips_probe_watch_registers(struct cpuinfo_mips *c) 1196aa3524cSDavid Daney { 1206aa3524cSDavid Daney unsigned int t; 1216aa3524cSDavid Daney 1226aa3524cSDavid Daney if ((c->options & MIPS_CPU_WATCH) == 0) 1236aa3524cSDavid Daney return; 1246aa3524cSDavid Daney /* 1256aa3524cSDavid Daney * Check which of the I,R and W bits are supported, then 1266aa3524cSDavid Daney * disable the register. 1276aa3524cSDavid Daney */ 12850af501cSJames Hogan write_c0_watchlo0(MIPS_WATCHLO_IRW); 129c5e1503fSPaul Burton back_to_back_c0_hazard(); 1306aa3524cSDavid Daney t = read_c0_watchlo0(); 1316aa3524cSDavid Daney write_c0_watchlo0(0); 13250af501cSJames Hogan c->watch_reg_masks[0] = t & MIPS_WATCHLO_IRW; 1336aa3524cSDavid Daney 1346aa3524cSDavid Daney /* Write the mask bits and read them back to determine which 1356aa3524cSDavid Daney * can be used. */ 1366aa3524cSDavid Daney c->watch_reg_count = 1; 1376aa3524cSDavid Daney c->watch_reg_use_cnt = 1; 1386aa3524cSDavid Daney t = read_c0_watchhi0(); 13950af501cSJames Hogan write_c0_watchhi0(t | MIPS_WATCHHI_MASK); 140c5e1503fSPaul Burton back_to_back_c0_hazard(); 1416aa3524cSDavid Daney t = read_c0_watchhi0(); 14250af501cSJames Hogan c->watch_reg_masks[0] |= (t & MIPS_WATCHHI_MASK); 14350af501cSJames Hogan if ((t & MIPS_WATCHHI_M) == 0) 1446aa3524cSDavid Daney return; 1456aa3524cSDavid Daney 14650af501cSJames Hogan write_c0_watchlo1(MIPS_WATCHLO_IRW); 147c5e1503fSPaul Burton back_to_back_c0_hazard(); 1486aa3524cSDavid Daney t = read_c0_watchlo1(); 1496aa3524cSDavid Daney write_c0_watchlo1(0); 15050af501cSJames Hogan c->watch_reg_masks[1] = t & MIPS_WATCHLO_IRW; 1516aa3524cSDavid Daney 1526aa3524cSDavid Daney c->watch_reg_count = 2; 1536aa3524cSDavid Daney c->watch_reg_use_cnt = 2; 1546aa3524cSDavid Daney t = read_c0_watchhi1(); 15550af501cSJames Hogan write_c0_watchhi1(t | MIPS_WATCHHI_MASK); 156c5e1503fSPaul Burton back_to_back_c0_hazard(); 1576aa3524cSDavid Daney t = read_c0_watchhi1(); 15850af501cSJames Hogan c->watch_reg_masks[1] |= (t & MIPS_WATCHHI_MASK); 15950af501cSJames Hogan if ((t & MIPS_WATCHHI_M) == 0) 1606aa3524cSDavid Daney return; 1616aa3524cSDavid Daney 16250af501cSJames Hogan write_c0_watchlo2(MIPS_WATCHLO_IRW); 163c5e1503fSPaul Burton back_to_back_c0_hazard(); 1646aa3524cSDavid Daney t = read_c0_watchlo2(); 1656aa3524cSDavid Daney write_c0_watchlo2(0); 16650af501cSJames Hogan c->watch_reg_masks[2] = t & MIPS_WATCHLO_IRW; 1676aa3524cSDavid Daney 1686aa3524cSDavid Daney c->watch_reg_count = 3; 1696aa3524cSDavid Daney c->watch_reg_use_cnt = 3; 1706aa3524cSDavid Daney t = read_c0_watchhi2(); 17150af501cSJames Hogan write_c0_watchhi2(t | MIPS_WATCHHI_MASK); 172c5e1503fSPaul Burton back_to_back_c0_hazard(); 1736aa3524cSDavid Daney t = read_c0_watchhi2(); 17450af501cSJames Hogan c->watch_reg_masks[2] |= (t & MIPS_WATCHHI_MASK); 17550af501cSJames Hogan if ((t & MIPS_WATCHHI_M) == 0) 1766aa3524cSDavid Daney return; 1776aa3524cSDavid Daney 17850af501cSJames Hogan write_c0_watchlo3(MIPS_WATCHLO_IRW); 179c5e1503fSPaul Burton back_to_back_c0_hazard(); 1806aa3524cSDavid Daney t = read_c0_watchlo3(); 1816aa3524cSDavid Daney write_c0_watchlo3(0); 18250af501cSJames Hogan c->watch_reg_masks[3] = t & MIPS_WATCHLO_IRW; 1836aa3524cSDavid Daney 1846aa3524cSDavid Daney c->watch_reg_count = 4; 1856aa3524cSDavid Daney c->watch_reg_use_cnt = 4; 1866aa3524cSDavid Daney t = read_c0_watchhi3(); 18750af501cSJames Hogan write_c0_watchhi3(t | MIPS_WATCHHI_MASK); 188c5e1503fSPaul Burton back_to_back_c0_hazard(); 1896aa3524cSDavid Daney t = read_c0_watchhi3(); 19050af501cSJames Hogan c->watch_reg_masks[3] |= (t & MIPS_WATCHHI_MASK); 19150af501cSJames Hogan if ((t & MIPS_WATCHHI_M) == 0) 1926aa3524cSDavid Daney return; 1936aa3524cSDavid Daney 1946aa3524cSDavid Daney /* We use at most 4, but probe and report up to 8. */ 1956aa3524cSDavid Daney c->watch_reg_count = 5; 1966aa3524cSDavid Daney t = read_c0_watchhi4(); 19750af501cSJames Hogan if ((t & MIPS_WATCHHI_M) == 0) 1986aa3524cSDavid Daney return; 1996aa3524cSDavid Daney 2006aa3524cSDavid Daney c->watch_reg_count = 6; 2016aa3524cSDavid Daney t = read_c0_watchhi5(); 20250af501cSJames Hogan if ((t & MIPS_WATCHHI_M) == 0) 2036aa3524cSDavid Daney return; 2046aa3524cSDavid Daney 2056aa3524cSDavid Daney c->watch_reg_count = 7; 2066aa3524cSDavid Daney t = read_c0_watchhi6(); 20750af501cSJames Hogan if ((t & MIPS_WATCHHI_M) == 0) 2086aa3524cSDavid Daney return; 2096aa3524cSDavid Daney 2106aa3524cSDavid Daney c->watch_reg_count = 8; 2116aa3524cSDavid Daney } 212