SPARC Architectural Model : VCPU Interface
Introduction
Vcpu hides the details of the cpu specific implementation.
It presents an abstract interface to the "virtual cpu" - for cpu with multiple strands, it represents each strand; for cpu without strands, it represent the cpu.
A few instances of cpu objects could be created; each cpu object may have a few cpu cores, each core may have a few strands.
CPU cores could run on separate threads of the host machine.
The interface is defined in vcpu.h file. It allows a hook up for an external source level debugger or user interface frontend module. Cpu module is built as a shared library. Vcpu interface has the following components, see Figure 1 below.
- control interface
- system interface (Memory and IO)
-
trace interface
Exported interface – routines in the CPU module which is called from outside of the module. Pointers to the routines exposed by the CPU module are defined in VCPU_ExInterface structure.
Imported interface – routines which CPU module calls to get access to the rest of the system.
It is defined by VCPU_ImpIntf structure - set of pointers that CPU module uses to send a request to the system modules.
Control interface constitute an exported interface; system and trace interfaces constitute an imported interface.
Memory is represented by an abstract interface to allow it to model different levels of memory hierarchy, including L2/L3 caches. Cache models are not included.
Currently, there are sparse memory models and flat memory models. Due to performance consideration, the memory model option is defined at build time instead of at run time.
Tracer is represented by an abstract interface which allows hook up of different analyzers and performance models. Vtracer interface is defined in vtracer.h header file.
The Cpu model calls Vtracer methods to output complete information about the architecture state change for every instruction. The information for every instruction is accumulated in VCPU_Instruction structure. Trap information is collected in VCPU_Trap structure, VCPU_TLB is for tlb information.
Cpu module instantiation.
Control interface.
Memory interface.
Physical IO interface.
Tracer interface.
NAME
get_ex_interface - Get exported interface from the cpu module
SYNOPSIS
#include “vcpu.h”
extern "C" int get_ex_interface
(
VCPU_ExInterface *intf // pointer to the interface structure
);
typedef int (*VCPU_GetIntfFn )( VCPU_ExInterface *intf );
DESCRIBTION
To get exported interface from the cpu shared library get_ ex_interface () method should be used. It takes a pointer to the VCPU_ExInterface structure and assigns the function pointers inside this structure to the addresses of the corresponding routines implemented in the CPU module.
RETURN VALUES
0 - success;
1 – fail.
USAGE
// open shared library, lib_name is the name of cpu shared libriry.
void *cpu_lib_handle = dlopen (lib_name, RTLD_LAZY|RTLD_GLOBAL|RTLD_PARENT);
// extract cpu lib exported interface
VCPU_GetIntfFn get_interface = (VCPU_GetIntfFn)dlsym ( cpu_lib_handle, "get_ex_interface" );
// obtain exported cpu interface
VCPU_ExInterface g_cpu_ex_intf;
get_interface ( &g_cpu_ex_intf);
//Create a vcpu instance
Vcpu * vcpu = (Vcpu*)g_cpu_ex_intf.create( &config_info, imp_intf );
SEE ALSO
NAME
create - Create and configure a vcpu instance.
SYNOPSIS
#include “vcpu.h”
void * (*create ) // new cpu module
(
VCPU_Config *cinfo, // cpu config params
VCPU_ImpIntf *intf // interface to the system
);
DESCRIPTION
This function pointer is a member of VCPU_ExInterface structure.
Pointer to the routine to create and configure a vcpu instance.
The routine takes a pointer to the set of vcpu parameters and a pointer to the imported interface structure.
RETURN VALUES
return a pointer to the vcpu class.
NULL if fail.
USAGE
Create a vcpu instance. Cpu module implementation may choose to create all core/strand objects at once and this call may simply return a pointer to the next available vcpu object.
This call should be made only once for each vcpu
A set of parameters describing vcpu configuration options are defined in
VCPU_Config structure.
Vcpu * vcpu = (Vcpu*)g_cpu_ex_intf.create( &config_info, imp_intf );
After vcpu instance is created vcpu id is assigned in sequential order – in the order create() calls are made, starting from 0.
From this point vcpu methods which are defined by Vcpu abstract class could be used.
SEE ALSO
NAME
destroy - Destroy all vcpu instances.
SYNOPSIS
#include “vcpu.h”
int (*destroy ) ();
DESCRIPTION
This function pointer is a member of VCPU_ExInterface structure.
Pointer to the routine to destroy all vcpu instances.
RETURN VALUES
1 – success;
0 - fail.
USAGE
int status = g_cpu_ex_intf.destroy();
SEE ALSO
NAME
reset - Reset cpu module.
SYNOPSIS
#include “vcpu.h”
int (*reset ) ();
DESCRIPTION
This function pointer is a member of VCPU_ExInterface structure.
Pointer to the routine to reset architecture visible CPU state.
RETURN VALUES
1 – success;
0 - fail.
USAGE
int status = g_cpu_ex_intf.reset();
SEE ALSO
NAME
save - Save complete simulation state for the cpu module.
SYNOPSIS
#include “vcpu.h”
int (*save ) (char *dir_name);
DESCRIPTION
This function pointer is a member of VCPU_ExInterface structure.
Pointer to the routine to save complete simulation state for the CPU module.
The state is saved to the directory dir_name.
RETURN VALUES
1 – success;
0 - fail.
USAGE
int status = g_cpu_ex_intf.save(dir_name);
SEE ALSO
NAME
restore - Restore complete simulation state for the cpu module.
SYNOPSIS
#include “vcpu.h”
int (*restore ) (char *dir_name);
DESCRIPTION
This function pointer is a member of VCPU_ExInterface structure.
Pointer to the routine to restore complete simulation state for the CPU module.
The state is restored from the directory dir_name.
RETURN VALUES
1 – success;
0 - fail.
USAGE
int status = g_cpu_ex_intf.restore(dir_name);
SEE ALSO
NAME
Vcpu::id - Get vcpu id
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::id();
DESCRIPTION
Virtual method of Vcpu class which is used to get vcpu id. The id is used as an argument to other routines to identify the vcpu instance.
"Unique" platform dependent id of a cpu. The id is the one that is to be used for cpu cross calls and identifying cpu target for device interrupts. Typically function Vcpu *get_vcpu(int id), defined in cpu_interface.h is used to get the target Vcpu pointer given its id. The id's may or may not by sequential, they are defined by cpu sysconf cpu parameter "id". If the parameter is not present on cpu config line, id's are assigned in sequential order.
RETURN VALUES
vcpu id value
USAGE
Create a vcpu instance, this call should be made only once for each vcpu
Vcpu * vcpu = (Vcpu*)g_cpu_ex_intf.create( &config_info, imp_intf );
After vcpu instance is created the id is assigned in sequential order – in the order create() calls are made, starting from 0.
From this point vcpu methods which are defined by Vcpu abstract class could be used.
...
printf(“vcpu id is : %i \n”) vcpu->id();
SEE ALSO
NAME
Vcpu::stepi - Step n number of instructions
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::stepi ( int64_t n=1 );
DESCRIPTION
Virtual method of Vcpu class - step n number of instructions.
Each Vcpu can be called from a separate working thread of the host machine. Vcpu's that belong to the same core may need to be on the same working thread to reduce needs of locking for MT safaty
RETURN VALUES
1 – success;
0 – fail.
USAGE
....
Step 100 number of instructions
int n = 100;
vcpu->stepi(n);
SEE ALSO
NAME
Vcpu::update_stick– increment stick reg value;
SYNOPSIS
#include “vcpu.h”
virtual void Vcpu::update_stick(int64_t stickincr);
DESCRIPTION
Virtual methods of Vcpu class to increment stick reg value by stickincr amount.
RETURN VALUES
none
USAGE
// increment stick reg value by 10
g_vcpu[cpu_id]->update_stick(10);
SEE ALSO
NAME
Vcpu::interrupt - Signal an interrupt
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::interrupt ( VCPU_InterruptRequest *signal );
DESCRIPTION
Virtual method of Vcpu class to signal an interrupt. The interrupt message is described by the structure VCPU_InterruptRequest
RETURN VALUES
1 – success;
0 – fail.
USAGE
VCPU_InterruptRequest signal;
signal.isid = src_aid;
signal.itid = dst_aid;
signal.data[0] = idata[0];
vcpu->interrupt(&signal);
SEE ALSO
Vcpu:: access integer register
NAME
Vcpu::get_ireg - Read integer register
Vcpu::set_ireg - Write integer register
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::get_ireg (int wp, int regnum, uint64_t & regvalue);
virtual int Vcpu::set_ireg (int wp, int regnum, uint64_t value);
DESCRIPTION
Virtual methods of Vcpu class to read/write an integer register.
For SPARC V9 registers access
regnum = 0-7 (globals); wp = 0 (normal) , 1 (alternate) , 2 (mmu), 3 (interrupt)
regnum = 8-31; wp = -1 (current), wp >= 0 (window number)
RETURN VALUES
1 – success;
0 – fail.
USAGE
int reg_idx = 16;
uint64_t value = 0;
vcpu->get_ireg(VCPU_ACC_CUR , reg_idx, value);
value &= 0xff;
vcpu->set_ireg(VCPU_ACC_CUR , reg_idx, value);
SEE ALSO
Vcpu:: access floating point register
NAME
Vcpu::get_freg - Read floating point register
Vcpu::set_freg - Write floating point register
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::get_freg (int issingle, int regnum, uint64_t & regvalue);
virtual int Vcpu::set_freg (int issingle, int regnum, uint64_t value);
DESCRIPTION
Virtual methods of Vcpu class to read/write a floating point register.
If issingle == 1 – single precision 32 bit floating point register;
issingle == 0 – double precision 64 bit floating point register;
regnum is defined according to SPARC V9 and core specific implementation.
RETURN VALUES
1 – success;
0 – fail.
USAGE
int reg_idx = 16;
uint32_t value32 = 0;
// single precision value
vcpu->get_freg(1, reg_idx, value32);
// double precision value
#define SWAP_BIT_5_0(I) ((( (I) & 0x01e ) | ( ((I) & 0x020) >> 5 )) & 0x1f)
uint64_t value64 = 0;
vcpu->get_freg(0, SWAP_BIT_5_0(reg_idx), value64);
SEE ALSO
Vcpu:: access privileged register
NAME
Vcpu::get_pr - Read privileged register
Vcpu::set_pr - Write privileged register
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::get_pr(int regnum, uint64_t & value);
virtual int Vcpu::set_pr(int regnum, uint64_t value);
DESCRIPTION
Virtual methods of Vcpu class to read/write a privileged register.
For trap-level specific registers, get/set_pr functions use the current trap_level.
regnum = 0...31, it is defined according to SPARC V9 and core specific implementation.
RETURN VALUES
1 – success;
0 – fail.
USAGE
uint64_t value = 0;
vcpu->get_pr(VCPU_PR_PSTATE, value);
printf (“PSTATE = %llx”, value);
vcpu->get_pr(VCPU_PR_CWP, value);
printf(“CWP = %llx”, value);
SEE ALSO
Vcpu:: access ancillary register
NAME
Vcpu::get_acr - Read ancillary register
Vcpu::set_asr - Write ancillary register
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::get_asr(int regnum, uint64_t & value);
virtual int Vcpu::set_asr(int regnum, uint64_t value);
DESCRIPTION
Virtual methods of Vcpu class to read/write an ancillary register.
regnum is defined according to SPARC V9 and core specific implementation.
RETURN VALUES
1 – success;
0 – fail.
USAGE
uint64_t value = 0;
vcpu->get_asr(VCPU_ASR_PC, value)
printf (“PC = %llx”, value);
vcpu->get_asr(VCPU_ASR_ASI, value);
printf(“ASI = %llx”, value);
SEE ALSO
Vcpu:: access trap specific registers
NAME
Vcpu::get_trapreg - Read trap-level specific register
Vcpu::set_trapreg - Write trap-level specific register
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::get_trapreg(int tl, int regnum, uint64_t & value);
virtual int Vcpu::set_trapreg(int tl, int regnum, uint64_t value);
DESCRIPTION
Virtual methods of Vcpu class to read/write a trap-level specific register,
where tl is a trap level;
regnum could be one of
VCPU_PR_TPC = 0x0,
VCPU_PR_TNPC = 0x1,
VCPU_PR_TSTATE = 0x2,
VCPU_PR_TT = 0x3.
RETURN VALUES
1 – success;
0 – fail.
USAGE
uint64_t value = 0;
int tl = 1;
vcpu->get_trapreg(1, VCPU_PR_TPC, value)
printf (“trap level = %i, tpc = %llx”, tl, value);
SEE ALSO
Vcpu:: access hyper privileged register
NAME
Vcpu::get_hpr - Read hyper privileged register
Vcpu::set_hpr - Write hyper privileged register
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::get_hpr(int regnum, uint64_t & value);
virtual int Vcpu::set_hpr(int regnum, uint64_t value);
DESCRIPTION
Virtual methods of Vcpu class to read/write a hyper privileged register.
regnum is defined according to core specific implementation.
RETURN VALUES
1 – success;
0 – fail.
USAGE
uint64_t value = 0;
vcpu->get_hpr(VCPU_HPR_HPSTATE, value);
printf (“HPSTATE = %llx”, value);
SEE ALSO
NAME
Vcpu::read_mem – Read memory in the current CPU state
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::read_mem
(
uint64_t addr, // byte address
uint64_t *value, // value to load
int size, // number of bytes
int asi= 0x82, // ASI_PRIMARY_NO_FAULT
int is_physical=0 // 1-physical address, 0-virtual address
);
DESCRIPTION
Virtual methods of Vcpu class to read memory is used if caches or write buffer are present;
address could be virtuall or physical;
little or big endian access is defined by current state;
RETURN VALUES
1 – success;
0 – fail.
USAGE
// read from the double word aligned address
uint64_t addr8 = addr & ~uint64_t(7);
uint64_t value = 0;
if ( g_vcpu[cpu_id]->read_mem(addr8, &value, 8) != 0 )
{
reply_error (1);
return 1;
}
SEE ALSO
NAME
Vcpu::write_mem – Write memory in the current CPU state
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::write_mem
(
uint64_t addr, // byte address
uint64_t value, // value to write
int size, // number of bytes
int asi= 0x82, // ASI_PRIMARY_NO_FAULT
int is_physical=0 // 1-physical address, 0-virtual address
);
DESCRIPTION
Virtual methods of Vcpu class to write memory is used if caches or write buffer are present;
address could be virtuall or physical;
little or big endian access is defined by current state;
RETURN VALUES
1 – success;
0 – fail.
USAGE
// write 0 value to the double word aligned address
uint64_t addr8 = addr & ~uint64_t(7);
uint64_t value = 0;
if ( g_vcpu[cpu_id]->write_mem(addr8, value, 8) != 0 )
{
reply_error (1);
return 1;
}
SEE ALSO
NAME
Vcpu::set_breakpoint – Set a breakpoint
SYNOPSIS
#include “vcpu.h”
typedef int (*VCPU_BpActionFn)( int bp_id, int vcpu_id );
virtual int Vcpu::set_breakpoint
(
int *bp_id, // return breakpoint id;
VCPU_BpType type, // breakpoint type
uint64_t value, // opcode, instruction or data address
VCPU_BpActionFn action, // call this function on breakpoint hit
uint64_t mask= ~(uint64_t(0)) // optional data or addr mask
);
DESCRIPTION
Virtual methods of Vcpu class to set of breakpoint of specified type.
Address could be virtuall or physical. Action() routine is called by cpu module when breakpoint is reached, current instruction is not committed
Breakpoint type
typedef enum
{
VCPU_BP_INSTR_ADDR = 0,
VCPU_BP_DATA_READ_ADDR,
VCPU_BP_DATA_WRITE_ADDR,
VCPU_BP_OPCODE,
VCPU_N_BP_TYPES
} VCPU_BpType;
RETURN VALUES
1 – success;
0 – fail.
USAGE
VCPU_BpType type = VCPU_BP_INSTR_ADDR;
uint64_t addr = 0xfff00000;
int bp_id;
extern int bp_action ( int bp_id, int vcpu_id );
vcpu->set_breakpoint( &bp_id,type, addr, bp_action );
SEE ALSO
NAME
Vcpu::delete_breakpoint – Delete a breakpoint
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::delete_breakpoint ( int bp_id = ~(0) );
DESCRIPTION
Virtual methods of Vcpu class to remote breakpoint with bp_id.
If bp_id is ~(0) - remove all breakpoints.
RETURN VALUES
1 – success;
0 – fail.
USAGE
// remove all breakpoints
g_vcpu[cpu_id]->delete_breakpoint();
SEE ALSO
Vcpu::reconfig
NAME
Vcpu::reconfig– set new parameters for vcpu configuration;
SYNOPSIS
#include “vcpu.h”
virtual int Vcpu::reconfig(VCPU_Config conf );
DESCRIPTION
Virtual methods of Vcpu class to change cpu configuration parameters.
RETURN VALUES
1 – success;
0 – fail.
USAGE
// update cpu config parameters
g_vcpu[cpu_id]->reconfig(new_conf);
SEE ALSO
VCPU_ImpIntf::mem
NAME
mem - Pointer to the memory object.
SYNOPSIS
#include “vcpu.h”
#include “Memory.h”
class SMemory *mem;
DESCRIPTION
This pointer is a member of VCPU_ImpIntf structure.
CPU module uses this pointer internally to access physical memory.
Currently we support two types of simulated memory – flat memory and sparse memory.
For speed consideration the type of the memory is defined at build time.
USAGE
The SMemory object should be instantiated outside the CPU module and the pointer to the object is assigned in VCPU_ImpIntf structure and passed to the create() vcpu routine.
SEE ALSO
VCPU_ImpIntf::access_io
NAME
access_io - Access physical IO
SYNOPSIS
#include “vcpu.h”
int (*access_io)
(
int vcpu_id, // cpu id
int operation, // operation code- load, store and etc
uint64_t paddr, // physical address
uint32_t size, // access size
uint64_t &data, // 64 bit value to read/write
uint64_t bytemask // access byte mask
);
DESCRIPTION
This function pointer is a member of VCPU_ImpIntf structure.
Pointer to the routine to access physical io space from the CPU module.
Parameter operation is defined in VCPU_Operation.
CPU module uses this pointer internally to access physical IO space.
RETURN VALUES
1 – success;
0 - fail.
USAGE
The routine should be defined outside the CPU module and the pointer to the routine is assigned in VCPU_ImpIntf structure and passed to the Create vcpu routine.
SEE ALSO
VCPU_ImpIntf::access_asi
NAME
access_asi - Optional interface to access devices that mapped to asi ring
SYNOPSIS
#include “vcpu.h”
int (*access_asi)
(
int vcpu_id, // cpu id
int operation, // operation code- load,store and etc.
uint32_t asi, // asi value
uint64_t vaddr, // virtual address
int32_t size, // access size
uint64_t &buf // 64 bit data value
);
DESCRIPTION
This function pointer is a member of VCPU_ImpIntf structure.
Pointer to the routine to access device control registers mapped to the asi ring from the CPU module. Parameter operation is defined in VCPU_Operation.
CPU module uses this pointer internally to access asi mapped address space.
RETURN VALUES
1 – success;
0 - fail.
USAGE
The routine should be defined outside the CPU module and the pointer to the routine is assigned in VCPU_ImpIntf structure and passed to the Create vcpu routine.
NULL if not used.
SEE ALSO
VCPU_ImpIntf::access_serial
NAME
access_serial - Optional interface to access serial devices
SYNOPSIS
#include “vcpu.h”
//
int (*access_serial)
(
uint8_t *c, // character to read/write
bool_t wr // 0 - read, 1 - write
);
DESCRIPTION
This function pointer is a member of VCPU_ImpIntf structure.
Pointer to the routine to access serial device for software bring up and debugging from the CPU module. CPU module uses this pointer internally to access simulated serial device.
RETURN VALUES
1 – success;
0 - fail.
USAGE
The routine should be defined outside the CPU module and the pointer to the routine is assigned in VCPU_ImpIntf structure and passed to the Create vcpu routine.
NULL if not used.
SEE ALSO
VCPU_ImpIntf::vtrace
NAME
vtrace - Pointer to the vtracer object.
SYNOPSIS
#include “vcpu.h”
#include “vtracer.h”
class VTracer *vtrace;
DESCRIPTION
This pointer is a member of VCPU_ImpIntf structure.
CPU module uses this pointer internally to output instruction trace.
VTracer is an abstract class representing any analyzer which could be hooked up the CPU module. Cpu model calles Vtracer methods to output a complete information about architecture state change for every instruction. The information for every instruction is accumulated in VCPU_Instruction structure.
Trap information is collected in VCPU_Trap structure, VCPU_TLB is for tlb information.
USAGE
The Vtracer object should be instantiated outside the CPU module, pointer to the object is assigned in VCPU_ImpIntf structure and passed to the Create vcpu routine.
A tracer module must NOT define a static vtracer object. The
vtracer object must be created by the vtracer_init() function
provided by the module code and called by the simulator. Also, the
module must provide a function called vtracer_fini() which should
clean up before the module is unloaded (un-register ui commands, free
memory etc.)
Instruction information VCPU_Instruction - provides information
about the instruction been executed.
Fields in this structure are arranged according to the
order in which they are used during instruction lifetime.
SEE ALSO
Vtracer::instr
NAME
Vtracer::instr - Send an instruction info message.
SYNOPSIS
#include “vcpu.h”
#include “vtracer.h”
virtual int Vtracer::instr ( VCPU_Instruction *i );
DESCRIPTION
Virtual method of Vtracer class – output an instruction information.
VTracer is an abstract class representing any analyzer which could be hooked up the CPU module. VCPU_Instruction - provides information about the instruction been executed.
Fields in this structure are arranged according to the
order in which they are used during instruction lifetime.
USAGE
// collect trace record
VCPU_Instruction *i;
i->nregs = 0;
i->ld_num = 0;
i->st_num = 0;
i->itype = VCPU_UNKNOWN_ITYPE;
i->cpuid = cpuid;
i->pc_va = pc_va;
i->pc_pa = pc_pa;
i->npc_va = npc_va;
i->opcode = iw;
i->annul = an;
i->taken = (npc_va != (pc_va + 4));
// call tracer
g_ni_vcpu[cpuid]->sys_intf.vtrace->instr(i);
SEE ALSO
Vtracer::trap
NAME
Vtracer::instr - Send a trap info message.
SYNOPSIS
#include “vcpu.h”
#include “vtracer.h”
virtual int Vtracer::trap ( VCPU_Trap *t );
DESCRIPTION
Virtual method of Vtracer class – output trap information.
VCPU_Trap - provides information about the trap been taken.
USAGE
Sam::VCPU_Trap *t;
t->pc_va = tr_pc;
t->npc_va = tr_npc;
t->tno = tno;
t->cpuid = id;
//call tracer
g_ni_vcpu[id]->sys_intf.vtrace->trap(t);
SEE ALSO