* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: coverage.c
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#pragma ident "@(#)coverage.c 1.5 06/10/25 SMI"
#define DBGP(s) do { s; } while (0)
void dbg_coverage(simcpu_t
*sp
, uint32_t rawi
);
void dbg_coverage_parse(void);
void dbg_coverage_dump(void);
/* start/end for pc,instn coverage analysis */
bool_t decode_instn
= false;
void *coverage_data_filep
;
coverage_info_t
*coverage_bufp
;
* This will be called while parsing the conf file
* to allow this hook to parse specific options from
* Format of coverage directive is:
* debug_hook [coverage] [start] [end];
* [coverage] - we've already parsed this. That's how we got here.
* [data_file] - name of the file to mmap (will contain coverage data)
* [end] - only trace when %pc is within [start]-[end] range
* All samples for %pc within the range supplied will be stored
* in a data file (using the name provided in the directive). The
* results of the coverage run can be viewed by running the
* coverage_dump tool (in the build directory) at any time during
* NOTE: this feature will not overwrite the data_file
mode_t mode
= S_IRWXU
| S_IRWXG
| S_IRWXO
;
DBGP(printf("\nInside dbg_coverage_parse()"));
/* Parse data_file to mmap in */
strcpy(data_file
, lex
.strp
);
lex_get(T_Number
); /* start pc */
lex_get(T_Number
); /* end pc */
lex_fatal("end_pc needs to be larger than start_pc in conf file");
num_of_pcs
= ((end_pc
- start_pc
) / 4) + 1;
buf_size
= ((sizeof (coverage_info_t
)) * num_of_pcs
);
DBGP(printf("\ncoverage: start_pc=0x%llx, end_pc=0x%llx "\
"num_of_pcs=0x%llx, buf_size=0x%llx",
start_pc
, end_pc
, num_of_pcs
, buf_size
));
* Create the empty data_file of size buf_size
* Then mmap it into memory.
/* Make sure file does not exist */
if (stat(data_file
, &sb
) == 0)
lex_fatal("coverage: file %s already exists. Check conf file ",
if ((fd
= open(data_file
, O_RDWR
| O_CREAT
| O_TRUNC
, mode
)) == -1)
fatal("Could not create data_file %s\n", data_file
);
/* Set the size of the file by seeking to the end and write NULL */
if (lseek(fd
, (off_t
)buf_size
-1, SEEK_SET
) < 0)
fatal("Could not create data_file of size [0x%llx]", buf_size
);
if (write(fd
, "", 1) != 1)
fatal("Could not write to data_file of size [0x%llx]", buf_size
);
coverage_data_filep
= mmap(NULL
, buf_size
, PROT_READ
| PROT_WRITE
,
if (coverage_data_filep
== MAP_FAILED
)
fatal("Failed to mmap %s\n", data_file
);
coverage_bufp
= coverage_data_filep
;
* return to parse_debug_hook() which will take care of
* parsing the last semi colon.
* This function will get called before each instruction
* gets executed in execloop(). We use the coverage_dump tool
* in legion to read the datafile.
dbg_coverage(simcpu_t
*sp
, uint32_t rawi
)
extern uint32_t sim_atomic_add_32_nv(uint32_t *target
, int32_t delta
);
sparcv9_cpu_t
*v9p
= (sparcv9_cpu_t
*)(sp
->specificp
);
* Only store data when %pc is in Hypervisor and it is in range
* XXX FIXME: we could parse the state from the config file.
if ((v9p
->state
!= V9_HyperPriv
) ||
(sp
->pc
<= start_pc
) || (sp
->pc
>= end_pc
)) {
idx
= ((sp
->pc
- start_pc
) / 4);
/* Increment counter and copy instn into buffer once */
if (sim_atomic_add_32_nv(&(coverage_bufp
[idx
].count
), 1) == 1) {
coverage_bufp
[idx
].pc
= sp
->pc
;
coverage_bufp
[idx
].rawi
= rawi
;
printf("\ndbg_coverage_dump: caled with start=0x%llx, end=0x%llx",
printf("\nuse legion's coverage_dump tool to read the data file");