]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/dcache.c
gdb, gdbserver, gdbsupport: remove includes of early headers
[thirdparty/binutils-gdb.git] / gdb / dcache.c
CommitLineData
69517000
AC
1/* Caching code for GDB, the GNU debugger.
2
1d506c26 3 Copyright (C) 1992-2024 Free Software Foundation, Inc.
c906108c
SS
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
c906108c
SS
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c 19
c906108c
SS
20#include "dcache.h"
21#include "gdbcmd.h"
c906108c 22#include "gdbcore.h"
4de283e4 23#include "target-dcache.h"
4e5d721f 24#include "inferior.h"
25f122dc 25#include "splay-tree.h"
0d12e84c 26#include "gdbarch.h"
c906108c 27
1a532630
PP
28/* Commands with a prefix of `{set,show} dcache'. */
29static struct cmd_list_element *dcache_set_list = NULL;
30static struct cmd_list_element *dcache_show_list = NULL;
31
29e57380
C
32/* The data cache could lead to incorrect results because it doesn't
33 know about volatile variables, thus making it impossible to debug
34 functions which use memory mapped I/O devices. Set the nocache
35 memory region attribute in those cases.
c906108c 36
25f122dc 37 In general the dcache speeds up performance. Some speed improvement
c906108c
SS
38 comes from the actual caching mechanism, but the major gain is in
39 the reduction of the remote protocol overhead; instead of reading
40 or writing a large area of memory in 4 byte requests, the cache
25f122dc
DE
41 bundles up the requests into LINE_SIZE chunks, reducing overhead
42 significantly. This is most useful when accessing a large amount
43 of data, such as when performing a backtrace.
44
45 The cache is a splay tree along with a linked list for replacement.
e124be18
MS
46 Each block caches a LINE_SIZE area of memory. Within each line we
47 remember the address of the line (which must be a multiple of
48 LINE_SIZE) and the actual data block.
25f122dc
DE
49
50 Lines are only allocated as needed, so DCACHE_SIZE really specifies the
51 *maximum* number of lines in the cache.
52
53 At present, the cache is write-through rather than writeback: as soon
54 as data is written to the cache, it is also immediately written to
55 the target. Therefore, cache lines are never "dirty". Whether a given
56 line is valid or not depends on where it is stored in the dcache_struct;
57 there is no per-block valid flag. */
c906108c 58
29e57380 59/* NOTE: Interaction of dcache and memory region attributes
c906108c 60
29e57380
C
61 As there is no requirement that memory region attributes be aligned
62 to or be a multiple of the dcache page size, dcache_read_line() and
63 dcache_write_line() must break up the page by memory region. If a
64 chunk does not have the cache attribute set, an invalid memory type
65 is set, etc., then the chunk is skipped. Those chunks are handled
66 in target_xfer_memory() (or target_xfer_memory_partial()).
c906108c 67
85102364 68 This doesn't occur very often. The most common occurrence is when
29e57380
C
69 the last bit of the .text segment and the first bit of the .data
70 segment fall within the same dcache page with a ro/cacheable memory
71 region defined for the .text segment and a rw/non-cacheable memory
25f122dc 72 region defined for the .data segment. */
c906108c 73
25f122dc
DE
74/* The maximum number of lines stored. The total size of the cache is
75 equal to DCACHE_SIZE times LINE_SIZE. */
1a532630
PP
76#define DCACHE_DEFAULT_SIZE 4096
77static unsigned dcache_size = DCACHE_DEFAULT_SIZE;
c906108c 78
1a532630 79/* The default size of a cache line. Smaller values reduce the time taken to
25f122dc
DE
80 read a single byte and make the cache more granular, but increase
81 overhead and reduce the effectiveness of the cache as a prefetcher. */
1a532630
PP
82#define DCACHE_DEFAULT_LINE_SIZE 64
83static unsigned dcache_line_size = DCACHE_DEFAULT_LINE_SIZE;
c906108c
SS
84
85/* Each cache block holds LINE_SIZE bytes of data
86 starting at a multiple-of-LINE_SIZE address. */
87
1a532630
PP
88#define LINE_SIZE_MASK(dcache) ((dcache->line_size - 1))
89#define XFORM(dcache, x) ((x) & LINE_SIZE_MASK (dcache))
90#define MASK(dcache, x) ((x) & ~LINE_SIZE_MASK (dcache))
c906108c 91
c906108c 92struct dcache_block
25f122dc 93{
0963b4bd 94 /* For least-recently-allocated and free lists. */
6ffb2242
DE
95 struct dcache_block *prev;
96 struct dcache_block *next;
97
25f122dc 98 CORE_ADDR addr; /* address of data */
25f122dc 99 int refs; /* # hits */
1a532630 100 gdb_byte data[1]; /* line_size bytes at given address */
25f122dc 101};
29e57380 102
c5aa993b 103struct dcache_struct
25f122dc
DE
104{
105 splay_tree tree;
0963b4bd 106 struct dcache_block *oldest; /* least-recently-allocated list. */
c906108c 107
6ffb2242
DE
108 /* The free list is maintained identically to OLDEST to simplify
109 the code: we only need one set of accessors. */
25f122dc 110 struct dcache_block *freelist;
c906108c 111
25f122dc
DE
112 /* The number of in-use lines in the cache. */
113 int size;
1a532630 114 CORE_ADDR line_size; /* current line_size. */
4e5d721f
DE
115
116 /* The ptid of last inferior to use cache or null_ptid. */
117 ptid_t ptid;
60438659
PA
118
119 /* The process target of last inferior to use the cache or
120 nullptr. */
121 process_stratum_target *proc_target;
25f122dc 122};
c906108c 123
6ffb2242
DE
124typedef void (block_func) (struct dcache_block *block, void *param);
125
8edbea78 126static struct dcache_block *dcache_hit (DCACHE *dcache, CORE_ADDR addr);
c906108c 127
8edbea78 128static int dcache_read_line (DCACHE *dcache, struct dcache_block *db);
c906108c 129
8edbea78
C
130static struct dcache_block *dcache_alloc (DCACHE *dcache, CORE_ADDR addr);
131
491144b5 132static bool dcache_enabled_p = false; /* OBSOLETE */
07128da0 133
920d2a44
AC
134static void
135show_dcache_enabled_p (struct ui_file *file, int from_tty,
136 struct cmd_list_element *c, const char *value)
137{
6cb06a8c 138 gdb_printf (file, _("Deprecated remotecache flag is %s.\n"), value);
920d2a44
AC
139}
140
6ffb2242
DE
141/* Add BLOCK to circular block list BLIST, behind the block at *BLIST.
142 *BLIST is not updated (unless it was previously NULL of course).
143 This is for the least-recently-allocated list's sake:
144 BLIST points to the oldest block.
145 ??? This makes for poor cache usage of the free list,
146 but is it measurable? */
c906108c 147
6ffb2242
DE
148static void
149append_block (struct dcache_block **blist, struct dcache_block *block)
c906108c 150{
6ffb2242
DE
151 if (*blist)
152 {
153 block->next = *blist;
154 block->prev = (*blist)->prev;
155 block->prev->next = block;
156 (*blist)->prev = block;
157 /* We don't update *BLIST here to maintain the invariant that for the
158 least-recently-allocated list *BLIST points to the oldest block. */
159 }
160 else
161 {
162 block->next = block;
163 block->prev = block;
164 *blist = block;
165 }
166}
c906108c 167
6ffb2242 168/* Remove BLOCK from circular block list BLIST. */
c906108c 169
6ffb2242
DE
170static void
171remove_block (struct dcache_block **blist, struct dcache_block *block)
172{
173 if (block->next == block)
174 {
175 *blist = NULL;
176 }
177 else
c906108c 178 {
6ffb2242
DE
179 block->next->prev = block->prev;
180 block->prev->next = block->next;
181 /* If we removed the block *BLIST points to, shift it to the next block
182 to maintain the invariant that for the least-recently-allocated list
183 *BLIST points to the oldest block. */
184 if (*blist == block)
185 *blist = block->next;
186 }
187}
c906108c 188
6ffb2242
DE
189/* Iterate over all elements in BLIST, calling FUNC.
190 PARAM is passed to FUNC.
191 FUNC may remove the block it's passed, but only that block. */
25f122dc 192
6ffb2242
DE
193static void
194for_each_block (struct dcache_block **blist, block_func *func, void *param)
195{
196 struct dcache_block *db;
197
198 if (*blist == NULL)
199 return;
200
201 db = *blist;
202 do
203 {
204 struct dcache_block *next = db->next;
205
206 func (db, param);
207 db = next;
c906108c 208 }
6ffb2242
DE
209 while (*blist && db != *blist);
210}
211
1a532630
PP
212/* BLOCK_FUNC routine for dcache_free. */
213
214static void
215free_block (struct dcache_block *block, void *param)
216{
217 xfree (block);
218}
219
220/* Free a data cache. */
221
222void
223dcache_free (DCACHE *dcache)
224{
1a532630
PP
225 splay_tree_delete (dcache->tree);
226 for_each_block (&dcache->oldest, free_block, NULL);
227 for_each_block (&dcache->freelist, free_block, NULL);
228 xfree (dcache);
229}
230
231
6ffb2242
DE
232/* BLOCK_FUNC function for dcache_invalidate.
233 This doesn't remove the block from the oldest list on purpose.
234 dcache_invalidate will do it later. */
235
236static void
237invalidate_block (struct dcache_block *block, void *param)
238{
239 DCACHE *dcache = (DCACHE *) param;
240
241 splay_tree_remove (dcache->tree, (splay_tree_key) block->addr);
242 append_block (&dcache->freelist, block);
243}
244
245/* Free all the data cache blocks, thus discarding all cached data. */
246
247void
248dcache_invalidate (DCACHE *dcache)
249{
250 for_each_block (&dcache->oldest, invalidate_block, dcache);
c906108c 251
25f122dc 252 dcache->oldest = NULL;
25f122dc 253 dcache->size = 0;
4e5d721f 254 dcache->ptid = null_ptid;
60438659 255 dcache->proc_target = nullptr;
1a532630
PP
256
257 if (dcache->line_size != dcache_line_size)
258 {
259 /* We've been asked to use a different line size.
260 All of our freelist blocks are now the wrong size, so free them. */
261
262 for_each_block (&dcache->freelist, free_block, dcache);
263 dcache->freelist = NULL;
264 dcache->line_size = dcache_line_size;
265 }
4e5d721f
DE
266}
267
268/* Invalidate the line associated with ADDR. */
269
270static void
271dcache_invalidate_line (DCACHE *dcache, CORE_ADDR addr)
272{
273 struct dcache_block *db = dcache_hit (dcache, addr);
274
275 if (db)
276 {
277 splay_tree_remove (dcache->tree, (splay_tree_key) db->addr);
6ffb2242
DE
278 remove_block (&dcache->oldest, db);
279 append_block (&dcache->freelist, db);
4e5d721f
DE
280 --dcache->size;
281 }
c906108c
SS
282}
283
284/* If addr is present in the dcache, return the address of the block
7f79c47e 285 containing it. Otherwise return NULL. */
c906108c
SS
286
287static struct dcache_block *
fba45db2 288dcache_hit (DCACHE *dcache, CORE_ADDR addr)
c906108c 289{
52f0bd74 290 struct dcache_block *db;
c906108c 291
25f122dc 292 splay_tree_node node = splay_tree_lookup (dcache->tree,
1a532630 293 (splay_tree_key) MASK (dcache, addr));
c906108c 294
25f122dc
DE
295 if (!node)
296 return NULL;
c906108c 297
25f122dc
DE
298 db = (struct dcache_block *) node->value;
299 db->refs++;
300 return db;
c906108c
SS
301}
302
7f79c47e
DE
303/* Fill a cache line from target memory.
304 The result is 1 for success, 0 if the (entire) cache line
305 wasn't readable. */
c906108c 306
8edbea78
C
307static int
308dcache_read_line (DCACHE *dcache, struct dcache_block *db)
309{
310 CORE_ADDR memaddr;
6c932e54 311 gdb_byte *myaddr;
8edbea78
C
312 int len;
313 int res;
29e57380
C
314 int reg_len;
315 struct mem_region *region;
8edbea78 316
1a532630 317 len = dcache->line_size;
8edbea78
C
318 memaddr = db->addr;
319 myaddr = db->data;
320
321 while (len > 0)
322 {
25f122dc
DE
323 /* Don't overrun if this block is right at the end of the region. */
324 region = lookup_mem_region (memaddr);
325 if (region->hi == 0 || memaddr + len < region->hi)
29e57380
C
326 reg_len = len;
327 else
328 reg_len = region->hi - memaddr;
329
4e5d721f 330 /* Skip non-readable regions. The cache attribute can be ignored,
dda83cd7 331 since we may be loading this for a stack access. */
4e5d721f 332 if (region->attrib.mode == MEM_WO)
29e57380
C
333 {
334 memaddr += reg_len;
335 myaddr += reg_len;
336 len -= reg_len;
337 continue;
338 }
9f713294 339
aee4bf85
PA
340 res = target_read_raw_memory (memaddr, myaddr, reg_len);
341 if (res != 0)
cf7a04e8 342 return 0;
8edbea78 343
aee4bf85
PA
344 memaddr += reg_len;
345 myaddr += reg_len;
346 len -= reg_len;
8edbea78
C
347 }
348
8edbea78
C
349 return 1;
350}
351
c906108c 352/* Get a free cache block, put or keep it on the valid list,
f1d7622b 353 and return its address. */
c906108c
SS
354
355static struct dcache_block *
f1d7622b 356dcache_alloc (DCACHE *dcache, CORE_ADDR addr)
c906108c 357{
52f0bd74 358 struct dcache_block *db;
c906108c 359
1a532630 360 if (dcache->size >= dcache_size)
c906108c 361 {
6ffb2242 362 /* Evict the least recently allocated line. */
25f122dc 363 db = dcache->oldest;
6ffb2242 364 remove_block (&dcache->oldest, db);
25f122dc
DE
365
366 splay_tree_remove (dcache->tree, (splay_tree_key) db->addr);
c906108c
SS
367 }
368 else
369 {
25f122dc
DE
370 db = dcache->freelist;
371 if (db)
6ffb2242 372 remove_block (&dcache->freelist, db);
25f122dc 373 else
224c3ddb
SM
374 db = ((struct dcache_block *)
375 xmalloc (offsetof (struct dcache_block, data)
376 + dcache->line_size));
c906108c 377
25f122dc 378 dcache->size++;
c906108c
SS
379 }
380
1a532630 381 db->addr = MASK (dcache, addr);
f1d7622b 382 db->refs = 0;
f1d7622b 383
6ffb2242
DE
384 /* Put DB at the end of the list, it's the newest. */
385 append_block (&dcache->oldest, db);
c906108c 386
25f122dc
DE
387 splay_tree_insert (dcache->tree, (splay_tree_key) db->addr,
388 (splay_tree_value) db);
c906108c 389
25f122dc 390 return db;
c906108c
SS
391}
392
7f79c47e 393/* Using the data cache DCACHE, store in *PTR the contents of the byte at
8edbea78
C
394 address ADDR in the remote machine.
395
25f122dc 396 Returns 1 for success, 0 for error. */
8edbea78
C
397
398static int
6c932e54 399dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr)
8edbea78 400{
52f0bd74 401 struct dcache_block *db = dcache_hit (dcache, addr);
8edbea78
C
402
403 if (!db)
404 {
405 db = dcache_alloc (dcache, addr);
25f122dc
DE
406
407 if (!dcache_read_line (dcache, db))
dda83cd7 408 return 0;
8edbea78
C
409 }
410
1a532630 411 *ptr = db->data[XFORM (dcache, addr)];
8edbea78
C
412 return 1;
413}
414
c906108c 415/* Write the byte at PTR into ADDR in the data cache.
25f122dc 416
0f26cec1
PA
417 The caller should have written the data through to target memory
418 already.
25f122dc 419
0f26cec1
PA
420 If ADDR is not in cache, this function does nothing; writing to an
421 area of memory which wasn't present in the cache doesn't cause it
422 to be loaded in. */
25f122dc 423
0f26cec1
PA
424static void
425dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, const gdb_byte *ptr)
c906108c 426{
52f0bd74 427 struct dcache_block *db = dcache_hit (dcache, addr);
c906108c 428
25f122dc 429 if (db)
1a532630 430 db->data[XFORM (dcache, addr)] = *ptr;
c906108c
SS
431}
432
25f122dc
DE
433static int
434dcache_splay_tree_compare (splay_tree_key a, splay_tree_key b)
435{
436 if (a > b)
437 return 1;
438 else if (a == b)
439 return 0;
440 else
441 return -1;
442}
443
7f79c47e 444/* Allocate and initialize a data cache. */
25f122dc 445
c906108c 446DCACHE *
4930751a 447dcache_init (void)
c906108c 448{
8d749320 449 DCACHE *dcache = XNEW (DCACHE);
c906108c 450
25f122dc
DE
451 dcache->tree = splay_tree_new (dcache_splay_tree_compare,
452 NULL,
453 NULL);
c906108c 454
25f122dc 455 dcache->oldest = NULL;
25f122dc
DE
456 dcache->freelist = NULL;
457 dcache->size = 0;
1a532630 458 dcache->line_size = dcache_line_size;
4e5d721f 459 dcache->ptid = null_ptid;
60438659 460 dcache->proc_target = nullptr;
25f122dc 461
c906108c
SS
462 return dcache;
463}
464
e99586d5 465
0f26cec1
PA
466/* Read LEN bytes from dcache memory at MEMADDR, transferring to
467 debugger address MYADDR. If the data is presently cached, this
468 fills the cache. Arguments/return are like the target_xfer_partial
469 interface. */
c906108c 470
0f26cec1
PA
471enum target_xfer_status
472dcache_read_memory_partial (struct target_ops *ops, DCACHE *dcache,
473 CORE_ADDR memaddr, gdb_byte *myaddr,
474 ULONGEST len, ULONGEST *xfered_len)
c906108c 475{
0f26cec1 476 ULONGEST i;
c906108c 477
60438659
PA
478 /* If this is a different thread from what we've recorded, flush the
479 cache. */
4e5d721f 480
60438659
PA
481 process_stratum_target *proc_target = current_inferior ()->process_target ();
482 if (proc_target != dcache->proc_target || inferior_ptid != dcache->ptid)
4e5d721f
DE
483 {
484 dcache_invalidate (dcache);
485 dcache->ptid = inferior_ptid;
60438659 486 dcache->proc_target = proc_target;
4e5d721f
DE
487 }
488
29e57380 489 for (i = 0; i < len; i++)
c906108c 490 {
0f26cec1 491 if (!dcache_peek_byte (dcache, memaddr + i, myaddr + i))
4e5d721f
DE
492 {
493 /* That failed. Discard its cache line so we don't have a
494 partially read line. */
495 dcache_invalidate_line (dcache, memaddr + i);
0f26cec1 496 break;
4e5d721f 497 }
c906108c 498 }
0f26cec1
PA
499
500 if (i == 0)
501 {
0256a6ac
PA
502 /* Even though reading the whole line failed, we may be able to
503 read a piece starting where the caller wanted. */
cc9f16aa
YQ
504 return raw_memory_xfer_partial (ops, myaddr, NULL, memaddr, len,
505 xfered_len);
0f26cec1
PA
506 }
507 else
508 {
509 *xfered_len = i;
510 return TARGET_XFER_OK;
511 }
25f122dc 512}
c906108c 513
25f122dc
DE
514/* FIXME: There would be some benefit to making the cache write-back and
515 moving the writeback operation to a higher layer, as it could occur
516 after a sequence of smaller writes have been completed (as when a stack
517 frame is constructed for an inferior function call). Note that only
518 moving it up one level to target_xfer_memory[_partial]() is not
519 sufficient since we want to coalesce memory transfers that are
520 "logically" connected but not actually a single call to one of the
521 memory transfer functions. */
29e57380 522
0f26cec1
PA
523/* Just update any cache lines which are already present. This is
524 called by the target_xfer_partial machinery when writing raw
525 memory. */
4e5d721f
DE
526
527void
0f26cec1
PA
528dcache_update (DCACHE *dcache, enum target_xfer_status status,
529 CORE_ADDR memaddr, const gdb_byte *myaddr,
530 ULONGEST len)
4e5d721f 531{
0f26cec1 532 ULONGEST i;
9a619af0 533
4e5d721f 534 for (i = 0; i < len; i++)
0f26cec1
PA
535 if (status == TARGET_XFER_OK)
536 dcache_poke_byte (dcache, memaddr + i, myaddr + i);
537 else
538 {
539 /* Discard the whole cache line so we don't have a partially
540 valid line. */
541 dcache_invalidate_line (dcache, memaddr + i);
542 }
4e5d721f
DE
543}
544
2a2f9fe4
YQ
545/* Print DCACHE line INDEX. */
546
25f122dc 547static void
2a2f9fe4 548dcache_print_line (DCACHE *dcache, int index)
25f122dc
DE
549{
550 splay_tree_node n;
551 struct dcache_block *db;
552 int i, j;
553
2a2f9fe4 554 if (dcache == NULL)
25f122dc 555 {
6cb06a8c 556 gdb_printf (_("No data cache available.\n"));
25f122dc
DE
557 return;
558 }
559
2a2f9fe4 560 n = splay_tree_min (dcache->tree);
25f122dc
DE
561
562 for (i = index; i > 0; --i)
563 {
564 if (!n)
565 break;
2a2f9fe4 566 n = splay_tree_successor (dcache->tree, n->key);
25f122dc
DE
567 }
568
569 if (!n)
570 {
6cb06a8c 571 gdb_printf (_("No such cache line exists.\n"));
25f122dc
DE
572 return;
573 }
29e57380 574
25f122dc
DE
575 db = (struct dcache_block *) n->value;
576
6cb06a8c 577 gdb_printf (_("Line %d: address %s [%d hits]\n"),
99d9c3b9
SM
578 index, paddress (current_inferior ()->arch (), db->addr),
579 db->refs);
25f122dc 580
2a2f9fe4 581 for (j = 0; j < dcache->line_size; j++)
25f122dc 582 {
6cb06a8c 583 gdb_printf ("%02x ", db->data[j]);
25f122dc 584
0963b4bd 585 /* Print a newline every 16 bytes (48 characters). */
2a2f9fe4 586 if ((j % 16 == 15) && (j != dcache->line_size - 1))
6cb06a8c 587 gdb_printf ("\n");
25f122dc 588 }
6cb06a8c 589 gdb_printf ("\n");
c906108c
SS
590}
591
2a2f9fe4
YQ
592/* Parse EXP and show the info about DCACHE. */
593
c5aa993b 594static void
1d12d88f 595dcache_info_1 (DCACHE *dcache, const char *exp)
c906108c 596{
25f122dc 597 splay_tree_node n;
9128a503 598 int i, refcount;
25f122dc
DE
599
600 if (exp)
601 {
602 char *linestart;
9a619af0 603
25f122dc
DE
604 i = strtol (exp, &linestart, 10);
605 if (linestart == exp || i < 0)
606 {
6cb06a8c 607 gdb_printf (_("Usage: info dcache [LINENUMBER]\n"));
dda83cd7 608 return;
25f122dc 609 }
c906108c 610
2a2f9fe4 611 dcache_print_line (dcache, i);
25f122dc
DE
612 return;
613 }
614
6cb06a8c
TT
615 gdb_printf (_("Dcache %u lines of %u bytes each.\n"),
616 dcache_size,
617 dcache ? (unsigned) dcache->line_size
618 : dcache_line_size);
c906108c 619
d7e15655 620 if (dcache == NULL || dcache->ptid == null_ptid)
c906108c 621 {
6cb06a8c 622 gdb_printf (_("No data cache available.\n"));
25f122dc
DE
623 return;
624 }
5e2039ea 625
6cb06a8c
TT
626 gdb_printf (_("Contains data for %s\n"),
627 target_pid_to_str (dcache->ptid).c_str ());
4e5d721f 628
25f122dc 629 refcount = 0;
c906108c 630
2a2f9fe4 631 n = splay_tree_min (dcache->tree);
25f122dc 632 i = 0;
c906108c 633
25f122dc
DE
634 while (n)
635 {
636 struct dcache_block *db = (struct dcache_block *) n->value;
637
6cb06a8c 638 gdb_printf (_("Line %d: address %s [%d hits]\n"),
99d9c3b9
SM
639 i, paddress (current_inferior ()->arch (), db->addr),
640 db->refs);
25f122dc
DE
641 i++;
642 refcount += db->refs;
643
2a2f9fe4 644 n = splay_tree_successor (dcache->tree, n->key);
c906108c 645 }
25f122dc 646
6cb06a8c 647 gdb_printf (_("Cache state: %d active lines, %d hits\n"), i, refcount);
c906108c
SS
648}
649
2a2f9fe4 650static void
1d12d88f 651info_dcache_command (const char *exp, int tty)
2a2f9fe4 652{
41336620 653 dcache_info_1 (target_dcache_get (current_program_space->aspace), exp);
2a2f9fe4
YQ
654}
655
1a532630 656static void
eb4c3f4a 657set_dcache_size (const char *args, int from_tty,
1a532630
PP
658 struct cmd_list_element *c)
659{
660 if (dcache_size == 0)
661 {
662 dcache_size = DCACHE_DEFAULT_SIZE;
663 error (_("Dcache size must be greater than 0."));
664 }
41336620 665 target_dcache_invalidate (current_program_space->aspace);
1a532630
PP
666}
667
668static void
eb4c3f4a 669set_dcache_line_size (const char *args, int from_tty,
1a532630
PP
670 struct cmd_list_element *c)
671{
672 if (dcache_line_size < 2
673 || (dcache_line_size & (dcache_line_size - 1)) != 0)
674 {
675 unsigned d = dcache_line_size;
676 dcache_line_size = DCACHE_DEFAULT_LINE_SIZE;
677 error (_("Invalid dcache line size: %u (must be power of 2)."), d);
678 }
41336620 679 target_dcache_invalidate (current_program_space->aspace);
1a532630
PP
680}
681
6c265988 682void _initialize_dcache ();
c906108c 683void
6c265988 684_initialize_dcache ()
c906108c 685{
5bf193a2
AC
686 add_setshow_boolean_cmd ("remotecache", class_support,
687 &dcache_enabled_p, _("\
688Set cache use for remote targets."), _("\
689Show cache use for remote targets."), _("\
4e5d721f
DE
690This used to enable the data cache for remote targets. The cache\n\
691functionality is now controlled by the memory region system and the\n\
692\"stack-cache\" flag; \"remotecache\" now does nothing and\n\
693exists only for compatibility reasons."),
5bf193a2 694 NULL,
920d2a44 695 show_dcache_enabled_p,
5bf193a2 696 &setlist, &showlist);
c906108c 697
11db9430 698 add_info ("dcache", info_dcache_command,
07128da0
DE
699 _("\
700Print information on the dcache performance.\n\
ffb2b66c 701Usage: info dcache [LINENUMBER]\n\
25f122dc 702With no arguments, this command prints the cache configuration and a\n\
ffb2b66c
TT
703summary of each line in the cache. With an argument, dump\"\n\
704the contents of the given line."));
1a532630 705
f54bdb6d
SM
706 add_setshow_prefix_cmd ("dcache", class_obscure,
707 _("\
1a532630 708Use this command to set number of lines in dcache and line-size."),
f54bdb6d
SM
709 ("Show dcache settings."),
710 &dcache_set_list, &dcache_show_list,
711 &setlist, &showlist);
1a532630 712
dfd1f9bb
PA
713 add_setshow_zuinteger_cmd ("line-size", class_obscure,
714 &dcache_line_size, _("\
1a532630
PP
715Set dcache line size in bytes (must be power of 2)."), _("\
716Show dcache line size."),
dfd1f9bb
PA
717 NULL,
718 set_dcache_line_size,
719 NULL,
720 &dcache_set_list, &dcache_show_list);
721 add_setshow_zuinteger_cmd ("size", class_obscure,
722 &dcache_size, _("\
1a532630
PP
723Set number of dcache lines."), _("\
724Show number of dcache lines."),
dfd1f9bb
PA
725 NULL,
726 set_dcache_size,
727 NULL,
728 &dcache_set_list, &dcache_show_list);
c906108c 729}