Fail* directories reorganized, Code-cleanup (-> coding-style), Typos+comments fixed.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1321 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
adrian
2012-06-08 20:09:43 +00:00
parent d474a5b952
commit 2575604b41
866 changed files with 1848 additions and 1879 deletions

View File

@ -0,0 +1,71 @@
# Copyright (C) 2001 The Bochs Project
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@SUFFIX_LINE@
srcdir = @srcdir@
VPATH = @srcdir@
SHELL = /bin/sh
@SET_MAKE@
CC = @CC@
CFLAGS = @CFLAGS@
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
RANLIB = @RANLIB@
# ===========================================================
# end of configurable options
# ===========================================================
BX_OBJS = \
instrument.o
BX_INCLUDES =
BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/.
.@CPP_SUFFIX@.o:
$(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@
.c.o:
$(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@
libinstrument.a: $(BX_OBJS)
@RMCOMMAND@ libinstrument.a
@MAKELIB@ $(BX_OBJS)
$(RANLIB) libinstrument.a
$(BX_OBJS): $(BX_INCLUDES)
clean:
@RMCOMMAND@ *.o
@RMCOMMAND@ *.a
dist-clean: clean
@RMCOMMAND@ Makefile

View File

@ -0,0 +1,231 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2009 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <assert.h>
#include "bochs.h"
#include "cpu/cpu.h"
#include "disasm/disasm.h"
// maximum size of an instruction
#define MAX_OPCODE_SIZE 16
// maximum physical addresses an instruction can generate
#define MAX_DATA_ACCESSES 1024
// Use this variable to turn on/off collection of instrumentation data
// If you are not using the debugger to turn this on/off, then possibly
// start this at 1 instead of 0.
static bx_bool active = 1;
static disassembler bx_disassembler;
static struct instruction_t {
bx_bool valid; // is current instruction valid
unsigned opcode_size;
Bit8u opcode[MAX_OPCODE_SIZE];
bx_bool is32, is64;
unsigned num_data_accesses;
struct {
bx_address laddr; // linear address
bx_phy_address paddr; // physical address
unsigned op; // BX_READ, BX_WRITE or BX_RW
unsigned size; // 1 .. 8
} data_access[MAX_DATA_ACCESSES];
bx_bool is_branch;
bx_bool is_taken;
bx_address target_linear;
} *instruction;
static logfunctions *instrument_log = new logfunctions ();
#define LOG_THIS instrument_log->
void bx_instr_init_env(void) {}
void bx_instr_exit_env(void) {}
void bx_instr_initialize(unsigned cpu)
{
assert(cpu < BX_SMP_PROCESSORS);
if (instruction == NULL)
instruction = new struct instruction_t[BX_SMP_PROCESSORS];
fprintf(stderr, "Initialize cpu %d\n", cpu);
}
void bx_instr_reset(unsigned cpu, unsigned type)
{
instruction[cpu].valid = 0;
instruction[cpu].num_data_accesses = 0;
instruction[cpu].is_branch = 0;
}
void bx_instr_new_instruction(unsigned cpu)
{
if (!active) return;
instruction_t *i = &instruction[cpu];
if (i->valid)
{
char disasm_tbuf[512]; // buffer for instruction disassembly
unsigned length = i->opcode_size, n;
bx_disassembler.disasm(i->is32, i->is64, 0, 0, i->opcode, disasm_tbuf);
if(length != 0)
{
fprintf(stderr, "----------------------------------------------------------\n");
fprintf(stderr, "CPU: %d: %s\n", cpu, disasm_tbuf);
fprintf(stderr, "LEN: %d\tBYTES: ", length);
for(n=0;n<length;n++) fprintf(stderr, "%02x", i->opcode[n]);
if(i->is_branch)
{
fprintf(stderr, "\tBRANCH ");
if(i->is_taken)
fprintf(stderr, "TARGET " FMT_ADDRX " (TAKEN)", i->target_linear);
else
fprintf(stderr, "(NOT TAKEN)");
}
fprintf(stderr, "\n");
for(n=0;n<i->num_data_accesses;n++)
{
fprintf(stderr, "MEM ACCESS[%u]: " FMT_ADDRX " (linear) 0x%08x (physical) %s SIZE: %d\n", n,
i->data_access[n].laddr,
i->data_access[n].paddr,
i->data_access[n].op == BX_READ ? "RD":"WR",
i->data_access[n].size);
}
fprintf(stderr, "\n");
}
}
instruction[cpu].valid = 0;
instruction[cpu].num_data_accesses = 0;
instruction[cpu].is_branch = 0;
}
static void branch_taken(unsigned cpu, bx_address new_eip)
{
if (!active || !instruction[cpu].valid) return;
// find linear address
bx_address laddr = BX_CPU(cpu)->get_laddr(BX_SEG_REG_CS, new_eip);
instruction[cpu].is_branch = 1;
instruction[cpu].is_taken = 1;
instruction[cpu].target_linear = laddr;
}
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip)
{
branch_taken(cpu, new_eip);
}
void bx_instr_cnear_branch_not_taken(unsigned cpu)
{
if (!active || !instruction[cpu].valid) return;
instruction[cpu].is_branch = 1;
instruction[cpu].is_taken = 0;
}
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip)
{
branch_taken(cpu, new_eip);
}
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip)
{
branch_taken(cpu, new_eip);
}
void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64)
{
if (!active) return;
for(unsigned i=0;i<len;i++)
{
instruction[cpu].opcode[i] = opcode[i];
}
instruction[cpu].is32 = is32;
instruction[cpu].is64 = is64;
instruction[cpu].opcode_size = len;
instruction[cpu].valid = 1;
}
void bx_instr_interrupt(unsigned cpu, unsigned vector)
{
if(active)
{
fprintf(stderr, "CPU %u: interrupt %02xh\n", cpu, vector);
}
}
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code)
{
if(active)
{
fprintf(stderr, "CPU %u: exception %02xh, error_code = %x\n", cpu, vector, error_code);
}
}
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip)
{
if(active)
{
fprintf(stderr, "CPU %u: hardware interrupt %02xh\n", cpu, vector);
}
}
void bx_instr_mem_data(unsigned cpu, unsigned seg, bx_address offset, unsigned len, unsigned rw)
{
unsigned index;
bx_phy_address phy;
if(!active || !instruction[cpu].valid) return;
if (instruction[cpu].num_data_accesses >= MAX_DATA_ACCESSES)
{
return;
}
bx_address lin = BX_CPU(cpu)->get_laddr(seg, offset);
bx_bool page_valid = BX_CPU(cpu)->dbg_xlate_linear2phy(lin, &phy);
phy = A20ADDR(phy);
// If linear translation doesn't exist, a paging exception will occur.
// Invalidate physical address data for now.
if (!page_valid)
{
phy = 0;
}
index = instruction[cpu].num_data_accesses;
instruction[cpu].data_access[index].laddr = lin;
instruction[cpu].data_access[index].paddr = phy;
instruction[cpu].data_access[index].op = rw;
instruction[cpu].data_access[index].size = size;
instruction[cpu].num_data_accesses++;
}

View File

@ -0,0 +1,200 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2009 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// possible types passed to BX_INSTR_TLB_CNTRL()
#define BX_INSTR_MOV_CR3 10
#define BX_INSTR_INVLPG 11
#define BX_INSTR_TASKSWITCH 12
// possible types passed to BX_INSTR_CACHE_CNTRL()
#define BX_INSTR_INVD 20
#define BX_INSTR_WBINVD 21
// possible types passed to BX_INSTR_FAR_BRANCH()
#define BX_INSTR_IS_CALL 10
#define BX_INSTR_IS_RET 11
#define BX_INSTR_IS_IRET 12
#define BX_INSTR_IS_JMP 13
#define BX_INSTR_IS_INT 14
#define BX_INSTR_IS_SYSCALL 15
#define BX_INSTR_IS_SYSRET 16
#define BX_INSTR_IS_SYSENTER 17
#define BX_INSTR_IS_SYSEXIT 18
// possible types passed to BX_INSTR_PREFETCH_HINT()
#define BX_INSTR_PREFETCH_NTA 0
#define BX_INSTR_PREFETCH_T0 1
#define BX_INSTR_PREFETCH_T1 2
#define BX_INSTR_PREFETCH_T2 3
#if BX_INSTRUMENTATION
class bxInstruction_c;
void bx_instr_init_env(void);
void bx_instr_exit_env(void);
// called from the CPU core
void bx_instr_initialize(unsigned cpu);
void bx_instr_reset(unsigned cpu, unsigned type);
void bx_instr_new_instruction(unsigned cpu);
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip);
void bx_instr_cnear_branch_not_taken(unsigned cpu);
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip);
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip);
void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64);
void bx_instr_interrupt(unsigned cpu, unsigned vector);
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code);
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip);
void bx_instr_mem_data_access(unsigned cpu, unsigned seg, bx_address offset, unsigned len, unsigned rw);
/* initialization/deinitialization of instrumentalization*/
#define BX_INSTR_INIT_ENV() bx_instr_init_env()
#define BX_INSTR_EXIT_ENV() bx_instr_exit_env()
/* simulation init, shutdown, reset */
#define BX_INSTR_INITIALIZE(cpu_id) bx_instr_initialize(cpu_id)
#define BX_INSTR_EXIT(cpu_id)
#define BX_INSTR_RESET(cpu_id, type) bx_instr_reset(cpu_id, type)
#define BX_INSTR_HLT(cpu_id)
#define BX_INSTR_MWAIT(cpu_id, addr, len, flags)
#define BX_INSTR_NEW_INSTRUCTION(cpu_id) bx_instr_new_instruction(cpu_id)
/* called from command line debugger */
#define BX_INSTR_DEBUG_PROMPT()
#define BX_INSTR_DEBUG_CMD(cmd)
/* branch resoultion */
#define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip) bx_instr_cnear_branch_taken(cpu_id, new_eip)
#define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id) bx_instr_cnear_branch_not_taken(cpu_id)
#define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip) bx_instr_ucnear_branch(cpu_id, what, new_eip)
#define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) bx_instr_far_branch(cpu_id, what, new_cs, new_eip)
/* decoding completed */
#define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64) \
bx_instr_opcode(cpu_id, opcode, len, is32, is64)
/* exceptional case and interrupt */
#define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) \
bx_instr_exception(cpu_id, vector, error_code)
#define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector)
#define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip)
/* TLB/CACHE control instruction executed */
#define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr)
#define BX_INSTR_CACHE_CNTRL(cpu_id, what)
#define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3)
#define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset)
/* execution */
#define BX_INSTR_BEFORE_EXECUTION(cpu_id, i)
#define BX_INSTR_AFTER_EXECUTION(cpu_id, i)
#define BX_INSTR_REPEAT_ITERATION(cpu_id, i)
/* memory access */
#define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw)
/* memory access */
#define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw) \
bx_instr_mem_data_access(cpu_id, seg, offset, len, rw)
/* called from memory object */
#define BX_INSTR_PHY_WRITE(cpu_id, addr, len)
#define BX_INSTR_PHY_READ(cpu_id, addr, len)
/* feedback from device units */
#define BX_INSTR_INP(addr, len)
#define BX_INSTR_INP2(addr, len, val)
#define BX_INSTR_OUTP(addr, len, val)
/* wrmsr callback */
#define BX_INSTR_WRMSR(cpu_id, addr, value)
#else // BX_INSTRUMENTATION
/* initialization/deinitialization of instrumentalization */
#define BX_INSTR_INIT_ENV()
#define BX_INSTR_EXIT_ENV()
/* simulation init, shutdown, reset */
#define BX_INSTR_INITIALIZE(cpu_id)
#define BX_INSTR_EXIT(cpu_id)
#define BX_INSTR_RESET(cpu_id, type)
#define BX_INSTR_HLT(cpu_id)
#define BX_INSTR_MWAIT(cpu_id, addr, len, flags)
#define BX_INSTR_NEW_INSTRUCTION(cpu_id)
/* called from command line debugger */
#define BX_INSTR_DEBUG_PROMPT()
#define BX_INSTR_DEBUG_CMD(cmd)
/* branch resoultion */
#define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip)
#define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id)
#define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip)
#define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip)
/* decoding completed */
#define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64)
/* exceptional case and interrupt */
#define BX_INSTR_EXCEPTION(cpu_id, vector, error_code)
#define BX_INSTR_INTERRUPT(cpu_id, vector)
#define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip)
/* TLB/CACHE control instruction executed */
#define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr)
#define BX_INSTR_CACHE_CNTRL(cpu_id, what)
#define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3)
#define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset)
/* execution */
#define BX_INSTR_BEFORE_EXECUTION(cpu_id, i)
#define BX_INSTR_AFTER_EXECUTION(cpu_id, i)
#define BX_INSTR_REPEAT_ITERATION(cpu_id, i)
/* memory access */
#define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw)
/* memory access */
#define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw)
/* called from memory object */
#define BX_INSTR_PHY_WRITE(cpu_id, addr, len)
#define BX_INSTR_PHY_READ(cpu_id, addr, len)
/* feedback from device units */
#define BX_INSTR_INP(addr, len)
#define BX_INSTR_INP2(addr, len, val)
#define BX_INSTR_OUTP(addr, len, val)
/* wrmsr callback */
#define BX_INSTR_WRMSR(cpu_id, addr, value)
#endif // BX_INSTRUMENTATION

View File

@ -0,0 +1,72 @@
# Copyright (C) 2001 The Bochs Project
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@SUFFIX_LINE@
srcdir = @srcdir@
VPATH = @srcdir@
SHELL = /bin/sh
@SET_MAKE@
CC = @CC@
CFLAGS = @CFLAGS@
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
RANLIB = @RANLIB@
# ===========================================================
# end of configurable options
# ===========================================================
BX_OBJS = \
instrument.o
BX_INCLUDES =
BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/.
.@CPP_SUFFIX@.o:
$(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@
.c.o:
$(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@
libinstrument.a: $(BX_OBJS)
@RMCOMMAND@ libinstrument.a
@MAKELIB@ $(BX_OBJS)
$(RANLIB) libinstrument.a
$(BX_OBJS): $(BX_INCLUDES)
clean:
@RMCOMMAND@ *.o
@RMCOMMAND@ *.a
dist-clean: clean
@RMCOMMAND@ Makefile

View File

@ -0,0 +1,197 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2009 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <assert.h>
#include "bochs.h"
#include "cpu/cpu.h"
#include "disasm/disasm.h"
bxInstrumentation *icpu = NULL;
static disassembler bx_disassembler;
void bx_instr_init_env(void) {}
void bx_instr_exit_env(void) {}
void bx_instr_initialize(unsigned cpu)
{
assert(cpu < BX_SMP_PROCESSORS);
if (icpu == NULL)
icpu = new bxInstrumentation[BX_SMP_PROCESSORS];
icpu[cpu].set_cpu_id(cpu);
fprintf(stderr, "Initialize cpu %d\n", cpu);
}
void bxInstrumentation::bx_instr_reset(unsigned type)
{
valid = is_branch = 0;
num_data_accesses = 0;
active = 1;
}
void bxInstrumentation::bx_instr_new_instruction()
{
if (!active) return;
if (valid)
{
char disasm_tbuf[512]; // buffer for instruction disassembly
unsigned length = opcode_size, n;
bx_disassembler.disasm(is32, is64, 0, 0, opcode, disasm_tbuf);
if(length != 0)
{
fprintf(stderr, "----------------------------------------------------------\n");
fprintf(stderr, "CPU: %d: %s\n", cpu_id, disasm_tbuf);
fprintf(stderr, "LEN: %d\tBYTES: ", length);
for(n=0;n<length;n++) fprintf(stderr, "%02x", opcode[n]);
if(is_branch)
{
fprintf(stderr, "\tBRANCH ");
if(is_taken)
fprintf(stderr, "TARGET " FMT_ADDRX " (TAKEN)", target_linear);
else
fprintf(stderr, "(NOT TAKEN)");
}
fprintf(stderr, "\n");
for(n=0;n < num_data_accesses;n++)
{
fprintf(stderr, "MEM ACCESS[%u]: " FMT_ADDRX " (linear) 0x%08x (physical) %s SIZE: %d\n", n,
data_access[n].laddr,
data_access[n].paddr,
data_access[n].op == BX_READ ? "RD":"WR",
data_access[n].size);
}
fprintf(stderr, "\n");
}
}
valid = is_branch = 0;
num_data_accesses = 0;
}
void bxInstrumentation::branch_taken(bx_address new_eip)
{
if (!active || !valid) return;
// find linear address
bx_address laddr = BX_CPU(cpu_id)->get_laddr(BX_SEG_REG_CS, new_eip);
is_branch = 1;
is_taken = 1;
target_linear = laddr;
}
void bxInstrumentation::bx_instr_cnear_branch_taken(bx_address new_eip)
{
branch_taken(new_eip);
}
void bxInstrumentation::bx_instr_cnear_branch_not_taken()
{
if (!active || !valid) return;
is_branch = 1;
is_taken = 0;
}
void bxInstrumentation::bx_instr_ucnear_branch(unsigned what, bx_address new_eip)
{
branch_taken(new_eip);
}
void bxInstrumentation::bx_instr_far_branch(unsigned what, Bit16u new_cs, bx_address new_eip)
{
branch_taken(new_eip);
}
void bxInstrumentation::bx_instr_opcode(const Bit8u *opcode_bytes, unsigned len, bx_bool is32, bx_bool is64)
{
if (!active) return;
for(unsigned i=0;i<len;i++)
{
opcode[i] = opcode_bytes[i];
}
is32 = is32;
is64 = is64;
opcode_size = len;
valid = 1;
}
void bxInstrumentation::bx_instr_interrupt(unsigned vector)
{
if(active)
{
fprintf(stderr, "CPU %u: interrupt %02xh\n", cpu_id, vector);
}
}
void bxInstrumentation::bx_instr_exception(unsigned vector, unsigned error_code)
{
if(active)
{
fprintf(stderr, "CPU %u: exception %02xh error_code=%x\n", cpu_id, vector, error_code);
}
}
void bxInstrumentation::bx_instr_hwinterrupt(unsigned vector, Bit16u cs, bx_address eip)
{
if(active)
{
fprintf(stderr, "CPU %u: hardware interrupt %02xh\n", cpu_id, vector);
}
}
void bxInstrumentation::bx_instr_mem_data_access(unsigned seg, bx_address offset, unsigned len, unsigned rw)
{
bx_phy_address phy;
if(!active || !valid) return;
if (num_data_accesses >= MAX_DATA_ACCESSES)
{
return;
}
bx_address lin = BX_CPU(cpu_id)->get_laddr(seg, offset);
bx_bool page_valid = BX_CPU(cpu_id)->dbg_xlate_linear2phy(lin, &phy);
phy = A20ADDR(phy);
// If linear translation doesn't exist, a paging exception will occur.
// Invalidate physical address data for now.
if (!page_valid)
{
phy = 0;
}
data_access[num_data_accesses].laddr = lin;
data_access[num_data_accesses].paddr = phy;
data_access[num_data_accesses].op = rw;
data_access[num_data_accesses].size = len;
num_data_accesses++;
}

View File

@ -0,0 +1,249 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2009 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// possible types passed to BX_INSTR_TLB_CNTRL()
#define BX_INSTR_MOV_CR3 10
#define BX_INSTR_INVLPG 11
#define BX_INSTR_TASKSWITCH 12
// possible types passed to BX_INSTR_CACHE_CNTRL()
#define BX_INSTR_INVD 20
#define BX_INSTR_WBINVD 21
// possible types passed to BX_INSTR_FAR_BRANCH()
#define BX_INSTR_IS_CALL 10
#define BX_INSTR_IS_RET 11
#define BX_INSTR_IS_IRET 12
#define BX_INSTR_IS_JMP 13
#define BX_INSTR_IS_INT 14
#define BX_INSTR_IS_SYSCALL 15
#define BX_INSTR_IS_SYSRET 16
#define BX_INSTR_IS_SYSENTER 17
#define BX_INSTR_IS_SYSEXIT 18
// possible types passed to BX_INSTR_PREFETCH_HINT()
#define BX_INSTR_PREFETCH_NTA 0
#define BX_INSTR_PREFETCH_T0 1
#define BX_INSTR_PREFETCH_T1 2
#define BX_INSTR_PREFETCH_T2 3
#if BX_INSTRUMENTATION
class bxInstruction_c;
void bx_instr_init_env(void);
void bx_instr_exit_env(void);
void bx_instr_initialize(unsigned cpu);
// maximum size of an instruction
#define MAX_OPCODE_SIZE 16
// maximum physical addresses an instruction can generate
#define MAX_DATA_ACCESSES 1024
class bxInstrumentation {
public:
bx_bool valid; // is current instruction valid
bx_bool active; // is active
unsigned cpu_id;
/* decoding */
unsigned opcode_size;
Bit8u opcode[MAX_OPCODE_SIZE];
bx_bool is32, is64;
/* memory accesses */
unsigned num_data_accesses;
struct {
bx_address laddr; // linear address
bx_phy_address paddr; // physical address
unsigned op; // BX_READ, BX_WRITE or BX_RW
unsigned size; // 1 .. 8
} data_access[MAX_DATA_ACCESSES];
/* branch resolution and target */
bx_bool is_branch;
bx_bool is_taken;
bx_address target_linear;
public:
bxInstrumentation(): valid(0), active(0) {}
void set_cpu_id(unsigned cpu) { cpu_id = cpu; }
void activate() { active = 1; }
void deactivate() { active = 0; }
void toggle_active() { active = !active; }
bx_bool is_active() const { return active; }
void bx_instr_reset(unsigned type);
void bx_instr_new_instruction();
void bx_instr_cnear_branch_taken(bx_address new_eip);
void bx_instr_cnear_branch_not_taken();
void bx_instr_ucnear_branch(unsigned what, bx_address new_eip);
void bx_instr_far_branch(unsigned what, Bit16u new_cs, bx_address new_eip);
void bx_instr_opcode(const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64);
void bx_instr_interrupt(unsigned vector);
void bx_instr_exception(unsigned vector, unsigned error_code);
void bx_instr_hwinterrupt(unsigned vector, Bit16u cs, bx_address eip);
void bx_instr_mem_data_access(unsigned seg, bx_address offset, unsigned len, unsigned rw);
private:
void branch_taken(bx_address new_eip);
};
void bx_instr_init(unsigned cpu);
extern bxInstrumentation *icpu;
/* initialization/deinitialization of instrumentalization*/
#define BX_INSTR_INIT_ENV() bx_instr_init_env()
#define BX_INSTR_EXIT_ENV() bx_instr_exit_env()
/* simulation init, shutdown, reset */
#define BX_INSTR_INITIALIZE(cpu_id) bx_instr_initialize(cpu_id);
#define BX_INSTR_EXIT(cpu_id)
#define BX_INSTR_RESET(cpu_id, type) icpu[cpu_id].bx_instr_reset(type)
#define BX_INSTR_HLT(cpu_id)
#define BX_INSTR_MWAIT(cpu_id, addr, len, flags)
#define BX_INSTR_NEW_INSTRUCTION(cpu_id) icpu[cpu_id].bx_instr_new_instruction()
/* called from command line debugger */
#define BX_INSTR_DEBUG_PROMPT()
#define BX_INSTR_DEBUG_CMD(cmd)
/* branch resoultion */
#define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip) icpu[cpu_id].bx_instr_cnear_branch_taken(new_eip)
#define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id) icpu[cpu_id].bx_instr_cnear_branch_not_taken()
#define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip) icpu[cpu_id].bx_instr_ucnear_branch(what, new_eip)
#define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) icpu[cpu_id].bx_instr_far_branch(what, new_cs, new_eip)
/* decoding completed */
#define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64) \
icpu[cpu_id].bx_instr_opcode(opcode, len, is32, is64)
/* exceptional case and interrupt */
#define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) \
icpu[cpu_id].bx_instr_exception(vector, error_code)
#define BX_INSTR_INTERRUPT(cpu_id, vector) icpu[cpu_id].bx_instr_interrupt(vector)
#define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) icpu[cpu_id].bx_instr_hwinterrupt(vector, cs, eip)
/* TLB/CACHE control instruction executed */
#define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr)
#define BX_INSTR_CACHE_CNTRL(cpu_id, what)
#define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3)
#define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset)
/* execution */
#define BX_INSTR_BEFORE_EXECUTION(cpu_id, i)
#define BX_INSTR_AFTER_EXECUTION(cpu_id, i)
#define BX_INSTR_REPEAT_ITERATION(cpu_id, i)
/* memory access */
#define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw)
#define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw) \
icpu[cpu_id].bx_instr_mem_data_access(seg, offset, len, rw)
/* called from memory object */
#define BX_INSTR_PHY_WRITE(cpu_id, addr, len)
#define BX_INSTR_PHY_READ(cpu_id, addr, len)
/* feedback from device units */
#define BX_INSTR_INP(addr, len)
#define BX_INSTR_INP2(addr, len, val)
#define BX_INSTR_OUTP(addr, len, val)
/* wrmsr callback */
#define BX_INSTR_WRMSR(cpu_id, addr, value)
#else // BX_INSTRUMENTATION
/* initialization/deinitialization of instrumentalization */
#define BX_INSTR_INIT_ENV()
#define BX_INSTR_EXIT_ENV()
/* simulation init, shutdown, reset */
#define BX_INSTR_INITIALIZE(cpu_id)
#define BX_INSTR_EXIT(cpu_id)
#define BX_INSTR_RESET(cpu_id, type)
#define BX_INSTR_HLT(cpu_id)
#define BX_INSTR_MWAIT(cpu_id, addr, len, flags)
#define BX_INSTR_NEW_INSTRUCTION(cpu_id)
/* called from command line debugger */
#define BX_INSTR_DEBUG_PROMPT()
#define BX_INSTR_DEBUG_CMD(cmd)
/* branch resoultion */
#define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip)
#define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id)
#define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip)
#define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip)
/* decoding completed */
#define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64)
/* exceptional case and interrupt */
#define BX_INSTR_EXCEPTION(cpu_id, vector, error_code)
#define BX_INSTR_INTERRUPT(cpu_id, vector)
#define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip)
/* TLB/CACHE control instruction executed */
#define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr)
#define BX_INSTR_CACHE_CNTRL(cpu_id, what)
#define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3)
#define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset)
/* execution */
#define BX_INSTR_BEFORE_EXECUTION(cpu_id, i)
#define BX_INSTR_AFTER_EXECUTION(cpu_id, i)
#define BX_INSTR_REPEAT_ITERATION(cpu_id, i)
/* memory access */
#define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw)
/* memory access */
#define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw)
/* called from memory object */
#define BX_INSTR_PHY_WRITE(cpu_id, addr, len)
#define BX_INSTR_PHY_READ(cpu_id, addr, len)
/* feedback from device units */
#define BX_INSTR_INP(addr, len)
#define BX_INSTR_INP2(addr, len, val)
#define BX_INSTR_OUTP(addr, len, val)
/* wrmsr callback */
#define BX_INSTR_WRMSR(cpu_id, addr, value)
#endif // BX_INSTRUMENTATION

View File

@ -0,0 +1,72 @@
# Copyright (C) 2001 The Bochs Project
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@SUFFIX_LINE@
srcdir = @srcdir@
VPATH = @srcdir@
SHELL = /bin/sh
@SET_MAKE@
CC = @CC@
CFLAGS = @CFLAGS@
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
RANLIB = @RANLIB@
# ===========================================================
# end of configurable options
# ===========================================================
BX_OBJS = \
instrument.o
BX_INCLUDES =
BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/.
.@CPP_SUFFIX@.o:
$(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@
.c.o:
$(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@
libinstrument.a: $(BX_OBJS)
@RMCOMMAND@ libinstrument.a
@MAKELIB@ $(BX_OBJS)
$(RANLIB) libinstrument.a
$(BX_OBJS): $(BX_INCLUDES)
clean:
@RMCOMMAND@ *.o
@RMCOMMAND@ *.a
dist-clean: clean
@RMCOMMAND@ Makefile

View File

@ -0,0 +1,98 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <assert.h>
#include "bochs.h"
#include "cpu/cpu.h"
struct bx_instr_ia_stats {
bx_bool active;
Bit32u ia_cnt[BX_IA_LAST];
Bit32u total_cnt;
Bit32u interrupts;
Bit32u exceptions;
} *ia_stats;
static logfunctions *instrument_log = new logfunctions ();
#define LOG_THIS instrument_log->
void bx_instr_initialize(unsigned cpu)
{
assert(cpu < BX_SMP_PROCESSORS);
if (ia_stats == NULL)
ia_stats = new bx_instr_ia_stats[BX_SMP_PROCESSORS];
ia_stats[cpu].active = 0;
fprintf(stderr, "Initialize cpu %d instrumentation module\n", cpu);
}
void bx_instr_reset(unsigned cpu, unsigned type)
{
ia_stats[cpu].active = 1;
ia_stats[cpu].total_cnt = 0;
for(int n=0; n < BX_IA_LAST; n++)
ia_stats[cpu].ia_cnt[n] = 0;
ia_stats[cpu].interrupts = ia_stats[cpu].exceptions = 0;
}
void bx_instr_interrupt(unsigned cpu, unsigned vector)
{
if(ia_stats[cpu].active) ia_stats[cpu].interrupts++;
}
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code)
{
if(ia_stats[cpu].active) ia_stats[cpu].exceptions++;
}
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip)
{
if(ia_stats[cpu].active) ia_stats[cpu].interrupts++;
}
#define IA_CNT_DUMP_THRESHOLD 100000000 /* 100M */
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i)
{
if(ia_stats[cpu].active) {
ia_stats[cpu].ia_cnt[i->getIaOpcode()]++;
ia_stats[cpu].total_cnt++;
if (ia_stats[cpu].total_cnt > IA_CNT_DUMP_THRESHOLD) {
printf("Dump IA stats for CPU %d\n", cpu);
printf("----------------------------------------------------------\n");
printf("Interrupts: %d, Exceptions: %d\n", ia_stats[cpu].interrupts, ia_stats[cpu].exceptions);
for (int n=0;n < BX_IA_LAST; n++) {
if (ia_stats[cpu].ia_cnt[n] > 0) {
printf("%s: %f%%\n", get_bx_opcode_name(n), ia_stats[cpu].ia_cnt[n] * 100.0 / ia_stats[cpu].total_cnt);
ia_stats[cpu].ia_cnt[n] = 0;
}
}
ia_stats[cpu].interrupts = ia_stats[cpu].exceptions = ia_stats[cpu].total_cnt = 0;
}
}
}

View File

@ -0,0 +1,187 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// possible types passed to BX_INSTR_TLB_CNTRL()
#define BX_INSTR_MOV_CR3 10
#define BX_INSTR_INVLPG 11
#define BX_INSTR_TASKSWITCH 12
// possible types passed to BX_INSTR_CACHE_CNTRL()
#define BX_INSTR_INVD 20
#define BX_INSTR_WBINVD 21
// possible types passed to BX_INSTR_FAR_BRANCH()
#define BX_INSTR_IS_CALL 10
#define BX_INSTR_IS_RET 11
#define BX_INSTR_IS_IRET 12
#define BX_INSTR_IS_JMP 13
#define BX_INSTR_IS_INT 14
#define BX_INSTR_IS_SYSCALL 15
#define BX_INSTR_IS_SYSRET 16
#define BX_INSTR_IS_SYSENTER 17
#define BX_INSTR_IS_SYSEXIT 18
// possible types passed to BX_INSTR_PREFETCH_HINT()
#define BX_INSTR_PREFETCH_NTA 0
#define BX_INSTR_PREFETCH_T0 1
#define BX_INSTR_PREFETCH_T1 2
#define BX_INSTR_PREFETCH_T2 3
#if BX_INSTRUMENTATION
class bxInstruction_c;
// called from the CPU core
void bx_instr_initialize(unsigned cpu);
void bx_instr_reset(unsigned cpu, unsigned type);
void bx_instr_interrupt(unsigned cpu, unsigned vector);
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code);
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip);
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i);
/* initialization/deinitialization of instrumentalization*/
#define BX_INSTR_INIT_ENV()
#define BX_INSTR_EXIT_ENV()
/* simulation init, shutdown, reset */
#define BX_INSTR_INITIALIZE(cpu_id) bx_instr_initialize(cpu_id)
#define BX_INSTR_EXIT(cpu_id)
#define BX_INSTR_RESET(cpu_id, type) bx_instr_reset(cpu_id, type)
#define BX_INSTR_HLT(cpu_id)
#define BX_INSTR_MWAIT(cpu_id, addr, len, flags)
#define BX_INSTR_NEW_INSTRUCTION(cpu_id)
/* called from command line debugger */
#define BX_INSTR_DEBUG_PROMPT()
#define BX_INSTR_DEBUG_CMD(cmd)
/* branch resoultion */
#define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip)
#define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id)
#define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip)
#define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip)
/* decoding completed */
#define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64)
/* exceptional case and interrupt */
#define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) \
bx_instr_exception(cpu_id, vector, error_code)
#define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector)
#define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip)
/* TLB/CACHE control instruction executed */
#define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr)
#define BX_INSTR_CACHE_CNTRL(cpu_id, what)
#define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3)
#define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset)
/* execution */
#define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) bx_instr_before_execution(cpu_id, i)
#define BX_INSTR_AFTER_EXECUTION(cpu_id, i)
#define BX_INSTR_REPEAT_ITERATION(cpu_id, i)
/* memory access */
#define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw)
/* memory access */
#define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw)
/* called from memory object */
#define BX_INSTR_PHY_WRITE(cpu_id, addr, len)
#define BX_INSTR_PHY_READ(cpu_id, addr, len)
/* feedback from device units */
#define BX_INSTR_INP(addr, len)
#define BX_INSTR_INP2(addr, len, val)
#define BX_INSTR_OUTP(addr, len, val)
/* wrmsr callback */
#define BX_INSTR_WRMSR(cpu_id, addr, value)
#else // BX_INSTRUMENTATION
/* initialization/deinitialization of instrumentalization */
#define BX_INSTR_INIT_ENV()
#define BX_INSTR_EXIT_ENV()
/* simulation init, shutdown, reset */
#define BX_INSTR_INITIALIZE(cpu_id)
#define BX_INSTR_EXIT(cpu_id)
#define BX_INSTR_RESET(cpu_id, type)
#define BX_INSTR_HLT(cpu_id)
#define BX_INSTR_MWAIT(cpu_id, addr, len, flags)
#define BX_INSTR_NEW_INSTRUCTION(cpu_id)
/* called from command line debugger */
#define BX_INSTR_DEBUG_PROMPT()
#define BX_INSTR_DEBUG_CMD(cmd)
/* branch resoultion */
#define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip)
#define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id)
#define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip)
#define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip)
/* decoding completed */
#define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64)
/* exceptional case and interrupt */
#define BX_INSTR_EXCEPTION(cpu_id, vector, error_code)
#define BX_INSTR_INTERRUPT(cpu_id, vector)
#define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip)
/* TLB/CACHE control instruction executed */
#define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr)
#define BX_INSTR_CACHE_CNTRL(cpu_id, what)
#define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3)
#define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset)
/* execution */
#define BX_INSTR_BEFORE_EXECUTION(cpu_id, i)
#define BX_INSTR_AFTER_EXECUTION(cpu_id, i)
#define BX_INSTR_REPEAT_ITERATION(cpu_id, i)
/* memory access */
#define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw)
/* memory access */
#define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw)
/* called from memory object */
#define BX_INSTR_PHY_WRITE(cpu_id, addr, len)
#define BX_INSTR_PHY_READ(cpu_id, addr, len)
/* feedback from device units */
#define BX_INSTR_INP(addr, len)
#define BX_INSTR_INP2(addr, len, val)
#define BX_INSTR_OUTP(addr, len, val)
/* wrmsr callback */
#define BX_INSTR_WRMSR(cpu_id, addr, value)
#endif // BX_INSTRUMENTATION

View File

@ -0,0 +1,254 @@
README-instrumentation
To use instrumentation features in bochs, you must compile in support for it.
You should build a custom instrumentation library in a separate directory in
the "instrument/" directory. To tell configure which instrumentation library
you want to use, use the "--enable-instrumentation" option. The default
library consists of a set of stubs, and the following are equivalent:
./configure [...] --enable-instrumentation
./configure [...] --enable-instrumentation="instrument/stubs"
You could make a separate directory with your custom library, for example
"instrument/myinstrument", copy the contents of the "instrument/stubs"
directory to it, then customize it. Use:
./configure [...] --enable-instrumentation="instrument/myinstrument"
-----------------------------------------------------------------------------
BOCHS instrumentation callbacks
void bx_instr_init_env();
The callback is called when Bochs is initialized, before of reading .bochsrc.
It can be used for registration of parameters in siminterface. Then
when bx_instr_init() is called it can access configuration parameters defined
by bx_instr_init_env(), so instrumentalization module can use additional
options in .bochsrc.
void bx_instr_exit_env();
The callback is called each time Bochs exits.
void bx_instr_initialize(unsigned cpu);
The callback is called each time, when Bochs initializes the CPU object. It
can be used for initialization of user's data, dynamic memory allocation and
etc.
void bx_instr_exit(unsigned cpu);
The callback is called each time, when Bochs destructs the CPU object. It can
be used for destruction of user's data, allocated by bx_instr_init callback.
void bx_instr_reset(unsigned cpu, unsigned type);
The callback is called each time, when Bochs resets the CPU object. It would
be executed once at the start of simulation and each time that user presses
RESET BUTTON on the simulator's control panel.
void bx_instr_hlt(unsigned cpu);
The callback is called each time, when Bochs' emulated CPU enters HALT or
SHUTDOWN state.
void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags);
The callback is called each time, when Bochs' emulated CPU enters to the MWAIT
state. The callback receives monitored memory range and MWAIT flags as a
parameters.
void bx_instr_new_instruction(unsigned cpu);
The callback is called each time, when Bochs completes (commits) already
finished instruction and starts a new one.
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip);
The callback is called each time, when currently executed instruction is a
conditional near branch and it is taken.
void bx_instr_cnear_branch_not_taken(unsigned cpu);
The callback is called each time, when currently executed instruction is a
conditional near branch and it is not taken.
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip);
The callback is called each time, when currently executed instruction is an
unconditional near branch (always taken).
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip);
The callback is called each time, when currently executed instruction is an
unconditional far branch (always taken).
void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64);
The callback is called each time, when Bochs completes to decode a new
instruction. Through this callback function Bochs could provide an opcode of
the instruction, opcode length and an execution mode (16/32/64).
Please note, that Bochs uses translation caches so each simulated instruction
might be executed multiple times but decoded only once.
void bx_instr_interrupt(unsigned cpu, unsigned vector);
The callback is called each time, when Bochs simulator executes an interrupt
(software interrupt, hardware interrupt or an exception).
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code);
The callback is called each time, when Bochs simulator executes an exception.
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip);
The callback is called each time, when Bochs simulator executes a hardware
interrupt.
void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr);
The callback is called each time the CLFLUSH instruction is executed.
void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3);
void bx_instr_cache_cntrl(unsigned cpu, unsigned what);
The callback is called each time, when Bochs simulator executes a cache/tlb
control instruction.
Possible instruction types, passed through bx_instr_tlb_cntrl:
#define BX_INSTR_MOV_CR3 10
#define BX_INSTR_INVLPG 11
#define BX_INSTR_TASKSWITCH 12
Possible instruction types, passed through bx_instr_cache_cntrl:
#define BX_INSTR_INVD 20
#define BX_INSTR_WBINVD 21
void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset);
The callback is called each time, when Bochs simulator executes a PREFETCH
instruction.
Possible PREFETCH types:
#define BX_INSTR_PREFETCH_NTA 00
#define BX_INSTR_PREFETCH_T0 01
#define BX_INSTR_PREFETCH_T1 02
#define BX_INSTR_PREFETCH_T2 03
The seg/offset arguments indicate the address of the requested prefetch.
void bx_instr_wrmsr(unsigned cpu, unsigned msr, Bit64u value);
This callback is called each time when WRMSR instruction is executed.
MSR number and written value passed as parameters to the callback function.
void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i);
The callback is called each time, when Bochs simulator starts a new repeat
iteration.
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i);
The callback is called each time, when Bochs simulator starts a new
instruction execution. In case of repeat instruction the callback will
be called only once before the first iteration will be started.
void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i);
The callback is called each time, when Bochs simulator finishes any
instruction execution. In case of repeat instruction the callback will
be called only once after all repeat iterations.
void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw);
The callback is called each time, when Bochs simulator executes a linear
memory access. Note that no page split accesses will be generated because
Bochs splits page split accesses to two different memory accesses during its
execution flow. The callback also will not be generated in case of direct
physical memory access like in SMM, VMM or SVM modes.
Possible access types are: BX_READ, BX_WRITE and BX_RW.
Currently the callback is not supported when repeat-speedups optimization is
enabled.
void bx_instr_mem_data_access(unsigned cpu, unsigned seg, bx_address offset, unsigned len, unsigned rw);
The callback is called each time, when Bochs simulator executes segment based
linear memory access. In contrast to previous callback it will be called even
if memory access fails because of any reason (for example segment protection
failure or page fault).
The callback will not be called for system memory accesses like sys desriptor
tables reads/writes or new stack pushes during far call or exception.
void bx_instr_phy_read(unsigned cpu, bx_address addr, unsigned len);
void bx_instr_phy_write(unsigned cpu, bx_address addr, unsigned len);
These callback functions are the feedback from external memory system.
void bx_instr_inp(Bit16u addr, unsigned len);
void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val);
void bx_instr_outp(Bit16u addr, unsigned len, unsigned val);
These callback functions are a feedback from various system devices.
-----------------------------------------------------------------------------
Known problems:
1. BX_INSTR_LIN_ACCESS doesn't work when repeat-speedups feature is enabled.
2. BX_INSTR_MEM_DATA doesn't work when repeat-speedups feature is enabled.
Feature requests:
1. BX_INSTR_CNEAR_BRANCH_NOT_TAKEN callback should have an additional
'not taken' new_EIP parameter.
2. BX_INSTR_SMI, BX_INSTR_NMI, BX_INSTR_SIPI and other external events
callbacks
3. ???
While using Bochs as a reference model for simulations, the simulator needs
information about what loads/stores are taking place with each instruction.
Presumably, that is what the BX_INSTR_MEM_DATA() instrumentation macros
cover (which is the place where our simulator hooks up).
The RETnear_xxx() functions call access_linear() directly, rather than call
read_virtual_xxx() functions. This is a problem for code making use of the
BX_INSTR_MEM_DATA() hook because it does not get called for these
instructions. Should this be changed along with some other instructions
that exhibit this?
Brian Slechta

View File

@ -0,0 +1,72 @@
# Copyright (C) 2001 The Bochs Project
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@SUFFIX_LINE@
srcdir = @srcdir@
VPATH = @srcdir@
SHELL = /bin/sh
@SET_MAKE@
CC = @CC@
CFLAGS = @CFLAGS@
CXX = @CXX@
CXXFLAGS = @CXXFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
RANLIB = @RANLIB@
# ===========================================================
# end of configurable options
# ===========================================================
BX_OBJS = \
instrument.o
BX_INCLUDES =
BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/.
.@CPP_SUFFIX@.o:
$(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@
.c.o:
$(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@
libinstrument.a: $(BX_OBJS)
@RMCOMMAND@ libinstrument.a
@MAKELIB@ $(BX_OBJS)
$(RANLIB) libinstrument.a
$(BX_OBJS): $(BX_INCLUDES)
clean:
@RMCOMMAND@ *.o
@RMCOMMAND@ *.a
dist-clean: clean
@RMCOMMAND@ Makefile

View File

@ -0,0 +1,72 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2009 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "bochs.h"
#if BX_INSTRUMENTATION
void bx_instr_init_env(void) {}
void bx_instr_exit_env(void) {}
void bx_instr_initialize(unsigned cpu) {}
void bx_instr_exit(unsigned cpu) {}
void bx_instr_reset(unsigned cpu, unsigned type) {}
void bx_instr_hlt(unsigned cpu) {}
void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags) {}
void bx_instr_new_instruction(unsigned cpu) {}
void bx_instr_debug_promt() {}
void bx_instr_debug_cmd(const char *cmd) {}
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip) {}
void bx_instr_cnear_branch_not_taken(unsigned cpu) {}
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip) {}
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip) {}
void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64) {}
void bx_instr_interrupt(unsigned cpu, unsigned vector) {}
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code) {}
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip) {}
void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3) {}
void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr) {}
void bx_instr_cache_cntrl(unsigned cpu, unsigned what) {}
void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset) {}
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i) {}
void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i) {}
void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i) {}
void bx_instr_inp(Bit16u addr, unsigned len) {}
void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val) {}
void bx_instr_outp(Bit16u addr, unsigned len, unsigned val) {}
void bx_instr_mem_data_access(unsigned cpu, unsigned seg, bx_address offset, unsigned len, unsigned rw) {}
void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw) {}
void bx_instr_phy_write(unsigned cpu, bx_address addr, unsigned len) {}
void bx_instr_phy_read(unsigned cpu, bx_address addr, unsigned len) {}
void bx_instr_wrmsr(unsigned cpu, unsigned addr, Bit64u value) {}
#endif

View File

@ -0,0 +1,228 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2009 Stanislav Shwartsman
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// possible types passed to BX_INSTR_TLB_CNTRL()
#define BX_INSTR_MOV_CR3 10
#define BX_INSTR_INVLPG 11
#define BX_INSTR_TASKSWITCH 12
// possible types passed to BX_INSTR_CACHE_CNTRL()
#define BX_INSTR_INVD 20
#define BX_INSTR_WBINVD 21
// possible types passed to BX_INSTR_FAR_BRANCH()
#define BX_INSTR_IS_CALL 10
#define BX_INSTR_IS_RET 11
#define BX_INSTR_IS_IRET 12
#define BX_INSTR_IS_JMP 13
#define BX_INSTR_IS_INT 14
#define BX_INSTR_IS_SYSCALL 15
#define BX_INSTR_IS_SYSRET 16
#define BX_INSTR_IS_SYSENTER 17
#define BX_INSTR_IS_SYSEXIT 18
// possible types passed to BX_INSTR_PREFETCH_HINT()
#define BX_INSTR_PREFETCH_NTA 0
#define BX_INSTR_PREFETCH_T0 1
#define BX_INSTR_PREFETCH_T1 2
#define BX_INSTR_PREFETCH_T2 3
#if BX_INSTRUMENTATION
class bxInstruction_c;
void bx_instr_init_env(void);
void bx_instr_exit_env(void);
// called from the CPU core
void bx_instr_initialize(unsigned cpu);
void bx_instr_exit(unsigned cpu);
void bx_instr_reset(unsigned cpu, unsigned type);
void bx_instr_hlt(unsigned cpu);
void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags);
void bx_instr_new_instruction(unsigned cpu);
void bx_instr_debug_promt();
void bx_instr_debug_cmd(const char *cmd);
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip);
void bx_instr_cnear_branch_not_taken(unsigned cpu);
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip);
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip);
void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64);
void bx_instr_interrupt(unsigned cpu, unsigned vector);
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code);
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip);
void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3);
void bx_instr_cache_cntrl(unsigned cpu, unsigned what);
void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset);
void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr);
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i);
void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i);
void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i);
void bx_instr_inp(Bit16u addr, unsigned len);
void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val);
void bx_instr_outp(Bit16u addr, unsigned len, unsigned val);
void bx_instr_mem_data_access(unsigned cpu, unsigned seg, bx_address offset, unsigned len, unsigned rw);
void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw);
void bx_instr_phy_write(unsigned cpu, bx_address addr, unsigned len);
void bx_instr_phy_read(unsigned cpu, bx_address addr, unsigned len);
void bx_instr_wrmsr(unsigned cpu, unsigned addr, Bit64u value);
/* initialization/deinitialization of instrumentalization*/
#define BX_INSTR_INIT_ENV() bx_instr_init_env()
#define BX_INSTR_EXIT_ENV() bx_instr_exit_env()
/* simulation init, shutdown, reset */
#define BX_INSTR_INITIALIZE(cpu_id) bx_instr_initialize(cpu_id)
#define BX_INSTR_EXIT(cpu_id) bx_instr_exit(cpu_id)
#define BX_INSTR_RESET(cpu_id, type) bx_instr_reset(cpu_id, type)
#define BX_INSTR_HLT(cpu_id) bx_instr_hlt(cpu_id)
#define BX_INSTR_MWAIT(cpu_id, addr, len, flags) \
bx_instr_mwait(cpu_id, addr, len, flags)
#define BX_INSTR_NEW_INSTRUCTION(cpu_id) bx_instr_new_instruction(cpu_id)
/* called from command line debugger */
#define BX_INSTR_DEBUG_PROMPT() bx_instr_debug_promt()
#define BX_INSTR_DEBUG_CMD(cmd) bx_instr_debug_cmd(cmd)
/* branch resoultion */
#define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip) bx_instr_cnear_branch_taken(cpu_id, new_eip)
#define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id) bx_instr_cnear_branch_not_taken(cpu_id)
#define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip) bx_instr_ucnear_branch(cpu_id, what, new_eip)
#define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) bx_instr_far_branch(cpu_id, what, new_cs, new_eip)
/* decoding completed */
#define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64) \
bx_instr_opcode(cpu_id, opcode, len, is32, is64)
/* exceptional case and interrupt */
#define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) \
bx_instr_exception(cpu_id, vector, error_code)
#define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector)
#define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip)
/* TLB/CACHE control instruction executed */
#define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) bx_instr_clflush(cpu_id, laddr, paddr)
#define BX_INSTR_CACHE_CNTRL(cpu_id, what) bx_instr_cache_cntrl(cpu_id, what)
#define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) bx_instr_tlb_cntrl(cpu_id, what, new_cr3)
#define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) \
bx_instr_prefetch_hint(cpu_id, what, seg, offset)
/* execution */
#define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) bx_instr_before_execution(cpu_id, i)
#define BX_INSTR_AFTER_EXECUTION(cpu_id, i) bx_instr_after_execution(cpu_id, i)
#define BX_INSTR_REPEAT_ITERATION(cpu_id, i) bx_instr_repeat_iteration(cpu_id, i)
/* memory access */
#define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) bx_instr_lin_access(cpu_id, lin, phy, len, rw)
/* memory access */
#define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw) bx_instr_mem_data_access(cpu_id, seg, offset, len, rw)
/* called from memory object */
#define BX_INSTR_PHY_WRITE(cpu_id, addr, len) bx_instr_phy_write(cpu_id, addr, len)
#define BX_INSTR_PHY_READ(cpu_id, addr, len) bx_instr_phy_read(cpu_id, addr, len)
/* feedback from device units */
#define BX_INSTR_INP(addr, len) bx_instr_inp(addr, len)
#define BX_INSTR_INP2(addr, len, val) bx_instr_inp2(addr, len, val)
#define BX_INSTR_OUTP(addr, len, val) bx_instr_outp(addr, len, val)
/* wrmsr callback */
#define BX_INSTR_WRMSR(cpu_id, addr, value) bx_instr_wrmsr(cpu_id, addr, value)
#else
/* initialization/deinitialization of instrumentalization */
#define BX_INSTR_INIT_ENV()
#define BX_INSTR_EXIT_ENV()
/* simulation init, shutdown, reset */
#define BX_INSTR_INITIALIZE(cpu_id)
#define BX_INSTR_EXIT(cpu_id)
#define BX_INSTR_RESET(cpu_id, type)
#define BX_INSTR_HLT(cpu_id)
#define BX_INSTR_MWAIT(cpu_id, addr, len, flags)
#define BX_INSTR_NEW_INSTRUCTION(cpu_id)
/* called from command line debugger */
#define BX_INSTR_DEBUG_PROMPT()
#define BX_INSTR_DEBUG_CMD(cmd)
/* branch resoultion */
#define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip)
#define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id)
#define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip)
#define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip)
/* decoding completed */
#define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64)
/* exceptional case and interrupt */
#define BX_INSTR_EXCEPTION(cpu_id, vector, error_code)
#define BX_INSTR_INTERRUPT(cpu_id, vector)
#define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip)
/* TLB/CACHE control instruction executed */
#define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr)
#define BX_INSTR_CACHE_CNTRL(cpu_id, what)
#define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3)
#define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset)
/* execution */
#define BX_INSTR_BEFORE_EXECUTION(cpu_id, i)
#define BX_INSTR_AFTER_EXECUTION(cpu_id, i)
#define BX_INSTR_REPEAT_ITERATION(cpu_id, i)
/* memory access */
#define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw)
/* memory access */
#define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw)
/* called from memory object */
#define BX_INSTR_PHY_WRITE(cpu_id, addr, len)
#define BX_INSTR_PHY_READ(cpu_id, addr, len)
/* feedback from device units */
#define BX_INSTR_INP(addr, len)
#define BX_INSTR_INP2(addr, len, val)
#define BX_INSTR_OUTP(addr, len, val)
/* wrmsr callback */
#define BX_INSTR_WRMSR(cpu_id, addr, value)
#endif