x86_instruction_query x86_instrumentation_subscribe_v2
API Reference Manual  /  4 Model-to-Model Interfaces  / 

x86_instrumentation_subscribe

Description
The x86_instrumentation_subscribe interface is an x86 specific complement to the cpu_instrumentation_subscribe interface. It is implemented by processor objects that support instrumentation. It has the same requirements as the cpu_instrumentation_subscribe interface.

SIM_INTERFACE(x86_instrumentation_subscribe) {
        cpu_cb_handle_t *(*register_mode_switch_cb)(
                conf_object_t *cpu, conf_object_t *connection,
                x86_mode_switch_cb_t cb,
                lang_void *user_data);
        cpu_cb_handle_t *(*register_illegal_instruction_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_instruction_decoder_cb_t cb,
                cpu_instruction_disassemble_cb_t disass_cb,
                lang_void *data);
};
#define X86_INSTRUMENTATION_SUBSCRIBE_INTERFACE \
        "x86_instrumentation_subscribe"

The register_mode_switch_cb method is used to register a callback that is called whenever the processor cpu changes execution mode. The connection argument is the user object that registers the callback. This object will be passed to the callback when it is called. cb is the callback and user_data is user data for the callback. The signature of the callback looks like this:

typedef void (*x86_mode_switch_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        x86_detailed_exec_mode_t mode,
        lang_void *user_data);

The obj is the connection object that registered the callback. new_mode argument contains the new mode. The possible modes available are captured in the x86_detailed_exec_mode_t type:

typedef enum {
        X86_Detailed_Exec_Mode_Real_16,
        X86_Detailed_Exec_Mode_Real_32,
        X86_Detailed_Exec_Mode_V86,
        X86_Detailed_Exec_Mode_Protected_16,
        X86_Detailed_Exec_Mode_Protected_32,
        X86_Detailed_Exec_Mode_Protected_64,
        X86_Detailed_Exec_Mode_Compatibility_16,
        X86_Detailed_Exec_Mode_Compatibility_32,
} x86_detailed_exec_mode_t;

The user_data is the user data associated with the callback.

register_illegal_instruction_cb lets a user to implement new instructions. The cb argument is a callback function that will be called every time Simics does not decode an instruction. Allows new x86 instructions to be implemented which otherwise cause illegal instruction exception. Compared to register_instruction_decoder_cb method of cpu_instrumentation_subscribe interface this interface cannot change any instruction that correctly decodes according to the existing instruction set architecture. From this callback the user can accept the instruction or deny it. In most cases this only happens once per instruction address since Simics usually caches decoding results in the internal instruction cache. If the cache is flushed the callback may be called again. This instrumentation feature (if used alone) does not prevent VMP execution since illegal instructions cause exit while running inside VMP mode.

The callback signature looks like this:

typedef int (*cpu_instruction_decoder_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        decoder_handle_t *decoder_handle,
        instruction_handle_t *iq_handle,
        lang_void *user_data);

The instruction bytes are read by using the get_instruction_bytes method of the cpu_instruction_query interface together with the iq_handle. The returned value is of a cpu_bytes_t type. To access the bytes use the data and the size members in the returned value.

If the decoder requires more bytes (i.e., because the new instruction is longer), a negative integer value should be returned by the cb function, indicating the number of bytes needed. For example, if the available bytes are 3 but the decoder need at least 4 bytes, -4 should be returned. The callback will then be called again with more available bytes (this can be repeated if the new instruction requires even more bytes at this point). Note that requesting more data than actual needed can cause spurious page faults if the data crosses a page boundary.

If the instruction is accepted by the callback a positive integer number should be returned corresponding to the length of the instruction. In this case the register_emulation_cb method of the cpu_instruction_decoder interface should be called to set the actual (user) function that Simics will call each time the instruction is executed.

If the cb callback should ignore the instruction the number 0 should be returned. This means that any other registered decoder will have a chance to decode the instruction. If no decoder accepts it, Simics will generate illegal instruction exception.

The register_emulation_cb method also needs the decoder_handle which is available in the dedoder callback. For more information, see the documentation of the cpu_instruction_decoder interface.

A disass_cb argument should also be passed to the register_illegal_instruction_cb method. This function is called every time Simics wants to disassemble an instruction. For every accepted instruction a corresponding disassembly string should be returned by this function. It has the following signature:

typedef tuple_int_string_t (*cpu_instruction_disassemble_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        generic_address_t addr,
        cpu_bytes_t bytes);

obj is the object registering the register_illegal_instruction_cb and cpu is the processor disassembling the instruction. addr is the address of the instruction in a generic form. This means that it is typically a physical address or a logical address depending on the context of the disassembling. The address can be used for offset calculations, i.e., displaying an absolute address instead of a relative one, for example in a branch instruction. The bytes argument should be used to read instruction bytes. The return value is of type tuple_int_string_t and should be filled with the instruction length and an allocated (e.g., malloc) string representing the disassembly of the instruction. The ownership of the string is transferred to the calling environment which will free it when it is no longer needed.

If too few bytes are passed for the instruction to be disassembled a negative value should be returned for the length indicating the needed bytes. The disass_cb is then called again with more bytes. If the instruction is rejected a length of 0 should be returned and the string should be set to NULL.

To remove the callback used one of the methods remove_callback or remove_connection_callbacks in the cpu_instrumentation_subscribe interface.

The callback can also be enabled and disabled with the corresponding methods in the cpu_instrumentation_subscribe interface.

Execution Context
Global Context for all methods.

x86_instruction_query x86_instrumentation_subscribe_v2