xref: /dflybsd-src/contrib/gdb-7/gdb/dcache.c (revision 5796c8dc12c637f18a1740c26afd8d40ffa9b719)
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 (&current_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