connector cpu_cached_instruction_once
API Reference Manual  /  5 Model-to-Simulator Interfaces  / 

cpu_cached_instruction

Description
This interface allows registration of callbacks for individual instructions, i.e., instructions at a specific address. This interface can only be used inside a cpu_cached_instruction_cb_t callback where there is a valid ci_handle. The callback is installed by calling the register_cached_instruction_cb method in the cpu_instrumentation_subscribe interface. The signature of the callback function looks like this:

typedef void (*cpu_cached_instruction_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        cached_instruction_handle_t *ci_handle,
        instruction_handle_t *iq_handle,
        lang_void *user_data);

When the callback is installed Simics will call it every time an instruction is put into the internal instruction cache, which might have different entries for different execution modes. For example, in an unlikely case where the same instruction is executed in 32-bit mode and later in 64-bit mode (running an x86 processor for instance), this callback will be called twice, one time for each mode. This allows the user to install specific callbacks for this specific instruction and apply filtering based on instruction types, etc. This approach is more efficient than doing dynamic filtering in the instruction and read/write callbacks installed by the cpu_instrumentation_subscribe interface.

The iq_handle together with the cpu_instruction_query interface let a user examine instruction properties. The user_data is the user data for the callback.

SIM_INTERFACE(cpu_cached_instruction) {
        void (*register_instruction_before_cb)(
                conf_object_t *cpu,
                cached_instruction_handle_t *ci_handle,
                cpu_instruction_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_instruction_after_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_instruction_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_read_before_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_memory_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_read_after_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_memory_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_write_before_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_memory_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_write_after_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_memory_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
#ifndef PYWRAP
        void (*add_counter)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                uint64 *counter,
                bool use_atomic_increment);
#endif
};

#define CPU_CACHED_INSTRUCTION_INTERFACE "cpu_cached_instruction"

The method register_instruction_before_cb installs a callback that is called before the cached instruction is executed. The ci_handle is used to bind the callback to the cached instruction. The user_data is the callback's user data, and a callback for freeing the data is also available. The free_cb looks like this:

typedef void (*cpu_callback_free_user_data_cb_t)(
        conf_object_t *obj, conf_object_t *cpu, lang_void *user_data);

It is called when Simics wants to free cached instructions, which can happen in various situations. obj is the connection object that should free the data. The callback may be NULL if not needed.

The cb callback type is the same as used for instructions in the cpu_instrumentation_subscribe interface:

typedef void (*cpu_instruction_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        instruction_handle_t *handle,
        lang_void *user_data);

The object obj is the user object that registers the callback and cpu is the processor object executing the instruction. The handle can be used to query more data about the instruction. See the cpu_instruction_query interface for more information. The user_data is the user data associated with the callback.

The user data is a convenient location for storing information about the instruction, such as user specific decode information, etc. The user data is private for each installed callback.

The cached information about the instruction is bound to its physical address so the logical address cannot typically be saved since it may vary between calls (if the MMU-mapping has changed).

register_instruction_after_cb installs a callback that is called after a cached instruction is executed. Otherwise it works in the same as the before variant. However, reading the program counter register for a control flow instruction in this callback will reflect the new location, whereas using the cpu_instruction_query for reading out the instruction address will still return the address of the control flow instruction.

register_read_before_cb installs a callback that is called before each read operation in the cached instruction. The callback is the same as used for read and writes in the cpu_instrumentation_subscribe interface:

typedef void (*cpu_memory_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        memory_handle_t *handle,
        lang_void *user_data);

As for instructions, obj is the object that registered the callback and cpu is the processor doing the access. The handle can be used to further operate on the access by using the cpu_memory_query interface. The user_data and the free_cb arguments to register_read_before_cb can be used to store user data for the read operations in the cached instruction. The user data is private for each installed callback but is shared between all read before operations in the instruction.

register_read_after_cb installs a callback that is called after each read operation in the cached instruction. The user data is private for each installed callback but is shared between all read after operations in the instruction. Otherwise it works in the same way as the before variant.

register_write_before_cb and register_write_after_cb installs callbacks that is called before and after each write operation in the cached instructions. Otherwise they work in the same way as the read variants.

Note that installing a read or write callback on an instruction without any memory operations will be useless.

The add_counter method can be used to add simple counters for this particular instruction. The counter argument is a pointer to a 64 bit counter value that will be incremented each time the instruction is executed. This is the same thing (but more efficient) as registering a callback through the register_instruction_before_cb method and increasing the counter each time it is called.

Passing true for the argument use_atomic_increment makes the increment of the counter atomic, which may be useful if the tool cannot have an instrumentation connection per processor. This will however be slower due to the nature of atomic instructions.

The location of the counter value can only be removed/deallocated after a call to either the remove_callback method (passing the cpu_cb_handle_t returned by register_cached_instruction_cb), or to the remove_connection_callbacks method (with the connection object as the argument) in the cpu_instrumentation_subscribe interface.

This method is not available in Python.

The instrumentation_order interface cannot be used to reorder callbacks installed with the cpu_cached_instruction interface. The cached callbacks are always called in same order as the cpu_cached_instruction_cb_t callback that installed them, and before any callback installed by the corresponding methods in the cpu_instrumentation_subscribe.

Execution Context
Threaded Context for all methods, but must be called from a callback registered by the register_cached_instruction_cb method in the cpu_instrumentation_subscribe interface.

connector cpu_cached_instruction_once