1*5796c8dcSSimon Schubert /* Caching code for GDB, the GNU debugger. 2*5796c8dcSSimon Schubert 3*5796c8dcSSimon Schubert Copyright (C) 1992, 1993, 1995, 1996, 1998, 1999, 2000, 2001, 2003, 2007, 4*5796c8dcSSimon Schubert 2008, 2009 Free Software Foundation, Inc. 5*5796c8dcSSimon Schubert 6*5796c8dcSSimon Schubert This file is part of GDB. 7*5796c8dcSSimon Schubert 8*5796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify 9*5796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by 10*5796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or 11*5796c8dcSSimon Schubert (at your option) any later version. 12*5796c8dcSSimon Schubert 13*5796c8dcSSimon Schubert This program is distributed in the hope that it will be useful, 14*5796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of 15*5796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*5796c8dcSSimon Schubert GNU General Public License for more details. 17*5796c8dcSSimon Schubert 18*5796c8dcSSimon Schubert You should have received a copy of the GNU General Public License 19*5796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20*5796c8dcSSimon Schubert 21*5796c8dcSSimon Schubert #include "defs.h" 22*5796c8dcSSimon Schubert #include "dcache.h" 23*5796c8dcSSimon Schubert #include "gdbcmd.h" 24*5796c8dcSSimon Schubert #include "gdb_string.h" 25*5796c8dcSSimon Schubert #include "gdbcore.h" 26*5796c8dcSSimon Schubert #include "target.h" 27*5796c8dcSSimon Schubert #include "inferior.h" 28*5796c8dcSSimon Schubert #include "splay-tree.h" 29*5796c8dcSSimon Schubert 30*5796c8dcSSimon Schubert /* The data cache could lead to incorrect results because it doesn't 31*5796c8dcSSimon Schubert know about volatile variables, thus making it impossible to debug 32*5796c8dcSSimon Schubert functions which use memory mapped I/O devices. Set the nocache 33*5796c8dcSSimon Schubert memory region attribute in those cases. 34*5796c8dcSSimon Schubert 35*5796c8dcSSimon Schubert In general the dcache speeds up performance. Some speed improvement 36*5796c8dcSSimon Schubert comes from the actual caching mechanism, but the major gain is in 37*5796c8dcSSimon Schubert the reduction of the remote protocol overhead; instead of reading 38*5796c8dcSSimon Schubert or writing a large area of memory in 4 byte requests, the cache 39*5796c8dcSSimon Schubert bundles up the requests into LINE_SIZE chunks, reducing overhead 40*5796c8dcSSimon Schubert significantly. This is most useful when accessing a large amount 41*5796c8dcSSimon Schubert of data, such as when performing a backtrace. 42*5796c8dcSSimon Schubert 43*5796c8dcSSimon Schubert The cache is a splay tree along with a linked list for replacement. 44*5796c8dcSSimon Schubert Each block caches a LINE_SIZE area of memory. Wtihin each line we remember 45*5796c8dcSSimon Schubert the address of the line (which must be a multiple of LINE_SIZE) and the 46*5796c8dcSSimon Schubert actual data block. 47*5796c8dcSSimon Schubert 48*5796c8dcSSimon Schubert Lines are only allocated as needed, so DCACHE_SIZE really specifies the 49*5796c8dcSSimon Schubert *maximum* number of lines in the cache. 50*5796c8dcSSimon Schubert 51*5796c8dcSSimon Schubert At present, the cache is write-through rather than writeback: as soon 52*5796c8dcSSimon Schubert as data is written to the cache, it is also immediately written to 53*5796c8dcSSimon Schubert the target. Therefore, cache lines are never "dirty". Whether a given 54*5796c8dcSSimon Schubert line is valid or not depends on where it is stored in the dcache_struct; 55*5796c8dcSSimon Schubert there is no per-block valid flag. */ 56*5796c8dcSSimon Schubert 57*5796c8dcSSimon Schubert /* NOTE: Interaction of dcache and memory region attributes 58*5796c8dcSSimon Schubert 59*5796c8dcSSimon Schubert As there is no requirement that memory region attributes be aligned 60*5796c8dcSSimon Schubert to or be a multiple of the dcache page size, dcache_read_line() and 61*5796c8dcSSimon Schubert dcache_write_line() must break up the page by memory region. If a 62*5796c8dcSSimon Schubert chunk does not have the cache attribute set, an invalid memory type 63*5796c8dcSSimon Schubert is set, etc., then the chunk is skipped. Those chunks are handled 64*5796c8dcSSimon Schubert in target_xfer_memory() (or target_xfer_memory_partial()). 65*5796c8dcSSimon Schubert 66*5796c8dcSSimon Schubert This doesn't occur very often. The most common occurance is when 67*5796c8dcSSimon Schubert the last bit of the .text segment and the first bit of the .data 68*5796c8dcSSimon Schubert segment fall within the same dcache page with a ro/cacheable memory 69*5796c8dcSSimon Schubert region defined for the .text segment and a rw/non-cacheable memory 70*5796c8dcSSimon Schubert region defined for the .data segment. */ 71*5796c8dcSSimon Schubert 72*5796c8dcSSimon Schubert /* The maximum number of lines stored. The total size of the cache is 73*5796c8dcSSimon Schubert equal to DCACHE_SIZE times LINE_SIZE. */ 74*5796c8dcSSimon Schubert #define DCACHE_SIZE 4096 75*5796c8dcSSimon Schubert 76*5796c8dcSSimon Schubert /* The size of a cache line. Smaller values reduce the time taken to 77*5796c8dcSSimon Schubert read a single byte and make the cache more granular, but increase 78*5796c8dcSSimon Schubert overhead and reduce the effectiveness of the cache as a prefetcher. */ 79*5796c8dcSSimon Schubert #define LINE_SIZE_POWER 6 80*5796c8dcSSimon Schubert #define LINE_SIZE (1 << LINE_SIZE_POWER) 81*5796c8dcSSimon Schubert 82*5796c8dcSSimon Schubert /* Each cache block holds LINE_SIZE bytes of data 83*5796c8dcSSimon Schubert starting at a multiple-of-LINE_SIZE address. */ 84*5796c8dcSSimon Schubert 85*5796c8dcSSimon Schubert #define LINE_SIZE_MASK ((LINE_SIZE - 1)) 86*5796c8dcSSimon Schubert #define XFORM(x) ((x) & LINE_SIZE_MASK) 87*5796c8dcSSimon Schubert #define MASK(x) ((x) & ~LINE_SIZE_MASK) 88*5796c8dcSSimon Schubert 89*5796c8dcSSimon Schubert struct dcache_block 90*5796c8dcSSimon Schubert { 91*5796c8dcSSimon Schubert struct dcache_block *newer; /* for LRU and free list */ 92*5796c8dcSSimon Schubert CORE_ADDR addr; /* address of data */ 93*5796c8dcSSimon Schubert gdb_byte data[LINE_SIZE]; /* bytes at given address */ 94*5796c8dcSSimon Schubert int refs; /* # hits */ 95*5796c8dcSSimon Schubert }; 96*5796c8dcSSimon Schubert 97*5796c8dcSSimon Schubert struct dcache_struct 98*5796c8dcSSimon Schubert { 99*5796c8dcSSimon Schubert splay_tree tree; 100*5796c8dcSSimon Schubert struct dcache_block *oldest; 101*5796c8dcSSimon Schubert struct dcache_block *newest; 102*5796c8dcSSimon Schubert 103*5796c8dcSSimon Schubert struct dcache_block *freelist; 104*5796c8dcSSimon Schubert 105*5796c8dcSSimon Schubert /* The number of in-use lines in the cache. */ 106*5796c8dcSSimon Schubert int size; 107*5796c8dcSSimon Schubert 108*5796c8dcSSimon Schubert /* The ptid of last inferior to use cache or null_ptid. */ 109*5796c8dcSSimon Schubert ptid_t ptid; 110*5796c8dcSSimon Schubert }; 111*5796c8dcSSimon Schubert 112*5796c8dcSSimon Schubert static struct dcache_block *dcache_hit (DCACHE *dcache, CORE_ADDR addr); 113*5796c8dcSSimon Schubert 114*5796c8dcSSimon Schubert static int dcache_write_line (DCACHE *dcache, struct dcache_block *db); 115*5796c8dcSSimon Schubert 116*5796c8dcSSimon Schubert static int dcache_read_line (DCACHE *dcache, struct dcache_block *db); 117*5796c8dcSSimon Schubert 118*5796c8dcSSimon Schubert static struct dcache_block *dcache_alloc (DCACHE *dcache, CORE_ADDR addr); 119*5796c8dcSSimon Schubert 120*5796c8dcSSimon Schubert static void dcache_info (char *exp, int tty); 121*5796c8dcSSimon Schubert 122*5796c8dcSSimon Schubert void _initialize_dcache (void); 123*5796c8dcSSimon Schubert 124*5796c8dcSSimon Schubert static int dcache_enabled_p = 0; /* OBSOLETE */ 125*5796c8dcSSimon Schubert 126*5796c8dcSSimon Schubert static void 127*5796c8dcSSimon Schubert show_dcache_enabled_p (struct ui_file *file, int from_tty, 128*5796c8dcSSimon Schubert struct cmd_list_element *c, const char *value) 129*5796c8dcSSimon Schubert { 130*5796c8dcSSimon Schubert fprintf_filtered (file, _("Deprecated remotecache flag is %s.\n"), value); 131*5796c8dcSSimon Schubert } 132*5796c8dcSSimon Schubert 133*5796c8dcSSimon Schubert static DCACHE *last_cache; /* Used by info dcache */ 134*5796c8dcSSimon Schubert 135*5796c8dcSSimon Schubert /* Free all the data cache blocks, thus discarding all cached data. */ 136*5796c8dcSSimon Schubert 137*5796c8dcSSimon Schubert void 138*5796c8dcSSimon Schubert dcache_invalidate (DCACHE *dcache) 139*5796c8dcSSimon Schubert { 140*5796c8dcSSimon Schubert struct dcache_block *block, *next; 141*5796c8dcSSimon Schubert 142*5796c8dcSSimon Schubert block = dcache->oldest; 143*5796c8dcSSimon Schubert 144*5796c8dcSSimon Schubert while (block) 145*5796c8dcSSimon Schubert { 146*5796c8dcSSimon Schubert splay_tree_remove (dcache->tree, (splay_tree_key) block->addr); 147*5796c8dcSSimon Schubert next = block->newer; 148*5796c8dcSSimon Schubert 149*5796c8dcSSimon Schubert block->newer = dcache->freelist; 150*5796c8dcSSimon Schubert dcache->freelist = block; 151*5796c8dcSSimon Schubert 152*5796c8dcSSimon Schubert block = next; 153*5796c8dcSSimon Schubert } 154*5796c8dcSSimon Schubert 155*5796c8dcSSimon Schubert dcache->oldest = NULL; 156*5796c8dcSSimon Schubert dcache->newest = NULL; 157*5796c8dcSSimon Schubert dcache->size = 0; 158*5796c8dcSSimon Schubert dcache->ptid = null_ptid; 159*5796c8dcSSimon Schubert } 160*5796c8dcSSimon Schubert 161*5796c8dcSSimon Schubert /* Invalidate the line associated with ADDR. */ 162*5796c8dcSSimon Schubert 163*5796c8dcSSimon Schubert static void 164*5796c8dcSSimon Schubert dcache_invalidate_line (DCACHE *dcache, CORE_ADDR addr) 165*5796c8dcSSimon Schubert { 166*5796c8dcSSimon Schubert struct dcache_block *db = dcache_hit (dcache, addr); 167*5796c8dcSSimon Schubert 168*5796c8dcSSimon Schubert if (db) 169*5796c8dcSSimon Schubert { 170*5796c8dcSSimon Schubert splay_tree_remove (dcache->tree, (splay_tree_key) db->addr); 171*5796c8dcSSimon Schubert db->newer = dcache->freelist; 172*5796c8dcSSimon Schubert dcache->freelist = db; 173*5796c8dcSSimon Schubert --dcache->size; 174*5796c8dcSSimon Schubert } 175*5796c8dcSSimon Schubert } 176*5796c8dcSSimon Schubert 177*5796c8dcSSimon Schubert /* If addr is present in the dcache, return the address of the block 178*5796c8dcSSimon Schubert containing it. */ 179*5796c8dcSSimon Schubert 180*5796c8dcSSimon Schubert static struct dcache_block * 181*5796c8dcSSimon Schubert dcache_hit (DCACHE *dcache, CORE_ADDR addr) 182*5796c8dcSSimon Schubert { 183*5796c8dcSSimon Schubert struct dcache_block *db; 184*5796c8dcSSimon Schubert 185*5796c8dcSSimon Schubert splay_tree_node node = splay_tree_lookup (dcache->tree, 186*5796c8dcSSimon Schubert (splay_tree_key) MASK (addr)); 187*5796c8dcSSimon Schubert 188*5796c8dcSSimon Schubert if (!node) 189*5796c8dcSSimon Schubert return NULL; 190*5796c8dcSSimon Schubert 191*5796c8dcSSimon Schubert db = (struct dcache_block *) node->value; 192*5796c8dcSSimon Schubert db->refs++; 193*5796c8dcSSimon Schubert return db; 194*5796c8dcSSimon Schubert } 195*5796c8dcSSimon Schubert 196*5796c8dcSSimon Schubert /* Fill a cache line from target memory. */ 197*5796c8dcSSimon Schubert 198*5796c8dcSSimon Schubert static int 199*5796c8dcSSimon Schubert dcache_read_line (DCACHE *dcache, struct dcache_block *db) 200*5796c8dcSSimon Schubert { 201*5796c8dcSSimon Schubert CORE_ADDR memaddr; 202*5796c8dcSSimon Schubert gdb_byte *myaddr; 203*5796c8dcSSimon Schubert int len; 204*5796c8dcSSimon Schubert int res; 205*5796c8dcSSimon Schubert int reg_len; 206*5796c8dcSSimon Schubert struct mem_region *region; 207*5796c8dcSSimon Schubert 208*5796c8dcSSimon Schubert len = LINE_SIZE; 209*5796c8dcSSimon Schubert memaddr = db->addr; 210*5796c8dcSSimon Schubert myaddr = db->data; 211*5796c8dcSSimon Schubert 212*5796c8dcSSimon Schubert while (len > 0) 213*5796c8dcSSimon Schubert { 214*5796c8dcSSimon Schubert /* Don't overrun if this block is right at the end of the region. */ 215*5796c8dcSSimon Schubert region = lookup_mem_region (memaddr); 216*5796c8dcSSimon Schubert if (region->hi == 0 || memaddr + len < region->hi) 217*5796c8dcSSimon Schubert reg_len = len; 218*5796c8dcSSimon Schubert else 219*5796c8dcSSimon Schubert reg_len = region->hi - memaddr; 220*5796c8dcSSimon Schubert 221*5796c8dcSSimon Schubert /* Skip non-readable regions. The cache attribute can be ignored, 222*5796c8dcSSimon Schubert since we may be loading this for a stack access. */ 223*5796c8dcSSimon Schubert if (region->attrib.mode == MEM_WO) 224*5796c8dcSSimon Schubert { 225*5796c8dcSSimon Schubert memaddr += reg_len; 226*5796c8dcSSimon Schubert myaddr += reg_len; 227*5796c8dcSSimon Schubert len -= reg_len; 228*5796c8dcSSimon Schubert continue; 229*5796c8dcSSimon Schubert } 230*5796c8dcSSimon Schubert 231*5796c8dcSSimon Schubert res = target_read (¤t_target, TARGET_OBJECT_RAW_MEMORY, 232*5796c8dcSSimon Schubert NULL, myaddr, memaddr, reg_len); 233*5796c8dcSSimon Schubert if (res < reg_len) 234*5796c8dcSSimon Schubert return 0; 235*5796c8dcSSimon Schubert 236*5796c8dcSSimon Schubert memaddr += res; 237*5796c8dcSSimon Schubert myaddr += res; 238*5796c8dcSSimon Schubert len -= res; 239*5796c8dcSSimon Schubert } 240*5796c8dcSSimon Schubert 241*5796c8dcSSimon Schubert return 1; 242*5796c8dcSSimon Schubert } 243*5796c8dcSSimon Schubert 244*5796c8dcSSimon Schubert /* Get a free cache block, put or keep it on the valid list, 245*5796c8dcSSimon Schubert and return its address. */ 246*5796c8dcSSimon Schubert 247*5796c8dcSSimon Schubert static struct dcache_block * 248*5796c8dcSSimon Schubert dcache_alloc (DCACHE *dcache, CORE_ADDR addr) 249*5796c8dcSSimon Schubert { 250*5796c8dcSSimon Schubert struct dcache_block *db; 251*5796c8dcSSimon Schubert 252*5796c8dcSSimon Schubert if (dcache->size >= DCACHE_SIZE) 253*5796c8dcSSimon Schubert { 254*5796c8dcSSimon Schubert /* Evict the least recently used line. */ 255*5796c8dcSSimon Schubert db = dcache->oldest; 256*5796c8dcSSimon Schubert dcache->oldest = db->newer; 257*5796c8dcSSimon Schubert 258*5796c8dcSSimon Schubert splay_tree_remove (dcache->tree, (splay_tree_key) db->addr); 259*5796c8dcSSimon Schubert } 260*5796c8dcSSimon Schubert else 261*5796c8dcSSimon Schubert { 262*5796c8dcSSimon Schubert db = dcache->freelist; 263*5796c8dcSSimon Schubert if (db) 264*5796c8dcSSimon Schubert dcache->freelist = db->newer; 265*5796c8dcSSimon Schubert else 266*5796c8dcSSimon Schubert db = xmalloc (sizeof (struct dcache_block)); 267*5796c8dcSSimon Schubert 268*5796c8dcSSimon Schubert dcache->size++; 269*5796c8dcSSimon Schubert } 270*5796c8dcSSimon Schubert 271*5796c8dcSSimon Schubert db->addr = MASK (addr); 272*5796c8dcSSimon Schubert db->newer = NULL; 273*5796c8dcSSimon Schubert db->refs = 0; 274*5796c8dcSSimon Schubert 275*5796c8dcSSimon Schubert if (dcache->newest) 276*5796c8dcSSimon Schubert dcache->newest->newer = db; 277*5796c8dcSSimon Schubert 278*5796c8dcSSimon Schubert dcache->newest = db; 279*5796c8dcSSimon Schubert 280*5796c8dcSSimon Schubert if (!dcache->oldest) 281*5796c8dcSSimon Schubert dcache->oldest = db; 282*5796c8dcSSimon Schubert 283*5796c8dcSSimon Schubert splay_tree_insert (dcache->tree, (splay_tree_key) db->addr, 284*5796c8dcSSimon Schubert (splay_tree_value) db); 285*5796c8dcSSimon Schubert 286*5796c8dcSSimon Schubert return db; 287*5796c8dcSSimon Schubert } 288*5796c8dcSSimon Schubert 289*5796c8dcSSimon Schubert /* Using the data cache DCACHE return the contents of the byte at 290*5796c8dcSSimon Schubert address ADDR in the remote machine. 291*5796c8dcSSimon Schubert 292*5796c8dcSSimon Schubert Returns 1 for success, 0 for error. */ 293*5796c8dcSSimon Schubert 294*5796c8dcSSimon Schubert static int 295*5796c8dcSSimon Schubert dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr) 296*5796c8dcSSimon Schubert { 297*5796c8dcSSimon Schubert struct dcache_block *db = dcache_hit (dcache, addr); 298*5796c8dcSSimon Schubert 299*5796c8dcSSimon Schubert if (!db) 300*5796c8dcSSimon Schubert { 301*5796c8dcSSimon Schubert db = dcache_alloc (dcache, addr); 302*5796c8dcSSimon Schubert 303*5796c8dcSSimon Schubert if (!dcache_read_line (dcache, db)) 304*5796c8dcSSimon Schubert return 0; 305*5796c8dcSSimon Schubert } 306*5796c8dcSSimon Schubert 307*5796c8dcSSimon Schubert *ptr = db->data[XFORM (addr)]; 308*5796c8dcSSimon Schubert return 1; 309*5796c8dcSSimon Schubert } 310*5796c8dcSSimon Schubert 311*5796c8dcSSimon Schubert /* Write the byte at PTR into ADDR in the data cache. 312*5796c8dcSSimon Schubert 313*5796c8dcSSimon Schubert The caller is responsible for also promptly writing the data 314*5796c8dcSSimon Schubert through to target memory. 315*5796c8dcSSimon Schubert 316*5796c8dcSSimon Schubert If addr is not in cache, this function does nothing; writing to 317*5796c8dcSSimon Schubert an area of memory which wasn't present in the cache doesn't cause 318*5796c8dcSSimon Schubert it to be loaded in. 319*5796c8dcSSimon Schubert 320*5796c8dcSSimon Schubert Always return 1 (meaning success) to simplify dcache_xfer_memory. */ 321*5796c8dcSSimon Schubert 322*5796c8dcSSimon Schubert static int 323*5796c8dcSSimon Schubert dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr) 324*5796c8dcSSimon Schubert { 325*5796c8dcSSimon Schubert struct dcache_block *db = dcache_hit (dcache, addr); 326*5796c8dcSSimon Schubert 327*5796c8dcSSimon Schubert if (db) 328*5796c8dcSSimon Schubert db->data[XFORM (addr)] = *ptr; 329*5796c8dcSSimon Schubert 330*5796c8dcSSimon Schubert return 1; 331*5796c8dcSSimon Schubert } 332*5796c8dcSSimon Schubert 333*5796c8dcSSimon Schubert static int 334*5796c8dcSSimon Schubert dcache_splay_tree_compare (splay_tree_key a, splay_tree_key b) 335*5796c8dcSSimon Schubert { 336*5796c8dcSSimon Schubert if (a > b) 337*5796c8dcSSimon Schubert return 1; 338*5796c8dcSSimon Schubert else if (a == b) 339*5796c8dcSSimon Schubert return 0; 340*5796c8dcSSimon Schubert else 341*5796c8dcSSimon Schubert return -1; 342*5796c8dcSSimon Schubert } 343*5796c8dcSSimon Schubert 344*5796c8dcSSimon Schubert /* Initialize the data cache. */ 345*5796c8dcSSimon Schubert 346*5796c8dcSSimon Schubert DCACHE * 347*5796c8dcSSimon Schubert dcache_init (void) 348*5796c8dcSSimon Schubert { 349*5796c8dcSSimon Schubert DCACHE *dcache; 350*5796c8dcSSimon Schubert int i; 351*5796c8dcSSimon Schubert 352*5796c8dcSSimon Schubert dcache = (DCACHE *) xmalloc (sizeof (*dcache)); 353*5796c8dcSSimon Schubert 354*5796c8dcSSimon Schubert dcache->tree = splay_tree_new (dcache_splay_tree_compare, 355*5796c8dcSSimon Schubert NULL, 356*5796c8dcSSimon Schubert NULL); 357*5796c8dcSSimon Schubert 358*5796c8dcSSimon Schubert dcache->oldest = NULL; 359*5796c8dcSSimon Schubert dcache->newest = NULL; 360*5796c8dcSSimon Schubert dcache->freelist = NULL; 361*5796c8dcSSimon Schubert dcache->size = 0; 362*5796c8dcSSimon Schubert dcache->ptid = null_ptid; 363*5796c8dcSSimon Schubert last_cache = dcache; 364*5796c8dcSSimon Schubert 365*5796c8dcSSimon Schubert return dcache; 366*5796c8dcSSimon Schubert } 367*5796c8dcSSimon Schubert 368*5796c8dcSSimon Schubert /* Free a data cache. */ 369*5796c8dcSSimon Schubert 370*5796c8dcSSimon Schubert void 371*5796c8dcSSimon Schubert dcache_free (DCACHE *dcache) 372*5796c8dcSSimon Schubert { 373*5796c8dcSSimon Schubert struct dcache_block *db, *next; 374*5796c8dcSSimon Schubert 375*5796c8dcSSimon Schubert if (last_cache == dcache) 376*5796c8dcSSimon Schubert last_cache = NULL; 377*5796c8dcSSimon Schubert 378*5796c8dcSSimon Schubert splay_tree_delete (dcache->tree); 379*5796c8dcSSimon Schubert for (db = dcache->freelist; db != NULL; db = next) 380*5796c8dcSSimon Schubert { 381*5796c8dcSSimon Schubert next = db->newer; 382*5796c8dcSSimon Schubert xfree (db); 383*5796c8dcSSimon Schubert } 384*5796c8dcSSimon Schubert xfree (dcache); 385*5796c8dcSSimon Schubert } 386*5796c8dcSSimon Schubert 387*5796c8dcSSimon Schubert /* Read or write LEN bytes from inferior memory at MEMADDR, transferring 388*5796c8dcSSimon Schubert to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is 389*5796c8dcSSimon Schubert nonzero. 390*5796c8dcSSimon Schubert 391*5796c8dcSSimon Schubert The meaning of the result is the same as for target_write. */ 392*5796c8dcSSimon Schubert 393*5796c8dcSSimon Schubert int 394*5796c8dcSSimon Schubert dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache, 395*5796c8dcSSimon Schubert CORE_ADDR memaddr, gdb_byte *myaddr, 396*5796c8dcSSimon Schubert int len, int should_write) 397*5796c8dcSSimon Schubert { 398*5796c8dcSSimon Schubert int i; 399*5796c8dcSSimon Schubert int res; 400*5796c8dcSSimon Schubert int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr); 401*5796c8dcSSimon Schubert xfunc = should_write ? dcache_poke_byte : dcache_peek_byte; 402*5796c8dcSSimon Schubert 403*5796c8dcSSimon Schubert /* If this is a different inferior from what we've recorded, 404*5796c8dcSSimon Schubert flush the cache. */ 405*5796c8dcSSimon Schubert 406*5796c8dcSSimon Schubert if (! ptid_equal (inferior_ptid, dcache->ptid)) 407*5796c8dcSSimon Schubert { 408*5796c8dcSSimon Schubert dcache_invalidate (dcache); 409*5796c8dcSSimon Schubert dcache->ptid = inferior_ptid; 410*5796c8dcSSimon Schubert } 411*5796c8dcSSimon Schubert 412*5796c8dcSSimon Schubert /* Do write-through first, so that if it fails, we don't write to 413*5796c8dcSSimon Schubert the cache at all. */ 414*5796c8dcSSimon Schubert 415*5796c8dcSSimon Schubert if (should_write) 416*5796c8dcSSimon Schubert { 417*5796c8dcSSimon Schubert res = target_write (ops, TARGET_OBJECT_RAW_MEMORY, 418*5796c8dcSSimon Schubert NULL, myaddr, memaddr, len); 419*5796c8dcSSimon Schubert if (res <= 0) 420*5796c8dcSSimon Schubert return res; 421*5796c8dcSSimon Schubert /* Update LEN to what was actually written. */ 422*5796c8dcSSimon Schubert len = res; 423*5796c8dcSSimon Schubert } 424*5796c8dcSSimon Schubert 425*5796c8dcSSimon Schubert for (i = 0; i < len; i++) 426*5796c8dcSSimon Schubert { 427*5796c8dcSSimon Schubert if (!xfunc (dcache, memaddr + i, myaddr + i)) 428*5796c8dcSSimon Schubert { 429*5796c8dcSSimon Schubert /* That failed. Discard its cache line so we don't have a 430*5796c8dcSSimon Schubert partially read line. */ 431*5796c8dcSSimon Schubert dcache_invalidate_line (dcache, memaddr + i); 432*5796c8dcSSimon Schubert /* If we're writing, we still wrote LEN bytes. */ 433*5796c8dcSSimon Schubert if (should_write) 434*5796c8dcSSimon Schubert return len; 435*5796c8dcSSimon Schubert else 436*5796c8dcSSimon Schubert return i; 437*5796c8dcSSimon Schubert } 438*5796c8dcSSimon Schubert } 439*5796c8dcSSimon Schubert 440*5796c8dcSSimon Schubert return len; 441*5796c8dcSSimon Schubert } 442*5796c8dcSSimon Schubert 443*5796c8dcSSimon Schubert /* FIXME: There would be some benefit to making the cache write-back and 444*5796c8dcSSimon Schubert moving the writeback operation to a higher layer, as it could occur 445*5796c8dcSSimon Schubert after a sequence of smaller writes have been completed (as when a stack 446*5796c8dcSSimon Schubert frame is constructed for an inferior function call). Note that only 447*5796c8dcSSimon Schubert moving it up one level to target_xfer_memory[_partial]() is not 448*5796c8dcSSimon Schubert sufficient since we want to coalesce memory transfers that are 449*5796c8dcSSimon Schubert "logically" connected but not actually a single call to one of the 450*5796c8dcSSimon Schubert memory transfer functions. */ 451*5796c8dcSSimon Schubert 452*5796c8dcSSimon Schubert /* Just update any cache lines which are already present. This is called 453*5796c8dcSSimon Schubert by memory_xfer_partial in cases where the access would otherwise not go 454*5796c8dcSSimon Schubert through the cache. */ 455*5796c8dcSSimon Schubert 456*5796c8dcSSimon Schubert void 457*5796c8dcSSimon Schubert dcache_update (DCACHE *dcache, CORE_ADDR memaddr, gdb_byte *myaddr, int len) 458*5796c8dcSSimon Schubert { 459*5796c8dcSSimon Schubert int i; 460*5796c8dcSSimon Schubert for (i = 0; i < len; i++) 461*5796c8dcSSimon Schubert dcache_poke_byte (dcache, memaddr + i, myaddr + i); 462*5796c8dcSSimon Schubert } 463*5796c8dcSSimon Schubert 464*5796c8dcSSimon Schubert static void 465*5796c8dcSSimon Schubert dcache_print_line (int index) 466*5796c8dcSSimon Schubert { 467*5796c8dcSSimon Schubert splay_tree_node n; 468*5796c8dcSSimon Schubert struct dcache_block *db; 469*5796c8dcSSimon Schubert int i, j; 470*5796c8dcSSimon Schubert 471*5796c8dcSSimon Schubert if (!last_cache) 472*5796c8dcSSimon Schubert { 473*5796c8dcSSimon Schubert printf_filtered (_("No data cache available.\n")); 474*5796c8dcSSimon Schubert return; 475*5796c8dcSSimon Schubert } 476*5796c8dcSSimon Schubert 477*5796c8dcSSimon Schubert n = splay_tree_min (last_cache->tree); 478*5796c8dcSSimon Schubert 479*5796c8dcSSimon Schubert for (i = index; i > 0; --i) 480*5796c8dcSSimon Schubert { 481*5796c8dcSSimon Schubert if (!n) 482*5796c8dcSSimon Schubert break; 483*5796c8dcSSimon Schubert n = splay_tree_successor (last_cache->tree, n->key); 484*5796c8dcSSimon Schubert } 485*5796c8dcSSimon Schubert 486*5796c8dcSSimon Schubert if (!n) 487*5796c8dcSSimon Schubert { 488*5796c8dcSSimon Schubert printf_filtered (_("No such cache line exists.\n")); 489*5796c8dcSSimon Schubert return; 490*5796c8dcSSimon Schubert } 491*5796c8dcSSimon Schubert 492*5796c8dcSSimon Schubert db = (struct dcache_block *) n->value; 493*5796c8dcSSimon Schubert 494*5796c8dcSSimon Schubert printf_filtered (_("Line %d: address %s [%d hits]\n"), 495*5796c8dcSSimon Schubert index, paddress (target_gdbarch, db->addr), db->refs); 496*5796c8dcSSimon Schubert 497*5796c8dcSSimon Schubert for (j = 0; j < LINE_SIZE; j++) 498*5796c8dcSSimon Schubert { 499*5796c8dcSSimon Schubert printf_filtered ("%02x ", db->data[j]); 500*5796c8dcSSimon Schubert 501*5796c8dcSSimon Schubert /* Print a newline every 16 bytes (48 characters) */ 502*5796c8dcSSimon Schubert if ((j % 16 == 15) && (j != LINE_SIZE - 1)) 503*5796c8dcSSimon Schubert printf_filtered ("\n"); 504*5796c8dcSSimon Schubert } 505*5796c8dcSSimon Schubert printf_filtered ("\n"); 506*5796c8dcSSimon Schubert } 507*5796c8dcSSimon Schubert 508*5796c8dcSSimon Schubert static void 509*5796c8dcSSimon Schubert dcache_info (char *exp, int tty) 510*5796c8dcSSimon Schubert { 511*5796c8dcSSimon Schubert splay_tree_node n; 512*5796c8dcSSimon Schubert int i, refcount, lineno; 513*5796c8dcSSimon Schubert 514*5796c8dcSSimon Schubert if (exp) 515*5796c8dcSSimon Schubert { 516*5796c8dcSSimon Schubert char *linestart; 517*5796c8dcSSimon Schubert i = strtol (exp, &linestart, 10); 518*5796c8dcSSimon Schubert if (linestart == exp || i < 0) 519*5796c8dcSSimon Schubert { 520*5796c8dcSSimon Schubert printf_filtered (_("Usage: info dcache [linenumber]\n")); 521*5796c8dcSSimon Schubert return; 522*5796c8dcSSimon Schubert } 523*5796c8dcSSimon Schubert 524*5796c8dcSSimon Schubert dcache_print_line (i); 525*5796c8dcSSimon Schubert return; 526*5796c8dcSSimon Schubert } 527*5796c8dcSSimon Schubert 528*5796c8dcSSimon Schubert printf_filtered (_("Dcache line width %d, maximum size %d\n"), 529*5796c8dcSSimon Schubert LINE_SIZE, DCACHE_SIZE); 530*5796c8dcSSimon Schubert 531*5796c8dcSSimon Schubert if (!last_cache || ptid_equal (last_cache->ptid, null_ptid)) 532*5796c8dcSSimon Schubert { 533*5796c8dcSSimon Schubert printf_filtered (_("No data cache available.\n")); 534*5796c8dcSSimon Schubert return; 535*5796c8dcSSimon Schubert } 536*5796c8dcSSimon Schubert 537*5796c8dcSSimon Schubert printf_filtered (_("Contains data for %s\n"), 538*5796c8dcSSimon Schubert target_pid_to_str (last_cache->ptid)); 539*5796c8dcSSimon Schubert 540*5796c8dcSSimon Schubert refcount = 0; 541*5796c8dcSSimon Schubert 542*5796c8dcSSimon Schubert n = splay_tree_min (last_cache->tree); 543*5796c8dcSSimon Schubert i = 0; 544*5796c8dcSSimon Schubert 545*5796c8dcSSimon Schubert while (n) 546*5796c8dcSSimon Schubert { 547*5796c8dcSSimon Schubert struct dcache_block *db = (struct dcache_block *) n->value; 548*5796c8dcSSimon Schubert 549*5796c8dcSSimon Schubert printf_filtered (_("Line %d: address %s [%d hits]\n"), 550*5796c8dcSSimon Schubert i, paddress (target_gdbarch, db->addr), db->refs); 551*5796c8dcSSimon Schubert i++; 552*5796c8dcSSimon Schubert refcount += db->refs; 553*5796c8dcSSimon Schubert 554*5796c8dcSSimon Schubert n = splay_tree_successor (last_cache->tree, n->key); 555*5796c8dcSSimon Schubert } 556*5796c8dcSSimon Schubert 557*5796c8dcSSimon Schubert printf_filtered (_("Cache state: %d active lines, %d hits\n"), i, refcount); 558*5796c8dcSSimon Schubert } 559*5796c8dcSSimon Schubert 560*5796c8dcSSimon Schubert void 561*5796c8dcSSimon Schubert _initialize_dcache (void) 562*5796c8dcSSimon Schubert { 563*5796c8dcSSimon Schubert add_setshow_boolean_cmd ("remotecache", class_support, 564*5796c8dcSSimon Schubert &dcache_enabled_p, _("\ 565*5796c8dcSSimon Schubert Set cache use for remote targets."), _("\ 566*5796c8dcSSimon Schubert Show cache use for remote targets."), _("\ 567*5796c8dcSSimon Schubert This used to enable the data cache for remote targets. The cache\n\ 568*5796c8dcSSimon Schubert functionality is now controlled by the memory region system and the\n\ 569*5796c8dcSSimon Schubert \"stack-cache\" flag; \"remotecache\" now does nothing and\n\ 570*5796c8dcSSimon Schubert exists only for compatibility reasons."), 571*5796c8dcSSimon Schubert NULL, 572*5796c8dcSSimon Schubert show_dcache_enabled_p, 573*5796c8dcSSimon Schubert &setlist, &showlist); 574*5796c8dcSSimon Schubert 575*5796c8dcSSimon Schubert add_info ("dcache", dcache_info, 576*5796c8dcSSimon Schubert _("\ 577*5796c8dcSSimon Schubert Print information on the dcache performance.\n\ 578*5796c8dcSSimon Schubert With no arguments, this command prints the cache configuration and a\n\ 579*5796c8dcSSimon Schubert summary of each line in the cache. Use \"info dcache <lineno> to dump\"\n\ 580*5796c8dcSSimon Schubert the contents of a given line.")); 581*5796c8dcSSimon Schubert } 582